repo-history
Exposes a repo's historical engineering memory (decisions, landmines, guardrails) via MCP tools for AI coding agents.
README
repo-history
Git archaeology for AI coding agents. Most tools index a repo as it exists
today. repo-history walks the repo's entire commit history, works out why
it became what it is, and writes durable engineering memory your coding agent
can read.
Senior engineers carry context that isn't in the current code: "we tried X and reverted it," "this guard exists because of bug Y," "that abstraction was removed for a reason." That knowledge is buried in commits.
repo-historydigs it out and writes it down.
Run it once. Commit the output. Every future agent session — and every new teammate — inherits the repo's memory.
What it produces
A .repo-memory/ directory. It leads with the prescriptive guardrails an agent
should load — the part a controlled study found actually helps — and keeps the
narrative history as a human-onboarding bonus.
| File | What's in it |
|---|---|
GUARDRAILS.md |
The flagship. Terse do/don't rules + decision-constraints, each evidence-linked and tagged [observed] (stated in a commit/PR) or [inferred] (deduced from a diff). This is what an agent loads. |
LANDMINES.md |
Do-not-repeat lessons: reverts, removed abstractions, failed approaches — with the receipts. |
DECISIONS.md |
Past decisions, framed as constraints, grounded-first. |
onboarding/TIMELINE.md |
How the codebase evolved, in chapters — for humans getting oriented. |
onboarding/ARCHITECTURE.md |
The system today, annotated with how it got here. |
onboarding/HOTSPOTS.md |
Churn, change-coupling, bus-factor. Purely mechanical — zero LLM tokens. |
*.json |
Machine-readable mirrors (carrying the trust grade), shaped so the MCP server can serve them. |
Why lead with guardrails? A controlled ablation of repository context files found that narrative overviews don't measurably improve a coding agent's accuracy, while instructions and constraints — exactly what landmines and decision-rules are — do. So the output puts the agent-useful part first and treats the story as onboarding for people.
Real output
repo-history run on its own repo produced 15 decisions and 5 landmines from
7 commits. Every one was reconstructed from commit diffs alone — none of it is
written down in the source:
Do not parse git
--numstatpaths as plain strings; rename output has three distinct shapes. git emits renames asold.py => new.py,src/{old => new}/file.py, andsrc/{ => sub}/file.py(empty left side) … naive splitting will silently produce bogus paths.
Never trust a recorded head sha blindly — check it still exists before computing a
sincerange. After a rebase or force-push the head stored inindex.jsoncan vanish from the repo … rather than silently producing a wrong (and wrongly-scoped) commit range.
The full, unedited run is in examples/self-analysis/.
Install
Requires uv. The AI analysis step also needs Claude Code; the plain CLI (history stats, hotspots) works on its own.
# straight from GitHub — works today
uv tool install git+https://github.com/hr23232323/repo-history
# or, once published to PyPI
uv tool install repo-history
Then add the Claude Code skill:
repo-history install-skill # adds /repo-history to the current project
repo-history install-skill --global # ...or to every project (~/.claude)
Use
# 1. plan — mechanical pass + episode manifest (deterministic, no LLM, no cost)
repo-history plan --branch main
# 2. analyze — run /repo-history in Claude Code; it fans out subagents over the episodes
# 3. build — render .repo-memory/ from the analyses
repo-history build
# later: only pay for what's new
repo-history status
repo-history plan --since <sha>
Then commit .repo-memory/.
Serve it to agents live (MCP)
Instead of (or as well as) committing the files, expose the memory over MCP so an agent can query it on demand — "why is this file like this?", "anything I should know before I change X?":
uv tool install "repo-history[mcp]"
repo-history mcp # stdio server over ./.repo-memory
Tools: why_is_this(path), list_decisions(topic), list_landmines(),
check_before_you_do(proposal), get_timeline(), get_hotspots(). The server
is a pure reader — no LLM, no git, no network.
How it works
Two deterministic halves with the LLM sandwiched between them. The halves only ever talk through files on disk.
git history
│
▼
┌──────────────────── deterministic engine (this package) ─────────────────────┐
│ plan hotspots · change-coupling · revert detection · drop trivial commits │
│ → segment by release → cluster into "episodes" → condense diffs │
│ → enrich with PR/issue "why" (GitHub) → scrub secrets │
└──────────────────────────────────────────────────────────────────────────────┘
│ .repo-memory/.work/ (one Markdown bundle per episode)
▼
┌───────────────── LLM orchestrator (/repo-history skill) ─────────────────────┐
│ map one subagent per episode → {summary, decisions, landmines} │
│ reduce roll them up into a coherent narrative │
└──────────────────────────────────────────────────────────────────────────────┘
│ validated JSON
▼
┌──────────────────── deterministic engine (this package) ─────────────────────┐
│ build render .repo-memory/*.md + *.json │
└──────────────────────────────────────────────────────────────────────────────┘
The LLM step runs inside Claude Code, so it uses your existing subscription. There's no API key to configure and no per-token bill from this tool.
The "why" lives in pull requests
Commits say what changed; the PR that merged them, the issue it closed, and the
review discussion usually say why. When the repo is on GitHub and gh is
authenticated, repo-history automatically pulls that context into each episode
(PR body, linked-issue problem statement, human review notes — bots filtered, and
all secret-scrubbed like everything else). It's what lets a claim be graded
[observed] rather than [inferred]. No GitHub, no gh, or offline? It falls
back to commits-only. Turn it off with --no-github.
Why not analyze every commit?
A large repo has tens of thousands of commits; LLM-analyzing each one is slow, noisy, and expensive. The engine spends tokens only where there's signal:
- Drop the noise — lockfiles, minified bundles, generated files.
- Segment by release/tag — free, meaningful history windows.
- Cluster by change-coupling — commits touching the same files become one episode.
- Always keep landmarks — reverts get their own episode; they're the richest signal.
- Condense diffs — squashed and truncated, never whole file blobs.
- Run incrementally — after the first pass, only new commits cost anything.
Swappable analysis methods
How history is read is a plugin. The pipeline shape is fixed, but the method — what counts as signal, how commits become episodes — is swappable behind a registry.
repo-history methods # list registered methods
repo-history plan --method mechanical # the built-in, LLM-free method
repo-history plan --method mechanical --json # inspect a method's output, write nothing
Adding one is a single registered file and nothing downstream changes.
See docs/adding-a-method.md.
Safety
- Read-only. The engine only runs
git log/git show. It never writes to your repo, and never uses a shell string (no injection via refs or paths). - Secrets are scrubbed before any repo content reaches an LLM: private keys,
provider tokens, and
key = "value"pairs are redacted at the boundary. It errs toward redacting. It's a safety net, not a guarantee — don't rely on it to make a repo full of live credentials safe. - Local-first. Output is plain files in your repo. Read them, diff them, review them before you commit them.
Development
uv pip install -e ".[dev]"
uv run pytest
Tests run against a synthetic fixture repo built in a temp dir — with a real rename, a revert, and an annotated tag — so the history shapes that matter are actually exercised.
Status
Alpha, but working end-to-end: the deterministic engine, the /repo-history
skill, incremental re-runs, and the MCP server are all in place (see the
self-analysis example). The mechanical analysis method is the only one shipped
so far; more (and better episode grouping) are where the work goes next.
License
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
E2B
Using MCP to run code via e2b.