Repository navigation
cmux NEXT spaces: Move Space to This Window and Merge All Windows - #27327
teamleaderleo wants to merge 5 commits into
Conversation
Leo 2026-10-29: "there's also other ergo wrt new windows being like new spaces ... this could legit make our thing more useful than chrome by having windows be switchable in this way". - space.bringHere "Move Space to This Window" (palette, the space's right-click menu after Open in New Window, cmux space bring-here, MCP): every workspace of the space another normal window holds moves into this window, which shows the space with the workspace it last showed; a window left with none closes (WindowRegistry.move). Refused for an incognito space or window. - window.mergeAll "Merge All Windows" (Window menu, palette, cmux app merge-all-windows, MCP): every other open normal window's workspaces move here, each keeping its space; those windows close; incognito windows are left alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-a6ff86326d44fa86c638
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on 0ce3c31 to compare; do not merge until green; see lane-rules |
|
Owned by an agent session · session |
Default changesThis pull request changes 5 defaults at
Signed off on this commit by Regenerate the snapshot with |
|
Bead |
|
Found 7 test failures on Blacksmith runners: Failures
|
|
Review (codex gpt-6-astra high, next-review): SHIP at 69b56f9 No blocking findings. |
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
A newer verdict blocks 59c45ae (no independent SHIP at the head).
|
Review (codex-review-box/gpt-6-astra high, lane-place): BLOCK at 59c45ae BLOCK
|
|
Review (codex gpt-6-astra high fast, independent review host): BLOCK at 59c45ae
VERDICT: BLOCK |
…nd window.mergeAll Generated on the fleet by scripts/cmux-next/regenerate-action-exports.sh at 59c45ae; the only change is the two new actions and their counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-89c8bbec072d313a51cd
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
…g-here # Conflicts: # plans/cmux-next/actions.md
…without focus permission A CLI or MCP run without view-change permission still moves the space's workspaces, but the window keeps its space and selection, as New Space does (RoomHandlers.startNewSpace). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-89c8bbec072d313a51cd
|
Review (codex gpt-6-astra high fast, independent review host): SHIP at 36e595d No actionable correctness findings in the supplied diff at Static review only; builds and tests were not run. VERDICT: SHIP |
|
Carried onto #28049 with its commits and authorship, plus a fix for its own cmux-next checks red (action-wait and app-size guardrails). Its review is running there. This PR's branch can't be updated by the drain lane, so the work continues there. |
…rries #27327) (#28049) * cmux NEXT spaces: Move Space to This Window and Merge All Windows Leo 2026-10-29: "there's also other ergo wrt new windows being like new spaces ... this could legit make our thing more useful than chrome by having windows be switchable in this way". - space.bringHere "Move Space to This Window" (palette, the space's right-click menu after Open in New Window, cmux space bring-here, MCP): every workspace of the space another normal window holds moves into this window, which shows the space with the workspace it last showed; a window left with none closes (WindowRegistry.move). Refused for an incognito space or window. - window.mergeAll "Merge All Windows" (Window menu, palette, cmux app merge-all-windows, MCP): every other open normal window's workspaces move here, each keeping its space; those windows close; incognito windows are left alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-a6ff86326d44fa86c638 * cmux NEXT spaces: regenerate the action exports for space.bringHere and window.mergeAll Generated on the fleet by scripts/cmux-next/regenerate-action-exports.sh at 59c45ae; the only change is the two new actions and their counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-89c8bbec072d313a51cd * cmux NEXT spaces: Move Space to This Window keeps the view for a run without focus permission A CLI or MCP run without view-change permission still moves the space's workspaces, but the window keeps its space and selection, as New Space does (RoomHandlers.startNewSpace). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-89c8bbec072d313a51cd * fix(cmux-next spaces): Merge All Windows is a typed effect; the gather code joins WindowManager+Profiles The pre-push gate (and cmux-next checks' 'Pushed commits add no violations') refused #27327 for two guardrails it added: an untyped registry.bind for window.mergeAll (action-wait) and a new CmuxNextApp file (app-size). window.mergeAll now binds with the throwing bindEffect(requires:effect:), which refuses a thrown ActionFailure the same way and returns .done; WindowManager+Gather's extension moves unchanged into WindowManager+Profiles (a space move is a profile operation), which the app-size rule only warns about. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f050dc5d5c747badec51 * Test: Move Space to This Window leaves unresolved workspaces in their window Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window: leave unresolved workspaces in their window A workspace no session reports yet shows in every space, so bringing any space here moved it too and could close its window. Move only workspaces whose space is known. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Regenerate cmux-next action and defaults exports From the cmux-next-generated-patch artifact of run 41139330932. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: a workspace being created in a window that Move Space or Merge All closes follows the move Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window, Merge All Windows: claims follow the move A workspace being created in a source window the move closed kept its claim on that window, so reconcile reopened it when the workspace arrived. Retarget those claims (and drop the closed window's pending frame) to the acting window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: a pending sidebar placement follows Move Space and Merge All too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window, Merge All Windows: pending sidebar placements follow the move Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: a create queued before Move Space or Merge All lands in the acting window Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window, Merge All Windows: a create queued before the move lands in the acting window Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: Move Space and Merge All refuse to close a window still creating a workspace Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window, Merge All Windows: refuse to close a window still creating a workspace The earlier retargeting covered claims and placements but not queued lane creates or provisional rows. Refuse the move instead while a window it would close has a create in flight (claim, placement, lane, row); nothing changes and the user retries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: a window's own Home stays with its window, and local browser tabs move with their pane Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window, Merge All Windows: a window's own Home stays with its window; local browser tabs move with their pane Merge All moved each window's Home next to this window's Home, where closeSurplus closed it with the terminals beside it. Window Homes now stay in their window, which Merge All closes (kept as a closed window, terminals running, as Close Other Windows). Session-local browser tabs of moved panes move to the receiving window's state. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: carrying local browser tabs leaves other windows' panes alone Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window, Merge All Windows: carry local browser tabs from each workspace's own window only Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: a window incognito only by its space is no gather source Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window, Merge All Windows: a window on an incognito space is no source Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test fixture: use daemon handle types for screens, panes and surfaces Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: carried browser tabs never mix into a colliding pane id Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Local browser tabs: a carried pane never mixes into a colliding pane id Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: a pane-id collision in the receiving window refuses the move and loses no tabs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window, Merge All Windows: refuse when a moved pane's id collides with this window's browser tabs Session-local browser tabs are keyed by pane id, which older daemons can repeat across machines. Refuse the move before anything changes instead of mixing or dropping tabs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: a window keeping its own browser tabs is not gathered Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window, Merge All Windows: refuse instead of carrying window-kept browser tabs Window-kept browser tabs (daemons without frontend browser tabs) are keyed by pane id, which can repeat across machines, and die with their window. Carrying them kept turning up mixing and loss cases; refuse a move that takes a workspace out of such a window instead. Nothing moves or closes, and no tab is lost. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: no gather into a window that keeps its own browser tabs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window, Merge All Windows: refuse a move into a window keeping its own browser tabs too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: no-op gathers ignore window-kept tabs; an unregistered target gathers nothing Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window, Merge All Windows: no-op gathers ignore window-kept tabs; refuse an unregistered target Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: Merge All leaves unresolved workspaces in their window; incognito-source test counts every member Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Merge All Windows: move only workspaces a session reports; an unresolved one (a Home not mirrored yet) stays in its window Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: a closed window's selection is not the space's last shown workspace Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space to This Window: only an open window's selection counts as the space's last shown Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: Move Space's fallback switch leaves another window's Home Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space: the fallback switch leaves other windows' Homes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: a source window still creating a workspace gives nothing up Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space: refuse taking workspaces from a window still creating one Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space, Merge All: a window's claim protecting its own unreported workspace is no create Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Test: Move Space and Merge All leave the store's Home in its window Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 * Move Space, Merge All: the store's Home stays in its window as a window's Home does Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-710a4a518c009a6ad126 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: ci <ci@example.invalid> Co-authored-by: cmux-bot[bot] <348531757+cmux-bot[bot]@users.noreply.github.com>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Leo (2026-10-29): "could u guys also now work on the per space pins and groups? rn anything u make in teh default space goes across to new ones... there's also other ergo wrt new windows being like new spaces, incognito spaces, etc... this could legit make our thing more useful than chrome by having windows be switchable in this way. think of the potential perf savings~"
This PR covers the windows part of that ask. Per-space pins and groups are not in it.
What changed
space.bringHere"Move Space to This Window": the reverse of Open Space in New Window. Every workspace of the space that another normal window holds (open or closed) moves into the acting window. That window then shows the space and selects the workspace the space last showed (the one a window showing the space had selected, else the one remembered for the space). If no other window holds any of the space's workspaces, it is a plain space switch. Workspaces only change owner, so terminals keep running and nothing restarts. A source window left with no workspace closes through the existingWindowRegistry.move/closeEmptiedpath. A source window that still holds other spaces' workspaces stays open. Moving an incognito space, or moving into an incognito window, is refused with the existingRefusalStrings.incognitoMismatchHUD. Surfaces: the palette, the space's right-click menu ("Move to This Window", next to Open in New Window),cmux space bring-here, and MCP (spaces-overhaul-DESIGN.md rule 7).window.mergeAll"Merge All Windows": every other open normal window's workspaces move into the acting window, and each workspace keeps its space. The other windows close. The acting window stays on its space with the same selection. For spaces it never showed, it takes each merged window's last shown workspace, so switching there shows what that window showed. Incognito windows are left alone, and running it from an incognito window is refused. Surfaces: the Window menu (after New Incognito Window), the palette,cmux app merge-all-windows, and MCP. It has a context-menu exemption, as Close Other Windows does.needs_review, as in neighbouring entries).plans/cmux-next/action-surfaces.jsonandactions.mdare left to the base autofix (regenerate-action-exports.sh).Risk
MainMenuPlacementTestsnow expects 10 Window rows instead of 9.transition { $0.move(...) }), the same pathswitchProfileadoption and Move to Window use. Incognito windows are filtered out of the sources before the move, socrossesIncognitonever drops the batch.Tests
GatherWindowsTests(.closesItsWindows):SpaceSurfacesTestsnamesspace.bringHereand checks it is in the space menu.package-test-lane.shsuite GatherWindowsTests, SpaceSurfacesTests, MainMenuPlacementTests, ActionSurfaceParityTests, ShowWorkspaceOtherRoomTests, IncognitoSpaceTests): all 6 suites passed (ActionSurfaceParityTests: 2 export-freshness tests skipped as usual). cmux-ci step 0ca0e2da7b669522ed80b23f, at 62fed54: this head (69b56f9) with test(next): BrowserEntryRetirementTests compiles again (base red from #27166) #27301 merged in, on a CI-only branch. At this head alone, CmuxNextAppTests does not compile because of the base red from fix(next): retire browser pages before chrome teardown #27166 (BrowserEntryRetirementTests.swift:43:57, "returning main actor-isolated ... as a 'sending' result"; step c559ae7de547b95c91d859b5). This PR does not touch that file, and test(next): BrowserEntryRetirementTests compiles again (base red from #27166) #27301 fixes it.No capture: the only visible change is new rows in the Window menu, the space's right-click menu and the command palette, and the main window is unchanged. A fleet capture (steps-6d58e8bbea at 59c45ae: open the palette, type "merge all", then "to this window") keeps one still of the main window, and the palette panel and menus draw in their own windows outside it, so the still shows nothing new.
SpaceSurfacesTestsandMainMenuPlacementTestspin the new rows instead.Performance
No perf numbers: the word "perf" here is Leo's quote ("think of the potential perf savings"). This PR adds two window actions and changes no hot path, timer or observer; it measures nothing.
Agent session: agent session
🤖 Generated with Claude Code