dry-run
Rehearses Git operations such as force push and reset --hard, classifying destructive commands and fetching remote branches into a throwaway repo to list the exact commits and authors that would be lost.
Provides read-only GitHub checks for actions, including stars, forks, open pull requests, and branch protection status, to assess impact before execution.
Supports rehearsing Railway API operations (e.g., volume deletion) by classifying actions and resolving targets with production signals, backup survival, and token permissions.
Provides SaaS action classification for Slack, including member counts, external sharing, and @channel mentions, to preview consequences before sending messages.
Provides SaaS action classification for Stripe, including refund amounts, customer counts, and live-vs-test mode, to total financial impact before execution.
Parses Terraform plan JSON to identify deletions and replacements, data-bearing resources, and backups stored within the same resource, reporting their impact before apply.
Supports rehearsing Vercel API operations by classifying actions and experimentally resolving targets with production signals, backup survival, and token scope.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@dry-runrehearse DELETE FROM orders without a WHERE clause and tell me the blast radius"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Dry Run
Rehearse anything before your agent does it.
Dry Run is a flight simulator for AI agents. Before an agent deletes a volume, drops a table, force-pushes, applies Terraform or refunds 2,000 charges, it calls dry_run, sees the consequences, and stops if it should. It works with Claude Code, Codex, Cursor, Gemini CLI and anything else that speaks MCP.

In April 2026 a coding agent found a cloud token in an unrelated file, assumed it was working in staging, and deleted a startup's production database and all its backups in nine seconds. Humans pause because they can picture the outcome. Agents need that as a tool.
Install
npx dry-run-agents setup # detects your agents, shows a diff, backs up configs, asks before applying
npx dry-run-agents doctor # checks Docker, credentials, registration
npx dry-run-agents demo all # four showcases, fully local, no accounts neededPublished on npm as dry-run-agents. The examples below use the short command dryrun; run it as npx dry-run-agents <command>, or install it once with npm i -g dry-run-agents. To build from source instead: npm install && npm run build && npm run bundle -w dry-run-agents, then node packages/cli/dist/dryrun.mjs setup.
Requirements: Node 22+. Docker is optional but recommended: it enables Tier 3 sandbox rehearsal. Pull the two images once (no network is used when rehearsing):
docker pull alpine/git:latest # shell / git rehearsal
docker pull postgres:16-alpine # SQL rehearsal and the missing-where demoWithout Docker, Dry Run still works at Tier 1 and 2 and says so in every report. dryrun doctor tells you what is missing. Tested on macOS and Linux (CI); Windows: use WSL2 (untested).
setup registers an MCP server named dry-run. Read-only credentials for Tier 2 (database, Stripe, GitHub...) are passed to it through environment variables: see docs/credentials.md.
Related MCP server: agent-guard
What you get
Typical findings (paraphrased from real reports):
The agent is about to… | Dry Run tells it |
| "Removes 12,481 rows of |
delete a cloud volume | "Deletes |
| "Erases 3 remote commits by Priya Nair: |
refund 2,000 charges | "USD 69,500 to 800 customers, live mode. Irreversible." |
Every report returns a verdict: safe, confirm or block, with the evidence for each claim, and a shareable report card.

