The problem: AI agents and git muscle memory
Claude Code has git-prism registered as an MCP server. Five structured tools: change manifests, function context, file snapshots, commit history, and review diffs. Each one returns parsed, token-efficient JSON instead of raw patch text.
But Claude was trained on millions of git commands. That muscle memory runs deep. Give it a branch to review and it reaches for git diff. Hunk headers, plus and minus prefixes, a format built for humans reading patches in 2005. Registration is not enough.
This is the problem every MCP server author hits: your tools exist, but the model's default instincts predate them.
What v0.7.0 ships
git-prism v0.7.0 ships a bundled Claude Code PreToolUse redirect hook: a bash redirect interceptor that blocks dangerous commands before they reach the shell and nudges benign git porcelain toward structured alternatives.
How the redirect hook works
The hook is a Claude Code PreToolUse program. It reads a JSON payload on stdin describing the tool call about to execute, parses the bash command with Python's shlex tokenizer (not regex; compound commands, subshells, and pipelines all parse structurally), and decides via exit code:
- Exit 0: pass through silently (vanilla shell commands)
- Exit 0 + JSON on stdout: advisory. The command runs, but the agent sees a suggestion
- Exit 2: hard block. The command never reaches the shell
Hard block (exit 2): gh pr diff returns raw GitHub patch text. Not something an agent can act on reliably.
Advisory (exit 0 + JSON): git diff main..HEAD gets a nudge toward get_change_manifest. The command runs, but next time the agent knows the structured path.
Silent (exit 0): echo hello world. No output, no delay, no interference.
The tokenizer is stdlib-only Python: shlex.shlex(posix=True, punctuation_chars=True), zero third-party dependencies. Compound commands split correctly. Subshells are recognized. Heredoc bodies are suppressed so a 200-line heredoc doesn't blow through the tokenizer. Pipeline segments are parsed independently.
Install
git-prism hooks install
It copies the bundled scripts into ~/.claude/hooks/ and writes a PreToolUse entry into Claude Code's settings.json. Works for both top-level agents and custom subagents (default scope is user to dodge a known Claude Code project-scope MCP bug). Re-install is idempotent; git-prism hooks status shows what's installed and at what version.
During development, I tried to run gh pr diff inside a Claude Code session to review a PR. The hook blocked it. I used git-prism manifest instead.
review_change: the agent-native git diff
Alongside the hook, v0.7.0 adds a fifth MCP tool: review_change. It returns a combined { manifest, function_context } payload for a ref range in a single call, splitting the response budget 40/60 between the two halves.
This is the tool the redirect hook points agents toward. Instead of:
git diff main..HEAD # → 5-50k tokens of unstructured hunk noise
Agents call:
review_change(base_ref="main", head_ref="HEAD")
And get back:
- Per-file metadata (language, change type, line counts)
- Function-level diffs (added / deleted / modified / renamed, with body hashes)
- Callers, callees, and test references per changed function
- A blast-radius risk score (none / low / medium / high) for every changed function
- Dependency changes (Cargo.toml, go.mod, package.json, etc.)
Two independent pagination cursors let you advance the halves separately. Paginate the manifest without re-fetching the context, or vice versa.
Guardrails that keep agents from overflowing
LLM context windows are expensive and finite. A raw diff of a large PR easily burns 50k tokens before the agent has read a single source file. v0.7.0 adds response-size guardrails across all read tools:
-
Manifest token budget (default 8192). When the response would exceed the budget, function/import analysis is progressively trimmed per file: full → signatures-only → bare. Pass
max_response_tokens: 0to disable enforcement when you genuinely need the full payload. -
Function context pagination (default 25 entries per page). Opaque cursor, page-size knob (1–500), and a
function_namesfilter for re-querying specific entries that were clamped on a prior page. -
Per-entry
truncatedflags. When an entry gets clamped (top 5 callers, top 5 callees, top 3 test references), itstruncated: trueflag and a mirrored name inmetadata.function_analysis_truncatedtell the agent exactly what got cut. No silent data loss.
All internal callers (like get_function_context calling get_change_manifest) bypass the budget so the second-resort tools always get complete data regardless of the user-facing guard.
Breaking changes for 0.7.0
Pre-1.0 semver means breaking changes can land in minor bumps. Two changes from pre-v0.7.0 behavior:
-
get_change_manifestflips the default forinclude_function_analysistofalse. Function-level diffs are now opt-in, matching the tool's "cheapest first-resort" contract. Passinclude_function_analysis: trueto restore the old behavior. -
record_truncatedmetric gains areasonlabel. Existing dashboards relying on the old label format will need a one-field update. Cardinality is bounded.
Install
brew install mikelane/tap/git-prism
# or
cargo install git-prism
# or
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/mikelane/git-prism/releases/download/v0.7.0/git-prism-installer.sh | sh
Source and docs: github.com/mikelane/git-prism
The full changelog, BDD scenarios (Python/behave, 13-language test matrix), and ADRs are in the repo. v0.7.0 was built across 5 implementation PRs plus 3 dependency bumps. Tagged, released, and on crates.io as of today.
This article was originally published by DEV Community and written by Mike Lane.
Read original article on DEV Community