Cloady Docs

CLI Reference

Deploy and manage your applications from a terminal or a CI pipeline.

cloady deploys and manages your applications from a terminal. It calls the same REST API the dashboard uses, so anything you script behaves exactly like clicking through the UI.

Install

npm install -g cloady

Requires Node 20+. Verify with:

cloady --version

Authentication

cloady login with no arguments opens your browser, shows a code to confirm, and stores the token it hands back:

cloady login
# Confirm this code matches:  WXYZ-1234
# logged in as you@example.com

Add --scope read, --scope deploy or --scope full (the default) to limit what that token may do.

To use a token you made yourself, create one in the dashboard under Account → API tokens — the value (cldy_…) is shown once — and pass it as an argument:

cloady login cldy_…

Either way the token is stored in ~/.config/cloady/config.json (mode 0600; honors $XDG_CONFIG_HOME). cloady logout removes it.

Token resolution order, first match wins:

  1. --token <token> flag
  2. CLOADY_TOKEN environment variable
  3. The stored config file

CI tip: skip login entirely and set CLOADY_TOKEN in the job environment.

Global options

Every command accepts:

FlagEffect
--token <token>Use this API token for the single invocation
--api-url <url>Point at a different Cloady API; resolution mirrors the token: flag → CLOADY_CONTROL_PLANE_URL → config
--jsonPrint the raw API response as JSON instead of the human-readable line format — the mode to use in scripts

Errors print to stderr as error: <code>: <message> and exit non-zero, so && chains and CI steps fail correctly. The ones you'll actually hit:

CodeWhat it meansWhat to do
payment_requiredThe app would take the workspace past its free allowance and there is no card on file, or it was declinedAdd a card under workspace Settings → Billing, or make the app smaller
region_requiredAn app with that id exists in more than one regionPass --region
not_foundNo app with that id in that workspace and environmentCheck cloady apps <workspace>

Deploy from a repository

cloady deploy is the only create command; --type says where the code comes from (git, upload or catalog).

cloady deploy github.com/your-org/your-repo --type git

What happens with no other flags:

  • Workspace — if you have exactly one, it's used. Several → an interactive picker. None → the CLI walks you through creating one right there (name and id; a new workspace costs nothing).
  • Region — where most of your apps already run, otherwise the first region that's ready. Picking a region just chooses where this app runs.
  • Name — the repository name.
  • Environment — production.

The build runs on Cloady (your stack is detected, or your Dockerfile is used when the repo has one), and the app answers on a URL like shop-k7q2v9ze-acme.cloady.io — your app's name, a short code, and your workspace's name, with HTTPS set up for you. Preview and development apps put the environment in the URL: shop-k7q2v9ze-acme.preview.cloady.io.

The command returns as soon as the deploy starts, printing the app id, its status and its URL; the build keeps running afterwards. Private repositories work once the workspace has GitHub connected (Settings → Integrations).

cloady deploy resolves what you omit, sends one request, and returns while Cloady buildsyour machine — what the CLI resolves before it calls anythingtoken--token → env → config fileworkspace-w, else pick, or create oneregion--region, or where apps runPOST /api/workspaces/acme/deployevery flag is just a field of this requestreturns at once, printing the slug and URLstatus: deployingCloady — everything after that request happens hereapp row + URL existthe host is assigned at onceimage built on Cloadyrailpack, or your Dockerfilecontainers rolled outthe URL starts answeringthe build outlives the command — poll it with cloady apps acme --json

Flags, for every source type:

FlagMeaningDefault
--type <type>git · upload · catalogupload
-w, --workspace <id>Target workspaceauto-detected
--region <region>Where the app runsauto-detected
--name <name>Display name; the app id and its URL follow itrepo, folder or catalog name
--env <env>production · preview · developmentproduction
--port <port>Port your server listens on (ignored when your repo brings its own compose file)3000
--value <key=value>Set an environment variable on the new app; repeatable—
--branch <branch>Git branch to build (--type git)repo default
--subdir <dir>Build a subdirectory, for monorepos (--type git)repo root
cloady deploy github.com/acme/api --type git --name api --env preview --branch develop --port 8080

