npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sanlabs/sanbox-cli

v0.0.15

Published

Run isolated Sanbox agent tasks from a terminal, CI job, or autonomous coding agent.

Readme

Sanbox CLI

Run isolated Sanbox agent tasks from a terminal, CI job, or autonomous coding agent.

Sanbox packages a task and selected inputs, starts an isolated runner, streams events, and keeps the sandbox and outputs indefinitely.

The full machine operating protocol is available at https://console.sanbox.cloud/agent.md and in web/public/agent.md.

Install

npm install -g @sanlabs/sanbox-cli@latest
latest_cli_version="$(npm view @sanlabs/sanbox-cli version)"
installed_cli_version="$(sanbox --version)"
test "$installed_cli_version" = "$latest_cli_version"

Always use the latest published CLI. CLI 0.0.15 adds Secret Proxy management, template grants, and run-scope inspection. Use --path or --all-paths to configure request scope and repeatable --secret-proxy options to select proxies during template creation. Grants check HTTPS access; --add-network-access explicitly adds missing host rules on port 443. Proxy details include run-ID attachment, timestamps, and granted template IDs. If setup fails after template creation, the CLI reports the existing template ID and recovery commands. See Secret Proxies. CLI 0.0.14 adds repeatable --allowed-model options when creating OpenCode Computer templates and sanbox run --model to select a configured same-provider model at startup. The selected model is saved on the run and reused on Resume; SDK per-prompt switching does not change that saved startup default. CLI 0.0.13 allows service templates to start without an initial task, including OpenCode Computers that are ready for later SDK steering, and supports Custom OpenAI Proxy providers when creating templates, including Browser Use templates. CLI 0.0.12 adopted the Stop, Resume, and Delete lifecycle, separates run state from execution outcome, retains scrubbed deleted-run tombstones, and adds administrator-confirmed template deletion. CLI 0.0.11 added OpenCode Computer templates and short-lived native SDK connections for HTTP, SSE streaming, and interactive steering. CLI 0.0.10 added per-run Hermes email and Telegram channels, Supabase user authorization, and removed the retired run-chat commands. CLI 0.0.9 added user login for private SSH access to supported running sandboxes. CLI 0.0.6 added Anthropic self-hosted environment inspection and administration.

Configure

For an interactive local terminal, sign in with your Sanbox account:

sanbox login

The CLI opens the console for approval, binds the session to one organization, and stores it in ~/.sanbox/credentials.json. The file is written atomically and limited to the current user on POSIX systems. Run sanbox logout to revoke and remove that session.

For non-interactive automation, continue to use an organization API key:

export SANBOX_API_URL=https://console.sanbox.cloud
export SANBOX_API_KEY=sbx_live_...
export SANBOX_TEMPLATE=<template-id-or-slug>

SANBOX_API_URL is optional for the hosted service. SANBOX_TEMPLATE can instead come from --template or .sanbox/config.json default_template. Organization API keys are for automation; they cannot open terminal or SSH sessions.

An org admin configures provider credentials and templates in the console. Do not pass provider keys to the CLI or a runner.

Connect An Anthropic Self-Hosted Environment

Create a self_hosted environment in Claude Console and generate its environment key. Then connect it to Sanbox:

export ANTHROPIC_ENVIRONMENT_KEY='<environment-key>'
sanbox anthropic-environments connect env_example --json
unset ANTHROPIC_ENVIRONMENT_KEY

sanbox anthropic-environments get env_example --json
sanbox anthropic-environments list --json

The environment key is read only from ANTHROPIC_ENVIRONMENT_KEY; there is no secret-bearing CLI flag. Connect, key replacement, and disconnect require an organization-admin user session or operator credential. Regular organization-scoped member keys can list and inspect connections.

Disconnecting requires explicit confirmation and preserves existing session-to-workspace mappings:

sanbox anthropic-environments disconnect env_example --force --json

Check Readiness

sanbox auth check --json
sanbox context --json
sanbox templates list --json
sanbox templates validate "$SANBOX_TEMPLATE" --json
sanbox doctor --json

Model IDs are provider-scoped. The CLI never guesses or silently substitutes a provider, model, or template. For waited task runs, choose a template with runnable: true, template_type: "runner", and runner_config.harness: "opencode" or "browser-use". OpenCode remains the default one-shot mode, while OpenCode Computer runs a retained private OpenCode server:

