@yandy0725/pi-memory
File-system driven persistent memory layer for pi coding agent
Package details
Install @yandy0725/pi-memory from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@yandy0725/pi-memory- Package
@yandy0725/pi-memory- Version
1.3.4- Published
- Jul 15, 2026
- Downloads
- 811/mo · 401/wk
- Author
- yandy0725
- License
- MIT
- Types
- extension
- Size
- 82.6 KB
- Dependencies
- 0 dependencies · 4 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-memory
File-system driven persistent memory layer for pi coding agent. Stores project knowledge across sessions — facts, preferences, debugging history — in plain Markdown files under ~/.pi/memory/<project-hash>/.
Aligned with Claude Code's auto memory mechanism: per-topic MEMORY.md index, automatic topic file surfacing based on relevance, per-turn memory extraction, and typed memory categories.
Features
- One
memorytool, three actions:add(append entry),remove(delete entry by title),search(query memory or session history) - Topic-based file organization: each
memory addwrites a## entryblock to a named.mdfile under the project's memory directory MEMORY.mdindex — one compact line per topic file with a relevance hook:- [Name](file.md) — summary- Memory types: four categories —
user,feedback(default),project,reference— stored in topic file frontmatter - Auto-surfacing ⭐: on every user message, a side-query LLM selects up to N relevant topic files and injects their content into the agent's context. No manual
readneeded — use the built-inreadtool to inspect memory files. Session-level deduplication prevents re-injecting the same topic. - Extract memories ⭐: after each agent run, an async subagent analyzes the conversation and automatically writes learnings to memory — preferences, conventions, debugging insights
- Snapshot injection: on every new session, the MEMORY.md index is appended to the system prompt, keeping the agent aware of past work
/dreamcommand: launches a headless agent with a four-phase consolidation (Orient → Gather → Consolidate → Prune) to deduplicate, merge, and rebuild all memory files- Dream nudge: after N sessions or N hours, a gentle notification suggests running
/dream /memorycommand: show status, toggle on/off, inspect index and topic files- Session search: the
memory search scope=sessionsaction queries past conversation history - Branch-safe: memory directory is keyed by the git root (or absolute path), so forks share memory naturally
- Path traversal protection: topic files are validated against escaping the memory directory
Install
pi install npm:@yandy0725/pi-memory
Or add to ~/.pi/agent/settings.json:
{
"packages": ["npm:@yandy0725/pi-memory"]
}
Configuration
Create memory.json in the agent directory (~/.pi/agent/memory.json) or the project .pi/ directory (if trusted):
{
"enabled": true,
"memoryDir": "~/.pi/memory",
"memIndexMaxLines": 200,
"memIndexMaxBytes": 25600,
"defaults": {
"model": "deepseek/deepseek-v4-flash",
"sessionPersistence": { "enabled": false }
},
"dream": {
"nudgeAfterSessions": 5,
"nudgeAfterHours": 24,
"model": "auto",
"thinkLevel": "high",
"sessionPersistence": { "enabled": false }
},
"sessionSearch": {
"maxSessions": 10,
"maxMatches": 5
},
"autoSurfacing": {
"enabled": true,
"model": "auto",
"thinkLevel": "off",
"maxFiles": 5,
"maxTopicBytes": 4096,
"maxInjectionBytes": 20480,
"sessionPersistence": { "enabled": false }
},
"extractMemories": {
"enabled": true,
"model": "auto",
"thinkLevel": "high",
"maxContextTokens": 2000,
"sessionPersistence": { "enabled": false }
}
}
| Key | Default | Description |
|---|---|---|
enabled |
true |
Toggle the entire memory system on/off |
memoryDir |
~/.pi/memory |
Root directory for all memory data |
memIndexMaxLines |
200 |
Max lines in MEMORY.md before capacity errors |
memIndexMaxBytes |
25600 |
Max bytes in MEMORY.md before capacity errors |
defaults.model |
— | Shared model fallback for all sub-tasks. Per-task model overrides |
defaults.sessionPersistence.enabled |
false |
Shared session persistence fallback (default: in-memory). Per-task overrides |
defaults.sessionPersistence.sessionDir |
memoryDir/sessions/ |
Custom session directory for persisted headless agent sessions |
dream.nudgeAfterSessions |
5 |
Sessions since last dream before nudge is shown |
dream.nudgeAfterHours |
24 |
Hours since last dream before nudge is shown |
dream.model |
— | Model for dream consolidation ("provider/id"). Falls back to defaults.model → parent model |
dream.thinkLevel |
"high" |
Thinking effort for dream subagent: "off", "minimal", "low", "medium", "high", "xhigh" |
dream.sessionPersistence.enabled |
false |
Persist dream agent sessions to disk (debug/audit). Falls back to defaults.sessionPersistence.enabled |
dream.sessionPersistence.sessionDir |
memoryDir/sessions/ |
Custom session directory for dream sessions |
sessionSearch.maxSessions |
10 |
Max sessions to scan when searching history |
sessionSearch.maxMatches |
5 |
Max matches to return from history search |
autoSurfacing.enabled |
true |
⭐ Enable per-turn topic file auto-injection |
autoSurfacing.model |
— | ⭐ Model for side-query relevance selection. Falls back to defaults.model → parent model |
autoSurfacing.thinkLevel |
"off" |
⭐ Thinking effort for side-query (recommended: "off" for lightweight selection) |
autoSurfacing.sessionPersistence.enabled |
false |
Persist side-query agent sessions to disk. Falls back to defaults.sessionPersistence.enabled |
autoSurfacing.maxFiles |
5 |
⭐ Max topic files to inject per turn |
autoSurfacing.maxTopicBytes |
4096 |
⭐ Max bytes per injected topic file (truncated) |
autoSurfacing.maxInjectionBytes |
20480 |
⭐ Max total bytes of injected content per turn |
extractMemories.enabled |
true |
⭐ Enable per-turn memory extraction |
extractMemories.model |
— | ⭐ Model for the extraction subagent. Falls back to defaults.model → parent model |
extractMemories.thinkLevel |
"high" |
⭐ Thinking effort for extraction: "off" / "minimal" / "low" / "medium" / "high" / "xhigh" |
extractMemories.sessionPersistence.enabled |
false |
Persist extract agent sessions to disk. Falls back to defaults.sessionPersistence.enabled |
extractMemories.maxContextTokens |
2000 |
⭐ Max tokens of conversation to analyze |
Project-level config (.pi/memory.json) is only loaded when the project is trusted.
How it works
MEMORY.md index
MEMORY.md is a compact pointer index — one line per topic file, not per entry:
- [Debugging](debugging.md) — SSH uses port 2222; MySQL 30s timeout on staging
- [API Conventions](api.md) — REST handlers in src/api/handlers/; standard error format
Only the index is injected into the system prompt on every session (first 200 lines / 25KB). Topic file content is not loaded at session start — it's surfaced on demand via auto-surfacing or the built-in read tool.
Topic file format
Each topic file uses YAML frontmatter with four fields:
---
name: Debugging Tips
description: Common debugging patterns, SSH ports, MySQL timeout configs
type: feedback
updated: 2026-07-13
---
## SSH Gotcha
staging uses port 2222, key at ~/.ssh/staging
## MySQL Timeout
connection timeout after 30s on staging
The description field is critical — the auto-surfacing side-query uses it to determine relevance. Make it specific.
Memory types
| Type | Meaning | Example |
|---|---|---|
user |
User role, preferences, knowledge | "User is a data scientist focused on observability" |
feedback |
Lessons, corrections, confirmations (default) | "Use real DB not mocks — burned last quarter" |
project |
Project state, deadlines, incidents | "Merge freeze starts 2026-03-05 for mobile release" |
reference |
Pointers to external systems | "Bug tracker = Linear INGEST project" |
Auto-surfacing
On every user message (before_agent_start hook):
- Scan all topic files, extract their frontmatter metadata
- A side-query LLM selects up to
maxFilesrelevant topic files based on the user's query - Already-injected topics are skipped (session-level dedup)
- Selected topic file content is injected as context — the agent sees relevant memories automatically
Extract memories
After each agent run (agent_end hook):
- An async headless subagent is spawned with the conversation transcript
- It uses
lsandreadto check existing topic files and MEMORY.md, thenmemory_addto persist learnings - If it finds learnings worth persisting, it writes them — preferences, conventions, debugging insights
- The subagent runs independently; its results benefit future sessions
Memory extraction is selective: it ignores one-time tasks, code snippets derivable from the project, and anything already in CLAUDE.md.
Tool reference
memory(action: "add" | "remove" | "search",
content?, topic?, title?, type?,
entry?, query?, scope?)
add
Appends a ## entry block to a topic file. If the topic already exists in the index, the MEMORY.md hook is updated to summarize all entries. For new topics, a new index line is created.
content(required) — knowledge text to persisttopic(required) — target filename, e.g."debugging.md". Auto-created if newtitle(required) — descriptive, self-contained title for the entry. Only the MEMORY.md index line is injected into future prompts (topic file content is NOT), so the title alone must convey what was learnedtype(optional) — memory category:"user","feedback"(default),"project","reference"
remove
Deletes an entry by title. Searches across all topic files for the matching ## block. Updates the MEMORY.md hook for the affected topic. When the last entry in a topic is removed, the topic file and its index line are deleted.
entry(required) — exact entry title to remove
search
Queries either memory files or session history. Memory search returns the full entry block (entire ## section) for each match.
query(required) — search keywordscope(optional) —"memory"(default, scans topic files) or"sessions"(scans session history)
Commands
/memory
Show memory status (enabled/disabled, directory, index line count, topic files, last dream timestamp).
/memory — show status
/memory on — enable memory
/memory off — disable memory
/dream
Launch a headless agent that reads all memory files and consolidates them in four phases:
- Orient — list files, read MEMORY.md, skim topic files
- Gather Signal — find duplicates, contradictions, outdated entries
- Consolidate — merge duplicates, resolve contradictions, update dates
- Prune & Index — rebuild frontmatter, generate hooks, rebuild MEMORY.md
The model used can be configured via dream.model in memory.json.
A confirmation dialog is shown before the consolidation begins. The result summary is shown as a notification when done.
File layout
~/.pi/memory/
<12-char-sha256>/
MEMORY.md — compact index: one line per topic file
.dream-meta.json — last dream timestamp + session count
debugging.md — topic files with frontmatter + ## entries
preferences.md
...
The hash is derived from the project's git root (or absolute path), ensuring each project gets its own memory namespace.
Snapshot semantics
On every session_start, the MEMORY.md index is read and appended to the system prompt via before_agent_start. If the index exceeds memIndexMaxLines or memIndexMaxBytes, it is truncated with a [truncated] marker — the agent still gets the most relevant portion. This snapshot is a static copy at the start of the session.
Topic file content is surfaced separately via auto-surfacing (automatic, per-turn, relevance-based) or the built-in read tool.