cmux NEXT spaces: Move Space to This Window and Merge All Windows
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.- Titles are in ProfileActions.xcstrings and ActionCatalog.xcstrings (en and ja translated; the other locales are
needs_review, as in neighbouring entries). plans/cmux-next/action-surfaces.jsonandactions.mdare left to the base autofix (regenerate-action-exports.sh).
Risk
- Additive. No existing default, component or menu row is changed or removed.
- The Window menu gains one row, so
MainMenuPlacementTestsnow expects 10 Window rows instead of 9. - Both actions run one registry transition (
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
- New
GatherWindowsTests(.closesItsWindows):- Bring-here closes the window it emptied and keeps the space's last shown workspace selected.
- Only that space's workspaces move, and a source window that keeps other spaces stays open.
- Incognito space or window is refused and nothing changes.
- Merge-all keeps each workspace's space, closes the merged windows and leaves the incognito window alone.
SpaceSurfacesTestsnamesspace.bringHereand checks it is in the space menu.- Focused fleet Mac run (
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 62fed54c5b9f: this head (69b56f9016ae) with #27301 merged in, on a CI-only branch. At this head alone, CmuxNextAppTests does not compile because of the base red from #27166 (BrowserEntryRetirementTests.swift:43:57, "returning main actor-isolated ... as a 'sending' result"; step c559ae7de547b95c91d859b5). This PR does not touch that file, and #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 59c45ae21f5a: 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. SpaceSurfacesTests and MainMenuPlacementTests pin 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