I Built an Offline Agent That Tends Claude Code’s Memory So You Do Not Have To
Claude Code's auto-memory is brilliant. It is also incomplete, inconsistent, and trapped on one machine. Here is how I fixed that without replacing a single native line.
Claude Code's auto-memory is brilliant. It is also incomplete, inconsistent, and trapped on one machine. Here is how I fixed that without replacing a single native line.
A few weeks ago I noticed something annoying. I had been pair-coding with Claude Code on a big project for days. The context was rich - architectural decisions, API quirks, naming conventions we had settled on, bugs we had already debugged and fixed. Then I switched to my other laptop and it was like starting from scratch. Claude had no idea what we had built.
The problem was not Claude Code's fault. Anthropic ships a native auto-memory feature that writes memory notes as you work and reloads them next session. It works. But it has three blind spots:
- It only writes when Claude decides to, which means durable facts often get left in the transcript graveyard.
- It never reconciles old notes against new ones, so contradictions pile up until the memory becomes noise.
- It never leaves the machine it was born on. Your memory is siloed per device.
I built Memory Gardener to close those three gaps without replacing anything native.
What it actually does
Memory Gardener is an offline, scheduled agent that runs after your Claude Code sessions end. It follows a simple four-step pipeline:
Scan - It finds transcripts modified since the last run using a per-session mtime watermark. It skips sessions still in progress and ignores its own activity.
Distill - Pure-Python, deterministic noise stripping drops tool output, thinking blocks, and injected context. The result is a compact digest about 90 percent smaller than the raw transcript.
Extract and reconcile - One cheap claude -p call per project pulls durable facts: preferences, decisions, conventions, gotchas. New facts are reconciled against existing memory. Duplicates get skipped. Superseded entries get marked with a date stamp. Nothing is ever hard-deleted.
Commit and sync - Every run is one git commit in a memory repo. Because memory keys use home-relative logical names, they resolve identically on every machine and OS. A Mac and a Linux box share the same memory without path collisions. Raw transcripts never leave the machine; only distilled memory syncs.
The native loader still does all the reading and recall. The Gardener only writes.
Why zero dependencies matters
I wanted this to be something you drop onto any machine and it just works. No virtual environments to manage, no pip install nightmares, no version drift. The entire runtime is pure Python standard library. The only things you need are Python 3.9+, git, and Claude Code itself.
Tests use pytest, but that is the only development dependency.
The design philosophy
There were a few principles I refused to compromise on:
Native is the backbone. No parallel memory store, format, or loader. The native loader stays the only thing that reads memory into a session.
Deterministic where possible, LLM where necessary. Mechanical noise-stripping is Python; only the semantic extraction touches a model.
Git is the safety harness. Letting an LLM edit your memory autonomously is only safe because every run is a reviewable, revertible commit.
Eventually consistent, never blocking. A scheduled, unattended writer must never stall on a merge conflict, so it can't. The *.md merge=union strategy plus a regenerated index means two machines writing at once converge automatically.
Try it
git clone https://github.com/balakumardev/claude-memory-gardener
cd claude-memory-gardener
./install.sh
The install script resolves a stable system Python, migrates any existing native memory into the git-backed store (your originals get renamed, never deleted), and installs a scheduler. On macOS it uses launchd; on Linux, systemd.
Then just let the scheduler run it a few times a day. Watch the first run's git -C ~/.claude/memory diff to see what it distills before trusting it unattended.
The modules
| Module | Responsibility | | scanner, watermark | Find new transcripts; crash-safe per-session progress | | distiller | Deterministic transcript to digest noise strip | | agent, prompts | The single claude -p extraction and reconciliation step | | memindex | Regenerate the MEMORY.md index | | gitmemory | Bootstrap, union-merge, scale-guard, push-retry | | resolver | Stable logical-name keys plus autoMemoryDirectory pointers | | runner | Orchestrate the pipeline; fail-open per project; stale-lock recovery | | migrate | One-time lossless relocation of existing memory |
Run the tests yourself:
python3 -m pytest
45 tests, standard library plus pytest only.
The code
The repo is at github.com/balakumardev/claude-memory-gardener. MIT licensed. Pull requests welcome.
If you use Claude Code across multiple machines, this might save you from repeating yourself as often as I was.