Skip to main content

AI code review agent that detects dangerous patterns in LLM-generated code

Project description

Mastiff

PyPI version Python 3.12+ License: MIT

AI code review agent that detects dangerous patterns in LLM-generated code.

Mastiff analyzes git diffs using Claude or OpenAI to detect production-risk patterns across five categories — blocking/deadlocks, race conditions, performance degradation, resource leaks, and security vulnerabilities — scoring each finding by severity and confidence. Works with API keys or directly through the claude / codex CLI (no API key required).

Why Mastiff?

LLM-generated code often looks correct at first glance but can contain subtle patterns that only manifest in production:

  • Event loop blocking — synchronous calls in async contexts that freeze the application
  • Race conditions — shared mutable state accessed without proper synchronization
  • O(n²) algorithms — nested loops and unbounded queries that degrade with scale
  • Resource leaks — file handles, connections, and sockets opened but never closed

Traditional linters catch syntax and style issues. Mastiff focuses specifically on the patterns LLMs tend to introduce — not to replace linters, but to complement them with production-risk awareness.

What It Detects

Category Description Examples
Blocking/Deadlock Synchronous blocking calls in async contexts, potential deadlocks time.sleep() in async, synchronous I/O in event loop, inconsistent lock ordering
Race Condition Shared mutable state without synchronization, TOCTOU Global variable from multiple threads without locks, non-atomic read-modify-write
Degradation O(n²) algorithms, excessive allocations, unbounded growth Nested loops, loading entire DB table into memory, missing pagination
Resource Leak Resources opened but not properly closed open() without context manager, DB connection not returned to pool
Security SQL injection, XSS, command injection, SSRF, hardcoded secrets String-concatenated SQL queries, os.system() with user input, hardcoded API keys

Quick Start

pip install mastiff
export ANTHROPIC_API_KEY="sk-ant-..."
mastiff review --staged

Alternative installation methods:

pipx install mastiff
# or
uv tool install mastiff

Get your API key at https://console.anthropic.com/

With CLI providers (no API key needed):

If you have claude or codex CLI installed, Mastiff can use them directly — no API key required:

pip install mastiff
# claude CLI or codex CLI must be on PATH
mastiff review --staged

Mastiff auto-detects available providers in this order: claude CLI → codex CLI → ANTHROPIC_API_KEYOPENAI_API_KEY. To force a specific provider:

# mastiff.yaml
api:
  provider: claude-code  # or: codex, anthropic, openai

With OpenAI:

pip install "mastiff[openai]"
export OPENAI_API_KEY="sk-..."
mastiff review --staged

Supported OpenAI models: gpt-4.1, gpt-4o, gpt-4o-mini.

Output Example

Terminal (default):

                    Review Findings
┏━━━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ File         ┃ Line ┃ Severity ┃ Category      ┃ Title                      ┃ Confidence ┃
┡━━━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ api/users.py │ 42   │ critical │ blocking      │ time.sleep in async handler │ 92%        │
│ db/pool.py   │ 15   │ warning  │ resource_leak │ Connection not returned     │ 78%        │
└──────────────┴──────┴──────────┴───────────────┴────────────────────────────┴────────────┘

JSON (--format json):

{
  "findings": [
    {
      "rule_id": "blocking-sync-sleep",
      "category": "blocking",
      "severity": "critical",
      "file_path": "api/users.py",
      "line_start": 42,
      "title": "time.sleep in async handler",
      "confidence": 0.92
    }
  ]
}

Agent (--format agent):

[CRITICAL] src/api/users.py:42 blocking-sync-in-async
time.sleep() blocks the event loop in async handler
FIX: Replace time.sleep(n) with await asyncio.sleep(n)

Usage

CLI

# Review staged changes
mastiff review --staged

# Review a commit range
mastiff review HEAD~3..HEAD

# Choose review depth
mastiff review --staged --profile quick

# JSON output
mastiff review --staged --format json

# Strict mode: exit 2 on any finding
mastiff review --staged --strict

# Agent-friendly output (plain text, no ANSI)
mastiff review --staged --format agent

# Watch mode: continuous monitoring
mastiff watch --profile quick --format agent

Review profiles:

Profile Diff budget Context budget Use case
quick 5,000 tokens 3,000 tokens Pre-commit, editor saves
standard 20,000 tokens 15,000 tokens PR review (default)
deep 50,000 tokens 30,000 tokens Release audits

Exit codes:

Code Meaning
0 Success, no findings
1 Runtime error (config, API, etc.)
2 Success, findings present (--strict or --format agent)

Pre-commit Hook

# Install the pre-commit hook
mastiff install

# Commits are automatically reviewed
git commit -m "feat: add user endpoint"
# → mastiff reviews staged changes

In CI environments (CI=true), the hook runs in strict mode and blocks on any finding. When a baseline exists, only new findings are reported.

LSP Server (Experimental)

mastiff server

Provides real-time diagnostics on file save (quick profile). Configure your editor's LSP client to connect to mastiff.

With Claude Code

Mastiff is designed to review LLM-generated code. When using Claude Code as your development agent, Mastiff acts as an automated safety net that catches production-risk patterns before they reach your codebase.

Automatic feedback loop (recommended):

mastiff install --claude-code

This installs a PostToolUse hook that automatically reviews every file Claude Code writes or edits. When issues are found, they are fed back to Claude Code via stderr, creating an automatic fix loop.

Pre-commit hook:

Install the hook once and every commit Claude Code creates is automatically reviewed:

mastiff install

