Capability
Session handoff
Move an in-progress local Claude Code, Codex CLI, or opencode session into a fresh boxxkite sandbox — full conversation history, not a task summary — and keep interacting with it from there. The CLI keeps running under your own portable, scoped credential, never a copy of your laptop's raw login session.
How a handoff runs
Every step below composes existing, already-reviewed primitives — sandbox creation, file_create, and the same takeover PTY the dashboard's own terminal uses. No new control-plane or sidecar surface was added for this.
How a handoff runs
Locate session
The adapter finds your tool's real on-disk session state (or, for opencode, its own export format) and a portable, scoped credential -- never your raw browser login session.
Install & run
boxxkite handoff <tool> ships as part of the main CLI — one install, nothing extra to add:
pip install boxxkite-sandbox
boxxkite config set-key bxk_live_...
boxxkite handoff claude-codeset-keyalone is enough — it defaults to boxxkite's own hosted control-plane. Self-hosting instead? Run boxxkite config set-url <your-control-plane> too — everything else works the same. Pass --session <id> for a specific session, or omit it to hand off whichever local session was modified most recently. --api-key and --base-url flags override the saved config for a one-off run.
Per-provider setup
Each tool authenticates the sandbox with its own portable credential — never a copy of your local login.
- Claude Code — run
claude setup-tokenlocally (needs an active Claude subscription). It prints a long-lived, model-requests-only token — export it asCLAUDE_CODE_OAUTH_TOKENbefore running the handoff, or the adapter picks it up automatically if it's already in your environment. - Codex CLI — set
OPENAI_API_KEY(orCODEX_API_KEY/ a personal access token) if you have one. If your only local login is a ChatGPT Plus/Pro subscription, no extra setup is needed — the handoff falls back tocodex login --device-auth, a real device-code flow that opens a URL and code you complete from any browser, right inside the takeover terminal. It mints a fresh, independent login for the sandbox rather than copying your local session. - opencode — no setup needed beyond having logged in locally with a real provider API key (
type: "api"inauth.json). A provider configured only via opencode's own OAuth login isn't portable, and the handoff will say so clearly rather than copying it. - Cursor — get a key at cursor.com/dashboard/api and export it as
CURSOR_API_KEY. The adapter itself isn't implemented yet — see the table below for why.
How credentials stay safe
Your credential is never typed anywhere as a literal value. It's written once to a short-lived file, read back with a single reference to its path, and deleted immediately by that same command — so at no point does the raw token appear in a command, a log line, or shell history.
- Always the tool's own portable, scoped, independently-revocable token — never your raw browser/OAuth session.
- Written only to a short-lived file under
/tmp, never anywhere that syncs to durable storage. - Deleted by the same command that reads it, and every session identifier is validated before it can reach a shell command.
Full technical design
docs/handoff-adapters.md in the repo for the complete adapter contract, architecture diagrams, and security design behind this.Supported tools
| Tool | Status | Credential |
|---|---|---|
| Claude Code | Supported — cwd-sensitive resume | claude setup-token |
| Codex CLI | Supported — path-based resume, plus a device-auth fallback for subscription-only logins | OPENAI_API_KEY, a personal access token, or codex login --device-auth |
| opencode | Supported — via export/import | provider API key from auth.json |
| Cursor | Not yet — cursor-agent's local session store couldn't be confirmed as a portable, copyable file. Raises a clear error rather than faking support. | — |
| Gemini CLI | Not yet — in progress as a community contribution | GEMINI_API_KEY |
The adapter contract is designed for community contribution — adding a new tool means implementing onelocate_session() call, not touching the shared orchestration. See docs/handoff-adapters.md's "Adding a new adapter" section.
Where this fits today
Not an MCP capability, and not a control-plane API
boxxkite handoff stays a local-only CLI command for exactly this reason, and it composes existing control-plane/SDK primitives rather than adding new ones — there is nothing new to call directly from the Python/JS/Go/Rust SDKs either.Related
- Python SDK —
boxxkite handoffis built directly onBoxxkiteClient. - Audit log & takeover — the same channel this feature attaches to, and why everything typed on it gets logged.
- Secrets management — a different trust boundary (brokering a third-party key to a semi-trusted agent) than a handoff's own credential handling.
- MCP server — why this capability isn't exposed as an MCP tool.
- Security model — the broader defense-in-depth posture this feature was built to fit inside, not around.