sanbox templates create \
  --name "OpenCode Computer" \
  --harness opencode \
  --mode computer \
  --model-provider openai \
  --model '<default-model-id>' \
  --allowed-model '<additional-model-id>'

Repeat --allowed-model to make more models from the same provider available for native OpenCode SDK prompt switching. The default --model is included automatically. At template creation, Sanbox checks that each ID is in the organization's saved provider catalog; it does not infer model compatibility or availability. Later catalog changes do not block Computer startup or resume, even if the default model disappears. Configured IDs remain registered, and model errors surface when a prompt uses them.

Choose a different startup model when creating an OpenCode Computer run:

sanbox run --template <computer-template-id> --model '<additional-model-id>' --json
sanbox run "Inspect the repository" --template <computer-template-id> --model '<additional-model-id>' --json

sanbox run --model accepts an exact ID from the template's configured models (allowed_model_ids), using the template's provider. Omit it to use the template default. The selection is saved on the run; sanbox runs resume <run-id> reuses it without another --model flag. Neither run creation nor SDK per-prompt switching changes the template default, and SDK switches do not update the run's saved startup model. This override is supported only for OpenCode Computer, not task or Hermes templates. An external_run_id retry with a different explicit model returns idempotency_conflict.

Existing templates keep their current names, IDs, slugs, and task behavior. Browser Use is for one-shot web tasks whose target domains are already approved. Hermes service templates are always-on. A Hermes template declares which optional channels its runs may activate:

sanbox templates create \
  --name "Customer assistant" \
  --harness hermes \
  --model-provider openai \
  --model '<model-id>' \
  --channel email \
  --channel telegram

Omit both --channel flags for a WebUI-only computer. Channel credentials never belong to the template.

Delete a template when it should no longer be available for new runs:

sanbox templates delete <template-id-or-slug> --force --json

Deletion preserves existing runs and retained sandboxes. It requires organization-admin access and --force so scripts cannot remove a template accidentally.

Create A Browser Use Template

Browser Use runs local headless Chromium inside the Firecracker sandbox. It requires OpenAI, Anthropic, Google Gemini, Hetzner Inference, or a Custom OpenAI Proxy and at least one explicit browser target:

sanbox templates create \
  --name "Web research" \
  --harness browser-use \
  --model-provider openai \
  --model '<model-id>' \
  --browser-domain example.com \
  --browser-domain '*.example.org' \
  --browser-max-steps 30 \
  --browser-step-timeout-seconds 120 \
  --browser-vision-mode auto \
  --browser-viewport 1280x720 \
  --browser-download-policy allow

Targets are limited to hostnames and leading wildcards on ports 80 and 443. The remaining browser security controls are fixed. Runs return browser-use-response.md, a sanitized run ledger, and any allowed downloads. Browser Use templates are one-shot agent executions.

Run Idempotently

Task templates require a positional task or --task. Service templates may omit it:

sanbox run "Review this repo and write output/report.md" \
  --input src/ \
  --dry-run \
  --json

sanbox run "Review this repo and write output/report.md" \
  --template "$SANBOX_TEMPLATE" \
  --external-run-id "<stable-project-task-id>" \
  --input src/ \
  --wait \
  --json

sanbox run \
  --template "<service-template-id>" \
  --external-run-id "<stable-service-id>" \
  --json

A taskless OpenCode Computer starts opencode serve without making an initial model call. A taskless Hermes service starts its gateways and waits for WebUI or configured channel messages. Supplying instructions starts the initial OpenCode task or seeds Hermes's persistent operating context, preserving the existing behavior.

Repeat --input for files, directories, or globs. The CLI excludes common secrets and applies .sanboxignore. --include is a deprecated compatibility alias.

For a Hermes template that allows email, optionally request an address from one of the AgentMail domains listed in the Sanbox console:

sanbox run "Handle customer email for this project" \
  --template "$SANBOX_TEMPLATE" \
  --email-address [email protected] \
  --json

--email-address is optional. When supplied, AgentMail must be connected and Sanbox does not generate a fallback address; use agentmail.to or one of the domains listed for the connected Pod.

For a Hermes template that allows telegram, pass the bot token and at least one numeric user ID on the run. Both values are optional unless the run needs Telegram:

