memory
Persistent, cross-device memory for Claude Code projects — syncs via private GitHub Gist so your decisions follow you everywhere.
Without memory, you re-explain the same architecture every session. "We use server components by default." "The API validates with Zod." "Don't touch the legacy auth module." Every. Single. Time. The context window is large, but it resets to zero when a session ends.
Launchpad gives Claude persistent, project-scoped memory that syncs across devices via a private GitHub Gist. Switch laptops, pair on a teammate's machine, or set up a new dev environment. Your architecture decisions, bug patterns, and conventions are already there. You stop repeating yourself. Claude stops asking.
claude-launchpad memoryRunning without flags starts an interactive setup that walks you through installation.
What changes
Once memory is installed, three things happen automatically:
- Session start — Memories from other devices are pulled (if sync is configured), then relevant memories are injected into context based on your current branch, files, and recent work. No manual loading, no "please recall X."
- During sessions — Claude stores decisions, patterns, and insights as it works via MCP tools. CLAUDE.md guides it on what to remember.
- Session end — Memories are pushed to your private GitHub Gist (if sync is configured) so they're available on any machine next session.
The result: Claude remembers your architecture decisions, bug patterns, deployment quirks, and conventions across sessions.
Prerequisites
Memory requires native dependencies that are not bundled with the CLI (to keep install fast for everyone). Install them first:
npm install better-sqlite3 sqlite-vecThis requires a C++ compiler (Xcode on macOS, build-essential on Linux). The CLI will prompt you if these are missing.
Flags and subcommands
| Flag / Subcommand | Description |
|---|---|
--dashboard | Open the interactive memory TUI dashboard |
install | Explicitly (re-)run the install flow — useful when the setup is half-broken or after a purge |
Default behavior
Running claude-launchpad memory without flags uses a smart default:
- If memory is not installed, it starts the interactive installer
- If memory is partially installed (e.g. config written but MCP server not registered, or database missing), it tells you what's wrong and points at
memory install - If memory is fully installed, it shows memory stats
Memory counts as fully installed only when both the SessionStart context hook and the agentic-memory MCP registration are present (checked across .mcp.json, settings.local.json, and ~/.claude.json). Earlier versions only looked at the hook, which could report "healthy" on a setup with no MCP server registered.
claude-launchpad memory --dashboard requires memory to be fully installed first.
What it installs
- SQLite database at
~/.agentic-memory/(shared across projects, scoped per project internally) - SessionStart hook that injects relevant memories at session start. Your hook can call a
.shwrapper instead of running the command directly. Doctor reads one level inside the script, sobash .claude/session-start.shsatisfies the check as long as the script itself runsclaude-launchpad memory context. - SessionStart pull hook and SessionEnd push hook (when sync is configured) for automatic cross-device sync
- 7 MCP tools for storing, searching, and managing memories
- Memory guidance section in CLAUDE.md (or
.claude/CLAUDE.mdfor local placement) /lp-migrate-memoryskill for porting legacy auto-memory files (shared placement only)- MCP server registration via
claude mcp add(project or local scope based on placement)
If auto-registration fails, run the command manually:
# Shared placement (team sees it — creates .mcp.json)
claude mcp add --scope project agentic-memory -- npx claude-launchpad memory serve
# Local placement (only you — writes to ~/.claude.json)
claude mcp add --scope local agentic-memory -- npx claude-launchpad memory serveShared vs local placement
During setup, you choose where memory config lives:
? Where should memory config go?
❯ Shared (team sees it) — CLAUDE.md + settings.json + .mcp.json
Local (only you) — .claude/CLAUDE.md + settings.local.jsonShared (default) writes memory guidance, hooks, and tool permissions to committed project files. The MCP server is registered in .mcp.json (project scope). Your whole team sees the memory setup and gets the approval prompt on first use.
Local writes everything to gitignored files (.claude/CLAUDE.md and .claude/settings.local.json). The MCP server is registered at local scope in ~/.claude.json. Co-devs never see your memory config and can use their own setup (built-in auto-memory, a different MCP server, or nothing).
Your choice is persisted in settings.local.json so doctor --fix applies memory fixes to the correct files without re-asking.
Use local when:
- You share a repo with devs who use different memory setups
- You want to try agentic-memory without affecting the team config
- The project's shared CLAUDE.md is managed by someone else
Memory types
Not all knowledge ages the same way. A bug you fixed last Tuesday matters less next month. Your project's architecture matters for years. Memory types reflect this:
| Type | Half-life | Examples |
|---|---|---|
| working | Session only | Scratch notes, cleared each session |
| episodic | 30 days | Bugs fixed, decisions made, experiments tried |
| semantic | 18 months | Architecture, API contracts, conventions |
| procedural | 2 years | Build steps, deploy commands, environment setup |
| pattern | 6 months | Recurring issues, common solutions |
Claude assigns a type when storing each memory. Short-lived events naturally fade. Core knowledge persists.
MCP tools
These are the tools Claude uses to maintain its knowledge base. You rarely call them directly — Claude uses them as needed during sessions.
| Tool | What it does |
|---|---|
memory_store | Save a memory with type, importance, and tags |
memory_search | Search by keyword with ranked results |
memory_recent | Load recent context-matched memories |
memory_forget | Soft-delete (decay) or hard-delete a memory |
memory_relate | Create typed relations between memories |
memory_stats | Count, types, DB size, top-injected |
memory_update | Modify a memory while preserving access history |
Dashboard
claude-launchpad memory --dashboardTerminal-based memory browser. Shows all stored memories with their type, importance, decay status, and project scope.
Keybindings:
j/k- navigate memory list[/]- switch projects/- search1-5- filter by type (0 = all)l- cycle lifespan filter (healthy/fading/stale)s- cycle sort moder- remove the selected memory permanently (with confirmation)d- purge all memories for the current project permanently (with confirmation). Both are destructive and cannot be undone.p- project picker?- help
Cross-device sync
Push and pull memories between machines. Uses a private GitHub Gist for storage with one file per project. Requires the GitHub CLI (gh) to be installed and authenticated.
# Push current project's memories
claude-launchpad memory push
# Pull current project's memories on another machine
claude-launchpad memory pull
# Push/pull all projects at once
claude-launchpad memory push --all
claude-launchpad memory pull --allPush and pull auto-detect the current project from your working directory. No --project flag needed.
When sync is configured, doctor --fix adds SessionStart and SessionEnd hooks that pull and push automatically. You rarely need to run these commands manually after initial setup.
Gist structure
One private gist holds all your projects, each in its own file:
gist: "agentic-memory sync"
├── memories-my-app.json
├── memories-api-server.json
└── memories-shared-lib.jsonProject-scoped push/pull only touches that project's file. Other projects are never read or modified.
Sync details
First push creates a new private gist. The gist ID is saved to ~/.agentic-memory/sync-config.json.
New device: the gist is auto-discovered from your GitHub account. No config file to copy.
Deleted gist: if the stored gist was deleted from GitHub (via the web UI or gh gist delete), the next sync command detects the 404, clears the stale config, and re-runs discovery. If a fresh gist exists, it reconnects automatically; if not, your next push creates a new one.
Pull-before-push: every push pulls first, so remote changes are never silently overwritten.
Merge strategy: newer version of each memory wins (by updated_at). New memories are inserted, existing ones are updated in place, and relations are added (never removed by the merger).
Deletions follow you across machines. When you delete a memory, Launchpad records the deletion (id, project, time) and includes it in the next push. The other machine applies the deletion on pull, so a hard-delete never comes back. Both machines always converge to the same set — never more, never less.
pull --all skips projects with no local memories (they're listed at the end). To start tracking a new project on this machine, cd into it and run memory pull without --all.
| Subcommand | What it does |
|---|---|
memory push | Push current project's memories |
memory pull | Pull current project's memories |
memory push --all | Push all projects |
memory pull --all | Pull every project already set up on this machine (skips others) |
memory push -y | Skip confirmation prompt (for scripts) |
memory pull -y | No-op — pull never prompts |
memory sync status | Show local vs remote memory counts per project |
memory sync clean <project> | Remove a project from the sync gist |
memory sync clean <project> -y | Skip confirmation prompt |
Push and pull exit non-zero on failure (expired gh auth, network error, 404 on the gist itself). Earlier versions swallowed these errors and exited 0, which made sync drift invisible — now CI and manual invocations see the failure.
Data is validated with Zod on both push and pull. Corrupt or incompatible data is rejected with a clear error.
Migrating from built-in memory
After installing, use /lp-migrate-memory inside Claude Code. It reads your legacy ~/.claude/projects/*/memory/*.md files, deduplicates, and stores them with appropriate types and importance.
Doctor integration
When memory is detected, doctor adds a Memory analyzer that checks:
- MCP server registered (via
.mcp.json, settings, or tool permissions) - SessionStart context hook configured
- SessionStart pull hook configured (when sync is set up)
- SessionEnd push hook configured (when sync is set up)
- Built-in auto-memory disabled
- CLAUDE.md guidance present
- MCP tool permissions set
allowedMcpServers(when present) includesagentic-memory— HIGH severity if missing, becauseclaude mcp addis silently policy-blocked without it
doctor --fix auto-repairs missing permissions and auto-memory settings. The fixer respects your placement choice, writing to the local or shared files accordingly.
How it works under the hood
The sections above cover what memory does for you. This section is for those who want to understand the machinery.
Session injection
At session start, the SessionStart hook scores every candidate memory across six signals and assigns a presentation tier. Memories are packed into a token budget (default 3000 tokens). High-value memories get full content; lower-value ones get summaries or just titles.
| Tier | What Claude sees | When used |
|---|---|---|
| Full | Complete content (up to 500 chars) + tags | Top-scored memories (score > 0.6) |
| Summary | Title + first 350 chars | Mid-scored (score > 0.35) |
| Index | Title + type only | Lower-scored but still relevant |
When the token budget runs low, the algorithm demotes memories to cheaper tiers rather than dropping them entirely. A memory that would normally get full content might appear as a summary instead, fitting more knowledge into the same budget.
Scoring signals
These are listed for transparency. You do not need to configure or think about them.
| Signal | Weight | What it measures |
|---|---|---|
| Context relevance | 30% | Git branch + file overlap with stored context |
| Value signal | 25% | Access-to-injection ratio (searched often = valuable, injected but ignored = noise) |
| Importance | 20% | User-assigned or auto-calculated importance score |
| Recency | 15% | How recently updated, scaled by type (episodic: 7-day half-life, procedural: 90-day half-life) |
| Type bonus | 5% | Procedural and pattern knowledge prioritized over episodic events |
| Noise penalty | 5% | Penalizes memories injected many times without being accessed |
Diversity re-ranking (MMR)
At scale, pure relevance ranking can pack the top slots with near-duplicate memories on the same topic — five pnpm memories crowding out everything else. Injection re-ranks non-pinned candidates with Maximal Marginal Relevance: pick the most relevant, then for each next slot penalize candidates too similar (by content keywords + tags) to what's already chosen. Pinned high-importance memories (≥ 0.8) bypass re-ranking so critical knowledge never loses its seat. Same token budget, more topic coverage.
Self-tuning
The system learns from usage without configuration. When Claude searches for a memory, that memory rises in rank for future sessions. When a memory gets injected repeatedly but Claude never references it, the noise penalty kicks in and it gradually stops appearing. No ML models, no manual tuning — just a feedback loop through the value signal and noise penalty.
Search scoring
When Claude explicitly searches for memories (via memory_search), results use a different scoring formula optimized for keyword relevance:
- Text match (full-text search with relevance ranking) - 35%
- Importance (user-assigned) - 20%
- Recency (exponential decay) - 20%
- Git context (branch + file overlap) - 15%
- Access frequency - 10%