From a01d4f49a47641e966dff49fb09578119210942b Mon Sep 17 00:00:00 2001 From: Dora Qian Date: Thu, 5 Nov 2026 20:39:22 +0800 Subject: [PATCH 1/2] Add Pi package pi/: @simular-ai/box-pi. A small extension registers the box MCP server with Pi's built-in MCP (Pi 0.99+); sign in once with /mcp login box. The box skill copy uses Pi's tool names. Published to npm; pi.dev lists it through the pi-package keyword. Co-Authored-By: Claude Opus 5.5 --- README.md | 2 ++ pi/LICENSE | 21 +++++++++++++++++++++ pi/README.md | 32 ++++++++++++++++++++++++++++++++ pi/extensions/box.ts | 18 ++++++++++++++++++ pi/package.json | 25 +++++++++++++++++++++++++ pi/skills/box/SKILL.md | 22 ++++++++++++++++++++++ 6 files changed, 120 insertions(+) create mode 100644 pi/LICENSE create mode 100644 pi/README.md create mode 100644 pi/extensions/box.ts create mode 100644 pi/package.json create mode 100644 pi/skills/box/SKILL.md diff --git a/README.md b/README.md index 8e5b1bf..e1f7b3e 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Most agents need no plugin: add the MCP server `https://mcp.box.simular.ai/mcp` | DeepSeek Harness (dsh) | [`dsh/`](dsh/) | Personal key (`cb_...`), pasted on the plugin's page in Plugins | [dsh/README.md](dsh/README.md) | | 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) | +| 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 @@ -24,4 +25,5 @@ Add a folder named after the agent with its own manifest, MCP config and, where - `claude/`: bump `version` in `claude/.claude-plugin/plugin.json`. Claude Code doesn't auto-update third-party marketplaces: users get it with `/plugin marketplace update simular-box` and `/plugin update box@simular-box`, or with `npx @simular-ai/box connect`. - `dsh/`: bump `version` in `dsh/package.json`, then push a tag `dsh-vX.Y.Z`. The release workflow attaches `dsh-box.tgz`. - `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`, then `npm publish` from `pi/` (pi.dev lists packages with the `pi-package` keyword on its own). - `cli/`: bump `version` in `cli/package.json`, then push a tag `cli-vX.Y.Z`. The `publish-cli.yml` workflow tests it and publishes `@simular-ai/box` to npm through trusted publishing (OIDC), with provenance; the one-time npm setup is in [cli/README.md](cli/README.md#releasing). When the box endpoint moves, change `DEFAULT_MCP_URL` in `cli/src/constants.js`, add the old host to `OLD_HOSTS` there, change the URL in every plugin folder, and release each one. diff --git a/pi/LICENSE b/pi/LICENSE new file mode 100644 index 0000000..3514bf9 --- /dev/null +++ b/pi/LICENSE @@ -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. diff --git a/pi/README.md b/pi/README.md new file mode 100644 index 0000000..9665f30 --- /dev/null +++ b/pi/README.md @@ -0,0 +1,32 @@ +# 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 sign in once (inside Pi run `/mcp login box`, or from a shell `pi mcp login box`) and approve in the browser. 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 (Pi 0.99 or later). 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__`; `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. + +## 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). diff --git a/pi/extensions/box.ts b/pi/extensions/box.ts new file mode 100644 index 0000000..1745d04 --- /dev/null +++ b/pi/extensions/box.ts @@ -0,0 +1,18 @@ +// 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` (or `pi mcp login box`) +// and approve in the browser. No key is read or stored by this package. +export default function (pi: any) { + 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", + }, + }); +} diff --git a/pi/package.json b/pi/package.json new file mode 100644 index 0000000..e6d2c7a --- /dev/null +++ b/pi/package.json @@ -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"] + } +} diff --git a/pi/skills/box/SKILL.md b/pi/skills/box/SKILL.md new file mode 100644 index 0000000..9512644 --- /dev/null +++ b/pi/skills/box/SKILL.md @@ -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__`; 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. From f89f5467fb3df54d012171bbdfa7bb2e2c519736 Mon Sep 17 00:00:00 2001 From: Dora Qian Date: Fri, 6 Nov 2026 11:27:56 +0800 Subject: [PATCH 2/2] Pi: sign in only inside a session, guard older Pi, release workflow, CI check --- .github/workflows/publish-cli.yml | 14 +++++++ .github/workflows/release-pi.yml | 64 +++++++++++++++++++++++++++++++ cli/e2e/clients.json | 1 + pi/README.md | 8 +++- pi/extensions/box.ts | 6 ++- 5 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/release-pi.yml diff --git a/.github/workflows/publish-cli.yml b/.github/workflows/publish-cli.yml index 34dc8d3..aef41be 100644 --- a/.github/workflows/publish-cli.yml +++ b/.github/workflows/publish-cli.yml @@ -36,6 +36,7 @@ on: - 'dsh/**' - 'hermes/**' - 'openclaw/**' + - 'pi/**' - '.claude-plugin/**' - '.github/workflows/publish-cli.yml' push: @@ -132,6 +133,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 diff --git a/.github/workflows/release-pi.yml b/.github/workflows/release-pi.yml new file mode 100644 index 0000000..2ee6d48 --- /dev/null +++ b/.github/workflows/release-pi.yml @@ -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 && git push origin pi-v +# +# 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 diff --git a/cli/e2e/clients.json b/cli/e2e/clients.json index 6c9659e..aed1eaa 100644 --- a/cli/e2e/clients.json +++ b/cli/e2e/clients.json @@ -6,5 +6,6 @@ "gemini-cli": { "npm": "@google/gemini-cli@0.66.0" }, "openclaw": { "npm": "openclaw@2026.10.9" }, "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" } } diff --git a/pi/README.md b/pi/README.md index 9665f30..177d639 100644 --- a/pi/README.md +++ b/pi/README.md @@ -8,11 +8,11 @@ pi install npm:@simular-ai/box-pi ``` -Then sign in once (inside Pi run `/mcp login box`, or from a shell `pi mcp login box`) and approve in the browser. 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". +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 (Pi 0.99 or later). If you use pi-mcp-adapter instead, it connects the same server. +- 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__`; `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 @@ -21,6 +21,10 @@ Then sign in once (inside Pi run `/mcp login box`, or from a shell `pi mcp login - 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 && git push origin pi-v`. `.github/workflows/release-pi.yml` publishes it to npm with provenance. + ## Links - Docs: https://box.simular.ai/docs/mcp diff --git a/pi/extensions/box.ts b/pi/extensions/box.ts index 1745d04..1a051aa 100644 --- a/pi/extensions/box.ts +++ b/pi/extensions/box.ts @@ -1,8 +1,12 @@ // 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` (or `pi mcp login box`) +// 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",