Skip to content

Repository files navigation

Sandhop

Sandhop teleports a live local Claude Code or Codex session to a cloud sandbox and lets you continue it in an auth-gated browser terminal. It sends the dirty working tree, the active transcript, and the agent auth needed to resume the same session remotely — no commit, no context re-injection, native --resume.

Why Sandhop

Claude on the web and Codex cloud are good for clean repo tasks. Sandhop is for the messy local moment: uncommitted files, generated state, local slash commands, MCP config, and either Claude Code or Codex. The wedge is dirty-tree + cross-tool teleport, not another hosted agent UI.

Quickstart

Requires Node.js >=22.12.0. Older Node 22 builds such as 22.6.0 cannot load the current E2B SDK dependency chain and can fail with ERR_REQUIRE_ESM during sandhop setup.

npm install -g sandhop
sandhop setup

sandhop setup is a short wizard: pick your sandbox provider, paste its API key, choose a transport, and it installs the sandhop trigger into whichever agents you have — a /sandhop slash command for Claude Code, and a $sandhop skill for Codex. Credentials are stored in ~/.config/sandhop/config.json. You are never asked for your Claude/Codex API key — that auth is captured from your existing local session at teleport time.

Then, from inside a project session:

/sandhop     # Claude Code
$sandhop     # Codex

It runs sandhop push for the current session and prints the web-terminal URL:

SANDHOP_URL  https://<host>
SANDHOP_AUTH <user>:<password>

Open SANDHOP_URL and sign in with the SANDHOP_AUTH user/password to continue your session in the browser.

Sandbox providers

Sandhop is provider-agnostic. sandhop setup configures the default; override per-run with --provider.

Provider --provider Credentials (collected by sandhop setup)
E2B (default) e2b E2B_API_KEY
Modal modal MODAL_TOKEN_ID, MODAL_TOKEN_SECRET
Daytona daytona DAYTONA_API_KEY (+ optional DAYTONA_TARGET)
Vercel Sandbox vercel VERCEL_TOKEN, VERCEL_TEAM_ID, VERCEL_PROJECT_ID

Each provider SDK is an optional dependency, loaded lazily — installing Sandhop does not pull all four. The CLI resolves credentials environment first, then the sandhop setup store, so CI/scripts can just export the env vars and skip setup.

Usage

sandhop push                              # teleport the latest session in $(pwd)
sandhop push --provider modal             # choose a provider for this run
sandhop push --tunnel cloudflared         # private/portable URL (see below)
sandhop push --agent codex --session <id> # pin the agent and a specific session
sandhop list                              # list running sandboxes
sandhop kill <sandbox-id>                 # destroy a sandbox

Flags

  • --provider e2b|modal|daytona|vercel — sandbox provider (default: configured / e2b).
  • --tunnel public|cloudflared — URL transport (default: configured / public).
  • --agent claude-code|codex — force the agent (default: auto-detect from the cwd's sessions).
  • --session <id> — resume a specific session instead of the newest for the cwd.
  • --cwd <path> — operate on a directory other than the process cwd.
  • --exclude <patterns> — comma-split archive excludes; repeatable.
  • --include <absolute paths> — comma-split extra files/directories to recreate at the same absolute path; repeatable.
  • --no-profile — skip inline profile/skill transfer; settings-script, MCP, and plugin enrichment still run.
  • --no-ssh — skip transferring git SSH keys for the project's remotes (transferred hosts are listed in the push output).

Transports / private access

  • --tunnel public (default): exposes ttyd through the provider's HTTPS preview, gated by Sandhop's per-teleport ttyd Basic Auth.
  • (WIP) --tunnel cloudflared: binds ttyd to loopback and runs cloudflared inside the sandbox. Works through provider egress where native expose is token-gated (e.g. Daytona).
    • Quick tunnel (default): zero-config *.trycloudflare.com URL + Basic Auth.
    • Named tunnel (Access-gated, private): set CLOUDFLARE_TUNNEL_TOKEN + CLOUDFLARE_TUNNEL_HOSTNAME (or via sandhop setup); Sandhop returns https://<your-hostname> and Cloudflare Access enforces login.

What transfers

  • Working tree — full dirty/uncommitted state, restored at its original absolute path so the resumed session's recorded cwd matches.
  • Transcript — the exact session file; resumed natively (claude --resume / codex resume), not re-injected.
  • Agent auth — Claude/Codex credentials shipped as sandbox env/credential files over TLS, never inside the project tarball.
  • Referenced secrets — env vars and credential files needed by the detected agent/MCP config.
  • Explicit includes — each --include <absolute path> is recreated at the same absolute path in the sandbox.

How it works

  1. Collect the working-tree root, transcript, auth, secrets, and local CLI version in parallel.
  2. Create a single-tenant ephemeral sandbox that preserves the local home path, prepares files as provider root, and starts services as the non-root local-username runtime.
  3. Upload the bundle, transcript, credential files, SSH files, project memory, and explicit includes.
  4. Install the matching agent CLI, restore the transcript, start the terminal service, and verify service readiness.
  5. Run inline enrichment for agent profile, settings scripts, MCP code/deps, plugins, marketplaces, and skills before printing SANDHOP_URL / SANDHOP_AUTH. Enrichment steps fail soft: a failed step is reported (Environment ready · 6/7 steps ok) but never destroys the sandbox, and skipped MCP servers (e.g. localhost-bound) are listed with reasons.

Development

npm ci
npm run build
npx vitest run

License

MIT © Talking Computers

About

Teleport a live local Claude Code / Codex session to a cloud sandbox and continue in an auth-gated web terminal

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages