Files
2026-06-15 09:43:01 +02:00

272 lines
26 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Handoff: Helder — AI Code Workbench (Electron)
## Overview
**Helder** is a desktop code workbench for a developer who reviews and works with code written by an AI agent. It is a dense, four-column IDE-style window optimized for an ultrawide monitor (designed at **3440×1440**, but fully fluid down to ~1280px wide). It is **dark mode only** — there is intentionally no light theme and no theme toggle.
The core jobs the app supports:
- Fast project navigation + a single search that covers **both file contents and file names**.
- A Git review surface (commit box, staged list, changes list, per-file diff with four view modes).
- An editor with tabs and syntax-colored code.
- A live **Claude Code agent** terminal plus a normal shell terminal.
- A right-click **"Copy reference"** / **"Pass on to Agent"** flow that pushes `path:line` references into the agent's input so the developer can quickly point the agent at code.
## About the Design Files
The files in `design/` are a **design reference created in HTML/CSS/React-via-Babel** — a working prototype that shows the intended look, layout, and behavior. **They are not the production codebase and should not be shipped as-is.**
The task is to **recreate this design as a real Electron application**, using a proper build setup and the patterns below. The prototype loads React 18 + Babel from a CDN and stores everything in mock data; the real app should use a normal toolchain (see "Recommended Electron Stack"). Treat the HTML as the source of truth for *visual + interaction design*, and this README as the source of truth for *structure, tokens, and behavior*.
You can open `design/Helder - AI Code Workbench.html` directly in a browser to see and click the live prototype while building.
## Fidelity
**High-fidelity (hifi).** Colors, typography, spacing, diff coloring, and interactions are final. Recreate the UI pixel-faithfully. All exact values are in the Design Tokens section and in `design/styles.css` (the prototype's `:root` block is the canonical token list).
---
## Recommended Electron Stack
No target codebase exists yet, so choose a modern, conventional setup:
- **Electron** (latest stable) with a **main** process and a **renderer**.
- **Renderer:** React 18 + TypeScript + Vite (`electron-vite` is a good scaffold). The prototype is already React, so component structure ports directly.
- **Syntax highlighting:** the prototype uses **Prism 1.29** (`prism-core` + `markup-templating`, `php`, `python`, `typescript`, `json`, `bash`, `markdown`). Keep Prism, or swap to **Shiki**/**CodeMirror 6** if you prefer; the token→color mapping is documented below. **Important Prism gotcha:** `prism-php` requires `prism-markup-templating` to be loaded **first**, or every `Prism.highlight` call throws and silently falls back to plain text.
- **Fonts:** UI = system stack (`-apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif`); code/mono = **JetBrains Mono** (bundle the font locally for offline use — do not rely on Google Fonts CDN in Electron).
- **Real integrations to wire up (replacing the mock):**
- File tree + file contents → real FS via the main process (`fs`, `chokidar` for watching). Never touch FS directly from the renderer; use IPC / a preload bridge with `contextIsolation: true`.
- Git panel → shell out to `git` (or `simple-git`) for `status --porcelain`, staged/unstaged sets, `add`/`reset`, `commit`, and `diff`. The prototype computes diffs in JS with an LCS; in the real app prefer `git diff` output, but the four view modes still derive from an original/updated text pair per file.
- Terminals → real PTYs via **node-pty** + **xterm.js**. The "Claude agent" pane is just a terminal that runs the `claude` CLI; the bottom pane is a normal shell. The prototype fakes both — see "Terminals".
- Search → ripgrep (`rg`) for content search; a fast fuzzy matcher (e.g. `fzf`-style or `fuse.js`) for file-name search.
- "Copy reference" → Electron `clipboard.writeText`.
- "Pass on to Agent" → write into the agent terminal's PTY using **bracketed paste** (`\x1b[200~``\x1b[201~`) so the `claude` CLI treats it as pasted input and does NOT submit it. This is the real mechanism the prototype only simulates.
---
## Global Layout
Top-level vertical stack (`.app`, `height:100vh`, `display:flex; flex-direction:column`):
1. **Title bar**`height: 36px`, fixed.
2. **Workbench**`flex: 1`, a horizontal flex row of four columns separated by draggable splitters.
3. **Status bar**`height: 23px`, fixed.
**Design principle the client asked for:** keep the chrome minimal — title bar + tab strip + panel headers + status bar combined should stay ≈10% of vertical height so code and tools own the screen.
### Workbench columns (left → right)
All columns are **horizontally resizable** by dragging the 5px splitter between them. The editor is the flex-grow column; the other three have explicit pixel widths with min/max clamps.
| # | Column | Default width | MinMax | Notes |
|---|--------|---------------|---------|-------|
| 1 | **Source Control** (Git) | 232px | 160460 | commit box + staged list + changes list |
| 2 | **Explorer** (file tree) | 244px | 160520 | VS Code-style tree, colored type icons |
| 3 | **Editor** | flex:1 | min 240px | tabs + code/diff |
| 4 | **Right column** | 444px | 280780 | split vertically: agent terminal (top) + shell (bottom), draggable horizontal splitter, default top fraction 0.52 |
Splitter: 5px hit area, transparent; inner 1px line is `--border`, turning to `--accent` (0.55 alpha) on hover/drag. Vertical splitter cursor `col-resize`; horizontal `row-resize`.
---
## Screens / Components
### 1. Title bar (`.titlebar`)
- Height 36px, background `--bg-3`, bottom border `--border`, horizontal padding 12px, items gap 14px.
- Left → right:
- **Traffic lights**: three 12px circles, gap 8px — red `#e0696a`, yellow `#d8a85c`, green `#5cbd6b`. (On macOS use the native frame instead; these are decorative in the web prototype.)
- **Wordmark**: a small spark/diamond icon in `--accent`, then **`Helder`** (weight 600, `--fg-0`), an em-dash in `--fg-3`, then the project name (`console`) in `--fg-2`. Font 12px.
- **Breadcrumb** of the active file path, monospace 11.5px, `--fg-3`, segments joined by ` `; last segment `--fg-1`.
- Spacer (flex:1).
- **Search button**: `.tb-btn` — ghost button, 11.5px, `--fg-2`; search icon + "Search" + a `<kbd>⌘F</kbd>` chip. Hover → `--hover` bg, `--fg-0` text. (There is intentionally **no "Go to File" button** — search covers file names too.)
### 2. Source Control panel (`.col` #1)
Order, top to bottom:
**a. Panel header** (`.phead`, height 30px): branch icon + "SOURCE CONTROL" (uppercase, 10.5px, letter-spacing .09em, `--fg-2`) + a count pill on the right showing the number of changed (uncommitted) files.
**b. Commit box** (`.commit-box`, padding 9px 10px, bottom border): a flex row, `align-items:flex-start`, gap 7px.
- **Message field**: a 1-row auto-growing `<textarea>` (`.commit-input`), flex:1, bg `--bg-0`, 1px `--border-2` border, radius 7px, padding 7px 9px, font UI 12px, min-height 32px; focus border `--accent-line`. Placeholder: `Message (⌘↵ to commit)`.
- **Commit button** (`.commit-btn`): solid `--accent` bg, text `#0c1320`, weight 600, radius 7px, height 32px, padding 0 11px; a check icon + label `Commit` (or `Commit N` when N files are staged). **Disabled** (bg `--bg-3`, text `--fg-3`, `not-allowed`) unless there is ≥1 staged file AND a non-empty message. `⌘↵`/`Ctrl+↵` in the field commits.
**c. Two stacked lists** (`.git-body`, scrolls). Both lists are **always present** even when empty:
- **Staged Changes** group header (`.git-group`) with count; on hover shows an "unstage all" `` button on the right. Below it, the staged file rows — or, if empty, the hint `Nothing staged — use + to stage a file` (`.git-none`).
- A 1px **divider** (`.git-divider`, `--border`, margin 8px 12px 2px).
- **Changes** group header with count; hover shows a "stage all" `+` button. Below it, the unstaged rows — or hint `All changes staged`.
- If the working tree is fully clean (everything committed), show a centered empty state: a green check icon + `No changes — working tree clean`.
**Git file row** (`.git-row`, padding 3px 12px 3px 14px, gap 8px, `cursor:pointer`):
- **Status letter** (`.git-stat`, mono 11px bold, 13px wide): `M` = `--mod` (amber), `A` = `--add` (green), `D` = `--del` (red), `R` = `--ren` (blue).
- **File-type icon** (see Explorer).
- **File name** (`--fg-1`; deleted files get `line-through` + `--fg-3`).
- **Directory** (`.git-dir`): the parent path, `--fg-3`, 11px, right-aligned with `direction:rtl` ellipsis, max-width ~42%.
- **Stage/unstage button** (`.git-act`): appears on row hover, 20×20, a `+` (stage) on Changes rows or `` (unstage) on Staged rows.
- **Delta** (`.git-delta`, mono 10.5px): `+N` in `--add`, `-N` in `--del`.
- Hover bg `--hover`; active (open in editor) bg `--sel` + 2px `--accent` left rail.
- **Click** opens the file's diff in the editor. **Right-click** → context menu (see Interactions).
**d. Footer** (`.git-foot`): branch icon + branch name (`--fg-0` bold) on the left; total `+adds`/`-dels` (mono) on the right.
> Seed/demo data: branch `feat/payments-balance`; 6 changed files; 2 pre-staged (`PaymentService.php` [A], `config/app.json` [M]); 4 unstaged including a deleted `LegacyUser.php` [D].
### 3. Explorer / file tree (`.col` #2)
- Header `.phead`: "EXPLORER" + project name (`console`) right-aligned, mono 10.5px `--fg-3`.
- Tree body scrolls. Rows are 23px tall.
- **Folder row** (`.tree-row.folder`): a rotating chevron (▸ closed → ▾ open, CSS rotate 90°, .12s) + a simple folder glyph + name (`--fg-1`). Click toggles expand. Indent = `10 + depth*13` px.
- **File row**: file-type icon + name. Active file → `--sel` bg + 2px `--accent` left rail. Files with an uncommitted change show a status letter badge (`M`/`A`/`D`) on the right (cleared once that file is committed). Deleted files render struck-through.
- **File-type icon** (`.ficon`): a **15×15 rounded-square monogram chip** filled with a per-type color, containing 13 dark glyph characters (`#0c0d0f`, mono 7.5px bold). Do **not** use brand logos. Colors/labels:
- `.php``#a78bdb` "php" · `.js/.mjs``#e6c860` "js" · `.ts/.tsx``#5a9bd6` "ts" · `.py``#5fa8d6` "py" · `.html``#e08b6a` "<>" · `.css``#5a9bd6` "{}" · `.json``#d8a85c` "{}" · `.md``#9aa0a8` "md" · `.env/.sh``#7fc6a0` "$" · `.yml/.yaml``#cf7a6a` "yml".
- Special names: `composer.json` `#a78bdb` "co"; `package.json` `#cf7a6a` "pk"; `README.md` `#5a9bd6` "md"; `.env` `#7fc6a0` "$".
- Default/unknown: `#7d838c`, first two letters of the name.
### 4. Editor (`.col` #3)
**Tab strip** (`.tabs`, height 35px, bg `--bg-3`, horizontal scroll, no scrollbar):
- **Tab** (`.tab`): file-type icon + name, 12.5px, max-width 230px. Inactive `--bg-3`/`--fg-2`; active `--bg-0`/`--fg-0` with a 2px `--accent` top rail. A small mode badge (`.tab-mode`: `orig`/`upd`/`diff`/`split`) shows for changed files. A close `×` (`.tclose`, 17px) on the right; **middle-click** also closes. Hover bg `#272b31`.
**Diff toolbar** (`.diff-bar`, only shown for changed files; height 26px, bg `--bg-3`):
- Left: a status word (`Modified`/`Added`/`Deleted`) tinted by status, then `+N` (green) / `N` (red).
- Right: a **4-segment control** (`.seg`, 1px `--border-2`, radius 7px): **Original · Updated · Diff · [⊟ Split]**. Active segment bg `--accent-soft`, text `--fg-0`. The Split segment carries a small split-pane icon.
**Code area** (`.editor`, mono 13px, line-height 20px, scrolls). Each line is a flex row (`.ln-row`):
- **Gutter** (`.ln-gutter`, 54px, right-aligned, `--fg-3`, clickable to select that line; shift-click extends a range).
- (Diff mode only) a **sign column** (`.ln-sign`, 14px): `+`/`-`.
- **Code** (`.ln-code`, `white-space:pre`), syntax-highlighted.
- Cursor line gets a faint `rgba(255,255,255,.035)` bg; selected range gets `--accent-soft`.
**The four view modes** (all are presentations of the same per-file diff; same color language everywhere → **red = removed / changed-from, green = added / changed-to**; syntax highlighting stays on in all four):
1. **Original** — the pre-edit file, read-only. Removed/changed lines get a **red gutter bar** (`box-shadow: inset 2px 0 0 var(--del)` on the row). No inline +/- markers.
2. **Updated** — the current/live file. Added/changed lines get a **green gutter bar** (`inset 2px 0 0 var(--add)`). (In the real app this is the editable buffer.)
3. **Diff** — single-pane unified inline diff: removed lines red with `-`, added lines green with `+`, full file context in sequence. This is the default when a changed file is opened.
4. **Split** — clicking it opens a **full-screen overlay** (`.split-overlay`, `position:fixed; inset:0; z-index:60`) covering all panels: header bar (file icon + path + status + `+/`) with a **Collapse** button + `Esc` to exit; body is two side-by-side panes — **Original** left, **Updated** right — with lines aligned (blank padded rows where one side has no counterpart, rendered with a faint diagonal hatch `.ln-row.empty`), red bars on the left, green bars on the right, and **synced vertical scrolling** between panes.
Empty editor state (`.empty-ed`): file icon + "No file open" + a key-hint list (`Search files & content ⌘F`, `Copy reference right-click`, `Pass on to Agent right-click`).
### 5. Right column — terminals (`.col` #4)
Two stacked terminal panes split by a draggable horizontal splitter (top fraction default 0.52).
Each pane:
- **Header** (`.term-head`, height 28px, bg `--bg-3`): a status dot (the agent pane's dot is green + pulsing when a session is live), a mono label (`claude` / `zsh`), and a right-aligned tag (`agent session` / `— bash · ~/console`).
- **Body** (`.term-body`, mono 12.5px, line-height 18px, scrolls, `cursor:text`): a stream of output lines plus an input row at the bottom.
- **Input row** (`.term-input`): a colored prompt glyph (agent `>` in violet `#c98bdb`; shell `console %` with `%` in `--fg-3`) + a transparent auto-growing **`<textarea>`** (`.term-ta`, mono 12.5px, `caret-color:--accent`, up to 8 rows). **Enter** submits; **Shift+Enter** inserts a newline; ↑/↓ recall history (only when the buffer has no newline).
**Agent pane behavior (top):** it is a terminal. Typing `claude` "boots" an agent session (a bordered welcome card + intro line). In a live session, submitting a prompt streams a short simulated response: a "thinking…" line, `read`/`grep` tool lines, an **edit card** (`.term-card` — a bordered block with a header `edit · <path>` and red `-`/green `+` rows), then a green "Done" line. `/exit` ends the session. **In the real app, replace all of this with a real PTY running the `claude` CLI** (node-pty + xterm.js). The simulated content (`agentSeed`, `runAgent`, `bootAgent` in `design/src/terminals.jsx`) is only there to show the intended visual style — keep that styling, drop the fakery.
**Shell pane (bottom):** a normal terminal. The prototype fakes `ls`, `pwd`, `cat`, `git status`, `git diff`, `echo`, `clear`; replace with a real shell PTY.
### 6. Status bar (`.statusbar`, height 23px, bg `--bg-3`, 11px)
Segments left→right: an **accent-colored** branch chip (bg `--accent`, text `#0c1320`); `+adds / dels`; spacer; cursor position (`Ln X, Col Y`, or `N lines selected`); `Spaces: 4`; `UTF-8`; active file language (bold); and the current view mode word (`Original`/`Updated`/`Diff`/`Split`) when a changed file is active. Each segment hover bg `--hover`.
---
## Interactions & Behavior
### Search (⌘F) — `SearchModal`
- Opened by `⌘F` / `Ctrl+F` or the title-bar Search button. (There is no separate "go to file" command; this one modal does both.)
- A scrim (`.scrim`, `rgba(8,9,11,.5)`, slight blur) with a **large centered modal** (`.search-modal`, width 940px, max 94vw).
- Top: a single text input (search icon + field, placeholder `Search content and file names…`) and a right-aligned count chip (`N hits · M files`).
- Body is **two columns**:
- **Left — Content** (`.sc-left`, flex-grow, the wide pane, max-height 460px, scrolls): substring matches across all file contents (case-insensitive, min 2 chars), grouped by file. Each group: a file header (icon + path + hit count); then up to 12 matching lines, each `line# + the line text with the matched term wrapped in <mark>` (`mark` bg `rgba(216,168,92,.28)`). Clicking a line opens that file at that line.
- **Right — Files** (`.sc-right`, **fixed 256px — deliberately narrower**, max-height 460px, scrolls, slightly darker bg): fuzzy matches on file name (then path), each a 2-line cell (name with matched chars bolded in `--accent` + dimmed dir path). A `•` dot marks files with uncommitted changes. Clicking opens the file.
- Section headers (`.sc-head`) are sticky, uppercase 10px, with a count pill.
- **Keyboard:** ↑/↓ move a selection through the flat list of content hits (selected line highlighted `--accent-soft`); **Enter** opens the selected content hit (or the first file if there are no content hits); **Esc** closes. Clicking the scrim closes.
### Right-click in the editor → context menu (`.ctx`) — exactly two items
1. **Copy reference** — copies a **project-relative** reference to the clipboard:
- No selection: `path:line` (e.g. `src/Http/Controller/UserController.php:42`).
- With a selection: `path:start-end` (e.g. `src/Http/Controller/UserController.php:42-58`).
- The clicked line is resolved via `document.caretRangeFromPoint`; a multi-line text selection (or a gutter range-select) yields the start-end form.
2. **Pass on to Agent** — opens a small **inline popup** (`.pass-pop`) anchored at the click:
- A header (`✦ Pass on to Agent` + `esc` chip), one optional single-line text field (placeholder `Add a note (optional)…`), an `INSERTS` preview showing the composed line, and a footer `↵ insert into agent · esc cancel`.
- On **Enter**: compose ONE line = `<typed note> <reference>` (just the bare reference if the field is empty) and insert it into the **agent terminal's input** as a **new, unsubmitted line, leaving the caret on a fresh line below** — so the action can be repeated to **stack several references** before the developer presses Enter to send. **Insert never submits.** In the real app, do this by writing the text to the agent PTY wrapped in **bracketed paste** (`\x1b[200~ … \x1b[201~`).
- **Esc** cancels with no insert; clicking outside cancels.
- The context menu shows the resolved reference as a muted note at the top.
- The menu reuses a generic popup also used by tree/git rows; **only the editor menu is the two-item Copy/Pass menu.** Tree rows offer Copy reference / Send reference to agent / Copy file name / Open / Reveal; Git rows additionally offer **Stage changes** or **Unstage changes** and **Open diff**.
### Diff mode switching
- Clicking Original/Updated/Diff sets the active tab's mode and closes any open Split overlay. Clicking Split opens the full-screen overlay; the previous mode is preserved for when you collapse. `Esc` collapses Split.
- Opening a file from the Git panel defaults to **Diff**; opening from search/tree defaults to the plain file (**Updated** for changed files so line numbers map to the current content).
### Staging / commit
- Hover a git row → `+`/`` to stage/unstage; group headers have stage-all/unstage-all. Right-click → Stage/Unstage.
- Commit (button or `⌘↵`) moves staged files out of the working set, clears the message, shows a toast `Committed N file(s)`, and clears those files' badges in the tree.
### Toasts (`.toast-wrap`, bottom-center)
- Small dark pill with an icon, a title, and (optionally) a mono reference chip in `--accent`. Auto-dismiss after ~2.3s. Used for "Copied reference", "Passed to agent", "Committed N files".
### Keyboard shortcuts
- `⌘F` / `Ctrl+F` — open Search.
- `⌘W` / `Ctrl+W` — close active tab.
- `Esc` — collapse Split if open, else close any overlay/menu.
- `⌘↵` in commit box — commit.
- In terminals: `Enter` submit, `Shift+Enter` newline, `↑/↓` history.
### Animations
- Chevron rotate .12s. Splitter line color .12s. Overlays/toasts a ~.12s ease-out entrance (translateY 68px). Live agent dot: a 2.2s pulsing box-shadow ring. Keep motion subtle; respect `prefers-reduced-motion`.
---
## State Management
Renderer state (the prototype keeps all of this in the top `App` component; in the real app, lift FS/git/terminal state into the main process and stream via IPC):
- `openTabs: string[]` (file paths), `activeTab`, `tabMode: Record<path, 'original'|'updated'|'diff'|'code'>`.
- `splitFor: path | null` (which file is in full-screen Split).
- `openDirs: Set<path>` (expanded tree folders).
- `cursor: {path, line, col}`, `selection: {path, start, end} | null`.
- `overlay: 'search' | null`, `menu` (context menu descriptor), `passPopup: {x,y,ref} | null`, `toasts[]`.
- Git: `staged: Set<path>`, `committed: Set<path>`, `commitMsg`.
- Column sizes: `gitW`, `treeW`, `rightW` (px) + the right column's top-pane fraction.
- Per changed file the app needs an **original text** and **updated text**; the diff (`rows` for unified, `left`/`right` for Original/Updated with per-line add/del marks, and `split` aligned pairs, plus `+`/`` counts) is derived from those. See `buildDiff()` in `design/src/data.js` for the exact derivation (LCS line diff) — in production prefer real `git diff` but keep the same four derived views.
## Data the real app must supply (replacing `design/src/data.js`)
- Project file tree (nested dirs/files) from the opened folder.
- File contents on demand.
- Git: current branch, changed files with status (`A/M/D/R`) and `+/` counts, staged/unstaged sets, and original+updated text per changed file.
- Search: content matches (ripgrep) and file-name matches (fuzzy).
---
## Design Tokens
Canonical source: the `:root` block in `design/styles.css`. Key values:
**Surfaces / neutrals (cool charcoal):**
- `--bg-0 #16171a` (editor) · `--bg-1 #1a1c1f` (terminals) · `--bg-2 #1f2226` (sidebars) · `--bg-3 #23262b` (headers/tabs)
- `--hover #2a2e34` · `--active #313742` · `--sel #2b323d`
- `--border #2a2d33` · `--border-2 #34383f`
- Text: `--fg-0 #e6e8ea` · `--fg-1 #b4bac2` · `--fg-2 #838a94` · `--fg-3 #5d636c`
**Accent (single, cool blue):**
- `--accent #4d8dff` · `--accent-soft rgba(77,141,255,.16)` · `--accent-line rgba(77,141,255,.55)`
**Git / diff status:**
- `--add #5cbd6b` · `--del #e0696a` · `--mod #d8a85c` · `--ren #5aa6d6`
- `--add-bg rgba(92,189,107,.10)` · `--del-bg rgba(224,105,106,.10)`
**Syntax tokens (tuned to charcoal):**
- keyword `--t-key #c98bdb` · string `--t-str #94c980` · number `--t-num #e0a06a` · function `--t-fn #6aa6f0` · comment `--t-com #5f656e` (italic) · tag `--t-tag #7fc6a0` · attr-name `--t-attr #d8b15c` · punctuation `--t-punc #9aa0a8` · variable `--t-var #e6e8ea` · constant/boolean/builtin `--t-const #e08b6a` · property `--t-prop #6ec0c0`
- (See the `.ln-code .token.*` rules in `design/styles.css` for the full Prism token→variable mapping.)
**Typography:**
- UI: `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif`. Base 13px.
- Mono: `"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace`. Editor 13px / line-height 20px; terminals 12.5px / 18px.
- Panel headers: 1010.5px uppercase, letter-spacing ~.08em.
**Radii / spacing:** card/control radii 611px (panels 7px, modals 1011px, chips 45px). Icon chips 15px / radius 3.5px. Splitters 5px. Column gaps are the splitters; inside panels use the paddings noted per component.
**Shadows:** menus/popovers `0 16px 44px rgba(0,0,0,.5)`; modals `0 24px 70px rgba(0,0,0,.55)`; toasts `0 12px 34px rgba(0,0,0,.45)`.
## Assets
- **No raster/brand assets.** All icons are simple inline SVGs (geometric: search, branch, close, copy, terminal, spark/diamond, file, folder, diff, plus, minus, check, discard, expand/collapse) — see the `Icon` map in `design/src/components.jsx`. File-type icons are colored monogram chips (no third-party logos). Recreate these as a small icon set (or substitute an open icon library like Lucide for the UI icons, keeping the monogram chips for file types).
- **Font:** JetBrains Mono (OFL) — bundle locally.
## Files in this bundle
- `design/Helder - AI Code Workbench.html` — entry point; open in a browser to view the live prototype.
- `design/styles.css` — all styling + the canonical design-token `:root` block.
- `design/src/data.js` — mock filesystem, git changes, before/after file pairs, and the `buildDiff()` LCS diff that powers the four view modes. **Replace with real FS/git data.**
- `design/src/highlight.js` — Prism language/ext mapping + monogram file-icon metadata.
- `design/src/components.jsx``Icon` set, `FileIcon`, `GitPanel`/`GitRow`, `FileTree`.
- `design/src/editor.jsx` — tabs, the four-mode editor (`PaneView`, `buildLines`), and the full-screen `SplitView`.
- `design/src/terminals.jsx` — the agent + shell terminal component and the simulated session (replace the simulation with real PTYs).
- `design/src/overlays.jsx``SearchModal`, `ContextMenu`, `PassPopup`, `Toasts`.
- `design/src/app.jsx` — composition: layout, resizable splitters, keyboard shortcuts, git/commit/stage logic, copy-reference + pass-to-agent wiring.
## Implementation order (suggested)
1. Electron shell + frameless dark window; port tokens to CSS variables; bundle JetBrains Mono.
2. Static layout: four resizable columns + title/status bars.
3. Real file tree + open files into tabs (read-only) with Prism highlighting.
4. Git panel from `git status` (read-only), then staging + commit, then the four diff modes + Split.
5. Search (ripgrep + fuzzy).
6. Terminals via node-pty + xterm.js; run `claude` in the agent pane.
7. Copy reference + Pass-on-to-Agent (clipboard + bracketed-paste into the agent PTY).