Skip to content

Quickstart

Five minutes from an empty directory to a blocked DROP TABLE, an UPDATE that Postgres’s own change log confirms, and then the case Deedglass is for: the same UPDATE, the agent reports 1 row, and Postgres changed 301. It ends on the undo preview built from those rows.

Before you start

  • Docker is running, with about 2 GiB of free disk.
  • Node 22.12 or later (for npx), or Go 1.27 to build the CLI yourself.
  • macOS or Linux. On Windows, use WSL 2.

npx fetches the CLI for your platform. It has no install script.

Terminal
$ npx -y deedglass version
deedglass … · api 2026-10-01 · …

Prefer a binary on your PATH? go install github.com/deedglass/deedglass/cmd/deedglass@latest, then use deedglass in place of npx -y deedglass below.

In a new, empty directory:

Terminal
$ mkdir acme-agents && cd acme-agents
$ npx -y deedglass init --yes
deedglass init · setting up Deedglass in …
✓ Docker …
✓ Postgres …
✓ Deedglass http://127.0.0.1:…
✓ Agent quickstart-agent · key saved to .deedglass/quickstart.key …
✓ Policies postgres-safe v1 · enforce …
✓ Smoke · postgres.query Claimed · Matches · deed_…
✕ Smoke · DROP TABLE Blocked by policy "block-destructive-sql": DROP and TRUNCATE are never allowed for agents.
✓ Smoke · UPDATE 1 row Proven · Matches · Postgres committed the row in public.orders · deed_…
✓ Sealed. Your first record is in the ledger.

init starts Postgres 18.6 in Docker, runs deedglass serve on 127.0.0.1:8080, creates an org, an agent with a test key, the Acme demo database behind a Postgres connector, and the postgres-safe policy. Then it sends three actions through Deedglass:

  • a read, which runs: Claimed ·Matches
  • a DROP TABLE, which the policy blocks before Postgres sees it
  • an UPDATE of one row, which waits for a person (in dev, init countersigns as you), runs, and is checked at Proven: Proven ·Matches

With the Postgres image already pulled this takes 6 to 8 seconds on an M-series Mac. Run it again and it prints Nothing to change.

Terminal
$ npx -y deedglass doctor
deedglass doctor · 16 checks · …
…
16 ok

Each line is one check. A problem prints its fix; every check is explained in Doctor checks.

4. See the blocked action and the verified one

Section titled “4. See the blocked action and the verified one”

The admin key init saved lets the CLI read the Ledger:

Terminal
$ export DEEDGLASS_API_KEY="$(cat .deedglass/admin.key)"
$ npx -y deedglass actions list --limit 3
…postgres.execute…

The DROP TABLE is sealed as denied: its record names the rule and says that nothing ran. The UPDATE waited for a person, ran once approved, and was checked at Proven: Postgres’s change log shows exactly one row of public.orders changed.

The demo database has a legacy trigger written for it: when one order ships, it ships the next 300 open ones too. init --trigger turns it on, sends the same one-row UPDATE of order 42 as the quickstart agent (in dev, init countersigns as you again), and shows the Proven check:

Terminal
$ npx -y deedglass init --trigger
deedglass init --trigger · one UPDATE, a legacy trigger, and what Postgres really committed
…
✕ UPDATE order 42 Proven · Doesn't match · Postgres changed 301 rows in public.orders. The agent reported 1.
expected UPDATE 1 row in public.orders where id = 42 · sets status
observed UPDATE 301 rows in public.orders · 300 outside id = 42
…
✓ Trigger off orders_ship_open_batch dropped
✓ Undo preview Undo available · 301 rows in public.orders · 301 updates
…
The agent said 1 row. Postgres's change log says 301. Nothing was undone yet.
…

The agent’s tool answer said 1 row, and that is all an agent log would show. Deedglass read Postgres’s change log for the same transaction and found 300 more. The diff lists them (the first 20 here; all of them in the Console).

Then it turns the trigger off and previews the undo: 301 updates, planned from the rows Postgres recorded, each putting a status back. Nothing runs yet. Next prints the deedglass undo run line with the plan’s digest; the undo waits until a person countersigns it in the Console (Approvals), and Postgres’s change log checks the undo too.

Run init --trigger again any time: it puts the order statuses back to the seed’s first.

Pick your client. Each page shows the exact config, generated from the CLI’s own snippets.

Open http://127.0.0.1:8080/app and sign in as you@localhost.test. In dev, Deedglass writes mail to its log instead of sending it, so the sign-in link is in .deedglass/serve.log.

  1. The agent asked Deedglass to run a tool, and Deedglass checked its key.
  2. Your rules (the enforced policy) decided: allow, deny, or require approval.
  3. The denied call was sealed as a record and never reached Postgres.
  4. The allowed call ran through the Postgres connector as the least-privilege role deedglass_agent.
  5. The check compared what the tool reported with Postgres’s change log (Proven).
  6. Each result was sealed into the org’s record chain, which anyone can check offline.
  • The local stack is for a laptop: 127.0.0.1 only, dev mode, throwaway data. Run in production on one VM is the next step.
  • init doesn’t edit your MCP client’s config file. It prints what to paste.
  • It doesn’t use an existing database yet. Put Deedglass in front of Postgres covers your own database.
  • init --trigger changes only the demo database init made; the trigger exists for the length of the step.
  • deedglass init --stop stops the stack. It keeps .deedglass/ and the Docker volumes, so a later init picks up where you left off.