{"id":50874792,"url":"https://github.com/nnemlab/engram","last_synced_at":"2026-06-15T09:00:23.804Z","repository":{"id":363715432,"uuid":"1230389567","full_name":"nNemLab/engram","owner":"nNemLab","description":"Engram — Claude Code as kernel; canonical event log projected into an Obsidian vault (MCP server)","archived":false,"fork":false,"pushed_at":"2026-06-10T04:31:25.000Z","size":844,"stargazers_count":0,"open_issues_count":9,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-10T05:06:11.268Z","etag":null,"topics":["claude","knowledge-management","mcp","memory","obsidian","python","rag","sqlite"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nNemLab.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","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-05-06T00:31:10.000Z","updated_at":"2026-06-10T04:31:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nNemLab/engram","commit_stats":null,"previous_names":["nnemlab/engram"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/nNemLab/engram","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nNemLab%2Fengram","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nNemLab%2Fengram/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nNemLab%2Fengram/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nNemLab%2Fengram/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nNemLab","download_url":"https://codeload.github.com/nNemLab/engram/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nNemLab%2Fengram/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34355156,"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-15T02:00:07.085Z","response_time":63,"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":["claude","knowledge-management","mcp","memory","obsidian","python","rag","sqlite"],"created_at":"2026-06-15T09:00:18.315Z","updated_at":"2026-06-15T09:00:23.641Z","avatar_url":"https://github.com/nNemLab.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"design/brand/engram-lockup-horizontal-white.svg\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"design/brand/engram-lockup-horizontal-ink.svg\"\u003e\n    \u003cimg alt=\"Engram\" src=\"design/brand/engram-lockup-horizontal-ink.svg\" width=\"360\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eA personal knowledge platform built around an append-only event log, projected into an Obsidian vault, accessed by agents over MCP.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg alt=\"License: AGPL-3.0-or-later\" src=\"https://img.shields.io/badge/license-AGPL--3.0--or--later-blue.svg\"\u003e\u003c/a\u003e\n  \u003cimg alt=\"Python 3.11+\" src=\"https://img.shields.io/badge/python-3.11%2B-blue.svg\"\u003e\n  \u003ca href=\"https://docs.astral.sh/uv/\"\u003e\u003cimg alt=\"built with uv\" src=\"https://img.shields.io/badge/built%20with-uv-261230.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/nNemLab/engram/releases\"\u003e\u003cimg alt=\"latest release\" src=\"https://img.shields.io/github/v/release/nNemLab/engram?sort=semver\u0026amp;display_name=tag\u0026amp;cacheSeconds=3600\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003e **Status:** early development (`0.x`). While on the `0.x` series, APIs, schema, and on-disk layout may change between minor versions without migration paths. (The badge above shows the latest release.)\n\n---\n\n## Table of contents\n\n- [Highlights](#highlights)\n- [How it works](#how-it-works)\n- [Requirements](#requirements)\n- [Quick start](#quick-start)\n- [Docker](#docker)\n- [Ambient memory](#ambient-memory)\n- [What you can curate](#what-you-can-curate)\n- [Documentation](#documentation)\n- [Configuration](#configuration)\n- [Privacy \u0026 offline](#privacy--offline)\n- [Uninstall](#uninstall)\n- [Contributing](#contributing)\n- [FAQ](#faq)\n- [License](#license)\n\n## Highlights\n\n- **Event-log-canonical.** Every state change is an immutable event in an\n  append-only SQLite log. The FTS index, vector index, and Obsidian vault are\n  all rebuildable projections — the log is the only thing you have to back up.\n- **Hybrid retrieval.** `sqlite-vec` vector search fused with SQLite FTS5\n  full-text search via reciprocal-rank fusion, ranked by source-tier × recency ×\n  confidence.\n- **Ambient memory.** An optional Claude Code plugin auto-injects calibrated\n  retrieval on every turn, primes each session, and records what it used — so\n  memory shows up without being asked for. See [Ambient memory](#ambient-memory).\n- **Self-hosted \u0026 offline-capable.** Runs entirely on your machine. Everything\n  curated is local; query, read, and edit with no network. Web search goes\n  through your own SearXNG.\n- **Human-auditable.** The vault is plain markdown you can read, grep, diff, and\n  correct by hand — and every change is an immutable, timestamped event.\n- **One write path.** Human and agent write through the same dedup gate. There\n  is no hidden agent-only memory; you can always see and override what was stored.\n\n## How it works\n\nEngram treats:\n\n- **the event log as canonical** — every state change is an immutable event in SQLite,\n- **the Obsidian vault as a projection** — markdown files are a materialized view, not source of truth,\n- **the human and the agent as peers** — both write through the same dedup gate, both edit the same content.\n\n```mermaid\nflowchart TD\n    K[\"Claude Code · kernel\"]\n    L[(\"Event Log — SQLite, append-only\u003cbr/\u003eingested · merged · superseded · retrieved · edit · source_polled\")]\n    P[\"Projector\u003cbr/\u003elog → vault\"]\n    R[\"RAG view\u003cbr/\u003evec0 + FTS5\"]\n    Rx[\"Reactor\u003cbr/\u003eembed · staleness\"]\n    O[\"Obsidian\u003cbr/\u003ehuman edits\"]\n    W[\"Watcher\u003cbr/\u003eedits → log\"]\n    Po[\"Poller\u003cbr/\u003edue sources\"]\n    A[\"Adapters\u003cbr/\u003esitemap · github-repo · mediawiki · urls\"]\n\n    K \u003c--\u003e|MCP stdio| L\n    L --\u003e P --\u003e O\n    O --\u003e|edits| W --\u003e|edits → log| L\n    L --\u003e R\n    L --\u003e Rx --\u003e|embed / merge| L\n    L --\u003e Po --\u003e A --\u003e|candidates → gate| L\n\n    classDef kernel fill:#eef2ff,stroke:#6366f1,color:#0f172a;\n    classDef log fill:#e0f2fe,stroke:#0ea5e9,color:#0f172a;\n    classDef view fill:#ccfbf1,stroke:#14b8a6,color:#0f172a;\n    classDef human fill:#fef3c7,stroke:#f59e0b,color:#0f172a;\n    classDef source fill:#f3e8ff,stroke:#a855f7,color:#0f172a;\n\n    class K kernel\n    class L log\n    class P,R,Rx view\n    class O,W human\n    class Po,A source\n```\n\nEvery content write goes through `dedup.gate()` and produces an `ingested`\nevent. The reactor embeds and post-checks for near-dups. The projector renders\ncontent rows to the vault. The watcher tails the vault so manual edits in\nObsidian become authoritative.\n\n| Subsystem | Role |\n|---|---|\n| **Event log** | Append-only SQLite; canonical source of truth, replayable from 0. |\n| **Dedup gate** | The single write path: `exact_dup` / `superseded` / `near_dup` / `new`. |\n| **RAG** | Hybrid `vec0` + FTS5 retrieval, RRF-fused, ranked by confidence × source-tier × recency. |\n| **MCP server** | One server (stdio or HTTP), seven tool namespaces (`kb`, `rag`, `research`, `playbook`, `goals`, `sources`, `session`). |\n| **Projector / Watcher** | Log → vault markdown, and vault edits → log. |\n| **Reactor** | Embed-on-ingest, staleness checks, near-dup post-check. |\n| **Poller + adapters** | `sitemap`, `github-repo`, `mediawiki-api`, `urls`. |\n| **Research** | Self-hosted SearXNG, cross-encoder rerank, arXiv fetcher. |\n| **Playbooks** | Jupyter (scratch) / Marimo (curated), run via `playbook.run`. |\n| **Daemons** | Four systemd user units + a daily-digest timer (plus an optional grounding daemon for ambient memory). |\n\nFull internals — component-by-component, the confidence model, and\nfailure/recovery modes — are in [docs/architecture.md](docs/architecture.md).\n\n## Requirements\n\n- **[uv](https://docs.astral.sh/uv/)** — builds the runtime venv and installs engram (no separate `pip install`).\n- **Python 3.11+**\n- **[Obsidian](https://obsidian.md/)** — the human surface for the vault (optional but recommended).\n- **CPU by default; GPU optional.** Embeddings run on CPU out of the box; the GPU lane is an install-time choice — see [docs/configuration.md](docs/configuration.md).\n\nDeveloped and run on Linux; macOS should work (SQLite + a uv venv). The native\ninstall uses systemd user units; the [Docker](#docker) path needs only Docker.\n\n## Quick start\n\n**1. Get the code.**\n\n```bash\ngit clone https://github.com/nNemLab/engram.git \u0026\u0026 cd engram\n```\n\n**2. Initialize** (builds `~/.engram/.venv` and installs engram with the `[rag]`\nextra, then creates `~/.engram/{config.yml,.env,vault,db.sqlite}`).\n\n```bash\n./bin/eos-init\n```\n\n**3. Wire the MCP server into Claude Code.**\n\n```bash\nclaude mcp add -s user engram ~/.engram/.venv/bin/engram-mcp\n```\n\n**4. Start the daemons** (systemd user units; copy them in first — see [docs/setup.md](docs/setup.md)).\n\n```bash\nsystemctl --user enable --now \\\n  engram-projector engram-watcher engram-reactor engram-poller engram-daily-digest.timer\n```\n\n**5. Verify.**\n\n```bash\n./bin/eos-status\n```\n\nFull setup, troubleshooting, and round-trip verification:\n[docs/setup.md](docs/setup.md). To start feeding it content, see\n[What you can curate](#what-you-can-curate).\n\n## Docker\n\nPrefer containers? One command brings up the full stack (MCP server + daemons +\na private SearXNG):\n\n```bash\ndocker compose -f docker/compose.yml up -d --build\n```\n\nConnect any MCP client over the HTTP transport:\n\n```bash\nclaude mcp add --transport http engram http://localhost:8765/mcp\n```\n\nSee **[docker/README.md](docker/README.md)** for setup, the loopback-only\nsecurity note, and the provider-agnostic `ENGRAM_LLM_*` config.\n\n## Ambient memory\n\nFor auto-injected retrieval on every turn — calibrated so it stays quiet when\nnothing relevant exists — run the grounding daemon (`engram-rag serve`) and\nenable the Claude Code plugin in `engram-plugin/`. The plugin injects relevant\nmemory (`UserPromptSubmit`), primes each session (`SessionStart`), and records\nwhich entries were cited (`Stop`) so they rank higher next time.\n\nSee **[engram-plugin/README.md](engram-plugin/README.md)** for install options\nand configuration.\n\n## What you can curate\n\nAnything text-shaped that you want an agent to remember and reason over. Content\narrives three ways — you write it, the agent writes it, or a polled source feeds\nit — and all three land in the same gate.\n\n| You want to keep... | How |\n|---|---|\n| Your own notes, decisions, episodes | `kb.write`, or drop a markdown file into the vault inbox |\n| Docs sites that change over time | `sitemap` source (e.g. Docker, a framework's docs) |\n| Wikis | `mediawiki-api` source (Fandom game wikis, Wikipedia, PCGamingWiki, …) |\n| A GitHub repo's docs/code tree | `github-repo` source (tracks branch HEAD, incremental via compare API) |\n| Research papers | `research.fetch_arxiv` (abstracts + PDFs) |\n| One-off pages with no feed | `urls` source, or `research.ingest_url` |\n| Web-search findings | `research.search_web` via your local SearXNG, then ingest the keepers |\n\nA polled source is one declarative line. For example, track the Linux-relevant\nslice of Docker's docs, re-checked weekly:\n\n```bash\n./bin/eos-source add docker-docs-linux \\\n  --name \"Docker Docs (Linux)\" --adapter sitemap \\\n  --url https://docs.docker.com/sitemap.xml \\\n  --include '*/engine/*' --include '*/desktop/install/linux*' \\\n  --schedule 7d\n```\n\nThe poller fetches on its tick, runs every candidate through the dedup gate, and\nchains revisions when a page changes (old version stays queryable, vault file\nupdates in place). Per-source schedules, conditional GETs, and a circuit breaker\nkeep it polite.\n\n## Documentation\n\n| Document | What's inside |\n|---|---|\n| [Setup](docs/setup.md) | Full install, running the daemons, verification, and troubleshooting. |\n| [Configuration](docs/configuration.md) | `config.yml` reference, the LLM provider, embedding/reranker models, and the CPU-vs-GPU lane. |\n| [Architecture](docs/architecture.md) | Component-by-component internals, the confidence model, and failure/recovery modes. |\n| [MCP tool reference](docs/mcp-tool-reference.md) | Every tool across the seven namespaces, with arguments. |\n| [Event log schema](docs/event-log-schema.md) | Event types, tables, and the invariants the log guarantees. |\n| [Docker](docker/README.md) | Container install, what's exposed, and the loopback-only security posture. |\n| [Ambient memory plugin](engram-plugin/README.md) | Plugin install options and grounding-daemon configuration. |\n| [Contributing](CONTRIBUTING.md) | Dev setup, running the tests, and the PR flow. |\n\nNew to the project? Read [Setup](docs/setup.md) → [Configuration](docs/configuration.md)\n→ [Architecture](docs/architecture.md), then keep the\n[MCP tool reference](docs/mcp-tool-reference.md) handy.\n\n## Configuration\n\nAll settings live in `~/.engram/config.yml` (secrets in `~/.engram/.env`),\nwritten by `bin/eos-init`. See **[docs/configuration.md](docs/configuration.md)**\nfor the full reference — including the embedding/reranker model options and the\nCPU-vs-GPU lane choice.\n\n## Privacy \u0026 offline\n\nEngram is **online to gather, offline to use** — self-hosted, single-user, and\nfree of telemetry.\n\n- **Online to gather.** The poller refreshes live sources, `research.search_web`\n  queries your SearXNG, and the arXiv/URL fetchers pull new material. Search goes\n  through your own SearXNG instance, so queries aren't handed to a third-party API.\n- **Offline to use.** Everything already curated is local — a SQLite database\n  plus a markdown vault. Query, read, and edit it with no network; embeddings run\n  on CPU locally, so retrieval works on a plane or an air-gapped box. The poller\n  pauses and resumes when connectivity returns; nothing else depends on the network.\n- **Auditable by construction.** The append-only log is a full audit trail —\n  every ingest, merge, supersede, retrieval, and human edit is an immutable,\n  timestamped row. Nothing mutates silently; superseded revisions stay queryable\n  rather than being deleted.\n- **Yours to correct.** The vault is plain markdown in Obsidian: human-readable,\n  greppable, diffable, git-able. The watcher makes your hand edits authoritative,\n  and there is no hidden agent-only memory — one gate for human and agent alike.\n\n## Uninstall\n\n```bash\n./bin/eos-uninstall\n```\n\nRemoves the runtime (`~/.engram` — database, vault, venv — plus the systemd\nunits and the Claude Code MCP registration). It first reports the database size\nand offers to export it to an `engram-export-\u003ctimestamp\u003e.tar.gz`, then requires\nyou to type `DELETE` to confirm. **Removal is permanent; unexported curated\nknowledge is lost for good.** The source checkout is left in place. It\nauto-detects whether you have a native or Docker install and handles both.\n\n## Contributing\n\nContributions are welcome. See **[CONTRIBUTING.md](CONTRIBUTING.md)** for dev\nsetup, running the test suite, and the PR flow, and\n**[SECURITY.md](SECURITY.md)** for reporting vulnerabilities. Changes are tracked\nin [CHANGELOG.md](CHANGELOG.md).\n\n## FAQ\n\n**Is it multi-user?**\nNo. Single-user by design — no auth and no concurrency model beyond SQLite's WAL.\n\n**Does my data leave my machine?**\nNo. Engram is self-hosted with no cloud backend, no account, and no telemetry.\nWeb search runs through your own SearXNG, and outbound fetches are SSRF-guarded.\n\n**Do I need a GPU?**\nNo. Embeddings run on CPU by default. The GPU lane is an opt-in install choice,\nnot a config flag — see [docs/configuration.md](docs/configuration.md).\n\n**Is it a vector database?**\nNo. Retrieval is hybrid `sqlite-vec` + FTS5, RRF-fused and re-ranked. If you need\na dedicated vector DB at scale, this is the wrong project.\n\n**Is it a Claude API wrapper?**\nNo. Engram exposes tools to a kernel (Claude Code, or any MCP client). The kernel\ndoes the reasoning; engram is storage and retrieval.\n\n**Which clients work?**\nAny MCP-capable client. Claude Code is the primary target, over stdio (native) or\nthe HTTP transport (Docker).\n\n## License\n\n[AGPL-3.0-or-later](LICENSE). If you run a modified version of Engram as a\nnetwork service, you must offer your users the modified source under the same\nlicense.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnnemlab%2Fengram","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnnemlab%2Fengram","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnnemlab%2Fengram/lists"}