Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/publish-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ on:
- 'dsh/**'
- 'hermes/**'
- 'openclaw/**'
- 'pi/**'
- '.claude-plugin/**'
- '.github/workflows/publish-cli.yml'
push:
Expand Down Expand Up @@ -145,6 +146,19 @@ jobs:
if [ ! -d hermes ]; then echo "no hermes/ folder on this ref; skipped"; exit 0; fi
export HOME="$(mktemp -d)"
hermes plugins validate ./hermes
- name: Pi package
run: |
set -euo pipefail
if [ ! -d pi ]; then echo "no pi/ folder on this ref; skipped"; exit 0; fi
npm pack ./pi --dry-run
export HOME="$(mktemp -d)"
npm install -g "$(node -p "require('./cli/e2e/clients.json').pi.npm")"
pi install ./pi
# The package's extension registers box; with no sign-in yet Pi reports it as needing one,
# which proves the server is registered and reachable. No model or key is needed.
out=$( (printf '%s\n' '{"id":"1","type":"prompt","message":"/mcp"}'; sleep 20) | pi --mode rpc --no-session 2>&1 || true)
echo "$out"
echo "$out" | grep -q 'box: needs sign-in'
- name: OpenClaw plugin
run: |
set -euo pipefail
Expand Down
64 changes: 64 additions & 0 deletions .github/workflows/release-pi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Release Pi package

# Publishes @simular-ai/box-pi (pi/) to npm when a tag `pi-vX.Y.Z` is pushed.
#
# Cutting a release: bump "version" in pi/package.json, merge to main, then
# git tag pi-v<X.Y.Z> && git push origin pi-v<X.Y.Z>
#
# Auth: npm trusted publishing (OIDC), same as publish-cli.yml. Requires the trusted-publisher
# config on npmjs.com (package @simular-ai/box-pi -> Settings -> Trusted Publisher): organization
# "simular-ai", repository "box-plugin", workflow filename "release-pi.yml", environment "npm".
# npm only lets you configure it on a package that already exists, so the first version is
# published once by hand from pi/ (`npm publish --access public`).
#
# Gating: runs in the GitHub environment "npm" and refuses a tag whose commit is not on main.
on:
push:
tags: ['pi-v*']

permissions:
contents: read

jobs:
publish:
name: Publish to npm
runs-on: ubuntu-latest
timeout-minutes: 10
environment: npm
permissions:
contents: write # create the GitHub Release
id-token: write # npm trusted publishing (OIDC) and provenance
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
fetch-depth: 0
- name: Tagged commit is on main
run: |
set -euo pipefail
git fetch --quiet origin main
if ! git merge-base --is-ancestor "$GITHUB_SHA" origin/main; then
echo "::error::$GITHUB_REF_NAME points at $GITHUB_SHA, which is not on main. Tag a commit on main." >&2
exit 1
fi
# No `registry-url`: setup-node would write an .npmrc with `_authToken=${NODE_AUTH_TOKEN}`,
# which shadows the OIDC handshake. Node 24 ships npm 11 (trusted publishing needs >= 11.5.1).
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version: 24
- name: Tag matches pi/package.json
run: |
set -euo pipefail
version=$(node -p "require('./pi/package.json').version")
if [ "pi-v$version" != "$GITHUB_REF_NAME" ]; then
echo "::error::Tag $GITHUB_REF_NAME does not match pi/package.json ($version)." >&2
exit 1
fi
- name: Publish to npmjs.org
working-directory: pi
run: npm publish --provenance --access public
- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
TAG_NAME: ${{ github.ref_name }}
run: gh release create "$TAG_NAME" --title "$TAG_NAME" --notes "Pi package for box. See pi/README.md." --latest=false
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Most agents need no plugin: add the MCP server `https://mcp.box.simular.ai/mcp`
| Any of Claude Code, Codex, Cursor, OpenCode, Gemini CLI, Hermes, OpenClaw, VS Code (and steps for Claude Desktop) | [`cli/`](cli/) | OAuth; personal key with `--auth key` for Hermes and OpenClaw | `npx @simular-ai/box connect` (check with `npx @simular-ai/box doctor`) |
| Hermes Agent | [`hermes/`](hermes/) | Personal key (`cb_...`) in `MCP_BOX_API_KEY`; OAuth optional | [hermes/README.md](hermes/README.md) |
| ChatGPT and Codex (OpenAI plugin directory) | [`openai/`](openai/) | OAuth, once in the browser | Listed by OpenAI after review; build the upload with `openai/build-zip.sh` ([openai/README.md](openai/README.md)) |
| Pi | [`pi/`](pi/) | OAuth, once in the browser (`/mcp login box`) | `pi install npm:@simular-ai/box-pi` ([pi/README.md](pi/README.md)) |

