Files
AgentHub/docs/superpowers/specs/2026-08-14-split-terminal-view-design.md
nntrivi2001 17d56d0e01 refactor!: rebrand CCAM to AgentHub
Clean break, no compatibility alias. Renames the product name, the CLI
binary (`ccam` -> `agenthub`), the env var prefix (`CCAM_` ->
`AGENTHUB_`), the Prometheus metric namespace (`ccam_*` ->
`agenthub_*`), the tmux session prefix (`ccam-lane-<id>` ->
`agenthub-lane-<id>`), the per-repo runtime profile directory
(`.ccam/profile` -> `.agenthub/profile`), the lanes state root
(`~/.claude/ccam-lanes` -> `~/.claude/agenthub-lanes`), the bundled
plugins (`plugins/ccam*` -> `plugins/agenthub*`) and their slash
commands (`/ccam-doctor` -> `/agenthub-doctor`, `/ccam:*` ->
`/agenthub:*`).

Because there is no alias, an existing install has to be updated by
hand: rename its `.ccam/profile` directory and any `CCAM_*` variables,
and reinstall the plugin under its new name.

Two other name families are deliberately left alone here, since they are
not just strings: the `Claude-Code-Monitor` repository/marketplace name,
and the `agent-dashboard` npm package plus its `~/.claude/agent-dashboard`
runtime directory, which holds the live database and needs a migration
rather than a rename.

Verified: server 1406/1406, client 459/459, `grep -i ccam` clean across
tracked files, `openapi.yaml` regenerated (95 paths, unchanged count).
2026-09-07 12:09:15 +07:00

75 lines
3.3 KiB
Markdown

# Split terminal view for the Workspace console
**Status:** approved 2026-08-14.
## Problem
`Workspace.tsx` renders exactly one lane's run console at a time: a single
`RunSetup`/`TerminalView` switcher (client/src/pages/Workspace.tsx:789-824)
driven by page-level state (`selectedLaneId`, `prompt`, `cwd`, `model`,
`permissionMode`, `effort`, `resumeSession`, `handle`, `busy`, `activeRuns`,
`runHistory`, `cwdSuggestions`). Lanes are independent working directories
that can each have their own live tmux/PTY session running concurrently on
the server (`server/lib/pty-attach.js`), but the dashboard can only show one
at a time — comparing two lanes' output means switching back and forth.
The user wants to view multiple lanes' terminals side by side: 1 pane (today's
behavior), 2 panes (left/right), or 4 panes (2x2 grid).
## Approach
**Extract a self-contained `LaneConsolePane` component.** Move the existing
RunSetup/TerminalView switcher and all its state out of `Workspace.tsx` into
its own component that owns one lane's run lifecycle independently. Each
pane gets its own `laneId` (chosen via a dropdown in the pane header, listing
all lanes, not just ones with an active run) and manages its own
prompt/cwd/model/permissionMode/effort/resumeSession/handle/busy/activeRuns/
runHistory state — nothing is shared across panes.
Workspace keeps a `paneLaneIds: (number | null)[]` array sized to the current
layout (1, 2, or 4) and renders that many `LaneConsolePane` instances in a
CSS grid. This is the only viable approach given the existing state model is
single-lane; the alternative (keeping one shared state object indexed by
lane) would require rewriting every handler in Workspace.tsx to be
lane-aware and is a much larger, riskier diff for the same result.
## Layout
A layout toggle (1 / 2 / 4 buttons) sits next to the existing console
header. Grid via CSS:
- **1**: full width — identical to today.
- **2**: `grid-cols-2` — left/right.
- **4**: `grid-cols-2 grid-rows-2` — four corners.
Each pane has a small header with a lane-select dropdown. If the selected
lane has no active run, the pane shows a compact `RunSetup` (reused
component, same as today's pre-run form) so the user can start one directly
from the pane. If it has an active run, the pane shows `TerminalView` as
today.
## Persistence
The chosen layout mode and each pane's selected `laneId` are saved to
`localStorage` (e.g. key `agenthub.workspace.splitView`) and restored on next
visit to Workspace. If a persisted lane no longer exists, that pane falls
back to unselected (dropdown placeholder).
## Non-goals
- No server/API changes — this is purely a client-side rendering feature.
Each lane's run already exists independently server-side; this just lets
the UI display more than one at once.
- No synchronized input across panes (typing in one pane's terminal does not
affect others) — each `TerminalView` keeps its own independent WebSocket
connection, unchanged from today's single-instance behavior.
## Testing
- `client/src/pages/__tests__/Workspace.test.tsx` currently mocks
`TerminalView` and exercises the single-console flow; update it (or add a
sibling test file) to cover: layout toggle, per-pane lane dropdown,
starting a run from within a pane, and multiple panes rendering
independent `TerminalView`/`RunSetup` instances.
- Run `npm run test:client` before considering this done.