The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Dashclaw listing page.
With a supported enforcement integration, when your AI agent (OpenClaw, Hermes, Claude Code, Codex) tries something destructive or expensive, DashClaw catches it before it runs and asks you first, even when you are not at the keyboard. Every decision lands in a signed ledger.
Run agents unattended without giving them unconditional authority.
What you get · What it stops · The loop · What it is not · Quick start · Connect an agentAI agents: setting DashClaw up for your user? Run
npx dashclaw up --yes --no-browser— the plain command prompts and will hang a non-interactive shell. The API key lands in~/.dashclaw/instance.json; verify withGET http://localhost:3000/api/healthandnpx dashclaw doctor. Full runbook: dashclaw.io/llms.txt. Do not attempt the hosted trial headlessly — its captcha needs your human.
A 10-second capability scan before the dense sections:
dashclaw_invoke can cancel a blocked call before execution. Bare SDK, API, and ordinary MCP integrations are cooperative: the caller must honor the verdict./approvals inbox, the CLI, a phone PWA, Telegram, or Discord. No presence required.block at guard time; weaker ones raise a warn.At a supported enforcement seam, DashClaw is a fail-closed approval layer between an agent deciding to call a tool and the tool actually running. The Claude Code, Codex, and Hermes hooks, the OpenClaw gateway, and dashclaw_invoke can stop the call. Bare SDK, API, and ordinary MCP integrations still evaluate and record governance, but enforcement is cooperative: their caller must honor the result.
These are the catches on the record, from the maintainer log and THESIS.md, each one the same loop firing:
rm -rf on a working directoryDROP TABLE against a live databasegit push --force origin main.env and preparing to exfiltrate it (risk 100, two policies firing at once)The last one caught the maintainer's own shell command mid-verification: extracting an API key from .env.local, blocked live at risk 100. Here is roughly what the seam does with it:
The audience is narrow on purpose: a solo developer or small team running long, unattended coding-agent sessions (overnight runs, CI agents, background fleets) against a real repo and real infrastructure. You kick off a one-to-six-hour run, cannot watch every tool call, and are one bad run away from any of the four lines above.
Where DashClaw fits. Local runtime permission prompts serve the operator who is at the keyboard. DashClaw focuses on unattended work: remote and async approval, shared policy across supported runtimes, an auditable decision trail with signed evidence where issued, calibrated interruptions, and time-bounded liveness diagnostics for installed enforcement seams.
It is 2am, the run is in hour three, and the agent reasons its way to git push --force origin main. With the hook installed, DashClaw freezes the call and pages you wherever you are; you tap deny, and the decision ledger records the resolution. A signed receipt exists only where the eligible evidence path issues one.
The hook seam owns this lifecycle inside Claude Code, Codex, and Hermes. A bare SDK integration is cooperative, so application code must keep the real effect inside runGoverned() as shown here.
runGoverned() waits for required approval, claims one execution attempt under a fresh policy check, invokes the callback, and reports the outcome. The claim binds the action, agent, credential principal, and exact act; any applicable operator or plan authority is consumed atomically with the claim. If claim or completion acknowledgement is lost, the helper does not repeat the callback. Reconcile the action and external system before retrying; ledger idempotency cannot make an external effect exactly once. Python uses run_governed(). Full example: QUICK-START.md.
Upgrade order: deploy the matching schema and server before upgrading governed SDK helpers, which require execution-claim protocol 1. Hooks and OpenClaw preserve legacy guard/approval behavior only when the server advertises no claim protocol; that mode lacks atomic execution claims. Malformed or unsupported advertisements fail closed. Set DASHCLAW_REQUIRE_EXECUTION_CLAIMS=1 after the server upgrade to reject legacy responses. See the execution contract.
The decision lattice is allow < warn < allow_contained < require_approval < block. Join is max; a block is absolute and cannot be downgraded in the ledger. allow_contained only ever reaches a caller that advertised the capability string for the staging medium it would use — client_capabilities: ['allow_contained'] for a git worktree, ['allow_contained:db'] for an ephemeral database branch; an older client sees require_approval instead (version skew only tightens).
[!IMPORTANT] Enforcement is mechanically real only where DashClaw sits in the seam between decide and execute: the Claude Code, Codex, and Hermes PreToolUse hooks (fail-closed, exit-2 on block), the OpenClaw gateway, and
dashclaw_invoke. Everywhere else (bare SDK, API, and MCP callers, desktop chat) governance is cooperative: the caller consults guard and honors the decision; recording requires the caller to use a recording path. A block is never downgraded in the ledger. DashClaw does not claim universal hard enforcement. Even at the mechanical seam, the hook runs at the agent's own privilege level. An agent with write access to the hook path can disable its governor; DashClaw can govern and report that write, but the tamper-resistant boundary belongs to the deployment: a container, separate OS user, or read-only hook path. Per-surface table and full threat model:docs/architecture/enforcement-boundary.md.
This section exists so you can rule the tool out fast if it is the wrong thing.
dashclaw_invoke can hold a registered credential and execute that registered external API after server-side governance. The v5.0.0 cull removed the wider platform tier, and a CI surface-budget brake prevents it growing back.dashclaw_invoke); everywhere else it is cooperative. See the boundary note above.Full product definition and everything explicitly out of scope: THESIS.md.
Day-to-day, DashClaw is built and maintained by an AI agent, in public. That agent operates under a human-held charter, MAINTAINER.md, which pins five invariants it cannot change:
block is never downgraded, in the ledger or anywhere else.Material maintainer changes and design decisions are recorded in the maintainer log. Governing autonomous agents is the exact problem DashClaw exists to solve, so the project governs its own maintainer with its own runtime. That is the source of the sharpest design constraints below. The enforcement boundary, the blackout, and the liveness incident are included here so the claims remain auditable.
One command provisions Postgres (Docker or embedded), generates secrets, mints your API key, applies migrations, starts on :3000, offers to wire Claude Code hooks, and opens your browser already signed in. No account required on the path to your first caught action.
Click the button, add Neon when prompted, and fill in the variables from .env.example. Provider plans and limits determine hosting cost. The configured Vercel build runs schema migration before building the app; required-schema or migration-checksum failures stop it.
The hosted trial is the secondary door: to see the Approvals inbox before deploying anything, hosted.dashclaw.io mints a capped trial workspace in the browser. Coming from the trial, click Export workspace on its /connect card and run dashclaw import <bundle.json> against your own instance. Policies, decisions, history, agents, and assumptions carry over; API keys and secret values never ride a bundle. Operator runbook: docs/hosted-deployment-runbook.md.
Every path lands on the same guard engine, the same decision ledger, and the same Approvals inbox. The enforcement column is honest about which paths halt mechanically and which are cooperative.
| Your agent runs on | Path | Enforcement | Guide |
|---|---|---|---|
| Claude Code | Plugin + PreToolUse hooks | Mechanical, fail-closed | claude-code.md |
| Codex | Plugin | Mechanical, fail-closed | plugins/dashclaw |
| Hermes Agent | Plugin (lifecycle hooks) | Mechanical, fail-closed | hooks/README.md |
| OpenClaw | Gateway plugin | Mechanical | packages/openclaw-plugin |
dashclaw_invoke (MCP) | Guarded invoke | Mechanical | mcp.md |
| Claude Desktop (chat) | OAuth connector, no install | Cooperative | CLAUDE-DESKTOP-PLUGIN.md |
| Any stdio / HTTP MCP host | MCP server | Cooperative | mcp.md |
| LangChain / CrewAI / AutoGen | Python SDK | Cooperative | sdk-python/README.md |
| Custom / framework-less | Node or Python SDK | Cooperative | sdk/README.md |
| Anything HTTP | REST API + webhooks | Cooperative | OpenAPI |
End-to-end examples per runtime: examples/.
Coding-agent plugins (Claude Code, Codex, Hermes). One plugin source (plugins/dashclaw/), three ecosystems. Each manifest ships the MCP config, the dashclaw-governance protocol skill, and a distinct agent_id.
This repo is also a native Claude Code plugin marketplace — no CLI needed:
Claude Code hooks govern Bash, Edit, Write, MultiEdit, sub-agent spawns, and every mcp__* call with a fail-closed PreToolUse check. Fresh installs start in enforce mode (the seeded catastrophe pack holds the irreversible class); pass --observe or set DASHCLAW_HOOK_MODE=observe to log without blocking, and re-installs keep whichever mode you chose. Observe mode is loud, never silent: /approvals and /decisions show a red banner while any agent reports it, unenforced verdicts render "Logged, not enforced" in the ledger, and a gated action that executes anyway gets an executed_despite witness stamp from PostToolUse — a logged block is never presented as an enforced one. Narrowing the scope is loud too: DASHCLAW_GOVERNED_CATEGORIES decides which tool categories call guard at all, and an excluded category exits before the network call, so its tool calls are simply absent from /decisions — which reads identically to "that agent did nothing." Since v5.20 the hook declares the categories it is not governing on the calls it does make, and any category dropped below the default raises a red Governance scope narrowed signal naming what stopped being watched. Verify the wiring fires:
OpenClaw. @dashclaw/openclaw-plugin intercepts calls delivered through the gateway's installed before_tool_call hook, so those calls need no agent-initiated DashClaw tool. The CLI installs it, patches config, and writes the governance protocol into the resolved workspace's AGENTS.md. Embedded native tools need their own runtime hooks.
Run it bare in a terminal and it walks you through everything you're missing: no DashClaw instance yet? it offers the hosted trial or a local install (dashclaw up) inline; no API key? it collects one; then it suggests a per-machine agent id (<hostname>-openclaw). With --base-url, --api-key, and --agent-id (or the matching env vars) it runs non-interactively. Full guide: dashclaw.io/guides/openclaw.
MCP server (zero code). @dashclaw/mcp-server exposes 17 governance MCP tools across core governance, retrospection, identity, team tasks, and plans, plus 3 read-only resources (dashclaw://policies, dashclaw://agent/{agent_id}/history, dashclaw://status).
Every instance also serves Streamable HTTP MCP at /api/mcp. For Claude Desktop, add that URL as a custom connector (Settings, Connectors); OAuth auto-discovers, no key in the UI.
SDKs. npm install dashclaw (Node 18+) or pip install dashclaw (Python 3.7+). The 41-method canonical Node surface covers guard, record, assumptions, approvals, durable-execution finality, security scanning, sessions and the action graph, pairing, risk signals, policy simulation, plan authorization, delegation constraints, containment verdicts, and team tasks. The Python SDK exposes 61 methods, plus CrewAI and AutoGen integrations. Plan authorization pins the approved plan's content hash at submission (plan_hash); attestPlan(planId, planHash) / attest_plan(plan_id, plan_hash) let an unattended runner confirm -- before its first model call -- that the plan it is about to act under is still approved, unexpired, and hash-matched, failing closed on drift (not_approved | expired | revoked | hash_mismatch) without ever echoing the stored hash back on a mismatch.
REST. Every primitive is HTTP. The stable contract is pinned in docs/openapi/critical-stable.openapi.json; the full inventory (136 routes: 43 stable, 18 beta, 75 experimental) is in docs/api-inventory.md. Webhooks: decision.created, action.created, lost_confirmation, configurable per org.
The protocol-1 diagram above shows the current execution path. Eight points define its scope:
/policies/packs — 18 curated packs (spend, outbound comms, unattended overnight runs, prod infra, subagent fleets, and more), each previewable against your own action history before a one-click install./approvals, the CLI, the mobile PWA at /approve, Telegram, or Discord. When one policy blows its interruption budget, per-action pings collapse into one flood banner with bulk-resolve. A repeat interruption can be retired at the card with "Allow, don't ask again", which writes a target-scoped, expiring, revocable grant rather than silencing anything. Pending approvals are never auto-resolved.lost_confirmation. Protocol-1 execution claims give one caller authority for one attempt, but they cannot prove whether an external effect completed after a response was lost. Unknown completion requires reconciliation or effect-specific idempotency before retry. Spec below and in docs/architecture/durable-execution-finality.md./policies#calibration, default preview) turns your approve/deny verdicts into a proven false-interruption bound. Shadow-first, then it loosens as well as tightens: below the calibrated threshold an approval request becomes a recorded warning instead, bounded by the riskiest action you have personally approved and retracted by a single deny. It never reaches allow, never touches a block, and never edits a policy — standing policy changes still route through human-ratified proposals.block at guard time; lower-severity patterns raise a warn./policies; the guard calls it for applicable evaluations and joins its verdict stricter-wins — external deny is absolute for the evaluated act, external allow never overrides a stricter local result, and the verdict is bound to the exact input digest. An unreachable applicable provider takes an explicit posture (fail_closed default) and is recorded as external unavailable. A provider can be scoped to exact action types; out-of-scope acts stay local-only. Contract: docs/external-verdict-provider.md.The 18-day blackout (point 2). The reference deployment ran with all policies off for 18 days in June 2026 because the default pack fired an approval roughly every ten seconds. That is why the default is catastrophe-only: a governor you disable is worse than none. Cited in MAINTAINER.md and THESIS.md.
The governor caught asleep (point 6). In v4.72.1 a hook timeout was set to 3600000 in a field Claude Code reads as seconds; the harness multiplied by 1000, 3.6e9 ms overflowed the 32-bit timer ceiling, the timer fired immediately, and the harness cancelled the hook and ran the tool anyway. Every block and every approval wait was silently skipped, including a block on git push origin main. The worst part: the orphaned hook process lived long enough to land its guard call, so the ledger kept filling with decisions that looked enforced. Maximum false confidence. That incident is the entire reason the liveness probe (v4.75.0) verdicts by execution and not by the ledger. Story: docs/maintainer-log.md.
The calibration bound (point 5). The controller is the Gibbs-Candes online adaptive conformal recursion on a monotone decision loss, with a deterministic false-interruption bound: for any adjudication sequence (arbitrary drift, arbitrary dependence, adversarially chosen), the realized false-interruption rate is at most α + (b − θ₁)/(γT). With shipped constants (γ=2, θ₁=80, b=102) the excess above target is ≤ 11/T: within 0.1 of target after ~110 labeled adjudications, within 0.01 after ~1100. No distributional assumptions. Proof sketch: docs/architecture/governance-core-theory.md.
Signed, verifiable receipts (point 4). Each non_fabrication decision attempts to attach an Ed25519 proof receipt proving the verdict, the ruleset version (a content hash of the source of truth), and the issuer signature; signing is best-effort and never gates the verdict. The compliance export is a signed, hash-chained bundle. Anyone can re-verify at POST /api/integrity/verify with no API key. The signing key is the instance's own Ed25519 key, published via JWKS. Contract: docs/architecture/runtime-api.md.
The anti-regrowth brake. A 2026-03 SDK cull regrew to full sprawl in four months because the promised CI gate never shipped. This time scripts/check-surface-budget.mjs counts every governed surface and fails CI when any exceeds its v5.0.0 ceiling. Raising a ceiling requires amending THESIS.md and contracts/surface-budget.json in the same commit with a written reason.
Architecture map: PROJECT_DETAILS.md. Runtime API contract: docs/architecture/runtime-api.md.
Approved actions carry a terminal outcome separate from their lifecycle status. Five states, one-shot transitions, enforced at the repository layer.
| State | Meaning |
|---|---|
pending | Approved, no outcome reported yet. |
completed | Finished successfully. Set by the agent. |
partial | Started but did not finish. Set by the agent with a progress payload. |
failed | Attempted and errored. Set by the agent with an error message. |
lost_confirmation | Timeout exceeded without a report. Set by the cron sweep. |
POST /api/actions/[actionId]/outcome is one-shot: the first call wins, every later POST returns 409. A cron sweep marks stale pending rows lost_confirmation and emits a signal.detected event. That state means completion is unknown, not that the effect did not happen. Reconcile the external system and action record, or use the target system's idempotency primitive, before retrying. Spec: docs/architecture/durable-execution-finality.md.
waitForApproval() uses SSE for low latency and falls back to polling, reconciling the authoritative action state before it resolves.
| Surface | What it is | Setup |
|---|---|---|
Dashboard (/approvals) | The primary inbox: what your agent tried, what waits on you, and per item — allow, deny, or stop being asked about that exact target — each led by a plain-English sentence for what the command does. | None |
CLI (@dashclaw/cli) | Terminal inbox: dashclaw approvals, dashclaw approve <id>. | npm i -g @dashclaw/cli |
Mobile PWA (/approve) | Phone-first allow/deny with risk score and policy. Add to home screen. | None |
| Telegram | Inline Approve/Reject in an admin chat. | dashclaw install telegram (guide) |
| Discord | Inline Approve/Deny on DM embeds. | .env.example |
docs/README.md is the full index, ordered by adoption journey (understand, try, connect, operate, reference). Highlights:
Stated plainly, because a security tool that oversells itself is a liability:
Issues and PRs are welcome on github.com/ucsandman/DashClaw. If DashClaw caught something on one of your runs, a GitHub star is the honest signal that the wedge is real.
If my tools save you time, you can support my work here: