Add 'claudebox tmux <box> [session]' — attach-or-create a named tmux session in the box #6

Closed
opened 2026-07-11 13:09:21 +00:00 by dan-claude-bot · 0 comments
dan-claude-bot commented 2026-07-11 13:09:21 +00:00 (Migrated from github.com)

Problem

claudebox shell is a bare incus exec ... sudo -u claude -i. The shell is a child of the exec connection: if the operator's terminal or SSH session drops, everything running in it gets SIGHUP'd — a long Claude run dies. tmux is already installed and configured in the box, but using it relies on remembering to start it, and it's easy to forget (this has already cost one long run).

Proposal

Do not change shell — it stays bare and predictable (exit means exit, no nesting surprises). Add a sibling verb whose whole job is persistence:

claudebox tmux <box> [session]     # default session: main

which runs, inside the box:

tmux new-session -A -s <session>

-A is the contract: attach if the session exists, create it if not. So starting work and reattaching after a disconnect are the same commandclaudebox tmux incubator — with no state to remember.

The optional session name buys parallel long-running streams per box:

claudebox tmux incubator work-1    # long Claude run lives here
claudebox tmux incubator work-2    # second stream, same box, independent

Drop your SSH connection, come back, type the same command, and the run is still going.

Why a verb instead of changing shell

The original version of this issue proposed making shell attach tmux by default, and carried a cons list for it: nested-tmux prefix conflicts when the host terminal is itself in tmux, tmux owning scrollback/copy-paste, exit-vs-detach muscle-memory mismatch. As a separate opt-in verb, every one of those costs is only paid by someone who asked for tmux — and shell keeps being the escape hatch when tmux semantics are in the way. Two verbs, two contracts: shell = a plain shell, tmux = a session that survives you.

Notes for the implementer

  • Same resolve + tag boundary as every other verb: the box name goes through resolve_box(), untagged instances refused.
  • Session names should be validated or at least safely quoted on the way to tmux -s.
  • claudebox info <box> (or the verb itself with no session and none existing) could list live sessions via tmux ls — nice-to-have, not required.
  • After #17's rename this is box tmux <box> [session] — nothing Claude-specific in it.

🤖 Generated with Claude Code

## Problem `claudebox shell` is a bare `incus exec ... sudo -u claude -i`. The shell is a child of the exec connection: if the operator's terminal or SSH session drops, everything running in it gets SIGHUP'd — a long Claude run dies. tmux is already installed and configured in the box, but using it relies on remembering to start it, and it's easy to forget (this has already cost one long run). ## Proposal Do **not** change `shell` — it stays bare and predictable (`exit` means exit, no nesting surprises). Add a sibling verb whose whole job is persistence: ```sh claudebox tmux <box> [session] # default session: main ``` which runs, inside the box: ```sh tmux new-session -A -s <session> ``` `-A` is the contract: attach if the session exists, create it if not. So starting work and reattaching after a disconnect are the **same command** — `claudebox tmux incubator` — with no state to remember. The optional session name buys parallel long-running streams per box: ```sh claudebox tmux incubator work-1 # long Claude run lives here claudebox tmux incubator work-2 # second stream, same box, independent ``` Drop your SSH connection, come back, type the same command, and the run is still going. ## Why a verb instead of changing `shell` The original version of this issue proposed making `shell` attach tmux by default, and carried a cons list for it: nested-tmux prefix conflicts when the host terminal is itself in tmux, tmux owning scrollback/copy-paste, `exit`-vs-detach muscle-memory mismatch. As a **separate opt-in verb**, every one of those costs is only paid by someone who asked for tmux — and `shell` keeps being the escape hatch when tmux semantics are in the way. Two verbs, two contracts: `shell` = a plain shell, `tmux` = a session that survives you. ## Notes for the implementer - Same resolve + tag boundary as every other verb: the box name goes through `resolve_box()`, untagged instances refused. - Session names should be validated or at least safely quoted on the way to `tmux -s`. - `claudebox info <box>` (or the verb itself with no session and none existing) could list live sessions via `tmux ls` — nice-to-have, not required. - After #17's rename this is `box tmux <box> [session]` — nothing Claude-specific in it. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/box#6
No description provided.