Skip to content

fix(ssh): give up the wrapper's escape key on screen hosts - #175

Merged
kipavy merged 1 commit into
devfrom
fix/screen-escape-key
Aug 24, 2026
Merged

fix(ssh): give up the wrapper's escape key on screen hosts#175
kipavy merged 1 commit into
devfrom
fix/screen-escape-key

Conversation

@kipavy

@kipavy kipavy commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #170 / #159, found while verifying the GNU screen half of that fix end to end.

The gap

#170 made the tmux wrapper transparent — unset TMUX, and prefix None so C-b belongs to whatever the user runs inside. The screen fallback got the environment half but not the key half: our screen rc sets no escape, so the wrapper kept screen's default C-a and intercepted it.

Observed on a screen-only host, driving the app and polling the host while sending C-a d from inside a nested screen -r:

9616.mine (Attached)   voltius_… (Attached)
9616.mine (Attached)   voltius_… (Detached)   ← our wrapper took the key

The SSH channel then closed and the app reconnected under the user — their own screen never saw C-a.

The fix

screen has no prefix None equivalent: escape always names some key. It is pointed at \377 instead — a byte no key produces in a UTF-8 terminal — which is as close to "no escape key" as screen offers. The only theoretical cost is a latin-1 session where 0xFF is ÿ.

No version gate: escape and octal escapes long predate any screen still in use, and a screen that rejected the line would simply keep its default key. screen -x (the attach path) joins the running server, which keeps the setting this rc gave it at create time — same reasoning as the existing truecolor line.

Verification

Same host (GNU screen 5.0.2), same gesture, through the app:

9616.mine (Attached)   voltius_… (Attached)
9616.mine (Detached)   voltius_… (Attached)   ← the user's session took the key

The pane prints [detached from 9616.mine] and returns to the wrapper's shell, with the session timer running continuously — no reconnect. cargo test --lib shell_integration: 22/22, cargo fmt --check clean.

The tmux branch releases its prefix so a user's own tmux keeps C-b (#159),
but the screen fallback kept screen's default C-a. The outer wrapper
therefore swallowed it: a bare `C-a d` inside a nested screen detached
*our* session, the SSH channel closed, and the app silently reconnected —
the user's own screen never saw the key.

screen has no `prefix None` equivalent; `escape` always names some key. It
is now pointed at \377, a byte no key produces in a UTF-8 terminal, which is
as close to "no escape key" as screen gets. The one theoretical cost is a
latin-1 session where 0xFF is ÿ.

Verified on a screen-only host (GNU screen 5.0.2) through the app: attached
to the user's own session from inside a Voltius session, `C-a d` now prints
`[detached from 9616.mine]` and leaves the wrapper attached, where before
the wrapper flipped to (Detached) and reconnected underneath.
@kipavy
kipavy merged commit a3b1595 into dev Aug 24, 2026
4 checks passed
@kipavy
kipavy deleted the fix/screen-escape-key branch August 24, 2026 18:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant