Fix Shift+Enter not working in macos-container TUI #246

Merged
didericis merged 4 commits from fix-macos-container-shift-enter into main 2026-06-22 23:42:25 -04:00
Collaborator

Closes #245.

Summary

Apple's container exec --interactive --tty does not put the host terminal into raw mode before starting its I/O relay. In cooked (canonical) mode the kernel line discipline buffers modifier-key escape sequences — e.g. Shift+Enter in modifyOtherKeys mode generates \x1b[13;2~ — until a carriage-return arrives, so they never reach Claude Code inside the container.

Two changes land together:

  1. pty_forward.py — a new stdlib-only wrapper (modelled on the existing smolmachines/pty_resize.py) that sets the host terminal to raw mode via tty.setraw(), spawns the container exec command, and restores the original terminal attributes on exit. Falls back to a bare subprocess.run when stdin is not a TTY (piped invocations, CI) or when termios operations fail.

  2. --env TERM=<host> — retained from the first attempt: without TERM inside the container session, Claude Code cannot determine which modifier-key protocol to enable (modifyOtherKeys, kitty keyboard protocol) even with raw mode correctly set.

Changed files:

Closes #245. ## Summary Apple's `container exec --interactive --tty` does not put the host terminal into raw mode before starting its I/O relay. In cooked (canonical) mode the kernel line discipline buffers modifier-key escape sequences — e.g. Shift+Enter in `modifyOtherKeys` mode generates `\x1b[13;2~` — until a carriage-return arrives, so they never reach Claude Code inside the container. Two changes land together: 1. **`pty_forward.py`** — a new stdlib-only wrapper (modelled on the existing `smolmachines/pty_resize.py`) that sets the host terminal to raw mode via `tty.setraw()`, spawns the `container exec` command, and restores the original terminal attributes on exit. Falls back to a bare `subprocess.run` when stdin is not a TTY (piped invocations, CI) or when `termios` operations fail. 2. **`--env TERM=<host>`** — retained from the first attempt: without `TERM` inside the container session, Claude Code cannot determine which modifier-key protocol to enable (`modifyOtherKeys`, kitty keyboard protocol) even with raw mode correctly set. Changed files: - [`bot_bottle/backend/macos_container/pty_forward.py`](https://gitea.dideric.is/didericis/bot-bottle/src/commit/1c11110da529846b991561a50761ed1b4cbc785f/bot_bottle/backend/macos_container/pty_forward.py) — new raw-mode wrapper - [`bot_bottle/backend/macos_container/bottle.py`](https://gitea.dideric.is/didericis/bot-bottle/src/commit/1c11110da529846b991561a50761ed1b4cbc785f/bot_bottle/backend/macos_container/bottle.py) — `agent_argv` wraps TTY execs with `pty_forward.py` and forwards `TERM` - [`tests/unit/test_macos_container_bottle.py`](https://gitea.dideric.is/didericis/bot-bottle/src/commit/1c11110da529846b991561a50761ed1b4cbc785f/tests/unit/test_macos_container_bottle.py) — updated argv assertions - [`tests/unit/test_macos_container_pty_forward.py`](https://gitea.dideric.is/didericis/bot-bottle/src/commit/1c11110da529846b991561a50761ed1b4cbc785f/tests/unit/test_macos_container_pty_forward.py) — 8 new tests covering argv parsing, non-TTY fallback, and raw-mode setup/restore
didericis-claude added 1 commit 2026-06-22 21:53:49 -04:00
fix(macos-container): forward TERM env var in container exec --tty
lint / lint (push) Successful in 1m41s
test / unit (pull_request) Successful in 36s
test / integration (pull_request) Successful in 21s
25ca14a8a2
Without TERM, Claude Code inside the container cannot determine which
modifier-key protocol to enable (modifyOtherKeys / kitty). The inner
PTY session has no terminal-type context, so Shift+Enter and Enter
produce identical byte sequences (\r), making them indistinguishable.

Pass the host TERM via --env TERM=<value> on every container exec
--interactive --tty call, falling back to xterm-256color when TERM
is not set on the host. Non-TTY exec paths are unaffected.

Closes #245
didericis added 1 commit 2026-06-22 22:30:57 -04:00
fix(macos-container): set host terminal to raw mode for container exec
lint / lint (push) Failing after 1m42s
test / unit (pull_request) Successful in 33s
test / integration (pull_request) Successful in 19s
1c11110da5
Apple's container exec --interactive --tty does not put the host
terminal into raw mode before starting its I/O relay.  In cooked
(canonical) mode the kernel line discipline buffers modifier-key
escape sequences — e.g. Shift+Enter in modifyOtherKeys mode generates
\x1b[13;2~ — until a carriage-return arrives, so they never reach
Claude Code inside the container.

Add pty_forward.py, a stdlib-only wrapper (modelled on the existing
smolmachines pty_resize.py) that sets the host terminal to raw mode
via tty.setraw(), spawns the container exec command, and restores the
original terminal attributes on exit.  Falls back to a bare
subprocess.run when stdin is not a TTY (piped invocations, CI) or
when termios operations fail.

Also retain the --env TERM=<host> forwarding from the previous commit:
without TERM inside the container session, Claude Code cannot determine
which modifier-key protocol to enable even with raw mode correctly set.

Non-TTY exec paths (bottle.exec, cp_in) are unaffected.
didericis added 1 commit 2026-06-22 22:57:38 -04:00
fix(macos-container): forward terminal capability env
lint / lint (push) Failing after 1m48s
test / unit (pull_request) Successful in 34s
test / integration (pull_request) Successful in 20s
31b29631b6
didericis added 1 commit 2026-06-22 23:02:11 -04:00
test(macos-container): satisfy pyright mock typing
test / unit (pull_request) Successful in 33s
test / integration (pull_request) Successful in 18s
lint / lint (push) Successful in 1m35s
test / unit (push) Successful in 31s
test / integration (push) Successful in 15s
Update Quality Badges / update-badges (push) Successful in 1m20s
d314ccf455
didericis merged commit d314ccf455 into main 2026-06-22 23:42:25 -04:00
didericis deleted branch fix-macos-container-shift-enter 2026-06-22 23:42:25 -04:00
Sign in to join this conversation.