sark

CLI scripts

The three scripts you actually run, and what each one proves.

npm run devwrangler dev on :8787
npm run deploywrangler deploy
npm run typechecktsc --noEmit
npm testboth vitest projects
npm run dev-varsgenerate .dev.vars
npm run smokeverify Box credentials and template
npm run drivedrive a thread end to end

The three Node scripts read .dev.vars themselves (via scripts/env.ts), and an environment variable always wins over the file.

drive: talk to a thread

npm run drive -- --thread demo "create hello.txt with the word banana"
npm run drive -- --thread demo "what was in that file?"   # same thread => same sandbox
npm run drive -- --thread demo --stop                     # archive the sandbox
npm run drive -- --url https://<your-worker>.workers.dev --thread demo "hello"
Flag
--thread <id>Thread id. Defaults to a random cli-xxxxxx. Same id = same sandbox.
--url <origin>Worker origin. Defaults to $WORKER_URL, then http://localhost:8787.
--stopDELETE the thread: archive the sandbox and clear session state.

Everything after the flags is the message text.

It sends the prompt, then polls state and messages every 2s, printing:

  • phase transitions to stderr, as [starting_box box_7f21a9];
  • new messages to stdout;
  • edited messages marked (edited), because the status message is updated in place and the watchdog fallback lands there rather than as a new message.

It exits when the phase is idle with no active prompt, non-zero if lastError is set or after a 15-minute timeout.

user is sent as cli and userName as $USER, so the agent sees who ran it.

smoke: prove Box access

npm run smoke
TEMPLATE_BOX_ID=box_… npm run smoke
KEEP=1 npm run smoke              # leave the box running

Talks to the Box API directly: no Worker, no Slack, no MCP. If this fails, nothing downstream will work, and the failure is not a Worker problem.

It forks your template (or creates a fresh box), waits up to 180s for it to become usable, runs whoami && pwd && which claude codex, sends a real prompt, waits up to 300s for it to finish, prints the last few response events, reads back the file the agent was asked to write, then stops the box unless KEEP=1.

Honours BOX_API_KEY, BOX_BASE_URL, TEMPLATE_BOX_ID, and BOX_PROVIDER from the environment or .dev.vars.

dev-vars: generate local secrets

npm run dev-vars

Writes .dev.vars with BOX_API_KEY copied out of the box CLI's own config and freshly generated MCP_TOKEN_SECRET / API_TOKEN. No secret is ever typed, pasted, or echoed.

It refuses to overwrite an existing .dev.vars, so delete it first to regenerate. Needs jq and openssl. Details in Install.

deploy: ship it with your own settings

npm run deploy            # reads .deploy.env, injects it as wrangler overrides
npm run deploy -- --dry-run

Anything after -- is passed straight to wrangler deploy. WORKER_NAME and PUBLIC_URL are required; the rest are optional and simply left at whatever wrangler.jsonc says, which for the allowlists is empty and therefore fails closed.

tail and dev: target your own worker

npm run tail              # live logs from your deployed worker
npm run dev               # local dev server on :8787

Both read WORKER_NAME from .deploy.env. Calling npx wrangler tail directly looks up the placeholder name in wrangler.jsonc and fails with "This Worker does not exist on your account" (code 10007).

check-config: keep the template clean

npm run check-config

Fails if a real origin, a non-empty allowlist, an account_id, or a literal Slack/Box id reaches the tracked wrangler.jsonc. It reads the staged copy, so editing the file locally is fine — only committing it is not. Runs in CI, and works as a pre-commit hook:

ln -s ../../scripts/check-config-clean.sh .git/hooks/pre-commit

Curl, if you'd rather

Everything drive does is six routes. See the Control API.

API_TOKEN=$(grep '^API_TOKEN=' .dev.vars | cut -d= -f2)

curl -sX POST localhost:8787/api/threads/t1/prompt \
  -H "Authorization: Bearer $API_TOKEN" -H 'content-type: application/json' \
  -d '{"text":"run the tests"}'

curl -s localhost:8787/api/threads/t1 -H "Authorization: Bearer $API_TOKEN"

On this page