[BUG] Background sessions never receive SIGWINCH — TUI never reflows on terminal resize
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Environment
- Claude Code: 2.1.232 (native, linux-x64)
- OS: CentOS Stream 9, kernel 6.16, x86_64
- Terminal: Ghostty over SSH, inside tmux 3.7b
- Config:
"tui": "fullscreen"(also reproduces with"default")
Summary
Background sessions (claude --bg, or dispatched from claude agents / "agent view") are given a
pty that is not their controlling terminal. The kernel delivers SIGWINCH only to the
foreground process group of a pty's session, so a process with no controlling terminal can never
receive one.
The pty itself is resized correctly, and the renderer even has a working SIGWINCH handler
installed — it just never fires. The session keeps drawing at whatever size it had at startup,
forever.
Foreground sessions are unaffected.
Root cause
Every layer except signal delivery is correct, which is what makes this hard to spot:
| layer | state after a resize |
| --- | --- |
| terminal / ssh / tmux client / tmux pane | correct (479) |
| the session's pty — stty -F /dev/pts/N size | correct (479) |
| SigCgt bit 27 on the renderer | set — a SIGWINCH handler is installed |
| /proc/<pid>/stat field 7 (tty_nr) | 0 — no controlling terminal |
| ps -t /dev/pts/N | empty — nothing owns that pty as its ctty |
| the rendered frame | stale (239) — the handler never fires |
Concretely, for a background renderer:
$ readlink /proc/<PID>/fd/1
/dev/pts/26
$ awk '{print $7}' /proc/<PID>/stat # tty_nr
0 # <-- no controlling terminal
$ awk '$1=="SigCgt:"{print $2}' /proc/<PID>/status
000000017b826cff # bit 27 set: SIGWINCH IS handled
$ ps -t /dev/pts/26 # nothing claims it as ctty
(empty)
$ stty -F /dev/pts/26 size # pty geometry is correct
97 197
Proof
Delivering the signal by hand — which the kernel cannot do — fixes it instantly:
$ kill -WINCH <renderer-pid>
# frame immediately re-lays-out from 239 to 479 columns
Why the obvious workarounds don't help
- Resizing again / waiting — no hook exists to fire; the pty is already the right size.
Ctrl-L, tmux zoom/unzoom — these do force a repaint, but it repaints at the cached size.kill -WINCHon the foreground session — no effect; wrong process. The stale frame belongs to
the background renderer.
/tui default— cannot help. It reports:
> Saved. Background sessions always use the fullscreen renderer while attached; the default
> renderer will apply to sessions started directly with claude.
So the renderer-switch restart never applies to an attached background session.
- Detach and reattach in agent view — works sometimes, because attaching re-pushes a size; it
is a race.
A foreground claude in the same terminal reflows correctly (verified 100 → 160 columns with
both tui: "default" and tui: "fullscreen"), which isolates this to the background-session pty
path.
Suggested fix
Either of:
- Have the pty host
setsid()+ioctl(TIOCSCTTY)in the child so the pty becomes its controlling
terminal. The kernel then delivers SIGWINCH on every resize and no application-level plumbing
is needed. This seems like the correct fix.
- Have agent view send an explicit resize message over the background-session socket and have the
child apply it (TIOCSWINSZ on itself, or re-read + relayout), rather than relying on a kernel
signal that cannot arrive.
What Should Happen?
The attached background session's frame reflows to the new width/height, the way a foreground
session does.
Error Messages/Logs
Steps to Reproduce
- Start
claudein a terminal and dispatch a background agent (claude --bg "...", or from agent
view).
- Run
claude agentsand attach to that background session. - Resize the terminal window.
The frame keeps rendering at its startup size. In my case a 239-column frame inside a 479-column
pane — the input box border is drawn 239 wide with 240 columns of dead space to the right. It never
recovers, regardless of how long you wait or how many times you resize.
Claude Model
None
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.232
Platform
Google Vertex AI
Operating System
Other Linux
Terminal/Shell
Other
Additional Information
_No response_
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