pincherMCP indexes any repo into a byte-offset symbol store, a knowledge graph, and a BM25 full-text search — all populated in one AST pass — then exposes 36 tools over MCP stdio or HTTP REST. Agents get what they need in tokens, not files. Pincher is the foundation; the _meta envelope on every response is the enabler; the LLM in your host's loop is the router. Read the leverage-layers frame →
Why it mattersEvery tool response carries a real BPE token count. Real numbers on this codebase (~950 files, ~8,000 symbols, ~5,600 edges, v0.94):
Three leverage layers that stackSkip a layer and you leave value on the table. Most integrators wire up the atomic tools, miss the hook (the highest-leverage layer per token saved), and never branch on _meta — extracting ~20% of the available leverage. Full frame: loop-leverage-layers.md.
pincher hook-check intercepts Read / Grep BEFORE the agent commits. Returns "use this pincher tool instead" with a _meta-shaped justification. Zero round-trips — runs inside the host's tool-dispatch hook. The avoided call is infinite percent saving: the cost of a call that never fires is zero. Installed by pincher init --target=<your-host>.
_meta envelope mid-loopEvery response carries typed signals the agent's NEXT call branches on: next_steps[], empty_reason enum, warnings_v2[], capabilities[], request_id, drift fields. Three branches and a loop on the host side replaces a paragraph of model reasoning per turn. Per-field contract: meta-envelope-contract.md.
context_for_task (v0.66) bundles the canonical 5–10-call investigation behind one entry point. Same store, no nested envelopes — direct execution. Latency drops ~5× on interactive UIs; the agent stops seeing "thinking…" indicators between every atomic call. Phase 4 composites (#1391) gate on real usage data — composites bundling the wrong sequences are worse than no composite at all.
Same investigation, three shapesReal task: "why does the TestExtractGoCalls_Closure test sometimes emit phantom CALLS edges?" Three integration shapes, three radically different token / latency profiles.
7 calls: Grep for the test → Read three large files → Grep "phantom CALLS" → Grep "shadow" → Read 8 more files. None of the reads were "wrong" — just bigger than necessary. This is what most hosts default to without pincher wired into the hook layer.
_meta branching ~3.2K tokens4 calls: search → context → trace → query. Each call's _meta.next_steps shaped the next; _meta.warnings_v2 named the related fix (#1429) so the agent stopped exploring. 14× cheaper than shape A.
_meta ~2.8K tokens1 call: the agent's first instinct was Grep — the hook converted it to search. The agent then fired context_for_task, which returned the top symbols + context + inbound traces + related ADRs in one bundle. 16× cheaper than A; one round-trip vs A's seven. All three leverage layers contributing.
How it's stored under the hoodThree co-located indexes in one shared symbol table — populated by a single AST pass. No duplication, no sync overhead. (Distinct from the three leverage layers above — those are how an agent consumes pincher; these are how pincher stores the data.)
Every symbol persists start_byte/end_byte. Retrieval is 1 SQL lookup + 1 os.Seek + 1 os.Read. No re-parsing, no line scanning, sub-millisecond on any symbol.
Symbols are graph nodes; CALLS and IMPORTS are edges. Cypher-subset (pinchQL) queries compile down to three SQL strategies (scan, JOIN, BFS) for sub-ms structural lookups.
Virtual table with BM25 ranking over names, signatures, and docstrings. Auto-synced via INSERT/UPDATE/DELETE triggers — you never manage it manually.
30 tools, one mental modelEvery tool returns a _meta envelope with tokens used / saved and latency. Pick the tool by what you're trying to do, not by the underlying index.
search, architecture, list, schema, health — orient on any project without reading files.
symbol, symbols, context — pull one symbol, a batch, or a symbol plus its direct dependencies. Byte-offset, O(1).
query (Cypher), trace (BFS call paths with risk labels), changes (git-diff → blast radius).
adr persists architectural decisions across sessions; fetch stores URL content as a searchable Document symbol.
InstallPick your platform. Every install produces the same single binary; service templates live under packaging/.
git clone https://github.com/kwad77/pincher
cd pincher
go build -o pincher ./cmd/pinch/
# Drop the pincher policy block into your project's CLAUDE.md
./pincher init # ./CLAUDE.md
./pincher init --global # ~/.claude/CLAUDE.md
# Run the HTTP dashboard alongside your MCP client
./pincher --http 127.0.0.1:8080
# Or open the dashboard on demand — auto-starts the server if needed
./pincher web
# Stay current — pulls + rebuilds in place from this checkout
./pincher update
# Once a tap is published (see packaging/homebrew/pincher.rb)
brew tap kwad77/pincher
brew install pincher
brew services start pincher
PINCHER_HTTP_KEY=$(openssl rand -hex 16)
docker run -d --name pincher \
-v pincher-data:/data \
-p 8080:8080 \
-e PINCHER_HTTP_ADDR=:8080 \
-e PINCHER_HTTP_KEY \
ghcr.io/kwad77/pinchermcp:latest
# Download the matching archive from the releases page, then:
tar -xzf pincher-v1.9.0-linux-amd64.tar.gz
sudo mv pincher-v1.9.0-linux-amd64 /usr/local/bin/pincher
pincher --version
pincher init --target=<host> writes the host's project-rules / hook file at the canonical path. --target=detect walks the local filesystem and wires up every detected host in one pass.
# Wire up whichever editor / agent is installed locally
pincher init --target=detect
# Or pick a specific host
pincher init --target=claude # ./CLAUDE.md (Claude Code CLI)
pincher init --target=cursor # ./.cursor/rules/pincher.mdc
pincher init --target=zed # ./.zed/settings.json
pincher init --target=codex # ~/.codex/config.toml
pincher init --target=vscode-copilot # ./.github/copilot-instructions.md
pincher init --target=jetbrains # ./.junie/guidelines.md (v0.71)
pincher init --target=antigravity # ./.agents/rules/pincher.md (v0.72)
pincher init --target=antigravity-mcp # ~/.gemini/antigravity/mcp_config.json (v0.89)
pincher init --target=goose # ./.agents/plugins/pincher Open Plugins hook
pincher init --target=windsurf # ./.windsurf/rules/pincher.md
pincher init --target=gemini # ~/.gemini/settings.json
Goose users also add Pincher as a stdio MCP extension in ~/.config/goose/config.yaml; see the Goose tutorial for the two-piece MCP + hook setup.
Any MCP-compatible client works. Two example configs — the command is the same everywhere.
{
"mcpServers": {
"pincher": {
"type": "stdio",
"command": "/path/to/pincher"
}
}
}
{
"mcpServers": {
"pincher": {
"command": "/path/to/pincher"
}
}
}
Where pincher is goingPre-1.0. The cadence: nine minor releases per phase ending at a stable promotion (v0.60, v0.70, v0.80, v0.90, v1.0). Phase 3 closed at v0.80 stable, Phase 4 (composite-tool buildout) at v0.90 stable; currently in Phase 5 — the v1.0 supply-chain + measurement + RC dogfood path.
The v1.0 supply-chain + measurement + RC dogfood path (v0.83 → v0.99). Phase 4's composite-tool buildout completed at the v0.90 stable promotion — all five composites shipped: investigate_failure (bug-hunt from stack trace), plan_change (pre-edit blast radius), audit_unused (dead-code with deep-trace confirmation), onboard_module (new-contributor orientation), why_empty (empty-result recovery). Each emits the same typed _meta contract as the atomic tools. Phase 4 umbrella: #1391. Phase 3 (v0.71 → v0.80) closed at stable promotion 2026-05-18 — umbrella: #668.
Tool descriptions, MCP schemas, the _meta envelope shape, the empty_reason enum, the always-on capabilities list — all lock at v1.0. Migration guide finalized by then. Roadmap issue: #638. Until v1.0: minor versions can change surface; patch versions only fix bugs.
No cloud control plane. No telemetry beacons. No multi-tenant server mode. No router / orchestrator inside pincher itself. Local-first single-binary by design: your code never leaves your machine, every byte returned originates in your own pincher.db, and the install footprint stays one file. That constraint shapes everything else on this list.