A keyboard-heavy solo developer using several local repositories and signed-in model subscriptions.
Open a project, run or steer agents, inspect and edit files, verify work, and resume later without switching to an IDE.
Current tools either lock the runtime to one provider or grow into heavyweight IDE/dashboard shells. Brutal must remain a focused terminal cockpit.
Try ⌘/Ctrl+K, Alt+1–3, arrow keys, ⌘/Ctrl+W, right-click, folder disclosure, file double-click, pane seams, composer Enter/Shift+Enter, and the scenario buttons.
Structural alternatives
Three meaningfully different shells were compared before selecting the cockpit. The choice is based on task flow and the existing design contract, not visual preference.
A. Cockpit-first, selected
Projects across the top, files at left, uncapped peer panes in the canvas. Fastest path to terminal work; workflows appear only when invoked.
Why it wins:Preserves the original demo, supports parallel work, and avoids permanent utility regions.B. Repository hub
A launcher dashboard shows repositories, recent sessions, tasks, and workflows before entering the terminal.
Rejected:Adds a recurring navigation step and drifts toward a project-management dashboard.C. Workflow-first
A left graph rail drives planner, builder, tests, reviewer, and evidence while terminal panes support the graph.
Rejected:Makes advanced orchestration dominate ordinary single-agent prompts and violates the no-dashboard boundary.User flows
Select a flow to inspect its change-points, primary actions, and recovery branches. Each box represents a distinct screen or meaningful state transition.
Anti-pattern audit
Checks come directly from the selected app-shell, navigation, AI-chat, error, and wireframe skills.
| Check | Verdict | Evidence in prototype |
|---|---|---|
| Novel shell for differentiation | PASS | Uses the proven terminal cockpit: project tabs + navigation rail + peer panes. |
| Dashboard cards as working surfaces | PASS | No dashboard. Agent, editor, diff, and workflow are peer panes. |
| Command palette as the only path | PASS | Project plus button, file pointer actions, pane close controls, and dialogs duplicate keyboard paths. |
| Hidden AI context or tool use | PASS | Context chips, model/mode labels, named tool steps, and evidence remain inspectable. |
| No steering or stop control during generation | PASS | Send becomes Queue while a separate Stop preserves the next queued prompt. |
| Agent acts consequentially without a gate | PASS | Repository trust and workflow plan approval require explicit user action. |
| Error with no action or lost work | PASS | Drafts persist; error, offline, dirty close, and conflict states all carry recovery actions. |
| Blank empty panes | PASS | Agent empty state teaches with specific prompts; empty file rail explains how to open a project. |
| Hover-only critical controls | PASS | Hover resize signifiers supplement keyboard separators; all menus open from keyboard or pointer. |
| Missing loading/empty/error coverage | PASS | State preview and inventory cover all three plus ideal, partial, and offline. |
| Full mobile clone of desktop panes | PASS | Narrow layout focuses one pane and turns the rail into an overlay without stopping background tasks. |
| Dedicated detached-task visual surface | OPEN | Prototype proposes a task dialog; current product is command/toast driven. Needs product decision. |
Screen inventory
Every row names the screen's job, primary action, and minimum empty/loading/error behavior. Search by screen, flow, or source.
| # | Screen / state | Purpose | Primary action | Empty · loading · error | Source |
|---|
Handoff annotations
This section records behavior, state, accessibility, persistence, component mapping, and unresolved product questions so implementation does not depend on chat history.
Interaction contract
- Project tabs switch isolated cwd, panes, drafts, task cursors, model, mode, and unread state. Alt+1–9 mirrors pointer selection.
- Folders disclose inline. One click selects; double-click or Enter opens; M mentions; X closes an already-open file.
- Pane focus is pointer and arrow-key reachable. ⌘W closes a pane; dirty editors intercept with Save and close / Discard / Keep editing.
- Visible seams stay 1px. Pointer hit areas may overlap panes; hover shows ↔ or ↕. Arrow keys resize focused separators.
- Composer Enter sends, Shift+Enter adds a line, paste never sends, and multiline paste requires ⌘Enter.
- Agent running swaps Send for Queue and exposes Stop separately. Partial output and the next queued prompt survive interruption.
Persistence contract
- Workspace state survives restart: project order, active project, rail width, pane order/type/focus, split ratios, drafts, and branch labels.
- Detached agent runs keep append-only event cursors and reattach without replaying duplicate events.
- Agent transcripts stay node-local. Graph nodes coordinate through projected shared state and compact outputs.
- Offline/failed saves preserve editor and composer drafts before displaying recovery messaging.
- Legacy
~/.nightcodestate is discovered without destructive migration; new state uses~/.brutal/code.
Accessibility contract
- All controls are semantic buttons, inputs, tabs, menu items, dialogs, or separators with visible keyboard focus.
- Command palette uses ↑/↓, Enter, and Esc; focus returns to its trigger on close.
- Blocking errors use alerts; status/toasts use polite live regions. State never depends on color alone.
- Streaming output announces by chunk, not token. “Response complete” is announced once.
- Reduced motion disables pulses and streaming animation while preserving explicit status text.
Responsive contract
- At wide widths, the file rail docks and peer panes tile compactly.
- Below 900px, the rail overlays, one pane is focused, and background runs remain mounted.
- Text, paths, branches, and tasks truncate rather than forcing horizontal page scroll.
- Pointer-independent actions remain available on touch and keyboard; hover is enhancement only.
- Layouts tolerate 40% longer strings and 200% zoom without fixed text heights.
Component mapping
| Wireframe component | Current implementation | Product rule |
|---|---|---|
| Project tabs | packages/desktop-ui/src/components/project-tabs.tsx | Primary project navigation; state persists per tab. |
| File rail + context menu | file-rail.tsx · file-context-menu.tsx | Navigation only; accordion folders; open/mention/close. |
| Pane grid + seams | pane-grid.tsx · app.tsx | Uncapped peer panes; one focused border; thin visible seams. |
| Terminal + composer | terminal-pane.tsx · command-composer.tsx | Real PTY, selectable output, explicit context, safe paste. |
| File editor | file-pane.tsx | Jailed reads/writes, dirty state, save/conflict recovery. |
| Command palette | command-palette.tsx · CLI command-menu/commands.tsx | Accelerator, not sole navigation; filter + keyboard execution. |
| Workflow status/evidence | CLI graph-status.tsx · graph-evidence-dialogue.tsx | Explicit advanced peer, visible human gates, evidence-defined success. |
| Native shell | packages/macos-app | Menus, shortcuts, folder picker, drag/drop, clipboard, restoration. |
Open questions
- Human gate: should plan editing be a structured peer pane or a small modal with raw JSON edit as an advanced path?
- Detached work: should the proposed task dialog ship in desktop, or should detached tasks remain command-only until daily use proves a visual center is needed?
- Desktop parity: which CLI inspection dialogs, including context, extensions, MCP, usage, and checkpoints, must be first-class desktop dialogs versus terminal commands?
Decision record
- Selected: cockpit-first shell from the canonical demo.
- Adapted: workflow and diff become optional peer panes, not fixed dashboard regions.
- Rejected: repository dashboard, workflow-first shell, IDE activity bar, permanent inspector, block-based terminal output.
- Deferred: visual node editor, hosted account shell, full settings center, libghostty migration.
Edge-case inventory
| Case | Expected behavior | Recovery |
|---|---|---|
| Repository moved or deleted | Tab remains labeled “missing”; no accidental home-directory fallback. | Bind to an existing repository or close the tab. |
| Provider subscription unavailable | Agent pane keeps draft and transcript; trust boundary is named. | Authenticate a signed-in adapter or select another available model. |
| Second writer targets same repository | Run is rejected before changes; reader panes continue. | Create a named isolated worktree or stop the existing writer. |
| File changes on disk while dirty | Show Disk and Unsaved versions; never overwrite silently. | Reload disk or keep editing and save deliberately. |
| Agent interrupted mid-tool | Persist partial transcript and terminal reason interrupted. | Resume from checkpoint or send a corrected prompt. |
| Tests fail in build-review | Evidence names command, exit code, output, and artifact paths. | Route findings to builder; stop after bounded review cycles. |
| Offline while editing | Cached reads continue; drafts and queued writes persist locally. | Retry visibly, then confirm “Back online. All changes saved.” |
| More panes than fit | Wide layouts add compact rows; narrow layouts focus one pane. | Use layout picker, keyboard focus, or close panes; runs keep going. |