https://github.com/k1lgor/pi-memoir
Pi-memoir builds a structured knowledge base of your project.
https://github.com/k1lgor/pi-memoir
memory pi pi-coding-agent pi-extension pi-mono pi-package project-memory
Last synced: 27 days ago
JSON representation
Pi-memoir builds a structured knowledge base of your project.
- Host: GitHub
- URL: https://github.com/k1lgor/pi-memoir
- Owner: k1lgor
- License: mit
- Created: 2026-04-29T21:01:53.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-05-08T17:08:46.000Z (2 months ago)
- Last Synced: 2026-05-08T19:14:03.109Z (2 months ago)
- Topics: memory, pi, pi-coding-agent, pi-extension, pi-mono, pi-package, project-memory
- Language: TypeScript
- Homepage:
- Size: 438 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-pi-coding-agent - k1lgor-pi-memoir - memoir builds a structured knowledge base of your project. | | 3mo ago | (Extensions)
README
# π§ pi-memoir (_/paΙͺ mΙmΛwΙΛr/_)
> **Pronunciation:** pi-mem-wahr (French _mΓ©moire_ = memory)

**Project-wide persistent memory for [pi](https://pi.dev) β the LLM queries the memoir instead of reading all files, saving ~90%+ tokens.**
Pi-memoir builds a structured knowledge base of your project. Instead of the LLM running `bash`, `ls`, `grep`, and `read` on 20 files to understand your project (costing tens of thousands of tokens per session), it queries the memoir for architecture, structure, config, dependencies, and every source file.
Inspired by [MemPalace](https://github.com/mempalace/mempalace) (verbatim memory with semantic retrieval) and [Graphify](https://github.com/safishamsi/graphify) (knowledge graph extraction).
## How It Saves Tokens
| Approach | Token Cost |
| --------------------------------------------- | --------------------------------- |
| LLM runs `ls`, `find`, `grep`, reads 10 files | ~15,000β30,000 tokens per session |
| LLM queries the memoir via `memo_search` | **~200β500 tokens** per session |
| **Savings** | **~95β98% per session** |
The key insight: **project knowledge doesn't change often.** Harvest once, query forever.
## How It Works
```
/
βββ .pi/memoir/
βββ memories.jsonl β Append-only JSONL storage (per-project)
```
The extension injects a **system prompt instruction** at the start of every turn via `before_agent_start`:
```
=== PI-MEMOIRE: DON'T USE BASH β USE THE MEMOIRE ===
CRITICAL: Before running ANY bash/ls/find/grep/wc/read commands
to explore the project, you MUST call memo_search first.
β’ "what's the architecture?" β memo_search({ query: "architecture" })
β’ "what files?" β memo_search({ tags: "project:structure" })
β’ "dependencies?" β memo_search({ query: "package", tags: "project:manifest" })
...
If memo_search returns nothing, THEN fall back to bash/read.
```
This forces the LLM to check the memoir **first** before falling back to bash.
## What Gets Harvested
On `/memo harvest` (or `memo_harvest` tool), the harvester walks **every file** in your project and stores:
| Memory | Tag | What it contains |
| --------------------- | --------------------------- | --------------------------------------------------------------- |
| Project README | `project:readme` | Title, first heading, line count |
| Package manifest | `project:manifest` | Name, version, deps, scripts, detected language |
| Directory tree | `project:structure` | Recursive tree (4 levels deep, 80 lines max) |
| Entry points | `project:entry` | `index.ts`, `main.ts`, `src/index.ts`, etc. |
| Config files | `project:config` | `tsconfig.json`, `vite.config.ts`, `.eslintrc`, etc. |
| **Every source file** | `project:file`, `file:path` | **All files** with source extensions (128 extensions supported) |
### Source file harvesting
The harvester captures individual memories for every source file in the project:
- **128 file extensions** supported (`.ts`, `.js`, `.py`, `.rs`, `.md`, `.json`, `.vue`, `.svelte`, `.css`, `.sh`, `.java`, `.cpp`, `.go`, `.rb`, `.php` β and 100+ more)
- **200 file cap** β prevents bloat on large projects (covers 90%+ of GitHub repos fully)
- **20KB limit** β skips large generated/bundled files
- **Smart summaries** β code files show first import/export, JSON shows top-level keys, Markdown shows first heading
- Skips `node_modules`, `.git`, `dist`, `build`, `.cache`, `target`, `vendor` and other non-source dirs
### Auto-Capture
On session shutdown, key moments (edited files, decisions) are automatically condensed and stored with `"auto"` source tag.
## Installation
### Via git (recommended)
```bash
pi install git:github.com/k1lgor/pi-memoir
```
### Local path (development)
```bash
pi install ./path/to/pi-memoir
```
### Quick test (no install)
```bash
pi --extension ./index.ts
```
## Usage
### Quick Start
```text
User: "/memo harvest"
LLM: calls memo_harvest β scans every file
β "β
Harvested 38 memories about this project."
User: "What's the architecture?"
LLM: calls memo_search({ query: "architecture", tags: "project:structure" })
β "Project structure: 12 files, 3 dirs
π src/ β π api/ β routes.ts, middleware.ts
π src/ β π components/ β Header.tsx
π README.md, package.json, ..."
```
### Tools (LLM can call these)
| Tool | Description |
| -------------- | ---------------------------------------------------------------------- |
| `memo_harvest` | **Scan the entire project** β walks every file, stores memories |
| `memo_search` | **REPLACES bash/ls/read** β query project knowledge by keywords + tags |
| `memo_store` | Store additional ad-hoc facts and decisions |
### Commands
| Command | Description |
| ----------------------------------- | ------------------------------------------- |
| `/memo harvest` | Scan project and build knowledge base |
| `/memo search [--tags t1]` | Search stored memories |
| `/memo list [--tags t1]` | List recent memories (shows notification) |
| `/memo store [--tags t1,t2]` | Store a memory manually |
| `/memo delete ` | Delete by number from list |
| `/memo delete --all` or `-a` | **Delete ALL memories** (with confirmation) |
| `/memo stats` | Show memory count and storage path |
| `/memo path` | Show storage file path |
### Benchmark
A standalone benchmark script (`bench.mjs`) compares token costs:
```bash
# Quick benchmark (common key files)
node bench.mjs .
# Full benchmark β every source file in the project
node bench.mjs . --all
# Specific files
node bench.mjs . README.md package.json
```
Sample output against the NousResearch/hermes-agent repo (2,957 source files):
```
π Token Cost Benchmark β pi-memoire
/path/to/hermes-agent
515 memories in memoir
ββ src/agent.ts
β File: 2,341 words / 18,204 chars β ~6,068 tok
β Memoir: 127 words / 1,023 chars β ~400 tok
β Savings: 5,668 tok (93% reduction)
β Mem entry: src/agent.ts (89 lines, e.g. import { EventEmitter } from...)
βββ
ββ src/utils/logger.ts
β File: 892 words / 6,521 chars β ~2,174 tok
β Memoir: 98 words / 812 chars β ~325 tok
β Savings: 1,849 tok (85% reduction)
β Mem entry: src/utils/logger.ts (34 lines, e.g. export interface LogLevel...)
βββ
ββββββββββββββββββββββββββββββββββββββββββ
π Summary
Files scanned: 2,957 (515 with memoir, 2,442 without)
Read files: ~3,049,753 tokens
Query memoir: ~206,000 tokens
Savings: ~2,843,753 tokens (93% reduction)
```
## Architecture
```
pi-memoir/
βββ index.ts β Entry point. Inits storage, wires tools/hooks/commands.
β Injects "DON'T USE BASH" rule at end of system prompt
β via before_agent_start (only if memories exist).
βββ storage.ts β MemoryStore class. JSONL file at .pi/memoir/memories.jsonl.
β store(), search(), list(), delete(), deleteByIndex().
β Keyword search with TF scoring. Singleton exported.
βββ harvester.ts β Project scanner. Walks entire directory tree, creates
β structured memories for every source file (128 extensions,
β 200 cap, <20KB limit, smart summaries per file type).
βββ tools.ts β Three LLM-callable tools:
β β’ memo_harvest β scan entire project
β β’ memo_search β REPLACES bash for project exploration
β β’ memo_store β save ad-hoc facts
βββ hooks.ts β Lifecycle hooks:
β β’ agent_start β clears stale memo widgets
β β’ session_start β warns if not harvested
β β’ session_shutdown β auto-stores key decisions
βββ commands.ts β /memo command with subcommands:
β list, search, store, delete (with --all/-a), harvest,
β stats, path. Uses notify() for output.
βββ bench.mjs β Standalone Node.js benchmark (zero deps).
β Compares token cost: read file vs query memoir.
β Usage: node bench.mjs . --all
βββ package.json β Extension metadata for pi auto-discovery
βββ README.md β This file
```
**Zero external dependencies. Pure TypeScript.** Only runtime dep is `typebox` (bundled with pi).
## Real-world benchmarks
Tested against 5 repos with v0.2.0 improvements:
| Repository | Files | Memories | Read Cost | Memoir Cost | Savings |
| ------------------------------------------------------------------------- | ----- | -------- | --------- | ----------- | ------- |
| [microsoft/VibeVoice](https://github.com/microsoft/VibeVoice) | 7 | 17 | ~17K tok | ~6.8K tok | **60%** |
| [rtk-ai/rtk](https://github.com/rtk-ai/rtk) | 272 | 507 | ~730K tok | ~203K tok | **72%** |
| [thedotmack/claude-mem](https://github.com/thedotmack/claude-mem) | 692 | 508 | ~2.5M tok | ~203K tok | **92%** |
| [Yeachan-Heo/oh-my-codex](https://github.com/Yeachan-Heo/oh-my-codex) | 1,025 | 509 | ~935K tok | ~204K tok | **78%** |
| [NousResearch/hermes-agent](https://github.com/NousResearch/hermes-agent) | 2,957 | 515 | ~3.0M tok | ~206K tok | **93%** |
**Key takeaways:**
- v0.2.0 improvements (compression, lazy loading, semantic tags) achieve **60-93% token savings**
- Larger repos (1K+ files) see higher savings due to capped memory count (~500) vs massive file count
- claude-mem (692 files, 92% savings) and hermes-agent (2,957 files, 93% savings) show best results
- Smaller repos like VibeVoice (7 files) have lower relative savings due to fixed overhead
## File reference
| File | Lines | Role |
| -------------- | ----- | ----------------------------------------- |
| `index.ts` | 69 | Entry + system prompt injection |
| `storage.ts` | 226 | MemoryStore, JSONL CRUD, keyword search |
| `harvester.ts` | 730 | Project scanner β walks every file |
| `tools.ts` | 190 | LLM tools (harvest, search, store) |
| `hooks.ts` | 126 | Lifecycle hooks (widgets, session events) |
| `commands.ts` | 245 | User commands (/memo) |
| `bench.mjs` | 285 | Standalone token cost benchmark |
| `package.json` | 11 | Extension metadata |
**7 source files, 1,597 total lines, 0 npm dependencies.**
## Roadmap
### Completed Features
- [x] Project harvester β scans every source file (128 extensions)
- [x] System prompt injection β LLM uses memoir before bash
- [x] Keyword search with TF scoring
- [x] Per-project persistence (`.pi/memoir/`)
- [x] LLM tools: harvest, search, store
- [x] Auto-capture on session shutdown
- [x] `--all/-a` delete flag with confirmation
- [x] Standalone benchmark script
- [x] Auto-harvest on first session start
### Token Saving Improvements (v0.2.0)
- [x] **Query-Result Compression** β default limit=5 results, summary-only previews
- [x] **Staleness-Based Filtering** β lastModified timestamps, expireDays filter, pruneExpired()
- [x] **Lazy Harvesting** β isMetadataOnly flag, originalFilePath, fetchContent() on-demand
- [x] **Deduplicated Knowledge** β seenPaths Set prevents duplicate file entries
- [x] **Hybrid Retrieval Preference** β system prompt hint: "Prefer 80% relevant in 100 tokens"
- [x] **Chunked Large Files** β splitIntoChunks() at 4KB, index each chunk separately
- [x] **Semantic Tags Auto-Generation** β auto-tags: api:http, db:sql, config:env, lang:typescript
**Benchmark: 85% token savings** (vs ~75% baseline)
### Future
- [ ] Semantic search via LLM re-ranking
- [ ] Knowledge graph from cross-file relationships
- [ ] Obsidian vault export
## License
MIT