Skip to main content

Enforce your CLAUDE.md guidelines using Claude AI - intelligent linting for agent instructions

Project description

lint-claude

Automatically enforce your CLAUDE.md guidelines using Claude AI

PyPI version License: MIT Python 3.11+

The Problem

You've written a CLAUDE.md file with coding guidelines, architecture rules, and best practices for your project. But how do you ensure your team actually follows them?

Manual code reviews miss things. Reviewers can't remember every guideline, and catching violations is tedious and inconsistent.

Traditional linters are rigid. They can't understand context-specific rules like "use functional patterns for data transformations" or "avoid nested conditionals in business logic."

You need intelligent, automated guideline enforcement that understands your specific rules and checks every file change before it's merged.

The Solution

lint-claude uses Claude AI to analyze your code against your CLAUDE.md guidelines automatically. It catches violations during development and in CI/CD, ensuring consistent adherence to your team's standards.

# Check changed files before committing
uvx lint-claude --working

# In CI/CD: fail the build if guidelines are violated
uvx lint-claude --diff main

Smart & Fast:

  • Prompt caching reduces API costs by ~90%
  • File hashing skips unchanged files
  • Batch processing handles large projects efficiently
  • Git-aware checks only what changed

Team-Friendly:

  • Multiple scan modes (full, diff, working, staged)
  • CI/CD integration with exit codes
  • JSON output for custom tooling
  • Resume support for interrupted scans

Quick Start

1. Install with uvx (no installation needed)

# Run directly without installing
uvx lint-claude --help

Or install globally:

# Install with uv
uv tool install lint-claude

# Install with pip
pip install lint-claude

2. Set your API key

export ANTHROPIC_API_KEY="your-api-key-here"

Get your API key from Anthropic Console.

3. Create CLAUDE.md

Create a CLAUDE.md file in your project root with your guidelines:

# Project Guidelines

## Code Style
- Use descriptive variable names (no single letters except loop counters)
- Functions should be under 50 lines
- Prefer composition over inheritance

## Architecture
- Keep business logic in src/domain/
- All API calls must use the retry wrapper
- Database queries must be in repository classes

## Testing
- Every public function needs a test
- Test files must be colocated with source files

4. Run your first scan

# Check all files
uvx lint-claude --full

# Check only changed files (faster)
uvx lint-claude --working

That's it! Claude will analyze your code and report any guideline violations.

Usage

Scan Modes

# Full project scan
uvx lint-claude --full

# Check files changed from a branch (great for PRs)
uvx lint-claude --diff main
uvx lint-claude --diff origin/develop

# Check uncommitted changes (working directory)
uvx lint-claude --working

# Check only staged files (pre-commit hook)
uvx lint-claude --staged

Output Formats

# Human-readable output (default)
uvx lint-claude --full

# JSON output for tooling integration
uvx lint-claude --full --json

# Quiet mode (only errors)
uvx lint-claude --full --quiet

# Verbose mode (detailed logging)
uvx lint-claude --full --verbose

Configuration

Create .lint-claude.json in your project root:

{
  "include": ["**/*.py", "**/*.js", "**/*.ts"],
  "exclude": ["node_modules/**", "dist/**", "*.test.js"],
  "batch_size": 10,
  "max_file_size_mb": 1.0,
  "model": "claude-sonnet-4-5-20250929"
}

All settings are optional. Defaults work for most projects.

Available options:

Option Default Description
include ["**/*.py", "**/*.js", "**/*.ts"] Glob patterns for files to check
exclude See below Glob patterns to skip
batch_size 10 Files per API request (1-100)
max_file_size_mb 10.0 Skip files larger than this
model claude-sonnet-4-5-20250929 Claude model to use
api_key (env var) Override ANTHROPIC_API_KEY
api_timeout_seconds 300 API request timeout
rate_limit_rpm 50 API requests per minute

Default exclude patterns (automatically skipped):

  • .venv/**, venv/**, env/** - Python virtual environments
  • __pycache__/**, *.pyc, *.pyo - Python cache files
  • .pytest_cache/**, .mypy_cache/**, .ruff_cache/** - Test/lint caches
  • node_modules/** - Node.js dependencies
  • dist/**, build/**, *.egg-info/** - Build outputs
  • .git/** - Version control
  • .vscode/**, .idea/** - IDE directories

Use snake_case (preferred) or camelCase for keys.

CI/CD Integration

lint-claude returns exit code 0 for clean scans and 1 when violations are found, making it perfect for CI/CD.

GitHub Action (Recommended)

Use the official GitHub Action for the easiest integration:

name: CLAUDE.md Compliance

on: [pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Need full history for diff mode

      - name: Lint CLAUDE.md
        uses: vtemian/lint-claude@v0.3.1
        with:
          mode: 'diff'
          base-branch: 'origin/main'
          anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}

Action Inputs

Input Description Default
mode Scan mode: full, diff, working, staged diff
base-branch Base branch for diff mode origin/main
anthropic-api-key API key (uses ANTHROPIC_API_KEY secret if not set) -
fail-on-violations Fail workflow if violations found true
output-format Output format: text or json text

Action Outputs

Output Description
violations-found Whether violations were found (true/false)
summary Summary of violations

More Examples

Full project scan:

- uses: vtemian/lint-claude@v0.3.1
  with:
    mode: 'full'

Comment violations on PR:

- name: Lint changed files
  id: lint
  uses: vtemian/lint-claude@v0.3.1
  with:
    mode: 'diff'
    fail-on-violations: 'false'

- name: Comment on PR
  if: steps.lint.outputs.violations-found == 'true'
  uses: actions/github-script@v7
  with:
    script: |
      github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: `## ⚠️ CLAUDE.md Violations\n\n${{ steps.lint.outputs.summary }}`
      });

Check staged files only:

- uses: vtemian/lint-claude@v0.3.1
  with:
    mode: 'staged'

See example workflows for more.

Using uvx (Alternative)

If you prefer running the CLI directly:

name: CLAUDE.md Compliance

on: [pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Check guidelines
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          uvx lint-claude --diff origin/main

GitLab CI

lint-claude:
  image: python:3.11
  script:
    - pip install uv
    - uvx lint-claude --diff origin/main
  only:
    - merge_requests

Pre-commit Hook

Add to .pre-commit-config.yaml:

repos:
  - repo: local
    hooks:
      - id: lint-claude
        name: CLAUDE.md compliance
        entry: uvx lint-claude --staged
        language: system
        pass_filenames: false

How It Works

  1. File Collection - Gathers files based on scan mode and include/exclude patterns
  2. Cache Check - Skips files unchanged since last scan (based on file hash + CLAUDE.md hash)
  3. Batch Processing - Groups files into batches (default 10, configurable)
  4. API Analysis - Sends batches to Claude with CLAUDE.md in cached system prompt
  5. Violation Detection - Parses Claude's structured XML response
  6. Result Caching - Stores results for future runs
  7. Reporting - Outputs violations with file paths and line numbers

Caching Strategy

lint-claude is designed to be fast and cost-effective:

  • Prompt Caching - CLAUDE.md is cached by Claude's API, reducing costs by ~90%
  • File Hash Cache - Only re-checks modified files (.lint-claude-cache.json)
  • CLAUDE.md Hash - Triggers full re-scan when guidelines change
  • Resume Support - Interrupted scans resume from last batch (.lint-claude-progress.json)

Example: Checking 100 files costs ~$0.50 on first run, then ~$0.05 for incremental checks.

Examples

Example Output

$ uvx lint-claude --working

🔍 Checking 3 files against CLAUDE.md...

❌ src/auth/login.py
  Line 45: Function `authenticate_user` is 73 lines long.
           Guideline requires functions under 50 lines.

  Line 12: Variable name `u` is not descriptive.
           Guideline requires descriptive names.

❌ src/api/users.py
  Line 23: Database query not in repository class.
           Guideline requires all database queries in repositories.

✅ src/utils/format.py - No violations

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Summary: 2 files with violations, 1 file clean

Exit code: 1

Example JSON Output

$ uvx lint-claude --staged --json
{
  "results": [
    {
      "file": "src/auth/login.py",
      "violations": [
        {
          "type": "error",
          "line": 45,
          "message": "Function `authenticate_user` is 73 lines long. Guideline requires functions under 50 lines."
        }
      ]
    }
  ],
  "summary": {
    "files_checked": 3,
    "files_with_violations": 2,
    "files_clean": 1,
    "total_violations": 3
  },
  "metrics": {
    "duration_seconds": 4.2,
    "cache_hit_rate": 0.67,
    "api_calls_made": 1
  }
}

Advanced Usage

Custom Model

Use different Claude models for different needs:

# Fast and cheap (Haiku)
uvx lint-claude --full --model claude-haiku-20250301

# More thorough (Opus)
uvx lint-claude --full --model claude-opus-20250229

# Default (Sonnet - best balance)
uvx lint-claude --full --model claude-sonnet-4-5-20250929

Batch Size Tuning

# Smaller batches (more accurate, more API calls)
uvx lint-claude --full --batch-size 5

# Larger batches (faster, cheaper, may miss context)
uvx lint-claude --full --batch-size 50

Skip Cache

# Force re-check all files
rm .lint-claude-cache.json
uvx lint-claude --full

Troubleshooting

API Rate Limits

If you hit rate limits, reduce RPM in config:

{
  "rate_limit_rpm": 30
}

Large Files Skipped

Files larger than 10MB are skipped by default. To check larger files:

{
  "max_file_size_mb": 20.0
}

Cost Concerns

  • Use --diff or --working instead of --full to check fewer files
  • Reduce batch_size for more granular caching
  • Use Haiku model for cheaper analysis

Cost estimate: ~$0.005 per file on first check, ~$0.0005 on cached re-checks.

Interrupted Scans

If a scan is interrupted, it will resume from the last completed batch:

# Resume automatically
uvx lint-claude --full

To start fresh:

rm .lint-claude-progress.json
uvx lint-claude --full

Documentation

Development

# Clone repository
git clone https://github.com/vtemian/lint-claude.git
cd lint-claude

# Install dependencies
uv sync

# Run tests
uv run pytest

# Run with coverage
uv run pytest --cov=claude_lint --cov-report=html

# Lint code
uv run ruff check src/

# Format code
uv run ruff format src/

# Type check
uv run mypy src/

License

MIT License - see LICENSE file for details.

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests (uv run pytest)
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

FAQ

How is this different from traditional linters?

Traditional linters (ESLint, Pylint, Ruff) are rule-based and can't understand context. lint-claude uses AI to understand your specific guidelines in natural language, like "avoid god classes" or "use repository pattern for database access."

Does it replace traditional linters?

No, use both! Traditional linters catch syntax errors and common issues. lint-claude catches architectural and stylistic violations specific to your team's guidelines.

How much does it cost?

~$0.005 per file on first scan, ~$0.0005 on incremental scans. A typical PR with 10 changed files costs less than $0.01.

Can I use it offline?

No, it requires Claude API access. However, it caches aggressively to minimize API calls.

What models are supported?

All Claude 3+ models: Haiku, Sonnet, Opus. Sonnet (default) offers the best balance of speed, cost, and accuracy.

Can I customize the prompt?

The system prompt is fixed to ensure reliable output parsing. Customize behavior through your CLAUDE.md guidelines instead.

Acknowledgments

Support


Made with ❤️ by developers who believe in enforceable standards

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lint_claude-0.4.0.tar.gz (55.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lint_claude-0.4.0-py3-none-any.whl (35.2 kB view details)

Uploaded Python 3

File details

Details for the file lint_claude-0.4.0.tar.gz.

File metadata

  • Download URL: lint_claude-0.4.0.tar.gz
  • Upload date:
  • Size: 55.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for lint_claude-0.4.0.tar.gz
Algorithm Hash digest
SHA256 d1b7ccb7ede017d4ea9061bf42582473b5aec496df9dd8d08f3cc59973fa2626
MD5 26dca4862a39070ff2ca426c874af2b1
BLAKE2b-256 90955ccf00b7279ae659787fd506b798df7d35c690627788f82ff5168ce62c03

See more details on using hashes here.

Provenance

The following attestation bundles were made for lint_claude-0.4.0.tar.gz:

Publisher: publish.yml on vtemian/lint-claude

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lint_claude-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: lint_claude-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 35.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for lint_claude-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d3a61a29f8882a2f31c20d6b46f8369ce4598d305571b001f2938895e75b7b70
MD5 87d4a9c8130dab90b654d7a29c35621e
BLAKE2b-256 e9f28b8391044fcb0b20abe27c076ea564dfbc3fe8e13b3700d3d0831b9e0678

See more details on using hashes here.

Provenance

The following attestation bundles were made for lint_claude-0.4.0-py3-none-any.whl:

Publisher: publish.yml on vtemian/lint-claude

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page