Looks fine in chat
DELETE FROM sessions WHERE user_id = user_idWhat it actually does
A typo that compares a column with itself. It is true for every row, so every session is deleted.
Open source · Apache-2.0 · pre-release
Changeward sits between your agents and your databases, clusters and infrastructure. Every change an agent wants to make is previewed exactly, checked against your policy, applied by Changeward, and kept undoable.
Works with Claude Code, Codex, OpenCode, Gemini CLI, Cursor, any MCP client, GitHub Actions and GitLab CI.
ALTER TABLE invoices DROP COLUMN legacy_refDELETE FROM sessions WHERE user_id = user_idDELETE FROM sessions WHERE user_id = user_id48,210 rows: every row in public.sessions · dry run, rolled backLow risk: through in milliseconds. Risky: a person decides. Dangerous: stopped before it runs.
The problem
Coding agents now run psql, kubectl and terraform with your credentials. In a chat window, a dangerous command looks just like a safe one, because you are shown the command, not what it will do.
What the agent shows you
Stale sessions are slowing down login. I'll clean them up:
DELETE FROM sessions WHERE user_id = user_id;Looks routine. You've approved forty of these today.
What Changeward shows you
| id | user_id | last_used |
|---|---|---|
| 9f1c | 4 | 2026-10-24 09:12 |
| a2e7 | 17 | 2026-10-24 09:40 |
| b6d0 | 4 | 2026-10-24 10:03 |
| c311 | 88 | 2026-10-24 11:27 |
| d9a4 | 23 | 2026-10-24 12:55 |
| e05b | 17 | 2026-10-24 13:18 |
| … 48,204 more | ||
user_id = user_id is true for every rowapproval requiredThe effect is obvious, and policy stops it before anything runs.
Looks fine in chat
DELETE FROM sessions WHERE user_id = user_idWhat it actually does
A typo that compares a column with itself. It is true for every row, so every session is deleted.
Looks fine in chat
ALTER TABLE events ALTER COLUMN id TYPE bigintWhat it actually does
Rewrites the whole table under an exclusive lock. On a big table, writes stop until it finishes.
Looks fine in chat
kubectl apply -f deploy/What it actually does
Overwrites the fix someone applied by hand during last night's incident, or fights Argo CD for the object.
Looks fine in chat
terraform applyWhat it actually does
“1 to replace” is an aws_db_instance. Replacing a database means destroying it first.
The agent stops and asks before each command. After the fortieth prompt, people click "yes" without reading the SQL. And reading SQL does not tell you how many rows it touches anyway.
Skip permissions and hope. When something goes wrong, you find out afterwards, if you look, and "undo" means restoring a backup.
Show the exact effect before anything runs, let policy decide by risk and environment, apply only what was approved, and keep every change undoable. That is what Changeward does.
July 2025
During an explicit code freeze, an AI coding agent ran destructive commands against a production database. It deleted records for 1,206 executives and 1,196 companies, and then misreported what had happened.
With Changeward, that DELETE is planned in a transaction that is always rolled back. You see the exact rows, policy denies it in production, and the audit log records what really happened. Run the replay demo
How it works
The agent keeps doing the work. Changeward becomes the only way its changes reach your systems.
The agent calls propose_change with the SQL, manifest or plan, plus its intent. It never gets your credentials.
Changeward dry-runs it for real (a rolled-back transaction, a server-side dry run, a Terraform plan) and records the exact effects.
Policy routes on environment, reversibility and blast radius: auto-approve, ask you, ask someone else, or deny.
Changeward applies exactly the approved plan, then checks that only the planned rows or objects moved.
Every change keeps a tested undo path. Undo one step, the whole session, or let policy require a checkpoint first.
Try it
Pick what the agent wants to do and where. Changeward plans it, policy decides with the built-in defaults, and anything applied can be undone.
DELETE FROM sessions WHERE user_id = user_idreversibledestructive48,210 rows
approval required out of band, from a second person
Only the planned rows moved. The undo path is recorded on the session timeline.
See the effect, not the command
Changeward plans every change against the real system and shows what will actually happen: rows, locks, table rewrites, objects created, changed or destroyed.
Every row that changes, with before and after values. In production, values are hidden and keys hashed.
$ changeward exec --intent "archive customers inactive for two years" \ "UPDATE customers SET status = 'archived' WHERE last_seen < DATE '2024-10-19'" plan p_805e48ce4b33 · shop (personal) · reversible · 99 rows · live-dry-run #1 UPDATE public.customers — 99 rows ~ id=102 status: "active" → "archived" ~ id=103 status: "active" → "archived" … change c_0abd3564f023 (#2) — verified · 99 rows · UPDATE 99
Undo
Agents work in sessions. Each change records exactly how to reverse it: row images, soft-dropped tables, previous manifests, the last-applied config.
changeward logsession s_30f9a360ec02 · agent=claude-code · env=personalALTER TABLE customers ADD COLUMN status textUPDATE customers SET status = 'archived' WHERE …DELETE FROM customers WHERE status = 'archived' AND …Click undo on step 2.
changeward rewind undoes everything the agent did, newest first.checkpoint-only, and policy can require a checkpoint first.Before and after
Policy
Each connection is bound to an environment class that the agent can never change. Sensible defaults come built in; write your own rules in CEL for anything else.
personalReversible changes are auto-approved. Anything else asks you in the agent's UI.
shared-devAuto-approved if reversible, non-destructive and under 1,000 rows; otherwise you confirm.
stagingAuto-approved if reversible, non-destructive and under 10,000 rows; otherwise a second person approves.
prodNeeds an incident or ticket reference, plus approval from someone other than the proposer.
prod-restrictedRead-only for agents acting directly.
rules:
- name: prod-destructive-needs-dba
when: change.env == "prod" && change.destructive
decide: require
channel: out-of-band
approvers: ["group:dba", "group:sre"]
quorum: 2
- name: release-freeze
when: change.env == "prod" && calendar.freeze("q4-release")
decide: denydblink, DO blocks) are never run while planning.Two lanes, one engine
The same planner, policy and audit log cover both. Most teams use both.
Direct lane
Coding agents and your own agents call Changeward through its MCP server, hooks, SDKs or an MCP gateway. Each write becomes plan → decision → apply → verify, on a session timeline you can undo step by step.
$ changeward log SESSION s_30f9a360ec02 agent=claude-code #1 ALTER TABLE customers ADD COL... verified #2 UPDATE customers SET status ... verified $ changeward rewind --yes
CI lane
Migrations, Kubernetes manifests and Terraform plans in a PR are rehearsed or dry-run. The report is posted on the PR or MR, and policy gates the merge or the deploy.
# .github/workflows/changeward.yml
- uses: srawlin/changeward/integrations/github-action@main
with:
mode: gate
synthetic-rows: 1000changeward promote --pr turns what an agent did directly in dev into migration files and a pull request, so Git stays the source of truth.
Integrations
One command sets up a coding agent: changeward install claude-code adds the MCP server and a hook that blocks direct writes and points the agent to Changeward's tools. Claude Code, Codex, OpenCode and Gemini CLI were tested end to end with each real CLI.
Measured, not promised
Agent unsafe-action benchmark v0: 20 scripted scenarios on Postgres 18, including actions induced by prompt injection. Each runs once with raw credentials and once through Changeward.
The two misses with built-in policy are small, reversible updates whose effect doesn't match what was asked for (one came from an injected ticket). Optional intent signals catch both and route them to a person; signals can only tighten a decision, never loosen it. Risky actions auto-applied in a personal environment count as safe only when undo restored the database byte for byte. v0 is scripted; v1 will drive real agents. Methodology and full results
Who it's for
Your developers already point agents at psql and kubectl. Give them a paved road instead of a ban: one policy, one audit log, and a shared executor that holds the credentials so they never reach a laptop.
Shared executorLet Claude Code or Codex move fast on your dev database without babysitting every command. Read the session timeline afterwards and undo any step, or the whole session, in one command.
Getting startedYour support or ops agent needs to write to real systems. The Python and TypeScript SDKs give it plans, approvals and undo, with policy you control rather than a prompt.
SDKsSeparation of duties, approvals bound to the exact plan, production values redacted from plans, and a hash-chained audit log you can export to OpenTelemetry.
ConceptsQuick start
Pre-release: build from source (Go 1.27+ and a C compiler). Homebrew, npx and uvx packages come with the first release.
git clone https://github.com/srawlin/changeward && cd changeward
make build && export PATH="$PWD/bin:$PATH"Its environment class decides the default policy.
changeward connect app --dsn 'postgres://localhost/myapp_dev' --env personalAdds the MCP server and a hook that blocks direct writes.
changeward install claude-code # or codex, opencode, gemini, cursorThe session timeline, step-by-step undo, and a local web view.
changeward log
changeward undo 2 --yes
changeward uiFAQ
checkpoint-only, and policy can require a checkpoint first. Keep your backups.reversible, compensatable, checkpoint-only or irreversible. Policy sees it, so "irreversible in production" can be denied or sent to a DBA.Open source, self-hosted, and running in five minutes.