Standalone design harness for Cortex TUI surfaces. Browse every product screen with fixture data, tweak chrome before touching the real CLI, and dump ASCII frames for review or golden tests.
This is a sibling git repository next to cortex-code.
It is not a member of the cortex-code Cargo workspace. The designer depends
on the product tui crate through a static path so tooling stays out of the
product monorepo.
Brand: Cortex / Cortex Code. Default theme: CortexNight
(cortexnight). Default canvas: 92×30.
Clone both repos as neighbors (names matter for the default path):
/work/baseintelligence/ # or your parent directory
cortex-code/ # product monorepo
crates/tui/ # path dependency target
crates/tui-core/ # transitive TUI stack
crates/frame/ # theme tokens (CortexNight, …)
…
cortex-tui-designer/ # this repo (separate git root)
src/
snapshots/ # golden ASCII dumps (when present)
.designer-out/ # local write dumps from interactive `w` (gitignored)
parent/
├── cortex-code/ # product
│ └── crates/tui/
└── cortex-tui-designer/ # this harness
Path dependency (Cargo contract):
tui = { path = "../cortex-code/crates/tui", features = ["designer"] }CORTEX_CODE_PATH is for docs and helper scripts only (default
../cortex-code). Cargo path = cannot read env vars. Keep the sibling folder
names above, or edit Cargo.toml to match your checkout.
| Layout | tui path in Cargo.toml |
When |
|---|---|---|
| local (default, committed) | ../cortex-code/crates/tui |
Designer and cortex-code are siblings |
| ci | ./cortex-code/crates/tui |
cortex-code checked out inside designer root |
Preferred CI layout (designer as $GITHUB_WORKSPACE):
$GITHUB_WORKSPACE/ # designer repo root
Cargo.toml
scripts/use-layout.sh
cortex-code/ # actions/checkout path: cortex-code
crates/tui/
# CI in-workspace checkout
tui = { path = "./cortex-code/crates/tui", features = ["designer"] }Switch the committed path line without inventing a Cargo env path:
./scripts/use-layout.sh local # ../cortex-code/crates/tui (default)
./scripts/use-layout.sh ci # ./cortex-code/crates/tuiAlternatively, CI may keep the local path and symlink:
ln -sfn "$GITHUB_WORKSPACE/cortex-code" ../cortex-codeCI may also check out cortex-code as a true sibling and use the same relative
path. Pick one layout and keep Cargo.toml in sync (prefer use-layout.sh).
| Goal | How |
|---|---|
| See every Cortex TUI surface with fake data | Scenario catalog + product paint path |
| Iterate design without running live agent turns | Hermetic fixtures (no DB, no network, no OAuth) |
| Capture frames for review / regression | Headless dump and optional goldens under snapshots/ |
| Drive real product chrome | tui::draw (re-export of ui::draw under feature designer) |
Paint goes through the product stack (App + draw / ui::draw), not a
parallel mock UI. Fixture bridges (App::designer_*) live behind
feature = "designer" on crates/tui in cortex-code.
- Rust 1.85+ (edition 2024), matching cortex-code
- A local checkout of cortex-code as a sibling (see layout)
- Optional: a real TTY for interactive
run
From this repo root:
# Resolve product tui via ../cortex-code/crates/tui
cargo check
cargo build --release
# Scripts / docs may set this; Cargo still uses the path in Cargo.toml
export CORTEX_CODE_PATH="${CORTEX_CODE_PATH:-../cortex-code}"If the path is wrong, cargo fails to resolve tui. Fix the sibling layout or
the path = line, then retry.
Pin ratatui = "0.29" and crossterm = "0.28" with the product workspace.
CLI surface (flags stay stable):
# List scenario ids
cargo run --release -- list
# Interactive gallery (TTY): j/k navigate, Enter select, r reload, w dump, q quit
cargo run --release -- run
cargo run --release -- run --scenario home-motd
# Headless UTF-8 buffer to stdout (default size 92x30, theme cortexnight)
cargo run --release -- dump --scenario home-motd
# ANSI colors (theme tokens: truecolor SGR) — use in a real terminal
cargo run --release -- dump --scenario home-motd --color always
cargo run --release -- dump --scenario view-mc-home --color always
cargo run --release -- dump --scenario chat-idle --width 92 --height 30 --theme cortexnight| Subcommand | Role |
|---|---|
list |
Print catalog ids (and categories when available) |
run |
Interactive browser over scenarios |
dump |
Headless paint of one scenario to stdout |
Defaults for dump and goldens: size 92×30, theme cortexnight, reduced motion on (stable frames). Unknown scenario ids exit non-zero.
Stability: designer_prepare_base forces reduced_motion(true). Shell
fixtures avoid live clocks/rand in settled paints — double-dump of home-motd
and chat-idle is byte-equal (see scenarios::shell tests). Busy/streaming
frames may still include elapsed timers and are not stability-guaranteed.
Interactive w writes the current buffer under ./.designer-out/<id>.txt
(directory created on demand; gitignored).
run is not a slideshow of dumps. It starts a live product event loop on a
fixture App: every normal key goes to App::on_key (composer text, list nav,
dialogs, slash, permissions, scroll, …). Data stays mocked (no network/DB).
| Key | Action |
|---|---|
| (any normal key) | Product TUI handler (App::on_key) |
F6 / F7 |
Previous / next catalog scenario (rebuild mock) |
F8 |
Write plain dump → .designer-out/<id>.txt |
F9 |
Rebuild current scenario (reset mock state) |
F10 or Ctrl+C |
Quit designer |
cargo run -- run -- id home-motd
# or
cargo run -- run dialog-modelsColored dump for screenshots (no interaction):
cargo run -- dump --scenario dialog-models --color always- Ensure cortex-code is checked out beside this repo and
cargo checkworks. - Add or edit a scenario fixture (see How to add a scenario).
- Paint headless:
cargo run -- dump --scenario <id>(or--release). - Browse live:
cargo run -- run --scenario <id>(TTY required). - Run the suite:
cargo test(includes catalog completeness + core goldens). - Full gate:
./scripts/verify.sh(test + list + three dump smoke checks). - When product chrome or tokens change in cortex-code (
crates/tui,frame), re-dump here and update goldens only if the visual change is intentional (see Golden snapshots).
Typical loop: edit fixture → dump → run → adjust product or fixture → test → dump again.
- Pick a stable id in kebab-case. Prefer the plan catalog names
(
home-motd,dialog-models,view-mc-home, …) so dumps and goldens stay aligned across workers. - Register the id in the scenario catalog (module that backs
list/dump/run). One id → one builder that returns a configuredApp. - Build hermetic state via product fixtures only:
- Prefer
App::designer_*helpers underfeature = "designer"(prepare base, transcript, dialogs, views, sidebar, palette, permission preview, …). - Call
set_theme("cortexnight")andset_reduced_motion(true)for dump paths (or usedesigner_prepare_base). - Do not open the real store, ambient auth, live MCP, or network refresh on the fixture path.
- Prefer
- Paint with
tui::draw/ui::drawinto aTestBackend(or the live terminal inrun). Buffer must be non-empty and must not panic. - Verify:
cargo run --release -- list | grep -F '<your-id>' cargo run --release -- dump --scenario <your-id>
- Optional golden: for core ids, store normalized ASCII under
snapshots/<id>.txtat 92x30 cortexnight reduced motion. - Document any rename of a catalog id in this README in one line so dumps and external checklists stay in sync.
Every id is registered in default_catalog() and must paint a non-empty 92×30
buffer. Golden = committed under snapshots/ (core set, todo 24).
| Id | Title | Category | Golden |
|---|---|---|---|
home-motd |
Home MOTD | shell | yes |
chat-idle |
Chat idle | shell | yes |
chat-streaming |
Chat streaming | shell | yes |
chat-tools |
Chat tools | shell | yes |
chat-error |
Chat error | shell | |
chat-blocked |
Chat blocked | shell | |
chrome-shell-mode |
Chrome shell mode | shell | |
chrome-plan-mode |
Chrome plan mode | shell | |
overlay-slash |
Overlay slash | shell | yes |
overlay-mention |
Overlay mention | shell | |
overlay-find |
Overlay find | shell | |
overlay-toast-error |
Overlay toast error | shell | |
dialog-sessions |
Dialog sessions | overlays | |
dialog-models |
Dialog models | overlays | yes |
dialog-agents |
Dialog agents | overlays | |
dialog-skills |
Dialog skills | overlays | |
dialog-variants |
Dialog variants | overlays | |
dialog-themes |
Dialog themes | overlays | |
dialog-subagents |
Dialog subagents | overlays | |
dialog-attachments |
Dialog attachments | overlays | |
dialog-fork |
Dialog fork | overlays | |
dialog-export |
Dialog export | overlays | |
palette |
Command palette | overlays | |
permission-dock |
Permission dock | overlays | yes |
dialog-rename |
Dialog rename | overlays | |
dialog-compact |
Dialog compact | overlays | |
dialog-init |
Dialog init | overlays | |
sidebar-context |
Sidebar context | overlays | yes |
sidebar-files |
Sidebar files | overlays | |
sidebar-lsp |
Sidebar LSP | overlays | |
sidebar-mcp |
Sidebar MCP | overlays | |
sidebar-todo |
Sidebar todo | overlays | |
sidebar-subagents |
Sidebar subagents | overlays | |
sidebar-queue |
Sidebar queue | overlays | |
auth-login |
Auth login | fullscreen | yes |
connect-picker |
Connect picker | fullscreen | |
onboarding |
Onboarding | fullscreen | |
view-status |
View status | fullscreen | yes |
view-timeline |
View timeline | fullscreen | |
view-queue |
View queue | fullscreen | |
view-mcp |
View MCP | fullscreen | |
view-diff |
View diff | fullscreen | |
view-help |
View help | fullscreen | |
view-review |
View review | fullscreen | |
view-mc-home |
View MC home | fullscreen | yes |
view-mc-failure |
View MC failure | fullscreen | |
view-mc-stub-concurrency |
View MC stub concurrency | fullscreen | |
view-mc-stub-launch |
View MC stub launch | fullscreen | |
view-mc-stub-launch-blocked |
View MC stub launch blocked | fullscreen | |
view-mc-stub-team-board |
View MC stub team board | fullscreen | |
theme-gallery |
Theme gallery | fullscreen | yes |
diff-viewer |
Diff viewer | fullscreen |
Core goldens live in snapshots/<id>.txt (UTF-8, C5 dump format: cell symbols
only, trailing spaces trimmed, final newline). Defaults: 92×30, theme
cortexnight, reduced_motion on.
| Check | Command |
|---|---|
| Compare dumps to goldens | cargo test goldens:: |
| Regenerate all core goldens | UPDATE_GOLDENS=1 cargo test goldens:: -- --nocapture |
| Stability (double dump) | included in goldens::tests::double_dump_core_ids_byte_equal_after_normalize |
When to update goldens
- You intentionally changed product chrome/tokens in cortex-code, or a designer fixture, and the new frame is correct.
- Run
UPDATE_GOLDENS=1 cargo test goldens:: -- --nocapture. - Review
git diff snapshots/(ASCII only — no binary). - Commit snapshots with the fixture/product change that caused the delta.
- Re-run
cargo testwithoutUPDATE_GOLDENSso CI matches the committed files.
Do not regenerate goldens to silence a flake. If a core id is unstable under reduced_motion, fix the fixture (seed clocks, freeze timers) first.
Core golden ids (12): home-motd, chat-idle, chat-streaming, dialog-models,
permission-dock, auth-login, view-mc-home, theme-gallery, view-status,
sidebar-context, chat-tools, overlay-slash.
./scripts/verify.shRuns cargo test, cargo run -- list, and headless dumps for home-motd,
dialog-models, and view-mc-home. Exits non-zero on any failure.
| Symptom | Likely cause | Fix |
|---|---|---|
error: failed to load source for dependency tui |
cortex-code not at the path in Cargo.toml |
Clone sibling layout, or ./scripts/use-layout.sh ci after checking out cortex-code under this root |
unknown scenario id: … |
Typo or id not registered | cargo run -- list; add builder in src/scenarios/ + REQUIRED_IDS |
| Golden mismatch in CI | Product paint drifted without snapshot update | Inspect dump locally; if intentional, UPDATE_GOLDENS=1 and commit |
| Flaky golden / double-dump differs | Live clock, rand, or animation still on | Ensure designer_prepare_base / set_reduced_motion(true); freeze fixture timers |
| Empty paint / panic in dump | Fixture left App in invalid state | Reproduce with cargo run -- dump --scenario <id>; fix App::designer_* setup |
Interactive run exits immediately |
No TTY | Use a real terminal, or stick to dump / list |
| Auth / store side effects in tests | Real home/XDG used | Fixtures must stay hermetic (temp home); see fullscreen auth tests |
| CI path wrong | Layout still local while cortex-code is nested |
Workflow should run ./scripts/use-layout.sh ci after checkout |
scenario builder → App (fixtures / designer_*) → tui::draw (ui::draw) → buffer
- Import paint as
use tui::draw(crate-root re-export under featuredesigner). - Theme tokens and CortexNight live in cortex-code
crates/frame(style) and related TUI crates; this repo does not fork the palette. - Interactive product binary remains
cortexfrom cortex-code; this binary is only the gallery harness.
- Product name: Cortex (CLI
cortex), open-source terminal coding agent. - Theme name in docs and flags: CortexNight /
cortexnight. - This crate name: cortex-tui-designer.
- Do not use third-party product branding in docs or fixture copy beyond model ids that already appear as upstream identifiers inside cortex-code fixtures.
Apache-2.0. See LICENSE (same Apache License Version 2.0 text as
cortex-code).
Linked product crates remain under their own licenses in the cortex-code tree.
See NOTICE for a short provenance pointer.
This harness tracks the product TUI via a path dependency. Record the cortex-code commit SHA used when publishing or cutting a designer release:
| Field | Value |
|---|---|
| cortex-code remote | https://github.com/CortexLM/cortex-code |
| cortex-code branch | dev |
| cortex-code SHA | 81802b1d058c63ffff24bc20dc9cbc0d17ae9a98 |
| designer feature | tui crate feature designer |
After bumping the product path checkout, run ./scripts/verify.sh and update
core goldens if chrome changed.
| Path | Role |
|---|---|
../cortex-code/crates/tui |
Product TUI (App, draw, designer feature) |
../cortex-code/crates/frame |
Style / theme tokens |
../cortex-code/README.md |
Product overview and build |
CORTEX_CODE_PATH |
Doc/script default ../cortex-code (not a Cargo env) |
| https://github.com/CortexLM/cortex-tui-designer | This repository (public) |
| https://github.com/CortexLM/cortex-code | Product monorepo |