Claude Code commits through git, so the pre-commit hook runs transparently on every commit. Critical findings block the commit, giving you a chance to review before the code lands.

CI integration:

Add Mastiff to your CI pipeline to review every pull request that Claude Code opens:

# .github/workflows/ci.yml
- run: pip install mastiff
- run: mastiff review origin/main..HEAD --strict --format json

Manual review after a session:

After Claude Code completes a task in a worktree, review all changes before merging:

mastiff review main..HEAD --profile deep

With Codex CLI

mastiff install --codex

Installs a git post-commit hook. Since Codex CLI applies changes via commits, every commit is automatically reviewed. Existing post-commit hooks are preserved and chained.

Baseline

# Record current findings as baseline
mastiff baseline

# Only new findings are reported from now on

# Regenerate after refactoring
mastiff baseline --rebase

The baseline uses fingerprint-based stable IDs that are independent of line numbers, so minor code shifts don't invalidate existing suppressions.

Configuration

Generate a config file:

mastiff init

This creates mastiff.yaml with documented defaults. Key settings:

api:
  model: claude-opus-4-20250514      # Claude model to use

detection:
  min_confidence: 0.6           # Minimum confidence to report

security:
  never_send_paths:             # Files never sent to the API
    - .env
    - "*.pem"
    - "*.key"

cost:
  max_cost_usd_per_run: 1.00   # Per-run cost limit

All config models use Pydantic extra="forbid", so typos in config keys are caught immediately.

Security & Privacy

Mastiff sends code to the Claude API for analysis. Here is what it does to minimize exposure:

  • What is sent: Only the diff is sent — never complete source files. Import tracing may include small fragments from related files, bounded by a token budget.
  • Automatic redaction: Built-in regex patterns detect API keys, tokens, passwords, and private key headers. Detected values are replaced with [REDACTED] before sending. The Redactor also exposes Shannon entropy analysis for identifying high-entropy strings.
  • File exclusion: The never_send_paths setting excludes sensitive file patterns (.env, *.pem, *.key, etc.) by default. These files are filtered out before any API call.
  • Output sanitization: ANSI escape sequences and control characters are stripped from all output to prevent terminal injection.
  • Prompt injection defense: User-supplied data (diffs, context) is wrapped in delimiter tags (<diff>, <context>) and the system prompt establishes reviewer-only behavior.

This is a best-effort approach to minimize sensitive data exposure. It does not guarantee that no secrets are sent. Review your never_send_paths configuration and consider the sensitivity of your codebase before use.

Cost Control

Approximate cost per review (depends on diff size and Claude API pricing):

Profile Estimated cost
quick ~$0.01–0.05
standard ~$0.05–0.30
deep ~$0.10–0.50

The cost.max_cost_usd_per_run setting (default: $1.00) enforces a per-run budget.

Migration

From v0.2.0

  • CLI providers: Mastiff now auto-detects claude and codex CLIs and prefers them over API keys. If you want to keep using API keys when a CLI is also installed, set api.provider: anthropic (or openai) explicitly in mastiff.yaml.
  • New provider names: claude-code and codex are now valid values for api.provider.

From v0.1.0

  • Exit code change: --strict now exits with code 2 (was 1) when findings are present. Update CI scripts that check for exit 1.
  • New category: The security detection category is enabled by default. If you explicitly list categories in mastiff.yaml, add security: true to enable it.

Requirements

Optional extras:

pip install "mastiff[tree-sitter]"  # Enhanced import tracing
pip install "mastiff[lsp]"          # LSP server support
pip install "mastiff[openai]"       # OpenAI provider support

Development

git clone <repo> && cd mastiff
uv sync --all-extras
pytest                 # 325 tests
ruff check .           # lint
mypy src/              # type check

Package structure:

src/mastiff/
├── _internal/       # Git and subprocess utilities
├── analysis/        # Categories, prompt building, LLM client
├── cli/             # Commands and terminal output
├── config/          # Schema, loader, defaults
├── context/         # Language parsers, import tracer, resolver
├── core/            # Engine, models, fingerprinting, severity
├── diff/            # Diff parsing, filtering, collection
├── integrations/    # Pre-commit, Claude Code, Codex hooks, LSP server
├── observability/   # Logging and metrics
└── security/        # Secret patterns, redactor, sanitizer

License

MIT

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

mastiff-0.3.0.tar.gz (107.6 kB view details)

Uploaded Source

Built Distribution

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

mastiff-0.3.0-py3-none-any.whl (55.5 kB view details)

Uploaded Python 3

File details

Details for the file mastiff-0.3.0.tar.gz.

File metadata

  • Download URL: mastiff-0.3.0.tar.gz
  • Upload date:
  • Size: 107.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mastiff-0.3.0.tar.gz
Algorithm Hash digest
SHA256 7709c526a5abea754ad678a10385bba27839859c70cd9a5e633054b38f26e25f
MD5 bf2653df7e59012e7df77b0f42c1fa9f
BLAKE2b-256 6114b4c9fd61a2d237a82455207ec3bb252cd94135bd5298b14976fdf4e606c4

See more details on using hashes here.

File details

Details for the file mastiff-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: mastiff-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 55.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mastiff-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4babf76cc30cf6b8819f264f264e88680032fed2f5ad1a81fb61f1b47d92f553
MD5 aba811f487440c0c97577f0b534d091e
BLAKE2b-256 508437d70813d32f13b0c639ea94bac6905f1a5090388da300fe4a14c48eb949

See more details on using hashes here.

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