← Upstash RedisCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Upstash Redis
Snapshot Sep 30, 2026 · 23:07 UTC · version 1.2.1
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"name": "upstash-box-remote-work",
"description": "Do work in an Upstash Box, a sandboxed cloud container driven through the remote Upstash MCP server (mcp.upstash.com), instead of on the local machine. Use when the user asks to run, build, test, clone, or edit something remotely, in a sandbox, in the cloud, or in a box, when the deliverable is a pull request, a public preview URL, or a screenshot of a running app, when the local machine cannot deliver (no GitHub login for gh, no way to expose a port, a dirty or slow local checkout), or when several independent tasks should run in parallel on separate machines, a code factory that turns a list of tasks into a list of pull requests. Applies whenever the session has the box_* and blob_* MCP tools, even when Upstash is not named.",
"included_files": [],
"skill_md_contents": "---\nname: upstash-box-remote-work\ndescription: Do work in an Upstash Box, a sandboxed cloud container driven through the remote Upstash MCP server (mcp.upstash.com), instead of on the local machine. Use when the user asks to run, build, test, clone, or edit something remotely, in a sandbox, in the cloud, or in a box, when the deliverable is a pull request, a public preview URL, or a screenshot of a running app, when the local machine cannot deliver (no GitHub login for gh, no way to expose a port, a dirty or slow local checkout), or when several independent tasks should run in parallel on separate machines, a code factory that turns a list of tasks into a list of pull requests. Applies whenever the session has the box_* and blob_* MCP tools, even when Upstash is not named.\n---\n\nA box is a sandboxed Linux container in the cloud with a shell, a filesystem,\ngit, an optional headless Chromium, and public URLs for its ports. Everything\nhere goes through the remote Upstash MCP server. There is no SDK to install\nand no API key in the environment: the server forwards the session's OAuth\ntoken to the Box API, and screenshot bytes travel from the box to Blob\nwithout passing through the server.\n\n## When to take work into a box\n\n- The user asks for it: remote, in a sandbox, in the cloud, in a box, not on\n my machine.\n- The deliverable is a **pull request**, a **public preview URL**, or a\n **screenshot** of the running result. A box has GitHub credentials, public\n ports and a browser; the local machine often has none of the three.\n- The work needs isolation: untrusted or generated code, a heavy dependency\n install, a clean checkout, branches the local tree should not carry.\n- The work scales out: several independent tasks, one box each, in parallel.\n\nOnce a task is in a box, do all of it there. The box's filesystem is not the\nlocal one, so an edit made locally and a build run in the box act on two\ndifferent checkouts, and neither side reports the mismatch.\n\n## Connect\n\nThe plugin already registers `https://mcp.upstash.com/mcp`, and the box and\nblob tools are part of its default tool set. To add the server by hand:\n\n```bash\nclaude mcp add --scope user --transport http upstash \"https://mcp.upstash.com/mcp\"\n```\n\nOn first use the client opens the Upstash consent page. Pick the account or\nteam the boxes and buckets should live in, and **turn the read-only switch\noff**: every step below except listing is refused with 403 on a read-only\ngrant.\n\n## Tools\n\n| Tool | Actions / purpose |\n|---|---|\n| `box_manage` | create, list, get, delete, pause, resume, fork |\n| `box_exec` | run a shell command in the box (`command` is an argv array, `folder` is the working directory) |\n| `box_git` | clone, status, diff, commit, checkout, push, create_pr |\n| `box_preview` | create, list, delete public URLs for ports in the box |\n| `box_browser` | goto, content, screenshot, tabs, tab_new, tab_close, live_view |\n| `box_snapshots` | create, list, list_all, delete, restore (a new box from a snapshot) |\n| `box_logs`, `box_runs` | what happened inside a box, and its run history |\n| `box_apikey` | list, create, delete Box API keys for a deployed app or CI (the key outlives the OAuth grant, so tell the user to revoke it when done) |\n| `blob_bucket` | list, create (create defaults to `visibility: public`) |\n| `blob_upload_url` | presigned PUT URLs for paths in a bucket, plus `public_url` on public buckets |\n\n## The flow: one task, one box\n\n1. **Create.** `box_manage` `create`. Set `browser: true` if you will take\n screenshots or check pages. Use `ephemeral: true` with a `ttl` for\n throwaway work (no paid plan needed); use `keep_alive: true` when a preview\n URL must outlive the session (paid plan). Note the returned `id`.\n2. **Clone with `box_git` `clone`**, never with `git` in `box_exec`. The clone\n is what writes the account's GitHub credentials into the box; without it\n `push` and `create_pr` fail with a bare 500. The checkout lands at\n `/workspace/home/<repo name>`. Pass that as `folder` on every later\n `box_exec` and `box_git` call: the default is the workspace root, which is\n not a repository.\n3. **Work.** `box_exec` for install, build, tests, and the app itself. Each\n call waits for the command, so detach servers:\n `[\"sh\", \"-c\", \"( pnpm preview --host 0.0.0.0 --port 4321 > /workspace/home/app.log 2>&1 & )\"]`,\n then poll the port with `curl` in a second call. Edit files with shell\n commands or a short script in `box_exec`, not with local file tools.\n4. **Preview URL.** `box_preview` `create` with the `port`. The app must\n listen on `0.0.0.0`; a server bound to `127.0.0.1` answers curl inside the\n box and still gives 502 through the preview. The URL has the shape\n `https://<box-id>-<port>.preview.box.upstash.com`. Add `basic_auth` or\n `bearer_token` when the page should not be open to anyone with the link;\n the credential is returned once. Say in the reply how long the URL lives:\n an ephemeral box takes it down at `expires_at`.\n5. **Screenshots.** `box_browser` `goto` the page on `http://localhost:<port>`,\n then `screenshot`. With no `path` the PNG comes back as an image you can\n look at; with a `path` it is written inside the box and only `{saved,\n bytes}` returns. Look while you work, save the ones that count, and pass\n `full_page: true` for long pages.\n6. **Publish screenshots.** GitHub's attachment endpoint rejects the box's\n token, so images go through Blob. `blob_bucket` `list`, and `create` a\n **public** one if none fits (private buckets only serve short-lived\n signed URLs). `blob_upload_url` with `bucket_id` and\n `files: [{path: \"<repo>/<branch>/after.png\", content_type: \"image/png\", size: <bytes>}]`,\n minted right before use (a URL lives at most 10 minutes). Then `box_exec`\n the `curl_example` from the result, sending the returned headers verbatim\n (they are part of the signature). Bytes go straight from the box to storage.\n7. **Pull request.** `box_git` `checkout` a branch, `commit`, `push` with the\n branch name, then `create_pr` with `base`, `title`, and a `body` that\n carries the preview URL and `` for each screenshot.\n `create_pr` pushes nothing itself. Reply with the PR URL, the preview URL,\n and the screenshot URLs.\n8. **Clean up.** `box_manage` `delete` (or `pause`) unless the user wants the\n box or its preview kept. Ephemeral boxes expire on their own.\n\n## Scaling out\n\n- One box per independent task. Create them with a shared `labels` entry,\n drive them in parallel, and `box_manage` `list` with `label` to find and\n delete them at the end. Never run two tasks in one box at once.\n- When every task needs the same expensive setup (clone, dependency install,\n build cache), do it once, `box_snapshots` `create`, then `restore` one new\n box per task from the snapshot. `fork` does the same for an idle or paused\n non-ephemeral box.\n- `size` is `small`, `medium` or `large`; pick it per task rather than\n oversizing all of them.\n- A `live_view` URL lets a person watch a box's browser tab as it works\n (frames out, no input in); hand it over for long runs.\n\n## Gotchas\n\n- Read-only grant → 403 on create, exec, screenshot-to-path, git writes and\n upload URLs. Re-consent with read-only off.\n- `box_git` `create_pr` fails if the account has no GitHub installation\n covering the repo; ask the user to connect GitHub in the Upstash console\n under Box settings.\n- Prefer `box_git` `clone` over `clone_repo` on `box_manage` `create`: on an\n ephemeral box the option can be ignored, and on a persistent one it runs in\n the background with no completion signal beyond `box_logs`.\n- Paths inside the box are relative to `/workspace/home` unless absolute.\n `ls /workspace` itself is denied (root-owned, mode 711).\n- The `node` image has no corepack and boxuser cannot `npm i -g`, so a\n `packageManager`-pinned pnpm fails to self-install. Use\n `npx -y pnpm@<version>` or `export npm_config_manage_package_manager_versions=false`\n (the preinstalled pnpm); `sudo npm i -g pnpm@<version>` also works, sudo is\n passwordless.\n- `blob_upload_url` headers are signed. A missing or changed `content-type`\n or `cache-control` → 403 from storage (`SignatureDoesNotMatch`). An expired\n URL → mint again.\n- Bucket names are account-wide. Reuse one bucket such as `agent-proof` with\n per-repo prefixes rather than creating one per run.\n- `box_browser` fails with \"browser is not enabled for this box\" unless the\n box was created with `browser: true`; there is no way to add it later.\n"
}SHA-256: 9a471f6ef5963dde11ff286e3ae1759c680e9e2ade4b4c70e9a361947ddb4f32