## Offload: move a coding task into your box and back

Expand All @@ -28,5 +29,6 @@ Add a folder named after the agent with its own manifest, MCP config and, where
- `dsh/`: bump `version` in `dsh/package.json`, then push a tag `dsh-vX.Y.Z`. The release workflow attaches `dsh-box.tgz`.
- `openai/`: bump `version` in `openai/plugin.json` and `publication.release_notes`, run `openai/build-zip.sh`, upload the ZIP at platform.openai.com/plugins.
- `hermes/`: bump `version` in `hermes/plugin.json`. Users copy the folder by hand until box is in the Hermes plugin catalog.
- `pi/`: bump `version` in `pi/package.json`, merge to main, then push a matching tag `pi-vX.Y.Z`. `release-pi.yml` publishes `@simular-ai/box-pi` to npm through trusted publishing, with provenance (the first version is published once by hand, see the workflow's header). pi.dev lists packages with the `pi-package` keyword on its own.
- The Claude plugin's CLI pin: since 1.0.0, `@simular-ai/box` on npm is the Rust CLI released from [simular-ai/box-cli](https://github.com/simular-ai/box-cli). To move the plugin to a new CLI release, change the exact pin `npx -y @simular-ai/box@X.Y.Z` in `claude/skills/box-offload/SKILL.md` and bump `version` in `claude/.claude-plugin/plugin.json` in one PR (CI fails unless every pin under `claude/` names the same exact version and that version is on npm; never a range, because the Claude directory review requires that what runs is what it read).
- `cli/`: the JavaScript CLI (0.2.x). It no longer publishes to npm: its trusted publisher on `@simular-ai/box` was removed when the Rust 1.0.0 shipped, so do not push `cli-v*` tags. The endpoint and CLI changes now go to simular-ai/box-cli.
1 change: 1 addition & 0 deletions cli/e2e/clients.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
"gemini-cli": { "npm": "@google/gemini-cli@0.66.0" },
"openclaw": { "npm": "openclaw@2026.11.1" },
"hermes": { "git": "https://github.com/NousResearch/hermes-agent", "tag": "v0.22.6" },
"pi": { "npm": "@earendil-works/pi-coding-agent@1.5.0" },
"cursor": { "cursorAgent": "2026.10.22-27dcf5f" }
}
21 changes: 21 additions & 0 deletions pi/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Simular LLC

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
36 changes: 36 additions & 0 deletions pi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# box for Pi

[box](https://box.simular.ai) gives the [Pi coding agent](https://pi.dev) a computer of its own: a cloud Linux desktop with Chrome and a shell that it drives over MCP, while your own computer stays free. Pi can browse sites (including ones behind a login), fill forms, use desktop apps and run commands there. You can watch the box live and take over at https://box.simular.ai/box.

## Install

```bash
pi install npm:@simular-ai/box-pi
```

Then start `pi`, run `/mcp login box` inside the session and approve in the browser (the `pi mcp` shell commands don't load extensions, so they can't see box). New accounts get free credit. Ask Pi for anything that needs a computer, for example "open Hacker News in my box and summarize the top five posts".

## What the package adds

- An extension that registers box's hosted MCP server, `https://mcp.box.simular.ai/mcp`, with Pi's built-in MCP support. Needs Pi 0.99 or later; on an older Pi the extension prints a warning and does nothing. If you use pi-mcp-adapter instead, it connects the same server.
- A `box` skill that tells Pi which box tool to use for what. Tools are named `mcp__box__<tool>`; `shell`, `browser_navigate`, `browser_snapshot`, `screenshot` and `box_status` are declared directly and the rest are found with `tool_search`.

## Sign-in and what it touches

- Sign-in is OAuth only. Pi stores the token in `~/.pi/agent/mcp-auth.json`; the package reads no key, environment variable or local file.
- Network: only `https://mcp.box.simular.ai/mcp` and the box sign-in page.
- Commands and file edits run on the box, not on your machine.

## Releasing

Bump `version` in `pi/package.json`, merge to main, then push a matching tag: `git tag pi-v<X.Y.Z> && git push origin pi-v<X.Y.Z>`. `.github/workflows/release-pi.yml` publishes it to npm with provenance.

## Links

- Docs: https://box.simular.ai/docs/mcp
- Privacy policy: https://www.simular.ai/product-sai/privacy
- Terms of use: https://www.simular.ai/terms-of-use

## License

MIT. See [LICENSE](LICENSE).
22 changes: 22 additions & 0 deletions pi/extensions/box.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Registers box's hosted MCP server with Pi for every session.
// Pi's built-in MCP support (and pi-mcp-adapter, if installed) connects it.
// Sign-in is OAuth: the first time, run `/mcp login box` inside a Pi session
// and approve in the browser. No key is read or stored by this package.
export default function (pi: any) {
if (typeof pi?.registerMcpServer !== "function") {
console.warn("box: this Pi has no built-in MCP support (needs Pi 0.99 or later); box was not added.");
return;
}
pi.registerMcpServer("box", {
url: "https://mcp.box.simular.ai/mcp",
description: "box by Simular: the user's cloud Linux computer with Chrome and a shell",
exposure: "deferred",
toolExposure: {
shell: "direct",
browser_navigate: "direct",
browser_snapshot: "direct",
screenshot: "direct",
box_status: "direct",
},
});
}
25 changes: 25 additions & 0 deletions pi/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "@simular-ai/box-pi",
"version": "0.1.0",
"description": "box by Simular for the Pi coding agent: a cloud Linux computer with Chrome and a shell that Pi drives over MCP, while your own computer stays free. Sign in once in the browser; no key to paste.",
"license": "MIT",
"homepage": "https://box.simular.ai",
"repository": {
"type": "git",
"url": "git+https://github.com/simular-ai/box-plugin.git",
"directory": "pi"
},
"author": {
"name": "Simular",
"url": "https://simular.ai"
},
"keywords": ["pi-package", "box", "simular", "computer-use", "cloud-computer", "browser-automation", "mcp"],
"files": ["extensions", "skills", "README.md", "LICENSE"],
"publishConfig": {
"access": "public"
},
"pi": {
"extensions": ["./extensions/box.ts"],
"skills": ["./skills"]
}
}
22 changes: 22 additions & 0 deletions pi/skills/box/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
name: box
description: Use box, a cloud Linux computer with Chrome and a shell, when a task needs a real computer - browsing sites (including ones behind a login), filling forms, using desktop apps, or running commands somewhere other than the user's machine.
---

# Use box

box is the user's own cloud Linux desktop. Its tools come from the `box` MCP server and are named `mcp__box__<tool>`; the most used ones are declared directly, find the rest with `tool_search`. If box's tools are missing or need sign-in, ask the user to run `/mcp login box` once and approve in the browser. A sleeping box wakes on the first call, which can take a few seconds.

## Pick the right tool

- **Shell and files:** `shell` runs a command; `read_file`, `write_file`, `edit_file` and `list_dir` work on the box's files. Prefer these whenever the task can be done without the screen.
- **Web pages:** `browser_navigate` opens a URL, `browser_snapshot` or `browser_read` reads the page, `browser_click`, `browser_type` and `browser_fill` act on elements from the last snapshot, `browser_tabs` manages tabs, `browser_fetch` fetches a URL without rendering. Re-snapshot after the page changes; element refs go stale.
- **Desktop apps:** send a whole GUI plan in one `gui_plan` call (open the app, menu, click, type, wait, save) instead of a chain of single clicks. Use `desk` for one accessibility-tree action, `computer_act` and `computer_state` for raw pointer and keyboard work, and `script_run` for loops over many items.
- **Seeing the screen:** `screenshot` when you need to look; don't take one after every step.
- **The box itself:** `box_status`, `box_list`, `box_wake`, `box_hibernate`, `box_save` and `box_upgrade`.

## Working with the user

- The user can watch the box live and take over at https://box.simular.ai/box. Mention it for long tasks.
- When a step needs the user (a sign-in, a password, a 2FA code, a captcha, a payment), stop and ask them to do it on that page, then continue. Never ask for passwords in chat.
- Report what you did and anything you saved on the box, with paths.
Loading