▍log
0x0000

 record · seq=0001 · type=meta

Memory that
outlives the
context window.

Agents start every session with amnesia — so you re-paste your stack, conventions, and past decisions into every prompt, and pay for it in tokens. AegisDB is the memory layer that keeps that knowledge and feeds back only what's relevant, per prompt.

written in C
NDJSON / TCP
vector · tag · time
MIT
0x00D0

 record · seq=0002 · type=semantic

Why not Redis, SQLite, or a vector store?

You almost certainly run a database already. None of them was built to remember the way an agent needs to.

A vector store recalls by similarity but has no notion of an event, a fact that gets corrected, or context that should expire. A cache forgets on its own timer. A relational table stores rows but can't rank by meaning. Agent memory is all of these at once — so AegisDB makes each its own kind, with the lifecycle it actually needs.

what each one remembers

redis       fast, but evicts on its own TTL
sqlite      durable rows, no recall by meaning
pgvector    similarity only — no events, TTL, or graph
aegisdb     events, facts, working + a graph, each lifecycled
0x0140

 record · seq=0003 · type=semantic

Stop paying to re-teach the model.

Every session normally re-pastes your stack, conventions, and past decisions into the prompt. AegisDB keeps that knowledge out of the window and feeds back only what's relevant, per prompt — so you pay for the work, not for re-establishing context.

  • Recall, don't re-explain — your stack, conventions, and past decisions are already known, so you stop re-pasting them each session.
  • A relevant slice, not a dump — each prompt pulls only the top-ranked memories — ranked by similarity × importance — instead of replaying entire transcripts; the model never sees the rest.
  • Short sessions, full knowledge — start fresh instead of dragging a giant transcript whose every turn re-bills the whole context.
  • Distilled & shared — capture stores salient outcomes, not raw logs, and a team reuses context established once.
0x01A0

 record · seq=0004 · type=semantic

A memory model shaped like memory.

Three kinds of memory, each with the lifecycle it actually needs — not one generic store with a TTL bolted on. Persisted memories are durable by default, and can be set to auto-archive after a deadline when you want them to fade.

episodic — immutable events semantic — facts that update working — volatile, expires

Episodic events

Append-only records of what happened. Written once, never rewritten — the source of truth every index is rebuilt from.

Semantic facts

Updatable knowledge where the latest version wins. Correct a fact and the old one steps aside, no duplicates left behind.

Working memory

A per-session ring buffer with a TTL. Keep scratch context close, then promote what proves worth keeping.

Recall, three ways

Search by vector similarity, by tags (all/any), or by time range — each on a purpose-built index, not a scan.

Vector search that scales

Exact cosine while a set is small; past a threshold it switches to an HNSW graph for sublinear approximate-nearest-neighbour search, so recall stays fast as memories accumulate. The graph is checkpointed — a restart reloads it instead of rebuilding — and vectors can be int8-quantized to cut its memory ~4×.

A graph of context

Link memories with directed edges and walk them breadth-first to pull in what's related to what you just recalled.

Built for production — and more
  • Ranked like memory — similarity × importance × confidence, with opt-in recency decay and a minimum-score gate.
  • Crash-safe log — magic + CRC frames; a torn tail is trimmed and interior bit-rot skipped, so one bad record never costs you the log.
  • Multi-tenant isolation — namespace + scope (ro/rw/admin) tokens; a tenant sees only its own memories.
  • Per-tenant quotas + rate limits — bound one namespace's records, bytes, and request rate.
  • Encryption at rest — optional XChaCha20-Poly1305 over the log + checkpoints (vendored, no deps), with an offline migrator.
  • Tunable durabilitysync/batch/interval fsync; checkpoint + non-blocking compaction recovery.
  • Read replicas — async log-shipping standbys for read scaling and manual failover.
  • Online backup + restore — consistent point-in-time snapshots, no downtime.
  • Memory-bounded — a soft index-RAM cap backpressures instead of getting OOM-killed.

Full reference in the README & docs.

0x0500

 record · seq=0005 · type=semantic

Fast enough to be invisible.

Recall sits in the agent's inner loop, so latency is the whole game. AegisDB keeps vector search sub-millisecond as memories pile up — exact while a set is small, an HNSW graph past a threshold, so recall stays fast without losing accuracy.

These are AegisDB's own numbers, not a comparison — and you can reproduce them yourself: make bench (vector recall + latency) and make wire-bench (end-to-end over TCP).

make bench · make wire-bench

vector recall   0.14 ms @ 10k · 0.22 ms @ 100k
recall@10       1.00  (384-dim, HNSW)
ping            158k ops/s · p50 0.05 ms
read (get)      p50 0.8 ms over the wire

measured on a 2023 laptop i7, loopback
0x0640

 record · seq=0006 · type=semantic

One JSON line in. One JSON line back.

The wire protocol is newline-delimited JSON over TCP. No SDK, no driver — any language that can open a socket can speak it.

store a memory, then recall it

# write an episodic memory
{"operation":"insert", "type":"episodic", "tags":["user"], "data":"Prefers dark mode"}
 {"ok":true, "record":{"id":1, "type":"episodic"}}

# recall it by tag
{"operation":"search", "tags":["user"], "top_k":5}
 {"ok":true, "total":1, "records":[ … ]}

operations  ·  ping insert get update delete search count promote relate traverse stats

insert takes a batch of records in one call; delete and count work by id or by filter (tags / type / time range).

stats reports durability lag, live & tombstone counts, log size, and per-index sizes — for monitoring and capacity planning.

0x07A0

 record · seq=0007 · type=semantic

Long-term memory for Claude Code.

An MCP server plus session hooks: relevant memories are recalled into context on every prompt, and the ones worth keeping are captured when the session ends.

  • Automatic recall on each prompt, inside a strict time budget.
  • Automatic capture at session end, filtered by salience.
  • Per-project namespaces — isolated by default, shared by choice.
  • No cloneuvx fetches the published package (aegisdb-mcp on PyPI) on demand.
  • One-command setupuvx --from aegisdb-mcp aegisdb-init writes the config below and the hooks; or install the /aegis-setup skill and let Claude do it.
  • Fails open — if the backend is down, your session keeps working.

.mcp.json — scaffolded by aegisdb-init

{
  "mcpServers": {
    "memory": {
      "command": "uvx",
      "args": ["aegisdb-mcp"],
      "env": {
        "AEGIS_NAMESPACE": "my-project",
        "AEGIS_EMBEDDING_DIMENSIONS": "1024"
      }
    }
  }
}
0x0940

 record · seq=0008 · type=episodic

Run it, talk to it.

Pull the image or build from source — either way you're holding a connection in seconds.

01

Run it — prebuilt multi-arch image, no toolchain

docker run -d --name aegisdb -p 9470:9470 -v aegis-data:/data ghcr.io/d4n-larsson/aegisdb:latest
02

…or build from source

git clone https://github.com/d4n-larsson/aegisdb && cd aegisdb && make ./build/aegisdb --data-dir ./data --port 9470
03

Talk to it — the binary is also the client

docker exec aegisdb aegisdb client put --tags user "prefers dark mode" docker exec aegisdb aegisdb client search --tags user
04

Read the reference

The wire-protocol reference and quickstart cover every operation.

0x0B20

 record · seq=0009 · type=meta

Set up shared memory for a team.

One server, one tenant token per project, and Claude Code wired in with uvx — no clone anywhere. Uses the published image and the aegisdb-mcp PyPI package.

01

Mint a tenant token

docker run --rm ghcr.io/d4n-larsson/aegisdb \ gen-token --namespace my-project --scope rw

Prints a hashed token-file line and the one-time token. Append the line to tokens.txt; keep the token for step 3.

02

Run the server — authenticated, durable

docker run -d --name aegisdb -p 9470:9470 \ -v aegis-data:/data -v "$PWD/tokens.txt:/tokens.txt:ro" \ ghcr.io/d4n-larsson/aegisdb:latest \ --data-dir /data --embedding-dim 1024 --auth-token-file /tokens.txt

Tokens travel in plaintext — keep the port on a private network or behind a TLS-terminating proxy. For a shared box, add --encryption-key-file (see gen-key) to encrypt the data volume at rest.

03

Point Claude Code at it — .mcp.json

{ "mcpServers": { "memory": { "command": "uvx", "args": ["aegisdb-mcp"], "env": { "AEGIS_HOST": "memory.internal", "AEGIS_PORT": "9470", "AEGIS_AUTH_TOKEN": "<token from step 1>", "AEGIS_EMBEDDING_DIMENSIONS": "1024" } } } }

The token's namespace is authoritative — no AEGIS_NAMESPACE needed. uvx fetches the package on demand (install uv once). Or skip the hand-editing: uvx --from aegisdb-mcp aegisdb-init --host memory.internal --auth-token <token> writes this and the hooks.

04

Enable auto recall & capture — .claude/settings.json

{ "hooks": { "UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "uvx --from aegisdb-mcp aegisdb-recall-hook" } ] } ], "SessionEnd": [ { "hooks": [ { "type": "command", "command": "uvx --from aegisdb-mcp aegisdb-capture-hook" } ] } ] } }

Relevant memories are recalled into context each prompt; salient outcomes are captured at session end.

05

Onboard a teammate

They repeat step 1 for their own token (their own --namespace for isolation, or a shared one to pool memory) and steps 3–4. No clone, no build.

Full step-by-step walkthrough — quotas, encryption at rest, backups & troubleshooting: the team server tutorial.