deplaneDocs Dashboard

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.

FlagWhat it does
--jsonPrint exactly one JSON document on stdout. Streams print one JSON object per line. Progress messages still go to stderr.
--yesAnswer yes to every confirmation.
--debugLog each HTTP request and response to stderr. Tokens, cookies, Authorization headers, and secret values are replaced with [REDACTED].
--app NAMEThe app to act on. Default: app in ./deplane.toml.
--helpShow 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

VariableWhat it does
DEPLANE_TOKENUse this token instead of the stored login.
DEPLANE_API_URLThe API to use. Default https://api.deplane.cloud.

Exit codes

The exit codes are stable. Scripts and agents can rely on them.

CodeMeaning
0Success.
1User error: a bad flag, a bad value, a missing app, a cancelled confirmation.
2Authentication error: not logged in, login expired, or a fresh passkey confirmation is needed.
3The build failed.
4The deploy failed: the new release did not become healthy.
5Platform error: the API could not be reached, or something failed on our side.
6Quota 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.

FlagWhat it does
--name NAMEThe token's name, instead of the positional argument.
--expires-in-days NLifetime 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.

FlagWhat it does
--name NAMEThe new app's name. Default: the folder name, with a random suffix if that name is taken.
--app NAMEDeploy 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.

FlagWhat it does
--app NAMEDeploy 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.

FlagWhat it does
--size SIZEsmall, medium, or large. See Limits.
--max MAutoscale between N and M instances. --max 0 turns autoscaling off.
--sleep TIMEPut 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:

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.

FlagWhat it does
-f, --followKeep streaming new lines until you press Ctrl-C.
--tail NLines 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.

FlagWhat it does
--buildSet 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.

FlagWhat it does
--status STATUSpending (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.

FlagWhat it does
--status STATUSopen (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.

FlagWhat it does
--status STATUSRequired. investigating, actioned, or rejected.
--note TEXTWhat 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.

FlagWhat it does
--reason TEXTRequired, 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.

FlagWhat it does
--reason TEXTRequired, 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.

FlagWhat it does
--app NAMEUnsuspend this app.
--org SLUGUnsuspend 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.