| name | rule-creator |
| description | Create SwiftASTLint lint rules for a user's linter project. Covers Rule (no args) and ParameterizedRule (YAML-configurable args) APIs, RuleSet composition, YAML config for per-rule args/include/exclude/disabled_rules, autofix with SwiftSyntax FixIt, and unit testing with SwiftASTLintTestSupport. Use when: user asks to "add a lint rule", "create a rule", "write a rule", mentions "SwiftASTLint rule", "lint rule", "AST rule", wants to check code patterns via SwiftSyntax, or needs help writing Rule closures. Also trigger when user says "add a check for...", "detect when...", "enforce that...", "ban X in code", or any request about catching code patterns at the AST level — even if they don't mention SwiftASTLint. Also use when user runs /rule-creator.
|
Rule Creator for SwiftASTLint
Orchestration
Determine where the user is and guide them to the next step. If they already have a linter project set up, skip straight to writing rules.
Step 1: Determine project state
Check the working directory for Sources/Rules/Rules.swift and a Package.swift that imports SwiftASTLint.
- Found — proceed to Step 2.
- Not found — ask the user before scaffolding:
- Package name (default: MyLinter)
- Output path (default:
./<name>)
- macOS deployment target (e.g. v13, v14, v15 — default: v15)
Wait for answers before proceeding. Then scaffold with explicit flags:
swiftastlinttool init --path <path> --name <name>
Patch Package.swift if macOS version differs from v15. After scaffolding, delete the auto-generated entry point that conflicts with main.swift:
rm -f <path>/Sources/swift-ast-lint/swift-ast-lint.swift
If swiftastlinttool is not installed:
curl -fsSL https://raw.githubusercontent.com/Ryu0118/swift-ast-lint/main/install.sh | bash
Step 2: Understand the rule
Check the existing rules first — enumerate them with the rules subcommand instead of
reading Rules.swift and the YAML side by side (requires a swift-ast-lint version that ships it):
swift run --package-path <linter-path> swift-ast-lint rules
Use the output to avoid duplicate rule ids and to see whether an existing rule already covers
(or nearly covers) the request. See references/rule-api.md for the
JSON shape. If the subcommand is unavailable (older swift-ast-lint), fall back to reading
Sources/Rules/Rules.swift.
If the user already described the rule clearly, skip questions and start writing. Otherwise ask:
- What code pattern should this catch? (concrete example)
- Warning or error?
- Fixable? (auto-correct via FixIt)
- Configurable thresholds? (→ ParameterizedRule)
- Specific file paths? (→ YAML include/exclude)
Step 3: Write the rule (TDD order — tests first)
Always write in this order:
- Write test file in
Tests/RulesTests/ first — violation cases, false-positive cases, edge cases
- Run
swift test --filter <RuleName> — all tests should fail (red)
- Create
.swift implementation file in Sources/Rules/
- Register the rule in
RuleSet in Rules.swift
- Run
swift test --filter <RuleName> again — all tests must pass (green)
Never create the implementation before the tests exist.
Set the optional description: parameter on new rules — it feeds the rules subcommand so
agents and tooling can understand the rule without reading its source.
For API reference, see references/rule-api.md. For test design principles and examples, see references/testing-guide.md.
Step 4: YAML configuration
After writing the rule, ask whether to add YAML config to .swift-ast-lint.yml:
args — override ParameterizedRule defaults (thresholds, limits, etc.)
include / exclude — restrict rule to specific file paths (glob)
disabled_rules — disable a rule entirely
Example:
rules:
deep-nesting:
args:
max_depth: 5
include:
- "Sources/**"
exclude:
- "**/*Generated.swift"
After editing the YAML, verify it took effect: run the rules subcommand and check the rule's
effective_args (and enabled) against what you configured.
If the user declines, move on.
Step 5: Iterate if needed
If the user says "also catch X" or "that's not quite right", read the existing rule and test file before modifying. Always add or update tests first, confirm they fail (or capture the new expected behavior), then update the implementation.
Step 6: Setup guide (new projects only)
Skip this step if the user pointed to an existing project (not scaffolded in Step 1).
After all rules pass tests, present:
- How to run lint:
swift run --package-path <linter-path> swift-ast-lint <target-path>
- Optional automation — ask which they want:
- a) Checksum cache script — skip rebuild when Rules sources unchanged
- b) Makefile target —
make ast-lint
- c) Claude Code hooks / git pre-commit — auto-lint on commit
- d) None
Wait for answer, then set up what they chose. See references/setup-guide.md for templates.