Layout Modes
The desktop has two top-level layouts: workspace (sidebar rail + optional lists panel + main + optional inspector) and compact (header-only). The active mode is chosen automatically from window width and persisted per window; the inspector can embed in workspace mode or float as an overlay in compact mode.
Layout modes are how the desktop adapts to wide displays, narrow displays, and everything in between without losing functionality.
The two top-level modes
The desktop runs in one of two modes at any time. Workspace is the full layout: a 64 px sidebar rail on the left, an optional 250 px lists panel for the active tab, the main content area, and an optional 300 px inspector on the right. Compact collapses the rail and lists panel into a header-only layout for narrow windows. The dispatch happens in cmd/cmdop-desktop/frontend/src/layouts/layoutSwitch.tsx and is driven by the useDesktopLayoutMode() context hook.
Workspace layout — four inner variants
Inside workspace mode there are four inner variants, picked by resolveWorkspaceLayoutMode() in WorkspaceLayout/modes.ts:
| Variant | Composition | When |
|---|---|---|
| Lists + Main + Inspector | Rail + 250 px list + main + 300 px inspector | Wide windows with an active inspector target |
| Lists + Main | Rail + 250 px list + main | Wide windows with no file in the inspector |
| Main + Inspector | Rail + main + 300 px inspector | Medium windows where the lists panel would crowd the main pane |
| Main only | Rail + main | Tabs that have no list (e.g., Activity in tail mode) |
The dispatch is reactive — the layout reflows the moment a tab opens an inspector target or the window crosses a breakpoint.
Compact mode
Compact mode is the narrow-window fallback. The 64 px rail and the lists panel both collapse, leaving a header bar with tab navigation and the main pane underneath. The inspector is still available but it floats as an overlay over the main pane (mounted conditionally in AppShell.tsx) instead of taking a dedicated column. Compact mode is intentionally Spartan — it is for laptops on the move, not for daily work.
Compact mode is selected automatically when the window is below the breakpoint, but you can force it from Settings → Appearance → “Force compact layout” regardless of width.
Inspector placement
The inspector toggles between two placements depending on layout mode. In workspace mode it embeds as a third column on the right and shares the window with the lists panel and main pane. In compact mode it slides in as an overlay over the main pane and dismisses on Esc. The inspector itself is the same React tree in both placements — only the surrounding shell differs.
Persistence and per-window state
Layout preferences are persisted per-window through useLayoutPrefs(), which reads and writes a layoutPrefs store backed by localStorage. That means opening a second window does not inherit the first window’s compact override — each window remembers its own state. Closing and reopening a window restores the last saved layout.
Layout preferences live in localStorage. Clearing browser-style storage from the desktop’s developer tools resets layout state along with everything else.
Forcing a mode
Settings → Appearance exposes a “Force compact layout” toggle that overrides the automatic dispatch. Use it on wide screens when you want a minimal surface (for example, when streaming a desktop and only the chat needs to be visible).
How tabs interact with layout
Each tab declares whether it has a lists panel. Chat, Machines, Board, Activity, Connection, and Projects all have one; Settings does not. When you switch to a tab with no lists panel the layout reflows to the “Main + Inspector” or “Main only” variant automatically.