CLI reference
Every deplane command with its flags, a human example, and its --json output.
Run deplane help for a short list. Commands that act on an app use the app in ./deplane.toml, or the one you pass with --app NAME.
Global flags
These flags work with every command, anywhere on the command line.
| Flag | What it does |
|---|---|
--json | Print exactly one JSON document on stdout. Streams print one JSON object per line. Progress messages still go to stderr. |
--yes | Answer yes to every confirmation. |
--debug | Log each HTTP request and response to stderr. Tokens, cookies, Authorization headers, and secret values are replaced with [REDACTED]. |
--app NAME | The app to act on. Default: app in ./deplane.toml. |
--help | Show the command list. |
Without a terminal, the CLI never asks a question. A command that needs confirmation fails with confirmation_required and tells you to pass --yes.
Flags that take a value accept --flag VALUE or --flag=VALUE.
Environment variables
| Variable | What it does |
|---|---|
DEPLANE_TOKEN | Use this token instead of the stored login. |
DEPLANE_API_URL | The API to use. Default https://api.deplane.cloud. |
Exit codes
The exit codes are stable. Scripts and agents can rely on them.
| Code | Meaning |
|---|---|
| 0 | Success. |
| 1 | User error: a bad flag, a bad value, a missing app, a cancelled confirmation. |
| 2 | Authentication error: not logged in, login expired, or a fresh passkey confirmation is needed. |
| 3 | The build failed. |
| 4 | The deploy failed: the new release did not become healthy. |
| 5 | Platform error: the API could not be reached, or something failed on our side. |
| 6 | Quota exceeded: every error code that starts with limit_ exits with 6. |
Errors
Every error says what happened and how to fix it. Without --json it goes to stderr:
$ deplane scale 9
Error: This needs 9 instances in total and your plan allows 3.
Fix: Use fewer instances, scale down another app, or email support@deplane.cloud to raise the limit.
With --json the error is the one JSON document on stdout:
{
"error": {
"code": "limit_instances",
"message": "This needs 9 instances in total and your plan allows 3.",
"fix": "Use fewer instances, scale down another app, or email support@deplane.cloud to raise the limit.",
"exit_code": 6
}
}
Every code is listed in Troubleshooting and error codes.
Account
deplane login
Log in through your browser with your passkey. The CLI shows a code, opens https://login.deplane.cloud/device, and waits until you approve. The token is stored in your OS keychain, or in a file only you can read if there is no keychain. It lasts 30 days. See Install for the full flow.
No flags besides the global ones. It refuses to run while DEPLANE_TOKEN is set.
$ deplane login
To log in, open https://login.deplane.cloud/device and type this code:
WDJB-MJHT
Only approve it if you just ran this command yourself. The code expires in 10 minutes.
Logged in as you@example.com (organization you-example).
{
"email": "you@example.com",
"logged_in": true,
"org": "you-example",
"stored_in": "keychain"
}
stored_in is keychain or file.
deplane logout
Revoke this computer's token and remove it.
$ deplane logout
Logged out. The token was revoked and removed from this computer.
{
"logged_out": true,
"was_logged_in": true
}
deplane whoami
Show who you are logged in as, your organization, and its plan limits.
$ deplane whoami
Logged in as you@example.com
Organization: You (you-example)
{
"entitlements": {
"memory_mb": 1536,
"apps": 3,
"instances": 3,
"sizes": ["small", "medium", "large"],
"build_minutes_month": 300,
"concurrent_builds": 1,
"log_retention_days": 7,
"backup_retention_days": 7,
"disk_gb": 10,
"log_streams": 3,
"assistant_enabled": true,
"assistant_requests_month": 300
},
"org": {
"id": "org_2b7k9m4x1q8w5e3r6t0y",
"name": "You",
"plan_id": "pln_beta",
"slug": "you-example"
},
"user": {
"email": "you@example.com",
"id": "usr_8c3v6b1n9m4k2j7h5g0f",
"is_admin": false
}
}
deplane version
Print the CLI version.
$ deplane version
deplane 0.1.0
{
"version": "0.1.0"
}
deplane doctor
Check that the API answers, that you are logged in, whether this folder is a project Deplane can build, and whether deplane.toml is valid. Each failed check has a fix. The exit code is the code of the first failed check, or 0.
$ deplane doctor
ok api The Deplane API at https://api.deplane.cloud answers.
FAIL login You are not logged in, or the login expired.
Fix: Run `deplane login`, or set DEPLANE_TOKEN.
ok project Detected Flask 3, Python 3.12, port 8000.
ok config deplane.toml is valid (app my-api).
{
"ok": false,
"checks": [
{"name": "api", "ok": true, "detail": "The Deplane API at https://api.deplane.cloud answers."},
{"name": "login", "ok": false, "detail": "You are not logged in, or the login expired.", "fix": "Run `deplane login`, or set DEPLANE_TOKEN."},
{"name": "project", "ok": true, "detail": "Detected Flask 3, Python 3.12, port 8000."},
{"name": "config", "ok": true, "detail": "deplane.toml is valid (app my-api)."}
]
}
Tokens
deplane tokens list
List your API tokens. kind is cli for logins and ci for tokens made with tokens create.
$ deplane tokens list
ID NAME KIND EXPIRES LAST USED
tok_5h2j8k1l4z7x9c3v6b0n macbook cli 2026-11-12 2026-10-13
tok_1q9w3e7r5t2y8u4i6o0p github-actions ci 2027-01-11 never
{
"tokens": [
{
"id": "tok_1q9w3e7r5t2y8u4i6o0p",
"name": "github-actions",
"kind": "ci",
"expires_at": "2027-01-11T09:00:00Z",
"last_used_at": null,
"created_at": "2026-10-13T09:00:00Z"
}
]
}
deplane tokens create
Create a CI token for CI, agents, and scripts: deplane tokens create NAME. The token is shown once. Store it as DEPLANE_TOKEN in your CI secrets.
Creating a token needs a fresh confirmation with your passkey from the last 5 minutes. In a terminal, the CLI opens your browser for it and then continues. CI tokens cannot create tokens.
| Flag | What it does |
|---|---|
--name NAME | The token's name, instead of the positional argument. |
--expires-in-days N | Lifetime from 1 to 365 days. Default 90. |
$ deplane tokens create github-actions --expires-in-days 90
Token "github-actions" (tok_1q9w3e7r5t2y8u4i6o0p) created; it expires on 2027-01-11. It is shown only once: store it in your CI secrets as DEPLANE_TOKEN.
dpl_4Fh7Kq2Lm9Np3Rs6Tv8Wx1Yz5Ab0Cd
The message goes to stderr and only the token goes to stdout, so deplane tokens create ci > token.txt saves just the token.
{
"token": "dpl_4Fh7Kq2Lm9Np3Rs6Tv8Wx1Yz5Ab0Cd",
"id": "tok_1q9w3e7r5t2y8u4i6o0p",
"name": "github-actions",
"kind": "ci",
"expires_at": "2027-01-11T09:00:00Z"
}
deplane tokens revoke
Revoke a token at once: deplane tokens revoke ID. Asks for confirmation; pass --yes to skip it.
$ deplane tokens revoke tok_1q9w3e7r5t2y8u4i6o0p --yes
Revoked tok_1q9w3e7r5t2y8u4i6o0p.
{
"revoked": "tok_1q9w3e7r5t2y8u4i6o0p"
}
Apps and deploys
deplane launch
Detect how to build this folder, create the app, write deplane.toml, build, deploy, and print the URL. See the Quickstart for what it detects.
| Flag | What it does |
|---|---|
--name NAME | The new app's name. Default: the folder name, with a random suffix if that name is taken. |
--app NAME | Deploy this folder to an app you already have (the same as deplane deploy --app NAME). |
deplane launch --template NAME [--name APP] deploys a template instead of the folder: Deplane creates the app (and a database and disk if the template needs them), sets its secrets, builds it from Deplane's own copy of the template and rolls it out, while the command shows each step. It ends with the app's URL and what to do next, for example "Open the URL and create the first admin account". If a step fails, everything made so far is kept and the command exits with code 4 and tells you how to retry or delete it. --no-wait returns at once. See Templates.
Run again in the same folder, launch deploys that folder's app again. It never deploys a folder over a different existing app: --name with the name of an app you already have stops with an error, and a folder whose name matches an existing app gets a new app with a suffix.
$ deplane launch
Detected Next.js 15, Node 22, port 3000
Created app my-shop.
Wrote deplane.toml.
Uploading 214 files (1.3 MB)...
Build bld_4m8q2k7x9c1v5b3n6z0a queued.
Building...
...
Built 4f1c2a9e8b7d. Rolling out release v1...
Running: 1 of 1 instances ready.
Deployed my-shop v1: https://my-shop.deplane.dev
With --json, progress and the build log still go to stderr, and stdout gets one document:
{
"app": "my-shop",
"build": "bld_4m8q2k7x9c1v5b3n6z0a",
"created": true,
"image_digest": "sha256:4f1c2a9e8b7d...",
"release": 1,
"status": "running",
"url": "https://my-shop.deplane.dev"
}
A failed build exits with 3. A release that does not become healthy exits with 4.
deplane deploy
Build and deploy this folder's app again. It applies deplane.toml first. It does not create apps: without a deplane.toml and without --app, it fails with no_app.
| Flag | What it does |
|---|---|
--app NAME | Deploy this folder to this app. |
$ deplane deploy
Detected Next.js 15, Node 22, port 3000
Uploading 214 files (1.3 MB)...
Build bld_9t2w6r1y8u3i5o7p4a0s queued.
Building...
...
Built 0b9e7d61a2c3. Rolling out release v2...
Running: 1 of 1 instances ready.
Deployed my-shop v2: https://my-shop.deplane.dev
{
"app": "my-shop",
"build": "bld_9t2w6r1y8u3i5o7p4a0s",
"created": false,
"image_digest": "sha256:0b9e7d61a2c3...",
"release": 2,
"status": "running",
"url": "https://my-shop.deplane.dev"
}
deplane redeploy
Build the app's last source again (an upload or a GitHub commit) and release it, for example after changing a build variable with deplane secrets set --build. It counts toward the 10 deploys per hour.
$ deplane redeploy
Rebuilding shop from its last source. Build bld_… queued.
Deployed shop v8: https://shop.deplane.dev
deplane apps
List your organization's apps. An autoscaled app shows its range in INSTANCES (for example 1-5), and an app that is asleep shows sleeping in STATUS.
$ deplane apps
NAME STATUS RELEASE INSTANCES SIZE URL
my-shop active v2 1 small https://my-shop.deplane.dev
my-api active v5 2 small https://my-api.deplane.dev
{
"apps": [
{
"id": "app_7k2m9x4q1w8e5r3t6y0u",
"name": "my-shop",
"region": "fra",
"status": "active",
"url": "https://my-shop.deplane.dev",
"current_release": 2,
"instances": 1,
"size": "small",
"port": 3000,
"health_check": {"type": "tcp"},
"created_at": "2026-10-13T09:12:00Z"
}
]
}
status is active or suspended. health_check is {"type": "tcp"} or {"type": "http", "path": "/healthz"}.
deplane apps destroy
Destroy any app by name: deplane apps destroy NAME. Its instances, releases, and secrets are deleted, and its disk if it has one (the question says so), and the name becomes available to others. Asks for confirmation; pass --yes to skip it. It also needs a confirmation in your browser: the CLI prints a link and a code (and opens the link), you approve with your passkey, and the command continues. --yes does not skip this, and CI tokens cannot do it at all.
$ deplane apps destroy my-old-app --yes
Destroyed my-old-app.
{
"destroyed": "my-old-app"
}
deplane destroy
Destroy this folder's app, or the one named by --app. Same as deplane apps destroy, including the browser confirmation.
$ deplane destroy --app my-shop --yes
Destroyed my-shop.
{
"destroyed": "my-shop"
}
deplane status
Show the app's URL, release, instances, health, the last build, and the last error with its fix.
$ deplane status
App: my-shop (active)
URL: https://my-shop.deplane.dev
Release: v3
Instances: 0 of 1 ready, size small
State: Failed
Problem: HealthCheckFailed: The app started but did not pass its health check on port 3000. Make sure it listens on $PORT.
Fix: Make the app listen on 0.0.0.0 at the port in $PORT, and make health_check (if set) answer 200. Run `deplane logs` to see why it failed.
Last build: bld_9t2w6r1y8u3i5o7p4a0s, succeeded
State is Pending (no release yet), Deploying, Running, or Failed.
{
"app": "my-shop",
"url": "https://my-shop.deplane.dev",
"status": "active",
"release": 2,
"phase": "Running",
"reason": "",
"message": "1 of 1 instances ready.",
"fix": "",
"instances": 1,
"ready_instances": 1,
"size": "small",
"last_build": {
"id": "bld_9t2w6r1y8u3i5o7p4a0s",
"status": "succeeded",
"builder": "railpack",
"position": 0,
"image_digest": "sha256:0b9e7d61a2c3...",
"release": 2,
"created_at": "2026-10-13T09:40:00Z",
"finished_at": "2026-10-13T09:41:10Z",
"seconds": 70,
"failure": null
}
}
reason is empty, or one of Unschedulable, ImagePullFailed, HealthCheckFailed, Crashing, and Timeout. last_build is null before the first build. A failed build has failure set to {"code", "message", "fix"}.
deplane scale
Change the number of instances, the size, autoscaling, or when the app sleeps: deplane scale [N] [--size small|medium|large] [--max M] [--sleep 5m|15m|60m|off]. deplane scale 0 stops the app without deleting it. The change starts at once; it does not create a release.
| Flag | What it does |
|---|---|
--size SIZE | small, medium, or large. See Limits. |
--max M | Autoscale between N and M instances. --max 0 turns autoscaling off. |
--sleep TIME | Put the app to sleep after 5m, 15m, or 60m without requests; the next request wakes it. off turns sleeping off. |
deplane status shows the autoscale range, and Sleeping since HH:MM UTC while the app sleeps. The JSON for scale, apps, and status includes max_instances (null when off), sleep_after_minutes, sleep_state, and slept_at.
$ deplane scale 2 --size medium
my-shop now runs 2 medium instance(s).
Autoscale between 1 and 5 instances and sleep after 15 idle minutes (see Scaling):
$ deplane scale 1 --max 5 --sleep 15m
The JSON is the app, as in deplane apps:
{
"id": "app_7k2m9x4q1w8e5r3t6y0u",
"name": "my-shop",
"region": "fra",
"status": "active",
"url": "https://my-shop.deplane.dev",
"current_release": 2,
"instances": 2,
"size": "medium",
"port": 3000,
"health_check": {"type": "tcp"},
"created_at": "2026-10-13T09:12:00Z"
}
deplane releases
List the app's releases, newest first (up to 50). A release is a build plus its settings and secret names. STATUS is pending, active, superseded, or failed.
$ deplane releases
VERSION STATUS IMAGE CREATED DESCRIPTION
v3 failed 7a1b2c3d4e5f 2026-10-13 10:02 Deploy (HealthCheckFailed)
v2 active 0b9e7d61a2c3 2026-10-13 09:41 Deploy
v1 superseded 4f1c2a9e8b7d 2026-10-13 09:12 Deploy
{
"releases": [
{
"version": 2,
"status": "active",
"image_digest": "sha256:0b9e7d61a2c3...",
"description": "Deploy",
"failure_reason": "",
"created_at": "2026-10-13T09:41:00Z"
}
]
}
Descriptions are Deploy, Set secrets NAMES, Unset secrets NAMES, Rollback to vN, or Automatic rollback to vN: X% of requests failed after vM (see Automatic rollback). In --json, automatic_rollback is true for a release Deplane made by rolling back automatically, and released_at is when a release went live.
deplane rollback
Roll back to the previous release that ran successfully, or to a version: deplane rollback [VERSION]. Both 3 and v3 work. A rollback creates a new release from the earlier release's build and settings. Asks for confirmation; pass --yes to skip it.
$ deplane rollback 1 --yes
Created release v4 (Rollback to v1). Run `deplane status` to follow the rollout.
{
"version": 4,
"status": "pending",
"image_digest": "sha256:4f1c2a9e8b7d...",
"description": "Rollback to v1",
"failure_reason": "",
"created_at": "2026-10-13T10:05:00Z"
}
Automatic rollback
When a new release starts failing right after it goes live, Deplane rolls it back for you. For the first 10 minutes after a release goes live, Deplane checks the errors your app returns every minute and rolls back to the previous good release when all of these hold:
- at least 50 requests and at least 10 errors from the app over at least two minutes of its own traffic (the minute it went live and the next one are left out: they can still hold the previous release's requests);
- more of them failed than your team's error-rate threshold (5% unless you changed it on Alerts);
- the rate is at least 3 times the previous release's over its last 30 minutes (or the previous release had no errors);
- the errors reached visitors on at least 3 different networks (a /24 for IPv4, a /48 for IPv6).
Only 5xx responses your app returned count. 502, 503 and 504 do not: Deplane's router sends those itself when no instance answers in time, which a flood of requests or a rollout can cause. Requiring several networks means one visitor who keeps opening a page that fails cannot roll your app back on their own. To count networks, Deplane keeps a keyed hash of each network that got an error, never the address, for one day. The errors alert still counts every 5xx.
The rollback is a new release, exactly like deplane rollback, described as Automatic rollback to v1: 42% of requests failed after v2. Your team's alert channels get "Rolled back my-shop to v1", and it shows on Alerts. If the GitHub commit's status said success, it becomes a failure. Deplane never rolls back the same release twice, and never rolls back an automatic rollback; deplane rollback without a version skips a release that was rolled back automatically. If the rollback's own release does not start, the release before it keeps serving and your team gets "Automatic rollback of my-shop failed: still on v2" with the reason. It is on for every app; turn it off with deplane config --auto-rollback off or in the app's Settings tab.
deplane config
Show the app's port, health check, and whether automatic rollback is on. With --auto-rollback on|off, turn automatic rollback on or off; this applies right away. The port and health check come from deplane.toml and apply from the next deploy.
$ deplane config
Port 8080
Health check HTTP /healthz
Auto rollback on
$ deplane config --auto-rollback off
Automatic rollback is off for my-shop. Roll back by hand with `deplane rollback`.
With --json, both print the app, including "auto_rollback": false.
deplane open
Open the app's URL in your browser and print it. Without a terminal it only prints it.
$ deplane open
https://my-shop.deplane.dev
{
"url": "https://my-shop.deplane.dev"
}
deplane logs
Show the app's recent log lines, or follow them live.
| Flag | What it does |
|---|---|
-f, --follow | Keep streaming new lines until you press Ctrl-C. |
--tail N | Lines per instance, from 0 to 1000. Default 100. |
$ deplane logs --tail 2
x7k2p | ready - started server on 0.0.0.0:3000
x7k2p | GET / 200 in 12ms
Each line starts with the short name of the instance that wrote it. With --json, each line is its own JSON object:
{"instance": "x7k2p", "line": "ready - started server on 0.0.0.0:3000"}
{"instance": "x7k2p", "line": "GET / 200 in 12ms"}
Your organization can follow at most 3 live streams at once; see limit_log_streams.
Secrets
See Secrets for how secrets work.
deplane secrets set
Set one or more secrets: deplane secrets set NAME=VALUE [NAME=VALUE...]. Changing a runtime secret on an app that has a release creates a new release.
| Flag | What it does |
|---|---|
--build | Set build secrets, used only while building. |
$ deplane secrets set DATABASE_URL=postgres://u:p@db.example.com/shop API_KEY=sk_live_123
Set runtime secret(s) API_KEY, DATABASE_URL.
Created release v5 with the new secrets.
{
"names": ["API_KEY", "DATABASE_URL"],
"scope": "runtime",
"release": 5
}
release is null when no release was created: for build secrets, and for apps that have not been deployed yet.
deplane secrets unset
Remove secrets: deplane secrets unset NAME [NAME...]. Pass --build to remove build secrets.
$ deplane secrets unset API_KEY
Removed runtime secret(s) API_KEY.
Created release v6 without them.
{
"names": ["API_KEY"],
"scope": "runtime",
"release": 6
}
deplane secrets list
List secret names and when they changed. Values are never shown.
$ deplane secrets list
NAME SCOPE UPDATED
NPM_TOKEN build 2026-10-13 09:30
DATABASE_URL runtime 2026-10-13 09:50
{
"secrets": [
{"name": "DATABASE_URL", "scope": "runtime", "updated_at": "2026-10-13T09:50:00Z"},
{"name": "NPM_TOKEN", "scope": "build", "updated_at": "2026-10-13T09:30:00Z"}
]
}
GitHub
Connect a repository in the dashboard (an app's Settings, or Import from GitHub on New app). See GitHub.
deplane github
Show the app's connected repository, its branch and root folder, whether pull requests get previews (and their own databases), the open previews with their databases, and the last problem deploying from GitHub, if any.
$ deplane github
Repository: acme/shop
Branch: main (every push deploys)
Root: /
Previews: on, for pull requests from the repository
#12 Faster checkout https://shop-pr-12.deplane.dev Running
deplane github deploy
Deploy the latest commit of the connected branch now, without a push, and follow it like deplane deploy.
Assistant
deplane ask
Ask the assistant a question about your apps. In a folder with a deplane.toml, or with --app, that app is the context. It reads the same data as the dashboard (never variable values) and suggests commands; it never runs them.
$ deplane ask "why did my last deploy fail?"
The build failed in `npm install`: package.json asks for react@19.4.0, which does not exist yet.
Change it to ^19.2.0 and deploy again.
Alerts
Rules and channels (Slack, Discord, webhooks; email is not delivered yet) are set in the dashboard. See Alerts.
deplane alerts
List your team's firing alerts, then recent ones.
$ deplane alerts
1 firing:
STATE ALERT STARTED
FIRING shop is down: 0 of 2 instances ready: CrashLoopBackOff Oct 14 12:03
resolved shop is slow: p95 response time above 2000 ms for 5 minutes Oct 13 18:40
Usage
deplane usage
Show what your team used: requests, bandwidth, CPU, memory, build minutes, database disk and app disks, then each app, database and disk. Pick the period with --range: 24h, 7d, 30d, month (the default, since the 1st) or prev_month. Dates are in UTC. Build minutes are always this month's, counted against your plan. Deleted apps still show what they used, marked with *. Databases and disks have no requests, bandwidth or builds, so those columns show –; disks have no CPU or memory either. DISK GB-H is the storage a database or disk held. Add --json for the full data, including per-day or per-hour series.
$ deplane usage
Usage this month (Oct 1 – Oct 18)
Requests 12,345
Bandwidth out 1.2 GB
CPU 3.4 hours
Memory 120.5 GB-hours reserved (31.0 used)
Build minutes 12.5 of 300
Database disk 4,200 GB-hours
App disks 120 GB-hours
APP REQUESTS BANDWIDTH CPU H MEMORY GB-H BUILD MIN DISK GB-H
shop 12,000 1.1 GB 3.0 100.0 10.0 –
old-api* 345 100.0 MB 0.4 20.5 2.5 –
shopdb – – 0.2 4.0 – 4200.0
shop disk – – – – – 120.0
* deleted
Custom domains
Serve an app at your own domain, with HTTPS. Deplane routes a domain only after DNS proves it points at the app, then gets its certificate automatically.
deplane domains
List the app's custom domains: waiting for DNS, issuing certificate, or active.
$ deplane domains
DOMAIN STATE
www.example.com active
example.com waiting for DNS
deplane domains add
Connect a domain and show the DNS records to set. For a subdomain such as www.example.com, add a CNAME to <app>.deplane.dev. A root domain such as example.com cannot have a CNAME: add an A record to the address shown instead. Either way, add the TXT record _deplane-challenge.<domain> with the value shown, which proves the domain is yours. An app can have up to 10 domains.
$ deplane domains add www.example.com
www.example.com is waiting for DNS. No DNS record for www.example.com yet. Add a CNAME record pointing to shop.deplane.dev and a TXT record _deplane-challenge.www.example.com with the value dpl-… (DNS changes can take a few minutes).
Set these records at your DNS provider (the TXT record proves the domain is yours):
CNAME www.example.com shop.deplane.dev
TXT _deplane-challenge.www.example.com dpl-…
deplane domains check
Check a domain's DNS and certificate now. Deplane also checks every 2 minutes for 48 hours after you add it.
deplane domains remove
Disconnect a domain. It stops serving the app right away. Asks for confirmation; pass --yes in scripts.
Databases
Managed Postgres 17 next to your apps. Each database runs in its own microVM on a 10 GB disk that only it uses, reachable only by your team's apps. Attaching it to an app sets the app's DATABASE_URL, a write-only variable, and rolls out a new release. A database counts against your plan as one instance of its size.
deplane db
List your team's databases, their state, and the apps they are attached to.
deplane db create
Create a database. It is ready in about a minute.
$ deplane db create main
$ deplane db attach main --app shop
deplane db attach
Give an app the database as DATABASE_URL (postgres://app:…@pg--main:5432/app). An app uses one database at a time.
deplane db detach
Remove the app's DATABASE_URL. The database and its data stay.
deplane db destroy
Delete a database and all its data, after detaching it from its apps. Asks for confirmation; pass --yes in scripts. It also needs a confirmation in your browser: the CLI prints a link and a code (and opens the link), you approve with your passkey, and the command continues. --yes does not skip this, and CI tokens cannot do it at all. Its backups are kept for your plan's backup window; restore it with deplane db restore NAME --deleted --at latest.
deplane db backups
Show a database's backup status (Protected, Behind, Starting or Off), the window it can be restored to (your local time and UTC; gaps show as more than one window), the last full copy, the space used and recent restores. --deleted shows a deleted database's backups.
deplane db restore
Restore a database into a new database; the original is never changed. --at is latest, a time such as 2026-10-15 16:31 (your local time) or 2026-10-15T14:31:20Z, or a time ago: -10m, 2h, 1d. The new name is --to, or <name>-restored-<HHMM>. --deleted restores a deleted database. It waits up to 15 minutes, showing progress (--no-wait returns at once), then prints the deplane db switch command to run.
Restoring and switching need a confirmation in your browser with your passkey: the CLI prints a link and a code, waits for you to approve, and continues. Each restore or switch uses up its confirmation, so the next one asks again. CI tokens and AI tools cannot restore or switch databases.
$ deplane db restore main --at -10m Restoring from main as of 2026-10-15 14:42:31 UTC. main-restored-1442 is ready. Check it, then move your apps to it: deplane db switch main-restored-1442 --from main
deplane db switch
Give every app attached to --from this database as DATABASE_URL instead (a new release each, no downtime). The original database is kept until you delete it.
Team
Work on apps together. Everyone signs in with their own passkey, and everything they do appears in the activity log with their name. Members deploy and manage apps; owners can also invite and remove people.
deplane team
List your team's members and open invitations.
deplane team invite
Invite someone by email. You get a link to send them yourself: it works once, for that address, for 7 days, and they set up a passkey when they join. Needs a fresh confirmation with your passkey. --role owner makes them an owner.
$ deplane team invite colleague@company.com
Send this link to colleague@company.com. It works once, for 7 days, and is shown only now:
https://login.deplane.cloud/invite?t=…
deplane team remove
Remove a member. Their tokens for the team stop working. Asks for confirmation; pass --yes in scripts. Needs a fresh confirmation with your passkey.
Workers and cron jobs
Run more processes from the same app: workers that run all the time (a queue consumer, a bot) and cron jobs that run on a schedule (a nightly report). They use the app's current image and its variables, each in its own microVM, and their output appears in deplane logs. The command runs through the image's shell (/bin/sh -c). Workers count against your plan's instances and memory; a cron job counts as one instance of its size.
deplane processes
List the app's workers and cron jobs.
$ deplane processes
NAME KIND RUNS SIZE COMMAND
emails worker 1 instance(s) small node emails.js
nightly cron 0 3 * * * UTC small node report.js
deplane processes add
Add a worker, or with --schedule a cron job. Schedules have five fields in UTC (minute, hour, day of month, month, day of week), or @hourly, @daily, @weekly, @monthly. A cron job runs one instance at a time, for at most an hour, and a failed run is not retried.
$ deplane processes add emails --command "node emails.js"
$ deplane processes add nightly --command "node report.js" --schedule "0 3 * * *"
deplane processes scale
Change a worker's instances (0 stops it), or any process's --size, --command, or --schedule.
deplane processes remove
Remove a worker or cron job. Asks for confirmation; pass --yes in scripts.
App disks
A 5 GB disk for an app, mounted at a path, whose files stay across deploys and restarts. An app with a disk runs one instance and does not autoscale, and each deploy stops it for a few seconds. See Disks.
deplane disks create
Give an app a disk: deplane disks create APP [--path /data]. The app must run one instance without autoscaling; if it runs more, scale it first with deplane scale 1 --max 0 --app APP.
$ deplane disks create my-app
Added a 5 GB disk to my-app at /data. Files there survive deploys and restarts, and are backed up every night.
my-app now runs one instance and cannot autoscale. Each deploy stops it for a few seconds while the new release takes the disk.
deplane disks list
List your team's disks with their path and last backup. --json prints {"disks": [...]}.
deplane disks backups
List an app's disk backups, newest first: ID, status, nightly or on request, start time (UTC), and size.
deplane disks backup
Back up an app's disk now. At most once an hour; the app keeps running.
deplane disks restore
Replace all files on an app's disk with a backup: deplane disks restore APP BACKUP-ID. Files written since that backup are lost, and the app stops while the restore runs. Asks for confirmation; pass --yes in scripts. It also needs a confirmation in your browser with your passkey, each time; CI tokens and AI tools cannot restore disks.
deplane disks destroy
Destroy an app's disk and the files on it. Asks for confirmation; pass --yes in scripts. Like restore, it needs your passkey in the browser each time. Its backups are kept for 3 days.
deplane templates list
Lists the templates with what each needs (memory, Postgres, a disk) and whether your team can deploy it now: ready, "no room now" (free some room: the message says how much is needed and free) or "needs a larger plan". Below, your team's recent template deploys with their ID, status and step. --category Starters|Analytics|Monitoring|Productivity|Developer tools|Data narrows the list. --json prints both lists.
deplane templates show
deplane templates show NAME shows one template: its description, what it needs, whether your team has room, its licence, source and version, the variables it sets (names only) and the trademark notice.
deplane templates retry
deplane templates retry DEPLOY-ID continues a failed template deploy from the step that failed. What was already made is kept and its generated secrets stay the same; at the last step it builds again.
deplane templates credentials
deplane templates credentials DEPLOY-ID shows, once, the admin sign-in a template set up at deploy time (for example Grafana's generated admin password), for a deploy you started and that is done. deplane launch --template prints it by itself when it waits for the deploy; use this for a deploy started with --no-wait, from the dashboard or by an AI tool. Deplane never shows it a second time (template_credentials_shown).
deplane templates delete
deplane templates delete DEPLOY-ID deletes the app (with its disk) and the database that this deploy made, and nothing else. It asks first (--yes skips the question) and needs your browser confirmation, like other deletions. A running deploy cannot be deleted; wait for it to finish or fail.
Redis
A managed Redis (Valkey 8, 256 MB) for caches and queues. See Redis.
deplane redis create
Create a Redis: deplane redis create NAME. It counts 256 MB against your plan's memory.
deplane redis list
List your team's Redis with their address, apps and last backup. --json prints {"redis": [...]}. Passwords are never shown.
deplane redis attach
Give an app the Redis as REDIS_URL: deplane redis attach NAME --app APP. A new release rolls out. An app has one Redis.
deplane redis detach
Remove an app's REDIS_URL: deplane redis detach NAME --app APP. The Redis and its data are kept.
deplane redis backups
List a Redis's backups, newest first: ID, status, nightly or on request, start time (UTC), size.
deplane redis backup
Back up a Redis now. At most once an hour; it keeps running.
deplane redis restore
Replace a Redis's data with a backup: deplane redis restore NAME BACKUP-ID. Data written since the backup is lost, and the Redis stops while the restore runs. Asks for confirmation; pass --yes in scripts. It also needs your passkey in the browser each time; CI tokens and AI tools cannot restore.
deplane redis destroy
Destroy a Redis and its data; its apps lose REDIS_URL. Asks for confirmation; pass --yes in scripts. Needs your passkey each time. Its backups are kept for 3 days.
Admin commands
These commands work only for Deplane administrators. Everyone else gets not_found. Each one needs a fresh passkey confirmation from the last 5 minutes; in a terminal the CLI opens the browser for it.
deplane admin requests
List beta access requests.
| Flag | What it does |
|---|---|
--status STATUS | pending (default), approved, or denied. |
$ deplane admin requests
ID EMAIL NAME COMPANY REQUESTED
acr_3n8m2b5v9c1x7z4l6k0j dev@example.com Dana Lee Example 2026-10-12
{
"access_requests": [
{
"id": "acr_3n8m2b5v9c1x7z4l6k0j",
"email": "dev@example.com",
"name": "Dana Lee",
"company": "Example",
"use_case": "Internal tools",
"status": "pending",
"created_at": "2026-10-12T16:20:00Z"
}
]
}
deplane admin approve
Approve a pending access request by email or ID: deplane admin approve EMAIL|ID. This creates the user and a personal organization on the default plan, and tries to email them a sign-in link. Email sending is not set up yet, so the email may not arrive; contact them another way.
$ deplane admin approve dev@example.com
Approved dev@example.com. They were emailed a sign-in link.
{
"user_id": "usr_6f1d9s4a8p2o7i3u5y0t",
"org_id": "org_9r4e7w2q5t8y1u6i3o0p",
"email": "dev@example.com"
}
deplane admin deny
Deny a pending access request by email or ID: deplane admin deny EMAIL|ID. Asks for confirmation; pass --yes to skip it.
$ deplane admin deny dev@example.com --yes
Denied dev@example.com.
{
"denied": "acr_3n8m2b5v9c1x7z4l6k0j"
}
deplane admin abuse list
List abuse reports, oldest first, so the queue is worked in order.
| Flag | What it does |
|---|---|
--status STATUS | open (default), investigating, actioned, rejected, or all. |
$ deplane admin abuse list
ID STATUS CATEGORY APP URL REPORTED
abr_2k7j4h9g1f6d3s8a5p0o1q2w open phishing pay-verify-01 https://pay-verify-01.deplane.dev/x 2026-10-13 07:55
{
"abuse_reports": [
{
"id": "abr_2k7j4h9g1f6d3s8a5p0o1q2w",
"status": "open",
"category": "phishing",
"url": "https://pay-verify-01.deplane.dev/x",
"details": "This page copies our bank's login form.",
"reporter_email": "victim@example.org",
"reporter_ip": "203.0.113.9",
"app_id": "app_8d2k4j6h1g3f5s7a9p0o1q2w",
"app": "pay-verify-01",
"org_id": "org_3j5h7g9f1d2s4a6p8o0i1u2y",
"org_slug": "7f3k2p",
"actions": [],
"created_at": "2026-10-13T07:55:00Z",
"resolved_at": null,
"resolution_note": ""
}
]
}
app, app_id, org_id, and org_slug are empty when the reported address is not a Deplane app. reporter_email is empty for an anonymous report.
deplane admin abuse show
Show one abuse report in full: deplane admin abuse show ID. This includes the details, the reporter, the reported app and its organization, and the history of the report.
$ deplane admin abuse show abr_2k7j4h9g1f6d3s8a5p0o1q2w
Report: abr_2k7j4h9g1f6d3s8a5p0o1q2w
Status: open
Category: phishing
URL: https://pay-verify-01.deplane.dev/x
App: pay-verify-01 (organization 7f3k2p, org_3j5h7g9f1d2s4a6p8o0i1u2y)
Reporter: victim@example.org from 203.0.113.9
Received: 2026-10-13T07:55:00Z
Details:
This page copies our bank's login form.
The JSON is one report, with the same fields as in deplane admin abuse list.
deplane admin abuse resolve
Move a report to a new status: deplane admin abuse resolve ID --status investigating|actioned|rejected [--note TEXT]. Each step is added to the report's actions history. actioned and rejected also record who resolved it, when, and the note. Resolving a report does not suspend anything; use suspend-app or suspend-org for that.
| Flag | What it does |
|---|---|
--status STATUS | Required. investigating, actioned, or rejected. |
--note TEXT | What you found or did. Stored with the report. |
$ deplane admin abuse resolve abr_2k7j4h9g1f6d3s8a5p0o1q2w --status actioned --note "Phishing confirmed; app suspended."
Report abr_2k7j4h9g1f6d3s8a5p0o1q2w is now actioned.
The JSON is the updated report, as in deplane admin abuse show, with status, resolved_at, resolution_note, and a new entry in actions (at, by, status, note).
deplane admin suspend-app
Suspend an app by name, in any organization: deplane admin suspend-app NAME --reason TEXT [--yes]. The app runs zero instances and can no longer be deployed or changed. Nothing is deleted. The reason is recorded in the organization's audit log. Without a terminal, pass --yes.
| Flag | What it does |
|---|---|
--reason TEXT | Required, at most 500 characters. Why the app is suspended; include the report ID. |
$ deplane admin suspend-app pay-verify-01 --reason "Phishing, report abr_2k7j4h9g1f6d3s8a5p0o1q2w" --yes
Suspended app pay-verify-01. Undo with `deplane admin unsuspend --app pay-verify-01`.
{
"id": "sus_4h6j8k0l2z4x6c8v0b2n4m6q",
"target_type": "app",
"target_id": "app_8d2k4j6h1g3f5s7a9p0o1q2w",
"reason": "Phishing, report abr_2k7j4h9g1f6d3s8a5p0o1q2w",
"created_at": "2026-10-13T08:10:00Z",
"lifted_at": null
}
deplane admin suspend-org
Suspend an organization by slug or ID: deplane admin suspend-org SLUG --reason TEXT [--yes]. All its apps run zero instances, and all its logins and tokens stop working (account_suspended). You cannot suspend your own organization.
| Flag | What it does |
|---|---|
--reason TEXT | Required, at most 500 characters. Why the organization is suspended. |
$ deplane admin suspend-org 7f3k2p --reason "Repeated phishing" --yes
Suspended organization 7f3k2p. Undo with `deplane admin unsuspend --org 7f3k2p`.
The JSON has the same shape as for suspend-app, with "target_type": "org" and the organization's ID as target_id.
deplane admin unsuspend
Lift a suspension: deplane admin unsuspend --app NAME or deplane admin unsuspend --org SLUG. Pass exactly one of the two. Apps return to the instance count they had. Without a terminal, pass --yes.
| Flag | What it does |
|---|---|
--app NAME | Unsuspend this app. |
--org SLUG | Unsuspend this organization (slug or ID). |
$ deplane admin unsuspend --org 7f3k2p --yes
Unsuspended organization 7f3k2p.
The JSON is the lifted suspension, with lifted_at set.
Help
deplane help prints the command list, the global flags, the environment variables, and the exit codes. deplane help --json prints:
{
"commands": [
{"command": "apps", "usage": "List your apps."},
{"command": "deploy", "usage": "Build and deploy this folder's app again [--app NAME]."}
]
}
This page is also available as Markdown. AI agents can start at /llms.txt.