sanbox run "Handle Telegram messages for this project" \
  --template "$SANBOX_TEMPLATE" \
  --telegram-bot-token '<telegram-bot-token>' \
  --telegram-allowed-user '<numeric-telegram-user-id>' \
  --json

You can set SANBOX_TELEGRAM_BOT_TOKEN instead of passing --telegram-bot-token. Do not use both.

For a long-running Hermes Computer that should act as one Supabase user, provide that user's Supabase Auth UUID. Sanbox automatically uses the organization's connected Supabase project:

sanbox run "Act as this user's procurement assistant" \
  --template "$SANBOX_TEMPLATE" \
  --external-run-id "hermes:<tenant-id>:<user-id>" \
  --supabase-user-id "<supabase-auth-user-uuid>" \
  --json

sanbox runs supabase authorize <run-id> --open

The run stays in awaiting_grant until the expected Supabase user approves the browser consent flow. Without --open, the authorize command prints the URL for copying into any browser. The callback lands on a Sanbox-hosted completion page, so a CLI demo does not need a customer web app. Customer integrations may use --return-url <https-url> when its origin matches the return origin configured on the organization Supabase connection.

Reuse the same external ID when retrying an ambiguous submission. To stream activity, replace --wait --json with --jsonl. Ctrl-C detaches without stopping unless --stop-on-interrupt is supplied.

Inspect And Recover

sanbox runs list --limit 50 --json
sanbox runs get <run-id> --json
sanbox runs events <run-id> --after-event-id <cursor> --json
sanbox runs watch <run-id> --after-event-id <cursor> --jsonl

Retrieve Outputs

Tasks should write durable deliverables under /workspace/output.

sanbox runs artifacts <run-id> --json
sanbox runs download <run-id> --output .sanbox/output/<run-id> --json
sanbox runs download <run-id> \
  --output .sanbox/output/<run-id> \
  --artifact report.md \
  --overwrite \
  --json

Downloads are path-safe and return their byte counts and SHA-256 digests. Existing files are preserved unless --overwrite is explicit.

Share A Running Filesystem

Create one read-only bearer URL for the running sandbox's entire root filesystem:

sanbox runs share <run-id> --expires 1h --json
sanbox runs shares <run-id> --json
sanbox runs unshare <run-id> <access-point-id> --json

The URL always starts at /; there is no root or output selector. Append a path to read an arbitrary ordinary file, or add ?format=json to a directory URL for agent-friendly navigation. The URL stops working when the exact sandbox session stops, the link expires, or it is revoked. It is shown only when created and must be handled as a bearer secret. See Live Filesystem Access for the HTTP contract and exclusions.

Stop, Resume, Or Delete A Run

sanbox runs get <run-id> --json
sanbox runs resume <run-id> --wait --json
sanbox runs share <run-id> --expires 1h --json
sanbox runs stop <run-id> --wait --json
sanbox runs delete <run-id> --yes --json

Stop terminates compute and durably syncs the workspace. It does not retain RAM, process state, or network connections. Resume fresh-boots the pinned runtime artifact with the retained workspace; it does not silently replay a completed task. state is the single run phase; inspect latest_execution.outcome for the last bounded execution outcome and workspace.saved_at for disk persistence proof. Stopped runs have no automatic TTL. Delete permanently removes the workspace after archiving usage. The control plane retains a scrubbed run tombstone, but normal CLI run listings exclude deleted runs.

SSH Into A Running Sandbox

sanbox login
sanbox ssh <run-id>

The run must be a currently running OpenCode run or Hermes Computer created from an SSH-capable artifact. The signed-in user must own the run or be an organization admin. The command uses your local OpenSSH client, but it does not expose the microVM on a public IP or port. The CLI generates a temporary Ed25519 identity, pins the microVM's runtime host key, and tunnels the SSH stream over a one-time authenticated WebSocket. The temporary key is deleted when the connection closes, and the saved user token is not passed to the OpenSSH child process.

OpenCode and Browser Use runs are one-shot agent executions. OpenCode Computer keeps its private server running so it can accept later steering; when an initial task is supplied, Sanbox submits it after the server becomes ready. A persisted task workspace can still be fresh-booted manually for inspection after the run stops.

Connect The OpenCode SDK

Create a short-lived connection for a currently running OpenCode Computer:

