Letting a coding agent run production, safely
October 15, 2026
Coding agents got good at writing apps quickly. Running them is a different job: a git host, a build service, a database, staging, backups, a domain, logs. Every one of those is another account the human has to create and wire up, and another set of credentials handed to the agent with no limits on what it can do.
We built Plinth around one idea: the agent does all of the work, and the owner approves only the steps that can hurt. Here is what that takes in practice.
One interface the agent already understands
Everything is one CLI, or one MCP server, with about 70 actions: project.create, deploy, promote, db.query, logs.query, http.probe, cron.add, domains.buy. Every response is JSON with an error code and a message that says what to do next. Agents read error messages much more carefully than people do, so most of our "documentation" lives in those messages.
Agents without a shell (Claude or ChatGPT connectors) use the remote MCP server at https://tryplinth.dev/mcp. They can sign up and write code over HTTP with no git.
What needs the owner, and what doesn't
| Runs without asking | Waits for the owner |
|---|---|
| Pushing to staging and previews | Creating or deleting a project |
| Reading logs, requests, metrics | Promoting staging to production |
| Reading production data (read-only transaction) | Any write to production data |
| Restarting, rolling back staging | Destructive migrations (DROP, TRUNCATE, unscoped DELETE) |
| Setting staging secrets | Production shell access or its database URL |
| Anything that costs money |
The owner can move items from the right column to the left once they trust their agent. Most people start by letting the agent create projects freely and keep production gated.
The approval link never goes to the agent
Our first version gave the agent an approve URL to show its human. That means an agent that misreads its instructions, or follows a prompt injection, can approve itself. Now the link that decides is emailed only to the owner's address. The agent gets a URL that shows the request, but it can't approve with it. A promote approval covers the exact release shown on the card. If staging changes before the owner clicks, the approval fails and the agent has to ask again.
Production reads are free; writes are not
Debugging usually starts with reading production data. Asking for approval on every SELECT would train owners to click "Approve" without reading. So reads run without asking, in a read-only transaction that the database itself enforces. That doesn't depend on our SQL parser getting every edge case right. Writes, and anything our destructive-SQL detector flags, wait for the owner. A snapshot is taken before every migration either way.
Every app in its own sandbox
Each build and each running app gets its own gVisor sandbox: its own kernel, read-only code, writable /tmp only, its own network, and a memory and CPU limit. Each environment has its own Postgres database and role. Staging can't reach production's data, and one customer's app can't reach another's.
Staging is for the human too
Many of our users don't write code. When they open their staging site, a bar says "Test version. Visitors don't see this," with a button that copies a ready-made prompt for their agent: "this looks good, publish it." The agent runs plinth promote, the owner gets the email, and the change goes live. Staging and previews also tell search engines not to index them, so they never compete with the real site.
Leaving is easy
The code is a normal git repo and backups are standard pg_dump files. If Plinth isn't right for you, take both and go.
Try it
Paste this into Claude Code, Codex or Cursor:
Read https://tryplinth.dev/_plinth/agent.md and deploy this app on Plinth. My email is you@example.com.
Plinth is in public beta, hosted in Falkenstein, Germany. We'd love to hear what breaks: the agent can file it with plinth support.send.