pleach
Provides Claude with the session graph, enabling it to log, show, grep, export, summarize, branch, name, and merge Claude Code sessions.
README
pleach
Branch tracking, visualization, and merging for Claude Code sessions.
Claude Code can fork a conversation (/branch, --fork-session) but keeps no
record of what forked from what, shows no tree anywhere, and has no way to bring
two divergent branches back together. pleach adds those three things.
Unofficial third-party tool. Not affiliated with or endorsed by Anthropic. It reads session transcripts already on your disk and shells out to your own
claudebinary. It never touches credentials and never bundles Claude Code source.
* 9703da58 (leaky-bucket) 2026-08-01
| * a7aa4a1d (sliding-window) 2026-08-01
|/
| * 36a05f40 (token-bucket) 2026-08-01
|/
* 97c6581b 2026-08-01
If you can read git log --graph, you already know how to read this.
Requirements
Python 3.9+ and an installed claude. No dependencies, no build step, no
pip install — it runs from a checkout. (Claude Code 2.x ships as a native
binary and brings no Node runtime, which is why this is Python.)
Learn it in five minutes
Three commands, modeled on git:
pleach log # the session graph for this project — works instantly,
# even on history from before you installed pleach
pleach branch 9703da58 # fork a session; prints the `claude --resume` command
pleach merge a7aa a1d3 # reconcile two branches via a background agent
That's the whole core. Ids take any unambiguous prefix, like git SHAs. Typing
bare pleach prints this cheatsheet.
Two optional extras that pay for themselves:
pleach name 9703da58 leaky-bucket # labels show in the graph, like branch names
pleach init --write # install hooks: new forks tracked live
# (backs up settings.json; --uninstall reverses)
There is no index to build and no scan step — every command refreshes lineage for the current project automatically, the way git just reads your repo.
The interactive graph
pleach ui
Full-screen interactive graph in the spirit of VS Code's git-graph panel, keys
modeled on tig/lazygit: j/k move between nodes, enter toggles the detail
panel, n names, b branches, s opens a branch summary in a pager, m
marks a node and m on a second node merges the pair (dry-run or dispatch),
r prints the resume command, a toggles all projects, q quits.
The VS Code extension takes the same keys, so the two surfaces are one set of
muscle memory: j/k (or arrows) move, g/G jump to the ends, enter resumes,
b branches, n renames, s summarizes, o opens the transcript, m pins a
session as the other half of a merge, a toggles all projects, / focuses the
filter, and ? lists the lot.
Claude Code's TUI has no extension point for custom panes, so ui can't render
inside a session — run it in a terminal pane next to one, exactly how the VS
Code git graph sits next to the editor. Inside a session, /pleach (from the
plugin) is the same functionality with Claude as the interaction layer: it
shows the graph and resolves "branch the top one as X" or "merge those two"
into the right commands for you.
Commands
| Command | What it does |
|---|---|
ui |
Interactive full-screen graph — navigate, name, branch, merge. |
log (alias tree) |
Git-style session graph. --all for every project. |
branch <id> |
Fork a session (a file copy — no API call). |
merge <a> <b> |
Reconcile two branches via a background agent. --dry-run first. |
name <id> <label> |
Label a session; labels show in the graph. |
summary <id> |
What happened in a branch, distilled. Cached. |
grep <term> |
Full-text search across transcripts. --all for every project. |
export <id> |
Render a transcript as readable markdown. Local, free. |
show <id> |
Parent, branch point, children, entry count. |
merges |
Merges run here, and whether the agent has finished. |
status |
What's tracked, what's live, what's configured. |
list |
Flat table of tracked sessions. |
scan |
Full rescan of every project (per-project refresh is automatic). |
prune |
Drop stale index entries; --snapshots also deletes merge bases. |
doctor |
Environment checks; --test-synthesis verifies merge-base support. |
mcp |
Run the MCP server (stdio) — see below. |
Give Claude itself the graph (MCP)
pleach mcp is a zero-dependency MCP server
over stdio. Register it once:
claude mcp add --scope user pleach -- python3 /path/to/checkout/bin/pleach mcp
From then on, Claude — in any terminal session and inside the official VS
Code extension's panel — can query your session graph directly. Ask it "which
of my branches dealt with the flux bug?" and it can call pleach_grep, read
the graph with pleach_log, pull a branch digest with pleach_summary, or
hand you the exact claude --resume command via pleach_show.
Tools exposed: pleach_log, pleach_show, pleach_grep, pleach_export,
pleach_summary, pleach_branch, pleach_name, pleach_merge_plan,
pleach_merge, pleach_status. Reads are free and local (summaries cost a
cached haiku call). The only side-effectful tools are pleach_branch (copies
a transcript, same as pleach branch) and pleach_merge (dispatches a
background merge agent); pleach_merge_plan is the dry run and its tool
description tells the model to use it first.
Remove with claude mcp remove pleach.
How merging works
A merge is not a replay of tool calls. It is:
- Reconstruct the shared context. Find the last entry both branches share — their branch point — and rebuild the conversation as it stood there.
- Summarize each branch separately. A cheap model reads each full branch and reports what was tried, what worked, what failed, what was decided.
- Seed a new agent from the shared context and hand it both summaries to reconcile.
Step 3 runs as a background session (claude agents to watch it), so it doesn't
disturb the session you're in. The merge agent is read-only by default: it
is given no tools at all, since it is pure synthesis over two summaries already
in its prompt. Pass --allow-writes if you actually want it editing files.
Merge bases are reused when the branch point hasn't moved, so re-merging the
same pair doesn't accumulate transcripts. pleach prune --snapshots --yes
removes the ones pleach created.
Use --dry-run to see the merge base, its confidence, and the exact prompt
without dispatching anything.
Because the agent runs in the background, pleach merges says which merges
have finished, and pleach export <merge-session> reads the reconciliation.
The extension does both for you: the sidebar tracks a dispatched merge from
"running" to "ready" and offers a Read the merge button.
What's verified
Built against measured behaviour, not assumptions. The experiments and results are in PLAN.md §8, and the whole pipeline has been run end to end against real sessions:
- Fork copying (§8.2). Forks preserve entry uuids exactly while rewriting
the
sessionIdfield — the property that makes retroactive inference work. - Inference (§8.9). 19 edges inferred from real history, each re-derived independently from the raw transcripts: 19/19 correct parent and exact branch point.
- Live fork detection (§8.10). Confirmed against a real fork with hooks installed.
- Merge-base synthesis (§8.6). Confirmed: Claude Code resumes a transcript
pleach wrote. Merge bases are exact, and
pleach branchcosts no API calls. - The merge pipeline. Dispatched, ran, and produced a real reconciliation seeded from the correct shared context.
pleach doctor --test-synthesis re-checks the synthesis property on your
machine. If a future release breaks it, merges fall back to forking the live
parent and say so with a drifted warning rather than silently using a wrong
base.
Still untested: the interactive /branch and /fork TUI commands. All fork
testing used the --fork-session CLI flag. scan catches those either way.
What it refuses to do
The lineage index is the only place fork edges, names, and merge history live — none of it can be rebuilt by rescanning transcripts. So pleach never replaces a file it could not read:
- An unreadable
~/.pleach/lineage.jsonis recovered fromlineage.json.bak(written before every change) or, failing that, left exactly as it is while the command exits 3. It is never overwritten with an empty index. - An unreadable
~/.claude/settings.jsonstopspleach initentirely, with the same exit code.--writeand--uninstallboth back it up first, and--uninstallleaves the file alone if none of pleach's hooks are in it. (A UTF-8 BOM counts as readable — it used to count as "empty".)
Transcript text is untrusted input: it is whatever a session contained,
including anything an agent quoted from a web page. Text sent to a model is
fenced with a per-call nonce and the rules are restated after the content, so a
transcript that contains instructions gets reported rather than obeyed —
verified end to end against a deliberately poisoned transcript. Merge agents
still run with no tools unless you pass --allow-writes.
How branch detection works
Claude Code has no fork hook, and it signals forks differently across versions — pleach handles both.
On recent versions (measured on 2.1.219), SessionStart announces the fork
explicitly with source: "fork", but reports the child id and never names
the parent. The parent is recovered by prefix-matching the child's transcript
against its siblings, which is exact because a fork's transcript literally
begins with its parent's.
On older versions (2.1.207), SessionStart instead reports the parent with
source: "resume" — indistinguishable from a plain resume — and the child only
appears on UserPromptSubmit. There the signal is the mismatch between the two
events.
This is why init installs three hooks rather than one: on both paths a single
SessionStart hook detects nothing. Details in pleach/track.py.
One consequence worth knowing: the child's transcript is not on disk when
SessionStart fires, so parent resolution is retried on later events and falls
back to scan. A missed hook degrades to inference, never to a lost branch.
Edges found live are marked observed. Edges reconstructed by scan are marked
inferred — those pick the closest plausible ancestor, so in rare cases (a
branch taken immediately, before the parent did further work) they may attribute
to a grandparent rather than a parent. A shallower tree, not a wrong one.
Layout
bin/pleach entry point
pleach/track.py hook handler — the fork-detection state machine
pleach/infer.py retroactive lineage inference
pleach/transcript.py JSONL parsing, prefix comparison, branch points
pleach/mergebase.py shared-context reconstruction
pleach/merge.py the merge pipeline
pleach/graph.py tree building and rendering
test/smoke.py offline end-to-end tests
Run the tests with python3 test/smoke.py. They use a throwaway config dir and
never touch your real ~/.claude.
Storage
Everything pleach records lives in ~/.pleach/ (override with PLEACH_HOME).
The only thing it ever writes into ~/.claude/projects/ is a reconstructed
merge base, which is tagged and removable with pleach prune --snapshots --yes.
It never modifies an existing transcript.
License
MIT.
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.
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.
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.
E2B
Using MCP to run code via e2b.
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.