CI/CD Integration Guide
Run claudelint in your CI pipeline to catch configuration issues before they reach production.
GitHub Actions
Basic Setup
name: Lint Claude Config
on: [push, pull_request]
jobs:
claudelint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: '20'
- run: npm install -g claude-code-lint
- name: Validate with annotations
run: claudelint check-all --format githubErrors and warnings appear directly on the PR diff at the relevant lines. No permissions or upload steps needed.
Alternative Annotations
Problem Matcher (Stylish Format)
If you prefer the default stylish format but still want PR annotations, use a problem matcher:
- name: Register problem matcher
run: echo "::add-matcher::.github/claudelint-problem-matcher.json"
- name: Run claudelint
run: npx claudelint check-allThe problem matcher parses stylish output and converts errors/warnings into GitHub annotations. Place .github/claudelint-problem-matcher.json in your repo (available in the claudelint repository).
SARIF Upload (Code Scanning)
Use SARIF when you need persistent results, trend tracking, or more than 50 annotations per run (GitHub limits workflow annotations to 50 per run). Add security-events: write to permissions and replace the run step in the basic setup:
permissions:
security-events: write
# ... checkout, setup-node, install as above ...
- name: Run claudelint (SARIF)
run: claudelint check-all --format sarif > results.sarif
continue-on-error: true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: results.sarifOptimizing CI Runs
Changed Files Only
Speed up PR checks by only validating files that changed:
- name: Lint changed files only
run: claudelint check-all --since origin/main --format github
- name: Lint uncommitted changes
run: claudelint check-all --changed --format githubUse --since <ref> to check files changed since a git ref (ideal for PRs), or --changed for uncommitted changes.
Selective Validators
Instead of check-all, run only the validators relevant to your project:
- name: Check CLAUDE.md files
run: claudelint validate-claude-md
- name: Validate settings
run: claudelint validate-settings
- name: Validate MCP servers
run: claudelint validate-mcpAll available validators: validate-claude-md, validate-skills, validate-settings, validate-hooks, validate-mcp, validate-plugin, validate-agents, validate-commands, validate-lsp, validate-output-styles. Run claudelint --help for descriptions.
Caching
Add caching to speed up repeated runs:
- name: Cache claudelint results
uses: actions/cache@v5
with:
path: .claudelint-cache
key: claudelint-${{ hashFiles('**/*.md', '**/*.json') }}
restore-keys: claudelint-
- name: Run claudelint
run: claudelint check-all --cacheWith Claude Code GitHub Actions
Claude Code GitHub Actions lets Claude respond to @claude mentions in PRs, create PRs from issues, and run automated code review. claudelint validates your Claude Code configuration files — the two complement each other.
Add a claudelint validation job alongside your Claude Code action to catch config issues in the files Claude relies on:
jobs:
lint-config:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: '20'
- run: npm install -g claude-code-lint
- run: claudelint check-all --format github
claude-review:
runs-on: ubuntu-latest
steps:
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}GitLab CI
claudelint:
image: node:20
stage: lint
script:
- npm install -g claude-code-lint
- claudelint check-all --format compact
cache:
key: claudelint
paths:
- .claudelint-cache/
rules:
- changes:
- "**/*.md"
- ".claude/**"
- ".mcp.json"
- "skills/**"Git Hooks
Husky
Run claudelint as a git hook with Husky:
npx husky initAdd to .husky/pre-commit for a fast check on every commit:
npx claudelint check-all --fast --changed --quietAdd to .husky/pre-push for a thorough check before pushing:
npx claudelint check-alllint-staged
Run claudelint only on staged files using lint-staged:
{
"lint-staged": {
"*.md": "claudelint validate-claude-md --allow-empty-input",
".claude/**/*.json": "claudelint check-all --allow-empty-input"
}
}Pre-commit (Python)
Using the pre-commit framework:
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: claudelint
name: claudelint
language: system
entry: npx claude-code-lint check-all
pass_filenames: false
files: '\.(md|json)$'Configuration
Exit Codes
| Code | Meaning |
|---|---|
| 0 | No issues found |
| 1 | Validation issues found |
| 2 | Configuration or runtime error |
Useful Flags
| Flag | Description |
|---|---|
--format github | GitHub Actions annotations (inline on PR diffs) |
--format sarif | SARIF output for GitHub Code Scanning |
--format json | JSON output for custom processing |
--format compact | One-line-per-issue for log parsing |
-q, --quiet | Suppress warnings, show only errors |
--warnings-as-errors | Fail on warnings too |
--strict | Fail on any issue (errors + warnings + info) |
--max-warnings <n> | Fail if warning count exceeds limit |
--allow-empty-input | Exit 0 when no files found (useful with lint-staged) |
--cache | Enable result caching (default in check-all) |
--no-cache | Disable caching |
--config <path> | Custom config file path |
--fix | Auto-fix fixable issues |
--fix-dry-run | Preview fixes without applying |
--changed | Only check files with uncommitted changes |
--since <ref> | Only check files changed since a git ref |
--fast | Skip expensive checks (good for pre-commit) |
-o, --output-file <path> | Write results to a file |
--timing | Show per-validator timing breakdown |
--stats | Include per-rule statistics in output |
Configuration File
Create .claudelintrc.json in your project root:
{
"rules": {
"skill-body-too-long": ["warn", { "maxLines": 600 }],
"skill-body-word-count": ["warn", { "maxWords": 7000 }],
"skill-description-max-length": ["warn", { "maxLength": 300 }]
},
"output": {
"format": "stylish"
}
}Monitoring Config Drift
Not every rule needs to be a hard gate. Setting rules to warn lets CI surface trends before they become problems — you get a heads-up in your PR checks without blocking the build.
CLAUDE.md size is a good example. Claude Code performance degrades once the file exceeds 40KB, but you probably want to know well before that:
{
"rules": {
"claude-md-size": {
"severity": "warn",
"options": { "maxSize": 30000 }
}
}
}This pattern works with any configurable rule — skill body length, word counts, import depth. Set the threshold where you want the early signal, and let CI do the monitoring.
Monorepo Support
For monorepo projects with multiple packages:
- name: Validate all workspaces
run: claudelint check-all --workspaces
- name: Validate specific package
run: claudelint check-all --workspace my-package