Skip to content

feat: hopx shell — create a sandbox and open a terminal in one step#1

Merged
alexo-bunnyshell merged 3 commits into
mainfrom
feat/shell-command
May 31, 2026
Merged

feat: hopx shell — create a sandbox and open a terminal in one step#1
alexo-bunnyshell merged 3 commits into
mainfrom
feat/shell-command

Conversation

@alexo-bunnyshell
Copy link
Copy Markdown
Contributor

Summary

Connecting to a fresh sandbox took two commands — hopx sandbox create, then copying the printed ID into hopx terminal <id>. This PR adds hopx shell (alias sh) that does both in one step.

hopx shell                      # default template, terminal opens
hopx shell -t code-interpreter
hopx shell -e KEY=value --timeout 600
hopx shell --rm                 # ephemeral: kill the sandbox on exit
  • Creates the sandbox and attaches an interactive terminal directly to the live object returned by Sandbox.create() — no reconnect round-trip.
  • Reuses create's provisioning options: --template/-t, --timeout, --env/-e.
  • Prints the sandbox ID on connect, so even an ephemeral session is recoverable until exit.

Lifecycle on exit

  • Default: the sandbox keeps running after you exit; reattach with hopx terminal <id>.
  • --rm: ephemeral — the sandbox is killed when the session ends (à la docker run --rm).

Refactor

The interactive-terminal plumbing (raw stdin forwarding, resize handling, cleanup) was extracted from terminal.ts into src/lib/terminal/session.ts and is now shared by both terminal and shell. No behavior change for hopx terminal (it's now a thin wrapper). The shared helper takes an onExit hook, which --rm uses to kill the sandbox before exit.

Changes

  • src/commands/shell.ts — new command
  • src/lib/terminal/session.ts — shared attachInteractiveTerminal() helper
  • src/commands/terminal.ts — refactored onto the helper (~70 fewer lines)
  • src/index.ts — register shellCommand
  • Docs: README (commands table, quick-start, "Interactive Shell" section), CLAUDE.md, CHANGELOG
  • Version bump 0.2.2 → 0.3.0 (package.json + version.ts)
  • Unit test for the shell command shape
  • chore commit: pin bun via mise.toml, gitignore mise.local.toml (local secrets)

Testing

  • bun test (offline): 200 pass, 0 fail
  • E2E against prod (SKIP_E2E=0, real key): 21 pass, 0 fail
  • hopx shell --help / --version verified; tsc --noEmit clean for all touched files

Note: a full end-to-end manual hopx shell session against a live backend wasn't run in CI; worth a quick manual smoke test before release.

🤖 Generated with Claude Code

alexo-bunnyshell and others added 2 commits May 31, 2026 18:39
… step

Connecting to a fresh sandbox took two commands — `sandbox create`, then
`terminal <id>` with the printed ID. `hopx shell` (alias `sh`) does both:
creates a sandbox and attaches an interactive terminal to the live object
(no reconnect round-trip). It reuses create's provisioning options
(--template/-t, --timeout, --env/-e) and prints the sandbox ID on connect.

By default the sandbox persists after you exit and can be reattached with
`hopx terminal <id>`; `--rm` makes it ephemeral (killed on exit, like
`docker run --rm`).

The interactive-terminal plumbing (stdin forwarding, resize, cleanup) is
extracted into src/lib/terminal/session.ts and shared by both `terminal`
and `shell` — no behavior change for `terminal`.

Bumps 0.2.2 -> 0.3.0; updates README, CLAUDE.md, CHANGELOG; adds a unit test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a mise.toml pinning bun (the project's runtime) so contributors get a
consistent toolchain, and gitignores mise.local.toml where local secrets
such as HOPX_API_KEY / HOPX_BASE_URL live.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alexo-bunnyshell alexo-bunnyshell added the ready-for-human Requires human implementation label May 31, 2026
attachInteractiveTerminal connects the terminal WebSocket as its first
action; if that rejects (e.g. agent not ready) after the sandbox was
already created, the onExit hook never ran and a `--rm` sandbox was left
running and billable. Wrap the attach call and best-effort kill on `--rm`
before rethrowing. The kill logic is shared with the onExit hook.

Addresses review feedback on PR #1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alexo-bunnyshell alexo-bunnyshell merged commit ac56ea6 into main May 31, 2026
1 check passed
@alexo-bunnyshell alexo-bunnyshell deleted the feat/shell-command branch May 31, 2026 22:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Requires human implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant