Redthread: Portable, Git-Backed Memory for AI Coding Agents
Every coding agent I use keeps its memory in a local folder — .claude/,
.cursor/, .agent/. That works until you switch machines, and then the
agent has amnesia. The context it built up about your project stays on the
laptop where it happened.
Redthread is a small tool I wrote to fix that. It stores agent memory in a git repo instead of a local folder, and exposes it over MCP, so every machine that clones the store sees the same memory. This post is a quick walkthrough: install it, wire it to your agent, and use it.
Install¶
Everything below needs redthread 0.6 or newer — that release reworked the agent-facing surface substantially, and a few of the tool signatures changed with it.
Create a store¶
A store is a git repo with a declared phase pipeline — an ordered list
of whatever names fit your project. build,test,present and
train,eval,present are equally valid:
Connect your agent¶
For Claude Code, one command:
uvx fetches Redthread from PyPI on first launch, so this works even
without the install step above. Already installed it? Drop uvx:
Verify with /mcp inside Claude Code — redthread should show up as
connected with 17 tools. A quick smoke test is asking the agent to call
context_bootstrap. Note that MCP servers are only read at session start,
so if you added it mid-session you'll need to restart Claude Code before
the tools appear.
Cursor uses an install deeplink rather than a CLI command, and VS Code has
code --add-mcp; the
per-client reference
covers Cursor, VS Code, Windsurf, Claude Desktop, Codex CLI, Gemini CLI,
and the Claude Agent SDK.
Make the agent actually use it¶
This is the part that's easy to miss, and the part I've spent the most time on. Registering the MCP server gives the agent the capability to use memory — nothing tells it to actually reach for those tools. It'll happily ignore them for an entire session.
There are two halves to fixing that.
One: give it a front door. A cold agent that wants to use memory still has to figure out which runs exist, which memory namespaces exist, and what's in them — several calls deep before it learns anything useful, and it usually gives up first. So there's a single tool that answers all of it at once:
That prints the same payload the agent gets from context_bootstrap: the
phase pipeline, recent runs and their status, published handoffs, and an
index of every memory entry with a one-line description each. It also
returns a _next field telling the agent what to do with what it just got
— read these entries, or start a run, or write a session summary before
finishing. One call, and the agent knows where it is.
Two: give it the habit. A note in AGENTS.md (or CLAUDE.md) is the
first thing most agents read. Redthread will write it for you — ask the
agent to call agents_md_bootstrap and it appends a short usage policy to
your project's existing file. Idempotent, so it's safe to call every
session.
One caveat worth knowing if you use subagents: they don't inherit the main
agent's instructions, and they don't read AGENTS.md. A subagent doing
real work will silently skip memory entirely. That's why the guidance lives
in the tool descriptions and responses too, not just in a config file — it's
the only channel that reaches every agent in every client. If you delegate
something worth remembering, tell the subagent to call context_bootstrap
as well.
Make it portable¶
So far this is a local git repo. Give it a remote and sync:
git -C ./my-store remote add origin git@github.com:you/my-store.git
redthread sync --store ./my-store
sync is a one-shot commit + pull --rebase + push. Any other machine
that clones the store now sees the same memory — which is the whole point.
There's also an auto-commit daemon (redthread daemon run) if you'd rather
not think about it.
Don't want to provision a second repo? Redthread can put the store on an orphan branch of a repo you already have, as a git worktree, without ever touching that repo's checked-out branch:
This writes a small .redthread.yaml marker into the host repo. Commit it,
and the next machine just clones your code repo and registers the same MCP
command — no flags to remember, no manual clone of the store.
The CLI, in 60 seconds¶
The same store also tracks multi-phase runs, which is useful outside the agent case — pipelines where one phase's conclusions feed the next. One end-to-end pass:
# a run is one attempt through your declared phases
run_id=$(redthread run start --store ./my-store)
# append immutable context entries as a phase works
redthread log "$run_id" build note '{"msg": "kicked off build"}' --store ./my-store
# publish the build phase's curated handoff for the next phase
echo '{"headline": "build ok", "key_results": {"warnings": 0}}' > handoff.json
redthread handoff publish "$run_id" build handoff.json --store ./my-store
# the test phase reads only the handoff — never build's raw log
redthread handoff get "$run_id" build --store ./my-store
# full raw history, one JSON entry per line
redthread read "$run_id" --store ./my-store
The handoff/raw-log split is deliberate. Entries are append-only and immutable, so the raw log grows without bound — but a downstream phase reads the short curated handoff, not the transcript. That's what keeps context windows from filling with a previous phase's noise.
One quality-of-life note: run_id is optional on every run-scoped tool on
the MCP side. Omit it and it resolves to the store's newest active run, with
the id it picked echoed back in the response — so an agent can't quietly
write to the wrong run. Pass it explicitly when several runs are in flight
across machines.
Memory that describes itself¶
Long-term memory is separate from runs, because most of what's worth remembering isn't tied to one attempt. Each entry carries a one-line description, stored as YAML frontmatter:
redthread memory write notes toolchain.md ./note.md \
--description "Why this project uses uv, not conda" \
--tags toolchain --store ./my-store
redthread memory list --store ./my-store
That description does more work than it looks like. Listing memory returns descriptions rather than bare filenames, so an agent can tell what's worth opening without reading every entry first — which is the difference between memory that gets used and memory that quietly rots. Entries written without one fall back to their first meaningful line, so old stores still list sensibly.
When you're after something specific, search covers keys, descriptions, tags, and bodies, and reports the line that matched:
The same reads are also exposed as MCP resources —
redthread://bootstrap, redthread://memory,
redthread://handoff/{run_id}/{phase}, and a few more — for clients that
can attach context directly instead of spending a tool call on it.
One warning¶
The store is a git repo, usually pushed to a shared remote. Never write secrets to it. Anything an agent puts in memory is committed to history and visible to everyone with access.
Links¶
- Repo: github.com/sina5/redthread
- Docs: sina5.github.io/redthread
- Quickstart · Full usage reference · Architecture
It's MIT-licensed and works on Windows, Linux, and macOS (Python 3.11+). Issues and PRs welcome.