Encrypted-first embedded database and memory engine, faster than unencrypted SQLite.
Every page is encrypted and authenticated before it touches disk. A full SQL engine that wins all 50 head-to-head benchmarks against SQLite - and, on the same encrypted pages, a memory engine with vector recall, an MCP server, and cryptographic forgetting.
cargo add citadeldb citadeldb-sqlA live model of Citadel's on-disk format: my.db is opaque ciphertext until the passphrase decrypts the page. Nothing is stored - to run real SQL, open the playground.
An encrypted file format that is both a database and a memory.
The same AES-256-CTR + HMAC pages, copy-on-write B+ tree, and shadow-paging commit power both halves. Use the SQL engine, the memory engine, or both in one file.
Encrypted database
A complete embedded SQL + key-value engine. ACID without a WAL, snapshot isolation, and a single self-contained file - faster than unencrypted SQLite at equal cache budgets.
- SQL: FULL OUTER & LATERAL joins, recursive CTEs, window functions, triggers, materialized views
- JSON / JSONB with 14 PostgreSQL operators, GIN indexes, full-text search
- Key-value API and SQL share one transaction
- P2P encrypted sync over Noise; Python, CLI, C FFI, and WebAssembly bindings
Memory engine
Memory that lives encrypted at rest. Typed atoms and edges, hybrid recall, and a Model Context Protocol server so Claude Desktop or any MCP client can read and write it.
VECTOR(N)type with a PRISM-backed filtered ANN index- Hybrid recall: vector ANN + BM25 keyword + recency + optional cross-encoder reranker
- Cryptographic forgetting: erase an atom or region by destroying its key
- 13-tool MCP server; 85.5% on the LoCoMo long-memory benchmark
A complete engine in a single file.
Full SQL, real ACID, encrypted sync, and a memory engine. Key hierarchy built around RFC 3394, RFC 5869, and a Rust-only crypto core.
Encrypted at rest
AES-256-CTR + HMAC-SHA256 per page, verified before decryption. Fresh random IV on every write. ChaCha20 available.
Real SQL
FULL OUTER + LATERAL joins, recursive CTEs (with-DML), window functions, triggers, materialized views, UPSERT, RETURNING, JSON/JSONB.
ACID, no WAL
Copy-on-Write B+ tree with shadow paging. Snapshot isolation with concurrent readers, atomic single-byte commits.
Vector + memory engine
VECTOR(N) with a PRISM filtered ANN index, plus a memory engine of typed atoms with hybrid vector + keyword recall.
MCP server
Expose encrypted memory to Claude Desktop or any MCP client over stdio. 13 tools for recall, remember, link, evolve, and forget.
Cryptographic forgetting
Erase data by destroying its key, not by overwriting. Whole-store, per-region, and per-atom, with verifiable erasure receipts.
P2P encrypted sync
Merkle-based table diffing over Noise (NNpsk0_25519_ChaChaPoly_BLAKE2s) with ephemeral forward secrecy.
Three-tier key hierarchy
Passphrase → Argon2id → Master Key → AES-KW → REK → HKDF → DEK + MAC. Instant rekey, no page re-encryption.
Cross-platform bindings
Windows, Linux, macOS. Python, C FFI (37 functions), and WebAssembly from one Rust core. Tamper-evident HMAC-chained audit log.
Open a database in six lines.
The API is small on purpose. One builder, one connection, one passphrase.
Add the crates
Engine + SQL frontend from crates.io.
Open with a passphrase
Argon2id derives the master key in memory. Keys live in {dbname}.citadel-keys, not inside the database.
Run SQL, or use the KV API
Both are first class. Mix them in the same transaction.
Ship a single file
Embedded, zero-config. No servers, no daemons, no runtime dependencies.
What "open my.db" actually does.
Six stages from passphrase to a sealed 8,208-byte page on disk. Real algorithm names, real byte counts, drawn from the citadel-crypto source.
my.db.citadel-keys. The passphrase stays in memory only; never touches disk.zeros(32)"citadel-dek-v1"→"citadel-mac-key-v1"→epoch ‖ page_id ‖ IV ‖ ciphertext, so a forged page id or replay from another epoch fails the tag. Page = 16 + 8,160 + 32 = 8,208 bytes.my.db alone and you get opaque ciphertext. Lose the passphrase and nothing opens.Encrypted memory engine.
citadel-mem stores memory as typed atoms grouped into regions and connected by typed edges. Recall blends vector similarity, keyword scoring, and recency; forgetting destroys keys, not just rows.
Hybrid fusion recall. A query over-fetches ANN candidates, then scores each on normalized semantic distance, BM25 keyword overlap, recency (30-day half-life), and importance. An optional cross-encoder reranker (replace or reciprocal-rank-fusion) sharpens the top results, and a graph walk pulls in linked neighbors.
Forgetting that is real. On encrypted regions every atom is sealed under its own key, wrapped by a per-region key. forget and evict destroy those keys and return an erasure receipt; the ciphertext that remains is unrecoverable. Re-verify any atom off disk: authentic, tampered, or key-erased.
Bring your own embedder. A keyword-only mock for tests, or Candle models (BGE small/base/large, MiniLM, E5-large) and a cross-encoder reranker, pulled on demand. CUDA optional.
LoCoMo long-term conversational-memory benchmark, encrypted regions, gpt-4o-mini reader and judge - zero LLM at ingest or retrieval. 90.6% (3-run mean) with a gemini-3.5-flash reader. Protocol and full numbers in citadeldb-membench.
Plug encrypted memory into Claude Desktop.
citadel-mcp serves one memory region over MCP (JSON-RPC 2.0 on stdio) with 13 tools. Encrypted by default, with per-atom sealing and cryptographic erasure. Any MCP client - Claude Desktop, an IDE - can read and write it.
Read tools
- mem_recall
- mem_fetch
- mem_edges
- mem_profile
- mem_summarize
- mem_verify
Write & forget tools
- mem_remember
- mem_remember_batch
- mem_update
- mem_link
- mem_evolve
- mem_evict
- mem_forget
{
"mcpServers": {
"citadel": {
"command": "citadel-mcp",
"args": [
"--db", "memory.citadel",
"--region", "default",
"--embedder", "bge-small"
],
"env": { "CITADEL_KEY": "your-passphrase" }
}
}
}One-time setup: citadel-mcp pull bge-small downloads the embedder (models are never fetched automatically; omit --embedder for keyword-only recall). Recall hits carry provenance, per-hit integrity verdicts, and memory://atom/{id} resource links. mem_forget returns an erasure receipt.
50 of 50 head-to-head, won.
Single-threaded, 100K rows, (id INTEGER PK, name TEXT, age INTEGER). Equal cache budgets (~32 MB). Ratio is SQLite / Citadel time; higher means Citadel wins by more. Geometric mean ~2.8×.
journal_mode=OFF, synchronous=OFF, cache_size=8192. Citadel: SyncMode::Off, cache_size=4096. Reproduce: cargo bench -p citadeldb-sql --bench h2h_bench.20 crates, one file format.
A layered engine: each crate has one job, depends only on the layers beneath it, and can be read on its own.
Page layout is 8,208 bytes. Sixteen bytes of random IV, 8,160 bytes of ciphertext, 32 bytes of HMAC-SHA256. Corrupt pages fail loud, not silent.
Commit protocol is shadow paging. Dirty pages go to new locations, BLAKE3 Merkle hashes climb bottom-up, the inactive 240-byte commit slot is updated, then one byte in the file header flips to publish the new root. No write-ahead log.
The memory layers reuse the same pages. Vectors, atoms, and edges are stored, encrypted, and committed exactly like table rows - one file format, one crypto path. citadel-membench is the LoCoMo harness that measures recall on top.
A SQL dialect that doesn't disappoint.
FULL OUTER and LATERAL joins, recursive and DML-bearing CTEs, triggers, materialized views, window frames, JSON/JSONB with PostgreSQL operators, full-text search, and a native VECTOR type.
Statements
- CREATE / DROP / ALTER TABLE
- CREATE INDEX (partial / expr)
- CREATE VIEW / MATERIALIZED VIEW
- CREATE TRIGGER
- UPSERT (ON CONFLICT)
- RETURNING (OLD / NEW)
- TRUNCATE / SAVEPOINT
- PREPARED / $1, $2, ...
- EXPLAIN
Clauses & joins
- INNER / LEFT / RIGHT / CROSS
- FULL OUTER / LATERAL
- Subq.: scalar / IN / EXISTS / ANY/ALL
- Correlated subqueries
- WITH / WITH RECURSIVE
- WITH-DML (RETURNING)
- UNION / INTERSECT / EXCEPT
- GROUP BY / HAVING
- Window frames (ROWS / RANGE)
JSON / JSONB & search
- 14 PostgreSQL operators
->/->>/#>/#>>@>/<@/?/?|/?&- 16 scalar / 4 aggregate fns
- GIN indexes on JSONB
- FTS: tsvector / ts_rank / phrase
VECTOR(N)+ ANN index<->L2 /<#>inner /<=>cosine
Types / constraints / windows
- INT / REAL / TEXT / BLOB / BOOL
- DATE / TIME / TIMESTAMP(TZ)
- INTERVAL / IANA zones (jiff)
- Generated cols (STORED / VIRTUAL)
- STRICT tables
- COLLATE BINARY / NOCASE / RTRIM
- FK: CASCADE / SET NULL / DEFERRABLE
- ROW_NUMBER / RANK / LAG / LEAD
- SUM / AVG OVER / PARTITION BY
Keys are handled like they matter.
No plaintext on disk
Every page is encrypted before writing, authenticated before reading. The database file is indistinguishable from random.
Keys live outside the database
Encryption material lives in {dbname}.citadel-keys. The passphrase derives a master key in memory via Argon2id and never touches disk.
Instant rekey
Changing a passphrase re-wraps the root key only. No pages are re-encrypted. The operation is instant regardless of database size.
Cryptographic erasure
citadel-mem seals each atom and region under its own key. Forgetting destroys the key and issues a receipt; the remaining ciphertext cannot be recovered.
Forward-secret sync
Noise NNpsk0_25519_ChaChaPoly_BLAKE2s with a 256-bit PSK. Ephemeral Curve25519 keys per session; compromise of one doesn't leak prior traffic.
FIPS 140-3 mode
A feature flag swaps Argon2id for PBKDF2-HMAC-SHA256 (600,000+ iterations) with AES-256-CTR only, for compliance environments.
Rust, Python, C, WebAssembly, and a CLI.
Rust
crates.io / citadeldbThe reference API. Builder-style open, typed transactions, no hidden allocation. 15 crates published.
Python
PyPI / citadeldbThe full engine in one wheel: encrypted SQL, vector search, the memory engine, and the MCP server. Typed, with numpy vectors.
C / C++
cbindgen / citadel.h37 panic-safe functions, static or dynamic linkage. Drop into any toolchain that speaks C ABI.
WebAssembly
npm / @citadeldb/wasmA real encrypted database in your browser tab. Compiled with wasm-pack. Powers the playground.
CLI
crates.io / citadeldb-cliAn interactive SQL shell with tab completion, syntax highlighting, and 26 dot-commands.
From the blog.
- Introducing Citadel
An embedded database that encrypts every page, with a built-in memory engine.
Start with the browser build.
No install, no signup. Run real SQL against an encrypted database compiled to WebAssembly.