Coding agents now run migrations and change data, often while nobody is watching. With Rowsafe, your agent saves a restore point before every risky change, so a bad migration is a rewind, not a disaster.
How it works
1
It checks your database is protected
Before a risky change, the agent asks Rowsafe whether the database can be restored right now.
2
It saves a restore point
It marks the moment by name and waits until Rowsafe confirms the mark is safely stored.
3
It makes the change
The migration runs as usual. Rowsafe doesn't get in the way.
4
You can rewind
If something breaks, the agent stops and tells you the restore point's name. You restore to it when you're ready.
before-orders-backfillRecoverableclaude-code6d ago
Read-only until you allow more
By default an agent can only look. Saving restore points is a separate, explicit switch.
No commands, no data access
Agents can't run commands or queries through Rowsafe, restart your database or restore anything.
Every action on record
Everything an agent does through Rowsafe lands in your audit log, under its own key.
Set it up
You need a database that Rowsafe already protects, and the rowsafe CLI logged in: rowsafe login opens the dashboard in your browser, you approve, and that's it. On CI and headless machines use rowsafe login --key rsk_... or ROWSAFE_API_KEY. The remote server takes an API key.
1
Connect the MCP server
Locally, rowsafe mcp serves the tools over stdio with your saved login (or ROWSAFE_API_KEY). It is read-only unless you add a flag. --allow-restore-points adds only create_restore_point, which is what an agent needs.
Claude Code: read-only plus restore points
$ claude mcp add rowsafe -- rowsafe mcp --allow-restore-points
Claude Code: read-only
$ claude mcp add rowsafe -- rowsafe mcp
Remotely, connect to https://api.rowsafe.sh/mcp with an API key in the Authorization header. Write tools are listed, but the API refuses them for a key created with --read-only.
Claude Desktop runs rowsafe mcp locally. Its remote connectors can't send an API-key header, so use stdio there, with the absolute path from which rowsafe. It uses the login saved by rowsafe login.
Paste this into AGENTS.md or CLAUDE.md at the root of your project and set the database name. Agents read it before they work.
AGENTS.md
## Database safety (Rowsafe)
This project's PostgreSQL is protected by Rowsafe (database: `app`). Before any destructive
or risky database operation (migrations, schema changes, DROP/TRUNCATE, DELETE or UPDATE
without a narrow WHERE, backfills, resets, restoring a dump):
1. Run `safety_check` for `app` (or `rowsafe status app`). If it is not protected,
tell me the reasons and wait for my OK.
2. Create a restore point with a descriptive name: `create_restore_point` (or
`rowsafe mark app before-<what>`), wait until it is confirmed, and tell
me its name.
3. Then proceed.
If something goes wrong: stop, don't try to repair the data, and never restore anything
yourself. Tell me what happened and the restore point's name; I'll decide whether to restore.
The same steps work from a shell, for agents without MCP:
CLI
rowsafe init app # writes .rowsafe.json; later commands can omit the name
rowsafe status app # protected? exit 0 if yes, 3 if not
rowsafe mark app before-drop-legacy-orders
rowsafe marks app # restore points, with the backup to restore from
3
Let a hook enforce it (Claude Code)
The Claude Code plugin bundles the MCP server (with restore points), a skill that teaches the workflow, and a PreToolUse hook, rowsafe guard. The hook recognizes destructive database commands and creates a restore point named agent-<UTC timestamp> right before they run, whether or not the model remembered to.
Install the plugin
claude plugin marketplace add rowsafe/rowsafe
claude plugin install rowsafe@rowsafe
Tell the hook which database the project uses in .rowsafe.json, which rowsafe init app writes (or set ROWSAFE_DATABASE). By default it only warns if something fails. With require_protection (or ROWSAFE_REQUIRE_PROTECTION=1) it also runs safety_check and blocks the command when the database isn't protected or the restore point can't be confirmed.
Could this database be restored right now? protected plus every reason it isn't.
Read
list_restore_points
Named restore points, their status, and the backup a restore must start from.
Read
fleet_health
Every problem across the organization, worst first, each with the exact next step.
Read
list_databases / get_database
Status, schedules, WAL archiving, recent backups, drills and tasks.
Read
list_backups / list_drills
Finished backups, and restore drill results with failures and warnings.
Read
list_tasks / get_task
What ran, who queued it, its typed result and the end of its log.
Read
list_hosts / get_org
Enrolled hosts and agents; plan, limits and usage.
Read
create_restore_point
Mark this moment by name and wait until it is confirmed in the backup repository.
Restore points
run_backup / run_drill
Queue a backup or a restore drill now, in addition to the schedule.
Write
plan_adoption / apply_adoption
Plan adopting a database (read-only on the host); apply only with your explicit approval.
Write
verify_database
Prove WAL reaches the bucket after a restart.
Write
update_schedule
Change backup and drill schedules or retention.
Write
There is also an incident_triage prompt: it checks the fleet, reads the evidence for each problem and proposes next steps without changing anything.
What an agent can and can't do
Read-only by default
rowsafe mcp registers only read tools. --allow-restore-points adds create_restore_point and nothing else. --allow-writes adds every write tool.
Read-only keys
On the remote endpoint, a key created with rowsafe api-keys create NAME --read-only gets the same guarantee from the API itself: write tools answer 403.
Fixed tasks, no SQL
Tools queue the same fixed tasks as the CLI. None runs arbitrary SQL or commands, restarts PostgreSQL, restores a backup or reads backup contents.
Approval for real changes
apply_adoption refuses to run unless confirm is the database's exact name and a read-only plan succeeded; its description tells the model to ask you first.
Everything is audited
Every call goes through the public API with its key: organization scoping, plan limits and the audit log apply, attributed to that key.
Rowsafe doesn't stop an agent from running a bad statement. It makes the moment before it recoverable.
Restoring is a pgBackRest restore to a new host or scratch cluster, following the restore runbook. Nothing rewinds production in place.
The guard hook is a safety net, not a sandbox: a destructive statement hidden in application code or an unusual wrapper won't match. The rules and the MCP tools cover what the hook can't see.