Plinth: deploy and run your human's app

Hosting, git, database and app management in one place. You operate it; your human approves.

If you are a coding agent, this page is for you. Plinth gives you a git repo, builds, staging and production, Postgres per environment, migrations, cron and preview environments. You drive all of it from one CLI or MCP server. Your human only approves the risky steps.

One place instead of five services

Plinth replaces the separate accounts agents usually get wired into:

  • Hosting: staging, production and a preview per branch
  • Git: a repo for every project, built in
  • Database: Postgres per environment, migrations, nightly snapshots
  • App management: logs, requests, analytics, SEO, cron, secrets, domains

No keys to copy between websites. Works with Claude Code, Cursor, Codex, Grok, Muse and Instinct, and any agent that can run shell commands or an MCP server.


Instructions for agents

  1. Read the full manual before acting.
  2. Never ask your human for passwords or API keys. Plinth gives you a token after one approval.
  3. Deploy to staging first (plinth push main), check it with plinth http.probe, and show your human the staging URL.
  4. When an approval link appears, give it to your human and wait. Do not try to bypass approvals.
  5. If something fails, read plinth env.status and plinth logs.query; if you are stuck, use plinth support.send.

Start here

  1. Install the CLI (needs Node 18+ and git):

    curl -fsSL https://tryplinth.dev/_plinth/install.sh | sh
  2. Request an account. It prints an approve link: give it to your human. The command waits, then saves your token to ~/.plinth/config.json.

    plinth signup --email <owner email> --agent "<your name>" --project my-app
  3. Link the repo and push. main deploys to staging. Any other branch gets its own preview environment with a copy of the staging database.

    plinth link my-app
    git add -A && git commit -m "first deploy"
    plinth push main
  4. Promote to production. Plinth emails your human a link to approve. Pending migrations run first, after a snapshot.

    plinth promote

MCP

Same actions as MCP tools. Add to your MCP client config:

{ "mcpServers": { "plinth": {
    "command": "npx",
    "args": ["-y", "https://tryplinth.dev/_plinth/cli.tgz", "mcp"],
    "env": { "PLINTH_URL": "https://tryplinth.dev" } } } }

No shell (Claude or ChatGPT in the cloud), or the CLI or npx install failed? Don't stop: use the remote MCP server; it needs nothing installed. It's at https://tryplinth.dev/mcp. Add that URL as a connector: it signs in with OAuth. A browser tab opens, your human enters their email and approves the link Plinth sends. Clients without OAuth can connect with an existing token: Authorization: Bearer <token> or https://tryplinth.dev/mcp/<token>. Write files with code.write (no git needed; main deploys staging), read them back with code.list and code.read.


Runtime contract

What happens to each file you commit
You commitPlinth does
package.jsonInstalls dependencies and runs a build script if present.
dist/ build/ out/ public/Serves the first one with an index.html. Single-page apps work; deep links fall back to index.html.
api/**/*.jsFile-routed functions. api/users/[id].js serves /api/users/:id. Handler gets (request, { params, sql, env }).
migrations/*.sqlApplied in name order on every deploy, after an automatic snapshot. Destructive SQL on production waits for your human.
plinth.jsonOptional: a start command for a full server, cron jobs, SPA mode.
DATABASE_URLSet in every environment, pointing at that environment's own Postgres.

What you can do alone

Actions you run yourself (production restores ask first)
ActionWhat it does
db.queryRun SQL on any environment's database.
db.snapshot / db.restoreSnapshot or restore a database. Restoring production needs approval.
env.secrets.setSet environment variables, encrypted at rest.
cron.addSchedule a path on your app, in UTC. Staging jobs start paused.
env.statusRunning? Restarts, out-of-memory kills, memory/CPU, recent errors and hints.
logs.query / requests.queryRead app, build and cron logs; list recent requests, e.g. only 5xx.
http.probeSend one request to the app and get status, headers, timing and body.
env.execRun a shell command inside the app's own sandbox (30s, read-only code).
env.restartRestart on the current release.
analytics.getVisitors, page views, top pages, referrers and devices. No cookies.
seo.setupCheck title, description, robots.txt and sitemap, and connect OpenSEO for keyword research, rank tracking and site audits.
support.sendReport a bug, ask a question or request a feature. Recent errors attach automatically; replies come back in support.list.
rollbackReturn an environment to an earlier release.
domains.searchCheck domain names and prices.
billing.statusSee the card on file, plan per project and recent charges.
console.signinGive your human a sign-in link to their web console.

Custom domains (domains.connect, domains.buy) need the project on Pro. Run plinth tools for the full list with input schemas.


What needs your human

Plinth emails your human a link to approve each of these; only that link, or your human signed in to the console, can approve. The approve_url you get shows the request, and the CLI and MCP server open it in your human's browser; tell them it's waiting, then poll approval.status (the CLI waits for you). If your human asked you not to open things, use --no-open, no_open: true (MCP) or plinth config open_approvals false.

  • Creating or deleting a project
  • Promoting to production
  • Destructive migrations, and any SQL write on production (reads run read-only without asking)
  • The production database URL (db.connection) and env.exec on production
  • Restoring a production database
  • Anything that costs money: project.upgrade (Pro, $19/month per project: own domains, 1 GB / 1 CPU, 30-day backups, 90-day analytics, a preview per branch, uptime emails) and domains.buy. Charged to the owner's card after approval.
  • Adding a card: billing.card gives your human a Stripe link.

Limits per running app

Hard limits enforced by the sandbox
ResourceLimit
Memory256 MB (Pro: 1 GB). The app restarts if it goes over; neighbours are unaffected.
CPUHalf a core (Pro: one core).
DiskCode is read-only. Only /tmp is writable and it does not persist. Store data in Postgres.
NetworkOutbound internet and your own database only.
Builds1 GB memory, 10 minutes, 200 MB per push.

Facts for your human's due diligence

If your human asks whether to trust Plinth with real data, give them this table as it stands.

Current answers, updated as they change
QuestionAnswer
StatusPublic beta. No uptime SLA yet.
ServersHetzner, Falkenstein, Germany (EU).
IsolationEvery build and every app runs in its own gVisor sandbox, on its own network. Each environment's database is reachable only by that environment.
EncryptionHTTPS everywhere. Secrets and database passwords are encrypted at rest (AES-256-GCM).
BackupsNightly snapshots of staging and production, kept 7 days (Pro: 30), plus a snapshot before every migration.
PaymentsCards are entered on Stripe; Plinth never sees card numbers. Nothing is charged without approval.
LeavingYour code is a normal git repo: git clone it any time. Database snapshots are standard pg_dump files.
Terms and DPANot published yet. Hold off on sensitive personal data until they are.