Design Reference

Cyber UI

A Tokyo Night–derived terminal TUI language: one job per color, restrained tool-row signal, breathing motion, and fish-isomorphic command highlighting.

theme · cyber-ui-dark mode · truecolor

01 Palette

Base

bg
#0a0a0d
page background
toolSurface
#121218
tool / input panel
bgAlt
#1f2335
side panels · third-party pending
bgSelection
#33467c
selection
fg
#c0caf5
primary text
fgMuted
#a9b1d6
secondary text
fgDim
#565f89
borders / quiet info

Accent — one job per color

cyan
#7dcfff
brand / focus / tool name / $ / shell command
cyanBright
#b4f9f8
emphasis (rare)
blue
#7aa2f7
links · function
tealDark
#41a6b5
quote border · operator
teal
#4fd6be
inline code · context
purple
#bb9af7
keyword · thinking high
green
#9ece6a
diff added · strings · $VAR
orange
#e0af68
number · warning · bash mode
red
#f7768e
error · max thinking
pink
#fca7ea
user bar · pulse peak · path ~ · xhigh

Silver / Path / Prompt

Live in themes/cyber-ui-dark.json vars, read through palette.ts as the single source. Reserved for the working breath, path, and prompt glyph — not body text. Pink already sits in Accent (tokyonight moon magenta).

silverDim
#6f7794
breath trough · path separators
silver
#c8d3ea
breath midpoint (reference)
silverHi
#e6ecfa
breath peak · letter-wave highlight
promptSilver
#aab8ca
prompt glyph

02 Surfaces

Editor

editor
──────────────────────────────────────────⟦ refactor-ui ⟧────
keep tps on the working line after idle

prompt glyph = promptSilver · border tracks thinking / bash · static session label at top-right · long text wraps to the width after the prompt, no clipped glyphs or caret

Working line · running

working · 30fps frame cap
Reasoning... (12s · ↑47.3k ↓1.50k · 182 tps · 󰄉 3)

64-frame dual breath (fgDim ↔ pink / fgDim ↔ cyan, peaks alternate) · verb letter-wave (fgMuted ↔ silverHi) · ambient motion capped at 33ms / 30fps · elapsed · tokens · tps · turn inside the parens · fades in after 10s esc to cancel

Idle summary

idle
done · 2:14 · ↑47.3k ↓3.20k · 156 tps

Shown after retries, compaction, and follow-ups actually settle, until the next prompt · only is green; the rest stays muted

Footer

footer

Thinking ladder · cold → warm, seven steps

thinking
off · minimal · low · medium · high · xhigh · max

One hue, warming as the level rises · xhigh takes pink (tokyonight moon magenta, purple → pink → red) so red stays free for max · max lands on red + bold · no per-character rainbow

Left: model · thinking (max is red/bold) · context · cache  |  Right: path · git · extension statuses · folds to +N when narrow

Tool row · signal restraint

Principle (Grok restraint × sci-fi HUD × high-end dark UI): saturate the status layer, keep content low-chroma. Bars — blue = running, teal = success, red = failure, pink = user input; one panel #121218. Tool name / $ / shell command = cyan (native fish); everything else mostly splits on muted / dim luminance.

