A Claude Code plugin that reviews a PR or branch against what it was asked to build — reconstructed from the plan/spec, the Claude session that produced it, and the git development history.
Existing AI reviewers ask "is this code correct?" driftguard asks "is this what was actually requested — and only that?"
- Intent drift — the agent built what you asked, plus three things you didn't.
- Slop — one-caller abstractions, one-case config, placeholder logic, reimplementations of what already exists.
- Agent-specific defects — hallucinated package imports (a supply-chain vector), tests weakened so the suite goes green, dead code added by the diff.
- Security holes introduced by the diff — committed credentials (evidence redacted), pinned deps with known CVEs (OSV.dev), injection/deserialization/authz gaps traced by a dedicated security subagent.
- Methodology bugs in ML work (data-scientist role) — the class of defect where the code is correct, the plan was followed, the tests pass, and the result is still wrong: a leaked split, a metric computed on training data, a feature window that reaches past the prediction timestamp, an NDCG no code in the diff produces.
Inside any Claude Code session, straight from GitHub:
/plugin marketplace add pparitoshh/driftguard
/plugin install driftguard@driftguard
(The repo root doubles as a marketplace via .claude-plugin/marketplace.json.)
Local alternative: clone this repo and either copy it into your project's
.claude/plugins/ or point /plugin marketplace add /path/to/driftguard at it.
Requirements on the target machine: git, python3 (3.11+, stdlib only), and
gh (only for PR-number mode — branch mode works without it). The PyPI/npm/OSV
registry checks are the only thing that would use the network, and they are off
unless you opt in (see below); disabled or offline, they degrade to
"check skipped", never to a crash.
/driftguard:review 123 # PR number — context via `gh`
/driftguard:review --base main # local branch vs. base, no PR needed
/driftguard:review --task "..." # explicit task statement override
/driftguard:review --role ds # data-scientist review (skips the role question)
/driftguard:learn "prefer early returns in auth code — easier to debug in prod"
Everything runs inside your Claude Code session. No API keys, no servers, no embeddings, no Docker. Code never leaves your machine.
Offline by default. Two checks would otherwise make outbound requests —
deps_check (package names to PyPI/npm) and osv_check (pinned name+version
pairs to OSV.dev). Both reveal part of your dependency graph, so both are off
unless you opt in:
DRIFTGUARD_ALLOW_NETWORK=1 /driftguard:review 123 # enable registry + CVE lookupsDisabled, they report themselves under "Not checked" as
network disabled (DRIFTGUARD_ALLOW_NETWORK unset) — never as a silent pass.
Every other check (secrets, linters, dead code, test subversion, ML patterns,
and all subagents) is local-only and unaffected.
A review ends with a fix-loop handoff — say "fix findings 1-3" and the same session addresses them (no separate autofix bot needed; the reviewer is your coding agent).
Like Greptile/CodeRabbit custom rules and learnings — but as markdown in your repo:
-
.driftguard/rules.md— standing review rules in plain English. Binding on every subagent. Supports path scoping and negative rules (filters):# Rules Every new endpoint must have an auth check. ## path: scripts/** Never flag shell=True here — these are local dev tools.
-
.driftguard/learnings.md— append-only memory, one dated line per preference. Written by/driftguard:learn "..."(credentials are redacted before writing). Steers findings; never suppresses Tier 0 errors. -
Auto-detected guidelines —
CLAUDE.md,AGENTS.md,.cursorrules, and.github/copilot-instructions.mdare picked up automatically.
Before reviewing, driftguard asks what kind of feature the PR is — data
scientist, data engineer, or other — hinting at an answer from the
changed paths and manifests, so confirming takes one keystroke. Pass
--role ds|de|other to skip the question.
ds attaches a domain specialist a generalist reviewer can't replace: the code
can be correct, the plan followed, the tests green, and the NDCG still fake
because the same user is on both sides of the split. It adds one deterministic
pre-flight (ml_patterns.py — fit-before-split, metrics on train data, label in
the feature list, tuning before the split, missing seeds) and the ds-review
subagent, which walks a 48-check catalog: split integrity, data leakage,
training/serving skew, ranking labels and feedback loops, negative sampling and
loss, evaluation protocol, experiment hygiene, and data audit. Findings are
tagged ml-* and carry stable IDs (DS-08), so a rule can suppress one check
("never flag DS-18 here — position is a deliberate feature"). Every check group
is listed in the output, clean or not.
de is specced but not built yet (v0.4) — it runs as other and says so.
other is exactly the generic review, unchanged.
- Context assembly (scripts, no LLM) — plan/spec resolution chain
(PR body → linked issue → PLAN.md → commit messages → branch name → --task),
git development history (churn per changed file, branch commits), a
digest of the Claude session that produced the branch (matched from
~/.claude/projects/<slug>/*.jsonlby commit time-window + files touched), a deterministic triage card (risk level, review-effort estimate, churn hotspots, sensitive-path touches, suggested review order), and team context (.driftguard/rules.mdcustom/path-scoped rules,.driftguard/learnings.mdmemory, auto-detected CLAUDE.md/AGENTS.md/.cursorrules/copilot-instructions). - Tier 0 deterministic pre-flight — hallucinated-dependency check against
PyPI and npm, secrets scan (redacted evidence), known-vulnerability
check for pinned deps (OSV.dev), repo's own linters (ruff, local eslint),
AST dead-code scan, test-subversion diff analysis — plus the ML-methodology
scan (
ml_patterns.py) when the role is data-scientist. - Tier 1 subagent fan-out — intent-scope, slop-redundancy, regression-contract, test-integrity, security run in parallel, each with its own context window, drilling into the repo with Read/Grep/Bash — plus ds-review when the role is data-scientist.
- Noise control — cross-agent dedup, evidence-mandatory filter (findings without tool-derived evidence are dropped), team negative-rules filter, hard finding budget, and a mandatory "Not checked" section so a green verdict can't be over-trusted.
- Learning loop — correct a finding with
/driftguard:learn "..."and the preference is appended to.driftguard/learnings.md(plain markdown, no database), steering every future review. Fix findings conversationally — driftguard already runs inside your coding agent.
No RAG: the per-review corpus is small and well-scoped by construction (deterministic pre-filtering + subagent context isolation). An optional BM25 ranker is specced as a fallback only and is not shipped.
Every review returns the same shape: verdict (pass / review_needed / blocked), risk + review-effort from the triage card, a walkthrough table of what changed per file (sensitive paths first), severity- and category-tagged findings with tool evidence and a concrete action each, and a mandatory "Not checked" section listing everything the review did not verify.
- Intent as the reference point — reviews against the stated plan and the session transcript, not just the codebase. driftguard is the only reviewer that reads the transcript of how the code was produced.
- Agent-specific detection — catches the failure modes of AI-written code: overreach beyond the plan, silent scope creep, undoing of earlier decisions.
- Local and free — runs entirely on your machine; your code is never hosted on someone else's servers.
- Secrets scan — detects accidentally committed credentials, with values redacted in output.
- Known-CVE dependency check — queries the free OSV.dev API (no key
required); off unless
DRIFTGUARD_ALLOW_NETWORK=1. - npm dependency hygiene — validates imports against
package.jsonand the npm registry. - Security subagent — a dedicated review pass focused on vulnerabilities.
- Risk/effort triage card — every review is scored for risk, complexity, and estimated review effort.
- Custom rules and learnings — plain markdown in your repo, no database.
- Role-based review — a data-scientist role that checks methodology (splits, leakage, ranking evaluation) the way a generalist reviewer can't.
python3 -m unittest discover -s tests # 117 tests, stdlib only
python3 evals/build_fixtures.py /tmp/fixture # planted-issue fixture repo
python3 evals/build_fixtures.py /tmp/ds --set ds # data-scientist fixtureLayout: commands/ (slash commands), agents/ (Tier 1 subagents),
scripts/ (context + Tier 0, stdlib-only Python), evals/ (fixtures + results),
agent/ (agent runner, stdlib-only Python).
A minimal ReAct loop that executes one small task under a human-approved
contract. The LLM (headless claude CLI, no API key) never touches the
filesystem directly — it emits one JSON action per turn and the runner
validates, executes, and returns the observation.
/driftguard:task_run "add subtract() to calc" # spec/tasks (superpowers etc.) → per task: contract → approve → run → reviewOr by hand, from the driftguard checkout (or with PYTHONPATH pointing at it):
python3 -m agent.contract --task "add subtract() to calc" \
--files calc.py test_calc.py --creates calc.py \
--tests test_calc.py::test_subtract --budget 40
python3 -m agent.contract --propose "add subtract() to calc" # LLM drafts, you approve
python3 -m agent.run --contract .driftguard/contract.json
/driftguard:review --base main # unchanged review stageSafety model: the agent has no shell tool — only read_file, write_file,
run_tests, done. write_file enforces the contract allowlist, TDD-first
ordering, forbidden patterns, and a 1.5x LOC-budget hard stop; the stop gate
requires green tests plus correct test/impl write order, with a circuit
breaker that releases to a human after 3 failed stops (exit 2) or max_iterations
(exit 1). write_file also denies deleting existing lines beyond max_deleted_loc
(default 0). The runner calls claude -p --model sonnet; set DRIFTGUARD_MODEL
to change it.
Every run ends with a stats line, and the same numbers go to .driftguard/state.json and
metrics.jsonl:
stats: iterations 5/15 · calls 5 · tokens in 142310 out 1204 · cost $0.1873 (max 1500000, max $2.0) · LOC 11/20 · denials 0 · gate failures 0
Optional spend caps on the contract, --max-tokens N and --max-cost USD
(max_tokens and max_cost_usd), abort the run with exit 1 once they are reached,
alongside --max-iterations.
driftguard can also run the whole build, not just review it:
/driftguard:spec "add caching to menu API" → SPEC.md [you approve]
/driftguard:run → tasks.json [you approve]
→ per task: coder subagent → test → review → commit
→ branch review + summary [you decide merge/PR]
/driftguard:run --resume → continue an interrupted run
The orchestrator never writes code. Each task runs in a fresh coder
subagent under a contract from .driftguard/tasks.json (file allowlist,
max_loc budget, test command), and two hooks enforce it at tool level:
guard.py (PreToolUse) blocks edits outside the task's files, budget.py
(Stop/SubagentStop) blocks when the diff outgrows the budget. After the coder
returns, the orchestrator runs the test itself and /driftguard:reviews the
task diff before committing; one fix wave is allowed, then the task is
blocked and the run stops for a human decision.
Exactly three human gates: spec, task list, final merge.
State files (all local, gitignored):
| File | Purpose |
|---|---|
SPEC.md (repo root) |
source of truth for intent |
.driftguard/tasks.json |
task contracts + status (the ledger) |
.driftguard/current |
active task id — hooks are inert when absent |
.driftguard/traces/ |
full subagent outputs and hook error log |
To pause enforcement mid-run, delete .driftguard/current. To disable
entirely, uninstall/disable the plugin (hooks are registered in
hooks/hooks.json). Ledger CLI: python3 scripts/contract.py validate|init|next|show|status|attempt|summary|base.
Design inspiration: obra/superpowers (spec interview, plan tasks, subagent-per-task, review-each-step). Harness mode adds what superpowers deliberately lacks: hard tool-level enforcement (file allowlist + LOC budget) and intent-drift review of each task diff against SPEC.md.
See agentic_code.md: superpowers (design, plan) → /driftguard:task_run → /driftguard:review → finish. Written as an agent protocol that humans can read too.
Standalone/headless mode (CI), non-Claude host agents, vector retrieval, multi-repo, IDE plugins, web UI. See the plan doc §15 for upgrade triggers.