Standard procedure for authoring TypeSpec linter rules.
Install
mkdir -p .claude/skills/create-linter-rule && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/10163" && unzip -o skill.zip -d .claude/skills/create-linter-rule && rm skill.zipInstalls to .claude/skills/create-linter-rule
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Create a new TypeSpec linter rule, lint diagnostic, or design guideline checker with a TDD approach, including implementation, tests, documentation, ruleset registration, and changeset. Use this skill when asked to create, add, implement, or write a new linter rule, lint warning, validation rule, or design guideline enforcement for TypeSpec Azure libraries.Key capabilities
- →Implement linter rules
- →Write validation tests
- →Add documentation
- →Register rulesets
How it works
Follows a TDD approach to scaffold, implement, test, and register new TypeSpec linter rules.
Inputs & outputs
When to use create-linter-rule
- →Implement new linter rule
- →Write TypeSpec validation guideline
- →Add lint diagnostic check
About this skill
Create a TypeSpec Linter Rule
Follow these steps in order to create a complete, high-quality linter rule.
Step 1: IDENTIFY
Determine the rule metadata before writing any code:
- Package:
typespec-azure-core(data-plane rules),typespec-azure-resource-manager(ARM rules), ortypespec-client-generator-core(client SDK generation rules) - Rule name: Must follow these naming conventions:
- Use kebab-case (lowercase letters, numbers, hyphens)
- DO NOT include the package name in the rule ID (the package is already part of the fully-qualified diagnostic code)
- Use
no-<thing>when the rule bans a construct or usage (e.g.,no-nullable,no-enum,no-format) - Use
use-<preferred-thing>when the rule points users to a standard/preferred TypeSpec pattern (e.g.,use-standard-operations,use-extensible-enum) - Keep names short and concise — prefer
no-enumoverno-enum-type-usage
- Severity: All linter rules are warnings; no severity choice is needed
- Target ruleset(s):
data-plane,resource-manager, or both - Description: One-line explanation of what the rule enforces
Choose the package by scope:
- Decorators from
typespec-client-generator-core, or rules only about client SDK generation →typespec-client-generator-core - Rules specific to ARM APIs →
typespec-azure-resource-manager - Rules that apply to both data-plane and ARM, or only data-plane →
typespec-azure-core
Step 2: SCAFFOLD
Generate all required files using the repo's scaffolding tool:
pnpm create:linter-rule < rule-name > --package < azure-core | azure-resource-manager | client-generator-core > --description "<description>"
This creates:
packages/<pkg>/src/rules/<rule-name>.ts— rule skeletonpackages/<pkg>/test/rules/<rule-name>.test.ts— test skeletonpackages/<pkg>/src/rules/<rule-name>.md— docs skeleton (referenced from the rule viadocs: fileRef.fromPackageRoot(...))- Updates
packages/<pkg>/src/linter.ts— registers the rule
Step 3: WRITE FAILING TESTS FIRST (TDD)
Edit packages/<pkg>/test/rules/<rule-name>.test.ts:
- Write tests for valid code that should produce no diagnostics (
.toBeValid()) - Write tests for invalid code that should produce specific diagnostics (
.toEmitDiagnostics()) - Create equivalence classes for the input and write tests covering at least one instance of each class:
- Group inputs by how the rule handles them (e.g., for a rule targeting
ModelProperty):- Simply defined properties
- Properties defined using
spreadoris - Properties inherited from a base class
- Add boundary conditions specific to the rule logic (e.g., for a name-prefix rule):
- Properties with the forbidden prefix
- Properties with the prefix text in the middle or end of the name
- Properties with names shorter than the prefix
- Group inputs by how the rule handles them (e.g., for a rule targeting
- Always include at least one test verifying that library types in
Azure.CoreandAzure.ResourceManagerare not subject to the rule
Test API reference:
// No diagnostics expected
await tester.expect(`model Foo {}`).toBeValid();
// Specific diagnostic expected
await tester.expect(`model foo {}`).toEmitDiagnostics([
{
code: "@azure-tools/typespec-<pkg>/<rule-name>",
severity: "warning",
message: "Expected message text",
},
]);
// Test code fix (if rule provides one)
await tester
.expect(`enum Color { red }`)
.applyCodeFix("fix-id")
.toEqual(`union Color { string, red: "red" }`);
Verify tests fail before implementing:
pnpm --filter "@azure-tools/typespec-<pkg>..." build
pnpm --filter "@azure-tools/typespec-<pkg>..." test
Step 4: IMPLEMENT THE RULE
Edit packages/<pkg>/src/rules/<rule-name>.ts:
- Implement visitor logic in the
create(context)function - Return a
SemanticNodeListenerwith the appropriate hooks:model— for model-level checksmodelProperty— for property-level checksoperation— for operation-level checksenum— for enum checksnamespace— for namespace-level checksinterface— for interface checksunion/unionVariant— for union checks
- Use
context.reportDiagnostic({ target })to report violations - Use
paramMessagefrom@typespec/compilerfor interpolated messages - Add
codefixesarray toreportDiagnostic()if a fix is possible
Step 5: VERIFY TESTS PASS
pnpm --filter "@azure-tools/typespec-<pkg>..." build
pnpm --filter "@azure-tools/typespec-<pkg>..." test
All tests should pass. If not, fix the implementation until they do.
Step 6: REGISTER IN RULESETS
Add the rule to the appropriate ruleset(s):
- Data-plane rules: Edit
packages/typespec-azure-rulesets/src/rulesets/data-plane.ts - ARM rules: Edit
packages/typespec-azure-rulesets/src/rulesets/resource-manager.ts
TCGC rules generally go in both rulesets. Rules in typespec-azure-core that apply to both ARM and data-plane specs also go in both rulesets. Only rules that are truly ARM-specific go exclusively in resource-manager.ts; otherwise, add the rule to both resource-manager.ts and data-plane.ts as appropriate.
Add an entry: "@azure-tools/typespec-<pkg>/<rule-name>": true,
Every rule MUST be explicitly listed (enabled or disabled). The validate-rules-defined.test.ts test will fail otherwise.
Verify:
pnpm --filter "@azure-tools/typespec-azure-rulesets..." build
pnpm --filter "@azure-tools/typespec-azure-rulesets..." test
Step 7: WRITE DOCUMENTATION AND REGENERATE DOCS
Edit packages/<pkg>/src/rules/<rule-name>.md:
- Replace all placeholder text
- Write a clear description of what the rule checks and why
- Provide realistic ❌ Incorrect and ✅ Correct examples using actual TypeSpec patterns
- Add a required
## Impactsection: a bulleted**Area:**line (e.g.API,SDK,Emitters) followed by a short paragraph describing what breaks or degrades when the rule is violated - Add a required
## Suppressionsection: state whether suppression is acceptable and why, and point to the correct fix. Suppressions use the#suppress "<rule-id>" "<justification-string>"directive placed on the line above the target — NOT a// suppresscomment - Add a
## LintDiff Equivalentsection when an equivalent LintDiff (azure-openapi-validator) rule exists, deep-linking to the specific rule id in the OpenAPI authoring automated guidelines. Omit only when no equivalent exists - This file holds only the extended documentation body — the page title, rule id, and
short description are generated from the rule definition.
tspdrenders the page atwebsite/src/content/docs/docs/libraries/<pkg>/rules/<rule-name>.md - For ARM rules, also update the alphabetized rule table in
website/src/content/docs/docs/howtos/ARM/arm-rules.mdwith the documentation URL, LintDiff equivalent, and impact. This table is authored manually and is not updated byregen-docs.
Then regenerate the library's reference docs (updates the rule listing):
pnpm --filter "@azure-tools/typespec-<pkg>..." build
pnpm --filter "@azure-tools/typespec-<pkg>" regen-docs
Step 8: CREATE CHANGESET
pnpm change add
When prompted:
- Select change kind:
feature(new rule) orfix(bugfix to existing rule) - Select affected package:
@azure-tools/typespec-<pkg> - Write a concise description: "Add
<rule-name>linter rule that <what it does>"
Step 9: FINAL VALIDATION
Run the general pre-PR validation to ensure everything is ready:
pnpm validate:pr
This checks: branch is up to date, build passes, tests pass, lint passes, format is clean, spelling is clean, regen-docs is clean, changeset exists, and diff only contains expected files.
If any check fails, fix the issue and re-run. Use pnpm validate:pr --fix to auto-fix formatting and lint issues.
Step 10: EXTERNAL INTEGRATION CHECK
New linter rules MUST NOT break existing Azure service specs. After pushing your PR:
- Apply the
int:azure-specslabel to the PR to trigger the External Integration check:gh pr edit --add-label "int:azure-specs" - If the agent cannot apply the label automatically, tell the user to apply the
int:azure-specslabel manually in the GitHub UI - After applying the label, the External Integration workflow will start. Monitor it via
gh run list --workflow=external-integration.yml - This workflow packages your changes and runs TypeSpec validation against all specs in
Azure/azure-rest-api-specs - Wait for the check to pass before requesting review
If the check fails, your rule produces diagnostics on existing specs. To resolve:
- Apply an API-neutral fix to the spec (preferred): If the fix doesn't change API behavior, submit a PR to
Azure/azure-rest-api-specson the main branch. - Suppress the rule: If the spec cannot be fixed without changing API behavior, add a
#suppress "<rule-id>" "<justification-string>"directive on the line above the target (NOT a// suppresscomment). Suppressions always go to the main branch. - Fix on typespec-next: If the fix requires unreleased TypeSpec APIs or behavior, submit to the typespec-next branch (uses nightly builds).
- Link your spec fix PR: Always link the spec fix PR in your linter rule PR description.
The External Integration workflow:
- Builds and packs all typespec-azure packages from your PR
- Checks out
Azure/azure-rest-api-specs(main branch) - Patches in your packaged changes
- Runs
tsp-integration azure-specs --stage validate - Checks for unexpected git changes
Important Notes
- Import extensions: Always use
.jsextensions in imports (e.g.,from "./rules/my-rule.js") - Rule URL: Must match
https://azure.github.io/typespec-azure/docs/libraries/<pkg>/rules/<rule-name>
Content truncated.
When not to use it
- →General TypeSpec development
- →Non-Azure libraries
Prerequisites
Limitations
- →Requires TypeSpec environment
- →Strict registration rules
How it compares
It provides a specific scaffolding and TDD workflow for Azure-specific TypeSpec libraries.
Compared to similar skills
create-linter-rule side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| create-linter-rule (this skill) | 0 | 2mo | Review | Advanced |
| python-testing-patterns | 77 | 2mo | Review | Intermediate |
| dependency-upgrade | 26 | 5mo | Review | Intermediate |
| test-cases | 57 | 7mo | No flags | Beginner |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by Azure
View all by Azure →You might also like
python-testing-patterns
wshobson
Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development. Use when writing Python tests, setting up test suites, or implementing testing best practices.
dependency-upgrade
wshobson
Manage major dependency version upgrades with compatibility analysis, staged rollout, and comprehensive testing. Use when upgrading framework versions, updating major dependencies, or managing breaking changes in libraries.
test-cases
cexll
This skill should be used when generating comprehensive test cases from PRD documents or user requirements. Triggers when users request test case generation, QA planning, test scenario creation, or need structured test documentation. Produces detailed test cases covering functional, edge case, error handling, and state transition scenarios.
reviewing-code
CaptainCrouton89
Systematically evaluate code changes for security, correctness, performance, and spec alignment. Use when reviewing PRs, assessing code quality, or verifying implementation against requirements.
wcag-audit-patterns
wshobson
Conduct WCAG 2.2 accessibility audits with automated testing, manual verification, and remediation guidance. Use when auditing websites for accessibility, fixing WCAG violations, or implementing accessible design patterns.
code-coverage-with-gcov
gadievron
Add gcov code coverage instrumentation to C/C++ projects