Repository navigation
Conversation
A phone sharing a terminal with the same user's Mac under the default fit-everyone policy gets min(Mac, phone) and shows an empty band. These cases expect the phone to switch that terminal to follow the latest device and count itself, once, unless the user turned the preference off or already chose a policy or counts override, or the grid already fills the phone. Adds the preference key and the store's defaults seam the tests inject.
Under the default fit-everyone policy a phone next to the same user's Mac gets min(Mac, phone) and shows an empty band under a full-screen agent. When a size state shows this phone letterboxed under the untouched default, with no counts choice of its own, the phone counts itself and switches the terminal to follow the latest device, once per terminal. The grid then fills whichever device was used last, through RPCs the Mac already accepts. TerminalSizingState.isFillScreenClaimable(by:) holds the decision; the cmux.mobile.fillScreenWhenShared preference (default on) turns it off.
Settings > Terminal gets "Fill Screen in Shared Terminals", on by default. It writes cmux.mobile.fillScreenWhenShared, which the shell reads before it claims a letterboxed terminal. Strings in all nine locales.
Follow latest resizes the grid under the phone on any Mac keystroke, and the phone's render stalls mid-stream on that resize. The claim should put this phone first in a priority policy, move build 7's follow-latest claims over, and hand the grid back while the phone is inactive by default.
… latest Follow latest gave the grid back to the Mac on any Mac keystroke, including cmux send. The resize landed mid-stream and the phone went blank, then showed a stale 97x29 scaled grid until the next phone input. The phone now counts itself and comes first in a priority policy, keyed to its own device, so Mac input no longer resizes the grid while the phone shows the terminal. Build 7's follow-latest claims (latest with the phone counted) move over. Hand Off Terminal Sizing When Inactive now defaults to on, so the Mac takes the grid back when the phone goes to the background.
Seen on device with build 8: after Home and back, the Mac listed the phone with counts=false and kept its own 97x29 grid under the phone's priority claim. The reattached phone had lost its counts override, and the claimed-set guard stopped the phone from sending it again.
The claim decision now returns what to send. Under this phone's own priority policy with no counts choice, which is how the Mac sees a phone reattach after Hand Off, the phone re-sends counts_override true and leaves the policy alone. That repeat is guarded only while its request is in flight; the policy claim stays once per terminal.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a terminal is open on both the iPhone and the same person's Mac, the iPhone now fills its screen while it shows that terminal. Previously it showed a hatched empty band under the grid.
Cause. Each terminal's sizing policy defaults to Fit everyone (
.smallest), so the grid is the minimum of every viewer. A full-screen TUI such as Claude Code mirrors that grid exactly, so a phone next to a shorter Mac pane gets 72x44 and a blank band below.Fix. This is phone-only, so it works against an unchanged Mac (0.65.2). When a size state shows that this phone is letterboxed under the untouched default policy, the phone does two things, once per terminal:
counts_override: true.mobile.terminal.size_policy.setwith modepriorityand its own priority key (user/iphone/device).The phone then owns the grid while it counts. When it leaves the terminal, or goes to the background, the Mac takes the grid back through the priority fallback.
Why not Follow latest. The first version (build 7) used
latest. Any Mac keystroke then resized the grid under the phone, includingcmux sendfrom agents. I reproduced it on a real iPhone through iPhone Mirroring:With priority, Mac input does not change the owner.
Decision.
TerminalSizingState.fillScreenClaim(for:)returns what to send (countsThisPhone,policy), ornil. Three cases qualify:Every other policy or counts choice is left alone. The store marks the terminal claimed before sending, so repeated pushes don't resend, and unmarks it if a request fails.
Hand off. Hand Off Terminal Sizing When Inactive now defaults to on. Without it, a backgrounded phone would keep the Mac at the phone's size. A stored choice is kept.
Back from a hand-off. The Mac treats a returning phone as a fresh attach, without its counts override, so under the phone's own priority policy it stopped counting and the Mac kept the grid (seen on build 8). The decision now also covers this state: this phone's priority policy with no counts choice re-sends
counts_override: trueand leaves the policy alone. That repeat is guarded only while its request is in flight.Settings. Settings › Fill Screen in Shared Terminals turns the claim off. It is on by default.
Upstream manaflow-ai#27195 ("iPhone First") does the same thing with a new
handheld_firstpolicy field. That field needs a Mac update. Drop this once a release ships manaflow-ai#27195.Testing
Focused commands, with Xcode 26.3:
swift test --filter TerminalFillScreenClaimTestsinPackages/iOS/CmuxMobileShell.✘ Test run with 6 tests in 1 suite failed ... with 6 issues. The claim sentlatest, and build 7's follow-latest state was not moved.✔ Test run with 6 tests in 1 suite passed.swift testinPackages/iOS/CmuxMobileShellModel.fillScreenPolicy(for:)does not exist yet.verify-local.py --affected: 16/16.Observed / Not run
cmux surface size:priority-fallback). Coming back left the phone atcounts=falseunder the Mac's grid.Expectation failed: recounted), green on 60024f0 (14 tests across the two focused suites; model 445).MobileDisplaySettingsTests(CmuxMobileShellUI is iOS-only and needs a simulator run).// debt:comment.Changelog
Added: On iPhone, a terminal shared with your Mac fills the screen while you view it, and the Mac gets its size back when you leave (Settings › Fill Screen in Shared Terminals).
Stacked on #1.
🤖 Generated with Claude Code