Skip to content

Repository files navigation

Engram

Brain-inspired long-term memory for Claude Code — tiered, self-forgetting, auto-consolidating. Injects relevant memory at session start and consolidates at session end. One Rust binary, zero deps, no vector DB.

English | 中文

Using Codex instead of — or alongside — Claude Code? There's a Codex adapter too: engram-codex. Same engine, shared memory store (~/.engram + per-project .engram/), so memories are common to both CLIs.


Why

Most "memory" for AI agents dumps everything into a vector database and stuffs chunks back into the prompt — token-heavy, noisy, and awkward to actually use. Engram takes the opposite approach, modeled on how human memory works:

  • Remember the gist, not the details. Each memory is a one-line cue + a pointer to the ground truth (file:line, a doc, a URL). You recall the cue, then follow the pointer when you need detail — verification, not reconstruction.
  • Store the complement of your artifacts. Your code is already the perfect detail store (grep finds it). Engram only stores what the code doesn't capture: intent, decisions, dead-ends, the "why".
  • Forget the noise. Memories decay over time (ACT-R-style) unless reinforced by real use; low-value ones demote out of the hot set. Forgetting = demotion, not deletion.

The result: a tiny, always-relevant hot index in your context, plus a much larger searchable cold storewithout a vector database.

Install

/plugin marketplace add jimhy/engram
/plugin install engram
/reload-plugins

/reload-plugins (or restart a session) applies it; approve the hooks in /hooks if prompted. The engine is a single self-contained Rust binary shipped with the plugin — nothing else to install.

Update

/plugin marketplace update engram-marketplace
/plugin update engram
/reload-plugins

