Skip to content
Merged
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
21 changes: 13 additions & 8 deletions .github/workflows/publish-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ name: Publish CLI
# headless clients reach box and list its tools. Never on PRs from forks.
# Publishing happens only when a tag `cli-vX.Y.Z` (or `cli-vX.Y.Z-rc.N`, dist-tag "next") is pushed.
#
# Cutting a release: bump "version" in cli/package.json, merge to main, then
# git tag cli-v<X.Y.Z> && git push origin cli-v<X.Y.Z>
# Since @simular-ai/box 1.0.0 (the Rust CLI from simular-ai/box-cli) this repo no longer
# publishes the CLI: its npm trusted publisher was removed, so do not push cli-v* tags. The
# publish job below is kept only until cli/ is retired.
#
# Auth: npm trusted publishing (OIDC). The publish job's `id-token: write` lets the npm CLI swap
# a GitHub OIDC token for a short-lived publish token, so no long-lived npm token is stored.
Expand Down Expand Up @@ -124,14 +125,18 @@ jobs:
export HOME="$(mktemp -d)"
claude plugin validate .
claude plugin validate ./claude
- name: Plugin pins the CLI to the exact version in cli/package.json
# A range (^0.2.0) lets npx run a version published after review; the Claude directory
# review asks for an exact pin, and it must be the CLI version this ref ships.
- name: Plugin pins the CLI to one exact version that is on npm
# A range (^1.0.0) lets npx run a version published after review; the Claude directory
# review asks for an exact pin. Since 1.0.0 the CLI is the Rust simular-box, released from
# simular-ai/box-cli, so the pin follows its npm releases, not cli/package.json.
run: |
set -euo pipefail
want="@simular-ai/box@$(node -p "require('./cli/package.json').version")"
bad=$(grep -rnoE '@simular-ai/box@[^ `"]*' claude | grep -vF ":$want" || true)
if [ -n "$bad" ]; then echo "pin npx to $want in claude/:"; echo "$bad"; exit 1; fi
pins=$(grep -rhoE '@simular-ai/box@[^ `"]*' claude | sort -u)
if [ "$(printf '%s\n' "$pins" | grep -c .)" -ne 1 ]; then echo "claude/ must pin one CLI version, found:"; echo "$pins"; exit 1; fi
v=${pins#@simular-ai/box@}
if ! printf '%s' "$v" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then echo "pin an exact release, not $pins"; exit 1; fi
if [ "$(npm view "@simular-ai/box@$v" version)" != "$v" ]; then echo "$pins is not on npm"; exit 1; fi
echo "claude/ pins $pins"
- name: DeepSeek Harness package
run: npm pack ./dsh --dry-run
- name: Hermes plugin
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ 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.
- `cli/`: bump `version` in `cli/package.json`, and, in the same PR, the exact pin `npx -y @simular-ai/box@X.Y.Z` in `claude/skills/box-offload/SKILL.md` plus `version` in `claude/.claude-plugin/plugin.json` (CI fails while the pin and `cli/package.json` disagree; never a range, because the Claude directory review requires that what runs is what it read). Then push a tag `cli-vX.Y.Z` right after the merge. 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.
- 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.
2 changes: 1 addition & 1 deletion claude/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "box",
"displayName": "box by Simular",
"version": "0.2.1",
"version": "0.2.2",
"description": "Give Claude 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. You sign in once in the browser; no key to paste.",
"author": {
"name": "Simular",
Expand Down
8 changes: 6 additions & 2 deletions claude/skills/box-offload/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ description: Hand this coding task to an agent in the user's box (their cloud co

The agent in the box starts fresh. It knows only what your hand-over says, plus the repo.
Write the hand-over as if for a capable engineer who has never seen this conversation.
`box` below is `npx -y @simular-ai/box@0.2.0`. Run it in the repo the user works in. It does every
`box` below is `npx -y @simular-ai/box@1.0.0`. Run it in the repo the user works in. It does every
mechanical step: never copy files or secrets yourself, never print a secret, never edit the
files it writes.
The CLI prints follow-up commands as `simular-box ...`; that name is not on PATH under npx, so
when you pass one to the user, write it with `box` (the npx command above) instead.

## OFFLOAD

Expand All @@ -20,11 +22,13 @@ files it writes.
`codex`, `cursor`). Add `--box NAME` when the user names a box.
- "not signed in": ask the user to run `box login` in their terminal (it opens the
browser), then run offload again.
- Exit 4 is a refused sign-in (expired or revoked): ask the user to run `box login`, then
run offload again.
- Exit 3 is a block: stop and tell the user why, one line per finding. If the box CLI is
missing or signed out, tell the user to run, in their own terminal,
`box offload install-cli --kind <K>` and then `box offload sign-in --kind <K>`
(the sign-in asks them to approve in the browser and paste a code, so you cannot do it).
- Exit 4 is warnings: tell the user each one, and run again with `--yes` only when they
- Exit 5 is warnings: tell the user each one, and run again with `--yes` only when they
agree, or said beforehand to go ahead.
- For a secret it warns about, ask the user; only they opt one in
(`box offload secrets add file:.env`). Never opt in on your own.
Expand Down
Loading