
Skill
upstash-box-cli
manage remote sandboxed workspaces with Upstash
Description
Drive an Upstash Box (a remote sandboxed workspace) from the terminal with the `box` CLI. Use when asked to run commands, edit files, clone repos, run builds or tests, publish a public URL, or do any work inside a box rather than on this machine.
SKILL.md
box operates on a remote container, not this machine. Your own file and shell
tools act locally; anything that must happen inside the box goes through box.
Install
npm i -g @upstash/box-cli
Authentication
Every command needs an API key, or it fails with "API token required". Set it once,
or pass --token on any single command. Create one at
https://console.upstash.com/box.
export UPSTASH_BOX_API_KEY=box_...
Selecting a box
Resolution order is --box <id>, then $BOX_ID, then the nearest .box file
(searched upward). Create one and pin it to the working directory:
box create --no-repl --runtime node # prints the id, writes .box
box create --no-repl --runtime node --clone-repo https://github.com/org/repo
box status # id, where it came from, state
paused is not an error; the next command resumes the box.
Clean up when the work is done. Boxes cost money while they exist:
box pause # keeps the workspace, resumes on the next command
box delete --yes # irreversible; --yes is required without a terminal
Never run box create without --no-repl, or box connect / box from-snapshot:
they open an interactive REPL and will hang.
Running commands
Put the remote command after --, or its flags are parsed as box's own.
box exec -- npm install
box exec -C repo -- npm test
box exec --json -- node -e 'console.log(1)' # {stdout, stderr, exit_code}
One argument is a shell expression, sent as written, so pipes and redirection work. Several arguments are argv and are quoted individually, so an argument containing spaces stays one argument.
The remote command's exit code is passed through, so box exec -- npm test && ...
chains normally. Exit code 125 means the CLI itself failed (bad box, bad flags),
never a status the remote command returned.
A background server dies with the command that started it. Detach it:
box exec -- '( npm run dev > dev.log 2>&1 & )'
box public-url 3000 # prints the public URL
Building something and handing back a link
"Make me a snake game, use Upstash Box" is a request to build it in a box, run it there, and reply with a URL the user can open. Do the whole thing; do not stop at writing the file.
box create --no-repl --runtime node # writes .box, so later commands need no --box
box files write index.html - <<'HTML'
<!doctype html><meta charset="utf-8"><title>Snake</title>
<canvas id="c" width="400" height="400"></canvas>
<script>/* the game */</script>
HTML
box files write server.js - <<'JS'
const http = require("http"), fs = require("fs");
http.createServer((_, res) => {
res.writeHead(200, { "Content-Type": "text/html" });
res.end(fs.readFileSync("index.html"));
}).listen(3000);
JS
box exec -- '( node server.js > server.log 2>&1 & )' # detached, or it dies
box exec -- 'sleep 1; curl -sf localhost:3000 >/dev/null && echo up'
box public-url 3000 # the link to reply with
Node's own http module rather than a package: no install, no network fetch, and it
works on a bare node runtime.
Check the port answers before publishing it. A public URL for a port nothing is listening on returns 502, which reads as a broken game rather than as a race with a server that had not finished starting.
Reply with the URL itself, not just "it is running". Say that the box keeps costing
money until box delete --yes, and that the URL is public to anyone who has it —
box public-url 3000 --basic-auth puts credentials in front of it.
Files
Paths are relative to /workspace/home.
box files list src
box files read src/index.ts
box files write src/app.ts - < local.ts # - reads stdin: use this for code
box files write notes.txt "short text"
box files stat src/index.ts
box files mkdir -p a/b/c
box files rename old.ts new.ts
box files remove build -r # a directory needs -r
box files upload ./local.zip /workspace/home/local.zip
box files download repo
Write code with - and stdin. Passing source as an argument mangles it in the shell.
To search, use the box's own tools: box exec -- grep -rn TODO src.
Git
A clone lands in a directory named after the repo, and every git verb except clone
needs that directory via -C. Without it git runs at the workspace root, which is not
a repository.
box git clone https://github.com/org/repo
box git clone https://github.com/org/repo -C my-app # -C is the destination here
box git status -C repo
box git diff -C repo
box git config -C repo --name "Bot" --email bot@example.com
box git checkout -C repo feature/x # creates the branch if missing
box git exec -C repo -- add -A
box git commit -C repo -m "message"
box git push -C repo
box git create-pr -C repo --title "Fix the thing" --base main
box git exec takes git's arguments without the leading git, and passes git's exit
code through.
Private repos and PRs need a token at creation: box create --no-repl --git-token $GITHUB_TOKEN.
Agent
If the box was created with an agent, hand it a task:
box create --no-repl --agent-harness claude-code --agent-model anthropic/claude-sonnet-5
box run "Fix the failing test in src/auth.test.ts"
box run - < prompt.txt
Text goes to stdout, tool calls to stderr. Prefer doing the work yourself with the
commands above; box run is for delegating a whole task to the box's own agent.
Output
Data goes to stdout, diagnostics to stderr, so piping is safe. --json prints the
result as JSON with no wrapper, on every command that returns data. The ones that
open a REPL or print a shell script (connect, from-snapshot, init-demo,
completion) reject it rather than answering an automation caller with a prompt:
box files list --json | jq -r '.[].name'
box get "$(cat .box)" --json
More skills from the skills repository
View all 8 skillsupstash
build applications with Upstash SDKs
Sep 4DatabaseRedisServerlessUpstashupstash-box-py
build sandboxed environments with Upstash Box
Sep 4CloudCode ExecutionPythonSandboxing +1upstash-cli
manage Upstash resources via CLI
Sep 1CLIDatabaseRedisServerless +1upstash-qstash-js
manage serverless messaging with QStash
Sep 1MessagingNode.jsServerlessUpstashupstash-ratelimit-js
implement rate limiting with Upstash
Sep 1Node.jsPerformanceSecurityUpstashupstash-redis-js
manage serverless Redis with Upstash
Sep 1Node.jsRedisServerlessUpstash
More from Upstash
View publishercontext7-cli
manage documentation and skills with ctx7
context7
Apr 6CLIDocumentationKnowledge Managementcontext7-docs
fetch documentation and code examples
context7
Jul 28CLIDocumentationReferenceSDKcontext7-mcp
retrieve library documentation via MCP
context7
Jul 28DocumentationKnowledge ManagementMCPfind-docs
retrieve documentation for developer technologies
context7
Jul 28DocumentationResearchSearchupstash-ratelimit-ts
implement Redis rate limiting with Upstash
ratelimit-js
Apr 6PerformanceRedisTypeScriptUpstashredis-js
manage serverless Redis with Upstash
redis-js
Apr 6Node.jsRedisServerlessUpstash