Repository navigation
feat(claude): detach from Claude Code with Ctrl-Q and resume the live session - #56
Conversation
|
Blocking issue: the Ctrl+Q translation is not safe when a kitty/modifyOtherKeys CSI sequence is split across terminal reads.
Please retain incomplete input CSI bytes between reads, translate once the sequence completes, and add an end-to-end regression test that writes the Ctrl+Q sequence in at least two chunks. The existing |
bf8a2a8 to
b98d2b6
Compare
|
Thanks, fixed: an unterminated CSI sequence at the end of a read is now kept until the next read completes it (or forwarded as is after 50ms if nothing follows, so a lone Esc isn't stuck). The |
… session Unlike OpenCode, Claude Code has no server to reconnect to: it ran as the `exec` of the attach, so leaving a workspace killed Claude and any turn in progress. - Run Claude under dtach inside the container (socket /tmp/opencode-manager-claude.sock). Ctrl-Q detaches back to the dashboard while Claude keeps working; the next attach resumes the same session. Ctrl-C stays with Claude to interrupt a turn. Ctrl-Q is unbound in Claude Code and typeable on any layout (Ctrl-\, dtach's default, needs AltGr on AZERTY). - Add dtach to the base image, and install it best-effort in the workspace image when the base predates it. Without dtach, attaching runs Claude directly, as before. - Relay Claude attaches (TUI and `ocm ws attach`) through a host-side pty (internal/termproxy). Claude switches capable terminals to the kitty keyboard protocol and modifyOtherKeys, where Ctrl-Q arrives as an escape sequence dtach never matches; the relay rewrites it to the raw byte. It also resets the keyboard/reporting modes Claude enabled once detached, so the dashboard keeps working, replays them on reattach, and briefly narrows the pty by one column so Claude repaints its whole screen instead of showing a blank one. - Document the detach keys (TUI guide, getting started, CLI, README). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The relay translated each read on its own, so a kitty or modifyOtherKeys Ctrl-Q split across reads (ESC[113; then 5u) reached dtach unchanged and did not detach. Hold back an unterminated control sequence at the end of a read until the next one completes it, or forward it as is after 50ms, so a lone Escape key press is not stuck. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
b98d2b6 to
50c349c
Compare
Problem
OpenCode survives leaving a workspace because the attach is only a client of a persistent
opencode serve. Claude Code has no server: it ran as theexecof the attach, so leaving a workspace killed Claude and whatever turn it was running. There was no way to go back to the dashboard while Claude kept working.Fix
Claude runs under dtach inside the container. The Claude attach command becomes
dtach -A /tmp/opencode-manager-claude.sock -e '^q' -r winch -z claude: the first attach starts the session, later attaches reconnect to it, andCtrl+Qdetaches back to the dashboard while Claude keeps running (its status stays live through the existing hooks).Ctrl+Cstays with Claude to interrupt a turn.Ctrl+Qis unbound in Claude Code and typeable on every layout; dtach's defaultCtrl+\needs AltGr on AZERTY.dtachis added to the base image, andDockerfile.workspaceinstalls it best-effort when the resolved base predates it. Withoutdtach, attaching runs Claude directly, as before.Claude attaches are relayed through a host-side pty (
internal/termproxy). Three problems only show up with a real terminal:Ctrl+Qarrives asESC[113;5u/ESC[27;5;113~instead of0x11. The relay rewrites those encodings (press/repeat, Caps/Num Lock, alternate-key fields) to the raw byte.The relay is used by the TUI (
Enter/Ctrl+A) andocm ws attach --runtime claude. OpenCode and DeepSeek attaches are unchanged. The relay reads stdin throughmuesli/cancelreader(already used by Bubble Tea), so no goroutine is left holding the terminal after a detach. New dependency:github.com/creack/pty.Shortcut documentation
docs/tui.md: a "Returning to the dashboard" table (OpenCodeCtrl+C, Claude CodeCtrl+Q) and a "Detaching from Claude Code" section.docs/getting-started.md,docs/cli.md(ws attach) andREADME.mdmention the detach keys.AGENTS.mdnotes for future changes.Testing
gofmt,go vet ./...andgo test ./...pass; the branch also builds fordarwin/arm64.Ctrl+Qas0x11, and the terminal is reset afterwards), the redraw resize, and the attach script with and withoutdtach.claudeunderdtachthrough the relay in a pty harness: Claude enabled the kitty protocol,Ctrl+Qdetached with the session still alive, and a reattach repainted the full screen (before the redraw fix: 42 bytes of output and no text).Notes: no version bump, left to your release tags. Existing workspaces rebuild their image once (the build context changed) to pick up
dtach.🤖 Generated with Claude Code