Skip to content

fix: create boo ui sessions at the viewport size#73

Merged
kylecarbs merged 1 commit into
mainfrom
fix/ui-session-birth-size
Jun 17, 2026
Merged

fix: create boo ui sessions at the viewport size#73
kylecarbs merged 1 commit into
mainfrom
fix/ui-session-birth-size

Conversation

@kylecarbs

Copy link
Copy Markdown
Member

Problem

A newly created terminal in boo ui appears at the wrong height until the terminal is resized. Reported repro: open a new session, run curl https://coder.com, and the output overflows the viewport.

Root cause

boo ui creates sessions by shelling out to boo new -d. That path starts the session daemon's PTY and ghostty terminal at the daemon default 24x80 (no size is ever passed in), and the UI only corrects the size when it attaches. So a freshly created session is born at the wrong geometry: its first prompt and any early output are laid out at 24x80 until the next resize re-runs layout. That is the "wrong until I resize" behavior.

ui.createSession()  ->  boo new -d            # daemon born at 24x80
                    ->  focusIndex/attach     # only now resized to the viewport

Fix

  • boo new gains --rows/--cols to set the session's initial terminal size (the 24x80 default is unchanged when the flags are absent).
  • boo ui's createSession passes the current viewport size, so a session is born at the geometry it will be displayed at.
  • The attach handshake still resizes, so reconnects and create/attach races stay correct.

Validation

  • New integration test: a detached boo new -d --rows 30 --cols 100 session reports 30 100 from stty size inside the child, with no attach, proving the size reaches the PTY at creation. (Sanity-checked by deliberately asserting the wrong value and confirming it fails reporting the real 30 100.)
  • Drove the real boo ui under a PTY + VT emulator: new sessions are born at the viewport size (e.g. 40 rows x 85 cols in a 40x110 terminal) and curl output stays within the viewport.
  • zig fmt --check, zig build test, and zig build test-integration all pass.
Investigation & decision log

How I traced it

  • boo ui renders sessions in a sub-viewport (full terminal height, cols - sidebar - 1). createSession runs boo new -d; runDaemon -> Daemon.run never sets rows/cols, so Options defaults to 24x80 and the child PTY + ghostty terminal are born at 24x80.
  • The daemon resizes on both .attach (then repaints) and .resize. Both the daemon term and the PTY winsize are updated, and libghostty's grow/shrink (including scrollback reflow) is robust, so the final state is correct after attach.

Honest note on reproduction

I was not able to reproduce a persistent visual overflow on Linux: in a real-PTY + VT-emulator harness at 16/40/50 rows, with both seq output and the literal curl https://coder.com, the attach resize always corrected the final frame and content stayed within the viewport. What is unambiguously wrong is the birth size: the session (and its child process's first output) starts at 24x80 and is only corrected on attach. That is the exact mechanism behind "new terminal is wrong until I resize," so this change fixes the root cause; the residual visible artifact on the reporter's setup is likely terminal/timing dependent (first-frame reflow, delayed SIGWINCH). Happy to dig further with the reporter's terminal + size if it persists after this.

Scope

  • Interactive boo new / boo attach are intentionally left on the existing attach-handshake sizing: they render the daemon's screen 1:1 in the real terminal, so the transient is invisible there.
  • --rows/--cols are also useful for automation (creating a headless session at a known size).

This PR was generated by Coder Agents on behalf of @kylecarbs.

New sessions in `boo ui` were created with `boo new -d`, which starts the session daemon's PTY and ghostty terminal at the default 24x80. The UI only corrected the size on attach, so a freshly created session was born at the wrong geometry: its first prompt and early output were laid out at 24x80 until the next resize.

Add --rows/--cols to `boo new` and have the UI pass the viewport size at creation, so a session is born at the geometry it will be shown at. The attach handshake still resizes, so reconnects and races stay correct.
@kylecarbs kylecarbs merged commit 9120b76 into main Jun 17, 2026
5 checks passed
BenLocal added a commit to BenLocal/boo that referenced this pull request Jun 18, 2026
Brings in upstream coder#73 (boo ui sessions created at the viewport size),
coder#74 (capture held prefix keys via kitty release events), coder#75 (scrollback
replay on attach), and the v0.5.21/v0.5.22 releases.

Conflict resolution:
- main.zig / daemon.zig: union the createSession / runDaemon / Options
  params — self's state_dir/cwd/max_scrollback (restore + config) plus
  main's rows/cols (viewport-size fix). restoreOne passes null rows/cols.
- scrollback replay (ui.zig, daemon.zig, protocol.zig, client.zig): self
  and main implemented the same feature two ways. Kept main's design (a
  separate `.ui` marker message before a SizePayload attach) and dropped
  self's redundant AttachPayload.ui flag, so client and daemon agree on
  the wire.
- window.zig: kept self's added alt-screen historyReplay test.

Verified: zig fmt, zig build, unit tests, and PTY integration tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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