dent8
A memory firewall for coding agents — it prevents low-authority or stale project facts from silently overriding trusted state, and can replay exactly why an agent believed something.

From a clone, see it run through the real CLI path:
DENT8="cargo run -q -p dent8 --" ./examples/firewall/demo.sh — a
high-authority fact is asserted, a low-authority source is rejected when it tries to override
it, and an integrity receipt explains the result with a verified hash chain.
Why a firewall? (the one-command proof)
Run dent8 eval — dent8's adversarial corpus pits each attack against the real firewall
and a recency-only baseline (newest-write-wins, the resolution Zep/Graphiti use):
| attack | family | firewall | recency-only baseline |
|---|---|---|---|
minja_low_authority_injection |
T1 memory injection | blocked ✓ | compromised |
authority_laundering |
T1 memory injection | blocked ✓ | compromised |
canonical_contradiction |
T5 canonical contradiction | blocked ✓ | compromised |
sybil_corroboration |
earned entrenchment | blocked ✓ | compromised |
poisoned_source_retraction |
T2 retraction cascade | blocked ✓ | compromised |
The firewall blocks 5/5 attacks a recency-only memory falls to — including
poisoned_source_retraction: retract a poisoned source and dent8 flags every fact derived
from it (dent8 derive records the edge, dent8 verify surfaces the taint), the
dependency-cascade integrity recency-only memory structurally cannot express.
Install
# Install with Cargo (Rust 1.95+):
# …or from Git before the first crates.io release:
# …or run from a clone without installing:
The stock dent8 binary uses a local file log by default, needs no services, and includes
signed source identity plus the embedded SQLite backend (sqlite:// DENT8_STORE_URL) for
local multi-agent dogfooding. Opt-in builds add the operational Postgres backend
(--features postgres) and the Ed25519 witness (--features witness).
Quickstart
; ;
For a protected agent setup, let init create the authority registry and signed source
identity bundle together:
For multiple agents in one belief base, initialize a shared backend first and then add each agent profile:
Use dent8 mcp install --agent <profile> to patch/show an existing agent MCP config later
(--dry-run renders without writing; --check exits non-zero if the config would change).
If doctor reports a stale generated identity bundle or MCP env, dent8 doctor --agent <profile> --repair repairs the generated env and refreshes the installed MCP config before
rerunning the normal checks. For repo-local dogfood where MCP startup must not invoke Cargo,
build once with CARGO_TARGET_DIR=.dent8/target-sqlite cargo build -p dent8 --features sqlite,witness, then pass --mcp-local-bin on init / agent add or --local-bin on
mcp install; dent8 writes .dent8/bin/dent8 and doctor verifies the wrapper and prebuilt
target.
Source .dent8/env + the source-specific identity env (for example
.dent8/identity-codex.env) when you want to run CLI commands from the same shell. Use
dent8 init --identity --source <source> for a custom source id. Agent shortcuts are
available for codex, claude-code, cursor, grok-build, gemini, cascade, and
hecate. The installer writes command = "dent8" by default, so Codex, Claude Code, Cursor,
Gemini, Grok Build, Cascade, and Hecate can all use one globally installed binary; pass
--mcp-command / --command if the binary lives elsewhere; doctor --agent reads the installed
config back, smokes that exact command/args/cwd/env, and can run the write-check through that
installed MCP server. Stdio MCP clients normally launch their own
dent8 subprocess, but those processes can share the same operational belief base by using the
same DENT8_STORE_URL (Postgres is the production-shaped multi-agent store) while keeping
distinct per-agent grants/keys for provenance. dent8 agent add --agent <profile> is the
one-command path for that shared-backend case: it refuses file-dev bundles, adds/repairs the
agent's identity, grants its source an authority ceiling, patches the MCP config, and prints
the follow-up doctor command. A single long-lived local/remote MCP daemon over HTTP is future
transport work, not part of v0. dent8 identity status checks a local
identity bundle; dent8 identity repair-env repairs the generated per-source identity env /
active-grants files from the current signed grant without rotating keys; and
dent8 identity rotate-source replaces the active source key/grant while keeping the stable
.dent8/identity-<source>.env paths that MCP configs use. Rotation updates .dent8/active-grants.json,
so the old grant/key pair is rejected even if someone manually points env vars at backed-up
grant material. identity bootstrap remains available for custom layouts and keeps the issuer
key outside .dent8 by default ($XDG_CONFIG_HOME/dent8/issuer.key or
$HOME/.config/dent8/issuer.key; override with --issuer-key). The project bundle contains
only the trust registry, active-grant registry, per-source key, grant, and env snippet an agent
needs. The default issuer key is shared across projects for the same
OS user; use a project-specific --issuer-key when you want grant-signing isolation between
projects.
Facts persist to ./dent8-log.jsonl by default (override with DENT8_LOG). dent8 --help
lists the full surface (assert/supersede/retract/contradict/reinforce/expire/
derive/explain/replay/facts/verify/conflicts/eval/export/authority/agent add/hook/witness/
init/doctor/completions/mcp serve/mcp install). Use the global --color auto|always|never flag to control
colored help, errors, and verdict words in human-facing output. Use
--output json for stable machine-readable output on the write commands, explain,
replay, facts list, verify, conflicts, eval, init, agent add, authority,
identity <subcommand>, doctor, completions, export, schema postgres, and mcp install;
unsupported commands fail closed instead of silently returning
prose.
The core primitive is a claim event, not a generic memory item: every accepted write preserves provenance, evidence, authority, freshness, contradiction state, supersession lineage, and replayability. (Origin: dentate gyrus, the hippocampal structure associated with pattern separation.)
Status
This is an early open-source project. docs/STATUS.md is the single source of truth for what is built. In short:
- Runnable today: the full lifecycle through the firewall —
assert/supersede/retract/contradict/reinforce/expire/derive/explain/replay— plusfacts listfor browsing known fact streams and the operator surfacesverify(integrity + retraction-taint check),conflicts,eval(the self-demonstrating benchmark), andexport(the whole log to Parquet for offline DuckDB forensics/audit, behind--features export— see examples/duckdb/),dent8 init/dent8 doctor,dent8 authority,dent8 identity,dent8 witness(behind--features witness), anddent8 schema postgres. State persists to a local file log and composes across separate invocations; the file log is a dev store (single-writer, non-transactional) — the operational backends are Postgres (server) and embedded SQLite, selected byDENT8_STORE_URL.dent8 mcp serveexposes the full belief surface plus read/audit tools to agents over MCP (stdio JSON-RPC), through the same firewall — see examples/mcp/, examples/codex/, examples/claude-code/, examples/gemini/, examples/cascade/, examples/cursor/, examples/grok-build/, examples/hecate/, and examples/vercel-ai-sdk/ for agent-client wiring. Optional native memory/rules hook guards use the built-indent8 hook native-memory-guard; provider profiles live in examples/agent-hooks/. - Implemented as a tested library: the
ClaimEventmodel and replay fold; the unbypassable write-path firewall (EventStore::append) with authority-weighted arbitration + retraction, an anti-laundering challenger check, and the canonical-contradiction hard-alarm; the coding-agent predicate registry; the integrity receipt; a freshness evaluator; policy-counterfactual and entity-level replay with lineage and earned-entrenchment audits; and serde canonicalization + a SHA-256 hash chain. - Validated by an adversarial corpus (
dent8 eval, orcargo test -p dent8-evals): MINJA injection, authority laundering, canonical contradiction, Sybil corroboration, and poisoned-source retraction all fail against the firewall (0/5) while compromising a recency-only baseline (5/5) — see docs/evals.md. - DB-verified: the v0 Postgres adapter (
PostgresEventStore, behind the store crate'sadapterfeature; CLI users enable it with--features postgres) — transactional append, firewall via the sharedarbitrate_events, JSONB event log, plus a materialized projection + edge graph (migration 003) folded in the same transaction with aprojection == fold(log)check. TheDATABASE_URL-gated integration tests pass against a livepostgres:16. - Runnable (v0): an MCP server (
dent8 mcp serve) exposing read/audit tools (list_facts/verify/conflicts) and the full belief surface (assert/supersede/retract/contradict/reinforce/expire/derive/explain/replay) as tools, plusresources/list/resources/readand JSON-RPC batches, over stdio JSON-RPC, through the shared firewall path. - Design-only: the official MCP
rmcpSDK / richer transports (the v0 server already does the nine tools above, resources, and JSON-RPC batches) and a richer per-column Postgres event table (a possible later design; the JSONB log, projection, and edge graph are built, above; evidence-dependency edges ship asEvidenceKind::DerivedFrom+ retraction taint, ADR 0010).
The runnable surface persists either way: a local file dev log by default, or — with
DENT8_STORE_URL set and a --features postgres build — the DB-verified transactional
Postgres backend (each multi-event operation committed as one transaction). An opt-in
authority ceiling (dent8 authority) caps what each source may assert, rejecting a
write above its registered ceiling. Signed source identity — dent8 identity
— included in the default CLI build — binds a source id to a source public key via an
issuer-signed grant and verifies source-key possession on every CLI/MCP write when a trust
root is configured.
The witness is runnable as a primitive — dent8 witness (--features witness) emits
Ed25519 signed tree heads and detects a history rewrite or rollback that an internal chain
re-verify cannot. dent8 init --witness configures verifier-side paths and dent8 doctor
reports signed-head coverage; dent8 witness doctor <writer|signer|both> checks the
operator split so writer/agent/MCP processes do not inherit the private witness key; and
dent8 witness publish <heads.jsonl> / verify-published <heads.jsonl> append and check
externally saved heads so a local witness-log rollback cannot erase retained evidence. The
finite witness commands support --output json for monitors and CI; witness serve remains
a streaming text command.
remaining gap to a hardened multi-user product is operating those controls well: key
distribution/rotation, stronger secret storage, managed head publication, and an operated
witness service that signs on a cadence from separate infrastructure. See
docs/witness.md, the runnable witness example, the
Roadmap, and docs/STATUS.md.
Initial Shape
The durable design is a backend-agnostic append-only event log (the EventStore / AsyncEventStore traits), not a database choice. Postgres was the first operational adapter — the source of truth for append-only claim events, projections, audit queries, and multi-user use — and an embedded SQLite backend is the second; both are selected by DENT8_STORE_URL and share the same firewall and hash chain. DuckDB and Parquet are an export-only analytical lane — built as dent8 export (Parquet, queried directly by DuckDB) for replay, forensic inspection, and benchmark analysis, never a runtime write store.
Workspace crates:
dent8-core: typed domain model, claim-event state machine, invariants.dent8-store: storage and replay traits (EventStore+ asyncAsyncEventStore) shared by backends.dent8-store-postgres: Postgres adapter, schema, and migration boundary.dent8-store-sqlite: embedded SQLite adapter (the secondAsyncEventStorebackend).dent8: operator and developer CLI surface.dent8-evals: adversarial corpus behind the self-demonstratingdent8 eval.dent8-export: Parquet export for offline DuckDB analysis (opt-in,--features export).
Commands (see docs/STATUS.md for what runs today):
dent8 eval: run the adversarial corpus that proves the firewall blocks attacks a recency-only baseline accepts.dent8 init: create a local.dent8/setup: env file, authority registry, and selected file/SQLite/Postgres store profile; optional--witnessadds verifier-side signed-head paths without exposing the witness signing key to the writer env.dent8 agent add --agent <profile>: add a second agent to an existing shared SQLite/Postgres-backed.dent8/bundle, creating/reusing that agent's authority grant, signed identity env, and MCP config.dent8 doctor [--agent <profile>] [--repair] [--write-check]: inspect binary, store, authority, witness coverage when configured, verify, MCP availability; with--agent, validate the generated bundle/config and smokemcp servewithinitialize+tools/list; with--repair, refresh stale generated identity env and installed MCP config; with--write-check, run an internal diagnostic trusted-write / low-authority-rejection flow (through the installed MCP server for agent profiles).dent8 identity bootstrap/status/repair-env/rotate-source: create, inspect, repair generated env files for, and rotate a local signed source identity bundle (operator issuer key outside the bundle, source key, trust registry, active-grant registry, grant, and.dent8/identity-<source>.env).dent8 assert <subject> <predicate> <value> --authority <level> --source <source>: assert a fact through the firewall, persisted to a file-backed log (DENT8_LOG).dent8 supersede <subject> <predicate> <new-value> --authority <level> --source <source>: revise the believed fact — rejected unless the revision can out-rank the incumbent.dent8 retract <subject> <predicate> --authority <level> --source <source>: remove the believed fact — also rejected unless it can out-rank the incumbent.dent8 contradict <subject> <predicate> <opposing-value> --authority <level> --source <source>: flag a conflict (dissent) — contest the fact and keep both, even from low authority.dent8 derive <subject> <predicate> <value> --from <source-subject> <source-predicate> --authority <level> --source <source>: assert a fact derived from another fact, recording the dependency edge thatverifycan later audit.dent8 reinforce <subject> <predicate> --authority <level> --source <source>: corroborate the believed fact without restating its value.dent8 expire <subject> <predicate> --authority <level> --source <source>: terminally close the believed fact for policy retention — authority-gated like retraction; TTL staleness is read-time and non-mutating.dent8 explain <subject> <predicate>: print the believed (or terminal) fact's receipt.dent8 replay <subject> <predicate>: replay the full event history — why the fact is what it is.dent8 facts list [--kind KIND] [--key KEY] [--predicate PREDICATE] [--include-diagnostics]: list known fact streams, hiding internal doctor/write-check diagnostics by default.dent8 --output json <write-command>|explain|replay|facts list|verify|conflicts|eval|init|agent add|authority|identity <subcommand>|doctor|completions|export|witness <one-shot>|schema postgres|mcp install: emit stable JSON for scripting and agent-side checks while preserving existing text output by default.doctor --output jsongroups checks into stableok,warn,fail, andskipsections.dent8 export [out.parquet]: export the whole log to Parquet for offline DuckDB forensics/audit (needs--features export; see examples/duckdb/).dent8 completions <bash|elvish|fish|powershell|zsh>: print a shell completion script.dent8 hook native-memory-guard: provider hook helper for session verification and native memory/rules write guards.dent8 schema postgres: print the initial Postgres schema.dent8 mcp serve: expose read/audit tools, the full belief surface, resources, and JSON-RPC batches to agents over MCP (stdio JSON-RPC), withstructuredContentfields for accepted/rejected/contested decisions, accepted event hashes, and integrity receipts.dent8 mcp install --agent <profile> [--dry-run|--check] [--command dent8|--local-bin]: patch the selected agent's MCP config with dent8, write it atomically, and print the resulting file.
Project Docs
Status
- Implementation Status — single source of truth for what is built
- Configuration — env vars + Cargo features in one place
- Changelog
Design
- Project Brief
- Architecture
- Domain Model
- Belief Revision — dent8's formal identity (the lead lens)
- Storage & the Event Log
- Interfaces
- Naming
Correctness & security
Planning & research
- Release Checklist
- Roadmap
- Related Work
- Research Dossier
- Open Research Directions
- Training Substrate
- Paper Outline · Preprint Draft
- Decision Records
Development
DENT8="cargo run -q -p dent8 --"
# The DB-verified Postgres adapter is feature-gated; its integration tests are gated
# on DATABASE_URL (they skip without one). Throwaway DB via Docker:
DATABASE_URL=postgres://postgres:dent8@localhost:5432/dent8 \
CI (.github/workflows/ci.yml) runs the workspace
fmt/clippy/test gate and the adapter against a Postgres service container.
Status
dent8 is pre-1.0 (v0.x) and experimental — the API, the on-disk event encoding, and the
storage schema may change between minor versions. docs/STATUS.md is the
single source of truth for what is runnable vs. library-only vs. design-only, and
docs/threat-model.md states precisely what the firewall does and
does not defend against. Security reports: see SECURITY.md.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.