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 askingWaits for the owner
Pushing to staging and previewsCreating or deleting a project
Reading logs, requests, metricsPromoting staging to production
Reading production data (read-only transaction)Any write to production data
Restarting, rolling back stagingDestructive migrations (DROP, TRUNCATE, unscoped DELETE)
Setting staging secretsProduction 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.