Sandbox

CLI Reference

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

# 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

create

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

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
# 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

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

tenki sandbox set <session-id>

list

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

tenki sandbox list
tenki sandbox list --json

get

Inspect a single session.

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

exec

Run a command inside a session.

# 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

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.

# 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 a guest port through a preview URL, list exposed ports, and remove an exposure.

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

ssh

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

# 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 a session to free compute while preserving its files and memory, then resume it later.

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

terminate

Tear a session down.

tenki sandbox terminate --session <session-id>

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).

# 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

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

# 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

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 for the full workflow.

# 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

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.

# 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.

LinkedIn