Sandbox CLI (v2) (Beta)
Every cofactor sandbox command for Sandboxes v2: what it does, its flags, and what its JSON output contains.
All Sandboxes v2 commands live under cofactor sandbox. The same command group also holds the older Sandboxes (Beta) commands (create, provision, logs, diagnostics and others); this page covers only the v2 ones.
| Command | What it does |
|---|---|
validate | Check a cofactor.sandbox.yaml offline |
connect | Build an application's sandboxes from a GitHub repository |
push | Push a built image as the application's next version |
envs | What an application's sandboxes offer |
claim | Claim a sandbox |
show | A sandbox's status, URLs, logins and seed outputs |
run | Run an action or emulator operation on a sandbox |
destroy | Tear a sandbox down |
verify-env | Prove each environment's seed chain runs, end to end |
preview | A pull request's preview and its logins |
guide v2 | Print the built-in Sandboxes v2 guide |
01Common flags
--application <name|id>names the application (case-insensitive name, or id).--propertyis accepted as an alias. Required byconnect,push,envs,claim,verify-envandpreview.--environment <name>is a sandbox environment from the definition (default,free-plan…).--env <dev|prod>is the CLI's global flag for which Cofactor to talk to. It has nothing to do with a sandbox's environment, which is always--environment.--jsonprints machine-readable output on stdout (progress, where there is any, goes to stderr). Accepted by every command exceptdestroy.- The other global flags (
--org,--token,--api-url) work as on every command. See Command reference.
connect, push, envs, claim, show, run, verify-env and destroy refuse any argument they don't take, rather than ignoring it: a quoted "--at pr-12" is an error, not a claim of the newest version. validate, preview and guide v2 don't check for unknown arguments.
validate and guide v2 run offline with no login. Every other command needs a logged-in session or an API key; the sandbox scope table lists what each needs.
02The core loop
cofactor sandbox validate [--upload] # check the definition cofactor sandbox push --application A <image> --wait # or: connect, once cofactor sandbox envs --application A # what's there cofactor sandbox claim --application A --environment E --wait # get a sandbox cofactor sandbox run <id> <action> --input k=v # as many times as the test needs cofactor sandbox destroy <id> # always
03validate
cofactor sandbox validate [file] [--upload] [--json]
Offline schema check and cross-check of a definition. No sandbox, no login.
| Argument / flag | Meaning |
|---|---|
file | The definition. Default: ./cofactor.sandbox.yaml. |
--upload | Check it as a definition for pushed images (no setup, no lifecycle.build, no after_build). Without it, as one built from a GitHub checkout (setup and lifecycle.build required). |
--json | Print { ok, issues }. |
On success it prints the counts of environments, actions and emulator operations. On failure it prints one path: message line per issue and exits 1. See Sandbox definition for every rule.
JSON output:
{ "ok": false, "issues": [{ "path": "environments.default.seeds[0].action", "message": "unknown action \"create-workspce\"" }] }
04connect
cofactor sandbox connect --application <name|id> --repo <owner/name> [--dir <path>] [--json]
Builds the application's sandboxes from a GitHub repository: the cofactor.sandbox.yaml under --dir at each commit. Requires GitHub to be connected to your organization.
| Flag | Meaning |
|---|---|
--repo | The repository, owner/name. Required. |
--dir | The definition's directory, relative to the repository root, with no leading or trailing / and no ... Default: . (the root). |
connect reads the definition at the default branch's head and saves nothing unless it exists and is valid (invalid definitions print their issues). Then the definition's environments become the application's sandbox environments and its personas the application's personas. Each repository directory belongs to at most one application.
Output: the same as envs.
05push
cofactor sandbox push --application <name|id> <image> [--definition <file>] [--tag <tag>]... [--wait] [--json]
For an application that gives Cofactor no repository access: pushes a locally built image, with its definition, as the application's next version.
| Argument / flag | Meaning |
|---|---|
image | A local Docker image (name:tag or id). It must be linux/amd64, with a WORKDIR other than /. Required. |
--definition | The definition to push with the image. Default: ./cofactor.sandbox.yaml. Validated as for validate --upload before anything is uploaded. |
--tag | Name this push. Repeatable, up to 10. Letters, digits, ., _ and -, at most 64 characters, starting with a letter or digit. A tag always names the newest ready push carrying it. Also accepted as --tag=<tag>. |
--wait | Wait until Cofactor has imported the image: booted it until every service is healthy. It waits up to 50 minutes; if the import is still going then, push prints the push as importing and exits 0 (follow it with envs). Without --wait, push returns once the upload completes. |
What it does: validates the definition, reads the image's config (platform, WORKDIR, ENV), saves the image from local Docker, adds Cofactor's sandbox helper (and the declared object storage server) plus a small layer with your definition, and uploads only the layers Cofactor doesn't already have for your organization. It prints how many blobs and bytes it sent and how much Cofactor already had. Docker must be installed and running.
Pushing to an application connected to GitHub fails: that application takes no pushed images. The first push to an application with no sandbox setting makes it a pushed-image application.
Exit status: non-zero if the push failed (with the reason, such as a service's log when the image could not start).
JSON output (the push, plus what was uploaded):
| Field | Meaning |
|---|---|
id | The push id, a version you can claim with --at. |
status | uploading, importing, ready or failed. With --wait, ready or failed, or still importing if the 50-minute wait ran out. |
tags | The push's tags. |
error | Why it failed, or null. |
createdAt | When the push was created. |
uploaded.blobs | How many blobs were uploaded. |
uploaded.of | How many blobs the image has in all. |
uploaded.bytes | Bytes uploaded. |
uploaded.reusedBytes | Bytes Cofactor already had. |
See Sandboxes from a pushed image.
06envs
cofactor sandbox envs --application <name|id> [--json]
The application's delivery (GitHub or pushed images), its current version, recent pushes, its sandbox environments, and what its definition offers at that version: every environment (description, seeds), actions, emulator operations (with their schemas), personas and ports. This is what an agent reads to decide which environment to claim and how to call each action.
An application with pushes but none ready yet shows no version and no definition.
JSON output:
| Field | Meaning |
|---|---|
applicationId | The application's id. |
delivery | github or upload (pushed images). |
repo, definitionDir | The connected repository and directory (GitHub), else null. |
sandboxEnvironments[] | The application's environments created from the definition: id, name (as shown in Cofactor) and environment (the definition's name). |
pushes[] | Pushed images only: the newest 10 pushes (id, status, tags, error, createdAt). null for GitHub. |
version | The current version: a commit SHA, or a push id. null before the first push is ready. |
definition.environments[] | name, description, extends (or null), seeds[] (id, action, input) and envKeys (the names its env: sets). |
definition.actions[] | slug, description, input, output and timeout, as declared. |
definition.operations[] | Emulator operations: name (<plugin>.<op>), description, inputSchema, outputSchema (JSON Schema). |
definition.personas | Persona names. |
definition.ports[] | name and access, the implicit emulation and object-storage ports included. |
definition.emulation | Declared emulation plugin ids. |
07claim
cofactor sandbox claim --application <name|id> [--environment <name>] [--at <version>] [--wait] [--json]
Claims a sandbox: a fresh copy of the ready snapshot for the version and environment, given its own URLs and persona logins by prepare. If that snapshot doesn't exist yet, it is built first (build, prepare, seeds), once, however many claims are waiting on it.
| Flag | Meaning |
|---|---|
--environment | The environment to claim. Default: default. |
--at | The version. GitHub: a full 40-character commit SHA. Pushed images: a push id or a tag. Default: for GitHub, the default branch's current ready snapshot of the environment (else its head); for pushes, the newest ready push. |
--wait | Block until the sandbox is ready or failed (up to 30 minutes), then print it as show does. Without it, print the claim id and return. |
Exit status: non-zero if the claim fails, or with --wait if the sandbox ends failed. A sandbox you stopped waiting for is still yours: show or destroy it.
JSON output: without --wait, { "id": "<sandbox id>" }. With --wait, the same object as show.
Destroy every sandbox you claim when you're done with it.
08show
cofactor sandbox show <id> [--json]
A sandbox's current status, per-port URLs, persona logins (decrypted: this is where they are meant to be read from), seed outputs, how long it took to become ready, when it expires, and the actions and operations you can run on it.
JSON output:
| Field | Meaning |
|---|---|
id, applicationId, applicationName | The sandbox and its application. |
environment | The environment it was claimed on. |
version | The commit SHA or push id it runs. |
status | claiming, ready, failed or destroyed. |
error | Why it failed (which step, its action, and the script's stderr), or null. |
portUrls | Port name → URL. |
personas[] | name, email and password of each persona. |
seedOutputs | Seed step id → its output object. The same for every copy of a snapshot. |
leaseExpiresAt, expired | When the sandbox's lease ends, and whether it already has. |
readyMs | Milliseconds from claim to ready. |
phases | snapshotMs (waiting for the ready snapshot), restoreMs (restoring the copy), prepareMs (preparing it). Set once ready. |
snapshot | The ready snapshot it's a copy of: builtAt, and buildPhases (buildMs, the build steps that ran with their times, prepareMs, and each seed step's id, action and ms). null once the snapshot is gone. |
actions[], operations[] | As in envs. |
The output holds working passwords. Don't paste it anywhere public.
09run
cofactor sandbox run <id> <action|plugin.op> [--input key=value]... [--json-input '{...}'] [--json]
Runs a definition action, or an emulator operation (named <plugin>.<op>, such as email.sent-emails), on a ready sandbox, waits for it, and prints its output.
| Flag | Meaning |
|---|---|
--input key=value | One input. Repeatable (also --input=key=value). The value is coerced to the declared type: integer and number must parse as numbers, boolean must be true or false, string and persona pass as written. An unknown key is an error that lists the known ones. |
--json-input '{...}' | The whole input as a JSON object. Overrides --input. |
Invalid input (a missing required input, a wrong type, a value outside enum, an undeclared persona) prints the issues and the action's or operation's input schema, and runs nothing. The CLI waits for the action's timeout plus a minute.
Output: on success, the action's output object. On failure, the error and the script's stderr, with exit status 1.
JSON output (the run):
| Field | Meaning |
|---|---|
id, sandboxId | The run and its sandbox. |
action | The action or operation name. |
seedStepId | The seed step this run was, or null for a call you made. |
input | The input, with sensitive values masked. |
status | running, succeeded or failed. |
output | The result object, or null. |
exitCode | The script's exit code, or null. |
stdoutTail, stderrTail | The end of the script's stdout and stderr. |
error | Why it failed, or null. |
durationMs, createdAt, completedAt | Timing. |
See Seeds and actions.
10destroy
cofactor sandbox destroy <id>
Tears the sandbox down. Always do this when a claimed sandbox is no longer needed. Prints Sandbox <id> destroying.
11verify-env
cofactor sandbox verify-env --application <name|id> [--environment <name>] [--json]
For each environment of the current version (or only the one named): claim, wait for ready, print every seed step's output and the time it took, then destroy. Environments are verified one at a time. This is the end-to-end proof that an environment's seed chain actually runs, where validate only proves it's well-formed.
It ends with a summary table (Environment, Result, Seconds) and exits 1 if any environment failed. A sandbox that failed or timed out is still destroyed.
JSON output: progress goes to stderr; stdout carries an array of { environment, ok, seconds, error? }.
12preview
cofactor sandbox preview --application <name|id> --pr <number> [--json]
A pull request's preview of a GitHub-delivered application: its status, commit, URLs, expiry, and the persona logins its pull request comment deliberately leaves out.
JSON output:
| Field | Meaning |
|---|---|
applicationId, prNumber | The application and pull request. |
status | queued, building, ready, failed or destroyed. |
headSha | The pull request's head commit. |
appliedSha | The commit the preview currently runs, or null. Differs from headSha while a newer push is building. |
portUrls | Port name → URL. |
personas[] | name, email, password. |
error | Why the last update failed, or null. |
readyMs | How long the last update took. |
leaseExpiresAt | When the preview's lease ends. |
13guide v2
cofactor sandbox guide v2 [topic] [--json]
Prints the built-in Sandboxes v2 guide: every topic, or just one. Topics: overview, definition, environments, seeds-and-actions, personas, env, emulation, object-storage, ports, upload, verify, cli. For pushed images, start with cofactor sandbox guide v2 upload. Plain cofactor sandbox guide prints the older Sandboxes (Beta) guide.
14API key scopes
With an API key, each command needs these sandbox scopes. Every command that takes --application also needs property:read: the CLI lists your applications to resolve it, even when you pass an id.
| Command | Scopes |
|---|---|
validate, guide v2 | None (offline) |
envs, show, preview | sandbox:read |
connect | sandbox:edit |
push | sandbox:read, sandbox:publish |
claim | sandbox:create; with --wait, also sandbox:read |
run | sandbox:read, sandbox:run |
destroy | sandbox:delete |
verify-env | sandbox:read, sandbox:create, sandbox:delete |
sandbox:read includes the sandboxes' persona logins.