CLI (descanto command)
descanto: the command-line interface for Descanto cloud desktops.
@descanto/cli ships the descanto command -- a thin wrapper over
@descanto/sdk (bundled in) for driving desktops
from a shell or a CI pipeline.
Install
npm install -g @descanto/cli
descanto --help
# or run it without installing:
npx -y @descanto/cli --helpAuth
Highest wins:
--api-key <canto_sk_...>(exists for CI; beware shell history)CANTO_API_KEYenv var~/.config/canto/config.json($XDG_CONFIG_HOME/canto/config.jsonwhen set), written0600bydescanto login
descanto login # prompts (hidden) for the key, validates via /v1/me, saves config
descanto whoamiBase URL resolves the same way: --base-url -> CANTO_BASE_URL -> the
config file -> the SDK default. descanto login follows that same chain when
validating the key, so it always talks to the API every later command
will. Logging in again merges into the existing config file rather than
replacing it -- an existing baseUrl survives a re-login, and only
--base-url (not CANTO_BASE_URL, which stays env-scoped for that one
invocation) gets persisted.
Commands
descanto list [--state awake]
descanto create [--tier default] [--billing-mode hourly] [--idle-timeout 600] \
[--env K=V ...] [--setup-script file.sh] [--ephemeral]
descanto wake <id> [--no-wait]
descanto hibernate <id> [--no-wait]
descanto destroy <id> [--yes] [--no-wait] # prompts unless --yes or --json
descanto fork <id> --count N --acknowledge-shared-state [--ephemeral] [--no-wait]
descanto exec <id> <command...> [--timeout SECS] # exits with the guest exit code
descanto exec <id> -d <command...> # detached: prints the processId
descanto exec-status <id> <process-id> [--wait]
descanto files get <id> <remote-path> [local-path] # omitted/- writes raw bytes to stdout
descanto files put <id> <local-path> <remote-path> # - reads stdin
descanto stream <id> [--claim view|control] [--takeover] [--open]
descanto usage [--days 30] [--start MS --end MS]
descanto keys create <name> | descanto keys list | descanto keys revoke <id>
descanto webhooks create --url U --event E [--event E ...]
descanto webhooks list | descanto webhooks delete <id>
descanto webhooks deliveries <id> [--limit N]Each command maps directly onto the API reference: descanto create is POST /v1/desktops, descanto exec is POST .../exec, and so on
-- see the linked reference pages for field-level detail on each
(--tier, --billing-mode, --idle-timeout, --env, --setup-script
map onto CreateDesktopBody;
--acknowledge-shared-state is the same required acknowledgment
forking requires everywhere else).
descanto exec -d mirrors the SDK's detached: true -- it prints the
processId and returns immediately instead of blocking; poll it with
descanto exec-status <id> <process-id> [--wait].
--json contract
Every command accepts --json: exactly the API's JSON (or the SDK's
settled result) on stdout, nothing else on stdout; problem+json (or
{ "error": { "message": ... } } for non-API failures) on stderr. This
makes descanto ... --json | jq safe to script against without worrying
about interleaved human-readable output.
Exit codes: 0 success, 1 API/runtime error, 2 usage error -- except
blocking descanto exec (and descanto exec-status --wait), which instead
propagates the guest command's own exit code, so descanto exec $ID make test && echo ok works the way you'd expect from a local shell.
Development
bun install
bun run test # vitest, SDK/fetch mocked
bun run typecheck
bun run build # tsup, bundles @descanto/sdk (noExternal)Releases go out in lockstep with @descanto/sdk / @descanto/mcp.