Skip to main content
Glama
README.md
# git-receipts

**Answers with receipts.** git-receipts is an MCP server that records *why code exists* at the moment it is written — and serves that context back later with full provenance, instead of letting it die in a chat scrollback.

The engine inside is called **Rosetta**: the MCP server registers as `rosetta` and all of its tools are `rosetta_*` — you'll see both names throughout.

When an AI agent (or you) makes a decision and writes code for it, Rosetta captures the decision text and the **declared** set of code sites implementing it, binds that capture to the commit that introduces it, and keeps watching: if the anchored code later changes, the fact is honestly demoted to *stale* rather than silently served as current. Ask `rosetta_why` about a file or symbol six weeks later and you get the decision chain — each line stamped with where it came from (`observed | inferred | asserted`), when (`as_of`), its current lifecycle state (`bound_current`, `bound_stale`, `superseded`, …), and confidence. When nothing was captured, the answer is *"Rosetta doesn't know"* — never a guess.

Two invariants shape everything:

- **Never block.** No Rosetta mechanism can prevent, delay, or fail a commit or any other git operation. Hooks are verify/log-only and always exit 0. If Rosetta breaks, your workflow doesn't.
- **Capture at authorship, never confident re-inference.** The author declares the decision→code links while the "why" still exists. Rosetta never retrofits links by guessing; broken anchors get flagged for review, not silently repaired.

## Maturity — read this first

This is a **pilot-stage tool**, built and dogfooded by a single developer working with AI coding agents (Rosetta's own event store tracks Rosetta's development). The mechanism is real and tested in daily use; the edges are not smoothed. Schemas are versioned but may change, the review-queue UX is young, cross-repo linking is not built, and the test suite hasn't been published yet. It is open-sourced to find out whether it is useful to anyone else — see [Feedback wanted](#feedback-wanted).

## How it works, briefly

1. **Capture.** During a session the agent calls `rosetta_capture_decision` when a decision lands in conversation, and `rosetta_capture` when code implementing it exists — declaring the *full* set of sites (file + symbol + role), never a single "primary" location. Each capture is one immutable, self-hashed JSON event under `.rosetta/events/`.
2. **Bind.** The event file is staged and committed *with* the code (`rosetta_prepare_commit` hands the agent the paths and a `Rosetta-Id:` trailer). The commit binding is **derived from git topology** — the commit that introduces the event file — so it survives squashes, rebases, and amends without any hook needing to fire.
3. **Watch.** Verify/log-only git hooks keep a derived index fresh. Anchor drift (the code under a link changed) demotes facts to `bound_stale`; a small severity-tiered review queue collects what needs a human verdict, capped at 5 items per review, with honest states like *snooze* and *archive-as-unknown*.
4. **Serve.** `rosetta_context` serves relevant decision chains, rejected approaches, and open questions into the agent's context at task start. `rosetta_why`, `rosetta_what_implements`, and `rosetta_explain_change_risk` answer the day-to-day questions — every response carries a `health` field and per-line provenance.

## Prerequisites

- Python **3.10+**
- **git** (Rosetta binds facts to commits; a git repo is assumed)
- An MCP client: Claude Desktop, Claude Code, Codex, or anything speaking MCP over stdio
- *(Optional)* an `ANTHROPIC_API_KEY` — **only** if you enable the intake gate, which is **off by default**. Without it Rosetta makes zero network calls.

## Install

Not yet on PyPI — install from a clone:

```sh
git clone https://github.com/Tasktivity/git-receipts && cd git-receipts
python3 -m venv .venv && .venv/bin/pip install .
.venv/bin/git-receipts --help   # sanity check
```

Or with [pipx](https://pipx.pypa.io/): `pipx install /path/to/git-receipts` (puts `git-receipts` on your PATH).

## Hook it up to your MCP client

The server runs over stdio: `git-receipts serve` (equivalently `python -m rosetta_mcp.server`). Setting `ROSETTA_PROJECT` to your repo's absolute path is the recommended default binding for single-project setups; agents can also pass `project` explicitly per call, which always wins.

**Claude Desktop** — add to `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/`; use the *absolute* path from `which git-receipts`, since Desktop doesn't inherit your shell PATH):

```json
{
  "mcpServers": {
    "rosetta": {
      "command": "/absolute/path/to/git-receipts",
      "args": ["serve"],
      "env": { "ROSETTA_PROJECT": "/absolute/path/to/your/repo" }
    }
  }
}
```

**Claude Code**:

```sh
claude mcp add rosetta --env ROSETTA_PROJECT=/absolute/path/to/your/repo -- git-receipts serve
```

**Codex** — add to `~/.codex/config.toml`:

```toml
[mcp_servers.rosetta]
command = "git-receipts"
args = ["serve"]
env = { "ROSETTA_PROJECT" = "/absolute/path/to/your/repo" }
```

## 60-second quickstart

```sh
# 1. Initialize Rosetta in your repo (creates .rosetta/, installs verify-only hooks,
#    ends with a doctor run). You can also just ask your agent to run rosetta_setup.
git-receipts --project /path/to/your/repo init --alias myproject
git-receipts --project /path/to/your/repo install-hooks

# 2. Add the MCP config above, restart your client, start a session in that repo.
#    The agent's first Rosetta call (rosetta_context) binds the project and returns
#    the session contract — from then on decisions get captured as you work.

# 3. Work normally. Captures acknowledge themselves with one receipt line, e.g.
#    (logged: switch retry queue to exponential backoff)
#    and commits carry Rosetta-Id trailers binding facts to code.

# 4. Later — ask why something exists, from any session:
#    "why does src/retry.ts exist?"  → the agent calls rosetta_why and answers
#    with the decision chain, provenance, and lifecycle state. Or check health:
git-receipts --project /path/to/your/repo status
```

## The contract: three duties

Rosetta teaches the agent itself, per session. The first `rosetta_context` call returns a short mode-specific contract *as the tool result* — the one channel that provably reaches a model — together with an ack nonce, so adoption is tracked instead of hoped for. (Instruction files like `AGENTS.md` can be generated as redundancy: `git-receipts doctor --emit-agents-md --write`.) The coding-mode contract is three duties plus a relay rule:

1. **A decision made in conversation** → `rosetta_capture_decision`, immediately — decisions exist before code does.
2. **Code implementing a decision exists** → `rosetta_capture` with the **full** site set (or an honest abstain).
3. **Before every commit** → `rosetta_prepare_commit`; stage the event paths it returns and append its trailer block to the commit message.

Plus: relay any Rosetta question to the user verbatim and return the answer via `rosetta_capture_answer`. Mutating tools error until the session has bootstrapped; read tools work but carry a warning. And by design the agent stays quiet about all of this — a capture produces one `(logged: …)` receipt line, not ceremony.

The full tool surface (26 tools: queries, drift, review queue, metrics, audits) is described in [docs/TOOLS.md](docs/TOOLS.md); the design itself in [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md); every knob in [docs/CONFIGURATION.md](docs/CONFIGURATION.md); where external systems (issue trackers, CI) would plug in, as future state, in [docs/INTEGRATIONS.md](docs/INTEGRATIONS.md).

## Privacy: what `.rosetta/` stores, and where it goes

Be deliberate about this before pushing to a shared or public remote.

- **`.rosetta/events/` is committed** — that's the point: facts travel with the repo. Events contain decision text, triggers, rationale, and code-site anchors. Whoever can read your repo can read them.
- **`.rosetta/local/` never leaves your machine** — Rosetta writes a `.gitignore` for it. It holds only derived views (the index, rebuildable at any time), telemetry, the session-adoption log, and private material below.
- **Sidecar mode** (`init --privacy sidecar`, offered at setup when a remote exists): commits only skeleton events — structure, anchors, hashes — while all prose stays in `.rosetta/local/private/`. For repos with public remotes.
- **`visibility=private` captures** live whole in `.rosetta/local/private_events/`, never committed (the default for strategy decisions captured from chat-style clients).
- **`.rosettaignore`** (gitignore syntax, scaffolded at setup) excludes matching paths from symbol inventory, context serving, exports, and any outbound payload.
- **Secret scanning** runs on capture prose at write time; flagged captures are excluded from any outbound payload.
- **Network: zero by default.** The one networked feature is the optional intake gate (an LLM that cross-references new captures against your outcome corpus, `gate.enabled=false` out of the box). When enabled it calls the Anthropic API with a deny-list redaction pass applied first, and reads `ANTHROPIC_API_KEY` from the environment only — never from any file.

## Feedback wanted

This project is public precisely to collect outside signal. Most useful right now:

- **Install/setup friction** — where did the quickstart lie to you?
- **Adoption by your client** — does your agent actually bootstrap, capture, and attach trailers? (`git-receipts status` shows adoption counts.)
- **Answer quality** — was a `rosetta_why` / `rosetta_context` answer useful, wrong, or noise? The `rosetta_context_feedback` tool records verdicts.
- **Privacy posture** — anything about the committed-store model that would block you from using it.
- **Integration pull** — [docs/INTEGRATIONS.md](docs/INTEGRATIONS.md) sketches where trackers like JIRA would plug in as outcome sources; tell us which source of truth you'd actually connect.

Open an issue. Small, sharp bug reports and "this concept fails for me because X" write-ups are worth more than feature PRs at this stage — see [CONTRIBUTING.md](CONTRIBUTING.md).

## License

MIT — see [LICENSE](LICENSE).