gutter · panel #121218 · bar ▍ static triad · fish palette
make the tool row a neon fish gutter
$ npm run typecheck
read extensions/pi-cyber-ui/palette.ts 120 lines
edit themes/cyber-ui-dark.json  12  "vars": { -13    "toolSuccessBg": "#0b1020", +13    "toolSurface": "#121218",  14    "toolErrorBg": "#281e20",
edit themes/cyber-ui-dark.json ✗ oldText not found
ask_user success bar? → teal neon ↑ late-registered tool · original renderer kept, same gutter shell
startup · gutter wrap diagnostic
Warning: pi-cyber-ui dynamic gutter unavailable · all tools use themed block fallback

A healthy dynamic wrap stays silent. One warning if the running Pi renderer bridge is incompatible; every tool then falls back to the native themed block. A single third-party renderer exception keeps the gutter and shows Pi-equivalent raw fallback inside it.

Signal · bar

▍ blue running · static (motion lives in the working HUD)
▍ teal done · static
▍ red failure · the only alarm
▍ pink user input · high-chroma identity; ❯ promptSilver stays quiet

Structure · panel + text

bg #0a0a0d → panel #121218 (shared by tools and input)
tool name / $ / shell command = cyan · path / args / flags = fgMuted
bash quotes = silverDim · $VAR = green · pipes / separators = fgDim · redirects = fg
bar ▍ is 3/8 cell · 1-line pad top and bottom · 1-line gap between call and result

Built-in, extension, and SDK tools all get the same gutter. Tools registered later need no reload. Execute, schema, active set, and original renderer ownership stay untouched. A mismatched renderer bridge falls the whole set back to the native themed block. A failed user-message structure check silently keeps the theme box.

Bash · fish-isomorphic highlight

tokyonight fish palette · lightweight shell tokenizer
$ grep -n -B2 -A10 "function formatBashCall" bash.js
$ npm run typecheck 2>&1 | tail -3
$ CI=1 env bash -lc 'echo $HOME'
$ echo $HOME | wc -c
# $ / tool name / command cyan · param fgMuted · quote silverDim · end fgDim · $VAR green

Cool Minimal × native fish: tool name / $ / shell command share full cyan (same as the tokyonight fish theme — no derived dim). Param/path fall to fgMuted, quote = silverDim, end = fgDim, expansion = green (native fish green). No loud purple/yellow; below the command, lexicon is mostly luminance.

Diff · Syntax · Markdown

diff · added teal / context fgDim
edit themes/cyber-ui-dark.json  12  "vars": { -13    "toolSuccessBg": "#0b1020", +13    "toolSurface": "#121218",  14    "toolErrorBg": "#281e20",
syntax v2 · fence fgDim / string teal / number pink
```ts
  // resolve theme vars
  const resolve = (name: string)
    => hexToRgb("#121218", 255)
```

diff added = teal · context = fgDim; syntax string = teal · number = pink; Markdown fence = fgDim, a low-weight structural edge.

03 Semantic scales

TPS · higher is better

<30 30–59 60–99 ≥100
badexceptional

Context · lower is better

<30% <55% <75% <90% ≥90%
freshcrowded

Cache · higher is better

<30% ≥30% ≥60% ≥85% ≥95%
coldhot

04 Motion

ElementPeriodNotes
spinner pulse4800ms64-frame dual breath · peak pink/cyan alternate · trough fgDim · 75ms/frame
verb wave1800ms120ms/char · 4:3 out of phase with the spinner
message motion30fps · 33msletter-wave, odometer, glow, freeze-fade stay time-continuous; the terminal frame cap drops useless full redraws without changing animation periods
verb rotate8000ms20 verbs, several languages
tps smoothingτ 500mstime-based EMA + 0.5s denominator floor · kills first-frame spikes and stair-step jitter
value odometer≈250msdisplayed value ease-out chases the real count · tokens roll instead of jumping
value glowhold 600 · attack 120 / release 350mseach data arrival re-arms a 600ms hold: stay lit while the stream is live, transition only on start/stop · peak capped at 70% · dt clamped to 64ms
freeze fade250mstoken / tps dim while a tool runs, restore when it ends
hint / summary fade600msesc to cancel and the ✓ done summary fade in

TPS smoothing · raw vs EMA

raw · unsmoothed

— tps

tokens arrive in steps + per-frame recompute → number and color chatter

ema α=0.2 · smoothed

— tps

low-pass · converges smoothly · color stays still

Live tps sim: base drift + arrival noise · left jumps, right EMA chases

Value odometer + glow · raw vs smooth

raw · instant jump

↑128k ↓0

each token batch jumps the number · the whole line shimmies when width changes

odometer + glow · smooth climb

↑128k ↓0

display ease-out chases (~250ms) · a brief glow on text change · fixed-width slot so the line does not shake

Crossing 999 → 1.02k: left line jitters sideways, right slot stays put · glow hits only the changing number, not the whole row

While a tool runs · HUD motion pauses

streaming ⇄ tool running · loop
Reasoning... (12s · ↑47.3k ↓1.50k · 182t/s · 󰄉 3)

While a tool runs, keep the last token / tps and fade them dim · restore live emphasis when it ends

Fade-in · esc hint / idle summary

compressed timeline · loop
Iterating... (0s · ↑47.3k ↓2.80k · esc to cancel)
done · 2:14 · ↑47.3k ↓3.20k · 156t/s

After 10s, esc to cancel fades in (600ms) instead of popping · the summary line fades the same way when the task actually finishes · the terminal interpolates color from bg → target