Documentation
Metatron captures your codebase's real implementation decisions as structured decisions and serves them to AI coding agents over MCP. Bootstrap once, curate what's worth keeping, serve it to your agent — and let the agent's feedback feed the next round of candidates.
Overview
A decision is a typed record — pattern, scope,
rationale, confidence, source_refs — not a prose
doc. Metatron is self-hosted and runs against a private codebase: extraction sends only
structural signals (imports, decorators, base classes, commit subjects) to the
model, never raw source, and agent feedback is stored only in your local SQLite database.
How Metatron Compares
| Dimension | Code RAG (e.g., Cursor) | Code Graphs (e.g., Graphify) | Metatron (Decisions) |
|---|---|---|---|
| Primary Focus | Text similarity search | Code architecture & call chains | Intent, gotchas & conventions |
| Primary Data Source | Raw source files | Abstract Syntax Trees (AST) | Git logs + Developer feedback |
| What it Captures | What code is written where | How files/functions are connected | Why decisions were made |
| Curation Gate | None (fully automated) | None (fully automated) | Curated (Human-in-the-loop) |
| Best For | Finding code examples | System navigation & exploration | Writing code like a team senior |
The loop
Bootstrap with ingest, curate candidates into the canonical set, then
serve them to your agent over MCP. As the agent works it reports gaps via
submit_feedback; refine-feedback reshapes those gaps into new
candidate decisions — closing the loop on the conventions extraction can't see
(cross-file and workflow rules). Crucially, feedback returns as candidates, so
the human gate is never bypassed.
┌─────────── ingest ───────────┐ your repo ─┤ parse (tree-sitter) + git ├─▶ candidate decisions └──────── LLM extraction ───────┘ │ ▼ curate (human) ◀── triage (advisory) │ approve / reject ▼ coding agent ◀──── serve (MCP) ──── canonical decisions │ └── submit_feedback ──▶ refine-feedback ──▶ candidate decisions ──▶ curate
Install
To install Metatron as a global tool on your system:
$ pip install getmetatron # Or if you use uv: $ uv tool install getmetatron
Alternatively, you can use our installer script which handles Python, uv, and path configuration automatically:
$ curl -sSf https://getmetatron.com/install.sh | sh
To run it locally from source or contribute to the project, clone and sync instead:
$ git clone https://github.com/kerbelp/metatron.git $ cd metatron $ uv sync # create venv and install dependencies
Run with Docker
A Dockerfile is included (it's also what the Glama.ai listing builds). The
image's entrypoint is the metatron CLI and its default command serves the MCP
server over stdio, so docker run with no arguments starts the server.
$ docker build -t getmetatron .
Decisions live in a SQLite database, so mount a volume to persist it across runs. Ingest a repo, then serve the curated decisions:
# 1. ingest a repo into a persisted DB (needs an API key) $ docker run --rm \ -e ANTHROPIC_API_KEY \ -v metatron-data:/data -e METATRON_DB=/data/metatron.db \ -v /path/to/your/repo:/repo:ro \ getmetatron ingest /repo # 2. serve the curated decisions over stdio (no API key needed) $ docker run -i --rm \ -v metatron-data:/data -e METATRON_DB=/data/metatron.db \ getmetatron serve --repo <id>
ingest prints the <id> to pass to serve. The
-i flag on serve is required — stdio needs an open stdin. To point
a coding agent at the container, use it as the MCP command:
{
"mcpServers": {
"metatron": {
"command": "docker",
"args": ["run", "-i", "--rm",
"-v", "metatron-data:/data",
"-e", "METATRON_DB=/data/metatron.db",
"getmetatron", "serve", "--repo", "<id>"]
}
}
}
Configure
Secrets come from the environment only. The CLI auto-loads a
.env from the working directory (it never overrides an already-exported
variable, and .env is gitignored):
ANTHROPIC_API_KEY=sk-ant-...
Non-secret settings live in an optional metatron.toml.
Environment variables METATRON_DB / METATRON_MODEL override it.
[metatron] db_path = "metatron.db" # one SQLite file holds many repos model = "claude-sonnet-4-6" # default extraction model
Quick start
$ metatron ingest /path/to/your/repo # 1. bootstrap candidates (needs API key) $ metatron candidates list # 2. review … $ metatron candidates approve <id> # … and curate $ metatron serve --repo <id> # 3. serve canonical decisions over MCP
ingest prints the <id> to use for serve. To wire
it into a coding agent automatically, see Connect an agent.
ingest
Parses git-tracked source files (tree-sitter) and reads commit history, aggregates per-area signals, asks the model to infer decisions, and stores them as candidates.
$ metatron ingest /path/to/your/repo Ingested repo 'github.com/acme/app': parsed 214 files, read 500 commits across 38 scopes, created 271 candidate decisions. Review them with: metatron candidates list --repo github.com/acme/app
| Flag | Default | Meaning |
|---|---|---|
--max-commits N | 500 | how much git history to read |
--since DATE | — | only commits after e.g. 2024-01-01 |
--path SUBTREE | — | limit ingest to a subtree, e.g. src/components |
--repo ID | origin remote | override the repo identity |
Decisions are keyed by a repo identity derived from the origin
remote (constant across developers; a checkout path isn't), with a directory-name
fallback when there's no remote. One DB holds many repos; each is isolated on retrieval.
candidates
Review and curate — humans decide what becomes canonical.
$ metatron candidates list 1d2ab8e8… [high] (CheckoutSuccessRedirect (paid submit/finish flow)) After a paid submission completes, redirect to /my-dashboard/?thanks=1 … $ metatron candidates approve 1d2ab8e8… Decision 1d2ab8e8… approved. $ metatron candidates reject d672a984… Decision d672a984… rejected.
candidates list accepts --repo <id> and --scope <path>
filters. approve promotes a candidate to canonical; reject discards it.
triage
For large candidate queues, a separate LLM pass scores each candidate (recommended / borderline / not-recommended) with a reason, so you curate a ranked, pre-filtered queue. It does not curate — a human still approves.
$ metatron triage --repo github.com/acme/app Triaged 271 candidates: approve=88, borderline=96, reject=87 judge cost: ~$0.42
Flags: --repo <id> (limit to one repo), --limit N (max candidates to judge).
serve
Expose canonical decisions to agents over MCP (stdio). One served instance serves exactly
one repo (--repo, the id printed by ingest), so an agent only
ever sees that repo's decisions. It also records usage events to the same DB for the UI.
$ metatron serve --repo github.com/acme/app
ui
The local curation web UI. Binds to localhost (bumping to the next free
port if taken) and reads/writes the same store as the CLI.
$ metatron ui Metatron curation UI on http://127.0.0.1:1337 (Ctrl-C to stop)
- Decisions — browse paginated; filter by status / scope / triage / origin; full-text search; approve/reject with a click.
- Usage — how often agents query, coverage, most-queried scopes, recent queries.
- Quality — decision quality by origin (ingest vs feedback) and one-time ingest cost.
- Feedback — the agent feedback stream, filterable All / Unhandled / Handled, with a Refine into decisions button per report.
Flag: --port N (starting port, default 1337).
refine-feedback
When an agent reports a missing convention via submit_feedback, this
reshapes those free-text gap reports into structured candidate decisions
(defaults to Opus, the higher-stakes step). Nothing it produces is canonical — it all
goes to curation.
$ metatron refine-feedback Refined 3 feedback report(s) into 13 candidate decision(s) for curation. refiner cost: ~$0.19
Flags: --repo <id>, --limit N, --model <name>.
version
Print the installed version and check for an available update.
$ metatron version metatron 0.7.0 (rev a3f1c2d) → update available: 0.8.0 (run: uv tool upgrade getmetatron)
The update notice is suppressed when already on the latest release, when running a
dev checkout, or when METATRON_NO_UPDATE_CHECK=1 is set. The PyPI check
is throttled to once every 24 hours and cached locally — it adds no latency to normal
commands. The upgrade command shown matches how you installed (uv or pip); override it
by setting METATRON_INSTALL_CMD or by editing
~/.metatron/install.json.
Connect an agent
So a coding agent reliably consults decisions rather than rediscovering conventions, run the onboarding script from inside the target repo:
$ bash /path/to/metatron/metatron_setup.sh # or pass the repo dir as an arg
It is additive and idempotent — it adds (never deletes) four things to the target repo:
- A "query Metatron first" block in
CLAUDE.md(between markers). - A
UserPromptSubmithook in.claude/settings.jsonthat re-injects the directive every turn. - A
Stophook that reminds the agent (once per session) to callsubmit_feedbackwhen it consulted Metatron but never sent feedback. - The
metatronMCP server in.mcp.json.
Manual MCP client config
If you wire the server up yourself instead of using the script:
For PyPI / Global Installation:
{
"mcpServers": {
"metatron": {
"command": "metatron",
"args": ["serve", "--repo", "github.com/acme/app"]
}
}
}
For Local Clone / Development:
{
"mcpServers": {
"metatron": {
"command": "uv",
"args": ["run", "--project", "/abs/path/to/metatron", "metatron", "serve", "--repo", "github.com/acme/app"],
"env": { "METATRON_DB": "/abs/path/to/metatron.db" }
}
}
}
MCP tools exposed
| Tool | Purpose |
|---|---|
get_decisions_for_context |
the relevant canonical decisions as compact structured context, with a query_id to reference in feedback |
submit_feedback |
rate served decisions by [index] and report a convention Metatron should have known — captured for refine-feedback; never auto-applied |
submit_candidate_decision |
record a convention the agent learned as a new candidate (never auto-promoted) |
A get_decisions_for_context call returns context like this:
metatron:query b1f2… · rev 1101886 (reference the query id in submit_feedback) [1] [medium] Record payment/sale events into the shared payments ledger when handling subscription billing. scope: src/routes/api/subscription why: A fix commit explicitly records sales into the payments ledger, establishing this as the expected billing-recording pattern.
Privacy
Metatron is self-hosted and built for sensitive, on-prem codebases:
- Extraction sends only structural signals — imports, decorators, base classes, commit subjects — to the model. Never raw source.
- Agent feedback and usage are stored only in your local SQLite database.
serve,ui, andcandidatesare fully local and need no API key.- No decision self-promotes — a human curates everything that becomes canonical.