{"id":50233884,"url":"https://github.com/k1lgor/pi-memoir","last_synced_at":"2026-06-20T19:01:45.652Z","repository":{"id":356579084,"uuid":"1224999198","full_name":"k1lgor/pi-memoir","owner":"k1lgor","description":"Pi-memoir builds a structured knowledge base of your project.","archived":false,"fork":false,"pushed_at":"2026-05-08T17:08:46.000Z","size":448,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-08T19:14:03.109Z","etag":null,"topics":["memory","pi","pi-coding-agent","pi-extension","pi-mono","pi-package","project-memory"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/k1lgor.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-29T21:01:53.000Z","updated_at":"2026-05-08T17:08:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/k1lgor/pi-memoir","commit_stats":null,"previous_names":["k1lgor/pi-memoir"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/k1lgor/pi-memoir","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1lgor%2Fpi-memoir","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1lgor%2Fpi-memoir/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1lgor%2Fpi-memoir/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1lgor%2Fpi-memoir/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/k1lgor","download_url":"https://codeload.github.com/k1lgor/pi-memoir/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1lgor%2Fpi-memoir/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34581934,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-20T02:00:06.407Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["memory","pi","pi-coding-agent","pi-extension","pi-mono","pi-package","project-memory"],"created_at":"2026-05-26T19:00:32.272Z","updated_at":"2026-06-20T19:01:45.646Z","avatar_url":"https://github.com/k1lgor.png","language":"TypeScript","funding_links":[],"categories":["Extensions"],"sub_categories":[],"readme":"# 🧠 pi-memoir (_/paɪ mɛmˈwɑːr/_)\n\n\u003e **Pronunciation:** pi-mem-wahr (French _mémoire_ = memory)\n\n![pi-memoir Hero](docs/assets/logo.png)\n\n**Project-wide persistent memory for [pi](https://pi.dev) — the LLM queries the memoir instead of reading all files, saving ~90%+ tokens.**\n\nPi-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.\n\nInspired by [MemPalace](https://github.com/mempalace/mempalace) (verbatim memory with semantic retrieval) and [Graphify](https://github.com/safishamsi/graphify) (knowledge graph extraction).\n\n## How It Saves Tokens\n\n| Approach                                      | Token Cost                        |\n| --------------------------------------------- | --------------------------------- |\n| LLM runs `ls`, `find`, `grep`, reads 10 files | ~15,000–30,000 tokens per session |\n| LLM queries the memoir via `memo_search`      | **~200–500 tokens** per session   |\n| **Savings**                                   | **~95–98% per session**           |\n\nThe key insight: **project knowledge doesn't change often.** Harvest once, query forever.\n\n## How It Works\n\n```\n\u003cyour-project\u003e/\n└── .pi/memoir/\n    └── memories.jsonl    ← Append-only JSONL storage (per-project)\n```\n\nThe extension injects a **system prompt instruction** at the start of every turn via `before_agent_start`:\n\n```\n=== PI-MEMOIRE: DON'T USE BASH — USE THE MEMOIRE ===\nCRITICAL: Before running ANY bash/ls/find/grep/wc/read commands\nto explore the project, you MUST call memo_search first.\n• \"what's the architecture?\" → memo_search({ query: \"architecture\" })\n• \"what files?\" → memo_search({ tags: \"project:structure\" })\n• \"dependencies?\" → memo_search({ query: \"package\", tags: \"project:manifest\" })\n...\nIf memo_search returns nothing, THEN fall back to bash/read.\n```\n\nThis forces the LLM to check the memoir **first** before falling back to bash.\n\n## What Gets Harvested\n\nOn `/memo harvest` (or `memo_harvest` tool), the harvester walks **every file** in your project and stores:\n\n| Memory                | Tag                         | What it contains                                                |\n| --------------------- | --------------------------- | --------------------------------------------------------------- |\n| Project README        | `project:readme`            | Title, first heading, line count                                |\n| Package manifest      | `project:manifest`          | Name, version, deps, scripts, detected language                 |\n| Directory tree        | `project:structure`         | Recursive tree (4 levels deep, 80 lines max)                    |\n| Entry points          | `project:entry`             | `index.ts`, `main.ts`, `src/index.ts`, etc.                     |\n| Config files          | `project:config`            | `tsconfig.json`, `vite.config.ts`, `.eslintrc`, etc.            |\n| **Every source file** | `project:file`, `file:path` | **All files** with source extensions (128 extensions supported) |\n\n### Source file harvesting\n\nThe harvester captures individual memories for every source file in the project:\n\n- **128 file extensions** supported (`.ts`, `.js`, `.py`, `.rs`, `.md`, `.json`, `.vue`, `.svelte`, `.css`, `.sh`, `.java`, `.cpp`, `.go`, `.rb`, `.php` — and 100+ more)\n- **200 file cap** — prevents bloat on large projects (covers 90%+ of GitHub repos fully)\n- **20KB limit** — skips large generated/bundled files\n- **Smart summaries** — code files show first import/export, JSON shows top-level keys, Markdown shows first heading\n- Skips `node_modules`, `.git`, `dist`, `build`, `.cache`, `target`, `vendor` and other non-source dirs\n\n### Auto-Capture\n\nOn session shutdown, key moments (edited files, decisions) are automatically condensed and stored with `\"auto\"` source tag.\n\n## Installation\n\n### Via git (recommended)\n\n```bash\npi install git:github.com/k1lgor/pi-memoir\n```\n\n### Local path (development)\n\n```bash\npi install ./path/to/pi-memoir\n```\n\n### Quick test (no install)\n\n```bash\npi --extension ./index.ts\n```\n\n## Usage\n\n### Quick Start\n\n```text\nUser: \"/memo harvest\"\nLLM: calls memo_harvest → scans every file\n→ \"✅ Harvested 38 memories about this project.\"\n\nUser: \"What's the architecture?\"\nLLM: calls memo_search({ query: \"architecture\", tags: \"project:structure\" })\n→ \"Project structure: 12 files, 3 dirs\n     📁 src/ → 📁 api/ → routes.ts, middleware.ts\n     📁 src/ → 📁 components/ → Header.tsx\n     📄 README.md, package.json, ...\"\n```\n\n### Tools (LLM can call these)\n\n| Tool           | Description                                                            |\n| -------------- | ---------------------------------------------------------------------- |\n| `memo_harvest` | **Scan the entire project** — walks every file, stores memories        |\n| `memo_search`  | **REPLACES bash/ls/read** — query project knowledge by keywords + tags |\n| `memo_store`   | Store additional ad-hoc facts and decisions                            |\n\n### Commands\n\n| Command                             | Description                                 |\n| ----------------------------------- | ------------------------------------------- |\n| `/memo harvest`                     | Scan project and build knowledge base       |\n| `/memo search \u003cquery\u003e [--tags t1]`  | Search stored memories                      |\n| `/memo list [--tags t1]`            | List recent memories (shows notification)   |\n| `/memo store \u003ctext\u003e [--tags t1,t2]` | Store a memory manually                     |\n| `/memo delete \u003cnumber\u003e`             | Delete by number from list                  |\n| `/memo delete --all` or `-a`        | **Delete ALL memories** (with confirmation) |\n| `/memo stats`                       | Show memory count and storage path          |\n| `/memo path`                        | Show storage file path                      |\n\n### Benchmark\n\nA standalone benchmark script (`bench.mjs`) compares token costs:\n\n```bash\n# Quick benchmark (common key files)\nnode bench.mjs .\n\n# Full benchmark — every source file in the project\nnode bench.mjs . --all\n\n# Specific files\nnode bench.mjs . README.md package.json\n```\n\nSample output against the NousResearch/hermes-agent repo (2,957 source files):\n\n```\n📊 Token Cost Benchmark — pi-memoire\n   /path/to/hermes-agent\n   515 memories in memoir\n\n  ┌─ src/agent.ts\n  │ File:        2,341 words / 18,204 chars → ~6,068 tok\n  │ Memoir:     127 words / 1,023 chars → ~400 tok\n  │ Savings:     5,668 tok (93% reduction)\n  │ Mem entry:   src/agent.ts (89 lines, e.g. import { EventEmitter } from...)\n  └──\n\n  ┌─ src/utils/logger.ts\n  │ File:        892 words / 6,521 chars → ~2,174 tok\n  │ Memoir:     98 words / 812 chars → ~325 tok\n  │ Savings:     1,849 tok (85% reduction)\n  │ Mem entry:   src/utils/logger.ts (34 lines, e.g. export interface LogLevel...)\n  └──\n\n══════════════════════════════════════════\n📈 Summary\n  Files scanned:    2,957 (515 with memoir, 2,442 without)\n  Read files:       ~3,049,753 tokens\n  Query memoir:     ~206,000 tokens\n  Savings:          ~2,843,753 tokens (93% reduction)\n```\n\n## Architecture\n\n```\npi-memoir/\n├── index.ts       ← Entry point. Inits storage, wires tools/hooks/commands.\n│                      Injects \"DON'T USE BASH\" rule at end of system prompt\n│                      via before_agent_start (only if memories exist).\n├── storage.ts     ← MemoryStore class. JSONL file at .pi/memoir/memories.jsonl.\n│                      store(), search(), list(), delete(), deleteByIndex().\n│                      Keyword search with TF scoring. Singleton exported.\n├── harvester.ts   ← Project scanner. Walks entire directory tree, creates\n│                      structured memories for every source file (128 extensions,\n│                      200 cap, \u003c20KB limit, smart summaries per file type).\n├── tools.ts       ← Three LLM-callable tools:\n│                      • memo_harvest — scan entire project\n│                      • memo_search  — REPLACES bash for project exploration\n│                      • memo_store   — save ad-hoc facts\n├── hooks.ts       ← Lifecycle hooks:\n│                      • agent_start → clears stale memo widgets\n│                      • session_start → warns if not harvested\n│                      • session_shutdown → auto-stores key decisions\n├── commands.ts    ← /memo command with subcommands:\n│                      list, search, store, delete (with --all/-a), harvest,\n│                      stats, path. Uses notify() for output.\n├── bench.mjs      ← Standalone Node.js benchmark (zero deps).\n│                      Compares token cost: read file vs query memoir.\n│                      Usage: node bench.mjs . --all\n├── package.json   ← Extension metadata for pi auto-discovery\n└── README.md      ← This file\n```\n\n**Zero external dependencies. Pure TypeScript.** Only runtime dep is `typebox` (bundled with pi).\n\n## Real-world benchmarks\n\nTested against 5 repos with v0.2.0 improvements:\n\n| Repository                                                                | Files | Memories | Read Cost | Memoir Cost | Savings |\n| ------------------------------------------------------------------------- | ----- | -------- | --------- | ----------- | ------- |\n| [microsoft/VibeVoice](https://github.com/microsoft/VibeVoice)             | 7     | 17       | ~17K tok  | ~6.8K tok   | **60%** |\n| [rtk-ai/rtk](https://github.com/rtk-ai/rtk)                               | 272   | 507      | ~730K tok | ~203K tok   | **72%** |\n| [thedotmack/claude-mem](https://github.com/thedotmack/claude-mem)         | 692   | 508      | ~2.5M tok | ~203K tok   | **92%** |\n| [Yeachan-Heo/oh-my-codex](https://github.com/Yeachan-Heo/oh-my-codex)     | 1,025 | 509      | ~935K tok | ~204K tok   | **78%** |\n| [NousResearch/hermes-agent](https://github.com/NousResearch/hermes-agent) | 2,957 | 515      | ~3.0M tok | ~206K tok   | **93%** |\n\n**Key takeaways:**\n\n- v0.2.0 improvements (compression, lazy loading, semantic tags) achieve **60-93% token savings**\n- Larger repos (1K+ files) see higher savings due to capped memory count (~500) vs massive file count\n- claude-mem (692 files, 92% savings) and hermes-agent (2,957 files, 93% savings) show best results\n- Smaller repos like VibeVoice (7 files) have lower relative savings due to fixed overhead\n\n## File reference\n\n| File           | Lines | Role                                      |\n| -------------- | ----- | ----------------------------------------- |\n| `index.ts`     | 69    | Entry + system prompt injection           |\n| `storage.ts`   | 226   | MemoryStore, JSONL CRUD, keyword search   |\n| `harvester.ts` | 730   | Project scanner — walks every file        |\n| `tools.ts`     | 190   | LLM tools (harvest, search, store)        |\n| `hooks.ts`     | 126   | Lifecycle hooks (widgets, session events) |\n| `commands.ts`  | 245   | User commands (/memo)                     |\n| `bench.mjs`    | 285   | Standalone token cost benchmark           |\n| `package.json` | 11    | Extension metadata                        |\n\n**7 source files, 1,597 total lines, 0 npm dependencies.**\n\n## Roadmap\n\n### Completed Features\n\n- [x] Project harvester — scans every source file (128 extensions)\n- [x] System prompt injection — LLM uses memoir before bash\n- [x] Keyword search with TF scoring\n- [x] Per-project persistence (`.pi/memoir/`)\n- [x] LLM tools: harvest, search, store\n- [x] Auto-capture on session shutdown\n- [x] `--all/-a` delete flag with confirmation\n- [x] Standalone benchmark script\n- [x] Auto-harvest on first session start\n\n### Token Saving Improvements (v0.2.0)\n\n- [x] **Query-Result Compression** — default limit=5 results, summary-only previews\n- [x] **Staleness-Based Filtering** — lastModified timestamps, expireDays filter, pruneExpired()\n- [x] **Lazy Harvesting** — isMetadataOnly flag, originalFilePath, fetchContent() on-demand\n- [x] **Deduplicated Knowledge** — seenPaths Set prevents duplicate file entries\n- [x] **Hybrid Retrieval Preference** — system prompt hint: \"Prefer 80% relevant in 100 tokens\"\n- [x] **Chunked Large Files** — splitIntoChunks() at 4KB, index each chunk separately\n- [x] **Semantic Tags Auto-Generation** — auto-tags: api:http, db:sql, config:env, lang:typescript\n\n**Benchmark: 85% token savings** (vs ~75% baseline)\n\n### Future\n\n- [ ] Semantic search via LLM re-ranking\n- [ ] Knowledge graph from cross-file relationships\n- [ ] Obsidian vault export\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk1lgor%2Fpi-memoir","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fk1lgor%2Fpi-memoir","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk1lgor%2Fpi-memoir/lists"}