# CLI Reference (https://tenki.cloud/docs/sandbox/cli)

> For the complete documentation index, see [llms.txt](https://tenki.cloud/llms.txt)

Command reference for the `tenki` CLI covering authentication, session lifecycle, command execution, file transfer, port exposure, SSH, persistent volumes, and snapshots.



The `tenki` CLI drives sandboxes from the terminal. Every sandbox command lives under `tenki sandbox`, with `tenki sbx` available as a shorter alias.

Most session commands take a `--session <session-id>` flag. Set a current session once with `tenki sandbox set <session-id>` and you can omit `--session` on the commands that follow.

This page documents the commands used across the Sandbox docs. For the authoritative, always-current flag list, run `tenki sandbox --help` (or `--help` on any subcommand).

Authentication [#authentication]

```bash
# Interactive browser sign-in (stores the session, auto-selects a workspace/project)
tenki login

# Headless: print the sign-in URL instead of opening a browser
tenki login --no-browser

# Sign in with an API key (no browser), recommended for CI
tenki login --api-key tk_your_api_key

# Confirm you are signed in
tenki status

# Print the CLI version
tenki --version
```

The CLI and all SDKs also read credentials from the environment:

* `TENKI_API_KEY`: API key (tokens starting with `tk_` are sent as `Authorization: Bearer <token>`)
* `TENKI_API_URL`: override the API endpoint (defaults to `https://api.tenki.cloud`)

Sessions [#sessions]

create [#create]

Create a session and, by default, wait for it to reach `RUNNING` before printing the session ID.

```bash
tenki sandbox create --name demo --cpu 2 --memory-mb 4096
```

* `--name <name>`: human-readable session name
* `--cpu <cores>`: vCPU cores
* `--memory-mb <mb>`: memory in MB
* `--disk-size-gb <gb>`: root disk size in GB
* `--allow-inbound`: enable inbound exposure (preview URLs)
* `--allow-outbound`: allow the guest to make outbound network calls
* `--metadata <key>=<value>`: attach metadata (repeatable)
* `--env <key>=<value>`: set a guest environment variable (repeatable)
* `--tags <tag>`: freeform tags for filtering (repeatable, or comma-separated; not `key=value`)
* `--authorized-key <key>` / `--authorized-keys-file <path>`: SSH public keys to install in the guest
* `--volume <volume-id>:<mount-path>[:ro]`: attach a persistent volume at a mount path (append `:ro` for read-only)
* `--snapshot <snapshot-id>`: start from a snapshot instead of a fresh image
* `--image <ref>`: start from a published registry image, `<workspace>/<artifact>[:tag]` (mutually exclusive with `--snapshot`)
* `--max-duration <duration>`: hard cap on the session's lifetime
* `--idle-timeout <duration>`: terminate the session after it sits idle this long
* `--pause-retention <duration>`: how long a paused session's state is retained
* `--sticky`: keep the session alive until it is explicitly terminated
* `--no-wait`: return immediately instead of waiting for `RUNNING`
* `--wait-timeout <duration>`: how long to wait for `RUNNING` before giving up

```bash
# From a snapshot, with a cache volume mounted
tenki sandbox create --snapshot <snapshot-id> --volume <volume-id>:/workspace/cache

# With metadata
tenki sandbox create --metadata owner=alice --metadata job=ci-1234
```

set [#set]

Persist a session as the current one so later commands can omit `--session`.

```bash
tenki sandbox set <session-id>
```

list [#list]

List sessions. Add `--json` for machine-readable output.

```bash
tenki sandbox list
tenki sandbox list --json
```

get [#get]

Inspect a single session.

```bash
tenki sandbox get --session <session-id>
tenki sandbox get --session <session-id> --json
```

exec [#exec]

Run a command inside a session.

```bash
# Through a shell (pipes, redirects, globs, $VAR, && and & all work)
tenki sandbox exec --session <session-id> -c 'npm ci && npm test'

# Run a program directly, with no shell
tenki sandbox exec --session <session-id> -- go test ./...
```

* `-c, --shell <line>`: run the line through a shell
* `--`: pass the remaining arguments to the program directly (no shell)
* `--timeout <duration>`: command timeout (e.g. `2m`, `5m`)

Streamed stdout and stderr print live, followed by the final status, exit code, and duration.

write / read [#write--read]

Move files in and out of the session. Paths are rooted in the working directory `/home/tenki`; `/workspace/...` paths exist only where a volume is mounted.

```bash
# Write from inline data, a local file, or stdin
tenki sandbox write --session <session-id> --path /home/tenki/app.env --data 'PORT=3000'
tenki sandbox write --session <session-id> --path /home/tenki/config.json --data-file ./config.json
echo 'hello sandbox' | tenki sandbox write --path hello.txt

# Read to stdout, or save to a local file with --out
tenki sandbox read --session <session-id> --path /home/tenki/config.json
tenki sandbox read --session <session-id> --path /home/tenki/build.log --out ./build.log
```

expose / unexpose / ports [#expose--unexpose--ports]

Expose a guest port through a preview URL, list exposed ports, and remove an exposure.

```bash
tenki sandbox expose --session <session-id> --port 3000
tenki sandbox ports --session <session-id>
tenki sandbox unexpose --session <session-id> --port 3000
```

ssh [#ssh]

Open an SSH session, forward a port, or manage local SSH config and authorized keys.

```bash
# Open a shell
tenki sandbox ssh --session <session-id>

# Forward a local port to the guest
tenki sandbox ssh <session-id> -L 8080:127.0.0.1:8080

# Managed SSH config
tenki sandbox ssh config install
tenki sandbox ssh config status
tenki sandbox ssh config uninstall

# Set the guest's authorized keys
tenki sandbox ssh-keys set --session <session-id> --keys-file ~/.ssh/authorized_keys
```

pause / resume [#pause--resume]

Pause a session to free compute while preserving its files and memory, then resume it later.

```bash
tenki sandbox pause --session <session-id>
tenki sandbox resume --session <session-id>
```

terminate [#terminate]

Tear a session down.

```bash
tenki sandbox terminate --session <session-id>
```

Volumes [#volumes]

Persistent volumes are workspace-scoped and survive session termination. Volume commands require a workspace ID (find it with `tenki status` or the SDK's identity call).

```bash
# Create
tenki sandbox volume create --workspace <workspace-id> --name npm-cache --size 20GB

# List, inspect, resize, delete
tenki sandbox volume list --workspace <workspace-id>
tenki sandbox volume list --workspace <workspace-id> --json
tenki sandbox volume get <volume-id>
tenki sandbox volume resize <volume-id> --size 40GB
tenki sandbox volume delete <volume-id>

# Attach to / detach from a running session
tenki sandbox volume attach <session-id> <volume-id> --mount /workspace/cache
tenki sandbox volume attach <session-id> <volume-id> --mount /workspace/reference --readonly
tenki sandbox volume detach <session-id> <volume-id>
```

* `--workspace <workspace-id>`: target workspace (required for create/list)
* `--name <name>`: volume name
* `--size <size>`: size, accepts units (`20GB`, `10GiB`) or a plain MiB number (`1024`)
* `--mount <path>`: mount path when attaching
* `--readonly`: mount read-only

To attach a volume at create time instead, use `tenki sandbox create --volume <volume-id>:<mount-path>[:ro]`.

Snapshots [#snapshots]

Capture a point-in-time VM snapshot, then restore it later as a new session.

```bash
# Create from a running session (waits for READY by default)
tenki sandbox snapshot create --session <session-id> --name baseline
tenki sandbox snapshot create --session <session-id> --name with-strace --wait-timeout 10m

# List, inspect, delete
tenki sandbox snapshot list
tenki sandbox snapshot list --json
tenki sandbox snapshot get <snapshot-id>
tenki sandbox snapshot delete <snapshot-id>

# Restore as a new session
tenki sandbox snapshot restore <snapshot-id> --name restored-copy
```

* `--session <session-id>`: source session for `create`
* `--name <name>`: name for the snapshot or the restored session
* `--wait-timeout <duration>`: how long `create` waits for the snapshot to become `READY`

Snapshots capture VM state, not attached volumes, so reattach volumes explicitly when you restore. You can also create a session from a snapshot with `tenki sandbox create --snapshot <snapshot-id>`.

Templates [#templates]

A template is a reusable definition of a prepared environment. Build it once, publish it to the registry, then create sessions from the published reference. See [Templates](/docs/sandbox/templates) for the full workflow.

```bash
# Define a template (only --name and --setup-script are required)
tenki sandbox template create \
  --name my-node-env \
  --setup-script 'curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs' \
  --start-cmd 'node --version' \
  --env NODE_ENV=production

# Build it and wait for READY
tenki sandbox template build <template-id> --wait

# List, inspect, update, delete
tenki sandbox template list
tenki sandbox template get <template-id>
tenki sandbox template update <template-id> --start-cmd 'node server.js'
tenki sandbox template delete <template-id>
```

* `--name <name>`: template name (required for `create`)
* `--setup-script <script>`: shell script run at build time (required for `create`)
* `--start-cmd <cmd>`: command run when a session from the template starts
* `--env <key>=<value>`: environment variable (repeatable)
* `--cpu <cores>` / `--memory-mb <mb>` / `--disk-size-gb <gb>`: default resources for sessions built from the template
* `--tags <tag>`: freeform tags for filtering (repeatable)
* `--workspace <workspace-id>` / `--project <project-id>`: scope the template

`template build` takes `--wait` (block until `READY`, default 15m), `--wait-durable` (also wait for the snapshot upload), and `--wait-timeout <duration>`.

Registry [#registry]

The registry is a per-workspace namespace of publishable artifacts (templates or snapshots). Publishing gives an artifact a reference, `<workspace>/<artifact>[:tag]`, that `create --image` accepts.

```bash
# Publish a template (or a snapshot) as a named, versioned artifact
tenki sandbox registry publish \
  --image myworkspace/my-node-env:latest \
  --from-template <template-id> \
  --visibility private

# Browse and resolve artifacts
tenki sandbox registry list
tenki sandbox registry list --kind template
tenki sandbox registry get <workspace>/<artifact>
tenki sandbox registry resolve <workspace>/<artifact>:latest

# Create a session from a published reference
tenki sandbox create --image myworkspace/my-node-env:latest
```

* `--image <ref>`: the artifact reference to publish, `<workspace>/<artifact>[:tag]` (required)
* `--from-template <id>` / `--from-snapshot <id>`: the source to publish (exactly one)
* `--visibility <private|public|shared>`: who can pull the artifact (default `private`)
* `--label <label>` / `--title <title>` / `--description <text>`: optional metadata

Grant cross-workspace access with `tenki sandbox registry share --target-workspace <workspace-id>`; remove it with `unshare` or `share-revoke-grant`.
