Chat UI:
- Each Claude/Codex session keeps its own chat/terminal view; Settings only
sets how new sessions open.
- Composer + menu: upload, project files and folders (#54, also dragged from
the Files/Changes tree), context files, recent uploads, skills, plugins.
- Activity side panel (progress, outputs, files read, uploads, memory,
skills, connectors) with a file preview; edited-file counts per turn.
- Permission-mode chip (Shift+Tab steps, read back from the pane:
server/lib/pane-mode.js, GET|POST /api/run/:id/permission-mode).
- Stop (Esc) while the main agent works; the status is checked per agent
(with session_id /api/agents ignores its status filter) and re-read every
5 s while Stop shows.
- Dropped images shown in the conversation (GET /api/run/drop/:name, the
requester's own drop dir), full-size viewer.
- A plain-text paste over 5,000 characters is attached as pasted-text.txt,
so no prompt reaches tmux/argv limits (#68).
Changes panel: every /api/lanes/:id/git* route takes ?source=<lane_sources
id> (sourceFolder; ENOSOURCE otherwise) and a folder picker switches the
whole panel to a workspace's extra folder (#70).
Server mode S3 (one Linux user per account) — experimental, verified with
fake sudo plus a P6 managed-settings spike on a test account:
- member tmux listing runs in the background (cached, 15 s => unknown);
- transcript snapshot copy is async, chunked, temp file + rename;
- Express Layer patch only on Express 4;
- tmux capturePane/sendKey go to the member's own server.
Docs: the multi-user design moved in as docs/plans/server-mode/README.md
(the AgentHub-Server repo is gone); S3-PLAN P6 result; LANES/API/openapi.
- A resume of a session a live pane already holds is refused (409
ESESSIONLIVE with error.run_id) and the client opens that pane, pasting
any typed message there; catalog tools refuse resumeSessionId
(EUNSUPPORTED) instead of silently starting fresh.
- POST /api/lanes/:id/start takes slot: "auto": the server picks the free
tab under the lane lock (components/lanes/startSession.ts on the client,
kept out of WorkspaceHome so the sidebar does not pull react-markdown
into the main bundle).
- Unsaved whole-file edits are guarded on every exit (Back, another file,
tab switch, close, lane/session change, beforeunload).
- Closing an AI tab asks first; hiding a pane has its own icon. Tabs and
pane headers show the session name, a state dot, rename by double-click.
- Terminal: Ctrl+M toggles Tab-moves-focus (no keyboard trap), Cmd+F /
Ctrl+Shift+F find bar, clickable links (noopener), a write-only OSC 52
clipboard, a Reconnecting overlay, debounced resizes, optional screen
reader mode. Alt+1-4 / Alt+\ / Alt+W focus, split and hide panes.
- Changes panel: draggable splitter, wrapping git bar, history paging,
disarming discard/undo/abort, inline diff comments pasted only into a
visible pane; drag MIME guard on sidebar rows; IME-safe Enter; Show
more in the sidebar and Recents; idle dots readable with sr-only text.
- Adds @xterm/addon-clipboard, @xterm/addon-search, @xterm/addon-web-links.
- The lane terminal (xterm) takes its palette from the selected DARK theme —
it stays dark in light mode, as a terminal should — and repaints live when
the theme changes (`client/src/lib/terminalTheme.ts`).
- Charts on the Dashboard and Workflows pages draw their grid, axes, labels
and tooltips from theme tokens instead of hardcoded near-black/white, and
the activity heatmap ramps from the page surface to the accent, so it reads
on every theme instead of going near-black on light ones.
- Status/brand text that only worked on dark backgrounds
(`text-*-300/400`) gets a darker light-mode shade (`text-*-700
dark:text-*-300`) across sessions, conversations, workflows, config and
settings. Categorical chart colours are kept.
- Repo mode adopts a directory as-is via /lanes/ensure (no worktree, no
branch fields) - the right choice for a main repo you want stage
detection on. Worktree mode (default) keeps the existing provisioning
flow but now requires a manually-typed branch name instead of deriving
one from the title.
- POST /lanes/worktree accepts an optional `branch`, validated via
`git check-ref-format --branch`; omitting it preserves the CLI's
existing auto-derived-branch behavior.
- New GET /lanes/browse lists a directory's immediate subdirectories,
backing a small folder-browse modal on both path fields - browsers
cannot expose an absolute path from a native picker, so this is
server-backed instead, consistent with the tool's local-first model.