Linting Command
This command provides manual control over linting workflows. It can run linters on specific files/directories or discover and document project linters.
Usage Modes
1. Lint Files
Lint one or more files or directories:
/lint path/to/file.py
/lint path/to/directory/
/lint file1.py file2.py file3.py
Behavior:
- Read
## LINTERS section from project's CLAUDE.md to identify configured linters
- Run formatters first (auto-fix trivial issues)
- Run linters second (report substantive issues)
- If errors found, use linting-root-cause-resolver agent to fix systematically
- Re-run linters to verify resolution
2. Discover Project Linters
Scan the project and generate the ## LINTERS section for CLAUDE.md:
/lint init
/lint init --force # Overwrite existing LINTERS section
Behavior:
- Scan for linting configuration files:
.pre-commit-config.yaml
pyproject.toml (ruff, mypy, pyright, bandit)
package.json (eslint, prettier)
.husky/ directory
- Root
.eslintrc*, .prettierrc*, .markdownlint* files
- Identify configured formatters and linters
- Generate
## LINTERS section in standard format
- Append to
CLAUDE.md (or update if --force provided)
Implementation
When this command is invoked, perform the following steps based on the arguments:
For /lint <path> (Lint Mode)
Read project linting configuration:
Grep(pattern="^## LINTERS", path="CLAUDE.md", output_mode="content", -A=50)
If LINTERS section not found:
- Inform user: "No ## LINTERS section found in CLAUDE.md. Run
/lint init first to discover project linters."
- Exit
Parse LINTERS section to identify:
- Formatters list with file patterns
- Linters list with file patterns
Match file paths to tools:
- For each provided path, determine which formatters/linters apply based on file extension
- Example:
*.py files → ruff format, ruff check, mypy, pyright
Run formatters first (auto-fix phase):
# Python
uv run ruff format <file.py>
# JavaScript/TypeScript
npx prettier --write <file.ts>
# Markdown
npx markdownlint-cli2 --fix <file.md>
# Shell
shfmt -w <script.sh>
Run linters second (validation phase):
# Python
uv run ruff check <file.py>
uv run mypy <file.py>
uv run pyright <file.py>
# JavaScript/TypeScript
npx eslint <file.ts>
# Shell
shellcheck <script.sh>
If linting errors found:
Verify resolution:
- Re-run linters on all files
- Confirm all issues resolved
For /lint init (Discovery Mode)
Check for existing LINTERS section:
Grep(pattern="^## LINTERS", path="CLAUDE.md", output_mode="content")
If section exists and --force not provided:
- Inform user: "## LINTERS section already exists in CLAUDE.md. Use
/lint init --force to overwrite."
- Show existing configuration
- Exit
Scan for git pre-commit hooks:
test -d .git && echo "Git repository: yes" || echo "Git repository: no"
test -f .pre-commit-config.yaml && echo "pre-commit config: found" || echo "pre-commit config: not found"
test -d .husky && echo "husky: found" || echo "husky: not found"
Scan for Python linting config (pyproject.toml):
Read(file_path="pyproject.toml")
- Look for
[tool.ruff], [tool.mypy], [tool.pyright], [tool.bandit] sections
- Identify which tools are configured
Scan for JavaScript/TypeScript config (package.json):
Read(file_path="package.json")
- Look for
eslint, prettier, @typescript-eslint/* in devDependencies
- Check for
.eslintrc*, .prettierrc* config files
Scan for Markdown linting:
test -f .markdownlint.json && echo "markdownlint config: found"
test -f .markdownlint.yaml && echo "markdownlint config: found"
Scan for Shell linting:
- Look for shellcheck in
.pre-commit-config.yaml or installed globally
- Look for shfmt in
.pre-commit-config.yaml or installed globally
Generate LINTERS section:
## LINTERS
git pre-commit hooks: [enabled|disabled] pre-commit tool: [husky|pre-commit|manual]
### Formatters
- [tool] [file patterns] ...
### Static Checking and Linting
- [tool] [file patterns] ...
Append or update CLAUDE.md:
- If
--force provided, remove existing section first
- Append generated section to
CLAUDE.md
- Confirm success: "✓ LINTERS section written to CLAUDE.md"
File Pattern Matching
When determining which linters apply to files, use these standard patterns:
- Python:
*.py → ruff format, ruff check, mypy, pyright, bandit
- JavaScript/TypeScript:
*.{js,ts,jsx,tsx} → prettier, eslint
- Markdown:
*.{md,markdown} → markdownlint-cli2
- Shell:
*.{sh,bash,zsh,fish} → shfmt, shellcheck
- JSON:
*.json → prettier
- YAML:
*.{yml,yaml} → prettier (if configured)
Error Handling
If CLAUDE.md doesn't exist:
- In lint mode: Warn and suggest running
/lint init
- In init mode: Create CLAUDE.md with LINTERS section
If tools aren't installed:
- Show which tools are missing
- Suggest installation commands (e.g.,
uv add --dev ruff mypy pyright)
If linting errors persist after agent resolution:
- Show remaining errors
- Ask user if they want to continue investigation or accept current state
Examples
Example 1: Lint a single file
User: /lint src/auth.py
Claude:
1. Reading ## LINTERS section from CLAUDE.md...
2. Found formatters: ruff format [*.py]
3. Found linters: ruff check [*.py], mypy [*.py], pyright [*.py]
4. Running formatter: uv run ruff format src/auth.py
✓ Formatted 1 file
5. Running linters:
- uv run ruff check src/auth.py
✗ Found 2 errors (E501, F401)
- uv run mypy src/auth.py
✗ Found 1 error (arg-type)
6. Launching linting-root-cause-resolver agent for src/auth.py...
7. Agent resolved all 3 issues
8. Re-running linters:
- uv run ruff check src/auth.py ✓
- uv run mypy src/auth.py ✓
- uv run pyright src/auth.py ✓
9. All linting errors resolved ✓
Example 2: Lint multiple files
User: /lint src/auth.py src/models.py tests/test_auth.py
Claude:
1. Reading ## LINTERS section from CLAUDE.md...
2. Running formatters on 3 files...
✓ All files formatted
3. Running linters on 3 files...
✗ src/auth.py: 2 errors
✗ src/models.py: 5 errors
✓ tests/test_auth.py: no errors
4. Launching concurrent linting-root-cause-resolver agents:
- Agent 1: Resolving src/auth.py
- Agent 2: Resolving src/models.py
5. Both agents completed successfully
6. Re-running linters: All files clean ✓
Example 3: Discover project linters
User: /lint init
Claude:
1. Checking for existing ## LINTERS section in CLAUDE.md...
Not found - proceeding with discovery
2. Scanning project configuration:
✓ Git repository detected
✓ Found .pre-commit-config.yaml (6 hooks)
✓ Found pyproject.toml with [tool.ruff], [tool.mypy], [tool.pyright]
✓ Found package.json with prettier, eslint
✓ Found .markdownlint.json
3. Generating LINTERS section...
## LINTERS
git pre-commit hooks: enabled
pre-commit tool: pre-commit
### Formatters
- ruff format [*.py]
- prettier [*.{ts,tsx,json,md}]
- markdownlint-cli2 [*.md]
### Static Checking and Linting
- ruff check [*.py]
- mypy [*.py]
- pyright [*.py]
- eslint [*.{ts,tsx}]
- markdownlint-cli2 [*.md]
4. Appended to CLAUDE.md ✓
Example 4: Re-discover linters (force mode)
User: /lint init --force
Claude:
1. Checking for existing ## LINTERS section in CLAUDE.md...
Found existing section
2. --force flag provided, removing existing section
3. Re-scanning project configuration...
[Same discovery process as Example 3]
4. Updated CLAUDE.md with new configuration ✓
Notes
- The
/lint command respects the holistic-linting skill philosophy: format first (auto-fix trivial issues), lint second (report substantive issues), resolve systematically (understand root causes)
- Orchestrators should launch concurrent linting-root-cause-resolver agents when multiple files have errors
- Sub-agents should use this command on their touched files before completing tasks
- The init mode creates a "cache" in CLAUDE.md to avoid repeated configuration discovery overhead
1---2name: lint3description: Run linting and formatting on files or discover project linters. Usage with /lint path or /lint init with optional --force flag4---56# Linting Command78This command provides manual control over linting workflows. It can run linters on specific files/directories or discover and document project linters.910## Usage Modes1112### 1. Lint Files1314Lint one or more files or directories:1516```bash17/lint path/to/file.py18/lint path/to/directory/19/lint file1.py file2.py file3.py20```2122**Behavior**:23241. Read `## LINTERS` section from project's `CLAUDE.md` to identify configured linters252. Run formatters first (auto-fix trivial issues)263. Run linters second (report substantive issues)274. If errors found, use linting-root-cause-resolver agent to fix systematically285. Re-run linters to verify resolution2930### 2. Discover Project Linters3132Scan the project and generate the `## LINTERS` section for `CLAUDE.md`:3334```bash35/lint init36/lint init --force # Overwrite existing LINTERS section37```3839**Behavior**:40411. Scan for linting configuration files:42 - `.pre-commit-config.yaml`43 - `pyproject.toml` (ruff, mypy, pyright, bandit)44 - `package.json` (eslint, prettier)45 - `.husky/` directory46 - Root `.eslintrc*`, `.prettierrc*`, `.markdownlint*` files472. Identify configured formatters and linters483. Generate `## LINTERS` section in standard format494. Append to `CLAUDE.md` (or update if `--force` provided)5051## Implementation5253When this command is invoked, perform the following steps based on the arguments:5455### For `/lint <path>` (Lint Mode)56571. **Read project linting configuration**:5859 ```claude60 Grep(pattern="^## LINTERS", path="CLAUDE.md", output_mode="content", -A=50)61 ```62632. **If LINTERS section not found**:6465 - Inform user: "No ## LINTERS section found in CLAUDE.md. Run `/lint init` first to discover project linters."66 - Exit67683. **Parse LINTERS section** to identify:6970 - Formatters list with file patterns71 - Linters list with file patterns72734. **Match file paths to tools**:7475 - For each provided path, determine which formatters/linters apply based on file extension76 - Example: `*.py` files → ruff format, ruff check, mypy, pyright77785. **Run formatters first** (auto-fix phase):7980 ```bash81 # Python82 uv run ruff format <file.py>8384 # JavaScript/TypeScript85 npx prettier --write <file.ts>8687 # Markdown88 npx markdownlint-cli2 --fix <file.md>8990 # Shell91 shfmt -w <script.sh>92 ```93946. **Run linters second** (validation phase):9596 ```bash97 # Python98 uv run ruff check <file.py>99 uv run mypy <file.py>100 uv run pyright <file.py>101102 # JavaScript/TypeScript103 npx eslint <file.ts>104105 # Shell106 shellcheck <script.sh>107 ```1081097. **If linting errors found**:110111 - For each file with errors, launch a linting-root-cause-resolver agent:112 ```claude113 Task(subagent_type="linting-root-cause-resolver",114 description="Fix linting errors in <filename>",115 prompt="...")116 ```1171188. **Verify resolution**:119 - Re-run linters on all files120 - Confirm all issues resolved121122### For `/lint init` (Discovery Mode)1231241. **Check for existing LINTERS section**:125126 ```claude127 Grep(pattern="^## LINTERS", path="CLAUDE.md", output_mode="content")128 ```1291302. **If section exists and `--force` not provided**:131132 - Inform user: "## LINTERS section already exists in CLAUDE.md. Use `/lint init --force` to overwrite."133 - Show existing configuration134 - Exit1351363. **Scan for git pre-commit hooks**:137138 ```bash139 test -d .git && echo "Git repository: yes" || echo "Git repository: no"140 test -f .pre-commit-config.yaml && echo "pre-commit config: found" || echo "pre-commit config: not found"141 test -d .husky && echo "husky: found" || echo "husky: not found"142 ```1431444. **Scan for Python linting config** (pyproject.toml):145146 ```claude147 Read(file_path="pyproject.toml")148 ```149150 - Look for `[tool.ruff]`, `[tool.mypy]`, `[tool.pyright]`, `[tool.bandit]` sections151 - Identify which tools are configured1521535. **Scan for JavaScript/TypeScript config** (package.json):154155 ```claude156 Read(file_path="package.json")157 ```158159 - Look for `eslint`, `prettier`, `@typescript-eslint/*` in devDependencies160 - Check for `.eslintrc*`, `.prettierrc*` config files1611626. **Scan for Markdown linting**:163164 ```bash165 test -f .markdownlint.json && echo "markdownlint config: found"166 test -f .markdownlint.yaml && echo "markdownlint config: found"167 ```1681697. **Scan for Shell linting**:170171 - Look for shellcheck in `.pre-commit-config.yaml` or installed globally172 - Look for shfmt in `.pre-commit-config.yaml` or installed globally1731748. **Generate LINTERS section**:175176 ```markdown177 ## LINTERS178179 git pre-commit hooks: [enabled|disabled] pre-commit tool: [husky|pre-commit|manual]180181 ### Formatters182183 - [tool] [file patterns] ...184185 ### Static Checking and Linting186187 - [tool] [file patterns] ...188 ```1891909. **Append or update CLAUDE.md**:191 - If `--force` provided, remove existing section first192 - Append generated section to `CLAUDE.md`193 - Confirm success: "✓ LINTERS section written to CLAUDE.md"194195## File Pattern Matching196197When determining which linters apply to files, use these standard patterns:198199- **Python**: `*.py` → ruff format, ruff check, mypy, pyright, bandit200- **JavaScript/TypeScript**: `*.{js,ts,jsx,tsx}` → prettier, eslint201- **Markdown**: `*.{md,markdown}` → markdownlint-cli2202- **Shell**: `*.{sh,bash,zsh,fish}` → shfmt, shellcheck203- **JSON**: `*.json` → prettier204- **YAML**: `*.{yml,yaml}` → prettier (if configured)205206## Error Handling207208**If CLAUDE.md doesn't exist**:209210- In lint mode: Warn and suggest running `/lint init`211- In init mode: Create CLAUDE.md with LINTERS section212213**If tools aren't installed**:214215- Show which tools are missing216- Suggest installation commands (e.g., `uv add --dev ruff mypy pyright`)217218**If linting errors persist after agent resolution**:219220- Show remaining errors221- Ask user if they want to continue investigation or accept current state222223## Examples224225### Example 1: Lint a single file226227```text228User: /lint src/auth.py229230Claude:2311. Reading ## LINTERS section from CLAUDE.md...2322. Found formatters: ruff format [*.py]2333. Found linters: ruff check [*.py], mypy [*.py], pyright [*.py]2344. Running formatter: uv run ruff format src/auth.py235 ✓ Formatted 1 file2365. Running linters:237 - uv run ruff check src/auth.py238 ✗ Found 2 errors (E501, F401)239 - uv run mypy src/auth.py240 ✗ Found 1 error (arg-type)2416. Launching linting-root-cause-resolver agent for src/auth.py...2427. Agent resolved all 3 issues2438. Re-running linters:244 - uv run ruff check src/auth.py ✓245 - uv run mypy src/auth.py ✓246 - uv run pyright src/auth.py ✓2479. All linting errors resolved ✓248```249250### Example 2: Lint multiple files251252```text253User: /lint src/auth.py src/models.py tests/test_auth.py254255Claude:2561. Reading ## LINTERS section from CLAUDE.md...2572. Running formatters on 3 files...258 ✓ All files formatted2593. Running linters on 3 files...260 ✗ src/auth.py: 2 errors261 ✗ src/models.py: 5 errors262 ✓ tests/test_auth.py: no errors2634. Launching concurrent linting-root-cause-resolver agents:264 - Agent 1: Resolving src/auth.py265 - Agent 2: Resolving src/models.py2665. Both agents completed successfully2676. Re-running linters: All files clean ✓268```269270### Example 3: Discover project linters271272```text273User: /lint init274275Claude:2761. Checking for existing ## LINTERS section in CLAUDE.md...277 Not found - proceeding with discovery2782. Scanning project configuration:279 ✓ Git repository detected280 ✓ Found .pre-commit-config.yaml (6 hooks)281 ✓ Found pyproject.toml with [tool.ruff], [tool.mypy], [tool.pyright]282 ✓ Found package.json with prettier, eslint283 ✓ Found .markdownlint.json2843. Generating LINTERS section...285286## LINTERS287288git pre-commit hooks: enabled289pre-commit tool: pre-commit290291### Formatters292293- ruff format [*.py]294- prettier [*.{ts,tsx,json,md}]295- markdownlint-cli2 [*.md]296297### Static Checking and Linting298299- ruff check [*.py]300- mypy [*.py]301- pyright [*.py]302- eslint [*.{ts,tsx}]303- markdownlint-cli2 [*.md]3043054. Appended to CLAUDE.md ✓306```307308### Example 4: Re-discover linters (force mode)309310```text311User: /lint init --force312313Claude:3141. Checking for existing ## LINTERS section in CLAUDE.md...315 Found existing section3162. --force flag provided, removing existing section3173. Re-scanning project configuration...318 [Same discovery process as Example 3]3194. Updated CLAUDE.md with new configuration ✓320```321322## Notes323324- The `/lint` command respects the holistic-linting skill philosophy: format first (auto-fix trivial issues), lint second (report substantive issues), resolve systematically (understand root causes)325- Orchestrators should launch concurrent linting-root-cause-resolver agents when multiple files have errors326- Sub-agents should use this command on their touched files before completing tasks327- The init mode creates a "cache" in CLAUDE.md to avoid repeated configuration discovery overhead