@stackedhq/cli
v0.1.3
Published
The Stacked CLI — deploy, manage, and inspect your Stacked services from the terminal.
Readme
@stackedhq/cli
The Stacked CLI. Deploy, manage, and inspect your Stacked services from the terminal — and drive them from agents and CI with first-class JSON output.
npm i -g @stackedhq/cli
stacked --helpQuick start
stacked login # browser-based device flow (default)
stacked status # one-shot view of auth, API, linked service
stacked services list # human table — or pipe with --json
stacked deploy <slug> # watches the deployment until it terminates
stacked redeploy <slug># re-run the latest deployment, faithful to its config
stacked logs <slug> # tail runtime logs (Ctrl-C to stop)Commands
Auth & session
| Command | Description |
|---|---|
| stacked login | Authenticate. Browser device flow by default; --token <stk_…> to paste. |
| stacked logout | Sign out. Revokes the token server-side unless --keep-server. |
| stacked whoami | Show the current user. |
| stacked status | Single-shot view of auth, API reachability, version, linked service. |
Deploy & operate
| Command | Description |
|---|---|
| stacked deploy [service] | Deploy a service from its current config. Defaults to the linked service. --watch (default in TTY) follows status; --no-watch returns the deployment id immediately; --timeout <sec> (default 600). |
| stacked redeploy [service] | Re-run the service's most recent deployment, faithful to the exact image/git ref it shipped. Same --watch/--no-watch/--timeout flags as deploy. |
| stacked deployments list [service] | List a service's deployment history, or recent deployments across all services. |
| stacked deployments get <id> | Show one deployment. |
| stacked deployments cancel <id> | Cancel an in-flight deployment. |
| stacked logs [service] | Tail runtime container logs. --deployment <id> streams a deployment's build logs instead; --no-follow captures current logs and exits. |
| stacked restart [service] | Restart a service. |
| stacked stop [service] | Stop a service. |
Environment variables
| Command | Description |
|---|---|
| stacked env list [--service <id>] | List a service's env vars. |
| stacked env set KEY=VALUE … [--service <id>] | Upsert one or more vars (additive). |
| stacked env unset KEY … [--service <id>] | Remove vars by key. |
| stacked env pull [--service <id>] [--file .env] [--force] | Write env vars to a dotenv file. |
env subcommands take their target from --service <id-or-slug> or the linked service. (Positionals are reserved for KEY=VALUE pairs / keys.)
Inventory (read-only)
| Command | Description |
|---|---|
| stacked services list / stacked services get <id-or-slug> | List / show services. |
| stacked machines list / stacked machines get <id> | List / show connected machines. |
| stacked databases list / stacked databases get <id> | List / show databases. |
| stacked domains list | List domains. |
| stacked projects list | List projects. |
Project link & misc
| Command | Description |
|---|---|
| stacked link <service> | Link the current directory to a service (writes .stacked). |
| stacked unlink | Remove .stacked. |
| stacked open [service] | Open the dashboard in your browser. |
| stacked update | Print (or --run) the upgrade command for your install. |
| stacked completion [zsh\|bash\|fish] | Emit a shell completion script. |
| stacked schema | Emit a JSON description of every command, error code, exit code, and env var. |
Authentication
Three ways to provide a token, in precedence order:
--token <stk_…>flag — overrides everything, never persisted.STACKED_TOKENenv var — for CI and agent workflows. Stateless: nothing is written to disk.- Saved config — written by
stacked loginafter a successful browser device flow.
Tokens are minted at:
stacked login— opens the browser, you click Authorize, the CLI exchanges the code for a token. No copy-pasting.- Dashboard → Settings → API keys — create a named key for non-interactive workflows. Plaintext shown exactly once. Same primitive the CLI uses; usable from
curl, agents, MCP servers, CI, anywhere.
Revoke any key from the same dashboard page.
Agent & scripting mode
Pass --json (or --output ndjson) to get a stable, versioned envelope on stdout:
{
"schemaVersion": 1,
"ok": true,
"command": "services.list",
"requestId": "f0d4314f-…",
"data": { /* command-specific */ },
"meta": {
"apiUrl": "https://stacked.rest",
"apiUrlSource": "default",
"authSource": "env",
"durationMs": 142,
"cliVersion": "0.0.1"
}
}On failure:
{
"schemaVersion": 1,
"ok": false,
"command": "deploy",
"error": {
"code": "NOT_AUTHENTICATED",
"message": "Run `stacked login` first.",
"httpStatus": 401,
"hint": { "action": "login" }
},
"meta": { /* … */ }
}error.code is a closed enum — adding new codes is non-breaking; renaming or removing one bumps schemaVersion. Run stacked schema to enumerate every code, exit code, and env var.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Generic / unknown |
| 2 | USER_INPUT_ERROR / VALIDATION_ERROR |
| 3 | NOT_AUTHENTICATED |
| 4 | FORBIDDEN / FORBIDDEN_PRELAUNCH |
| 5 | NOT_FOUND |
| 6 | CONFLICT / DEPLOYMENT_IN_FLIGHT (a deployment is already running for the service) |
| 7 | RATE_LIMITED |
| 8 | NETWORK_ERROR |
| 9 | SERVER_ERROR |
| 10 | DEPLOYMENT_FAILED (deploy ended in failed/cancelled) |
| 11 | TIMEOUT (watched deploy didn't terminate before --timeout) |
Progress events
In JSON / ndjson mode, the runtime stays silent on stderr by default. Pass --verbose (or set STACKED_JSON_EVENTS=1) to receive ndjson progress events on stderr — useful while watching a deployment.
stacked --json --verbose deploy myapp 2> events.ndjsonAgent recipes
# Redeploy and block until it's live, parsing the result envelope.
stacked redeploy myapp --json --watch | jq -e '.ok and .data.status == "success"'
# Trigger a deploy without blocking, then poll on your own cadence.
ID=$(stacked deploy myapp --json --no-watch | jq -r .data.deploymentId)
stacked deployments get "$ID" --json
# Capture the current logs (no streaming) for a diagnosis prompt.
stacked logs myapp --json --no-follow | jq -r '.data.lines[]'
# Read/patch config non-interactively.
stacked env list --service myapp --json
stacked env set DATABASE_URL=postgres://… LOG_LEVEL=debug --service myapp --jsonNote: log following can't be expressed as the single-shot JSON envelope, so
--json requires --no-follow (it captures the currently-buffered lines and
returns them once). Human mode follows by default and prints lines as they
arrive. stacked schema enumerates every command, arg, error code, and exit
code for agents to introspect without parsing --help.
Environment variables
| Var | Purpose |
|---|---|
| STACKED_TOKEN | Long-lived API key. Overrides saved config. |
| STACKED_API_URL | Override API base URL (e.g. for a Cloudflare Tunnel). |
| STACKED_DEBUG | 1 → dump raw HTTP traffic to stderr (secrets redacted). |
| STACKED_JSON_EVENTS | 1 → emit ndjson progress events to stderr in JSON modes. |
| STACKED_NO_UPDATE_CHECK | 1 → disable the daily npm registry update probe. |
Development
From the repo root:
pnpm install
pnpm --filter @stackedhq/cli dev # run from source with hot reload
pnpm --filter @stackedhq/cli build # build to dist/
pnpm --filter @stackedhq/cli type-check
pnpm --filter @stackedhq/cli testPoint the CLI at a local API while developing:
STACKED_API_URL=http://localhost:3000 pnpm --filter @stackedhq/cli dev whoamiPublishing
Maintainers: full runbook in docs/cli-release.md (version bump, manual publish, GitHub Actions Publish CLI with NPM_TOKEN).
pnpm --filter @stackedhq/cli test
pnpm --filter @stackedhq/cli build
cd packages/cli && npm publish --access public