Two different jobs bring an agent here. Pick one; you do not need the other half.
- Use contextdb — drive the database from the CLI or embed it as a Rust library. Go to Use contextdb. No verification gate applies to you.
- Contribute to contextdb — change the code in this repo. Go to Contribute. The gate there is binding.
Plain contextdb <path> is a bounded read session; the --write flag, missing-store
refusal, owner-vs-file routing, and that .help rewrites nothing are in
docs/cli.md.
contextdb ./their.db # bounded read session, never modifies
echo ".tables" | contextdb ./their.db --json # reads without copying anything
contextdb ./their.db --write # explicit read-write sessionEvery row below changes or destroys durable data. Run none of them against a store you did not
create for this task until the operator confirms that exact path. Sole exception: an
ephemeral, task-scoped store you created yourself (:memory:, or a file under $(mktemp -d)) —
there, run them freely and without asking.
| Goal | Sanctioned command | Guardrail |
|---|---|---|
| Find out why a store will not open | contextdb diagnose <path> |
Read-only. Always safe. Start here. |
| Recreate a wedged or corrupt store | contextdb reset <path> --force |
Destroys all data. Recover what you need from a backup or a healthy sync peer first. --force is mandatory; without it the CLI refuses and exits 2. |
| Take a backup before any of the above | contextdb snapshot export <path> <dest> |
Purge-fenced; the safe prerequisite for reset. |
Apply declared RETAIN windows now instead of waiting for the background cycle |
.maintenance run (REPL meta-command) |
Synchronous; expires rows the table's own DDL already declared expirable. |
| Erase rows permanently | contextdb purge <path> --table <t> --force |
Purge-fenced; refuses without --force (exit 2). Only legal on a store that has never connected to a sync hub. |
| Make a route, sink or schedule actually fire | Run the DDL in a :memory: CLI session; inspect with .events status |
In an ephemeral :memory: session the CLI registers default callbacks, so routes deliver and schedules fire observably. On a file-backed store, events queue durably until your own program registers its callbacks (register_sink / register_cron_callback) — that durable queueing is the contract, not a gap. |
cargo test --workspace grows target/ to 55–90 GB, and incremental rebuilds keep growing it.
Never run two cargo commands at once (they deadlock on the target/ lock) and never start a
workspace build while another is live on the box — chain with && and wait. First:
df -h . # want ~100G free for a full workspace test run
export CARGO_PROFILE_DEV_DEBUG=0 # roughly halves target/, keeps backtraces usableNeed binaries? cargo build --release -p contextdb-cli -p contextdb-server (minutes on a cold
cache), or use an existing target/release; install options in
docs/getting-started.md.
Throwaway store to try anything against, machine-readable output:
db="$(mktemp -d)/scratch.db"
printf "%s\n" \
"CREATE TABLE decisions (id UUID PRIMARY KEY, status TEXT NOT NULL);" \
"INSERT INTO decisions VALUES ('550e8400-e29b-41d4-a716-446655440000', 'draft');" \
"SELECT * FROM decisions;" | contextdb "$db" --write --json
# {"rows_affected":0}
# {"rows_affected":1}
# {"result":{"columns":["id","status"],"rows":[{"id":"550e8400-e29b-41d4-a716-446655440000","status":"draft"}]}}--write is what creates the store and authorizes the CREATE/INSERT; drop it once you are
only reading the store back.
Prefer --json and read named fields; never scrape the human table output, which reflows freely.
JSON document shapes and the four exit codes are in
docs/cli.md.
Task-shaped recipes, copy-paste runnable. Read the one matching what you are doing.
| Skill | What it's for | Path |
|---|---|---|
using-contextdb |
Open a database, define tables, run SQL (including multi-line paste), read --json, recover after a refused statement, branch on exit codes. |
skills/using-contextdb/SKILL.md |
querying-the-graph |
Declare a DAG edge table, traverse it with GRAPH_TABLE, get cycle inserts refused, enforce STATE MACHINE transitions with PROPAGATE cascades. |
skills/querying-the-graph/SKILL.md |
running-triggers-and-schedules |
Declare CREATE EVENT TYPE/SINK/ROUTE/SCHEDULE, see them fire observably in :memory:, and wire register_sink/register_cron_callback so a file-backed store's durably-queued events actually deliver. |
skills/running-triggers-and-schedules/SKILL.md |
sync |
Stand up a hub, enroll an edge with its ticket, push/pull, change synced columns explicitly, and read the applied / skipped / conflicts counts correctly. | skills/sync/SKILL.md |
vector-search |
Embedding columns, <=> nearest-neighbour search, schema-declared USE RANK policies, and the hybrid graph + vector query. |
skills/vector-search/SKILL.md |
work-fabric |
Hand a job to another machine over the work ledger and move the bytes it needs over the blob plane. Library API — no CLI. | skills/work-fabric/SKILL.md |
operating-a-store |
Enforce RETAIN windows on demand with .maintenance run, permanently erase rows with purge (never-connected stores only), back up before a destructive op, and read pull_pages_read sync liveness. |
skills/operating-a-store/SKILL.md |
Reference docs, when a skill is not enough:
| Doc | What it covers |
|---|---|
docs/getting-started.md |
Install, first REPL session, embedding as a library, two-machine sync |
docs/cli.md |
Every flag and meta-command, the --json document shapes, the exit-code table |
docs/query-language.md |
SQL surface, GRAPH_TABLE traversal, vector search, constraints, what is unsupported |
docs/architecture.md |
Crate map, MVCC, sync protocol, work ledger and blob plane, store format and recovery |
docs/usage-scenarios.md |
Walkthroughs with SQL |
docs/why-contextdb.md |
Problem statement and comparison with alternatives |
docs/capability-index.md |
One page: what contextdb is, is not, and the numbers it stops at |
docs/agent-readiness.md |
How this repo measures whether AI assistants can use and contribute to it |
contextdb ships no built-in schema; the decisions example and that framing live in the
README. Conflict policy (KEEP FIRST vs KEEP LATEST) is in
docs/query-language.md, with one recipe in
skills/sync.
The nine-command verification gate is in CONTRIBUTING.md. All nine must
pass before any commit, release, or "done" claim. Read the disk and single-build rules in
Safety boundaries before you start
cargo test --workspace. Narrower suites while iterating:
cargo test -p contextdb-engine --test acceptance, --test integration, --test sql_surface.
How CI is organised — its paths, each PR check, and the local bash scripts/verify command
behind each check — is in .github/CI.md. If you edit anything under
.github/ or a CI script (scripts/verify, scripts/ci-*), also read
.github/AGENTS.md; its rules cover those scripts even though they live
outside .github/.
Describe the capability, then go to the crate that owns it — do not go looking by filename.
| Change | Where it lands |
|---|---|
| A new scalar SQL function | ONE match arm in the engine crate's executor (eval_function), plus the ORDER BY allowlist (is_known_scalar_function), plus tests. The parser takes function calls generically and the planner needs nothing. |
A function that works in SELECT but is refused in ORDER BY |
You added it to eval_function only. Those two lists are hand-synced with no cross-reference — add every new function to both. |
Grammar, DDL clauses, PROPAGATE |
Parser crate; grammar reference is docs/query-language.md. |
| Partial synced ALTER, explicit column drop/rename, ordered schema replay | Engine database.rs (author markers, schema projection and received-unit replay); durable installation in persistence.rs. Never infer a drop or rename from omitted columns. |
| Sync protocol, conflict arbitration, work ledger | Engine crate owns the implementations; the server crate re-exports them. Never add a mirror module in the server — extend the engine and re-export. |
| How a bounded read session opens and which route it takes | Engine crate, read_session.rs — it assembles the one public ReadSession and its two routes. Adding a third route, or a second way to open a store for reading, is out of bounds. |
| Reading a store nobody owns (the committed-snapshot file route) | Engine crate, direct_file_reader.rs. |
| Serving readers from a live writer (admission, client, service) | Engine crate, owner_read/. |
| Addressing, authenticating, framing or timing the owner channel | Engine crate, local_transport/. Never open a second transport beside it. |
| How a read is actually executed and charged against its budgets | Engine crate, executor/bounded.rs — the one execution kernel both routes share. Never give a consumer its own execution semantics. |
| The trusted companion, the claim window, reader holds, published reader identities | Engine crate, persistence.rs. |
| A refusal class or kind a reader can branch on | Core crate, read_contract.rs — the shared typed vocabulary. Never define a second refusal type downstream of it. |
| Vector search: routes, partition layouts, the global top-k merge, generation lifecycle, per-column vector policy | Vector crate (store.rs, hnsw.rs, mem.rs). Raw payload sharing and each column's charge ownership live in store.rs / quantized.rs; generation persistence and maintenance scheduling stay in the engine crate. |
| Vector generation admission, catalog inventory, journal cleanup or cancellation | Engine database.rs, database/vector_maintenance_inventory.rs, database/vector_source_page_admission.rs and persistence.rs. Vector store.rs selects resident frontier-live inputs; cold snapshots and delete-only carriers retain their raw-history path. |
| A graph primitive vector search cannot build on top of the HNSW fork | HNSW crate, as the smallest upstream-shaped change, plus its upstream-0.3.4.patch and MAINTENANCE.md. Anything composable goes in the vector crate's hnsw.rs instead. |
| A storage primitive (compaction step, read admission, bounded byte-table lookup or cursor) the engine cannot build on top of redb | redb fork crate, same rule: smallest change, patch and MAINTENANCE.md updated. Byte-node validation and reject-only windows live in tree_store/bounded_bytes.rs; compaction and inventory policy stay in the engine. |
A contextdb-server flag, exit code, automatic push trigger, or worker poll loop |
Server crate (main.rs, exit_codes.rs, sync_plugin.rs, work_ledger.rs). |
| Anything else | docs/architecture.md maps all 11 crates and the dependency direction. |
- No nondeterministic or wall-clock-dependent tests. Assert on state, counters, or events —
never on elapsed time, and never sleep as synchronization. A negative claim ("nothing fired")
is a counter read after a deterministic drive. One documented exception:
commit_index_reconstruction_is_not_quadratic, where the time bound IS the promise. - Time-dependent behavior uses the clock seam. Two audits enforce it on every gate; the
mechanics (
Wallclock::test_clock_guard, the thread-local limitation, the ratchet you may lower but never raise) are incrates/contextdb-engine/AGENTS.md. - When
timestamp_auditfails on a change that touched no timestamp columns: its whitelist is pinned by declaration text, so a line-count shift in a whitelisted file does not trip it. A newcreated_at/valid_from/valid_to TIMESTAMPdeclaration, or a removed whitelisted declaration, does. Do not disable or re-scope the audit. It scans git-tracked files only. - Testability touches in
src/are production-dead —#[doc(hidden)] ..._for_testaccessors or unused-in-production seams. Anything else is a behavior change and needs its own proof (benchmark + full gate), stated in the commit. - Never record test timing with a redirected
TMPDIR. Temp DBs on a real disk pay ~40× fsync cost vs tmpfs and silently corrupt every figure. Unset it before timing, and state the TMPDIR/filesystem alongside any recorded timing. - Deleting or merging tests requires mutation-testing evidence that coverage is preserved (compare per-mutant results before and after, not summary counts).
Every crate carries a guide: what the crate owns and must not own, its seams, each invariant with
the test that guards it, where a change lands, and the fast test command. A guide adds to this file
rather than overriding it. Read the matching one before you edit that crate.
docs/architecture.md maps every crate and the dependency
direction.
| Crate | Guide | Rule to know before editing |
|---|---|---|
contextdb-cli |
crates/contextdb-cli/AGENTS.md |
The CLI and REPL surface; behavior belongs to the engine. |
contextdb-core |
crates/contextdb-core/AGENTS.md |
Shared types, errors and the read-contract vocabulary; the workspace audits live in its tests/. |
contextdb-engine |
crates/contextdb-engine/AGENTS.md |
Clock-seam discipline: every persisted timestamp goes through Wallclock::now(); the test-estate ratchet audit enforces it. |
contextdb-graph |
crates/contextdb-graph/AGENTS.md |
Adjacency index and bounded BFS; DAG cycle refusal on insert. |
contextdb-hnsw |
crates/contextdb-hnsw/AGENTS.md |
Maintained fork of hnsw_rs 0.3.4: the delta stays minimal and additive code lives in contextdb-vector; see its MAINTENANCE.md. |
contextdb-parser |
crates/contextdb-parser/AGENTS.md |
Char-boundary discipline: every fixed-width lookahead over input must be boundary-safe, or multi-byte UTF-8 panics the parser. |
contextdb-planner |
crates/contextdb-planner/AGENTS.md |
Turns the parsed statement into a physical plan. |
contextdb-redb |
crates/contextdb-redb/AGENTS.md |
Maintained fork of redb 4.1.0, outside the workspace: the delta stays minimal and additive code lives in the engine; see its MAINTENANCE.md. |
contextdb-relational |
crates/contextdb-relational/AGENTS.md |
Row storage, scan, insert, upsert and delete. |
contextdb-server |
crates/contextdb-server/AGENTS.md |
The sync mover: sync semantics are the engine's and re-exported; never a mirror module. |
contextdb-tx |
crates/contextdb-tx/AGENTS.md |
MVCC transaction manager and deferred-apply write sets. |
contextdb-vector |
crates/contextdb-vector/AGENTS.md |
Partitioned maintained vector search; most of its tests need --features test-seams. |
Needs cargo install cargo-release. Run
cargo release {patch|minor|major} --execute --workspace --no-publish — patch for bug fixes,
minor for backward-compatible features, major for breaking API changes. It bumps every crate,
commits, tags, and pushes; CI (org context-graph-ai, repo contextdb, runs on main and PRs)
then publishes crates, Docker images, GitHub releases, and the contextdb.tech docs deploy. No
cargo login needed — CI holds the token.