Persistent, self-managing memory for the pi coding agent
⭐ If you like this project, star it on GitHub — it helps a lot!
Features • Installation • Usage • Configuration • Architecture • Troubleshooting
@aprimediet/memory gives the pi coding agent a persistent memory system that survives across sessions. It remembers durable facts, decisions, progress, and preferences — and keeps them organized by project scope.
The working tree stays clean: the only file written into <cwd>/.pi is a single <project-id>.md marker. All memory artifacts live globally under ~/.pi/projects/<project-id>/, with a reserved ~/.pi/projects/_global/ for cross-project ("global") memory.
- Persistent Memory — Save and recall durable facts, decisions, progress, and preferences across sessions
- Dual Scope —
projectscope for repo-specific memory,globalscope for cross-project knowledge - Background Distillation — Automatically distills session transcripts into durable memory entries in the background
- Smart Search — Keyword search over memory entries with optional SQLite FTS5 acceleration
- Heuristic Pruning — Automatic cleanup of stale, unused, or superseded entries
- Timeline Widget — Visual timeline of memory entries shown at session start
- Context Injection — Top memory entries are injected as hidden context at session start
- Clean Working Tree — All storage is global; the working tree only holds a project marker
pi install npm:@aprimediet/memoryNo manual npm install or settings.json edit needed. The extension registers automatically.
| Tool | Parameters | Description |
|---|---|---|
memory_write |
scope, type, text, tags? |
Save a durable fact/decision to persistent memory |
memory_search |
query, scope?, limit? |
Search memory for keywords or questions |
memory_forget |
id?, query?, scope? |
Archive (soft-delete) entries by id or keywords |
/memory status — Show config, entry counts, pruning settings, FTS status
/memory timeline — Show or reshow the memory timeline widget
/memory list [scope] — List entries (default: project scope)
/memory search <q> — Search all memory
/memory prune — Heuristic prune + background consolidation
/memory forget <id> — Archive a specific entry
/memory distill — Manually trigger session distillation
Config lives in ~/.pi/projects/<id>/memory.json (NOT in the working tree). Precedence:
bundled default (memory.json in package)
→ global default (~/.pi/agent/memory.json)
→ per-project (~/.pi/projects/<id>/memory.json)
→ env (MEMORY_MODEL / MEMORY_DISABLED)
→ flags
Default values:
enabled: truemodel: "claude-haiku-4-5"capture: "both"(tool + background)injection.scope: "both",digestMaxEntries: 20pruning.ttlDays: 90,maxEntries: 200,consolidateEverySessions: 10useFtsIndex: false
- Source of truth: Markdown files with frontmatter (
id,type,scope,created,lastUsed,useCount,tags,source,supersedes,status) + body text - Derived index:
MEMORY.mdis rebuilt on every write; not the source of truth - SQLite FTS: Optional accelerator (
memory.db); best-effort — falls back to plain file keyword scan ifbetter-sqlite3is missing
The distiller spawns a pi subprocess in headless JSON mode (--mode json --no-session) with a system prompt. Uses MEMORY_INTERNAL env var to prevent recursive re-entrance. Session transcripts are enqueued at session_shutdown and drained at the next session_start for that project. Consolidation runs every N sessions (consolidateEverySessions default: 10).
Deterministic from project root path: <slug>-<sha1-hash> (first 8 hex chars). If a marker file already exists with an id, that id wins (stable across renames). Marker file: <cwd>/.pi/<id>.md with frontmatter pi-project: true.
- Resolve superseded entries
- Archive never-used entries older than
ttlDays(default: 90) - LRU cap at
maxEntries(default: 200)
Tip
Check /memory status for a quick health check of your memory setup.
- No memories found: Verify the extension is enabled (
/memory statusshowsenabled: true). - FTS not working: Install
better-sqlite3(optional dependency). Check/memory statusfor "enabled (better-sqlite3 missing → file scan)". - Distillation not happening: Ensure
captureis not"tool"and the model flag is set correctly. - Recursive distiller crash: The
MEMORY_INTERNALenv guard prevents this. If it still happens, check the spawned process invocation path. - Timeline widget not showing: Verify
ctx.hasUIis true and the extension is enabled. - Entry duplicates:
findDuplicateuses Jaccard similarity ≥ 0.85 on normalized text.
- Pi Coding Agent — The agent this extension is built for
- TypeBox — Runtime type validation used for tool parameters
- better-sqlite3 — Optional SQLite FTS accelerator