Skip to content

CI/CD Integration Guide

Run claudelint in your CI pipeline to catch configuration issues before they reach production.

GitHub Actions

Basic Setup

yaml
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 github

Errors 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:

yaml
- name: Register problem matcher
  run: echo "::add-matcher::.github/claudelint-problem-matcher.json"

- name: Run claudelint
  run: npx claudelint check-all

The 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:

yaml
    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.sarif

Optimizing CI Runs

Changed Files Only

Speed up PR checks by only validating files that changed:

yaml
- name: Lint changed files only
  run: claudelint check-all --since origin/main --format github

- name: Lint uncommitted changes
  run: claudelint check-all --changed --format github

Use --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:

yaml
- name: Check CLAUDE.md files
  run: claudelint validate-claude-md

- name: Validate settings
  run: claudelint validate-settings

- name: Validate MCP servers
  run: claudelint validate-mcp

All 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:

yaml
- 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 --cache

With 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:

yaml
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

yaml
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:

bash
npx husky init

Add to .husky/pre-commit for a fast check on every commit:

sh
npx claudelint check-all --fast --changed --quiet

Add to .husky/pre-push for a thorough check before pushing:

sh
npx claudelint check-all

lint-staged

Run claudelint only on staged files using lint-staged:

json
{
  "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:

yaml
# .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

CodeMeaning
0No issues found
1Validation issues found
2Configuration or runtime error

Useful Flags

FlagDescription
--format githubGitHub Actions annotations (inline on PR diffs)
--format sarifSARIF output for GitHub Code Scanning
--format jsonJSON output for custom processing
--format compactOne-line-per-issue for log parsing
-q, --quietSuppress warnings, show only errors
--warnings-as-errorsFail on warnings too
--strictFail on any issue (errors + warnings + info)
--max-warnings <n>Fail if warning count exceeds limit
--allow-empty-inputExit 0 when no files found (useful with lint-staged)
--cacheEnable result caching (default in check-all)
--no-cacheDisable caching
--config <path>Custom config file path
--fixAuto-fix fixable issues
--fix-dry-runPreview fixes without applying
--changedOnly check files with uncommitted changes
--since <ref>Only check files changed since a git ref
--fastSkip expensive checks (good for pre-commit)
-o, --output-file <path>Write results to a file
--timingShow per-validator timing breakdown
--statsInclude per-rule statistics in output

Configuration File

Create .claudelintrc.json in your project root:

json
{
  "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:

json
{
  "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:

yaml
- name: Validate all workspaces
  run: claudelint check-all --workspaces

- name: Validate specific package
  run: claudelint check-all --workspace my-package