# Panes, Workspaces & Layout

> Compares tmux's sessions, windows, panes, split commands, and layout tree mechanics with cmux's workspaces, panels, Bonsplit-backed layout state, terminal panels, and persisted surface snapshots.

- Repository: tmux/tmux-with-manaflow-ai-cmux
- GitHub: https://github.com/tmux/tmux
- Human wiki: https://grok-wiki.com/public/wiki/tmux-tmux-with-manaflow-ai-cmux-62db34dfaddc
- Complete Markdown: https://grok-wiki.com/public/wiki/tmux-tmux-with-manaflow-ai-cmux-62db34dfaddc/llms-full.txt

## Source Files

- `tmux-tmux:window.c`
- `tmux-tmux:layout.c`
- `tmux-tmux:layout-set.c`
- `tmux-tmux:cmd-split-window.c`
- `tmux-tmux:spawn.c`
- `manaflow-ai-cmux:Sources/Workspace.swift`
- `manaflow-ai-cmux:Sources/TabManager.swift`
- `manaflow-ai-cmux:Sources/Panels/TerminalPanel.swift`

---

<details>
<summary>Relevant source files</summary>
The following files were used as context for generating this wiki page:
- [tmux-tmux:window.c](tmux-tmux/window.c)
- [tmux-tmux:layout.c](tmux-tmux/layout.c)
- [tmux-tmux:layout-set.c](tmux-tmux/layout-set.c)
- [tmux-tmux:cmd-split-window.c](tmux-tmux/cmd-split-window.c)
- [tmux-tmux:spawn.c](tmux-tmux/spawn.c)
- [tmux-tmux:tmux.h](tmux-tmux/tmux.h)
- [manaflow-ai-cmux:Sources/Workspace.swift](manaflow-ai-cmux/Sources/Workspace.swift)
- [manaflow-ai-cmux:Sources/TabManager.swift](manaflow-ai-cmux/Sources/TabManager.swift)
- [manaflow-ai-cmux:Sources/Panels/TerminalPanel.swift](manaflow-ai-cmux/Sources/Panels/TerminalPanel.swift)
- [manaflow-ai-cmux:Sources/Panels/Panel.swift](manaflow-ai-cmux/Sources/Panels/Panel.swift)
- [manaflow-ai-cmux:Sources/SessionPersistence.swift](manaflow-ai-cmux/Sources/SessionPersistence.swift)
- [manaflow-ai-cmux:Sources/TerminalController.swift](manaflow-ai-cmux/Sources/TerminalController.swift)
</details>

# Panes, Workspaces & Layout

This page compares tmux's terminal-native model of sessions, windows, panes, split commands, and mutable layout cells with cmux's app-level model of workspaces, panels, Bonsplit panes, surface tabs, and persisted session snapshots.

The useful contrast is ownership. tmux owns pseudo-terminals and screen geometry directly inside a server process. cmux owns higher-level UI surfaces, maps them onto Bonsplit layout state, and persists enough metadata to reconstruct the user workspace after restart.

## Mental Model

```text
tmux                                      cmux
session                                  TabManager
  winlink index -> window                  Workspace[]
                  window                    Workspace
                    panes[]                   panels[UUID]
                    active pane               surfaceIdToPanelId[TabID]
                    layout_root               BonsplitController tree
```

tmux separates a globally stored `window` from per-session `winlink` entries, so the same window can be linked into session-local window trees. cmux treats a `Workspace` as the sidebar tab and gives each workspace one `BonsplitController`; panels are app objects addressed by stable UUIDs while Bonsplit tabs are the layout/tab-strip handles.

Sources: [tmux-tmux:window.c:45-52](), [tmux-tmux:tmux.h:1509-1524](), [tmux-tmux:tmux.h:1350-1408](), [tmux-tmux:tmux.h:1412-1429](), [manaflow-ai-cmux:Sources/Workspace.swift:8973-9033](), [manaflow-ai-cmux:Sources/Workspace.swift:9921-10025]()

## Object Ownership

| Concern | tmux | cmux |
|---|---|---|
| Top-level user container | `session`, with current window and a tree of `winlink` entries. | `TabManager` owns `Workspace` tabs. |
| Layout container | `window`, with pane list, active pane, and `layout_root`. | `Workspace`, with one `BonsplitController`. |
| Leaf content | `window_pane`, containing PTY/process state, screen state, size, offsets, and layout cell pointer. | `Panel` implementations such as `TerminalPanel`, `BrowserPanel`, markdown, file preview, and right sidebar tool. |
| Layout identity | `layout_cell` tree points directly at panes. | Bonsplit pane/tab IDs are mapped to stable panel UUIDs through `surfaceIdToPanelId`. |

Sources: [tmux-tmux:tmux.h:1250-1345](), [tmux-tmux:tmux.h:1350-1488](), [manaflow-ai-cmux:Sources/Panels/Panel.swift:5-37](), [manaflow-ai-cmux:Sources/Panels/TerminalPanel.swift:6-23](), [manaflow-ai-cmux:Sources/Workspace.swift:9018-9033](), [manaflow-ai-cmux:Sources/Workspace.swift:10010-10025]()

## Splitting Panes

### tmux

`split-window` first resolves geometry into either a tiled or floating layout cell. For normal tiled panes, it refuses to split floating panes, computes split geometry, pushes zoom state, calls `layout_split_pane`, then passes a `spawn_context` to `spawn_pane`. `spawn_pane` creates or reuses a `window_pane`, assigns the prepared layout cell, and forks the process through a PTY.

Sources: [tmux-tmux:cmd-split-window.c:72-127](), [tmux-tmux:cmd-split-window.c:160-195](), [tmux-tmux:spawn.c:249-280](), [tmux-tmux:spawn.c:363-405]()

### cmux

cmux splitting is panel-first and Bonsplit-backed. `newTerminalSplit` finds the source panel's Bonsplit tab and pane, creates a new `TerminalPanel`, pre-generates a `Bonsplit.Tab`, installs the surface-to-panel mapping before layout mutation, then calls `bonsplitController.splitPane`. This is explicitly done to avoid transient empty-panel flashes while the layout changes.

Sources: [manaflow-ai-cmux:Sources/Workspace.swift:12312-12345](), [manaflow-ai-cmux:Sources/Workspace.swift:12396-12418](), [manaflow-ai-cmux:Sources/Workspace.swift:12427-12458](), [manaflow-ai-cmux:Sources/Workspace.swift:12615-12690]()

## Layout Trees

tmux's layout tree is internal C state. A `layout_cell` is either a split node (`LAYOUT_LEFTRIGHT`, `LAYOUT_TOPBOTTOM`, `LAYOUT_FLOATING`) or a `LAYOUT_WINDOWPANE` leaf. Split operations may insert into an existing same-orientation parent, create a new root, or resize an existing full-size root before inserting a child.

```c
/* tmux-tmux:tmux.h */
struct layout_cell {
    enum layout_type type;
    struct layout_cell *parent;
    u_int sx, sy;
    int xoff, yoff;
    struct window_pane *wp;
    struct layout_cells cells;
};
```

cmux persists a higher-level tree shape. A `SessionWorkspaceLayoutSnapshot` is either a pane containing ordered panel IDs and a selected panel ID, or a split containing orientation, divider position, and two children. That makes persisted layout state independent of live AppKit view objects and Bonsplit runtime IDs.

Sources: [tmux-tmux:tmux.h:1460-1488](), [tmux-tmux:layout.c:203-237](), [tmux-tmux:layout.c:984-1158](), [manaflow-ai-cmux:Sources/SessionPersistence.swift:1473-1519](), [manaflow-ai-cmux:Sources/Workspace.swift:352-373]()

## Resizing And Presets

tmux has built-in layout arrangers: even horizontal, even vertical, main-horizontal, main-vertical, mirrored variants, and tiled. These rebuild or redistribute the layout tree, then fix offsets and pane sizes. The tiled layout computes rows and columns, skips floating panes, builds row/column cells, and adjusts the final row or column to fill available space.

cmux delegates interactive split geometry to Bonsplit, but it snapshots divider positions and can reapply them during session restore with `setDividerPosition`. Debug tooling also asks Bonsplit for a `layoutSnapshot`, then correlates pane frames with selected panels and live AppKit view frames.

Sources: [tmux-tmux:layout-set.c:31-121](), [tmux-tmux:layout-set.c:139-185](), [tmux-tmux:layout-set.c:615-726](), [manaflow-ai-cmux:Sources/Workspace.swift:1199-1217](), [manaflow-ai-cmux:Sources/TerminalController.swift:17590-17758]()

## Persistence And Restore

tmux keeps pane state in the server process: panes carry PTY/process fields, screen buffers, size, offsets, and the current layout cell. Reattaching clients redisplays the virtual screen state, but this code path is not a structured app-session snapshot format.

cmux has explicit session persistence. A workspace snapshot stores title/custom metadata, current directory, focused panel, layout tree, panels, status/log/progress/git metadata, and optional remote configuration. Restore rebuilds the Bonsplit tree first, creates panels into each restored pane, prunes stale metadata, reapplies divider positions, and restores focus through old-to-new panel ID mapping.

Sources: [tmux-tmux:window.c:45-47](), [tmux-tmux:tmux.h:1250-1326](), [manaflow-ai-cmux:Sources/SessionPersistence.swift:1232-1256](), [manaflow-ai-cmux:Sources/SessionPersistence.swift:1429-1539](), [manaflow-ai-cmux:Sources/Workspace.swift:163-250](), [manaflow-ai-cmux:Sources/Workspace.swift:253-350](), [manaflow-ai-cmux:Sources/Workspace.swift:799-890]()

## Focus And Close Semantics

tmux focus is window-local: `window_set_active_pane` unzooms if needed, updates the last-pane stack, marks the active pane changed, sends focus events when enabled, updates window offsets, redraws, and emits `window-pane-changed`.

cmux focus crosses model and UI boundaries. `focusPanel` maps a panel UUID back to a Bonsplit tab, finds the containing pane, focuses that pane if needed, selects the tab, and then applies AppKit focus intent so keyboard input reaches the intended surface. Closing similarly begins from stable panel IDs but routes through Bonsplit tab close requests.

Sources: [tmux-tmux:window.c:524-554](), [tmux-tmux:window.c:804-833](), [manaflow-ai-cmux:Sources/Workspace.swift:13253-13297](), [manaflow-ai-cmux:Sources/Workspace.swift:14019-14120](), [manaflow-ai-cmux:Sources/TabManager.swift:6264-6335]()

## Portable Design Lessons

tmux is stronger as a compact terminal multiplexer core: geometry, PTYs, process lifetime, pane focus, and screen buffers are tightly integrated. cmux is stronger as an application workspace surface: multiple panel types, UI focus repair, browser/terminal surfaces, session snapshots, and layout restore are explicit product concerns.

The portable idea is to keep layout state provider-neutral. Neither system's layout model requires a model provider or hosted service: tmux uses C structs and PTYs; cmux uses file-serializable `Codable` snapshots, stable UUID panel IDs, and a layout adapter boundary around Bonsplit. That keeps BYOC/BYOK-friendly integrations possible because agents, terminals, browser panels, and future skill sources can remain panel payloads rather than hard dependencies of the layout tree.

Sources: [tmux-tmux:layout.c:595-662](), [tmux-tmux:layout.c:1161-1177](), [manaflow-ai-cmux:Sources/Panels/Panel.swift:5-37](), [manaflow-ai-cmux:Sources/SessionPersistence.swift:1473-1539](), [manaflow-ai-cmux:Sources/Workspace.swift:10010-10025]()

## Source And Method Note

No local `STRATEGY.md` or `docs/solutions/**` source was found in the prepared workspace during this focused pass. The selected Compound Engineering guidance was treated as bundled page-shape and QA routing context only; implementation claims above are grounded in repository code rather than an installed local workflow or any model-provider-specific tool.

In short: tmux makes panes the primitive and grows session/window semantics around them; cmux makes workspaces and panels the primitive, then projects them into Bonsplit layout state and persisted snapshots. The architectural bridge is the tree: tmux's tree is live geometry over panes, while cmux's tree is restorable UI structure over stable panel identities. Sources: [tmux-tmux:tmux.h:1250-1488](), [manaflow-ai-cmux:Sources/SessionPersistence.swift:1473-1539]()
