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

yaml
name: Claude Config Analysis
on: [push, pull_request]

jobs:
  claudelint:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
    steps:
      - uses: actions/checkout@v6

      - uses: actions/setup-node@v6
        with:
          node-version: '20'

      - run: npm install -g claude-code-lint

      - 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 individual validators as separate steps:

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

- name: Validate skills
  run: claudelint validate-skills

- name: Validate settings
  run: claudelint validate-settings

- name: Validate hooks
  run: claudelint validate-hooks

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

- name: Validate plugin manifest
  run: claudelint validate-plugin

- name: Validate agents
  run: claudelint validate-agents

- name: Validate commands
  run: claudelint validate-commands

- name: Validate LSP config
  run: claudelint validate-lsp

- name: Validate output styles
  run: claudelint validate-output-styles

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

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"
  }
}

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