Each app runs in one region and one environment, and an app's name is unique within a workspace and environment.

Deploy a local folder

With no --type, cloady deploy zips the current directory and uploads it — no git remote needed:

cloady deploy                     # the current folder
cloady deploy ./services/api      # some other folder

.git, node_modules, .next, dist, .turbo, .venv, venv, __pycache__ and .DS_Store are skipped. The CLI prints how many files it sent, then builds exactly as it does for a repository. The app is named after the folder unless you pass --name.

Install a catalog application

cloady deploy <applicationId> --type catalog

applicationId is the catalog id (wordpress, postgres, n8n, …) — the same ids the dashboard's New Application picker shows. Workspace and region are resolved the same way as for a repository, and all the flags above apply. Use --value for the settings the application asks for; anything you leave out gets its default or a generated secret.

cloady deploy wordpress --type catalog -w acme --region eu1 --name blog
cloady deploy postgres  --type catalog -w acme --region eu1 --value POSTGRES_DB=app

Inspect

cloady whoami                     # the authenticated user
cloady workspaces                 # your workspaces (alias: ws)
cloady regions                    # every region, with whether it's ready
cloady apps <workspace>           # apps in a workspace
cloady apps <workspace> --env production --region eu1

apps prints one line per app: id, status, region, environment, name. Add --json for the full objects — endpoints, services, resource limits, source.

Lifecycle

All of these take <workspace> <appId> plus --env (default production) and --region. Region can be omitted when the app id is unambiguous — if the same id exists in several regions you'll get a region_required error asking you to pass it.

cloady start acme blog            # start a stopped app
cloady stop acme blog             # stop it; its data is kept
cloady redeploy acme blog         # rebuild the latest code and roll the containers
cloady restart acme blog          # alias for redeploy
cloady delete acme blog           # delete the app AND its data

delete is immediate and unprompted, and it deletes the app's data permanently. There is no undo. To change an app's name or its URL, rename it in the dashboard — the address follows the name, so you never delete an app to rename it.

start, stop and redeploy move containers only; delete also destroys the app's dataredeploystoppedno containersrunningcontainers up, servingdeletednothing leftstartstopdeletedata volumes survivestart, stop and redeploy only move containersvolumes destroyedthere is no undoeach takes a workspace and an app id; delete works from either state

Run a command in a container

cloady exec <workspace> <appId> --component <name> -- <command…>

Runs a one-off command in a running container and prints its output. The command's exit code becomes the CLI's exit code (124 if it times out), and piped stdin is forwarded.

FlagMeaning
--component <name>Required. Which service of the app to run in (e.g. wordpress, db)
--cwd <dir>Working directory (default: the container's own)
--timeout <seconds>Give up after this long (default 30, max 300)
--env <env> / --region <region>As above
cloady exec acme blog --component wordpress -- wp plugin list
cloady exec acme db --component postgres -- psql -U app -c 'select 1'
echo 'select count(*) from users;' | cloady exec acme db --component postgres -- psql -U app

The command runs through /bin/sh -c, so quote pipes and globs if you want them evaluated inside the container. Long output is truncated to its tail, with a note on stderr. Two errors are specific to exec: unknown_component means the app has no service by that name (check the app's page in the dashboard), and no_pod means nothing is running — start the app first.

Scripting recipes

# wait until an app reports running
until cloady apps acme --json | jq -e '.[] | select(.slug=="blog" and .status=="running")' >/dev/null; do sleep 5; done

# redeploy from CI on every push to main
CLOADY_TOKEN=$CI_SECRET_TOKEN cloady redeploy acme api

# list every app across all workspaces
for ws in $(cloady ws --json | jq -r '.[].slug'); do cloady apps "$ws"; done

For anything the CLI doesn't cover, drop down to the REST API — same token, same base URL.

On this page