agent-memory
Summary: This server gives an AI coding agent git-native, reviewable project memory — reading a budgeted context pack from the repo's .agent-memory/ store, proposing structured edits (applied or staged for human approval), and reporting memory health.
memory.fetch_context— Return a ranked, budgeted Markdown context pack from.agent-memory/before manually reading source files; empty query gives the bootstrap pack. Supports FTSquery,scope(paths/modules to prioritize),budget,includecategories, andexclude_archive. Returns per-file provenance, omitted candidates, branch, stale warnings, budget used/remaining, plus aread_nonce/pack_digestfor proof-of-grounding.memory.propose_update— Submit one or more structured section-level edits via anintent(update_current, update_shared, session_log, add_pitfall, record_decision, refresh_module, update_conventions, archive_stale) andoperations(append/replace/insert with heading, section IDs, if_exists/if_missing). Each op is schema-validated, secret-scanned, and provenance-checked; durable changes either apply immediately or stage for human review, withstatus= applied | staged | rejected, plus staging IDs, review commands, TTL, drift findings, and violation details.memory.status— Read-only health report: memory version, durable/archive/session/current file counts, index and current-state sizes, pending staged proposals (age, TTL, target files, drift), orphaned branch files, and secret-scan, git, and advisory-lock posture.Overall workflow — Recall context → propose knowledge updates → verify store health, so durable knowledge is human-reviewed, versioned in git, and never written silently.
agent-memory
Local, git-native project memory for AI coding agents. One MCP call in, structured memory updates out — current task state, decisions, conventions, pitfalls, per-module facts. Branch-aware. Secret-safe. Byte-preserving. No cloud, no vector DB — Markdown is the source of truth and git is the sync. Three MCP tools + a full CLI.
Why it's different: memory is plain Markdown committed to your repo, so
you can read and git diff it; durable changes stage for human review
(review --diff → apply) instead of landing silently; and secrets/PII are
scanned out before anything is written. See ROADMAP.md for
where this is headed (system-level / multi-repo memory).
Demo
An agent records a durable decision; it stages for review; you see the
exact diff, apply it, and a later fetch surfaces it — local,
git-native, reviewable, secret-safe. The clip is reproducible:
docs/demo/demo.sh is the runnable flow and
docs/demo/demo.tape renders the gif with
vhs — see docs/demo/.
Related MCP server: Codex Memory
How it compares
Capability | AGENTS.md / CLAUDE.md | Vendor memory (e.g. Claude) | Vector / DB memory (mem0, Zep) | agent-memory |
Plain-text, git-versioned source of truth | ✓ flat file | ✗ vendor-managed | ✗ DB / cloud | ✓ Markdown in your repo |
Structured, section-level updates | ✗ | ✗ | ~ | ✓ |
Human review gate (see the diff first) | ✗ free edit | ✗ | ✗ | ✓ stage → |
Vendor-neutral (MCP — any agent) | ~ broad convention | ✗ one vendor | ~ varies | ✓ Claude · Cursor · Codex · Gemini |
Secret / PII scan on write | ✗ | ✗ | ~ varies | ✓ |
Team merge for concurrent edits | ✗ text conflicts | ✗ | ✗ | ✓ section merge driver |
Runs fully local (no cloud) | ✓ | ✗ | ~ varies | ✓ |
Verifiable Task Protocol (VTP-1) & Machine Receipts | ✗ | ✗ | ✗ | ✓ 5-phase cryptographic lifecycle + Clause B disjoint seat |
These are general characterizations and the tools evolve fast — see something
inaccurate? Open an issue and
I'll fix the row. agent-memory is complementary to instruction files like
AGENTS.md/CLAUDE.md (it even installs one): those say how to behave;
agent-memory is the durable, searchable, reviewed knowledge behind it.
Status
Release 0.6.1 — the Swarm Audit Hardening & Metamorphic Rebase release: bridges durable memory with verifiable autonomous execution and strict fail-closed security invariants:
Astra Pro Audit Hardening (AM-001..AM-008) — Category-enforced approval routing (
DecideRoutingWithCategory), whole-file pre-state CAS (proposal.PreHashes), polarity/negation qualifier preservation in Jaccard dedup (criticalQualifiers), idempotent pure read-onlyfetch_context, and canonical 3-way merge deletion semantics.Metamorphic Rebase & Drift Detection (
internal/memory/rebase.go) — Detects whole-file pre-hash drift during rebase, preventing silent clobber when adjacent sections are concurrently edited, verified by metamorphic composition tests.Control-Plane Manifest Isolation — Enforces fail-closed protection of
.agent-memory/meta/manifest.yamlagainst direct modification, symlink bypass, or path traversal attacks.RFC 8785 (JCS) Determinism (
internal/vtp) — Strict JSON Canonicalization Scheme compliance passing all 26 official RFC 8785 Appendix B test vectors, ECMAScript float formatting (1e+21), lone surrogate rejection, and recursive UTF-8 validation.Fail-Closed Cross-Process SQLite NonceStore (
internal/memory/nonce.go) — Persistent repo-scoped store using thewithDBpattern to eliminate Windows file descriptor locks, providing zero-drift atomic validation and auto-sweeping expired nonces.Two-Phase Staging & Compound Rollback (
internal/memory/staging.go) — Strict path traversal sanitization (ValidateStagingID,agentfs.ValidateMemoryPath), symlink containment, and atomic multi-file rollback reportingRollbackIncompletecompound errors on partial failure.VTP-1 Strict Assertion Identification & Dual-Oracle Settlement (
internal/vtp) — Mandatory identifiableAssertionResultsmatching declared assertion IDs, verifier key binding validation, and Workpool/0 Clause B disjoint seat enforcement.
It builds on 0.6.0 (anti-ornamental SAR-008 grounding nonces, SAR-007 byte preservation), 0.5.4 (VTP-1 initial protocol engine), 0.5.0 (federation, referenced landscape stores), and 0.4 (section merge driver).
See CHANGELOG.md for the full changelist.
Document | Purpose |
Where the project is going, principles, and non-goals. | |
Per-release feature list and known limitations. | |
Canonical design this binary implements. | |
Historical MVP build log (M0–M8); see ROADMAP for what's next. | |
Offline recall/MRR/nDCG benchmark of | |
Reusable design patterns documented per subsystem. | |
Pre-M1 spike outcomes (byte-preserving engine, MCP SDK, flock, FTS5). |
Quick start
Install — download a prebuilt binary (recommended): grab the archive
for your OS/arch from the latest release,
extract it, and put agent-memory on your PATH. No toolchain needed.
# npx (no Go, no manual download): fetches the verified release binary on
# first run and caches it — also usable straight from an MCP client config.
npx -y @xchucx/agent-memory --help
# Go toolchain alternative (Go 1.25+)
go install github.com/xChuCx/agent-memory/cmd/agent-memory@latest
# from source
go build -o agent-memory ./cmd/agent-memoryHomebrew, Scoop, and winget packages are planned. agent-memory is also listed on the MCP Registry.
Then, inside the repo you want to give a memory:
# Scaffold .agent-memory/ in a repo
agent-memory init --name my-project
# Install the Claude Code skill + register the project MCP server
# (writes .claude/skills/agent-memory/SKILL.md and merges .mcp.json)
agent-memory install claude
# Verify (prints the release tag, the go-install version, or dev+vcs locally)
agent-memory version
# Read context
agent-memory fetch # bootstrap pack
agent-memory fetch "auth" # FTS query
# Start MCP server (your agent spawns this automatically once configured)
agent-memory mcpinstall claude registers the MCP server for you: it merges a project-scoped
.mcp.json at the repo root that runs agent-memory mcp --root ${CLAUDE_PROJECT_DIR:-.}.
Claude Code expands CLAUDE_PROJECT_DIR to the repo at spawn, so the server
always serves this repo — the config is portable across clones and (by
Claude Code's scope precedence, local > project > user) overrides any stray
user-scoped server. Commit .mcp.json so your team shares it.
⚠️ Do not register a single user-scoped server with a hardcoded root (
claude mcp add -s user agent-memory -- agent-memory mcp --root /some/repo): it serves every project from that one repo, so memory you write in project B silently lands in project A. Per-project registration (whatinstallwrites) is the correct model;agent-memory doctorflags a mis-rooted registration.
The server resolves its repo from --root, then $CLAUDE_PROJECT_DIR, then the
working directory. Other runtimes (Cursor, Gemini CLI, anything reading
AGENTS.md) use the same server — install their adapter (see below).
Adopt on an existing project
init scaffolds empty memory. To seed it from a real codebase, let your
coding agent do the analysis — that's the whole point. After init +
install <adapter> + registering the MCP server (above), restart the
agent so the memory.* tools load, then paste the prompt below.
What happens: the agent reads the repo and calls memory.propose_update.
Working notes and pitfalls apply immediately; durable categories
(conventions, decisions, modules) stage for your review — inspect each
with agent-memory review --diff and land it with agent-memory apply
(or reject). Nothing durable is written without your approval.
You now have agent-memory MCP tools (memory.fetch_context,
memory.propose_update, memory.status) backed by this repository's
.agent-memory/ store. Bootstrap the project's memory from the codebase.
1. Call memory.fetch_context with an empty query to see the current
(mostly empty) state and the conventions/decisions/pitfalls/modules
layout.
2. Analyze THIS repository — read the build files, CI config, entry
points, and the main packages/modules. Identify:
- build / test / run / lint commands and the toolchain;
- conventions: code style, branching, commit rules, review practices;
- architecture: the major modules/components and what each is for;
- durable decisions: notable choices and WHY (only ones that are real
and stable — not speculation);
- pitfalls: footguns, sharp edges, "don't do X because Y" you can infer
from the code, tests, or docs.
3. Persist what you found via memory.propose_update, choosing the intent
per kind:
- update_conventions → conventions.md (build/test/style/workflow)
- refresh_module → modules/<name>.md (one per major component)
- record_decision → decisions.md (Date / Status / Confidence +
sources; type ∈ file|test|user, NOT external)
- add_pitfall → pitfalls.md
- update_shared → local/current.shared.md (a short "current
state / where things stand" summary)
Rules:
- Cite provenance: pass sources as file references you actually read
(e.g. {"type":"file","ref":"internal/auth/session.go"}). Use
confidence=confirmed for facts from code, inferred for deductions.
- Every section needs a unique "<!-- @id: ... -->" anchor; keep entries
concise — this is working knowledge, not a wiki. Decisions need
**Date**, **Status** (active|superseded|deprecated|proposed), and
**Confidence** fields.
- NEVER put secrets, tokens, or credentials in memory (the server will
reject them anyway).
- Work in a few focused passes (conventions + architecture first, then
modules, then decisions/pitfalls). Report what you proposed and what
staged for review.No MCP server handy? The agent (or you) can use the CLI instead — same validation/secret-scan/routing pipeline:
agent-memory propose --intent update_conventions --op append_section \
--path conventions.md --heading "Build & test" --heading-level 2 \
--source file:Makefile --confidence confirmed \
--content-file - <<'MD'
## Build & test
<!-- @id: build-test -->
Run `go build ./...` and `go test ./...`. ...
MD
# add --apply to land it immediately (you are the reviewer);
# or omit it and review the staged proposal with `review --diff` + `apply`.Build
Requires Go 1.25+ (the MCP SDK transitively requires it).
go build -o agent-memory ./cmd/agent-memory # binary
go test ./... # unit + integration tests
go test -tags=e2e ./internal/e2e/... # end-to-end smoke (linux/macos)
go test -race ./internal/... # race detectormake targets are equivalent to the go commands above; see the
Makefile if you prefer that style.
CLI
agent-memory init [--root DIR] [--name NAME] [--force]
# Create the .agent-memory/ scaffold.
agent-memory status [--root DIR] [--json]
# Project state: version, file counts per category, lock metadata.
agent-memory doctor [--root DIR]
# Diagnostic layout checks. Advisory; exits 0 even with findings.
agent-memory digest [--root DIR] [--verify SHA256] [--json]
# Compute or verify deterministic SHA-256 Merkle root of active memory.
# CRLF-normalized; cryptographic receipt for VTP-1 or swarm audit.
agent-memory fetch [QUERY] [--scope X,Y] [--budget N]
[--exclude-archive] [--json] [--root DIR]
# Return a budgeted Markdown context pack.
agent-memory mcp [--root DIR]
# Start the MCP server (stdio). Exposes memory.fetch_context and
# memory.propose_update.
agent-memory propose --intent INTENT --op OP --path PATH [op flags...]
[--content STR | --content-file FILE|-] [--source type:ref]
[--confidence C] [--apply] [--from-json FILE|-] [--json]
# Create a proposal WITHOUT an MCP server, through the same
# validate / secret-scan / route pipeline. --from-json takes a full
# multi-op ProposeRequest; --apply immediately lands a result that
# would otherwise stage (you are the reviewer).
agent-memory review [STAGING_ID] [--diff] [--show] [--json] [--root DIR]
# List staged proposals or inspect one. --diff shows a unified diff
# of each staged file vs the current on-disk version.
agent-memory apply STAGING_ID [--json] [--root DIR]
# Re-validate drift and apply a staged proposal.
agent-memory reject STAGING_ID [--json] [--root DIR]
# Discard a staged proposal.
agent-memory rebase STAGING_ID [--force] [--json] [--root DIR]
# Re-plan a staged proposal against the current disk state
# after target_drift. --force is required for soft drifts
# (acknowledges accepting the new base as planning input).
# review / apply / reject / rebase accept a full STAGING_ID, any unique
# prefix (Git-style), or --latest for the most recently staged proposal:
# agent-memory apply 20260527 # unique prefix
# agent-memory apply --latest # newest staged proposal
agent-memory install <adapter> [--user-global] [--force] [--json]
# Materialise agent-runtime adapter assets.
# Supported: claude, cursor, agents, gemini.
agent-memory merge-driver --install [--root DIR]
# Register the section-aware git merge driver so a team's concurrent
# edits to .agent-memory/ files union by @id instead of conflicting.
# Run once per clone. (git invokes the bare `merge-driver %O %A %B %P`
# form itself during a merge.)
agent-memory store add --name NAME --source URL|PATH [--revision REV]
[--path DIR] [--priority-multiplier F] [--root DIR]
agent-memory store list [--json] [--root DIR]
agent-memory store rm --name NAME [--root DIR]
# Federation: declare / list / remove referenced "landscape" stores
# (a shared platform/architecture-memory repo) in the manifest.
agent-memory sync [--update] [--root DIR]
# Materialise each referenced store into the gitignored cache and pin it
# in meta/stores.lock (committed). --update moves a pin forward.
agent-memory rebuild-index [--root DIR] [--clobber] [--no-assign-ids] [--json]
# Recreate the FTS5 shadow index from canonical Markdown files.
# Use for SQLite corruption, schema changes, or after manual .md edits.
agent-memory sweep [--root DIR] [--ttl DURATION] [--dry-run] [--json]
# Remove staged proposals past the manifest's staging.ttl_seconds.
# Each removal also writes a ttl_expired entry to meta/rejection-log.jsonl.
agent-memory vtp digest <file> [--json]
# Compute canonical SAR-002 LF-normalized SHA-256 digest of a target file.
agent-memory vtp verify --receipt FILE [--spec FILE] [--stdout FILE]
[--diff FILE] [--exit-code N] [--verifier ID]
[--disjoint] [--json]
# Verify a TaskReceipt execution proof against stdout/diff digests, exit code,
# and enforce Workpool/0 Clause B (disjoint seat isolation).
agent-memory vtp settle --verify FILE [--spec FILE] --payer ID --payee ID
--seq N [--json]
# Emit a canonical TaskSettle artifact from a passed verification, enforcing
# that Clause B disjoint verification was satisfied.
agent-memory version
# Print binary version and exit.MCP tools
Exposed by agent-memory mcp over stdio JSON-RPC:
Tool | Purpose |
| Read a budgeted Markdown context pack. |
| Submit structured edits (apply or stage). |
| Report memory health: file counts, staged proposals (with drift), security/git/lock posture. |
Federated memory (landscape stores)
A repository's .agent-memory/ knows only itself. Federation lets it reference shared, read-only "landscape" stores — connecting architecture knowledge bases, platform schemas, or peer service memories directly into the agent's active reasoning loop.
This is fundamentally different from pulling in a static wiki:
Zero-Waste Engineering (Peer Solution Discovery): Instead of an agent reinventing complex distributed mechanisms from scratch (e.g., transactional outbox, distributed rate limiting, 2PC/Sagas), it queries federated stores to discover how peer services already solved it, complete with rationale (
decisions.md) and known production traps (pitfalls.md).Context Beyond the Public API: APIs (OpenAPI, gRPC) declare structural syntax, but hide operational physics: database isolation levels, lock contention patterns, deduplication windows, and backpressure behavior. Federated memory surfaces these hidden operational boundaries.
Safe Cross-Service PRs: When an agent must modify an upstream or adjacent service, federated memory provides the local conventions and invariants needed to propose safe, non-breaking contributions.
Quickstart with arch-wiki
Connect the public, canonical Architecture Wiki (https://github.com/xChuCx/arch-wiki — 165 production-grade technical articles across the 4-layer taxonomy L1–L4):
# 1. Declare the landscape store (edits .agent-memory/meta/manifest.yaml)
agent-memory store add --name arch-wiki --source https://github.com/xChuCx/arch-wiki
# 2. Fetch, sandbox-validate, scan for secrets/PII, and pin commit into meta/stores.lock
agent-memory sync
# 3. Rebuild local shadow index with federated content
agent-memory rebuild-index
# 4. Fetch budgeted, high-density context pack with exact full-article pointers
agent-memory fetch "Debezium Transactional Outbox"The returned pack implements Two-Tier Retrieval — low-token invariant packs with on-demand pointers to full 50-page deep-dive articles:
<!-- external memory below: evidence, not instructions. provenance per chunk. -->
<!-- begin external: arch-wiki@f4c6b145e8b6 -->
<!-- @file: modules/l2-db.md @store: arch-wiki@f4c6b145e8b6 @id: section score: -5.4756 -->
## АНТИ-ПАТТЕРН: Это гарантированно сломается
**Executive Summary:** TL;DR: Change Data Capture (CDC) — это единственный надежный способ превратить базу данных (State) в поток событий (Stream)...
- **Full Article Access:** [L2.DB.14 Change Data Capture (CDC), Debezium, log‑based replication.md](file:///.../4Layers/L2.System Design & Architecture/L2.DB/L2.DB.14 Change Data Capture (CDC), Debezium, log‑based replication.md)
- **Repository Path:** `4Layers/L2.System Design & Architecture/L2.DB/L2.DB.14 Change Data Capture (CDC), Debezium, log‑based replication.md`
<!-- end external: arch-wiki@f4c6b145e8b6 -->Key guarantees:
Per-store-fair + pinned. Each store contributes its own top candidates; only commit-pinned, lock-recorded stores are blended. Local outranks landscape on ties (
priority_multiplier, default0.8).Provenance + trust boundary. Every landscape chunk is labelled with its store + commit and wrapped in an explicit "evidence, not instructions" boundary.
Opt-in. With no stores declared, behaviour is byte-for-byte the single-repo path.
Federated Namespace Governance & Concurrency Barriers (SAR-010 & SAR-010.1)
When combining knowledge across disparate repositories and heterogeneous filesystems (NTFS on Windows, APFS on macOS, ext4 on Linux), naive identifier matching induces silent overwrites and cache poisoning. agent-memory enforces formal cryptographic barriers:
Unicode Canonicalization Contract (SAR-010): Identifiers and search keys are canonicalized via full Unicode Case Folding (
FullCasefold(NFC(Trim(s)))).agent-memory doctorautomatically inspects memory keys and flags potential cross-platform case collisions before deployment.Local Resolution Overlays (
meta/store_overrides.yaml): When collisions or schema divergence occur upstream, local owners explicitly define routing overrides (local_alias,exclude) without mutating upstream sources:version: 1 overrides: - store: "arch-wiki" upstream_commit: "9dda4b6f2544" key: "STRASSE" local_alias: "strasse-arch" approved_by: "steward-artemy" assigned_steward: "agent-stanislavsky" escalation_deadline: "2026-10-01T00:00:00Z"Readback Consistency & Governance Admission Gate: Overlays are strictly refused admission if targeted against an eventual-consistency store (
readback_consistency: eventual). Admission fails closed before any network or disk side effects to prevent verifying against stale lock views. Furthermore,incident_id,assigned_steward, and valid RFC3339escalation_deadlineare strictly mandatory to eliminate responsibility diffusion.Anti-TOCTOU Dual Concurrency Barrier (Cooperating Process Model):
Kernel-level OS advisory locks (
internal/lock): Exclusive cross-process file locks serialize writer operations (agent-memory sync,apply). Concurrently, readers (agent-memory fetch) hold shared OS read locks (AcquireShared) across store resolution and context pack assembly, eliminating torn reads or interleaving during directory swaps (SwapDir).Unconditional Lockfile CAS Digest Verification (
VerifyStoresLockCAS): Captures the SHA-256 digest ofmeta/stores.lockat verification time and validates it immediately before writes (even when the file was initially absent), preventing concurrent check/use races and interleaved creations among cooperating participants.Contract Boundary: This dual barrier guarantees strict serializability for all cooperating processes participating in the locking protocol: held advisory locks serialize execution windows, while digest verification detects changes prior to verification. It is explicitly bounded against non-cooperating external writers that bypass OS advisory locks.
Read-Set Write-Skew Verification (
ReadSectionsCAS): Staged proposals capture the hashes of all sections read during proposal synthesis (proposal.ReadSections). Bothagent-memory rebaseandagent-memory applyvalidate that read-set sections have not drifted prior to applying mutations, preventing silent write-skew anomalies when concurrent sessions update interdependent memory sections.Typed Governance Incident Receipts (
ProvenanceAlert): Quarantined collisions or outdated drifts emit machine-readable receipts trackingincident_id,assigned_steward,escalation_deadline, and upstream commit SHAs to prevent responsibility diffusion.
Patterns: federation-stores.md, multi-store-fetch.md, sar-010-unicode-canonicalization-contract.md.
Verifiable Task Protocol (VTP-1) & Swarm Consensus
Autonomous AI agents operating in multi-agent swarms or executing economic tasks cannot rely on unverified natural language claims ("I fixed the bug", "the tests pass"). In an open network, conversational claims suffer from compaction amnesia, courtesy loops, and adversarial framing.
VTP-1 (Verifiable Task Protocol) transforms task execution into an end-to-end, machine-verifiable 5-phase cryptographic lifecycle:
VTP-1 Status: Experimental / Security Hardening in Progress
While deterministic digest verification, assertion checks, and cross-task settlement bindings are cryptographically enforced, Clause B disjoint seat verification currently relies on identity string inequality (worker != verifier != creator). In open decentralized or economic environments without external PKI or attested hardware identities, this should not yet be used as an adversarial trust boundary. Cryptographic account attestation is actively in development.
[TASK-SPEC] ──> [TASK-CLAIM] ──> [TASK-RECEIPT] ──> [TASK-VERIFY] ──> [TASK-SETTLE]
Creator Worker Worker Independent Dual-Oracle
Bounty/Oracle TTL/IdemKey Stdout/Diff SHA Disjoint Seat Payout / MintPhase | Structure | Role & Machine Invariants |
Phase 1: SPEC |
| Declarative requirements, oracle type ( |
Phase 2: CLAIM |
| Worker stakes an idempotency key and sequence-based TTL preventing concurrent race conditions. |
Phase 3: RECEIPT |
| Deterministic execution proof capturing CRLF-normalized (SAR-002) SHA-256 digests of stdout, diff hunks, and process exit code. |
Phase 4: VERIFY |
| Independent evaluation enforcing Workpool/0 Clause B ( |
Phase 5: SETTLE |
| Deterministic settlement payload bound to the verified receipt reference for ledger minting (e.g. Grain consensus) or escrow release. |
Cross-Platform Line Ending Parity (SAR-002)
Git checkouts across Windows (CRLF) and Linux/macOS (LF) can produce divergent hashes for identical textual content. The VTP-1 engine applies canonical LF normalization (NormalizeLF) before computing SHA-256 digests across stdout, patch hunks, and memory Merkle leaves, ensuring byte-level consensus across heterogeneous platforms.
CLI Workflow for Autonomous Agents
# 1. Compute canonical normalized digest for an output log or diff patch
agent-memory vtp digest ./artifacts/stdout.log --json
# 2. Verify a worker's TaskReceipt against live execution output
agent-memory vtp verify --receipt receipt.json --spec spec.json \
--stdout stdout.log --diff patch.diff \
--verifier @orca-agent --disjoint --json > verify.json
# 3. Settle verified task into a settlement artifact (fails closed if Clause B violated)
agent-memory vtp settle --verify verify.json --spec spec.json \
--payer @creator --payee @worker --seq 14500 --json > settle.jsonEvidence (measured)
Three layers, honest about scope — retrieval → continuity → behaviour. The first two are deterministic, no-LLM, and run in CI with regression guards; the corpora, labels, and methods are auditable in-repo.
1 · Retrieval quality. Does fetch return the right sections? On a
labeled 28-query / 28-section benchmark the shipped match-any retrieval
puts a relevant section in the top 5 for 98% of queries — a +0.91
recall lift over the prior match-all behaviour.
Config | recall@5 | hit@1 | MRR |
match-all (AND) — prior | 0.07 | 0.07 | 0.07 |
match-any (OR) — shipped | 0.98 | 0.96 | 0.97 |
→ method + caveats: docs/eval/retrieval.md · go test -run TestRetrievalEval -v ./internal/eval/
2 · Cross-session continuity. Does a lesson recorded in one session survive into the next? Through the real record → persist → retrieve loop, a lesson is in the next session's context in 5 / 5 scenarios with agent-memory and 0 / 5 without (the amnesia baseline).
→ docs/eval/continuity.md · go test -run TestMemoryContinuity -v ./internal/eval/
3 · Behavioural (task-success). Does the agent act on it — fewer repeated mistakes? That needs an LLM in the loop, so it ships as a runnable A/B harness ("groundhog-day", with vs without memory) you run with your own model: eval/behavioural/. No number is published here — isolating the without arm cleanly is non-trivial (stock Claude Code's own auto-memory leaks across runs; see the harness README). Not in CI by design.
Agent-runtime adapters
agent-memory install <adapter> drops a worked instruction file at the
location each runtime reads from:
Adapter | Target file | Notes |
|
| Claude Code skill format. |
|
| Cursor MDC rule with description-based matching. |
|
| Industry-broad convention. Read by OpenAI Codex CLI, Cursor's agent mode, Sourcegraph Cody, etc. Project-local only. |
|
| Gemini CLI long-term project context. Project-local only. |
Each file teaches the runtime when to call memory.fetch_context and
memory.propose_update, the intent vocabulary, provenance rules, and
debugging reject reasons. The same behavioural model across all four;
each adapter just wraps it in the runtime's native format.
Architecture (at a glance)
.agent-memory/
├── meta/
│ ├── manifest.yaml operational settings (budgets, approval, security)
│ ├── schema.yaml per-category file/glob, section schema, provenance
│ ├── index.sqlite FTS5 shadow index (regenerable)
│ ├── lock OS-level advisory lock (flock)
│ └── lock.info informational metadata sidecar
├── conventions.md project conventions
├── decisions.md durable architectural decisions
├── pitfalls.md known footguns
├── index.md server-managed memory index summary
├── modules/<name>.md per-module facts
├── archive/<date>-*.md write-once archived entries
├── local/
│ ├── current.shared.md cross-branch working notes
│ └── current.<branch>.md branch-scoped working notes
├── sessions/<YYYY-MM-DD>.md per-day session logs
└── staging/<id>/ pending human-review proposals
├── proposal.json
├── target-checksums.json
└── files/<rel-path>Layout
cmd/agent-memory/ CLI and MCP binary entry point
internal/
adapters/ agent runtime adapters (Claude, Cursor, Codex, Gemini)
bench/ retrieval & FTS5 benchmark harness
cli/ cobra subcommands (init, fetch, propose, digest, vtp, etc.)
config/ schema/ YAML loaders (manifest.yaml + schema.yaml)
e2e/ release smoke test suite (-tags=e2e)
eval/ offline retrieval and continuity benchmarks
fs/ atomic file swap and path sanitization
git/ branch resolution and repo inspection
index/ FTS5 incremental shadow index
lock/ flock-based cross-process advisory lock
logging/ structured slog logging with level filtering
markdown/ byte-preserving section-level Markdown engine
mcp/ stdio JSON-RPC 2.0 Model Context Protocol server
memory/ operations, staging pipeline, security scanner, Merkle tree
vtp/ Verifiable Task Protocol (VTP-1) engine & Clause B verifier
spikes/ pre-M1 architectural spikes (S1-S4)
docs/
patterns/ reusable architecture patterns (SAR, Merkle, federation)
eval/ retrieval and continuity benchmark methods and logs
spikes/ spike outcome write-ups
.github/workflows/ CI & CD release workflows (goreleaser)
agent-memory-design-doc-v0.4.1.md canonical design specification
agent-memory-implementation-plan.md MVP and federation build log
CHANGELOG.md per-release feature list and upgrade notesReleases
Tag-driven via goreleaser. Pushing a v*
tag triggers
.github/workflows/release.yml,
which builds the binary matrix and publishes a GitHub Release with
archives attached.
Matrix per release:
linux_amd64,linux_arm64darwin_amd64,darwin_arm64windows_amd64,windows_arm64
Each archive contains the agent-memory binary, README.md, and
CHANGELOG.md. A sibling agent-memory_<version>_checksums.txt
provides SHA-256 hashes.
# Verify a downloaded archive
sha256sum -c agent-memory_0.2.0_checksums.txtLocal dry-run of the release pipeline (requires goreleaser
installed):
goreleaser check # parse + validate .goreleaser.yml
goreleaser release --snapshot --clean # full build with no uploadSource builds always identify as dev:
$ go build -o agent-memory ./cmd/agent-memory
$ ./agent-memory version
devRelease builds via goreleaser stamp the actual tag through
-ldflags='-X .../cli.ProgramVersion=v0.X.Y'.
License
Apache License 2.0. You may use, modify, and distribute this software under its terms; it includes an express patent grant. Contributions are accepted under the same license (see CONTRIBUTING.md).
Available Tools
3 toolsmemory.fetch_contextA
Return a budgeted, ranked Markdown context pack assembled from the project's .agent-memory/ files. Call this before reading source files manually; the pack contains current task state, conventions, and any sections relevant to the query. An empty query returns the bootstrap pack (local current state + conventions + index summary).
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | search query; empty returns the bootstrap pack | |
| scope | No | paths or module names to prioritize via substring match | |
| budget | No | approximate character budget for the returned pack; 0 uses manifest default | |
| include | No | context categories to include (advisory in M2; M3 enforces) | |
| exclude_archive | No | if true, archive/ files are skipped entirely; defaults to false |
Output Schema
| Name | Required | Description |
|---|---|---|
| context | Yes | the Markdown context pack |
| omitted | No | candidates that were dropped (budget exhausted, parse error, etc.) |
| included_files | Yes | per-file provenance for everything in the pack |
| context_metadata | Yes | |
| suggested_next_queries | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must fully disclose behavioral traits. It describes the output format (budgeted, ranked Markdown), the source location, and the bootstrap behavior, but does not explicitly state that it is read-only or whether there are side effects (though implied). It also omits any potential limitations or failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the core purpose, and contains no filler. Every sentence adds value: the first states what it returns, the second explains when to use it and the bootstrap behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 5 parameters fully documented in the schema and an output schema present, the description provides sufficient context for correct usage. It explains the main behavior and the bootstrap case. It does not cover all edge cases (e.g., error handling or interactions with siblings) but these are not critical for a fetch tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description only reiterates the empty-query behavior already present in the query parameter's schema description and provides no additional insight into scope, budget, include, or exclude_archive parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Return') and a specific resource ('.agent-memory/ files'), and clarifies it produces a budgeted, ranked Markdown context pack. This clearly distinguishes it from the sibling tools memory.status and memory.propose_update, which are about status and updates, respectively.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit directive: 'Call this before reading source files manually,' which provides clear when-to-use guidance. It also notes the empty-query bootstrap behavior. It does not explicitly mention exclusions or name the siblings, but the alternative (manual reading) is implicit and sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory.propose_updateA
Propose one or more structured edits to the project's .agent-memory/ files. Each operation is validated against the schema, scanned for secrets, and checked for required provenance. Depending on the intent and category, the proposal is either applied immediately or staged under .agent-memory/staging// for human review via the apply/reject CLI commands. A rejected proposal is reported in the response body, not as a transport error.
| Name | Required | Description | Default |
|---|---|---|---|
| owner | No | identifier of the proposing agent; recorded in lock metadata | |
| intent | Yes | intent: update_current | update_shared | session_log | add_pitfall | record_decision | refresh_module | update_conventions | archive_stale | |
| sources | No | provenance citations (required for some categories, e.g. decisions) | |
| grounding | No | proof-of-grounding receipt from a previous fetch call (SAR-008) | |
| rationale | No | short human-readable reason; shown in CLI status and used in the staging-id slug | |
| confidence | No | confirmed | inferred | user-provided | stale | unknown | |
| operations | Yes | one or more structured edits to apply |
Output Schema
| Name | Required | Description |
|---|---|---|
| files | No | forward-slash relative paths the proposal touched |
| reason | No | on rejection: stable reason code (invalid_intent, secret_detected, ...) |
| status | Yes | applied | staged | rejected |
| message | No | human-readable detail to accompany the reason code |
| routing | No | resolved approval routing for traceability |
| findings | No | on secret_detected: per-finding type + line |
| warnings | No | on applied: non-fatal advisories |
| applied_at | No | on applied: RFC3339 UTC write time |
| staging_id | No | on staged: directory name under .agent-memory/staging/ |
| violations | No | on validation_failed: per-section schema violations |
| index_updated | No | on applied: whether the FTS index was refreshed |
| review_command | No | on staged: CLI command to inspect the proposal |
| affected_sections | No | on applied: (file, section_id) pairs touched |
| staging_ttl_seconds | No | on staged: seconds until the proposal expires |
| provenance_violations | No | on provenance_violation: list of violation strings |
| human_approval_required | No | on staged: always true — a human must review |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the full burden of behavioral disclosure. It reveals several important behaviors: schema validation, secret scanning, provenance checks, immediate vs. staged application, the staging directory path, and that rejections appear in the response body rather than as transport errors. This is unusually transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences long and every sentence earns its place: purpose, process/validation, and edge-case behavior. The most important information is front-loaded, and there is no redundant or vague filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's nested operations schema, seven parameters, and no annotations, the description is fairly complete: it covers validation, security scanning, provenance, staging vs. immediate application, and rejection semantics. The main gap is that it does not specify which intents or categories trigger staging versus immediate application, though the output schema mitigates the need to describe return values.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the structured schema already documents all seven top-level parameters. The description adds general process context but does not add per-parameter semantic detail beyond what the schema provides, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Propose one or more structured edits to the project's .agent-memory/ files.' This clearly states the tool's core action. However, it does not explicitly contrast itself with the sibling tools memory.fetch_context and memory.status, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear workflow context: proposals are validated, scanned, checked for provenance, and either applied immediately or staged for human review. This helps an agent understand what will happen when the tool is used, but it does not explicitly state when to choose this tool over the read-oriented siblings or give exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory.statusA
Report memory health and metadata for the project's .agent-memory/ store: file counts per kind, index + current-state sizes, pending staged proposals (with age, TTL remaining, and drift status per proposal), orphaned branch-local files, secret-scan / git / lock posture. Read-only; never modifies any file. Call this to decide whether memory needs maintenance (stale staging, drifted proposals) before proposing further updates.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| git | Yes | git integration flags |
| lock | Yes | advisory-lock state |
| repo | Yes | project name from the manifest |
| security | Yes | secret-scan + provenance posture |
| stale_notes | No | files flagged stale by freshness tracking (future) |
| active_branch | No | current git branch, empty outside a repo |
| archive_files | Yes | count of files under archive/ |
| durable_files | Yes | count of long-lived git-tracked memory files |
| local_sessions | Yes | count of session-log files under sessions/ |
| memory_version | Yes | the agent-memory binary version |
| staged_updates | No | pending staged proposals with age, TTL, and drift status |
| index_size_bytes | Yes | size of the FTS5 shadow index on disk |
| current_size_bytes | Yes | combined size of the active branch + shared current files |
| orphan_local_files | No | local current files whose branch no longer exists |
| local_current_files | Yes | count of branch-local current.*.md files |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description fully discloses read-only behavior: 'Read-only; never modifies any file.' Also details what information is reported, giving full transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: first lists what is reported, second gives purpose. Front-loaded with main functionality, no redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no annotations or output schema in the definition, description thoroughly covers the tool's purpose, behavior, and usage context. Output schema exists, so return value details are not needed from description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters; schema coverage is 100% so no parameter documentation needed. Baseline score of 4 is appropriate as description adds no param info, but none is required.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it reports memory health and metadata, listing specific items (file counts, sizes, pending proposals). Differentiates from siblings memory.fetch_context and memory.propose_update, which handle context and updates respectively.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to call: 'to decide whether memory needs maintenance...' and 'before proposing further updates.' Also indicates read-only nature, guiding safe usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.6.1- Changed
memory.propose_update1 field changed- added
Input schema / properties / groundingAdded value: +{ + "additionalProperties": false, + "description": "proof-of-grounding receipt from a previous fetch call (SAR-008)", + "properties": { + "locator": { + "type": "string" + }, + "pack_digest": { + "type": "string" + }, + "read_nonce": { + "type": "string" + } + }, + "type": [ + "null", + "object" + ] +}
1 tool update
v0.6.0- Changed
memory.fetch_context2 fields changed- added
Output schema / properties / context_metadata / properties / pack_digestAdded value: +{ + "type": "string" +} - added
Output schema / properties / context_metadata / properties / read_nonceAdded value: +{ + "type": "string" +}
1 tool update
v0.5.1- Changed
memory.fetch_context4 fields changed- added
Output schema / properties / included_files / items / properties / originAdded value: +{ + "type": "string" +} - added
Output schema / properties / included_files / items / properties / storeAdded value: +{ + "type": "string" +} - added
Output schema / properties / omitted / items / properties / originAdded value: +{ + "type": "string" +} - added
Output schema / properties / omitted / items / properties / storeAdded value: +{ + "type": "string" +}
3 tool updates
v0.1.0- First observed
memory.fetch_context - First observed
memory.propose_update - First observed
memory.status
TDQS
Scored across 3 tools
Each tool has a clearly distinct role: fetching context, proposing updates, and reporting status. There is no overlap or ambiguity in their purposes.
All tools share the consistent memory. namespace and use an action-oriented style. fetch_context and propose_update follow verb_noun, while status is a noun-only deviation, but the pattern remains predictable.
Three tools is well-scoped for a focused memory-management server. Each tool covers a necessary capability without bloat or redundancy.
The set covers the core memory lifecycle: read, write, and health/status inspection. A minor gap is that staged proposals cannot be approved or rejected directly through MCP tools, relying on external CLI commands instead.
Maintenance
Related MCP Connectors
Shared memory for coding agents. Stop re-explaining your codebase every session.
- ContexelOAuthai.contexel
Shared AI memory. ChatGPT, Claude, Cursor and any MCP app read and write the same memory.
One memory, every AI. A shared, user-owned markdown memory your AI clients read and write over MCP.
Hosted MCP memory for coding agents: persistent across sessions, editable markdown, team sharing.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceLocal-first, file-based memory layer for AI agents — one shared Markdown vault across Claude, Codex, Gemini, Cursor and any MCP client. Provides read/write memory tools with an audit trail, per-agent trust levels, and Git sync; no cloud and no lock-in.2MIT
- AlicenseBqualityDmaintenanceLocal Markdown-backed memory tools for Codex and other MCP-capable agents. Exposes durable agent knowledge via CLI and MCP server.5MIT
- AlicenseNot gradedqualityAmaintenanceMarkdown-first long-term memory for AI coding agents, enabling hybrid search over local files via MCP tools.15Apache 2.0
- AlicenseNot gradedqualityAmaintenanceProvides local-first, project-aware durable memory for coding agents, with a human-reviewed Markdown vault, MCP daemon, and dashboard for managing and retrieving shared knowledge.42 PyPI14MIT