CLI#
The taskcloud CLI is a thin layer over the REST API. Everything it does, you can do with the API.
Install and log in#
Install script#
Available once the first CLI release is tagged. The script installs a prebuilt binary for Linux or macOS (amd64 or arm64); run curl -fsSL https://task.cloud/install.sh | sh in a terminal.
It detects your OS and architecture, downloads the matching archive from the project's GitHub Releases, verifies its SHA-256 against the release's checksums.txt and installs taskcloud to ~/.local/bin (or /usr/local/bin when run as root). Optional environment variables:
| Variable | Effect |
|---|---|
TASKCLOUD_VERSION |
Install a specific version, e.g. TASKCLOUD_VERSION=0.2.0. Default: the latest stable release. |
TASKCLOUD_INSTALL_DIR |
Install somewhere else, e.g. TASKCLOUD_INSTALL_DIR=$HOME/bin. |
Each release also ships a signed checksum file and SBOMs; the release notes list the cosign and gh attestation verify commands.
Build from source#
Until the first release, and during the private beta, the CLI is built from source (Go 1.27.3+, standard library only); beta participants get access to the source repository:
cd cli && go build -o taskcloud . && sudo mv taskcloud /usr/local/bin/
Log in#
taskcloud login # prompts for an API key (opens the dashboard to create one)
taskcloud login --key-stdin < key.txt # non-interactive (CI)
taskcloud whoami
Coming soon: an npm wrapper (npm install -g @taskcloud/cli) and browser-based login. Until then, taskcloud login asks you to paste a key created in the dashboard.
Credentials are stored in ~/.config/taskcloud/config.json. The TASKCLOUD_API_KEY environment variable takes precedence.
Global flags: --json (machine-readable output; on automatically when stdout is not a TTY), --api-key <key>, --api-url <url>, --quiet.
Cheat sheet#
taskcloud create --template base --size default --name dev # prints the sandbox ID
taskcloud list # your sandboxes (deleted ones hidden)
taskcloud exec <id> -- npm test # exit code = command's exit code
taskcloud shell <id> # PTY session: prints its WebSocket URL
taskcloud ssh <id> # SSH through the gateway
taskcloud cp ./app <id>:/home/user/app -r # upload a directory
taskcloud port expose <id> 3000 --public # https://<short_id>-3000.taskhost.cloud
taskcloud pause <id> # $0 compute while paused
taskcloud fork <id> --name dev-copy # copy with memory
taskcloud fork <id> --count 5 -q # 5 copies, all or nothing; prints 5 IDs
taskcloud desktop <id> --ttl 10m --read-only --open # open the desktop in a browser
taskcloud screenshot <id> -o screen.png
taskcloud input <id> '[{"action":"left_click","coordinate":[640,412]}]' -o after.png
taskcloud delete <id> --yes
Commands#
Sandboxes#
| Command | Description | API |
|---|---|---|
create [flags] |
Create a sandbox. Flags: --template <name>, --snapshot <snap_id>, --image <ref>, --size small\|default\|large, --name, --label k=v (repeatable), --env K=V (repeatable), --idle-timeout 5m, --no-auto-pause, --always-on, --batch, --region auto\|eu-de\|eu-fi, --ttl 2h, --disk 100, --port 3000[:public] (repeatable), --no-wait |
POST /sandboxes |
list [--state s] [--label k=v] [--all] |
List sandboxes. Sandboxes in state deleted are hidden unless you pass --all or --state deleted; --all shows them only if the API still returns them. A guaranteed "recently deleted" view is coming soon. |
GET /sandboxes |
get <id> |
Show a sandbox | GET /sandboxes/{id} |
update <id> [flags] |
--name, --label k=v, --idle-timeout 15m, --no-auto-pause, --always-on, --no-always-on, --ttl |
PATCH /sandboxes/{id} |
pause <id> |
Pause (RAM + disk snapshot) | POST /sandboxes/{id}/pause |
resume <id> |
Resume | POST /sandboxes/{id}/resume |
fork <id> [--count N] [--name] [--label] |
Fork with memory. --count (-n) 1–50 creates N forks in one call, all or nothing; prints a table (-q: one ID per line, --json: array of sandboxes) |
POST /sandboxes/{id}/fork |
delete <id> [--yes] |
Delete permanently | DELETE /sandboxes/{id} |
Exec and terminals#
| Command | Description | API |
|---|---|---|
exec <id> [--cwd] [--env K=V] [--user] [--timeout 300] [--background] -- <cmd...> |
Run a command; streams output; exits with its exit code. --background prints the command ID. |
POST /sandboxes/{id}/exec |
commands list <id> |
Recent commands | GET /sandboxes/{id}/commands |
commands logs <id> <cmd_id> [--follow] |
Output of a command: replays earlier output, then follows until the command exits (the API has one replay-and-follow stream, so --follow currently changes nothing). Alias: taskcloud logs. |
GET .../commands/{cmd_id}/stream |
commands kill <id> <cmd_id> [--signal SIGKILL] |
Signal a command | POST .../commands/{cmd_id}/kill |
shell <id> [--user] [--cwd] |
Creates a PTY session and prints its websocket_url (valid 60 s until first connect). A built-in interactive terminal is coming soon; use taskcloud ssh meanwhile. |
POST /sandboxes/{id}/pty |
ssh <id> [--key file.pub] [--ttl 1h] [--user u] [--print] [-- ssh args] |
SSH via ssh.taskhost.cloud. Sends your local public key (default ~/.ssh/id_ed25519.pub, id_ecdsa.pub or id_rsa.pub) as a temporary key for this sandbox; nothing is stored on your account. --print only prints the command. |
POST /sandboxes/{id}/ssh |
Files#
| Command | Description | API |
|---|---|---|
cp <src> <dst> [-r] |
Copy local ↔ sandbox. Sandbox paths are <id>:/path. |
/files/upload, /files/content, /files/download |
files ls <id> <path> [-R] |
List | GET /sandboxes/{id}/files |
files cat <id> <path> |
Print a file | GET .../files/content |
files rm <id> <path> [-r] |
Delete | DELETE /sandboxes/{id}/files |
files watch <id> <path> |
Print change events | GET .../files/watch |
Networking and desktop#
| Command | Description | API |
|---|---|---|
port expose <id> <port> [--public] |
Public HTTPS URL | POST /sandboxes/{id}/ports |
port ls <id> / port rm <id> <port> |
List / remove | GET, DELETE .../ports |
token create <id> [--ttl 1h] [--port 3000] |
Access token for private ports | POST .../access-tokens |
ssh-key add <file.pub> / ssh-key ls / ssh-key rm <id> |
Account SSH keys | /ssh-keys |
desktop <id> [--ttl 10m] [--read-only] [--single-use] [--open] |
Desktop stream URL | POST /sandboxes/{id}/desktop |
screenshot <id> [-o shot.png] [--scale 0.5] [--format png\|jpeg] [--region x0,y0,x1,y1] |
Save a screenshot | GET .../screenshot |
input <id> '<actions JSON>' [-o after.png] [--coordinate-scale 0.5] |
Send mouse and keyboard actions: a JSON array of input actions (a single object also works; - reads stdin). -o saves a screenshot taken after the last action. |
POST .../input |
Snapshots and templates#
| Command | Description | API |
|---|---|---|
snapshot create <id> [--name] [--no-memory] |
Named snapshot | POST /sandboxes/{id}/snapshots |
snapshot ls [--sandbox <id>] / snapshot rm <snap_id> |
List / delete | /snapshots |
template create --name <n> (--image <ref> \| --snapshot <snap_id>) [--start-command] [--ready-check <cmd>] [--desktop] |
Create a template | POST /templates |
template ls / template logs <name> [--follow] / template rm <name> |
Manage templates | /templates |
Account#
| Command | Description | API |
|---|---|---|
key create --name <n> (--preset ci \| --scope exec ...) [--label k=v] [--sandbox <id>] [--expires 30d] |
Create an API key | POST /api-keys |
key ls / key rotate <id> / key revoke <id> |
Manage keys | /api-keys |
webhook create --url <url> --event sandbox.ready [--event ...] |
Create a webhook | POST /webhooks |
webhook ls / rm / rotate / test |
Manage webhooks | /webhooks |
usage [--group-by none\|sandbox\|day\|size\|label\|template] [--label-key customer] [--from] [--to] |
Usage and cost | GET /usage |
limits |
Plan, concurrency, rate limits | GET /limits |
spend-limit set <usd> [--on-limit pause_running\|block_new] / spend-limit clear |
Spend limit | PUT /account/spend-limit |
mcp [--read-only] [--tools a,b] |
Run the local MCP server on stdio (starts npx -y @taskcloud/mcp; needs Node.js and the published @taskcloud/mcp package, coming soon to npm) |
see MCP |
CI example#
taskcloud login --key-stdin <<< "$SANDBOX_API_KEY"
id=$(taskcloud create --template base --size large --batch --ttl 1h --json | jq -r .id)
trap 'taskcloud delete "$id" --yes' EXIT
taskcloud cp . "$id":/home/user/repo -r
taskcloud exec "$id" --cwd /home/user/repo --timeout 600 -- npm ci '&&' npm test
--batch halves the compute price; the sandbox may wait briefly in queued, and exec waits for it to start.