{"id":47787940,"url":"https://github.com/avanrossum/pmem-project-memory-tool-for-claude-code","last_synced_at":"2026-04-03T15:04:56.456Z","repository":{"id":347058801,"uuid":"1191845712","full_name":"avanrossum/pmem-project-memory-tool-for-claude-code","owner":"avanrossum","description":"Local-first RAG memory for Claude Code. Semantic search over your project's docs, decisions, and history. No external APIs. Setup in 2 minutes.","archived":false,"fork":false,"pushed_at":"2026-03-26T15:08:14.000Z","size":103,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-27T05:34:46.530Z","etag":null,"topics":["ai-tools","anthropic","chromadb","claude","claude-code","developer-tools","local-llm","mcp","memory","model-context-protocol","ollama","rag","semantic-search","vector-search"],"latest_commit_sha":null,"homepage":null,"language":"Python","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/avanrossum.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":"ROADMAP.md","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-03-25T16:34:58.000Z","updated_at":"2026-03-26T15:10:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/avanrossum/pmem-project-memory-tool-for-claude-code","commit_stats":null,"previous_names":["avanrossum/pmem-project-memory-tool-for-claude-code"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/avanrossum/pmem-project-memory-tool-for-claude-code","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avanrossum%2Fpmem-project-memory-tool-for-claude-code","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avanrossum%2Fpmem-project-memory-tool-for-claude-code/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avanrossum%2Fpmem-project-memory-tool-for-claude-code/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avanrossum%2Fpmem-project-memory-tool-for-claude-code/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/avanrossum","download_url":"https://codeload.github.com/avanrossum/pmem-project-memory-tool-for-claude-code/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avanrossum%2Fpmem-project-memory-tool-for-claude-code/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31359104,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T14:24:47.623Z","status":"ssl_error","status_checked_at":"2026-04-03T14:24:32.380Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["ai-tools","anthropic","chromadb","claude","claude-code","developer-tools","local-llm","mcp","memory","model-context-protocol","ollama","rag","semantic-search","vector-search"],"created_at":"2026-04-03T15:04:41.999Z","updated_at":"2026-04-03T15:04:56.350Z","avatar_url":"https://github.com/avanrossum.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pmem — Project Memory Tool\n\nA portable, local-first RAG memory layer for [Claude Code](https://docs.anthropic.com/en/docs/claude-code) projects. Gives Claude semantic search over your project's documentation, decisions, and history — using local models, with no external API dependencies.\n\nThink of it as long-term memory that persists across Claude Code sessions, queryable via MCP.\n\n## Why this exists\n\nI use Claude Code for more than writing code. I run specialized agents that maintain context across infrastructure, documentation, content pipelines, and operational workflows — sometimes six or more projects simultaneously. Each project accumulates hundreds of markdown files: architecture decisions, task logs, lessons learned, archived roadmaps.\n\nGrepping through all of that wastes tokens and misses semantic matches. \"What did we decide about the auth flow?\" doesn't match \"JWT was chosen over session tokens because...\" — not with grep, anyway.\n\nSo I built institutional memory for AI agents. pmem indexes your project's documentation into a local vector store, and Claude queries it by meaning instead of by keyword. No data leaves your machine. Setup takes two minutes.\n\nRead more about the methodology behind this: [Cognitive Offloading](https://mipyip.com/blog/cognitive-offloading) and [The Governance Documents](https://mipyip.com/blog/the-governance-documents).\n\n### How pmem differs from session memory tools\n\nMost Claude Code memory tools — claude-mem, claude-brain, supermemory — solve session continuity: what did Claude do last time? They capture Claude's actions, compress conversation history, and replay it into future sessions.\n\npmem solves a different problem: **what does the project know?**\n\nYour project has architecture decisions, task logs, lessons learned, archived roadmaps, and governance documents accumulated over months. That institutional knowledge exists in files, not in session transcripts. When you ask \"why did we choose this auth approach?\" the answer isn't in what Claude did yesterday — it's in an ADR you wrote three months ago.\n\n| | Session memory tools | pmem |\n|---|---|---|\n| **Remembers** | What Claude did | What the project documented |\n| **Source data** | Session transcripts, tool usage | Markdown, text, code files in your repo |\n| **Search method** | Keyword / hybrid over sessions | Semantic (vector) search over project docs |\n| **Requires** | Cloud API or session capture hooks | Local only — Ollama + ChromaDB, no API keys |\n| **Use case** | \"Continue where we left off\" | \"What did we decide about X six months ago?\" |\n\npmem doesn't replace session memory. It fills the gap that session memory can't: retrieving decisions, context, and rationale from your project's documentation by meaning, not by keyword.\n\n### Real-world comparison\n\nSame query — \"identify governance-related blog posts\" — run against a project with 500+ markdown files:\n\n| | **pmem (index-based)** | **Fresh search (Explore agent)** |\n|---|---|---|\n| **Results found** | 18 posts | 11 posts |\n| **Time** | ~20 seconds | ~90 seconds |\n| **Token cost** | ~5,500 | ~20,000–24,000 |\n| **Missed** | — | 7 posts (governance as supporting theme) |\n\nThe fresh search cost roughly **4× the tokens** and found **7 fewer results**. The posts it missed were the ones where governance was woven into the argument without being the headline topic — exactly the kind of semantic connection that keyword search can't make.\n\nFor the full breakdown — architecture decisions, the prompt that built it, and token cost analysis — read the [build story on the blog](https://mipyip.com/blog/project-memory-for-claude-code).\n\n## How it works\n\n```\nClaude Code → MCP tool call → pmem server\n                                  ↓\n                        embed query (Ollama)\n                                  ↓\n                        search ChromaDB (local)\n                                  ↓\n                        (optional) synthesize answer via local LLM\n                                  ↓\n                        return answer + sources to Claude\n```\n\npmem indexes your project's markdown and text files into a local vector database (ChromaDB). When Claude needs context, it queries the memory via MCP tools — no copy-pasting, no manual file pointing.\n\n## Quick start\n\n### 1. Prerequisites\n\n- Python 3.11+\n- [Ollama](https://ollama.ai) installed and running\n\nPull the embedding model (~274MB, one-time):\n\n```bash\nollama pull nomic-embed-text\n```\n\n### 2. Install pmem\n\n\u003e **PyPI package coming soon.** Once published, installation will be just `pip install pmem`. For now, install from source:\n\n```bash\ngit clone https://github.com/avanrossum/pmem-project-memory-tool-for-claude.git\ncd pmem-project-memory-tool-for-claude\npip install -e .\npmem install-skills\n```\n\n### 3. Register the MCP server\n\nAdd to `~/.claude.json` (global, all projects) or `.mcp.json` (per-project):\n\n```json\n{\n  \"mcpServers\": {\n    \"project-memory\": {\n      \"command\": \"/full/path/to/pmem\",\n      \"args\": [\"serve\"]\n    }\n  }\n}\n```\n\n\u003e **Important:** Use the full path to `pmem`, not just `\"pmem\"`. Claude Code spawns MCP servers as subprocesses without your shell profile, so pyenv shims and other version managers won't work. Run `which pmem` to get the path. `pmem init` prints the correct snippet automatically.\n\u003e\n\u003e **Note:** MCP servers go in `~/.claude.json` or `.mcp.json`, NOT in `~/.claude/settings.json` (which is for permissions and hooks only).\n\n### 4. Initialize in your project\n\n```bash\ncd ~/your-project\npmem init\npmem index\n```\n\nThat's it. Claude Code can now query your project's memory.\n\n## CLI reference\n\n```\npmem init                       Create .memory/config.json with sensible defaults\npmem index                      Incremental index (only changed files)\npmem index --force              Full reindex (re-embed everything)\npmem index --dry-run            Show what would be indexed\npmem query \"your question\"      Query memory from the terminal\npmem query \"...\" --no-llm       Return raw chunks (no LLM synthesis)\npmem status                     Show index state, stale files, config\npmem exclude \"snapshots/**\"     Add a pattern to the exclude list\npmem include \"**/*.py\"          Add a pattern to the include list\npmem serve                      Start the MCP server (used by Claude Code)\npmem config                     Print current config\npmem config --edit              Open config in $EDITOR\npmem config --global            Show global config\npmem config --init-global       Create global config at ~/.config/pmem/config.json\npmem watch                      Poll for changes and reindex automatically (every 5s)\npmem install-skills             Install /welcome, /sleep, /reindex to Claude Code\npmem install-skills --link      Symlink instead of copy (macOS/Linux)\n```\n\n\u003e **Note:** Don't run `pmem index` from the terminal while Claude Code is active on the same project — use the `memory_reindex` MCP tool (or `/reindex` skill) instead. `pmem watch` uses polling (not filesystem events) so it works reliably on all platforms.\n\n## MCP tools\n\nOnce registered, Claude Code has access to four tools:\n\n| Tool | Description |\n|------|-------------|\n| `memory_query` | Ask a natural language question — retrieves relevant chunks and optionally synthesizes an answer via a local LLM |\n| `memory_search` | Search for matching chunks with source locations (no synthesis) |\n| `memory_status` | Check index state: file count, chunk count, stale files, config |\n| `memory_reindex` | Trigger a reindex from within Claude Code |\n\n## Configuration\n\n`pmem init` creates `.memory/config.json` in your project root:\n\n```json\n{\n  \"project_name\": \"my-project\",\n  \"embedding\": {\n    \"endpoint\": \"http://localhost:11434\",\n    \"model\": \"nomic-embed-text\",\n    \"provider\": \"ollama\"\n  },\n  \"llm\": {\n    \"endpoint\": \"http://localhost:1234/v1\",\n    \"model\": \"local-model\",\n    \"provider\": \"openai_compatible\",\n    \"enabled\": false\n  },\n  \"indexing\": {\n    \"include\": [\"**/*.md\", \"**/*.txt\"],\n    \"exclude\": [\".memory/**\", \"**/.git/**\", \"**/node_modules/**\", \"*.lock\"],\n    \"chunk_size\": 400,\n    \"chunk_overlap\": 80,\n    \"split_on_headers\": true\n  },\n  \"query\": {\n    \"top_k\": 8,\n    \"auto_reindex_on_query\": false\n  },\n  \"update_channel\": \"stable\"\n}\n```\n\n### Embedding providers\n\n| Provider | Config | Notes |\n|----------|--------|-------|\n| `ollama` (default) | `endpoint: \"http://localhost:11434\"` | Uses `/api/embed` (batch). Free, local. |\n| `openai_compatible` | Any OpenAI-compatible endpoint | Uses `/v1/embeddings`. Works with LMStudio, vLLM, etc. |\n\n### LLM synthesis (optional, disabled by default)\n\nWhen used via MCP with Claude Code, LLM synthesis is unnecessary — Claude interprets the raw chunks directly. Synthesis is disabled by default.\n\nFor standalone terminal use (`pmem query`), you can enable synthesis by setting `llm.enabled: true` and pointing at any OpenAI-compatible endpoint (LMStudio, Ollama's OpenAI mode, vLLM, etc.). This sends retrieved chunks to a local LLM for a summarized answer.\n\n### Indexing options\n\n- **`include`** — glob patterns for files to index (default: `**/*.md`, `**/*.txt`)\n- **`exclude`** — glob patterns to skip (default: `.memory/**`, `.git/**`, `node_modules/**`, `*.lock`)\n- **`chunk_size`** — target chunk size in words (default: 400)\n- **`chunk_overlap`** — overlap between chunks in words (default: 80)\n- **`split_on_headers`** — split markdown at H1/H2/H3 boundaries before splitting by size (default: true). When a section is too large for a single chunk, it's split by size — but each sub-chunk retains the heading path from its parent section, so query results always show where in the document a chunk came from.\n\n### Indexing non-markdown files\n\npmem indexes markdown and text files by default, but you can add any file type:\n\n```bash\npmem include \"**/*.py\"\npmem include \"**/*.js\"\npmem include \"**/*.apex\"\n```\n\nThis writes to your project's `.memory/config.json` — it only affects the current project, not other projects using pmem.\n\nNon-markdown files are chunked by size (word count with overlap), since there are no header boundaries to split on. This works well for most code and documentation formats. Language-aware chunking (splitting on function/class boundaries) is on the roadmap but not yet implemented — size-based splitting is good enough for semantic retrieval in practice.\n\nAfter adding new patterns, reindex to pick up the new files:\n\n```bash\npmem index\n```\n\n### Query options\n\n- **`top_k`** — number of chunks to retrieve per query (default: 8)\n- **`auto_reindex_on_query`** — check for stale files before every query and re-embed if needed (default: false — `/welcome`, `/sleep`, and `pmem watch` handle freshness)\n\n### Update notifications\n\npmem checks GitHub for new releases once per day and shows a notice when an update is available — both in `pmem status` output and in MCP tool responses (so Claude will tell you).\n\nBy default, only stable releases trigger notifications. To opt into beta (pre-release) notifications:\n\n```json\n{\n  \"update_channel\": \"beta\"\n}\n```\n\nSet this in `.memory/config.json` (per-project) or `~/.config/pmem/config.json` (global).\n\n\u003e **Warning:** Beta releases may contain breaking changes, incomplete features, or bugs. Use at your own risk. If something breaks, pin back to the last stable version with `git checkout v\u003cversion\u003e \u0026\u0026 pip install -e .`\n\n## What gets created in your project\n\n```\nyour-project/\n└── .memory/\n    ├── config.json        ← commit this (your project's memory config)\n    ├── chroma/            ← gitignore (generated vector store)\n    └── index_state.json   ← gitignore (file hash registry)\n```\n\nAdd to your `.gitignore` (done automatically by `pmem init`):\n\n```\n.memory/\n```\n\n\u003e **Note:** Older versions of pmem added individual entries (`.memory/chroma/`, `.memory/index_state.json`). The single `.memory/` entry is preferred — it catches transient files like lock files that the specific entries miss.\n\n## Skills (optional)\n\npmem ships with three Claude Code slash command skills:\n\n- **`/welcome`** — Run at the start of each session. Reads governance files, runs incremental reindex, confirms readiness.\n- **`/sleep`** — Run at the end of each session. Full governance pass: updates tasks, docs, changelog, memory, and reindexes.\n- **`/reindex`** — Quick trigger to refresh the memory index mid-session.\n\n### Install skills\n\n```bash\n# Recommended: use the built-in installer\npmem install-skills\n\n# Or with symlinks (stays in sync with repo, macOS/Linux only)\npmem install-skills --link\n```\n\nOr manually:\n\n```bash\n# Copy\ncp skills/welcome.md ~/.claude/commands/welcome.md\ncp skills/sleep.md ~/.claude/commands/sleep.md\ncp skills/reindex.md ~/.claude/commands/reindex.md\n\n# Or symlink (macOS/Linux only)\nln -sf \"$(pwd)/skills/welcome.md\" ~/.claude/commands/welcome.md\nln -sf \"$(pwd)/skills/sleep.md\" ~/.claude/commands/sleep.md\nln -sf \"$(pwd)/skills/reindex.md\" ~/.claude/commands/reindex.md\n```\n\n## Recommended CLAUDE.md snippet\n\nAdd this to any project using pmem so Claude knows it's available:\n\n```markdown\n## Project Memory\n\nThis project has a local RAG memory index via `pmem`. Use the `memory_query` MCP tool when:\n- Looking for past decisions, context, or rationale (\"why did we do X?\")\n- Searching for historical task context or outcomes\n- Finding documented gotchas or lessons learned\n\nDo NOT use memory_query for: reading specific known files, checking current code\nstate, or anything derivable from `git log`. The index updates at session start\n(`/welcome`) and session end (`/sleep`), so it may be slightly behind mid-session.\n\nIf results seem stale, run `memory_reindex` to refresh.\n```\n\n## Hardware notes\n\n| Setup | Embedding | LLM synthesis |\n|-------|-----------|---------------|\n| Any Mac (even 8GB) | Runs locally — nomic-embed-text is tiny | Point at a remote machine or disable |\n| 32GB+ Mac | Runs locally | Run 8B–32B model locally via Ollama/LMStudio |\n| Dedicated server (Mac Studio, etc.) | Runs locally | Run 70B+ model, expose via Cloudflare tunnel |\n\n## Design principles\n\n- **Local-first** — no data leaves your machine. No API keys required.\n- **Portable** — install once globally, `pmem init` in any project.\n- **Low friction** — setup takes under 2 minutes. Querying is automatic via MCP.\n- **Minimal dependencies** — no LangChain, no LlamaIndex. Just ChromaDB, httpx, click, pathspec, and the MCP SDK.\n\n## Related reading\n\n- [Cognitive Offloading](https://mipyip.com/blog/cognitive-offloading) — The methodology behind deliberate memory externalization\n- [The Governance Documents](https://mipyip.com/blog/the-governance-documents) — ROADMAP.md, ARCHITECTURE.md, CLAUDE.md, CHANGELOG.md — the files pmem was built to index\n- [What Is Pass@1?](https://mipyip.com/blog/what-is-pass-at-1) — The development methodology where governance documents are thorough enough that AI generates correct implementations on the first attempt\n\n## Author\n\nBuilt by [Alex van Rossum](https://mipyip.com/about) — systems architect, fractional CTO, and the kind of person who builds tools when the existing ones waste too many tokens.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Favanrossum%2Fpmem-project-memory-tool-for-claude-code","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Favanrossum%2Fpmem-project-memory-tool-for-claude-code","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Favanrossum%2Fpmem-project-memory-tool-for-claude-code/lists"}