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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ 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) |

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

Going offline in the middle of a task? In Claude Code with the plugin, `/box:offload` hands the task to a fresh Claude Code (or Codex, Cursor) session in your box, which keeps working while you are away; `/box:back` brings its commits and its written hand-over home and merges them. Any other agent or a plain terminal uses `npx @simular-ai/box offload` and `npx @simular-ai/box back`. Setup and details: [cli/README.md](cli/README.md#offload).

## Adding an agent

Add a folder named after the agent with its own manifest, MCP config and, where the agent supports skills, a copy of `claude/skills/box/SKILL.md`. Point it at `https://mcp.box.simular.ai/mcp`. Use OAuth sign-in where the agent supports it; otherwise read a personal key from an environment variable or the agent's own credentials store, never from a file in the package. Add a row above.
Expand Down
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.1.1",
"version": "0.2.0",
"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
5 changes: 5 additions & 0 deletions claude/commands/back.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description: Bring the task back from my box and continue it here
---

Use the box-offload skill: BACK. $ARGUMENTS
5 changes: 5 additions & 0 deletions claude/commands/offload.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description: Move this coding task into my box, where an agent keeps working on it
---

Use the box-offload skill: OFFLOAD this task to my box. $ARGUMENTS
95 changes: 95 additions & 0 deletions claude/skills/box-offload/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
name: box-offload
description: Hand this coding task to an agent in the user's box (their cloud computer) and take it back. Use when the user says offload, "move this to my box", "keep working while I'm away", "I'm back" or "bring it back", or when a message is exactly OFFLOAD or BACK.
---

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
mechanical step: never copy files or secrets yourself, never print a secret, never edit the
files it writes.

## OFFLOAD

1. Finish the step you are in, or stop at a safe point. Do not start new work.
2. Run `box offload handover-path` in the repo and write the hand-over to the path it
prints, with the template below. Fill every section; write "none" for an empty one. Be
concrete: exact commands, versions you saw, file paths, error messages, decisions with
their reasons. Under "Secrets needed" give names only, never values.
3. Run `box offload --kind claude` (or the CLI the user asked for in the box:
`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 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
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.
4. When it prints `offloaded`, tell the user the box, that its agent runs with permission
prompts bypassed, and that `/box:back` returns the work. End your turn and make no more
changes to this repo.
5. On exit 1, report its last line. Nothing changed on this computer; do not retry by hand.

While the task is in the box, `box offload inbox` shows what the box agent posted
(progress, questions), `box offload send "<answer>"` answers it, and
`box offload status` shows whether it is working. The user can watch its terminal with
the `rsh -t ... tmux attach` line offload printed.

## BACK

Run `box back` in the repo. It waits for the box agent to go idle, then up to 10 minutes in
all for its hand-over, then lands the box's work against the snapshot taken at the offload.
Report how the code landed, as its first line says: fast-forward (the branch now points at
the box's commit), merged (the branch moved to the box's commit, or the box's changes applied
uncommitted, with any uncommitted paths listed), unchanged, or a branch with conflicts, where
your work tree is untouched. If it says nothing of this repo is in a box and names a
`back.md`, the work has landed already: read that file as the hand-over. Then check the
hand-over's claims against `git log` and `git diff`, run its verify commands, and continue
from its next steps.

## Hand-over template

```markdown
# Hand-over: <one-line goal>

From: <local | box> Agent: <claude|codex|cursor> Repo: <path> Branch: <branch> @ <short sha>

## Goal and definition of done
<what the user asked for, in their words where it matters; what "done" means>

## User preferences and constraints
<style, scope limits, things the user said not to do, deadlines; or none>

## Current state
<where the work stands in one paragraph: what works, what is broken, what is half-done>

## Decisions made
- <decision> — <why>; rejected: <alternative and why>

## Files touched
- `<path>` — <what changed and why; whether it is finished>

## Next steps
1. <the very next action, specific enough to start without asking>
2. <…>

## Commands
- Build: `<command>` Test: `<command>` Lint: `<command>` Run: `<command>`
- Verify the current state: `<command>` → <what passing looks like>

## Environment facts
- Tools and versions: <go 1.26.x, rustc 1.9x, node 22.x, …; where each came from>
- Services: <local databases, ports, docker compose services; or none>
- Hosts: <APIs or internal hosts the task calls; or none>
- Secrets needed: <names only, never values; or none>
- Installed during this session: <packages and tools added; or none>

## Gotchas learned
- <non-obvious things that cost time: flaky tests, a wrong doc, a tool quirk>

## Open questions
- <what needs the user, and what to do meanwhile>
```
29 changes: 28 additions & 1 deletion cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,36 @@ Without `BOX_TOKEN`, an interactive run asks for the key with hidden input. The

It prints a fix for each problem. `--json` prints a machine-readable report; the exit code is 1 when something needs fixing. OAuth sign-ins are stored by each app, so doctor can't see whether you've signed in.

## Offload

Move the coding task you are working on into your box, let an agent there keep going while you are away, and bring the work back. This is upstream cocoonbox's Offload (design §27), with the same box side.

```bash
npx @simular-ai/box login # once: sign this CLI in to box in the browser
npx @simular-ai/box offload install-cli --kind claude # once per box: the vendor's official installer, in the box
npx @simular-ai/box offload sign-in --kind claude # once per box: Claude Code's own login, run in the box
```

Then, in Claude Code with the `box` plugin, `/box:offload` and later `/box:back`. Elsewhere, write the hand-over to the path `offload handover-path` prints (or paste the request `offload --handover-prompt --kind codex` prints into your agent), then:

```bash
npx @simular-ai/box offload --kind claude # preflight, copy the repo, start the box agent from the hand-over
npx @simular-ai/box offload inbox # what the box agent posted; offload send "..." answers it
npx @simular-ai/box back # wait for its hand-over, fetch its commits, merge them here
```

How it works:

- **Sign-in.** `login` signs the CLI in as the relay's first-party `cocoonbox-cli` client: the consent page opens in your browser, the answer comes back to a one-time listener on `127.0.0.1` (PKCE, `state` and issuer checked), and the CLI gets a device token of its own, listed under Keys -> Devices and revoked there or with `logout`. It is kept in `~/.simular-box/credentials.json` (`0600`, directory `0700`; `BOX_HOME` moves it). `BOX_TOKEN=cb_...` (a personal key) wins over it, for CI or a server. `login --token -` reads a personal key from stdin or a hidden prompt. A token is never accepted as an argument or printed.
- **The box CLI has its own login.** `offload sign-in` runs the vendor's login (`claude auth login`, `codex login --device-auth`, `cursor-agent login`) on a terminal in the box, relayed to yours, with the box's browser kept shut. The first https link it prints on that vendor's own sign-in hosts opens in your browser, once; no other link from the box is opened. Approve, then paste the code into your terminal. Nothing is copied from this computer.
- **Transport.** Everything goes over `Session.Exec` on the relay's gRPC: `npx @simular-ai/box rsh` is an ssh-like remote shell (`rsync -e`, `GIT_SSH_COMMAND`). An offload is three Execs: `begin` (box checks), rsync of the work tree and `.git` without objects, and `send`, whose stream carries the hand-over, `env.json`, the history as a git bundle and any opted-in secrets.
- **Back.** It waits for the box agent to go idle (a hand-over request pasted while it is ending a turn can be lost; `back --interrupt` stops its current step instead), then up to 10 minutes in all for its hand-over, fetches the box's commits over `rsh`, and lands them against the snapshot taken at offload: a fast-forward when your repo has not changed, else a clean merge applied uncommitted (never touching a file you changed meanwhile), else the branch `cocoonbox/back-<time>` with your work tree untouched.
- **Preflight.** It blocks on a non-git directory, a box missing `git`/`rsync`/`tmux`/`mise`, a missing or signed-out box CLI, an offload not yet brought back, and macOS-only commands. It warns (go on with `--yes`) about local services and VPN-only hosts the box cannot reach, git-ignored `.env*` files and other secrets (opt one in with `offload secrets add file:.env`; values travel only in the Exec stream and land on a tmpfs in the box), LFS and submodules, and a copy over 500 MB.
- **Limits.** macOS and Linux (needs `git` and `rsync`); git repositories only; the box agent commits but never pushes; one session per repo and three per box; the box agent runs with permission prompts bypassed.

## Other endpoints

`BOX_MCP_URL` points everything at another endpoint (for example staging): `BOX_MCP_URL=https://… npx @simular-ai/box connect`. When box's endpoint moves, a new CLI version changes the default and `connect` updates each app: it rewrites a `box` entry that points at the old address and, for Claude Code, updates the `box@simular-box` plugin. Apps may then ask you to sign in to box again. box moved from `relay.simular.cloud` to `mcp.box.simular.ai` on 2026-11-04; `doctor` flags an app still on the old address.
`BOX_MCP_URL` points everything at another endpoint (for example staging): `BOX_MCP_URL=https://… npx @simular-ai/box connect`. Offload, `login` and `rsh` use its origin, or `BOX_ENDPOINT` when set. When box's endpoint moves, a new CLI version changes the default and `connect` updates each app: it rewrites a `box` entry that points at the old address and, for Claude Code, updates the `box@simular-box` plugin. Apps may then ask you to sign in to box again. box moved from `relay.simular.cloud` to `mcp.box.simular.ai` on 2026-11-04; `doctor` flags an app still on the old address.

## Development

Expand Down
Loading
Loading