Long-term memory for Claude: Markdown in a git repo you own. Survives context compaction.
Long-term memory for Claude and any MCP client, stored as plain Markdown in a git repo you own. Hybrid semantic search, a knowledge graph, auto-memory and compaction survival, at about 775 tokens of tool overhead per turn. Every memory is a git commit you can read, diff and revert.
curl -fsSL https://raw.githubusercontent.com/AnxovatomicaES/githippo/main/install.sh | sh
That's the whole install: no account, no token, no questions. It sets up a local memory vault, wires Claude Code (hooks, MCP, status line) and fetches semantic search in the background. Restart Claude Code and just talk; it remembers.
Want it backed up and synced across machines? githippo sync --github creates a private repo with your existing GitHub CLI login and pushes after every change. Just curious? npx -y github:AnxovatomicaES/githippo#v3.6.1 demo shows it working in 30 seconds without installing anything.
Because each good idea out there lives in a different tool. githippo takes the best of each and fixes the part that hurts:
| Idea | Borrowed from | githippo's twist |
|---|---|---|
| Entities + relations + observations | MCP reference memory server | Entities are Markdown files, relations are [[wikilinks]], and search is semantic, not substring: "the language I prefer" finds "TypeScript" |
| Markdown you can edit, Obsidian graph | Basic Memory | Same human-readable files, but synced through git: every device, full history, zero cloud fees |
Typed relations (works_on [[x]]) | Basic Memory, Dataview | Parsed into a queryable graph; recall follows links one hop automatically |
| Temporal facts ("what was true last quarter?") | Graphiti / Zep | Superseded facts move to a dated History section instead of vanishing, and history at=<date> gives exact time travel from git, with no graph DB and no LLM calls |
| Pinned "core memory" blocks | Letta (MemGPT) | Core memory rides inside the MCP server instructions, which live in the system prompt, so it survives compaction in every client, including claude.ai |
| Lifecycle hooks around compaction | claude-mem | The PreCompact hook builds the checkpoint deterministically from the transcript (goal, todo state, files changed, where it stopped). No LLM, no cost, can't hallucinate |
| Progressive disclosure | claude-mem | recall mode=brief returns one-line refs (~45 tokens) before you pay for full context |
| Consolidation / dedupe | mcp-memory-service, Mem0 | Embedding-based duplicate detection on every write, plus maintain health reports; optional LLM merge that refuses lossy rewrites (dropped links or frontmatter) |
| Remote MCP for claude.ai | Supermemory, Mem0 | Self-hosted Streamable HTTP; your data never leaves your repo and your server |
Version 3.1 adds the best idea from each of nine other memory tools, read in their source and credited in docs/prior-art.md: <private> tags, compaction steering and summary capture, session diffing, activity-aware decay, a code-aware tokenizer, errors in checkpoints, an honest status line, plugin packaging and alwaysLoad registration.
What else it does:
maintain reports possible contradictions. Measured in docs/calibration.md.When Claude Code compacts a long session, the conversation gets summarised and details die. githippo makes sure what matters doesn't.
flowchart LR
A[Context fills up] --> B[PreCompact hook]
B -->|parse transcript, no LLM| C[checkpoint: goal, todos, files, where it stopped]
C --> D[(local ~/.githippo)]
C --> E[(repo sessions/)]
F[Compaction] --> G[SessionStart hook, source=compact]
D --> G
G -->|injects the state itself, not a reminder to read it| H[Claude continues exactly where it stopped]
I[MCP instructions + core memory] -.->|system prompt, never compacted| H
checkpoint tool (any client, including claude.ai). Claude saves task, state and next step at milestones. After context loss, checkpoint with no args restores it.Bonus: a fresh session in the same project and branch within 24h gets a brief "last time you were…" note, including what changed in git since (commits, commits by others, branch switches, deleted files). The UserPromptSubmit hook proactively surfaces up to three relevant memories when the match is confident. It's capped at 300 tokens, skips trivial prompts and never repeats within a session. Before compaction, githippo also tells the compactor what must survive, and after compaction it keeps the compactor's summary with the checkpoint.
How we know the hooks do what we say: the contracts were read from Claude Code's own code (2.1.258). PreCompact passes each successful hook's stdout to the compactor as custom instructions (Claude Code also shows that text in the transcript as "PreCompact … completed successfully"); PostCompact receives compact_summary; every hook receives session_id, transcript_path and cwd; SessionStart sources are startup, resume, clear, compact and fork.
Recall also learns what you actually use: memory that keeps being handed to Claude gets a small boost (at most +40%) that halves every 30 days without use. The counts stay on your machine, are kept per user, and with no usage data ranking is exactly the same as without it.
Wrap anything in <private>…</private> and it never reaches memory. Turn hooks off without editing files: GITHIPPO_HOOK_PROFILE=minimal or GITHIPPO_DISABLED_HOOKS=prompt,steer.
A labelled benchmark ships in eval/: a 19-file working memory (people, projects, decisions; some notes in Spanish) and 52 queries labelled with the file that should come back, plus filing and duplicate/update cases. CI runs it on every change to the code and posts the results to issue #3; a quality floor fails the build if keyword retrieval regresses. Reproduce it with githippo eval.
| Queries (52) | Keyword + graph | + local model |
|---|---|---|
| Exact terms, code identifiers, names, graph hops (21) | 100% hit@1 | 100% hit@1 |
| Paraphrases (12) | 50% hit@1 · 67% hit@5 | 58% hit@1 · 100% hit@5 |
| Spanish ↔ English (13) | 15% hit@1 · 23% hit@5 | 54% hit@1 · 100% hit@5 |
| French, German, Portuguese, Italian → English (6) | 17% hit@5 | 100% hit@1 |
| All | 58% hit@1 · 64% hit@5 · MRR 0.60 | 79% hit@1 · 100% hit@5 · MRR 0.89 |
| Filing a new fact in the right file (12, held out) | 67%, none in a wrong file | 67%, none in a wrong file |
| Duplicate vs update vs new fact (11) | 91% | 82% |
hit@k: the right file is among the first k results. Recall puts several results in context, so with the model the right memory reached Claude in all 52 cases; every miss at rank 1 was at rank 2.
What this does and doesn't tell you: the set is small, hand-written by the author, and in-domain, so treat it as a regression guard and a rough guide, not a leaderboard number. Filing is the weakest area. It's deliberately cautious: when the evidence is a tie it parks the fact in the inbox (visible, one move away) rather than guessing, so a third of held-out facts wait in the inbox but none go to a wrong file. Filing rules were tuned on a separate development set (90% there, 2 of 20 in a wrong file) and the held-out number is reported as measured; it went down from 75% when the rules changed, in exchange for no wrong-file errors. Thresholds were calibrated on separate sentence pairs (docs/calibration.md), not tuned on this set.
LongMemEval (ICLR 2025) is a public long-term-memory benchmark: 500 questions, each with about 48 past chat sessions to search. githippo runs it with the same retrieval protocol agentmemory publishes (fresh index per question, recall_any@K over sessions, retrieval only, no LLM), on a pinned dataset revision, weekly in CI (eval/longmemeval.js, results in #3).
| LongMemEval-S, 500 questions | R@5 | R@10 | R@20 | MRR |
|---|---|---|---|---|
| githippo, keyword + graph (no model) | 96.2% | 98.4% | 99.2% | 91.5 |
| same, sessions shuffled (sanity check) | 96.2% | 98.4% | 99.2% | 91.5 |
| ablation: chunks only, no document-level evidence | 96.0% | 98.0% | 99.2% | 90.4 |
| ablation: whole-session documents instead of chunks | 97.4% | 98.2% | 99.6% | 91.1 |
| for reference: agentmemory BM25 / BM25 + vectors (their published numbers) | 86.2% / 95.2% | 94.6% / 98.6% |
Read it carefully: this is retrieval recall, not the official LongMemEval QA score (which needs an LLM to answer and a judge). Shuffling the sessions changes nothing, so the score isn't an ordering artifact. githippo's keyword search scores well above agentmemory's published keyword number under the same protocol; the difference is in tokenization and ranking details we haven't isolated, so treat cross-project comparisons as indicative and reproduce them yourself. Whole sessions beat ~700-character chunks on R@5 here, which led to one design change: githippo now also ranks whole notes and fuses that with chunk evidence (best MRR of the variants, chunk-level references kept). That change was evaluated on this benchmark, so LongMemEval is no longer fully held out for it; the in-repo eval didn't change.
Resources (measured in CI, Linux): githippo itself uses about 50 MB. The local model runs in a separate process that uses about 520 MB while you're using it and exits after 10 idle minutes (EMBED_IDLE_MS), so an idle githippo is back to about 50 MB. Without the model (EMBEDDINGS=none) it never goes above about 100 MB. The model embeds about 46 chunks a second on a 4-core CI machine (batch size and thread count make no difference), so the first semantic index of a 5,000-note vault takes a few minutes; it happens once in the background, vectors are cached on disk, and keyword search works in the meantime.
Scale: on a 5,000-file local vault, a re-sync takes about 0.4 s, a query about 25 ms and a remember about 0.1–0.4 s (asserted in CI). In GitHub mode (the remote server), a 2,000-file vault cold-starts with 2 API calls (one tarball), an unchanged sync is a free 304 Not Modified, and each write is 1 call.
githippo bench)| githippo v2 (our first version) | githippo now | |
|---|---|---|
| Tools | 12 | 8 |
| Model-visible schema, every turn | ~1,380 tok | ~775 tok |
| Instructions | ~340 tok | ~176 tok + your core |
| Typical recall response | ~190 tok (JSON) | ~117 tok pack / ~47 tok brief |
How: terse schemas, the redundant $schema URL stripped from tools/list, compact text responses instead of pretty JSON, wikilinks rendered as plain words, frontmatter stripped, 8-char version handles, History/index/sessions/core excluded from recall by default, and token budgets on every pack.
| Tool | What it does |
|---|---|
recall | Hybrid search (BM25 + embeddings, fused with reciprocal rank fusion) + one-hop graph expansion → token-budgeted context pack. mode=brief for refs only |
remember | Save a fact. Auto-routes to the right entity, dedupes, auto-links people/projects, flags what it may supersede. replaces= supersedes, pin= adds to core |
forget | Remove an exact fact |
graph | Typed relations around an entity |
history | Commit timeline, or the file as of a date |
checkpoint | Save or resume working state |
maintain | Duplicates, possible contradictions, orphans, broken links; suggested homes for inbox facts (tidy=true moves them); rebuild index; activity-aware decay; LLM merge |
files | Raw list/read/write/edit/delete with version checks |
Claude Code (full experience: hooks + MCP)
curl -fsSL https://raw.githubusercontent.com/AnxovatomicaES/githippo/main/install.sh | sh
Prefer to see what runs? It's a short shell script: check Node 20+, npm i -g github:AnxovatomicaES/githippo#v3.6.1, then githippo setup. setup is idempotent, keeps any status line you already have, and backs up ~/.claude/settings.json before touching it. githippo doctor checks everything afterwards.
Coming from the official reference memory server? githippo import ~/path/to/memory.jsonl turns its entities, observations and relations into notes and typed links (secrets guard and dedupe apply, so re-running is safe).
Plugin route: run the install above, then /plugin marketplace add AnxovatomicaES/githippo and /plugin install githippo. Or hand your agent INSTALL_FOR_AGENTS.md.
Download githippo-<version>.mcpb from the latest release and double-click it (or drag it into Settings → Extensions). It runs on Claude Desktop's built-in Node, so nothing else needs installing, and it uses the same vault as the CLI and Claude Code. Also listed in the official MCP Registry as io.github.AnxovatomicaES/githippo.
githippo sync --github # creates a private repo "githippo-memory" with your gh login
Every change is pushed in the background; the server pulls other machines' changes every 5 minutes. On a second machine: git clone the repo to ~/.githippo/vault, then run the installer. No token is stored anywhere: git uses your existing GitHub CLI, SSH or keychain login.
The phone and web apps can't reach your laptop, so this mode reads the vault from GitHub:
githippo sync --github (above).MEMORY_REPO (e.g. you/githippo-memory), GITHUB_TOKEN (fine-grained, that one repo, Contents: Read and write) and PUBLIC_URL (your service's https URL). MCP_SECRET is generated for you.https://<your-app>.onrender.com/mcp. Claude registers itself and opens a sign-in page; enter MCP_SECRET once. That's standard OAuth 2.1 (PKCE, dynamic client registration, audience-bound tokens), so nothing secret ever sits in a URL.A shared vault for a team. Add people with folder-level access; each signs in with their own password:
githippo users add john --acl "shared/:write,people/:read" # prints his password once
githippo users list
Rules use the longest matching folder (none, read, write). Everyone also gets a private users/<id>/ folder for their own inbox, sessions and pinned core memory, which a catch-all rule can never open. Facts a user can't write where they'd naturally go land in their own inbox instead. Every commit records who made it. Changing a password or ACL revokes that user's tokens immediately. On hosts without a disk, paste ~/.githippo/users.json into the USERS_JSON variable.
Local: command githippo serve. Remote: URL https://host/mcp; clients that support MCP OAuth sign in by themselves, others can send Authorization: Bearer <MCP_SECRET> (a header, so it doesn't end up in URL logs).
Plain Markdown, Obsidian-compatible. Open the repo as a vault and you get the graph view for free.
---
name: billing-v2
title: Billing v2
type: project
description: Billing rewrite
aliases: [billing rewrite]
---
## Decisions
- Use idempotency keys on every write endpoint
- owner:: [[sam-okafor]]
- Launch target is end of Q1
## History
- ~~Launch target is end of Q4~~ (until 2026-09-30)
Layout: core.md (pinned), index.md (table of contents), inbox.md (unrouted facts), people/, projects/, topics/, decisions/, sessions/ (checkpoints). See examples/memory.
| Variable | Default | |
|---|---|---|
VAULT_DIR | ~/.githippo/vault | local memory vault (a git repo) |
STORE | local | github reads/writes via the GitHub API instead (used by the remote server) |
GITHUB_TOKEN, MEMORY_REPO | only for STORE=github / remote mode | |
MCP_SECRET | remote mode, 24+ chars: owner login and OAuth signing key | |
PUBLIC_URL | remote mode: the server's public https URL (OAuth issuer) | |
USERS_JSON | remote multi-user: contents of githippo users file | |
EMBEDDINGS | local | local (paraphrase-multilingual-MiniLM-L12-v2 in a separate process: ~520 MB while in use, exits after EMBED_IDLE_MS, default 10 min), voyage, or none (keyword only). Choice and thresholds are measured in docs/calibration.md |
MEMORY_ROOT / MEMORY_BRANCH | memory / main | |
CORE_BUDGET_TOKENS | 400 | hard cap for pinned memory |
MEMORY_STYLE | plain | terse removes padding (articles, filler) from recalled memory and core before Claude reads it; files on disk are never changed. Rules from caveman, limited to deletions that can't change meaning: negations, numbers, names, code, URLs and paths always survive. Measured saving is small (about 3% on terse notes, 10% on wordy ones), and caveman's own cited research found compressing what a model reads can hurt answers, so it's off by default |
PROMPT_RECALL | 1 | 0 turns off the per-prompt hook |
ANTHROPIC_API_KEY | only for maintain rewrite= | |
VOYAGE_API_KEY | for EMBEDDINGS=voyage |
doctor warns if it isn't private)./mcp resource and to the user's current password and ACL). It's stateless: everything is HMAC-signed, so restarts don't log anyone out. The old secret-in-URL (/mcp/<secret>) is off unless LEGACY_SECRET_URL=1, because URLs end up in proxy logs. Login attempts are rate limited and every response is constant-time.forget removes a line from the current file, but git history keeps it; purging needs a history rewrite.npm ci && npm test # 89 tests: unit, hooks, adopted features, bug regressions, local vault, setup, end-to-end over Streamable HTTP with the official MCP client
npm run bench # token cost of the tool surface
Signed .mcpb releases · usage-aware decay (combine ranking signals with maintain decay) · SSO (GitHub/Google) as an OAuth identity provider for team vaults
MIT licensed. PRs welcome.
This listing does not have a supported local package template. Use the maintainer’s documentation for its hosted endpoint, authentication, and client-specific setup. No install command has been inferred.
https://github.com/AnxovatomicaES/githippo/releases/download/v3.9.3/githippo-3.9.3.mcpbothergithippo works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.