# Terminal Panel Design System > **Status:** Experimental. First consumer: `fleet-ops`. > > **Format:** Adapted from [google-labs-code/design.md](https://github.com/google-labs-code/design.md) — a structured design-spec template — and remapped to bash CLIs. Where that spec talks about screens, components, and tokens, this one talks about panels, sections, and glyphs. --- ## 1. Vision A unified terminal-output design language for bash-based CLIs in the claude-mods family. One panel grammar, one set of glyphs, one grid. Tools that follow it feel like instruments on the same workbench instead of seventy hand-rolled formats. The aspiration: outputs that read as **deliberate, bespoke, and quiet** — like a well-laid PCB. Every glyph in its place, nothing decorative, nothing shouting. When a user runs five tools in a session, the toolkit feels coherent. --- ## 2. Principles 1. **Information first, ornament last.** Decoration that doesn't carry meaning gets cut. 2. **Strip color and the layout still works.** Color amplifies; it never carries the only signal. 3. **ASCII fallback is mandatory.** Every Unicode glyph has a 1–3 char ASCII proxy registered alongside it. 4. **Use the invisible grid, not lines, to align.** Whitespace between columns aligns rows. Long horizontal rules are clutter. 5. **Tether to the left.** Primary content rides the left rail. Right-side elements are leaves or iconography, never floating UI. 6. **Let elements breathe.** Blank `│` rows between sections are content. Density without breath is unreadable. 7. **Pops of color are dopamine; everywhere is wallpaper.** One brand emoji in the header, two health indicators in the footer, color on state words. That's the budget. 8. **Borders are continuous.** Top and bottom rules run uninterrupted from corner to terminator. Gaps break the panel's "wrap the interface" feel. 9. **One style per diagram.** Pick rounded corners, stick with rounded corners. Don't mix box families. 10. **Same width, taller height for emphasis** — never wider. Width consistency is what makes columns line up; height variation gives presence without breaking the grid. 11. **Bespoke, not branded.** No ASCII art logos. No flashy gradients. The polish is in placement and restraint. --- ## 3. Foundations ### 3.1 Color tokens Color is signal, never the only signal. Disabled when stdout isn't a TTY or `NO_COLOR` is set; forced on with `FORCE_COLOR=1`. | Token | ANSI | Use for | | ------------- | ------- | -------------------------------------------------------- | | `accent` | cyan | Brand chrome (panel rules, hotkey letters, header rule) | | `pending` | yellow | RUNNING, CONFLICT, modified files, HEAD marker | | `ok` | green | READY, LANDED, healthy daemon, landed commits | | `alarm` | red | FAILED, blocked, conflicts, critical health | | `warn` | orange | Warning alerts, the inline alert triangle | | `tag` | magenta | Untracked files (lazygit/magit convention) | | `meta` | dim | Counts, ages, base branch, timestamps, dotted leaders | | `default` | fg | Branch names, file paths — the content the user came for | ### 3.2 Glyph palette Every glyph below is registered with an ASCII fallback in `term.sh`. Don't introduce new ones without registering them. #### Panel and tree connectors | Role | Unicode | ASCII | Notes | | ----------------- | ------- | ------- | --------------------------------------- | | corner: panel TL | `╭` | `+` | Rounded — for the outer panel only | | corner: panel TR | `╮` | `+` | Rounded | | corner: panel BL | `╰` | `+` | Rounded | | corner: panel BR | `╯` | `+` | Rounded | | T-junction | `├` | `+` | Section attachment point | | L-corner | `└` | `` ` `` | Last leaf in a section | | horizontal | `─` | `-` | Rule fill | | vertical | `│` | `\|` | Panel left edge, section continuation | #### Rail glyphs (commit-graph and pipeline beads) | Role | Unicode | ASCII | Meaning | | ------------------ | ------- | ----- | -------------------------------- | | commit (landed) | `●` | `*` | a commit on the rail | | HEAD | `◉` | `@` | tip of the lane | | conflict | `⊗` | `X` | rebase / merge failure point | | link | `─` | `-` | rail segment between commits | #### Pip-bar glyphs (progress / completion) | Role | Unicode | ASCII | | ---------- | ------- | ----- | | pip filled | `▰` | `#` | | pip empty | `▱` | `-` | Default width: **10 pips** = clean 10% increments. Override only when the data has a natural denominator that isn't a percentage (`5 of 7 stages` → 7 pips). #### Health indicators (small bullets, colored) | Role | Unicode | ASCII | Notes | | -------- | ------- | ------- | --------------------------------------- | | healthy | `•` | `(+)` | Green, slowly pulsing in live mode | | pending | `•` | `(.)` | Yellow | | warning | `•` | `(!)` | Orange | | critical | `•` | `(!!)` | Red | | busted | `⬤` | `(X)` | LARGE grey, motionless — unmissable | | unknown | `•` | `(?)` | Dim | `•` (BULLET, U+2022) is smaller than `●` and reads as a tidy dot when colored. `⬤` (BLACK LARGE CIRCLE, U+2B24) is intentionally bigger to make a busted state unmissable. #### The terminator dot `●` is reserved as the right-edge terminator on header and footer rules. **Never** used as an inline divider, decorator, or health indicator. One job, one place. #### Brand emoji registry | Tool | Unicode | ASCII | | ------------ | ------- | ----- | | fleet | ⚡ | `[F]` | | forge | 🔨 | `[B]` | | psql | 🐘 | `[P]` | | watch | 📡 | `[M]` | | deploy | 🚀 | `[D]` | | git | 🌿 | `[G]` | | windows-ops | 🩺 | `[H]` | #### Header indicators | Role | Unicode | ASCII | Use for | | --------------- | ------- | ----- | ---------------------------------- | | branch | `⎇` | `(b)` | `⎇ main` — base branch indicator | #### Inline alert | Role | Unicode | ASCII | Color | | -------- | ------- | ----- | ------ | | warning | `▲` | `!` | orange | | critical | `▲` | `!` | red | #### Empty state | Role | Unicode | ASCII | | ---- | ------- | ----- | | tip | `💡` | `(i)` | #### Spinners (live mode only) Three families, each with a different role: **Working** — task actively progressing. Fast, 10 frames, ~80ms/frame. ``` ⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏ ``` ASCII fallback: `| / - \` (classic 4-frame). **Heartbeat** — daemon proof-of-life. Slow, 6 frames, ~600ms/cycle. ``` · ∙ • ● • ∙ ``` ASCII fallback: `. : * :`. Used in the footer health-indicator slot. Stops and goes grey when the daemon is busted. ### 3.3 Spacing & the invisible grid Layout is built on whitespace alignment, not vertical bars. The grid for a leaf row in a panel: ``` [panel-vert] [section-indent] [tree-conn] [name-col] [rail-col] [meta-col] [age-col] │ ···· ├── 32 chars 14 chars 12 chars 6 chars ``` - **Panel vertical** — column 0, the panel's `│`. - **Section indent** — 4 cols of breathing room inside the panel. - **Tree connector** — `├──` or `└──` (4 cols including trailing space). - **Name column** — 32 cols, ellipsis-truncated past that (`feat/oauth-pkce-with-very-long…`). - **Rail column** — 14 cols, right-padded with spaces to align the next column. - **Meta column** — 12 cols (e.g., `M4 ?1`, `clean`, `blocked`). - **Age column** — 6 cols, right-aligned. These widths target an **80-col default**. They scale: a `--wide=120` mode bumps name to 48 and rail to 20. They never exceed terminal width — at <60 cols, drop the rail and meta columns rather than wrap. Section rows ride the same indent: `│ ` (panel + 3 spaces) to land at the section-indent column. --- ## 4. Components ### 4.1 Panel The outer frame: header bar, body, footer bar. The body is wrapped by the panel's `│` running unbroken from `╭──` down to `╰──`. ``` ╭── ⚡ fleet ───────────────────────────────── ⎇ main ───● │ [body] │ ╰── R refresh · L land · ? help ───── • daemon • 17m ───● ``` **Rules** - Top rule starts at column 0 with `╭──`, ends at the right with terminator `●`. - Bottom rule mirrors with `╰──` and a terminator. - The rules have no whitespace gaps. `─` fills every span between elements. - Body lives between the rules; every body line begins with `│`. **Helper:** `term_panel_open` / `term_panel_close`. ### 4.2 Header bar ``` ╭── ⚡ fleet ───────────────────────────────── ⎇ main ───● └┬─┘ └─┬─┘ └──┬──┘ └┬┘ │ │ │ └─ terminator │ └─ tool name (cyan) └─ right indicator (≤ 1) └─ brand emoji (always before name) ``` **Rules** - **Brand emoji + tool name** at top-left, in that order, always. The emoji *is* the tool's identity at a glance. - **One indicator** at top-right max — typically a context tag (`⎇ main`, `db: production`, `region: us-east`). Format: ` ` or `key: value` in dim. - The rule (`─`) fills every gap between brand and indicator and indicator and terminator. **Helper:** `term_panel_open `. ### 4.3 Footer bar ``` ╰── R refresh · L land · ? help ───── • daemon • 17m ───● └─────────┬──────────┘ └────┬─────┘ └┬┘ │ │ └─ terminator │ └─ health indicators (≤ 2) └─ hotkeys (≤ 3) ``` **Rules** - **Up to 3 hotkeys** at bottom-left, format ` `, separated by `·`. Hotkey letters in cyan. - **Up to 2 health indicators** at bottom-right, format `• `. **Two spaces** between indicators (no `·` separator — `•` is already a strong leading marker). - Continuous rule `─` fills the gap between hotkeys and health. - `●` terminator at far right. **Helper:** `term_panel_close `. ### 4.4 Section A grouped block under the header. Section labels are colored by state; no glyph at the junction, no trailing rule. ``` ├── RUNNING (2) │ ├── feat/oauth-pkce ●─●─●─◉ M4 ?1 12m │ └── spike/wasm-eval ●─●─●─●─◉ M7 34m │ ├── READY (2) │ ├── fix/cache-bust ●─◉ clean 2m │ └── chore/bump-axios ●─◉ clean 5m ``` **Rules** - Section header: `├── LABEL (count)`, label colored by state. - No icon at the junction. State is carried by the **label color** plus the **label text**. - One blank `│` row of breath between sections — never zero, never two. - Empty sections are omitted; never render `(0)`. **Helper:** `term_section