How it works
agent ──dry_run(action)──▶ MCP server ──▶ simulator for that action type
│
┌───────────────────────────────┼───────────────────────────────┐
▼ ▼ ▼
Tier 1: static Tier 2: read-only Tier 3: sandbox
parse + classify inspect the real system run it on a disposable copy
(SQL parser, shell (GET-only HTTP, read-only (Docker, no network, CPU/mem/
tokenizer, op catalog) Postgres session, git fetch time limits; diff files/rows/
into a throwaway repo) schema before vs after)
└───────────────────────────────┼───────────────────────────────┘
▼
findings ──▶ policy engine ──▶ Consequence Report
verdict · effects · reversibility
environment · blast radius · evidence
safer alternative · report cardDry Run reports; it never executes. The agent still runs the real action, after the verdict.
The guarantees, and how they are enforced
It never changes a real system. The HTTP client Dry Run hands to simulators has only
getand a GraphQL-query method (mutations are rejected before sending). Postgres access goes through a gate that accepts a singleSELECT/EXPLAIN/SHOW, in a server-side read-only session;EXPLAIN ANALYZEis refused. The untrusted statement is only ever executed inside a disposable, network-less container. Tests run every API simulator (cloud, Stripe, Slack, GitHub) against mock servers that record every request and fail on any non-GET, and every query sent to a real Postgres is asserted read-only.Unknown is not safe.
safeis reachable only if a simulator matched, Tier 1 positively classified the action as benign, nothing is unverified, no tier errored, and it is reversible. Unknown command, operation, provider, unparseable SQL, unreachable remote, missing credentials, Docker missing: allconfirmat best. Property tests and a golden corpus of dangerous inputs enforce this.Local-first. No telemetry, no uploads. Reports are written to
./.dryrun/reports/(redacted). Secrets are masked in reports, cards, logs and errors; tests assert absence across stdout, stderr, JSON, saved files and SVG.Action content is untrusted. Commands, SQL and payloads are parsed, not executed, except in the sandbox. MCP output wraps the report in an
<dryrun_report untrusted_strings="true">envelope and tells the agent that strings in it are data.Evidence for every claim. A report whose finding lacks evidence fails to build.
Showcases
Run any with dryrun demo <name> or all with dryrun demo all (writes JSON, SVG and PNG cards to ./dryrun-demo-output/). No accounts needed; missing-where and the sandbox part of force-push need Docker.
Demo | What happens | |
| Mock cloud with a production Postgres volume and same-volume backups; an over-scoped token sits in |
|
|
|
|
| Local git remote; a force push would erase a teammate's 3 commits. Names them. |
|
| Mock Stripe; a script would refund 2,000 live charges. Totals the money. |
|
Using it
From an agent (MCP): tools dry_run, explain_report, list_simulators. setup also installs short instructions (a Claude Code skill and CLAUDE.md block, AGENTS.md for Codex, GEMINI.md, a Cursor rule with --project) telling the agent to call dry_run before risky actions and to obey the verdict.
From the CLI:
dryrun sql "DELETE FROM orders" --db-env DRYRUN_DATABASE_URL
dryrun shell "git push --force origin main"
dryrun tf plan.json # terraform show -json tfplan > plan.json
dryrun api railway volumeDelete --params '{"volumeId":"..."}'
dryrun saas stripe refund --params '{"charges":["ch_1","ch_2"]}' --credential-env STRIPE_API_KEY
dryrun saas slack chat.postMessage --params '{"channel":"C123","text":"<!channel> hi"}'
dryrun list # what can be rehearsed here, by tier
dryrun explain <report-id> # plain languageExit codes: 0 safe, 2 confirm, 3 block, 1 error. Add --json and --card report.png.
What each simulator covers
Simulator | Tier 1 | Tier 2 (read-only) | Tier 3 (sandbox) |
shell / git | classify rm/mv/chmod/dd/force push/reset --hard/clean/publish/scripts/pipes/redirects; flags paths outside the project, | force push: fetches the remote branch into a throwaway repo, lists the exact commits and authors that would be lost | Docker, no network, read-only root fs, no capabilities; diffs files deleted/modified/created, and whether git can restore them |
postgres | real parser; DROP, TRUNCATE, DELETE/UPDATE without WHERE, DROP COLUMN, CASCADE | exact affected rows from the statement's own | disposable Postgres loaded with the schema and a row sample; diffs row counts and schema |
terraform | parses | — | — |
cloud_api | operation catalog (Railway, Vercel, AWS, plus the reference mock) | resolves the target: size, production signals (name, tags, domains, traffic), whether backups survive, what the token can do | — |
saas | Stripe, email, Slack, GitHub classification | Stripe amounts/customers/live-vs-test; Slack members/external sharing/@channel; GitHub stars/forks/open PRs/branch protection | — |
Honest status: Railway and Vercel classification comes from public API names; their Tier 2 resolvers are experimental (verified against the reference mock, not live APIs). AWS is classification-only; its targets are reported unverified, so AWS deletes are never safe. Email is Tier 1 only. See each catalog's status field.
Verdict policy
Defaults live in dryrun.config.json (all optional):
{ "thresholds": { "blockRows": 1000, "blockBytes": 1000000000, "blockMoney": 10000, "blockPeople": 1000,
"confirmRows": 1, "confirmFiles": 10, "confirmMoney": 1, "confirmRecipients": 50 },
"blockUnknownEnvIrreversible": true }Environment (production / staging / local / unknown) is inferred from evidence the simulator can see: names and tags containing prod/production/live, public domains and live traffic (cloud), the credential's mode (Stripe live vs test), protected/default branches (git). The report lists the evidence it used.
block: irreversible + critical in production; irreversible data loss where the environment cannot be confirmed as non-production; irreversible over a threshold; catastrophic commands (rm -rf /, ~, dd to a device). An invalid config is an error, never a silent fallback.
Credentials
Create read-only credentials for Dry Run and never reuse the agent's write credentials. See docs/credentials.md.
FAQ
Does Dry Run touch my systems? No writes, by construction (see the guarantees). It does make read-only calls (GET requests, read-only SQL, a git fetch of the remote branch into a temp repo) using the read-only credentials you give it, and it lists every call in the report's evidence.
Does anything leave my machine? No telemetry or uploads. The only network traffic is the read-only calls to the systems you point it at, and Docker image pulls you run yourself.
Can a malicious command or SQL hurt me while it is being rehearsed? Untrusted text only ever runs inside a container with no network, no capabilities, no-new-privileges, a read-only root filesystem, CPU/memory/pid/time limits, and a throwaway copy of your project (symlinks are copied as links, never followed). Projects over the copy limit skip Tier 3 rather than mount the real directory. Review docs/security.md.
What if Docker isn't installed? Tier 3 is skipped, the report says so, and the verdict can never be safe for anything that needed it.
What if Dry Run itself fails? Errors become confirm with the reason in the report. If the MCP server is unavailable, the installed instructions tell the agent to treat that as confirm.
Will the agent always call it? No. Instructions are advisory. For enforcement, pair Dry Run with permission prompts or a Claude Code PreToolUse hook; Dry Run does not install one yet.
Why not just BEGIN … ROLLBACK? Triggers, locks and sequences can have real side effects. Dry Run never runs your statement on the real database.
Contributing
See CONTRIBUTING.md. Adding a provider is a JSON file plus a test. A wrong safe verdict is treated as a security bug: report it via SECURITY.md. Design notes: docs/DECISIONS.md, history: CHANGELOG.md.
Status and limits (v0.1)
Early release. The report schema (schema_version: "0.1") may change before 1.0. Experimental: Railway/Vercel resolvers, AWS (classification only), email (Tier 1 only).
Reports only; it never executes for the agent. Postgres only. Windows via WSL. Sandbox rehearsals are approximations (no network, different OS tools, sampled data), and reports say where. Not a replacement for backups, least-privilege tokens or branch protection.
License
Apache-2.0
This server cannot be deployed
Maintenance
Related MCP Connectors
Pre-execution governance for AI agents. Deterministic PASS/FAIL/REVIEW verdicts, replayable proof.
Deterministic safety, correctness & cost gate that vets Postgres SQL before your AI agent runs it.
Deterministic runtime safety for AI agents: scan PII, gate tool actions, verify LLM output.
Deterministic allow/require_approval/deny verdicts for agent actions, before they happen.
Related MCP Servers
- AlicenseAqualityDmaintenanceA pre-action risk gate for AI agents. Your agent calls the forecast tool before any irreversible action — send email, run SQL, make a payment, delete a file — and gets a risk score (0–100) and a GO / CONFIRM / STOP verdict in a few seconds.189 npmMIT
agent-guardprivate
AlicenseAqualityAmaintenanceSafety checks an agent runs before it acts — flags malicious packages, destructive shell commands, secret leaks, and web-backend holes before execution.812 PyPIMIT- AlicenseAqualityBmaintenanceEnables AI coding agents to avoid irreversible mistakes by intercepting risky deletions, overwrites, and commands before execution, applying path, pattern, and blast-radius safeguards with quarantine backups.324 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to operate a simulated IT operations environment through policy-enforced, risk-tiered tool calls with human approval for risky writes, dry-run previews, rate limits, emergency lockdown, and tamper-evident auditing.MIT


