{"slug": "aegisdb-self-hosted-memory-for-ai-agents-in-one-c-binary", "title": "AegisDB – self-hosted memory for AI agents, in one C binary", "summary": "AegisDB, a self-hosted memory database for AI agents, has been released as a single C binary with multi-tenant support, encryption, backups, and observability. The tool provides durable long-term memory for AI agents, including episodic history, semantic facts with vector search, and working memory, while keeping data on the user's infrastructure. It includes a native integration with Claude Code and is designed for production use with crash recovery and security features.", "body_md": "Self-hosted memory for your AI agents.One small C binary — multi-tenant, encrypted, with backups, read replicas, and a one-command Prometheus + Grafana stack. Your agents' memory stays on your box; nothing ships to a SaaS.\n\nAI agents forget everything between sessions. **AegisDB** gives them durable,\nsearchable long-term memory — episodic history, semantic facts with vector\nsearch, and volatile working memory — behind a dead-simple JSON-over-TCP\nprotocol, with a first-class [Claude Code](#use-as-claude-code-memory)\nintegration. It's a single dependency-free binary you run yourself: your data,\nyour box, no third party in the loop.\n\nRun the server — no clone, no toolchain (prebuilt multi-arch image on GHCR):\n\n```\ndocker run -d --name aegisdb -p 9470:9470 -v aegis-data:/data \\\n  ghcr.io/d4n-larsson/aegisdb:latest\n```\n\nTalk to it — the same binary is also the client:\n\n```\ndocker exec aegisdb aegisdb client ping\ndocker exec aegisdb aegisdb client put --type semantic --tags user \"prefers dark mode\"\ndocker exec aegisdb aegisdb client search --tags user --top-k 5\n```\n\nWant the **whole observability stack** (server + Prometheus + a pre-built Grafana\ndashboard) in one command? Clone this repo and:\n\n```\ndocker compose --profile monitoring up      # dashboard on http://127.0.0.1:3000\n```\n\nGiving **Claude Code** a persistent memory is a one-liner (with a server\nrunning): `uvx --from aegisdb-mcp aegisdb-init`\n\n— see\n[Use as Claude Code memory](#use-as-claude-code-memory).\n\n**Self-hosted & private.** Your agents' memory never leaves your infrastructure — no SaaS, no per-token billing, no data-sharing. Encrypt it at rest with one flag.**One binary, no dependencies.** Written in C; the only vendored code is cJSON and the crypto. No JVM, no Python runtime, no external database to babysit.**Built for teams.** Multi-tenant auth (per-namespace, scoped tokens), per-tenant quotas + rate limits, online backups, read replicas, and turnkey Prometheus/Grafana observability.**Claude Code native.** Ships an MCP server + hooks so Claude remembers across sessions — installable with a single command.**Production-minded.** Corruption-resilient append-only log, crash recovery, a documented security review, and CI that runs ASan/UBSan/TSan plus continuous fuzzing.\n\n**Durable episodic memory**— append-only log with magic + CRC32 framing, corruption-resilient recovery, and legacy-log migration** Semantic facts**— updateable records (latest version wins)** Working memory**— volatile per-session ring buffer with TTL and promotion** Retrieval**— lookup by ID, time-range search, tag search (`all`\n\n/`any`\n\n), semantic (embedding) search ranked by cosine similarity weighted by importance × confidence;`count`\n\nand`consolidate`\n\n(dedup) over the same filters**Semantic scale**— exact cosine while small; past`--ann-threshold`\n\nan HNSW graph for sublinear approximate top-K, built off the write path and sharded so the build parallelizes (`--ann-shard-target`\n\n), optionally int8-quantized**Relationships**— directed edges between records, graph traversal, and agent-namespace isolation** Multi-tenant auth**— optional bearer tokens (constant-time check;`ping`\n\nexempt), each bound to a namespace + scope (`ro`\n\n/`rw`\n\n/admin) so one server safely isolates many tenants**Per-tenant limits**— optional storage quotas (records/bytes) and a request rate limit per namespace, so one team member's runaway agent can't fill the disk or monopolize the shared server**Encryption at rest**— optional XChaCha20-Poly1305 (vendored, no crypto dependency) over the log + checkpoints; opt-in via`--encryption-key-file`\n\n, with an offline migrator and encrypted backups/replicas**Observability**—`stats`\n\nop plus a drop-in[Prometheus exporter + Grafana dashboard](/d4n-larsson/aegisdb/blob/main/integrations/prometheus-exporter)(`docker compose --profile monitoring up`\n\n)**Operations**— online`snapshot`\n\n/restore backups and read replicas**Concurrency**— sharded`poll()`\n\nevent-loop threads (`--io-threads`\n\n); selectable`fsync`\n\ndurability (`sync`\n\n/`batch`\n\n/`interval`\n\n)\n\n- Linux (primary target) with GCC 11+ or Clang 14+\n- One of: CMake 3.20+\n**or** GNU Make - Python 3.8+ (optional, for the example client below)\n\n```\ncmake -B build -DCMAKE_BUILD_TYPE=Release\ncmake --build build\nctest --test-dir build --output-on-failure   # runs the unit test suite\nmake             # builds build/aegisdb\nmake test        # builds and runs the C unit tests\nmake integration # wire-protocol contract tests (launches the server)\nmake check       # unit + integration\nmake clean\n```\n\nThe server binary is produced at `build/aegisdb`\n\n.\n\nPrebuilt multi-arch images (`linux/amd64`\n\n, `linux/arm64`\n\n) are published to GitHub\nContainer Registry on every push to `main`\n\nand every release tag — no clone or\ntoolchain needed:\n\n```\ndocker run -p 9470:9470 -v aegis-data:/data ghcr.io/d4n-larsson/aegisdb:latest\n# or pin a release: ghcr.io/d4n-larsson/aegisdb:0.1.0\n```\n\nTo build it yourself instead, a multi-stage `Dockerfile`\n\n(Debian-slim) compiles\nthe server and ships a minimal runtime image. Data persists in a named volume at\n`/data`\n\n.\n\n```\n# Build and run with Docker Compose\ndocker compose up --build        # serves on localhost:9470\n\n# Or build and run the image directly\ndocker build -t aegisdb .\ndocker run -p 127.0.0.1:9470:9470 -v aegis-data:/data aegisdb\n```\n\nCompose is configured by an optional `.env`\n\nfile — copy the template and edit:\n\n```\ncp .env.example .env             # then tweak port, durability, tenant limits, …\ndocker compose up --build\n```\n\nEvery setting has a default, so `.env`\n\nis optional. It exposes the common flags\nas named vars (`AEGIS_PORT`\n\n, `AEGIS_EMBEDDING_DIM`\n\n, `AEGIS_DURABILITY`\n\n,\n`AEGIS_TENANT_MAX_RECORDS`\n\n, …) plus `AEGIS_EXTRA_ARGS`\n\nfor anything else\n(`--auth-token-file`\n\n, `--io-threads`\n\n, ANN tuning, …). See\n[ .env.example](/d4n-larsson/aegisdb/blob/main/.env.example) for the full list.\n\nTo skip building, point\n\n`docker-compose.yml`\n\nat the published image: replace`build: .`\n\nwith`image: ghcr.io/d4n-larsson/aegisdb:latest`\n\n.\n\nThe image ships a `HEALTHCHECK`\n\nthat uses the binary's built-in `--health-check`\n\nprobe (no extra tooling in the image), so `docker ps`\n\nand Compose\n`depends_on: condition: service_healthy`\n\nreflect real server liveness.\n\nThe container runs as an unprivileged user. The server listens on `0.0.0.0:9470`\n\n*inside* the container, but Compose publishes that port on the host's loopback\n(`127.0.0.1`\n\n) only by default — because the wire protocol is unauthenticated and\nplaintext out of the box, it must not be reachable off-box until you secure it.\nTo expose it deliberately, set `AEGIS_BIND=0.0.0.0`\n\n(or a specific host IP) in\n`.env`\n\n, and first enable authentication: mount a token file into `/data`\n\nand add\n`--auth-token-file /data/tokens.txt`\n\n(to `AEGIS_EXTRA_ARGS`\n\nunder Compose; see\n[Authentication](#authentication)). Even with auth, tokens travel in plaintext,\nso terminate TLS at a trusted proxy for any non-loopback exposure. Override other\nflags by appending them to the run command, e.g. `docker run aegisdb --embedding-dim 1024`\n\n, or (with Compose) via `.env`\n\n.\n\n```\n./build/aegisdb --data-dir ./data --port 9470\n```\n\nExpected startup output:\n\n```\n2026-06-28 12:00:00.000 INFO  [aegisdb] AegisDB 0.1.0 starting (log level: info)\n2026-06-28 12:00:00.000 WARN  [aegisdb] no auth tokens configured; ...\n2026-06-28 12:00:00.000 INFO  [aegisdb] recovery complete: N records loaded\n2026-06-28 12:00:00.000 INFO  [aegisdb] listening on 0.0.0.0:9470\n2026-06-28 12:00:00.000 INFO  [aegisdb] data directory: ./data\n```\n\nLogs go to stderr as `<timestamp> <LEVEL> [aegisdb] <message>`\n\n. Control the\nverbosity with `--log-level error|warn|info|debug`\n\n(default `info`\n\n) or the\n`AEGISDB_LOG_LEVEL`\n\nenvironment variable — the flag takes precedence. At\n`debug`\n\n, the server logs every accepted connection and dispatched operation.\n\nThe `WARN`\n\nline appears only when the server is started without\n`--auth-token`\n\n/`--auth-token-file`\n\n(see [Authentication](#authentication)).\n\nThe same binary is also a client — no `nc`\n\n, no hand-written JSON:\n\n```\naegisdb client ping\naegisdb client put --type semantic --tags user \"prefers dark mode\"\naegisdb client get 1\naegisdb client search --tags user --top-k 5\naegisdb client stats\n```\n\nHost, port, and token default to `$AEGIS_HOST`\n\n/ `$AEGIS_PORT`\n\n/ `$AEGIS_TOKEN`\n\n(`127.0.0.1`\n\n/ `9470`\n\n/ none) or `--host`\n\n/`--port`\n\n/`--token`\n\n. The exit code is\n`0`\n\non an ok response, so it scripts cleanly. Inside Docker:\n`docker exec aegisdb aegisdb client stats`\n\n.\n\nTo create a tenant token, `gen-token`\n\nprints a ready token-file line (hashed)\nand the one-time plaintext token:\n\n``` bash\n$ aegisdb gen-token --namespace acme --scope rw\nsha256$… acme rw          # paste into your --auth-token-file\ntoken: 9f3c…              # give to the client (AEGIS_TOKEN); not recoverable\n```\n\n| Flag | Default | Description |\n|---|---|---|\n`--data-dir <path>` |\n`./data` |\nPersistence directory |\n`--port <n>` |\n`9470` |\nTCP listen port |\n`--phase <1-4>` |\n`4` |\nHighest enabled feature phase (gates operations) |\n`--io-threads <n>` |\n2× CPUs (8–64) | `poll()` event-loop threads for dispatch parallelism (does not cap concurrent connections). Alias: `--workers` |\n`--max-payload <bytes>` |\n`1048576` |\nMax `data` size (1 MiB) |\n`--embedding-dim <n>` |\n`384` |\nExpected embedding vector length |\n`--ann-threshold <n>` |\n`10000` |\nLive vectors before semantic search switches from exact scan to the HNSW graph |\n`--ann-ef-search <n>` |\nHNSW default | HNSW query beam width (recall/latency knob) |\n`--ann-shard-target <n>` |\n`25000` |\nTarget vectors per HNSW shard; the graph splits into ~`count/n` shards (capped by CPUs) so the build parallelizes |\n`--ann-quantize` |\noff | Store HNSW vectors as int8 (~4× less memory, small recall cost) |\n`--durability <mode>` |\n`interval` |\n`sync` (fsync per write), `batch` (per `--fsync-batch` records), or `interval` (per `--fsync-interval-ms` ) |\n`--fsync-batch <n>` |\n`1000` |\nRecords between `fsync` calls in `batch` mode |\n`--fsync-interval-ms <n>` |\n`1000` |\nFlush cadence in `interval` mode (floored at the ~1s maintenance tick) |\n`--checkpoint-sec <n>` |\n`60` |\nIndex checkpoint cadence so recovery replays only the tail; `0` disables |\n`--compact-sec <n>` |\n`300` |\nLog-compaction check cadence; compacts only when enough of the log is dead; `0` disables |\n`--tenant-max-records <n>` |\n`0` |\nPer-namespace live-record cap (`0` = unlimited); enforced only when auth is enabled |\n`--tenant-max-bytes <n>` |\n`0` |\nPer-namespace live-byte cap (`0` = unlimited) |\n`--tenant-rate-qps <n>` |\n`0` |\nPer-namespace request rate limit in req/s, burst = 1s (`0` = unlimited) |\n`--max-index-bytes <n>` |\n`0` |\nSoft cap on in-RAM index size; inserts return `MEMORY_LIMIT` past it so a growing dataset backpressures instead of getting OOM-killed (accepts `K` /`M` /`G` ; `0` = unlimited). Watch `stats.memory` . |\n`--replication-port <n>` |\n— | Serve the read-replica log stream on this port (primary; requires `--replication-token` ) |\n`--replication-token <t>` |\n— | Token to subscribe to / follow the replication stream |\n`--replicate-from <h:p>` |\n— | Follow this primary's replication port as a read-only replica (implies `--read-only` ) |\n`--read-only` |\noff | Refuse client writes (`READ_ONLY` ) |\n`--working-capacity <n>` |\n`256` |\nWorking-memory ring buffer size |\n`--restore <dir>` |\n— | One-shot: install the snapshot at `<dir>` into an empty `--data-dir` , then exit |\n`--log-level <level>` |\n`info` |\n`error` , `warn` , `info` , or `debug` (also `$AEGISDB_LOG_LEVEL` ) |\n`--auth-token <token>` |\n— | Accept this global admin token (repeatable) |\n`--auth-token-file <path>` |\n— | Accept tokens, one per line: `<token> [namespace] [ro|rw|admin]` ; a token may be `sha256$<hex>` (hashed at rest) |\n`--hash-token <token>` |\nPrint the token's `sha256$<hex>` form and exit (paste into the token file) |\n|\n`--encryption-key-file <path>` |\n— | Encrypt the log + checkpoints at rest with the 32-byte key (64 hex chars) in `<path>` (\n|\n`--encrypt-migrate` |\nRewrite `--data-dir` 's plaintext log encrypted (needs `--encryption-key-file` ) and exit |\n|\n`--health-check` |\nProbe a local server on `--port` , print nothing, exit 0 if healthy / 1 otherwise |\n|\n`--help` |\nShow usage |\n\nSetting up a shared server for a team? Follow the step-by-step\n\n[team server tutorial]instead of assembling the flags below by hand.\n\nWith no `--auth-token`\n\n/`--auth-token-file`\n\n, the server runs **without\nauthentication** and every request is served with unrestricted access. When\ntokens are configured, each request must carry a matching `\"token\"`\n\nfield\n(except `ping`\n\n, which is always exempt) or the server returns `UNAUTHORIZED`\n\n.\nTokens are compared in constant time.\n\nEach token in the token file is bound to a **namespace** and a **scope**:\n\n```\nadmin-key                 # global admin: any namespace, all operations\nacme-key      acme   rw   # tenant \"acme\", read+write\nacme-view     acme   ro   # tenant \"acme\", read-only\nbeta-key      beta   rw   # tenant \"beta\"\n```\n\nA namespaced token can only write into its own namespace (`agent_id`\n\nis pinned\nautomatically) and only read its own records — another tenant's records read\nback as `NOT_FOUND`\n\n. Read-only tokens are refused writes with `FORBIDDEN`\n\n, and\n`stats`\n\nis admin-only. This lets one server back many isolated tenants/agents.\n\nTokens can also be managed **at runtime** (no restart) by an admin token via the\n`token_list`\n\n/ `token_add`\n\n/ `token_revoke`\n\noperations — a revoked token stops\nauthenticating immediately, and changes persist back to `--auth-token-file`\n\n(rewritten hashed). Tokens are referenced by a fingerprint id, so they can be\nlisted and revoked without exposing the secret. See\n[ docs/wire-protocol.md](/d4n-larsson/aegisdb/blob/main/docs/wire-protocol.md).\n\nTokens can be **stored hashed** so a leaked token file reveals nothing usable.\nRun `aegisdb --hash-token <tok>`\n\nto get its `sha256$<hex>`\n\nform and put that in\nthe token file; clients still send the plaintext token, which the server hashes\nand compares in constant time. Use high-entropy tokens (`openssl rand -hex 32`\n\n).\n\nTokens are sent in plaintext, so run the server behind an encrypted channel — a\nTLS-terminating reverse proxy (nginx/Caddy), `stunnel`\n\n, or a private network.\nTLS is intentionally kept out of the binary to preserve the single,\ndependency-free build.\n\nThe log and index checkpoints can be encrypted on disk with XChaCha20-Poly1305 (vendored — no crypto dependency added), so a stolen disk, volume snapshot, or backup tarball reveals nothing without the key. Mint a key and start with it:\n\n```\naegisdb gen-key > key.hex           # 32-byte key, 64 hex chars; store it 0600\naegisdb --data-dir ./data --encryption-key-file key.hex\n```\n\n**Opt-in and per-directory.** A data dir created without a key stays plaintext. On a*new*dir the key encrypts from the first write; to convert an*existing*plaintext dir, run the offline one-shot`aegisdb --encrypt-migrate --data-dir ./data --encryption-key-file key.hex`\n\n.**Fail-closed.** The server refuses to start if the key does not match the dir (wrong key, or a key given for a plaintext dir / no key for an encrypted one).**Backups** stay encrypted;`--restore`\n\nrequires the same key (the snapshot manifest records a non-secret key fingerprint and is checked before restoring).**Replicas** must be configured with the**same**`--encryption-key-file`\n\n; the subscribe handshake rejects a key mismatch. Each node encrypts its own log with the key.**Scope.** This protects data*at rest*. It is not a transport control (the wire, including replication, is still plaintext — front it with a proxy as above) and does not protect a running process's memory. Keep the key safe and separate from the data dir; without it the data is unrecoverable.\n\nNewline-delimited JSON (NDJSON) over TCP — one JSON object per line per\nrequest/response. See [ docs/wire-protocol.md](/d4n-larsson/aegisdb/blob/main/docs/wire-protocol.md)\nfor the full contract.\n\n```\n# Health check\necho '{\"operation\":\"ping\"}' | nc -q1 localhost 9470\n\n# Insert an episodic memory\necho '{\"operation\":\"insert\",\"type\":\"episodic\",\"tags\":[\"user\",\"preference\"],\"data\":\"User likes coffee\"}' | nc -q1 localhost 9470\n\n# Retrieve by ID\necho '{\"operation\":\"get\",\"id\":1}' | nc -q1 localhost 9470\n\n# Time-range search\necho '{\"operation\":\"search\",\"start_time\":0,\"end_time\":9999999999999,\"top_k\":10}' | nc -q1 localhost 9470\n\n# Tag search\necho '{\"operation\":\"search\",\"tags\":[\"user\"],\"match\":\"all\",\"top_k\":10}' | nc -q1 localhost 9470\n```\n\nSupported operations: `ping`\n\n, `insert`\n\n(episodic/semantic/working, single or\nbatch), `get`\n\n, `update`\n\n(semantic), `delete`\n\n(by id or query), `search`\n\n(time/tags/embedding), `count`\n\n, `consolidate`\n\n, `promote`\n\n, `relate`\n\n, `traverse`\n\n,\n`stats`\n\n, `snapshot`\n\n, and token administration (`token_list`\n\n/`token_add`\n\n/`token_revoke`\n\n).\n\n``` php\nimport socket, json\n\ndef request(payload: dict) -> dict:\n    with socket.create_connection((\"localhost\", 9470)) as s:\n        s.sendall((json.dumps(payload) + \"\\n\").encode())\n        return json.loads(s.recv(65536).decode())\n\nprint(request({\"operation\": \"ping\"}))\nprint(request({\"operation\": \"insert\", \"type\": \"episodic\",\n               \"tags\": [\"demo\"], \"data\": \"Hello from quickstart\"}))\nsrc/\n├── main.c              # Entry point, CLI args, client subcommands\n├── server/             # TCP NDJSON server, sharded poll() event loops\n├── protocol/           # JSON request parsing / response building\n├── query/              # Operation router / query engine\n├── storage/            # Append-only log, hash/time/tag/semantic indexes,\n│                       #   compaction, recovery\n├── memory/             # MemoryRecord encode/decode, working buffer\n└── util/               # CRC32, SHA-256, config, health check, client, logging\ninclude/aegisdb/        # Public headers\ntests/                  # unit/, integration/, contract/\nthird_party/            # Vendored cJSON and Unity\ndata/                   # Runtime data (gitignored)\n```\n\nAegisDB persists `episodic`\n\nand `semantic`\n\nrecords to an append-only\n`memory.log`\n\nwith per-frame header and payload CRC32 checksums. On startup it\nloads the index checkpoint (`memory.index`\n\n) and replays only the log tail written\nsince — falling back to a full scan if the checkpoint is missing or corrupt —\nthen rebuilds the in-memory indexes. A torn tail from a mid-write crash is\ntrimmed; interior corruption is skipped frame by frame so the surrounding records\nstill load. To verify:\n\n- Insert several records.\n`kill -9 <pid>`\n\nthe server.- Restart it — startup logs\n`recovery complete: N records loaded`\n\n. `get`\n\neach ID; all records return intact.\n\nRecovery + a durable volume + `restart: unless-stopped`\n\nalready survive a\nprocess crash. To survive losing the **host or disk**, take backups off the box.\n\nAegisDB is single-node by design (no built-in replication), and because the log\nis append-only a backup is just a consistent snapshot of its durable prefix. The\nadmin `snapshot`\n\nop writes one online (no downtime); `--restore`\n\ninstalls it into\nan empty data dir. [ scripts/aegis-backup.sh](/d4n-larsson/aegisdb/blob/main/scripts/aegis-backup.sh) automates\nthe loop — snapshot → tarball → ship off-box via a transport you supply (S3,\n\n`rclone`\n\n, `rsync`\n\n, …) → local retention:\n\n```\n# host cron (daily), shipping to S3:\nAEGIS_BACKUP_UPLOAD_CMD='aws s3 cp {} s3://my-bucket/aegis/' \\\n  scripts/aegis-backup.sh\n```\n\nOr run it on a schedule as the opt-in compose sidecar:\n\n```\ndocker compose --profile backup up -d      # loops the script (default: daily)\n```\n\nRestore a shipped tarball into a fresh server:\n\n```\ntar -xzf aegis-20260709T....tar.gz -C /tmp/snap\naegisdb --restore /tmp/snap/aegis-20260709T... --data-dir ./restored --embedding-dim 384\naegisdb --data-dir ./restored --embedding-dim 384    # start; recovery rebuilds indexes\n```\n\nSee [ .env.example](/d4n-larsson/aegisdb/blob/main/.env.example) for the backup knobs (\n\n`AEGIS_BACKUP_UPLOAD_CMD`\n\n,\n`AEGIS_BACKUP_INTERVAL`\n\n, `AEGIS_BACKUP_RETAIN`\n\n). The transport is pluggable so no\ncloud SDK is baked into the image — the same \"bring your own edge\" stance as TLS.\n\nDo notscale the server with`deploy: replicas: N`\n\nagainst the shared volume: AegisDB is single-writer (one append-only log, one id allocator), so multiple writers would corrupt the data. Backups and read replicas (below) are the supported resilience path.\n\nFor read availability and read scaling, a **read-only replica** follows a primary\nby streaming its append-only log and replaying it — always the same frames in the\nsame order, so the replica's log is byte-identical and offsets line up. Replicas\nare asynchronous (eventually consistent, bounded by lag) and read-only; promotion\nafter a primary failure is a manual, operator-fenced step. Full design and the\npromotion runbook: [ docs/read-replica-design.md](/d4n-larsson/aegisdb/blob/main/docs/read-replica-design.md).\n\n```\n# primary: serve the replication stream (needs a token)\naegisdb --data-dir ./p --port 9470 \\\n        --replication-port 9480 --replication-token \"$TOKEN\"\n\n# replica: follow the primary, serve read-only on its own port\naegisdb --data-dir ./r --port 9471 \\\n        --replicate-from 127.0.0.1:9480 --replication-token \"$TOKEN\"\n```\n\nSend writes to the primary and spread reads across either; a write to a replica\nreturns `READ_ONLY`\n\n. `stats`\n\nreports the replication posture (`role`\n\n,\n`lag_bytes`\n\n, connected replicas). Compaction on the primary rewrites offsets, so\na replica automatically re-bootstraps when it detects the change. Every node\nmust use the same `--embedding-dim`\n\n. The stream is authenticated by the token but\nnot encrypted — keep it on a trusted network / behind a TLS proxy, like the\nclient protocol.\n\nAegisDB can act as the persistent long-term memory of [Claude Code](https://claude.com/claude-code)\nvia the integration in [ integrations/claude-code/](/d4n-larsson/aegisdb/blob/main/integrations/claude-code):\nan MCP server exposing memory tools plus hooks for automatic recall and capture.\nIt is published to PyPI as\n\n[, so](https://pypi.org/project/aegisdb-mcp/)\n\n`aegisdb-mcp`\n\n`uvx aegisdb-mcp`\n\nruns it with no clone. **Fastest setup:** with a server running,\n\n`uvx --from aegisdb-mcp aegisdb-init`\n\nscaffolds `.mcp.json`\n\nand the hooks\nfor you (or install the `/aegis-setup`\n\nskill and let Claude do it). See\n[for that and the manual step-by-step.](/d4n-larsson/aegisdb/blob/main/integrations/claude-code/README.md)\n\n`integrations/claude-code/README.md`\n\n**Team server tutorial**(guided golden path — auth, tenants, encryption, backups):`docs/tutorial-team-server.md`\n\n- Wire protocol:\n`docs/wire-protocol.md`\n\n- Quickstart (solo / local):\n`docs/quickstart.md`\n\n- Architecture:\n`docs/architecture.md`\n\n- Read-replica design & promotion runbook:\n`docs/read-replica-design.md`", "url": "https://wpnews.pro/news/aegisdb-self-hosted-memory-for-ai-agents-in-one-c-binary", "canonical_source": "https://github.com/d4n-larsson/aegisdb", "published_at": "2026-07-16 23:15:56+00:00", "updated_at": "2026-07-16 23:47:19.233597+00:00", "lang": "en", "topics": ["ai-agents", "ai-infrastructure", "ai-tools", "ai-products"], "entities": ["AegisDB", "Claude Code", "Prometheus", "Grafana", "cJSON", "XChaCha20-Poly1305", "HNSW", "MCP"], "alternates": {"html": "https://wpnews.pro/news/aegisdb-self-hosted-memory-for-ai-agents-in-one-c-binary", "markdown": "https://wpnews.pro/news/aegisdb-self-hosted-memory-for-ai-agents-in-one-c-binary.md", "text": "https://wpnews.pro/news/aegisdb-self-hosted-memory-for-ai-agents-in-one-c-binary.txt", "jsonld": "https://wpnews.pro/news/aegisdb-self-hosted-memory-for-ai-agents-in-one-c-binary.jsonld"}}