From holistic-linting
Automates format-lint-resolve pipelines for code editing tasks. Discovers linters from pyproject.toml/.pre-commit-config.yaml/package.json, fixes ruff/mypy/bandit issues, ensures quality before completion.
npx claudepluginhub jamie-bitflight/claude_skills --plugin holistic-lintingThis skill uses the workspace's default tool permissions.
This skill embeds comprehensive linting and formatting verification into Claude Code's workflow, preventing the common pattern where code is claimed "production ready" without actually running quality checks.
references/accessing_online_resources.mdreferences/mypy-docs/error_code_list.rstreferences/mypy-docs/error_code_list2.rstreferences/pre-existing-issues-protocol.mdreferences/rules/bandit/credentials-secrets.mdreferences/rules/bandit/cryptography.mdreferences/rules/bandit/deserialization.mdreferences/rules/bandit/file-permissions.mdreferences/rules/bandit/framework-config.mdreferences/rules/bandit/index.mdreferences/rules/bandit/injection-command.mdreferences/rules/bandit/miscellaneous.mdreferences/rules/bandit/module-imports.mdreferences/rules/bandit/ssl-tls.mdreferences/rules/bandit/unsafe-functions.mdreferences/rules/bandit/xml-parsing.mdreferences/rules/mypy/default-errors/abstract.mdreferences/rules/mypy/default-errors/advanced.mdreferences/rules/mypy/default-errors/assignment.mdreferences/rules/mypy/default-errors/async.mdProvides workflows for sub-agents to resolve Python linting errors from ruff, mypy, pyright, and basedpyright via root-cause analysis, suppression gates, and verification steps.
Runs lint checks on codebase, groups issues into independent parallel streams, and dispatches AI agents to fix all issues iteratively until clean.
Sets up strict production-grade ESLint configuration for TypeScript projects and systematically fixes all linting issues via auto-fix and manual remediation.
Share bugs, ideas, or general feedback.
This skill embeds comprehensive linting and formatting verification into Claude Code's workflow, preventing the common pattern where code is claimed "production ready" without actually running quality checks.
Prevent Claude from:
# type: ignore or # noqa comments without understanding root causesEnsure Claude:
This skill applies to all code editing tasks in projects with linting configuration. It provides different behavior based on Claude's role:
After completing implementation work, orchestrators MUST delegate to specialized agents. See the holistic-linting-orchestrator skill for complete delegation workflows.
Quick reference:
.claude/reports/CRITICAL: Orchestrators do NOT run formatting or linting commands themselves. The agent gathers its own linting data, formats files, runs linters, and resolves issues. Orchestrators only delegate tasks and read completion reports.
Before completing any task that involved Edit/Write:
For detailed resolution workflows, see the holistic-linting-resolver skill.
This skill modifies Claude's standard workflow to include automatic quality checks:
Before this skill:
[User request] → [Code changes] → [Task complete ✓]
With this skill (Orchestrator):
[User request] → [Code changes] → [Delegate to linting agent] → [Read reports] → [Task complete ✓]
With this skill (Sub-Agent):
[Task assigned] → [Code changes] → [Format] → [Lint] → [Resolve issues] → [Task complete ✓]
Linter detection is handled automatically by scanning project configuration files. The linting hook's ConfigurationDetector identifies available tools at runtime by checking:
| Config File | Tools Detected |
|---|---|
.pre-commit-config.yaml | pre-commit/prek hooks (takes priority, skips others) |
.husky/ directory | Husky git hooks |
pyproject.toml | Ruff, MyPy, basedpyright, bandit |
package.json, .eslintrc* | ESLint |
package.json, .prettierrc* | Prettier |
.clang-format | clang-format (C/C++) |
.rubocop.yml | RuboCop (Ruby) |
.shellcheckrc | ShellCheck (shell scripts) |
.markdownlint.json/.yaml | markdownlint |
Detection Priority (highest to lowest):
The detection uses caching with a 5-minute TTL to avoid repeated disk reads.
Git Hook Tool Detection (if .pre-commit-config.yaml exists):
Use the detection script to identify and run the correct tool:
# Detect tool (outputs 'prek' or 'pre-commit')
uv run ./scripts/detect_hook_tool.py
# Run detected tool with arguments
uv run ./scripts/detect_hook_tool.py run --files path/to/file.py
# Check different repository on specific files
uv run ./scripts/detect_hook_tool.py --directory /path/to/repo run --files path/to/file.py
Important - Scoped Operations: Always use --files or staged file patterns rather than --all-files. Running hooks on all files formats code outside your current branch, causing:
Use --all-files ONLY when explicitly requested by the user for repository-wide cleanup.
Detection logic: reads .git/hooks/pre-commit line 2, token 5 identifies the tool. Defaults to prek if file missing.
Note: prek is a Rust-based drop-in replacement for pre-commit. Both tools use the same .pre-commit-config.yaml and have identical CLI interfaces.
For Python files:
# Format first (auto-fixes trivial issues)
uv run ruff format path/to/file.py
# Then lint (reports substantive issues)
uv run ruff check path/to/file.py
uv run mypy path/to/file.py
uv run pyright path/to/file.py
For JavaScript/TypeScript files:
# Format first
npx prettier --write path/to/file.ts
# Then lint
npx eslint path/to/file.ts
For Shell scripts:
# Format first
shfmt -w path/to/script.sh
# Then lint
shellcheck path/to/script.sh
For Markdown:
# Lint and auto-fix
npx markdownlint-cli2 --fix path/to/file.md
For Orchestrators: Delegate immediately to linting-root-cause-resolver WITHOUT running linters yourself. See the holistic-linting-orchestrator skill for complete delegation workflows.
Agent(subagent_type="holistic-linting:linting-root-cause-resolver", prompt="Format, lint, and resolve any issues in file1.py")
Agent(subagent_type="holistic-linting:linting-root-cause-resolver", prompt="Format, lint, and resolve any issues in file2.py")
Do NOT run ruff check or mypy before delegating. The agent gathers its own linting data.
For Sub-Agents: Follow the linter-specific resolution workflow documented in the holistic-linting-resolver skill based on the linting tool reporting the issue.
Location: ../../agents/linting-root-cause-resolver.md
This agent systematically investigates and resolves linting errors by understanding root causes rather than suppressing them with ignore comments.
To install the agent:
# Install to user scope (~/.claude/agents/)
uv run ./scripts/install_agents.py --scope user
# Install to project scope (<git-root>/.claude/agents/)
uv run ./scripts/install_agents.py --scope project
# Overwrite existing agent file
uv run ./scripts/install_agents.py --scope user --force
Philosophy:
Comprehensive documentation of linting rules from three major tools:
Location: ./references/rules/ruff/index.md
Covers all Ruff rule families including:
Each rule documents:
Location: ./references/rules/mypy/index.md
Comprehensive type checking error documentation organized by category:
Each error code documents:
Location: ./references/rules/bandit/index.md
Security vulnerability documentation organized by category:
Each check documents:
Available in ./scripts/:
/lint CommandThe /lint command is a shorthand that activates this skill with optional file/directory path arguments.
Usage:
/lint # Activate holistic-linting for current task's modified files
/lint path/to/file.py # Activate holistic-linting for specific file
/lint path/to/directory # Activate holistic-linting for all files in directory
The command loads this skill and follows the workflows documented above. It is equivalent to activating /holistic-linting:holistic-linting directly.
This skill complements the claude-linting-hook which provides automatic PostToolUse linting via Claude Code hooks. The hook and skill serve different purposes:
claude-linting-hook (PostToolUse hook):
holistic-linting skill (Workflow guidance):
Use both together for comprehensive linting coverage:
User: "Add authentication middleware to the API"
Orchestrator:
1. [Implements authentication middleware in auth.py]
2. [Implementation complete, now applying holistic-linting skill]
3. [Delegates to linting agent WITHOUT running linters]
4. Agent(subagent_type="holistic-linting:linting-root-cause-resolver", prompt="Format, lint, and resolve any issues in auth.py")
5. [Agent formats with ruff format, runs ruff check + mypy]
6. [Agent finds 3 ruff errors, 2 mypy type issues]
7. [Agent resolves all 5 issues at root cause]
8. [Agent verifies: ruff check + mypy - clean]
9. [Agent produces resolution report in .claude/reports/]
10. [Orchestrator reads report confirming clean resolution]
11. Task complete ✓
Orchestrator delegates: "Create database connection pool module"
Sub-agent:
1. [Writes db_pool.py with connection logic]
2. [Before completing, applies holistic-linting skill]
3. Formatting: uv run ruff format db_pool.py
4. Linting: uv run ruff check db_pool.py && uv run mypy db_pool.py
5. [Finds 1 mypy error: Missing return type annotation]
6. [Investigates: function should return ConnectionPool]
7. [Fixes: Adds -> ConnectionPool annotation]
8. [Verifies: uv run mypy db_pool.py - clean]
9. Returns to orchestrator with completed, lint-free module ✓
When a linter run reveals issues in files the current agent did not modify, "pre-existing issues not related to my changes" is a trigger to act — not a reason to skip. Every detected problem gets recorded. No detected issue silently disappears.
Two outcomes based on whether the issue blocks the pipeline:
Discover the tracking system (search in order): .claude/backlog/ per-item files, .claude/tasks/, TODO.md, TODO, docs/TODO.md, .gsd/, sam.md. If none exists, create a per-item file in .claude/backlog/.
Record each non-blocking issue with: tool, rule code, file:line, exact linter message, discovery date.
Report all pre-existing activity in the resolution report — both issues fixed and issues recorded.
For the full triage pipeline (groom → reproduce → plan → execute), see Pre-Existing Issues Protocol.
When uncertain whether an issue is blocking: treat it as blocking and fix it.
# type: ignore, # noqa, suppression comments, or modify linter config to reduce rule severity. If a code change cannot resolve the issue, escalate as UNRESOLVED with documentation of what was triedProblem: "I don't know which linters this project uses" Solution: Linters are detected automatically by scanning config files (pyproject.toml, package.json, .pre-commit-config.yaml, etc.). Check the Linter Detection section for supported tools.
Problem: "Linting errors but I don't understand the rule"
Solution: Reference the rules knowledge base at ./references/rules/{ruff,mypy,bandit}/index.md
Problem: "Multiple files with linting errors" Solution: If orchestrator, launch concurrent linting-root-cause-resolver agents (one per file). If sub-agent, resolve each file sequentially.
Problem: "Linter not found (command not available)"
Solution: Check that linters are installed. Use uv run <tool> for Python tools to ensure virtual environment activation.
error[unresolved-import]: Cannot resolve imported module 'X' — Add the directory containing module X to [tool.ty.environment] extra-paths in pyproject.toml; run uv run ty check <path> to verify; if errors persist, confirm pyproject.toml is the config ty is reading (a ty.toml in the project root takes precedence and pyproject.toml will be ignored).
Problem: "False positive linting error" Solution: Investigate using the rule's documentation. If the rule fires on code that is genuinely correct, document what you tried and why each approach failed, then return UNRESOLVED. The user decides whether to reconfigure the rule — agents do not modify linter configuration autonomously.
Problem: "No code change resolves the linting error"
Solution: This is expected for some issues (e.g., platform-conditional imports where ruff can't evaluate sys.platform). Mark the issue as UNRESOLVED in the resolution report with: (1) approaches attempted, (2) why each failed, (3) the fundamental constraint. The orchestrator will present this to the user for a human decision on suppression vs. rule reconfiguration.
This skill is automatically loaded when installed in ~/.claude/skills/holistic-linting.
To manually reference this skill in a session:
Activate the holistic-linting skill: Skill(skill: "holistic-linting:holistic-linting")