{"_id":"@aliildan/mneme","name":"@aliildan/mneme","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@aliildan/mneme","version":"0.1.0","description":"Local context and memory engine for AI coding agents — MCP server companion to openclaude.","type":"module","bin":{"mneme":"bin/mneme","mn":"bin/mneme"},"engines":{"node":">=20"},"license":"MIT","author":{"name":"Ali Ildan","email":"ali.ildan@gmail.com"},"keywords":["mcp","claude-code","code-index","memory","context","tree-sitter","sqlite","ai-agents","openclaude"],"repository":{"type":"git","url":"git+https://github.com/aliildan/mneme.git"},"bugs":{"url":"https://github.com/aliildan/mneme/issues"},"homepage":"https://github.com/aliildan/mneme#readme","publishConfig":{"access":"public"},"scripts":{"test":"node --test test/parse-ts.test.js test/merkle-invalidate.test.js test/rank.test.js test/budget.test.js test/mcp-smoke.test.js test/memory-roundtrip.test.js test/global-scope-isolation.test.js test/promote-explicit.test.js test/openclaude-client.test.js test/discovery-runner.test.js test/discovery-opus-excluded.test.js test/outcomes.test.js test/graph-callers.test.js test/cross-project.test.js test/gc.test.js test/lang-python.test.js test/lang-go.test.js test/lang-rust.test.js test/lang-php.test.js test/lang-csharp.test.js test/multi-language-pipeline.test.js test/gitignore-respect.test.js test/touch-command.test.js test/dirty-marker.test.js test/install-hook.test.js test/session-context.test.js test/session-start-hook.test.js test/install-skill.test.js test/tool-descriptions.test.js","prepublishOnly":"npm test"},"dependencies":{"@modelcontextprotocol/sdk":"^1.0.0","@noble/hashes":"^1.4.0","better-sqlite3":"^11.0.0","ignore":"^6.0.0","tree-sitter-wasms":"^0.1.10","web-tree-sitter":"^0.24.4"},"gitHead":"28038a96f374c733e28a6fcb567631842ccffad6","_id":"@aliildan/mneme@0.1.0","_nodeVersion":"24.16.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-D3eCD3FxAnzkXpP0OkRQdVTX3gxpwKPCtn2jqb61McbdxFW/IapEwYhHHzaIv/vKbnPaE27oIHBDHbiGMV51WA==","shasum":"00da4bc76380b81a558a43ca0870cbb7724c3357","tarball":"https://registry.npmjs.org/@aliildan/mneme/-/mneme-0.1.0.tgz","fileCount":79,"unpackedSize":168498,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICahxQikY3fwAIWSeN00lDacXq3vI0YQRkG9NteY9ARmAiEA/wHmLyrDx+DhzzOW2WO8RASNNpaaA+H4kxg+qt0Bm8M="}]},"_npmUser":{"name":"aliildan","email":"ali.ildan@gmail.com"},"directories":{},"maintainers":[{"name":"aliildan","email":"ali.ildan@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mneme_0.1.0_1782169722222_0.9911260259528714"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-22T23:08:42.045Z","0.1.0":"2026-06-22T23:08:42.378Z","modified":"2026-06-22T23:08:42.588Z"},"maintainers":[{"name":"aliildan","email":"ali.ildan@gmail.com"}],"description":"Local context and memory engine for AI coding agents — MCP server companion to openclaude.","homepage":"https://github.com/aliildan/mneme#readme","keywords":["mcp","claude-code","code-index","memory","context","tree-sitter","sqlite","ai-agents","openclaude"],"repository":{"type":"git","url":"git+https://github.com/aliildan/mneme.git"},"author":{"name":"Ali Ildan","email":"ali.ildan@gmail.com"},"bugs":{"url":"https://github.com/aliildan/mneme/issues"},"license":"MIT","readme":"<p align=\"center\">\n  <img src=\"./mneme_logo.png\" alt=\"Mneme\" width=\"220\" />\n</p>\n\n<h1 align=\"center\">Mneme</h1>\n\n<p align=\"center\">\n  <strong>Local context &amp; memory engine for AI coding agents.</strong><br/>\n  A precise symbol index of your codebase and a verbatim memory of past decisions — exposed over MCP, running entirely on your machine.\n</p>\n\n<p align=\"center\">\n  <a href=\"#install\"><img alt=\"Node\" src=\"https://img.shields.io/badge/node-%E2%89%A520-43853d?style=flat-square&logo=node.js&logoColor=white\" /></a>\n  <img alt=\"MCP\" src=\"https://img.shields.io/badge/MCP-stdio-5b21b6?style=flat-square\" />\n  <img alt=\"License\" src=\"https://img.shields.io/badge/license-MIT-blue?style=flat-square\" />\n</p>\n\n<p align=\"center\">\n  <a href=\"#setup\">Setup</a> ·\n  <a href=\"#mcp-tools\">MCP tools</a> ·\n  <a href=\"#memory-model\">Memory model</a> ·\n  <a href=\"#architecture\">Architecture</a> ·\n  <a href=\"#design-principles\">Principles</a>\n</p>\n\n---\n\n## Why Mneme\n\nAI coding agents waste tokens and degrade in quality because they load too much irrelevant context and forget what they've already learned. Mneme — named for the Greek personification of memory — fixes both, **locally**:\n\n| | Without Mneme | With Mneme |\n| --- | --- | --- |\n| **Finding code** | grep + read whole files into the prompt | Ranked symbols + minimal snippets, within a token budget |\n| **Re-using decisions** | The agent rediscovers what it learned last week | Verbatim recall of decisions, gotchas, learnings, todos |\n| **Cost** | Cloud embedding API + full-file loads | One SQLite file. Zero network. Zero embeddings cost. |\n| **Cross-project leakage** | Easy to mix learnings between repos | Isolated by project hash; globals require explicit promotion |\n\nThe goal is **measurably fewer tokens per task and more accurate context selection** — not raw text compression.\n\n---\n\n## Status\n\n`v0.1` — feature-complete for Phases 1, 2, and 4 of the architecture plan. Phase 3 multi-language symbol extraction ships (TypeScript, JavaScript, Python, Go, Rust, PHP, C#); the `sqlite-vec` semantic-search half of Phase 3 is deferred.\n\n- **182 tests**, 0 failures, ~9 seconds end-to-end\n- **7 languages** indexed via tree-sitter WASM\n- **15 MCP tools** exposed over stdio\n- **Auto-indexing on file reads** — `mneme init` installs a user-global Claude Code hook that nudges the index on every Read/Edit/Write\n- **Discovery model optional** — Mneme runs without one and never blocks on a model\n\n---\n\n## How it works\n\n```\n┌──────────────────┐        ┌──────────────────────┐        ┌────────────────┐\n│  Claude Code /   │  MCP   │   mneme stdio        │  SQL   │ index.db       │\n│  Cursor / any    │ ─────▶ │   (15 tools)         │ ─────▶ │ + global.db    │\n│  MCP-capable     │  JSON  │                      │  WAL   │ (per-project)  │\n│  agent           │ ◀───── │  ┌────────────────┐  │ ◀───── │                │\n└──────────────────┘        │  │ ensureFresh    │  │        └────────────────┘\n                            │  │   ├ Merkle walk│  │\n                            │  │   ├ tree-sitter│  │\n                            │  │   └ FTS5 upsert│  │\n                            │  └────────────────┘  │\n                            │  ┌────────────────┐  │        ┌────────────────┐\n                            │  │ rank → discov. │  │  HTTP  │ openclaude     │\n                            │  │ model → budget │  │ ─────▶ │ router         │\n                            │  └────────────────┘  │        │ (optional)     │\n                            └──────────────────────┘        └────────────────┘\n```\n\nEvery MCP call routes through `ensureFresh`: a bottom-up Merkle walk over blake3 content hashes that prunes unchanged subtrees in microseconds and reparses only what actually changed. The result is a stale-free index without polling, watchers, or git hooks.\n\n<img width=\"1657\" height=\"618\" alt=\"image\" src=\"https://github.com/user-attachments/assets/b9963941-8187-490b-a404-f1c71572f69b\" />\n\n---\n\n## Requirements\n\n- **Node.js ≥ 20**\n- A C++ toolchain **only if** `better-sqlite3` lacks a prebuilt binary for your platform (uncommon on macOS, Linux, Windows x64)\n- *Optional:* [openclaude](https://github.com/aliildan/openclaude) on `127.0.0.1:11436` for the discovery-model feature and the `/mneme` slash command\n\n---\n\n## Install\n\nInstall globally from npm — this registers the `mneme` and `mn` commands on your `PATH`:\n\n```bash\nnpm install -g @aliildan/mneme\n```\n\nThe package is scoped (`@aliildan/mneme`), but the commands stay `mneme` / `mn`, and they work from any directory on Linux, macOS, and Windows. `better-sqlite3` installs a prebuilt binary on common platforms; only if none exists for yours do you need a C++ toolchain to compile it.\n\nUpgrade later with `npm install -g @aliildan/mneme@latest`.\n\nOn Windows the config lives at `%USERPROFILE%\\.openclaude\\mneme.json` and per-project indexes under `%USERPROFILE%\\.openclaude\\mneme\\projects\\`; everything else is path-agnostic.\n\n> Mneme stores its index and memory databases under `~/.openclaude/mneme/` (or `%USERPROFILE%\\.openclaude\\mneme\\` on Windows), sharing the home directory with openclaude.\n\n---\n\n## Setup\n\nFrom zero to \"Claude Code can use it\" in five steps.\n\n### 1. Install Mneme\n\n```bash\nnpm install -g @aliildan/mneme\n```\n\nVerify it's on your PATH:\n\n```bash\nwhich mneme          # /opt/homebrew/bin/mneme or your npm global bin\nmneme help\n```\n\n> **Gotcha:** the `mneme` command must be on your PATH. If `which mneme` is empty, run `npm prefix -g` and make sure that directory's `bin` is on your shell PATH.\n\n### 2. Index a project\n\nGo into **any** repo you want Mneme to know about and run `init`:\n\n```bash\ncd /path/to/some/project\nmneme init\n```\n\nThis:\n- detects the project root\n- writes `~/.openclaude/mneme/projects/<hash>/index.db`\n- parses every `.ts / .js / .py / .go / .rs / .php / .cs` file in the tree\n- installs the `/mneme` slash command under `.claude/commands/`\n- installs a user-global PostToolUse hook in `~/.claude/settings.json` so every Read/Edit/Write/Glob/Grep nudges Mneme to re-index (pass `--no-hook` to skip; run `mneme uninstall-hook` to remove later)\n- **prints an MCP snippet to stdout** — copy it, you need it next\n\nSanity-check:\n\n```bash\nmneme status         # file / symbol / edge counts and merkle root\n```\n\n### How auto-indexing on reads works\n\nThe PostToolUse hook runs `mneme touch` after every Read/Edit/Write/Glob/Grep/MultiEdit tool call. That's a fast (~50–100 ms) side-effect-only command — no DB open, no parsing — that just drops a `.dirty` marker file next to the project index. On the **next** `mneme_*` MCP call, `ensureFresh` sees the marker, bypasses the usual 250 ms debounce, re-validates the Merkle tree, reparses anything changed, and deletes the marker. Net effect: the index never goes stale just because the agent was exploring with non-mneme tools.\n\n### 3. Wire it into Claude Code\n\nOpen `~/.mcp.json` (or a project-scoped `.mcp.json`) and paste the snippet `init` printed into the `mcpServers` block:\n\n```jsonc\n{\n  \"mcpServers\": {\n    \"mneme\": {\n      \"command\": \"mneme\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\n> **One entry, all projects.** Mneme auto-detects the project from the MCP server's cwd — it walks up looking for `.mneme`, `.git`, `package.json`, `pyproject.toml`, `Cargo.toml`, or `go.mod`. Claude Code spawns the MCP server in the project you launched it in, so a single user-scoped entry serves every repo; each session gets its own process pointed at the right root.\n>\n> To pin a specific root instead (e.g. for tests or unusual layouts), add `\"env\": { \"MNEME_PROJECT_ROOT\": \"/abs/path/to/project\" }`.\n\nRestart Claude Code. In a session, run `/mcp` — you should see `mneme` listed as connected with 15 tools.\n\n### 4. *(Optional)* Pick a discovery model\n\nOnly if you also run [openclaude](https://github.com/aliildan/openclaude) on `127.0.0.1:11436`:\n\n```bash\nmneme model          # interactive numbered menu\n# or\nmneme model 3        # by index\n```\n\nThe selection is written to `~/.openclaude/mneme.json` and applied on the **next** request — no restart needed. Skip this entirely and Mneme uses its deterministic ranker; nothing breaks.\n\n### 5. Smoke test\n\nIn Claude Code, ask the agent:\n\n> *\"Use `mneme_get_context` to find the auth middleware in this repo.\"*\n\nIf you see ranked symbols come back with file paths and line ranges, you're done.\n\n> **Hot config:** Mneme re-reads `~/.openclaude/mneme.json` on **every** MCP request — no restart needed after config edits.\n\n---\n\n## MCP tools\n\nFifteen idempotent tools. All are read-only at the MCP surface; index writes happen as a deterministic refresh side-effect of `ensureFresh` before any read.\n\n### Retrieval\n\n| Tool | Purpose |\n| --- | --- |\n| `mneme_get_context` | Ranked symbols + snippets for a task within a token budget. |\n| `mneme_lookup_symbol` | Direct symbol lookup by name (with optional `kind` filter). |\n| `mneme_callers` / `mneme_callees` | Walk the dependency graph N hops. |\n\n### Memory\n\n| Tool | Purpose |\n| --- | --- |\n| `mneme_record_memory` | Append a verbatim decision / learning / gotcha / todo. |\n| `mneme_recall_memory` | Search memory by text, kind, scope, files, tags. |\n| `mneme_list_memories` | Paginate without scoring. |\n| `mneme_forget` | Soft-delete by id (body preserved for audit). |\n| `mneme_promote_memory` | Explicitly copy a project memory to global scope. |\n| `mneme_gc_memory` | Manually soft-delete stale memories. |\n| `mneme_search_projects` | Cross-project memory recall (opt-in; memory only, never code). |\n\n### Operations\n\n| Tool | Purpose |\n| --- | --- |\n| `mneme_index_status` | Index health: file counts, schema version, merkle root. |\n| `mneme_list_models` | Available discovery models (Ollama + curated Anthropic, Opus excluded). |\n| `mneme_set_discovery_model` | Choose the discovery model (`null` = deterministic). |\n| `mneme_record_outcome` | Record whether a `get_context` call succeeded — closes the metrics loop. |\n\n---\n\n## Memory model\n\nTwo physical databases, one purpose each:\n\n- `~/.openclaude/mneme/projects/<hash>/index.db` — symbols, edges, chunks, and **project-scope** memory\n- `~/.openclaude/mneme/global.db` — **global-scope** memory only, shared across projects\n\nMemory has four kinds (`decision`, `learning`, `gotcha`, `todo`) and two scopes (`project`, `global`). Recall searches both by default and slightly favors project results over global.\n\nA memory becomes global **only through explicit action**:\n\n- `mneme_record_memory({scope: \"global\"})` writes directly to `global.db`\n- `mneme_promote_memory({id})` copies an existing project row to global with `source: \"promoted\"`\n\n> **Mneme never auto-promotes.** Misjudging a project-specific fact as portable would leak it everywhere.\n\nSoft delete only. `mneme_forget` sets `forgotten_at`; the body is preserved for audit and excluded from future recall.\n\n---\n\n## Supported languages\n\n| Language | Extensions | Coverage |\n| --- | --- | --- |\n| **TypeScript / JavaScript** | `.ts .tsx .js .jsx .mjs .cjs` | Full symbols + edges. `.d.ts` skipped. |\n| **Python** | `.py .pyw` | Functions, classes, decorated functions, imports. Methods inside classes carry `container` (parent class name). |\n| **Go** | `.go` | Functions, methods, structs, interfaces, grouped imports. |\n| **Rust** | `.rs` | Functions, structs (`class`), enums, traits (`interface`), impl blocks, `use` declarations. |\n| **PHP** | `.php .phtml .phar` | Functions, methods, classes, interfaces, traits (`class`), enums, `use` imports. Method `exported` reflects `public`/`private`/`protected`. |\n| **C#** | `.cs` | Classes, structs (`class`), records (`class`), interfaces, enums, methods, `using` directives. `exported` reflects `public` (with interface members treated as implicitly public). |\n\nOther languages walk fine but extract no symbols (`language: \"unknown\"`).\n\n---\n\n## CLI\n\n```text\nmneme mcp                Start the MCP stdio server (what Claude Code spawns)\nmneme init [path]        Initialize project index, install slash command + hook, print MCP snippet\nmneme init --no-hook     Same as above, but skip installing the user-global PostToolUse hook\nmneme reindex            Force a full re-parse\nmneme status             Index health and config\nmneme stats              Retrieval-outcome metrics (success rate, median tokens)\nmneme model              Show / select discovery model interactively\nmneme model <n>          Set discovery model by menu number (0 = none)\nmneme gc [--days N]      Manually GC memories older than N days (default 90)\nmneme touch              Mark project index dirty (called by the Claude Code hook)\nmneme uninstall-hook     Remove Mneme's PostToolUse entry from ~/.claude/settings.json\nmneme help               Show help\n```\n\nBoth `mneme` and the short alias `mn` are installed.\n\n---\n\n## Configuration\n\n`~/.openclaude/mneme.json` is read on **every** MCP request — edit it and changes take effect without restarting. On parse error Mneme falls back to defaults and logs a warning.\n\n```json\n{\n  \"discoveryModel\": null,\n  \"router\": { \"baseUrl\": \"http://127.0.0.1:11436\" },\n  \"indexer\": {\n    \"maxFileBytes\": 1048576,\n    \"ignore\": [\".git\", \"node_modules\", \"dist\", \"build\", \".next\", \".venv\", \"target\", \".mneme\"],\n    \"languages\": [\"typescript\", \"python\", \"go\", \"rust\", \"php\", \"csharp\"]\n  },\n  \"retrieval\": {\n    \"defaultTokenBudget\": 6000,\n    \"perFileCap\": 800,\n    \"tokenizer\": \"chars/4\"\n  },\n  \"memory\": {\n    \"globalDbPath\": \"$HOME/.openclaude/mneme/global.db\"\n  },\n  \"cross_project\": {\n    \"enabled\": false,\n    \"allow\": []\n  }\n}\n```\n\n**Environment variables:**\n\n| Variable | Effect |\n| --- | --- |\n| `MNEME_PROJECT_ROOT` | Pin the project root (otherwise auto-detected from `.mneme`, `.git`, `package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`). |\n| `MNEME_QUIET=1` | Suppress non-error logs. |\n| `MNEME_DEBUG=1` | Include stack traces on CLI errors. |\n\n---\n\n## Architecture\n\nA walker traverses the project root in lexicographic order, filtering via `.gitignore`, `.mnemeignore`, and config ignores. Each file's blake3 content hash becomes a leaf in a Merkle tree of directory-node hashes. On every MCP request the validator does a bottom-up walk: directory hashes that match the cached value let the entire subtree be pruned (no per-file work). Dirty files are reparsed by language plugins, symbols and edges are upserted in a single transaction, and a second pass resolves edge targets across files.\n\nSQLite (WAL mode, FTS5 for symbol search) is the only storage. The deterministic ranker scores candidates from FTS5 BM25, path-token matches, hint boosts, dependency 1-hop neighbors, recency, and the `exported` flag. The optional discovery model receives the top 60 candidates and returns a `{keep, drop}` JSON object — it can only remove, never reorder or add. The budget filler then packs symbols and code snippets until the token budget or per-file cap is hit, returning a **cache-stable** response.\n\n---\n\n## Design principles\n\nThese are enforced in code, not just documented:\n\n1. **Correctness over freshness.** Lazy validation at query time — a stale index that returns wrong files is worse than a slow one.\n2. **Verbatim, never summarized memory.** Paths, errors, identifiers are stored exactly.\n3. **The discovery model narrows, it does not decide.** Wrong context selection actively harms the agent.\n4. **Do not break prompt caching.** Stable response prefix; volatile metadata at the end of the response.\n5. **Measure everything.** `retrieval_outcomes` table + `mneme stats` close the feedback loop.\n6. **Stay small and composable.** No build step. ESM. Node built-in `test`. Mirror openclaude conventions where they apply.\n7. **Isolate projects; share globals only by explicit choice.** Default project-local. Never auto-promote.\n\n---\n\n## Roadmap\n\nWhat's deferred for a later release:\n\n- **`sqlite-vec` semantic search** and the embedding pipeline (Phase 3 scaffolding exists in `rank-v3.js` and the `chunks` table, but no embedder is wired up). BM25 over symbols is the active retrieval path today.\n- **`mneme outcome <id>` CLI** — a wrapper for `mneme_record_outcome`. Agents call the tool directly for now.\n- **Container tracking** for PHP and C# methods (only Python tracks parent class today).\n- **Large-repo benchmarks** (5k+ files). The plan targets `<200ms` full walk and `<50ms p50` for `mneme_get_context`; these still need real-world verification.\n\n---\n\n## Testing\n\n```bash\nnpm test\n```\n\nRuns **182 tests across 36 suites in ~9 seconds**. The test list is explicit in `package.json` — no glob, no hidden tests. Golden snapshots for symbol extraction live under `test/golden/`.\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n\n<p align=\"center\">\n  <sub>Built as a companion to <a href=\"https://github.com/aliildan/openclaude\">openclaude</a>. Local-first. No telemetry.</sub>\n</p>\n","readmeFilename":"README.md","_rev":"1-500c9d8d1cab729acc5475a1fb90f681"}