Then /doctor should report no plugin errors. (If /plugin update doesn't pick up the new version, /plugin uninstall engram then /plugin install engram re-clones the latest.)

What you get

Automatic memory, both directions:

Hook What it does
SessionStart Injects the hot index (relevant memory) into context; also catches up any consolidation a previous session didn't finish (crash / abrupt exit)
UserPromptSubmit Re-resolves the current project from the nearest .engram/ anchor and re-injects its L4 — only when the project scope (root) changes
SessionEnd Spins up an independent reviewer that consolidates only the increment since the last watermark (token-thrifty on long / resumed sessions): writes new memories, promotes/demotes, supersedes, merges

Slash commands: /engram list · /engram recall <query> · /engram status · /engram render · /engram root · /engram statusline [on|off]

Status-line indicator (optional, off by default): ● Engram | L1:2 L2:0 L3:1

How it works

Memory is tiered, like human memory:

Tier Role Decay
L1 "subconscious" — core identity / preferences almost never (high floor)
L2 important slow
L3 ordinary medium
L4 per-project, lives in <project>/.engram/engram.redb scoped to the project, located via the .engram/ anchor

Each tier also has a character budget (token governance): at consolidation the entry cap and the cumulative rendered-character budget act as dual constraints — whichever trips first wins — keeping the resident injection cost constant.

  • Activation = importance + recency + frequency (ACT-R base-level), with a per-tier floor so L1 stays put.
  • Climbing requires earned activation; falling is cushioned by the floor and a grace period — new and important memories aren't killed early.
  • Consolidation runs at session end via an independent claude -p reviewer reading the transcript, so the judgment of "what was actually used / worth keeping" isn't self-serving.

What goes in each tier

A memory is only worth keeping if it can't be cheaply recovered from the code/docs/git — engram stores the complement of your artifacts (intent, the "why", dead-ends, decisions, open loops), distilled into a one-line cue + a pointer to the ground truth.

General — cross-project, in the shared store (~/.engram/general.redb):

  • L1 — core identity & always-on global rules: who you are, how to address you, language, hard global conventions. Tiny, almost never forgotten.
  • L2 — important reusable knowledge that holds across projects (a tool gotcha, a durable preference).
  • L3 — ordinary, easily-forgotten general notes.

Per-project — L4, in that project's store (<project>/.engram/engram.redb):

  • L4.1 — project hard rules: the inviolable conventions / taboos for this repo, learned from your "always / never" directives or hard-won corrections. Not a copy of CLAUDE.md / lint configs (those are auto-loaded artifacts); L4.1 holds what they don't say.
  • L4.2 — durable project knowledge: what the project is, its architecture / module mental-map (what each part does and why it's split that way — distilled, not an ls dump), and settled / debated decisions (what was chosen, what was rejected and why — so a later session won't re-propose a dead option).
  • L4.3 — fast-decay tier: low-importance, short-lived memories (current progress, short-lived open loops, hand-off-able work land here naturally). Tiers are not bound to content types — an important long-lived open loop goes to a higher tier by its importance; verified done / stale entries get deleted.

Golden rule: store the distilled mental model, never what a single grep / ls already gives you. File locations live in the pointer, not the cue.

Where memory lives

  • Shared (cross-project L1-3): ~/.engram/general.redb (auto-created)
  • Per-project (L4): <project>/.engram/engram.redb (travels with the project)

Storage is redb (embedded, single-file, ACID) — no server, no external database.

Inspect / verify

/engram status            # counts per tier, projects, cold store, reviewer health
/engram list              # list everything
/engram recall <query>    # search (hot + cold)
/engram render            # preview what gets injected
engram export --dir <dir> # full JSON export (backup / migration, engine binary)
engram doctor --general-db ~/.engram/general.redb [--json]  # read-only health check: data version / per-tier distribution / bad rows / over-budget tiers / future timestamps / dangling pointers / off-anchor importance / duplicates (never writes)

Backup & migration

The official path is export / import (symmetric inverses; one JSON per memory with every field including schema_version):

# Backup: export shared + project libraries into a directory (<id>.json per memory)
engram export --general-db ~/.engram/general.redb --project-db name=path --dir ./backup
# Optional filters: --project <name> for one project; --status active for the hot tiers only

# Restore / migrate: import back on the target machine (L1-3 → shared, L4 routed via --project-db)
engram import --general-db ~/.engram/general.redb --project-db name=path --from-json-dir ./backup

Copying the redb files (general.redb / engram.redb) directly also works, but only while no session is active (hooks may hold the write lock at any moment; a hot copy can capture a torn transaction). For cross-machine migration prefer export/import — import also clamps bogus future timestamps to now (clock-skew / rollback sanitization).

Version migration (automatic, hands-off): when the engine's data version bumps, the first session after the upgrade auto-migrates once, backing up first (to <general-db parent>/backups/, one JSON per memory, restorable with import). Migration is best-effort and never blocks the session; once done it won't repeat. To inspect read-only first, or run it by hand:

engram doctor  --general-db ~/.engram/general.redb [--json]    # read-only check, never writes
engram migrate --general-db ~/.engram/general.redb --if-needed # one-shot migration (backs up first); add --dry-run to preview without writing

Status line (optional, off by default)

The engram status line is off by default — installing the plugin won't show it. To toggle the live ● Engram | L1:n L2:n L3:n indicator:

/engram:statusline on      # enable (no argument is the same as on)
/engram:statusline off     # disable (removes the config; leaves any status line you set for other tools untouched)

on pins the status-line script to ~/.engram/engram-statusline.sh (a stable, version-independent path), merges statusLine.command into your user-level settings.json, and tells you to restart. The content is driven by ~/.engram/status.txt, which the hooks refresh every turn — no DB hit. If you also have claude-hud installed, its line is prepended automatically; if not, only the Engram segment shows. off removes only the entry engram wrote, never a statusLine you configured for another tool.

Why off by default, and why this step: statusLine is user-level config that a plugin cannot ship automatically (plugin.json has no such field) — that's both why it's off by default and why this command writes it into your settings.json for you. Plugin upgrades need no reconfiguration — only re-run /engram:statusline on if a future upgrade changes the status-line script itself.

Configuration

  • ENGRAM_REVIEWER_CLI — which CLI the SessionEnd reviewer launches (default claude). Set it if your CLI isn't named claude (e.g. a local build).
  • ENGRAM_REVIEWER_PROXY — explicitly set the proxy for the reviewer subprocess (e.g. http://127.0.0.1:7897). Takes priority over any existing HTTPS_PROXY/ALL_PROXY and the system proxy.

Proxy environment

The reviewer is a headless claude -p subprocess spawned by a hook. If your claude reaches Anthropic through a local proxy, make sure HTTPS_PROXY (not just all_proxy) is visible to the hook subprocess — otherwise it goes direct and Anthropic rejects it with a region-limited "403 Request not allowed" (the review silently fails; ~/.engram/hook.log shows a 403 / not allowed diagnostic line). Before launching the reviewer engram derives the proxy automatically, in priority order: ENGRAM_REVIEWER_PROXY (explicit) > an existing HTTPS_PROXY/https_proxy (inherited) > ALL_PROXY/all_proxy (derived from) > (Windows only) the system proxy registry under HKCU\...\Internet Settings. Usually no manual setup is needed; if auto-derivation misses, point it explicitly with ENGRAM_REVIEWER_PROXY.

Platforms & releases

bin/engram is a small launcher that picks the right binary for your OS. Pushing a tag (v*) runs GitHub Actions (.github/workflows/release.yml) to cross-compile Windows / Linux x86_64 / macOS x86_64 / macOS arm64, commit the binaries into bin/, and attach them to a GitHub Release. (Linux arm64 isn't built yet — PRs welcome.)

Engine source lives in engine/ (Rust). Build locally with cargo build --release inside engine/.

On Windows, hooks run under bash, so paths use forward slashes (handled by the bundled launcher/scripts).

License

Apache License 2.0 — see LICENSE. Third-party dependency licenses are listed in THIRD-PARTY-NOTICES.md.

About

Brain-inspired long-term memory for Claude Code — tiered, self-forgetting, auto-consolidating. Injects relevant memory at session start and consolidates at session end. One Rust binary, zero deps, no ▎ vector DB.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages