Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5109ddf
docs(workspace): add unified stage-over-fleet layout plan (#992)
Juliusolsson05 Sep 18, 2026
f501447
feat(workspace): stage 1 of unified layout — v3 shape types and v2→v3…
Juliusolsson05 Sep 18, 2026
64d5739
feat(workspace): live v3 stage/project/pool views derived over v2 sta…
Juliusolsson05 Sep 18, 2026
ee9a646
chore: restore package-lock.json pruned by worktree npm install
Juliusolsson05 Sep 18, 2026
65f6b53
feat(workspace): stage always renders — grid/classic/tile-tabs branch…
Juliusolsson05 Sep 18, 2026
0c95953
feat(commands): one workspace surface — grid/dispatch mode gating del…
Juliusolsson05 Sep 18, 2026
94de112
feat(workspace): autosave writes the v3 stage triple and durable pool…
Juliusolsson05 Sep 18, 2026
23bf1f6
feat(workspace): stage 3a — delete Tile Tabs, bury/revive, grid attac…
Juliusolsson05 Sep 18, 2026
9a34787
refactor(workspace): make the lane grid a required stage (#992 stage …
Juliusolsson05 Sep 18, 2026
890ebe4
refactor(workspace): delete the tile tree; a session's project lives …
Juliusolsson05 Sep 18, 2026
13a9687
feat(workspace): context-places spawn, Clear Lane, and honest create …
Juliusolsson05 Sep 19, 2026
dd9805d
feat(keyboard): register the lane arrow grammar; delete the grid context
Juliusolsson05 Sep 19, 2026
c6107a6
feat(onboarding): starter card with live keybind hints on fresh agent…
Juliusolsson05 Sep 19, 2026
0d2ff7b
feat(contracts): narrow the published layout schema and retire mode v…
Juliusolsson05 Sep 19, 2026
6dd5830
chore(cleanup): delete the workspace-mode setting and retire mode voc…
Juliusolsson05 Sep 19, 2026
e52b035
Merge origin/main into feat/unified-stage-layout
Juliusolsson05 Sep 19, 2026
ceb3870
fix(workspace): restore main's lockfile and pin the merged projection…
Juliusolsson05 Sep 19, 2026
cbf5203
Merge origin/main into feat/unified-stage-layout
Juliusolsson05 Sep 19, 2026
ce2d1f2
test(workspace): pin the file version and pre-upgrade backup on a rea…
Juliusolsson05 Sep 19, 2026
e3ff921
fix(workspace): write the stage document as file version 3 and back u…
Juliusolsson05 Sep 19, 2026
8e398b1
test(workspace): pin v2-to-v3 migration on real persisted workspaces
Juliusolsson05 Sep 19, 2026
52d9f30
fix(workspace): commands follow the agent picked inside Spotlight
Juliusolsson05 Sep 19, 2026
a409c85
fix(extensions): a cold legacy command reveals its view so it can run
Juliusolsson05 Sep 19, 2026
b12b54f
refactor(workspace): drop related-agent leftovers and stale mode comm…
Juliusolsson05 Sep 19, 2026
db7a2f9
fix(settings): prune saved overrides for the commands the stage retired
Juliusolsson05 Sep 19, 2026
eb04658
fix(workspace): list orchestration grandchildren under their root
Juliusolsson05 Sep 19, 2026
60a3910
fix(workspace): clear the new badge on every placement, and badge ⌘T'…
Juliusolsson05 Sep 19, 2026
0e0d69a
fix(keyboard): ⌥⌫ never clears a lane from an extension input or full…
Juliusolsson05 Sep 19, 2026
33e62de
docs: agent-facing descriptions and glossary describe the stage, not …
Juliusolsson05 Sep 19, 2026
c8f0c5a
fix(workspace): the collapsed-children row shows a hidden child's new…
Juliusolsson05 Sep 19, 2026
af0c88d
test(workspace): pin the lane keyboard grammar and the ⌘ two-digit ro…
Juliusolsson05 Sep 19, 2026
837bda7
Merge remote-tracking branch 'origin/main' into feat/unified-stage-la…
Juliusolsson05 Sep 19, 2026
461ab40
fix(workspace): Close Tab closes the commanded agent's project, not t…
Juliusolsson05 Sep 19, 2026
3f61d42
fix(workspace): a failed pre-upgrade backup leaves no truncated file
Juliusolsson05 Sep 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 32 additions & 28 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,7 @@ accTitle: Why does streaming output not save the whole workspace?
accDescr: Layout changes and agent output update different stores. Only workspace metadata goes through workspace persistence.
%% scope: Renderer data flow · persisted layout versus live session state
subgraph Layout["Workspace changes"]
Action["Move a pane / change a tab"] -->|updates placement| Metadata["Workspace metadata"]
Action["Move a lane / switch project"] -->|updates placement| Metadata["Workspace metadata"]
Metadata -->|persists via preload| Saved[("Saved workspace")]
end
subgraph Live["Live agent output"]
Expand Down Expand Up @@ -1483,49 +1483,54 @@ Closing a window while the app continues can transfer its sessions to a survivin

<!-- architecture-diagram: workspace-model -->

[![How does the grid refer to its sessions?](docs/architecture/diagrams/workspace-model.svg)](docs/architecture/diagrams/workspace-model.svg)
[![How does the stage refer to its sessions?](docs/architecture/diagrams/workspace-model.svg)](docs/architecture/diagrams/workspace-model.svg)

A split contains two tiles; a leaf refers to session metadata by ID. Rearranging tiles changes placement without making the layout own a provider process.
A lane refers to session metadata by ID; a session's PROJECT is a field on its own row. Rearranging lanes changes placement without making the layout own a provider process.

<details>
<summary>Mermaid source</summary>

```text
classDiagram
accTitle: How does the grid refer to its sessions?
accDescr: A split contains two tiles; a leaf refers to session metadata by ID. Rearranging tiles changes placement without making the layout own a provider process.
%% scope: Grid layout · selected type relationships, not runtime class inheritance
accTitle: How does the stage refer to its sessions?
accDescr: A lane refers to session metadata by ID; a session's project is a field on its own row. Rearranging lanes changes placement without making the layout own a provider process.
%% scope: Stage layout · selected type relationships, not runtime class inheritance
direction LR
class Tab
class TileNode {
<<union>>
class WorkspaceState
class Stage {
lanes
rows
focusedLane
}
class TileLeaf {
sessionId
}
class TileSplit {
direction
ratio
class DispatchLane {
selectedSessionId
}
class SessionMeta {
kind
providerRuntime
cwd
projectId
joinedAt
}
class Project {
id
title
}
Tab *-- TileNode : root
TileNode <|-- TileLeaf : leaf variant
TileNode <|-- TileSplit : split variant
TileSplit "1" *-- "2" TileNode : children
TileLeaf ..> SessionMeta : references sessionId
WorkspaceState *-- Stage
WorkspaceState *-- SessionMeta : sessions by ID
WorkspaceState *-- Project : projects
Stage *-- DispatchLane : row-major
DispatchLane ..> SessionMeta : references sessionId
SessionMeta ..> Project : projectId names a project
```

</details>

`TileNode` is a TypeScript discriminated union: a leaf references a session, while a split contains child tiles. The class notation here summarizes that data structure. Each split has exactly two children, either of which can be a leaf or another split. A split ratio is normalized to the allowed range; a tab's focused session must be an actual leaf.
A session is OWNED iff its `projectId` names a project that exists; unowned rows are dropped at the read boundary. Lane selections, pins and the active project are pointers, never ownership — a stale pointer must not keep a session alive or bring one back. A project exists while at least one session names it and is removed by the commit that takes its last session.

Grid placement, Dispatch Mode lanes, pinning, detached sessions, and buried sessions describe visibility and organization. They do not by themselves terminate a backend. Dispatch lanes are a flat ordered sequence with explicit row structure; row weights and scope are normalized separately. Empty lanes remain meaningful and are not automatically populated from the session pool.
Lane placement, pinning and pool parking describe visibility and organization. They do not by themselves terminate a backend. Lanes are a flat row-major sequence with explicit row structure; row weights and per-row project bindings are normalized separately. Empty lanes remain meaningful and are not automatically populated from the session pool, and an occupied lane is never displaced by a spawn (context-places).

Related-session selection can display a child in a physical grid leaf owned by another session. Linked terminal parentage is a one-level association with cascading close behavior. Orchestration parent/root/run metadata is a separate relationship and should not be reused as the linked-terminal tree.
Linked terminal parentage is a one-level association with cascading close behavior. Orchestration parent/root/run metadata is a separate relationship and should not be reused as the linked-terminal tree.

#### 6.2.3 Recovery preserves the workspace shell

Expand Down Expand Up @@ -3074,12 +3079,11 @@ Sources: [Vitest configuration](vitest.config.ts), [live configuration](vitest.l
| Application session | Stable Agent Code identity associated with workspace metadata and, when active, a managed backend |
| Session run | One backend execution attempt, distinguished from the stable application session |
| Native session identity | Provider-owned conversation identity used to locate/resume native history |
| Pane / tile | A visible workspace placement; it is not itself a provider process |
| Project tab | A workspace membership boundary that can differ from another tab using the same directory |
| Dispatch Mode | Workspace presentation using explicitly ordered agent lanes and independent scope/focus |
| Stage | The one workspace layout: rows of lanes beside the agent index. Each lane shows at most one session |
| Lane | A visible slot on the stage; selecting a session into it shows that session. It is not itself a provider process |
| Pool | Every session a project owns. A session not in any lane is still in the pool, alive or hibernated |
| Project | A workspace membership boundary (`projectId` on each session) that can differ from another project using the same directory |
| Hibernated session | Retained session metadata whose backend is intentionally absent until wake |
| Buried session | Hidden retained session placement; a live backend can continue running |
| Detached session | Session associated with the workspace/project but not placed in the ordinary grid |
| Provider runtime flavor | The execution mechanism for a provider, such as structured OpenCode versus OpenCode terminal |
| PTY | Pseudoterminal connecting the application to a native interactive process |
| tmux attachment | A PTY connection to a separately managed persistent shell session |
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ a running session can move mid-task among Claude Code, Codex, and OpenCode.
- **Persistent terminals** — tmux-backed shells that survive UI reloads.
- **Built-in MCP + agent control** — orchestration lets a parent create and
coordinate real Agent Code children. The independently configurable Agent
Management MCP can inventory every grid, Dispatch, and buried agent in the
caller's project, expose transcript/activity evidence, read bounded outputs,
and send follow-ups. Destructive close is restricted to an explicit current
Management MCP can inventory every agent in the caller's project — on a
lane or parked in the pool — expose transcript/activity evidence, read
bounded outputs, and send follow-ups. Destructive close is restricted to an explicit current
user request and refuses self-close or multi-session cascades.

<p align="center">
<img src="docs/screenshots/orchestration.png" alt="Agent Code Dispatch sidebar with orchestration MCP tool calls (send_prompt, wait_agents, read_agent, close_run) running in a live session" />
<img src="docs/screenshots/orchestration.png" alt="Agent Code agent index with orchestration MCP tool calls (send_prompt, wait_agents, read_agent, close_run) running in a live session" />
</p>

- **TLDR peek** — enable **TLDR MCP** for an agent, then hold **Cmd+L** to
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/diagrams/renderer-state.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/architecture/diagrams/workspace-model.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions docs/command-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This repo treats command titles as stable names, not as descriptions of the curr
## Rules

1. Use a stable noun phrase for toggles and modes.
Examples: `Reader Mode`, `Spotlight`, `Tiled Tabs`, `Dangerous Agents`, `Git Bar`.
Examples: `Reader Mode`, `Spotlight`, `Auto-follow All Visible Agents`, `Git Bar`.

2. Do not encode state changes into the title.
Avoid: `Toggle`, `Enable`, `Disable`, `Enter`, `Exit`, `Turn On`, `Turn Off`.
Expand All @@ -14,7 +14,7 @@ This repo treats command titles as stable names, not as descriptions of the curr
Use short badges like `On`, `Off`, `Claude`, `Codex`, `Active`.

4. Use imperative verbs for one-shot actions.
Examples: `Open Settings`, `Copy Last Response`, `Normalize Layout`, `Reload Agent`.
Examples: `Open Settings`, `Copy Last Response`, `Close Focused Session`, `Reload Agent`.

5. Use `New X` for creation commands.
Examples: `New Tab`, `New Agent`, `New Terminal Right`.
Expand Down
Loading
Loading