Agents, CI, and scripts
Use Deplane from AI agents, CI pipelines, and scripts with a token, JSON output, and stable exit codes.
The CLI works the same for people and programs. Every command supports --json and --yes, never prompts without a terminal, and exits with a documented code.
Get a token
Create a CI token from your own machine:
deplane tokens create github-actions
Creating a token needs a fresh confirmation with your passkey from the last 5 minutes. In a terminal, the CLI opens your browser, you tap your passkey, and the command continues. The token is printed once. Store it in your CI's secret store.
Then set it in the environment where the CLI runs:
export DEPLANE_TOKEN=dpl_...
deplane deploy --json --yes
About CI tokens:
- A CI token belongs to your organization and acts as you.
- It lasts 90 days by default. Choose 1 to 365 days with
--expires-in-days. - It cannot create tokens, list or revoke other tokens, or run admin commands. It can revoke itself.
- Revoke it any time with
deplane tokens revoke ID. It stops working at once. - Tokens start with
dpl_. If one leaks into a log,deplaneoutput and--debughide it asdpl_[REDACTED].
GitHub Actions example
The deploy step in .github/workflows/deploy.yml:
- run: npx deplane deploy --json --yes
env:
DEPLANE_TOKEN: ${{ secrets.DEPLANE_TOKEN }}
Commit deplane.toml so the CI run knows which app to deploy, or pass --app NAME.
Rules for programs
- Use
--json. Each command prints exactly one JSON document on stdout. Progress messages and build logs go to stderr.deplane logs --jsonprints one JSON object per line. - Use
--yes. Commands that destroy or roll back ask for confirmation. Without a terminal, the CLI never asks. Instead the command fails with confirmation_required, and the fix names the flag to pass:--yes. - Check the exit code. It tells you what kind of failure happened, without parsing text.
- Read
fix. Every error has a fix: a sentence that says what to do next, usually with the exact command.
Exit codes
| Code | Meaning | What an agent should do |
|---|---|---|
| 0 | Success. | Continue. |
| 1 | User error. | Read fix, change the command or the project, and try again. |
| 2 | Authentication error. | Check DEPLANE_TOKEN, or ask a person to log in or confirm. |
| 3 | The build failed. | Read the build log on stderr and fix, change the code, and deploy again. |
| 4 | The deploy failed. | Run deplane logs --json and deplane status --json, fix the app, and deploy again. The previous release keeps serving. |
| 5 | Platform error. | Wait and retry. If it persists, report it. |
| 6 | Quota exceeded. | A plan limit was reached (codes starting with limit_). Free resources or ask a person to raise the limit. |
Error shape
With --json, a failure prints:
{
"error": {
"code": "no_app",
"message": "This folder has no deplane.toml, so there is no app to deploy.",
"fix": "Run `deplane launch` to create the app, or pass --app NAME.",
"exit_code": 1
}
}
code is stable. Look it up in Troubleshooting and error codes: each code has its own section at https://deplane.cloud/docs/errors#CODE.
Actions that need a fresh passkey
Some actions need the person to confirm with their passkey in the last 5 minutes: creating a token, inviting or removing a team member, destroying an app, deleting, restoring or switching a database, and every admin command. In a terminal, the CLI opens the browser, waits for the tap, and retries on its own. Destroying an app and deleting, restoring or switching a database each use up their confirmation, so every one of them needs its own tap.
Without a terminal, the CLI cannot do that. It fails with exit code 2 and step_up_required:
{
"error": {
"code": "step_up_required",
"message": "This command needs a fresh confirmation with your passkey, and no terminal is attached.",
"fix": "Run it in a terminal to confirm in your browser. For 5 minutes after that, most such commands also work from scripts; deleting, restoring and switching need a confirmation each time.",
"exit_code": 2
}
}
An agent should hand this step to a person. --yes does not replace it, and CI tokens are refused these actions with ci_token_not_allowed. Deploys, scaling, secrets, logs, and rollbacks never need it.
A typical agent session
deplane doctor --json
deplane launch --json --yes
deplane status --json
deplane logs --json --tail 200
deplane secrets set --json DATABASE_URL=postgres://...
deplane rollback --json --yes
Each command prints one JSON document and exits with a code from the table above.
After a deploy
A deploy that succeeded can still be rolled back by Deplane in its first 10 minutes live, if the 5xx errors the app returns spike (automatic rollback). To check, run deplane releases --json: a release Deplane made this way has "automatic_rollback": true and a description that starts with Automatic rollback to vN. Read the logs of the release that spiked before deploying again. To turn it off for an app, run deplane config --auto-rollback off.
Restore a database
Restores never change the original database. Restoring and switching need a fresh passkey, so a person runs them from a terminal (or the dashboard):
deplane db backups main --json
deplane db restore main --at -10m --json
deplane db switch main-restored-1442 --from main --json
deplane db restore waits until the new database is ready (up to 15 minutes); pass --no-wait to return at once. See Databases.
AI tools
Claude, ChatGPT, Cursor and other MCP clients can use Deplane without the CLI: see AI tools (MCP).
Docs for agents
- https://deplane.cloud/llms.txt lists every docs page with a one-line description and a link to its Markdown.
- Every docs page is also available as Markdown: add
.mdto its URL. For example, https://deplane.cloud/docs/limits.md. - The API is described by OpenAPI at https://api.deplane.cloud/v1/openapi.yaml. API errors have the same
code,message, andfix, plus adocslink and arequest_id.
This page is also available as Markdown. AI agents can start at /llms.txt.