AGENT MEMORY · GIT + MARKDOWN · LOCAL EMBEDDINGS

The agent doesn't start from zero every session.

Coding agents (Claude Code, Codex, and friends) are stateless across sessions: every conversation re-derives who you are, what you're working on, and what was already decided. That produces amnesia, context cost, and drift. The naive fix — one giant MEMORY.md — fixes the amnesia but makes the other two worse. This separates what the agent loads every turn from what it queries on demand, and makes the two layers provably consistent.

This page describes a system running daily on my own hardware. The repository is a sanitized architectural write-up — the design and the invariant, with invented example data — not the live store.

2 layers
portable lean (every session) + canonical deep (on demand)
deep ⊇ lean
the invariant: everything in the summary exists in the canon
0 cloud
local embeddings with Ollama — the corpus never leaves the machine
git only
diffable markdown, no database; if it didn't reach origin/main, it wasn't saved
The design in one sentence

A lightweight summary, a deep canon, tied together by an invariant.

Two layers — a portable lean layer loaded into context every session, and a canonical deep layer queried on demand — tied together by the deep ⊇ lean invariant, kept in sync by git hooks and a nightly job, and recoverable through a local semantic search layer for when manual routing fails.

LEAN — portable, fast to load

The summary that fits in every prompt

MEMORY.md as an executive index + routing table, domains/*.md with per-domain summaries, and .semantic/ with the local vector index. Optimized for low context-window cost and fast routing. It's derived from the canon; lives on the laptop + GitHub.

DEEP — canonical source of truth

The full history, with the why

Full history, rationale, and nuance. Optimized for completeness and auditability. Written first: every decision lands here before anywhere else. Lives on the home server + GitHub + _lean-mirror/ inside the deep store itself. Read on demand.

The invariant that makes it safe: deep ⊇ lean. Everything in the lightweight summary also exists in the canon. A nightly job re-mirrors the lean repo into deep/_lean-mirror/, so the canon can never silently fall behind its own summary.
The source-of-truth rule

If it didn't reach origin/main, it isn't saved.

Chat output is ephemeral. A decision that lives only in a conversation is lost when the window closes. That's why the mandatory last step of every useful session is writing the decision/correction/TODO to the canonical domain file, committing, and pushing. Conflicts resolve by the newest dated correction wins — every entry carries a date (YYYY-MM-DD, always absolute, never "yesterday").

Retrieval

Semantic search for when manual routing isn't enough.

Manual routing (a table of "if the topic is X, open file Y") is fast but brittle: it fails on queries that don't map cleanly to a known domain. That's why the lean repo carries a local semantic index.

01

Local embeddings

Ollama running nomic-embed-textlocal, no data leaves the machine. The corpus is personal by definition; sending it to a hosted embeddings API would leak exactly what this system protects. Local-first isn't a preference, it's the threat model.

02

Embedded vector store

LanceDB — embedded, no server to stand up. A single search queries the lean index and the deep one and merges by score, so you get the best hit no matter which layer it lives in.

03

Automatic re-indexing

Via a post-commit hook; manual re-index available for full rebuilds. Commit a markdown file and the index updates itself.

04

Agent routing rule

For a specific question where the routing table isn't obvious, run semantic search before answering from memory. For broad "where are things" questions, fall back to the executive index.

Synchronization

Consistency maintains itself.

The whole system falls apart if keeping the layers in sync is manual work. It isn't:

sync flow
# deep auto-push (post-commit hook)
commit to deep ──▶ push to GitHub # you can't forget to back up

# lean → deep mirror (nightly cron on the server)
git fetch + reset --hard origin/main   # read-only clone of lean
rsync --delete  ──▶ deep/_lean-mirror/ # enforces deep ⊇ lean
commit + push of deep

# escape hatch: same script, on-demand
force-sync # when you don't want to wait for the cron

The mirror enforces the deep ⊇ lean invariant instead of trusting a human to maintain it. And the deep store is published as a Docsify wiki served 24/7 from a Docker/nginx container (--restart unless-stopped, vendored assets to run offline): commit a markdown file and the readable wiki updates with no build step.

post-commit auto-pushnightly cronrsync --deleteDocsify wikiDocker / nginxoffline-first
Design decisions

Every choice, with the trade-off it accepted.

DecisionWhyTrade-off accepted
Two layers instead of one fileContext cost and completeness are in tension; separating them lets each side be optimized independently.More moving parts; needs the deep ⊇ lean invariant to stay honest.
Canonical deep, derived leanA single source of truth avoids the "which copy is the good one?" problem.The lean layer can lag intra-day until the next mirror; acceptable for a summary.
Markdown + git, not a databaseReadable, diffable, grep-able, zero infra to read; survives tooling changes.No rich queries unless you bolt on the semantic layer.
Local embeddings (Ollama)The corpus is private by definition.Requires a machine running Ollama; slower than a hosted API.
The newest dated correction winsDeterministic conflict resolution an agent can apply mechanically.Demands discipline: every entry must be dated.
The write-back is the last step, mandatoryKnowledge that stays in the chat is lost.Adds a step to every session; enforced by protocol, not tooling.
Docsify over a site generatorReads markdown live, no build; offline via vendored assets.Less polished than a full SSG.
Stack

Everything diffable, everything local.

GitMarkdownOllama nomic-embed-textLanceDBPythonPowerShellDockernginxDocsifycronrsyncSSHClaude Code & Codex

Running in production as the personal memory backbone of a multi-agent workflow since 2026. The repo is a sanitized architecture write-up: everything under examples/ uses made-up data for a fictional person. The real store is private.