sanbox opencode connect <run-id> --expires 1h --json
sanbox opencode connections list <run-id> --json
sanbox opencode connections revoke <run-id> <connection-id> --json

The create response contains url, access_token, and connection metadata. The plaintext token is returned only once, but it can authenticate all OpenCode SDK requests and SSE reconnects until it expires, is revoked, or the runtime session ends. Multiple connections can coexist. Organization API keys use their existing organization role and require member access or higher; no additional API-key or connection-token scopes are introduced.

import { createOpencodeClient } from "@opencode-ai/sdk"

const client = createOpencodeClient({
  baseUrl: connection.url,
  headers: { Authorization: `Bearer ${connection.access_token}` },
})

const events = await client.event.subscribe()

Sanbox proxies the native HTTP and SSE API through its private Firecracker management path. The microVM never exposes an inbound port. Only security-sensitive OpenCode configuration, authentication, credential mutation, server-administration, raw PTY, and public-share routes are denied; core session, event, file, command, and session-shell APIs remain native. See OpenCode SDK access for the API and lifecycle contract.

Batch Work

[
  { "task": "Review API behavior and write output/api.md", "external_run_id": "review-api", "input": ["app/"] },
  { "task": "Review CLI behavior and write output/cli.md", "external_run_id": "review-cli", "input": ["cli/"] }
]
sanbox batch --tasks tasks.json --template "$SANBOX_TEMPLATE" --max-parallel 5 --wait --json

Batch fan-out is client-side. Keep the CLI process alive until all tasks are submitted.

Machine Output

Use --json for request/response commands and --jsonl for streams. Envelopes have schema_version, ok, command, context, data or error, and next_actions.

Exit codes are 0 for command success, 1 for local/API failure, 2 for readiness or waited remote failure, and 130 for a detached watcher.

Secret Proxies

Create a proxy from a JSON configuration and read its credential from stdin. For example, save this as proxy.json:

{
  "name": "customer-api",
  "host": "api.example.com",
  "authentication": { "type": "bearer" },
  "attach_run_id": true
}
sanbox secret-proxies create --file proxy.json --secret-stdin \
  --path /users --path /projects < token-file
sanbox secret-proxies get customer-api
sanbox secret-proxies update customer-api --path /users --if-revision 1

Repeat --path to select paths and their subpaths, or use --all-paths for the entire API. /users includes /users/42, but excludes /users-admin. /users/ includes descendants but excludes /users. Paths do not support wildcards.

These options replace all request rules and allow every supported HTTP method: GET, HEAD, POST, PUT, PATCH, DELETE, and OPTIONS. To retain method restrictions, supply request_rules in the JSON file without either path option. Creation requires an explicit path option or rules in the file. Updates accept --file, path options, or both, and require the current --if-revision. Names and hosts are immutable.

Grant a proxy to an existing template:

sanbox templates secret-proxies grant TEMPLATE_ID customer-api
sanbox templates secret-proxies grant TEMPLATE_ID customer-api --add-network-access

Grants check whether the host is allowed on HTTPS port 443. Missing or partial access produces a warning and does not prevent the grant. IP/CIDR rules are reported as DNS-dependent when hostname access cannot be confirmed. --add-network-access explicitly adds missing host rules on port 443, preserving existing custom rules and descriptions. Managed provider and harness rules remain server-owned.

Select proxies while creating a template with repeatable --secret-proxy:

sanbox templates create --name "Customer support" \
  --model-provider openai --model MODEL_ID \
  --secret-proxy customer-api --secret-proxy billing-api \
  --add-network-access

Proxy names and IDs are resolved before creation. Network changes and grants are separate operations after the template is created. If setup fails, the CLI exits with an error, reports the existing template ID, and provides grant commands to finish setup. Successful grants and network changes remain saved. Use those recovery commands instead of creating another template.

secret-proxies get shows path scope, run-ID attachment, Created/Updated timestamps, and granted template IDs. With --json, grant results include data.network_access; template creation includes data.secret_proxies. Each network check includes its status, whether a rule was added, and any warning. Incomplete setup reports granted/pending proxy IDs under error.details and recovery commands under next_actions.

There is no enable or test step. Grants and configuration edits apply on the next start or resume. Inspect run scope with sanbox runs secret-proxies RUN_ID. Credentials are never accepted in command-line arguments or JSON configuration. See Secret Proxies for runtime behavior, rotation, and deletion.