Apron Chat Protocol
Apron is a minimal protocol for self-hosted chats. Simple enough to write a server in ~100 lines, powerful enough for rooms, threads, bots, reactions, and more.
Changeward lets AI agents change real databases, clusters and infrastructure safely: every change is previewed exactly, checked against your policy, applied, verified and kept undoable. Open source.
Developer toolsGitHub @srawlinOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
Let AI agents change real systems, safely. 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. Low-risk changes go through in milliseconds; risky ones wait for a person.
Taken from the repository README
Loading the full README.
Read the full README ↗Let AI agents change real systems, safely. 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. Low-risk changes go through in milliseconds; risky ones wait for a person; dangerous ones are stopped before they run.
Website · Documentation · Getting started · Open source, Apache-2.0, pre-release
$ changeward exec "DELETE FROM orders WHERE total > 990"
plan p_5b14 · app (personal) · reversible · 10 rows · live-dry-run
#1 DELETE public.orders — 10 rows
- id=17 total=999.00 customer_id=4 …
change c_0a34 — verified · 10 rows · DELETE 10
$ changeward undo c_0a34 --yes
undone c_0a34 DELETE FROM orders WHERE total > 990
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:
| Looks fine in chat | What it actually does |
|---|---|
DELETE FROM sessions WHERE user_id = user_id | A typo that compares a column with itself: it matches every row, so every session is deleted. |
ALTER TABLE events ALTER COLUMN id TYPE bigint | Rewrites the whole table under an exclusive lock. On a big table, writes stop until it finishes. |
kubectl apply -f deploy/ | Overwrites the fix someone applied by hand during last night's incident, or fights Argo CD for the object. |
terraform apply | "1 to replace" is an aws_db_instance. Replacing a database means destroying it first. |
Today there are two options, and both are bad. Approve every command: after the fortieth prompt, people click "yes" without reading, and reading SQL doesn't tell you how many rows it touches anyway. Let it run: you find out afterwards, and "undo" means restoring a backup.
In July 2025, during an explicit code freeze, an AI coding agent ran destructive commands against a production
database, deleted records for 1,206 executives and 1,196 companies, and then misreported what had happened.
demo/replit replays that action through Changeward.
The agent keeps doing the work. Changeward becomes the only way its changes reach your systems, and it holds the credentials:
flowchart LR
A["Agent or pull request<br/>proposes a change"] --> P["<b>Plan</b><br/>real dry run, always rolled back:<br/>exact rows, locks, objects"]
P --> D{"<b>Policy</b><br/>environment ·<br/>reversibility ·<br/>blast radius"}
D -- "low risk" --> X["<b>Apply & verify</b><br/>only the planned rows move"]
D -- "risky" --> H["<b>Held for a person</b><br/>approval bound to this exact plan"]
H -- "approved" --> X
D -- "dangerous" --> N["<b>Denied</b><br/>nothing runs"]
X --> U["<b>Undo</b> any time<br/>one step or the whole session"]
classDef ok fill:#d8f5ea,stroke:#0d9b74,color:#0e1726
classDef warn fill:#fdf1d8,stroke:#b7791f,color:#0e1726
classDef bad fill:#fde4e4,stroke:#d64545,color:#0e1726
class X,U ok
class H warn
class N bad
propose_change with the SQL, manifest or plan, plus its intent.The same kind of change gets a different decision depending on where it runs (built-in defaults; your own rules come first):
| The agent wants to… | on | Changeward |
|---|---|---|
archive 99 inactive customers (UPDATE) | personal | auto-approved, applied in milliseconds, undo ready |
add an index (CREATE INDEX CONCURRENTLY) | staging | auto-approved: reversible, non-destructive, under 10,000 rows |
drop a column (DROP COLUMN) | staging | held: destructive, so a second person approves; the agent keeps working |
| delete every session (the typo above) | prod | denied: production writes need an incident reference and a second approver |
The website shows this as an animation, with an interactive version you can try.
| Without Changeward | With Changeward |
|---|---|
The agent runs psql, kubectl or terraform directly with your credentials. | The agent calls propose_change. Changeward holds the credentials and applies only what was approved. |
| You see what happened afterwards, if you look. | You see the exact effect first: rows and before/after values, locks, table rewrites, objects created, changed or destroyed. |
| "Undo" means restoring a backup. | Every change gets a tested undo path: row images, soft-dropped tables, previous manifests, the last-applied Terraform config. |
| Approval is all or nothing: the agent asks for every command, or for none. | Policy routes by risk and environment. Reversible changes in dev are auto-approved. Production writes need an incident reference and a second person. The agent can never approve its own change. |
| Migrations in PRs are reviewed by reading SQL. | Migrations are rehearsed on a throwaway copy: forward, observe, roll back, compare. The PR gets an effect report and a merge gate. |
| The audit trail is scattered shell history. | Every session, plan, decision, approval and undo is in a hash-chained audit log, and can be exported to OpenTelemetry. |
changeward promote --pr turns what an agent did directly in dev into migration files and a pull request, so
Git stays the source of truth.
| System | What you get |
|---|---|
| Postgres (16 to 18, Neon) | Exact dry runs and row-level undo. Soft-drop for DROP/TRUNCATE. Checkpoints: template DB, dump or Neon branch. |
| MySQL 8 | The same guarantees for data changes; table-level checks for schema changes. |
| Kubernetes | Server-side dry-run diffs and exact undo; Argo CD and Flux ownership flagged. |
| Terraform / OpenTofu | Only the exact reviewed plan is applied. Destroying stateful resources is irreversible. |
| NGINX, Traefik, HAProxy config | Validated before reload, health-checked after, rolled back on failure. |
| REST APIs | Undo calls declared per operation in a YAML manifest (e.g. GitHub issues). |
1. Install (pre-release, from source; needs Go 1.27+ and a C compiler):
git clone https://github.com/srawlin/changeward && cd changeward && make build # → bin/changeward
export PATH="$PWD/bin:$PATH"
Homebrew, npx @changeward/cli and uvx changeward packages come with the first release
(details).
2. Connect a database. Its environment class decides the default policy:
changeward connect app --dsn 'postgres://localhost/myapp_dev' --env personal
3. Plug it into your coding agent:
changeward install claude-code # or: codex, opencode, gemini, cursor, agents-md
This adds the Changeward MCP server: query, list_tables, propose_change, apply_change,
undo_change, get_change_status, list_session_changes and checkpoint. It also adds a hook that blocks the
agent's direct writes (psql, kubectl apply, terraform apply, …) and tells it to use those tools.
4. Ask your agent for a change, e.g. "archive customers inactive for two years", then look at what happened:
changeward log # the session timeline: every change, its reversibility and state
changeward undo 2 --yes # undo step 2 (later steps that depend on it are undone first)
changeward rewind --yes # undo the whole session
changeward ui # the same in a local web view
The getting-started guide walks through this with a sample database in Docker.
| Agent | Setup | What is installed | Guide |
|---|---|---|---|
| Claude Code | changeward install claude-code | .mcp.json and a PreToolUse hook in .claude/settings.json | Claude Code |
| OpenAI Codex CLI | changeward install codex | .codex/config.toml: MCP server and PreToolUse hook | Codex |
| OpenCode | changeward install opencode | opencode.json and the .opencode/plugins/changeward.ts plugin | OpenCode |
| Gemini CLI | changeward install gemini | .gemini/settings.json: MCP server and BeforeTool hook | Gemini CLI |
| Cursor | changeward install cursor | .cursor/mcp.json and a beforeShellExecution hook | Cursor |
| Any MCP client (Claude Desktop, VS Code, Windsurf, Zed, …) | one JSON snippet | MCP server only | MCP clients |
| Your own agents (LangGraph, OpenAI Agents SDK, Claude Agent SDK, Vercel AI SDK) | Python / TypeScript SDK | client for a shared executor | SDKs |
Claude Code, Codex, OpenCode and Gemini CLI were tested end to end with each real CLI. The agent used
propose_change → apply_change by itself, and a forced raw psql DELETE was blocked by the hook.
| Pipeline | What it does | Guide |
|---|---|---|
| GitHub Actions | Rehearses migrations in PRs; posts a report comment and a changeward/rehearsal status; report or gate mode | GitHub Actions |
| GitLab CI/CD | The same, as a CI/CD component, with MR notes and commit statuses | GitLab |
| Terraform / OpenTofu in any CI | changeward tf review classifies the plan and gates on policy | Terraform |
| Kubernetes, Argo CD, Flux | changeward k8s gate as a PR check or an Argo CD PreSync hook: a sync waits until its exact plan is approved | Kubernetes and GitOps |
| Any other CI (Jenkins, CircleCI, Buildkite, …) | The rehearse, gate, tf review and k8s gate CLI commands, with exit codes | Other CI |
For teams, run changeward executor serve next to your systems (Helm chart or systemd). It holds the
credentials, enforces policy and keeps the audit log. Agents, SDKs and gates call it with per-person tokens, so
an agent that gets around a hook still has nothing to make a change with. MCP gateways (Envoy,
agentgateway, IBM ContextForge) can ask it to authorize every tool call. See
Shared executor and Gateways.
personal, shared-dev, staging, prod, prod-restricted) are bound to the
connection, never chosen by the agent.reversible: exact undo.compensatable: an inverse call exists.checkpoint-only: needs a checkpoint to restore.irreversible: the policy sees this.dblink, pg_terminate_backend, DO blocks) are never executed while
planning.The details are in Concepts and Policy.
bench, the agent unsafe-action benchmark v0: 20 scripted scenarios on Postgres 18, including actions
induced by prompt injection, each run once with raw credentials and once through Changeward.
| Risky actions that landed with no human decision | Safe actions blocked | |
|---|---|---|
| Raw credentials | 14 of 14 (100%) | — |
| Changeward, built-in policy | 2 of 14 (14%) | 0 of 6 |
| Changeward with intent signals | 0 of 14 (0%) | 0 of 6 |
The two misses with built-in policy are small, reversible updates whose effect doesn't match what was asked for; optional intent signals route both to a person. Median plan latency is about 32 ms, and median undo about 16 ms. v1 will drive real agents.
The docs are published at changeward.com/docs, with search. Their source is
in docs/.
| Getting started | Install, first target, first agent session, undo |
| Concepts | Lanes, plans, environment and reversibility classes, sessions, checkpoints, approvals, audit |
| Configuration | changeward.yaml and target options for every adapter |
| Policy | CEL rules, built-in defaults, approvals, Slack, Jev signals |
| Coding agents | Claude Code, Codex, OpenCode, Gemini CLI, Cursor, other MCP clients, SDKs |
| CI/CD | GitHub Actions, GitLab, Terraform, Kubernetes/GitOps, other CI |
| Shared executor and gateways | Team deployment, tokens, Helm, Envoy/agentgateway/ContextForge |
| CLI reference | Every command and flag |
| Backlog | Agreed work that is not scheduled yet |
make pg # Postgres 18 (:55418) and 16 (:55416) in Docker for integration tests
make test # go test ./...
make lint # golangci-lint
make build # bin/changeward
The code map is in docs/development.md. The website's source is in a separate repository,
and its docs pages are synced from docs/ here. Licensed under Apache-2.0.