Conversation
Member
Author
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1056 +/- ##
==========================================
- Coverage 82.56% 81.81% -0.76%
==========================================
Files 31 31
Lines 2770 2925 +155
Branches 518 546 +28
==========================================
+ Hits 2287 2393 +106
- Misses 346 392 +46
- Partials 137 140 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
cd2526a to
ed3063a
Compare
Member
Author
Code reviewFound 1 issue:
tmuxp/src/tmuxp/workspace/builder.py Lines 508 to 514 in ed3063a Contradicted by the PR's own test: tmuxp/tests/workspace/test_builder.py Lines 2165 to 2173 in ed3063a 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
This was referenced Jun 27, 2026
why: Loading a workspace waited for each pane's shell prompt one pane at a time, so a window's load cost scaled with its pane count. Preparing a window's panes together lets their shells warm up in parallel and collapses the per-window wait into a single readiness barrier. what: - Create a window's panes up front, then wait for every default-shell pane in one barrier before applying the layout and sending commands. - Honor the pane_readiness policy (auto/always/never) resolved in build(): auto waits only for zsh, so non-zsh shells skip the wait; always forces it; never disables it. - Fall back to sequential per-pane setup when later panes depend on an earlier pane's start_directory side effects. - Run before_script attached to the terminal by default so interactive prompts and TTY-aware tools behave normally. Restore panel capture with --progress-lines / TMUXP_PROGRESS_LINES.
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
_wait_for_panes_ready) that polls all of a window's default-shell panes together under one shared timeout.%fix: no pane is resized before its shell has drawn its prompt;select_layoutruns once per window, after that window's barrier.before_scripthandling to match the new build-event ordering (see Follow-on changes).Motivation
#1018 fixed the long-standing zsh
%marker (#365) by waiting for each pane's shell to draw its prompt before applying its layout. That wait ran serially: pane N+1 wasn't split until pane N was ready. Because tmux starts a pane's shell the moment the pane is split, the shells in a window already warm up concurrently — only the observation of readiness was serial. With a heavy interactive rc file, a window's load cost becamepanes × shell-init, the regression reported in #1053.Design decisions
Concurrent barrier per window. A window's panes are all split first, so their shells initialize together; a single barrier then waits for every default-shell pane in that window under one shared timeout. Readiness becomes one observation pass over all the panes instead of one blocking wait per pane.
Per-window, not whole-session. Windows are built one at a time: create panes → barrier → lay out → dispatch commands → finish → next window. A window's commands run before the next window is created, so a later window can depend on side effects of an earlier one (e.g. a
start_directorywhose directory an earlier command created). The readiness wait is collapsed within a window; window-to-window ordering is unchanged.Split the newest pane; defer layout until after the barrier. A split resizes the pane it targets, and the build only ever splits the newest pane — created microseconds earlier and still sourcing its rc, which is safe to resize. The window's single
select_layoutis deferred until after its barrier, when every shell in the window is past its prompt. Why not keep a per-splitselect_layout? That call also resizes the older panes; if one is mid-prompt, the resize races zsh's prompt redraw and resurrects the%marker.Adaptive space reclaim. Without a per-split layout, a window with many panes can run out of room for the next split.
_split_pane_reclaiming_spacehandles this: on a no-space failure it first waits for the window's existing panes (so they are safe to resize), runsselect_layoutto redistribute, then retries. Reclaim never resizes a not-ready pane, and a genuinely-too-small window still raises as before (#800).Internal and always-on. No new YAML keys or tunables; the barrier just makes the existing readiness behavior cheap.
Follow-on changes
Building a window's panes together (rather than one-ready-then-next) changes the grouping and ordering of build events, so two adjacent areas needed updates:
src/tmuxp/cli/_progress.py):window_doneevents now carry window identity, and the default progress bar tracks created vs. finished windows so the bar and the window label stay in sync as panes are created.before_scriptstreaming (src/tmuxp/cli/load.py,src/tmuxp/util.py):before_scriptinherits the terminal's stdio by default so TTY-aware tools run interactively, the spinner starts only afterbefore_scriptfinishes, and its output is captured into the panel only when a nonzero--progress-linesis requested.synchronize-panesrestore (src/tmuxp/workspace/builder.py): the temporarysynchronize-panesdisable is isolated to pane-command dispatch and skips targets for panes that exited during startup.Before / After
Readiness wait for a window with N default-shell panes:
Test plan
Builder / readiness:
test_wait_for_panes_ready_all_ready,test_wait_for_panes_ready_mixed— the barrier reports each pane ready and times out only non-prompt panestest_wait_for_pane_ready_returns_true,test_wait_for_pane_ready_timeout— the one-pane wrappertest_pane_readiness_waits_for_default_shell_panes— only default-shell panes enter the barrier (customshell/window_shellskipped)test_build_waits_for_each_window_before_dispatch— a window's panes are awaited together before its commands runtest_select_layout_called_once_per_window,test_layout_runs_after_readiness_barrier— the Outputs % / percent sign after every command in some panes #365 invariant:select_layoutruns once per window, after that window's barriertest_split_target_refreshes_without_readiness_wait— splitting no longer blocks on a per-pane prompt waittest_build_dispatches_window_commands_before_later_start_directory— a later window can depend on an earlier window's command side effectstest_issue_800_default_size_many_windows— reclaim still re-raises when a window is genuinely too small (no space for new pane with main-horizontal and a few panes #800)test_synchronize_panes_disabled_during_pane_commands,test_synchronize_panes_ignores_exited_targets— sync isolation and skipping exited targetstest_plugin_hook_order—on_window_create/after_window_finishedorder across windowsProgress / before_script:
test_builder_window_done_events_include_window_identity— completion events carry window identitytest_spinner_default_progress_tracks_started_window_in_phase_one,test_spinner_default_progress_tracks_completed_window_in_phase_two— bar and label stay in synctest_load_workspace_pauses_spinner_for_before_script— spinner starts afterbefore_scripttest_load_workspace_handles_explicit_before_script_progress_lines—before_scriptoutput captured into the panel only on explicit--progress-linesSuite / quality:
uv run py.test— full suite greenuv run mypy— strict, cleanuv run ruff check . && uv run ruff format .— cleanuv run py.test --doctest-modules src/tmuxp/workspace/builder.py— doctests for the readiness helpers