Local memory for the Pi coding agent, so Pi can remember your preferences, project conventions, decisions, and open todos across sessions.
pi-memory keeps long-lived notes in local Markdown, recalls the relevant ones before Pi answers, and redacts common secrets before they are saved. The goal is simple: a new Pi session should start with the context you meant it to remember, without turning memory into an opaque hosted service.
Pi already has compaction for long sessions. That helps continue a long conversation; it does not make a future session remember your stable preferences, project rules, prior decisions, or unresolved todos.
pi-memory fills that gap:
things worth remembering -> local Markdown memory -> private context for future turns
It provides:
- ✍️ Save explicit notes with
/remember. - 🔁 Carry durable facts forward from Pi compaction.
- 📥 Recover useful facts from short sessions with shutdown queue draining.
- 🔦 Recall relevant memory before each answer, privately and automatically.
- 🛡️ Redact common secrets and tokens before saving memory.
- 📄 Keep memory inspectable and editable in Markdown.
- ☂️ Degrade gracefully when recall is unavailable, so Pi can keep working.
- ⏳ Keep maintenance out of the interactive turn with offline cleanup jobs.
- Safer memory writes: common API keys, bearer tokens, private keys, service-account JSON, connection URLs, and
.env-style secrets are redacted before memory is saved. - More reliable recall: when a Pi turn is cancelled, memory lookup is cancelled with it instead of waiting for an internal timeout.
- Clearer status and maintenance output:
/memory-status,pi-memory status, queue draining, and reindex triggers now report more consistent counts. - Healthier foundation for future releases: internals were simplified and split into smaller pieces. This is mostly a maintainer-facing change, but it reduces the risk of future feature work.
Requirements:
- Node.js
>=24 <25 - pnpm
- Pi extension runtime packages supplied by Pi
Install from Pi:
pi install npm:@chendpoc/pi-memoryFor local development from this repository:
pnpm install
pnpm build
pnpm typecheck
pnpm testEnable the extension through Pi's extension loading mechanism. This package declares:
{
"pi": {
"extensions": ["./dist/pi-extension.js"]
}
}Published npm packages ship precompiled dist/; pi install npm:@chendpoc/pi-memory loads the compiled extension entry directly.
You usually do not need to run pi-memory init manually. The memory workspace is prepared automatically and never overwrites a non-empty MEMORY.md:
| When | What happens |
|---|---|
pnpm install |
postinstall runs pi-memory init (or a pre-build fallback) |
| First Pi session | Pi verifies or creates the memory workspace |
| Manual (optional) | pi-memory init |
Run pi-memory init explicitly only when:
- You set
PI_MEMORY_AGENT_DIRafter install (postinstall may have seeded the default path). - Install scripts were skipped (
--ignore-scriptsor corporate policy). - You want to bootstrap before opening Pi, or verify setup with
pi-memory status.
pi-memory init # optional; see above| Situation | Without pi-memory |
With pi-memory |
|---|---|---|
| New session asks "continue the plan from last time" | Agent has to ask for context or guess from the current repo. | Preflight recalls matching MEMORY.md facts and injects private reference context. |
| User says "remember that this repo uses Vitest" | The fact may stay only in the current session summary. | /remember writes a [user] entry that consolidate must preserve. |
| Long session compacts | Compaction helps continue that session but does not create durable cross-session facts. | One dual-purpose compact summary keeps session context and exports durable facts. |
| Subagent is spawned | It may inherit too much context or duplicate the parent session's memory writes. | Subagents receive a smaller scoped memory view by default, reducing noise and duplicate writes. |
| Memory recall is unavailable | A hard dependency would break the turn. | Pi falls back to Markdown or no memory injection; the model still runs. |
| Memory grows | A file can become noisy and unbounded. | 150-line MEMORY.md cap, auto-*.md overflow, consolidate merge/dedupe. |
- 📓 Auditable memory:
MEMORY.mdandauto-*.mdcan be opened, reviewed, edited, grepped, copied, or versioned. - 🔎 Context appears before the answer: Pi gets relevant private memory before the main model responds, so you do not have to manually paste old context.
- 🔒 User notes stay protected:
/rememberentries are marked as user-authored and consolidation must preserve them. - 🛡️ Safer by default: common secrets and tokens are replaced before they reach durable memory.
- ☂️ No hard dependency on recall: if memory recall is empty, slow, or unavailable, the turn still runs.
- 💤 Less interruption: heavier cleanup runs through maintenance jobs instead of blocking ordinary Pi turns.
- 🧹 Bounded growth: the main memory file stays capped, overflow goes into reviewable files, and consolidation merges duplicates.
- 👥 Subagent-aware behavior: root sessions get fuller recall; subagents use a smaller memory view by default to reduce noise.
pi-memory is not trying to be every memory system. The value is a specific Pi-native loop: local Markdown memory, private recall before answers, compaction export, and offline maintenance.
| System | Strength | Difference From @chendpoc/pi-memory |
|---|---|---|
Cursor Rules / OpenCode AGENTS.md |
Static project instructions, predictable injection. | Mostly user-authored rules; no automatic durable fact extraction or memory recall before every answer. |
| Claude Code Auto Memory | Agent can write local memory files. | File-based memory, but no Pi-specific compaction/shutdown integration or private recall-before-answer loop. |
pi-hermes-memory |
Rich Pi package with FTS5, failure memory, correction learning, security scanning. | More automated and feature-heavy; pi-memory is narrower, more Markdown-first, and focused on private pre-answer recall. |
| OpenClaw memory-core | Mature file + index design, dreaming, hybrid search, local embeddings. | Broader memory platform; pi-memory is narrower and Pi-extension focused. |
| Mem0 / Zep | Managed memory APIs with hybrid search, graph, temporal modeling. | Stronger retrieval infrastructure, but external service/database oriented and not Markdown-ground-truth first. |
| Letta | Context engineering with git-backed memory repos and sleep-time compute. | Powerful for autonomous memory management; heavier mental model than Pi's extension lifecycle. |
| Cognee | Knowledge engine with graph/vector/relational stores and many retrieval modes. | Better for knowledge graphs; overkill for lightweight coding-agent preferences and conventions. |
Where other systems are stronger:
pi-hermes-memory: failure memory, correction detector, tool quirks, secret scanning.- OpenClaw: dreaming stages, memory wiki, hybrid FTS/vector search, local embedding providers.
- Zep/Cognee: temporal graph reasoning and multi-hop graph retrieval.
- Mem0: hosted multi-tenant memory API.
- Letta: autonomous context repositories and sleep-time memory work.
These choices are mainly useful for operators and contributors. They explain how the user-facing behavior stays local, inspectable, and bounded.
| Choice | Why it matters |
|---|---|
MEMORY.md as Ground Truth |
Durable memory remains inspectable and editable instead of becoming opaque database state. |
UDS JSONL over node:net |
Local IPC stays private to the machine, avoids HTTP ports, and keeps request/response framing simple. |
| Spawned sidecar process | Vector query/reindex work is isolated from the Pi extension process; failures degrade to Markdown fallback. |
Offline maintenance job |
Consolidation and shutdown-queue draining can run outside the interactive agent turn. |
| Bounded Preflight | QueryIntent, sidecar query, cache, and fallback all share a tight latency budget. |
Pi extension process (MemoryRuntime)
|- session_start
| |- initialize MEMORY.md
| |- start/warm sidecar
| |- reindex derived vector index
| `- preload Memory Cap
|
|- before_agent_start / context
| `- Preflight recall (AbortSignal-aware sidecar query) -> <private_memory>
|
|- /remember
| `- append [user] Memory Entry
|
|- session_before_compact / session_compact
| `- dual-purpose summary -> Memory Export ingest
|
|- session_shutdown
| `- append shutdown metadata only
|
`- consolidate scheduler
`- merge/dedupe -> rewrite Ground Truth -> reindex
Sidecar process over UDS JSONL (`node:net`, no HTTP port)
|- ping
|- stats
|- query: embed -> cosine scan -> MMR
`- reindex: upsert chunks into memory.vec.sqlite
Root session:
Memory Cap from Ground Truth
+ Episodic Preflight for the current user message
-> merged <private_memory>
Subagent session:
Memory Cap only
-> no episodic QueryIntent / sidecar query by default
Fallback chain:
Sidecar results
-> if empty/error/timeout: MEMORY.md fallback
-> if empty: no injection
| Path | Trigger | LLM? | Blocking? | Purpose |
|---|---|---|---|---|
/remember |
User command | No | Yes | Explicit durable note |
| Compaction | session_before_compact + session_compact |
One summary call | Summary blocks; ingest is background | Continue current session and export durable facts |
| Shutdown Queue | session_shutdown + pi-memory maintenance |
Only offline, when no compaction summary exists | No during shutdown | Recover facts from short or missed sessions |
| Consolidate | overflow >= 12, 7 days, or daily cron | Optional | Offline/background | Dedupe, merge, prune obsolete todos |
pi-memory 0.3.0 redacts likely secrets before durable memory entries are written. This applies to every incremental write path that can persist to MEMORY.md, auto-*.md, or the derived vector index.
Covered write paths:
/rememberappend/appendUser/appendIfAbsent/appendMany- compaction
Memory Exportingest - shutdown queue drain ingest
The MVP focuses on secrets and tokens, including common API keys, bearer/JWT values, private-key blocks, service-account JSON, connection URLs, basic-auth URLs, and .env-style secret assignments. Matches are replaced with [REDACTED]; if nothing meaningful remains after redaction, the memory write is skipped instead of persisting a lone placeholder.
Current boundaries:
- Redaction is applied to durable memory entries, not full Pi session JSONL or LLM request bodies.
- Existing historical
MEMORY.mdcontent is not rewritten automatically. - PII detection is intentionally out of scope for 0.3.0.
- Debug logs report hit counts and policy version only; they do not print matched secret material.
For contributors, the shared write gate is prepareEntryForWrite.
All artifacts live under one memory agent directory.
Resolution order:
--agent-dirCLI flagPI_MEMORY_AGENT_DIR- default
~/.pi/pi-memory-data
| File | Role |
|---|---|
MEMORY.md |
Ground Truth file |
auto-*.md |
Overflow files after the 150-line cap |
.memory_gc |
Last consolidate timestamp |
.memory_compactions.json |
Compaction idempotency state |
.memory_shutdown_queue.jsonl |
Append-only shutdown metadata |
.memory_shutdown_processed.json |
Drain idempotency state |
memory.vec.sqlite |
Derived Vector Index |
memory.sock |
Sidecar Unix domain socket |
logs/maintenance.log |
Scheduled maintenance --cron stdout log |
logs/maintenance.err.log |
Scheduled maintenance stderr log (launchd / Windows) |
The logs/ directory is created automatically on extension session_start, pi-memory init, or CLI maintenance/consolidate — no manual mkdir required.
Canonical scaffold: templates/MEMORY.md.example
# Memory
## Preferences
## Conventions
## Findings
## TodosEntries are single Markdown bullets:
- [user] Prefer pnpm over npm <!-- id:abc123 user ts:2026-07-04T09:00:00.000+08:00 -->
- Project tests use Vitest <!-- id:def456 ts:2026-07-04T09:05:00.000+08:00 -->Rules:
/rememberwrites[user]entries.- Consolidate must not remove or rewrite
[user]entries. MEMORY.mdis capped at 150 lines.- Overflow entries spill to
auto-*.md, with a pointer inMEMORY.md. - Vector chunks are derived from entries; by default long entries split beyond
PI_MEMORY_CHUNK_MAX_CHARS=512.
Optional env file locations are loaded in this order:
PI_MEMORY_ENV_FILE- project
.env - project
.env.local ~/.pi/agent/pi-memory.env
Common variables:
| Variable | Default | Purpose |
|---|---|---|
PI_MEMORY_AGENT_DIR |
~/.pi/pi-memory-data |
Memory data root |
PI_MEMORY_EMBEDDER |
hash |
hash, ollama, or openai |
PI_MEMORY_HELPER_MODEL |
deepseek/deepseek-v4-flash |
Helper model spec for QueryIntent and consolidate |
PI_MEMORY_PREFLIGHT_BUDGET_MS |
800 |
Shared Preflight budget, clamped to 250-1500ms |
PI_MEMORY_INTENT_RETRIES |
0 |
Helper LLM retries after the first attempt |
PI_MEMORY_WARM_SIDECAR |
1 |
Warm sidecar at session_start |
PI_MEMORY_INTENT_CACHE |
1 |
Cache QueryIntent per session |
PI_MEMORY_REINDEX_DEBOUNCE_MS |
500 |
Debounce sidecar reindex after writes |
PI_MEMORY_TOP_K |
3 |
Vector recall result count |
PI_MEMORY_MMR_LAMBDA |
0.8 |
MMR relevance/diversity balance |
PI_MEMORY_MIN_RELEVANCE |
0.4 |
Minimum cosine similarity |
PI_MEMORY_CHUNK_MAX_CHARS |
512 |
Split long entries for indexing; 0 disables |
PI_MEMORY_DEBUG |
unset | 1 prints debug timing logs |
PI_MEMORY_SKIP_SCHEDULER_SYNC |
unset | 1 skips scheduler sync while set, including automatic sync and manual scheduler sync |
See .env.example for the full list.
| Embedder | Use When | Notes |
|---|---|---|
hash |
Zero-config local development | Offline, deterministic, lower semantic quality |
ollama |
Local semantic embeddings | Uses PI_MEMORY_OLLAMA_BASE_URL and PI_MEMORY_OLLAMA_EMBED_MODEL |
openai |
Higher-quality cloud embeddings | Requires PI_MEMORY_OPENAI_API_KEY or OPENAI_API_KEY |
The Vector Index stores embedding provider, model, and dimension metadata. When they change, old chunks are cleared and rebuilt.
Inside Pi:
/remember [section] <content>
/memory-status [refresh|expand|collapse|hide]
CLI:
pi-memory status
pi-memory maintenance --cron --verbose
pi-memory consolidate --force --verbose
pi-memory drain-shutdown-queue --verbose
pi-memory init # optional — usually automatic after install + first sessionmaintenance is the recommended scheduler entrypoint:
consolidate -> drain-shutdown-queue
macOS launchd is managed automatically: postinstall, pi-memory init, and every Pi session_start best-effort run scheduler sync (failures do not block install or sessions), writing ~/Library/LaunchAgents/com.pi.memory.maintenance.plist and removing legacy labels (e.g. dev.pi.memory-consolidate). You usually do not edit plists by hand.
Manual trigger or troubleshooting:
pi-memory scheduler sync --verboseIf PI_MEMORY_SKIP_SCHEDULER_SYNC=1 is set in the environment, unset it before running the manual sync command.
Linux / Windows: install from templates manually:
macOS reference plist (matches auto-generated job):
Use /memory-status or pi-memory status to inspect:
- memory agent directory
MEMORY.mdline count- entry count
- overflow count
- last consolidate timestamp
- sidecar socket status
- vector index generation and chunk count
- configured embedder
- index embedder mismatch
Use PI_MEMORY_DEBUG=1 to log Preflight timings:
{
"phase": "preflight",
"event": "recall",
"intent_ms": 0,
"intent_skipped": true,
"intent_cache_hit": false,
"sidecar_ms": 42,
"cache_hit": true,
"total_ms": 45,
"fallback": false,
"results": 3
}- Replacing Pi compaction.
- Replacing session search; use a dedicated session-search extension for old conversations.
- Maintaining a graph database inside this package.
- Making the sidecar authoritative.
- Storing full chat transcripts as memory.
- Adding multi-second reflection to every user turn.
pnpm typecheck
pnpm test
pnpm buildThe sidecar IPC test opens a Unix domain socket. If it fails with listen EPERM inside a restricted sandbox, run the test in a normal local shell.
- Chinese README
- Roadmap
- Launch kit
- UBIQUITOUS_LANGUAGE.md - domain glossary
MIT
