| 1 | # Codewhale terminal views as reusable Ratatui parts |
| 2 | |
| 3 | Use the parts of Codewhale's terminal interface in your own app. The library |
| 4 | accepts your display data, draws into a Ratatui buffer, and leaves application |
| 5 | actions with you. You can use the native composer by itself, put the workbar |
| 6 | beside your conversation, or build a complete picker with the instrument shell. |
| 7 | |
| 8 | The source reference for this guide is |
| 9 | [`Hmbown/CodeWhale` at `a79ce5c4d5ed1a5f7032185710c27343a900351c`](https://github.com/Hmbown/CodeWhale/tree/a79ce5c4d5ed1a5f7032185710c27343a900351c/crates/tui/src/tui). |
| 10 | Paths in the catalog below are relative to `crates/tui/src/tui/` in that tree. |
| 11 | |
| 12 | ## Start with an extracted renderer |
| 13 | |
| 14 | | Part | Current native source | What you supply | |
| 15 | | --- | --- | --- | |
| 16 | | `InstrumentSurface` | `views/mod.rs::render_underwater_surface`, action-footer helpers | Title and key/action labels | |
| 17 | | `SessionList`, `SessionRow` | `session_picker.rs::build_list_lines`, `format_session_line` | Filtered and sorted sessions, selected row, timestamp text | |
| 18 | | `NativeComposer` | `widgets/mod.rs`, `composer_chrome.rs` | Draft, focus, submission state, hint and target | |
| 19 | | `PostureBar` | `phase_strip.rs::TidelineFooter` | Permission, mode, clocks, counts and interrupt hint | |
| 20 | | `MetricsLine` | `infoline.rs::InfoLine` | Model, context, costs, timing and optional metrics | |
| 21 | | `Workbar` | `work_surface/{model,input,render}` | Tasks, agents, jobs, files, notes and workspace facts | |
| 22 | | `WorkflowProgress` | `widgets/workbar.rs` | Workflow runs, outcomes, elapsed time and tokens | |
| 23 | | `TerminalShell` | `ui/frame.rs` | Sizes for transcript, pending input, composer and footer slots | |
| 24 | | `OceanColumn`, `Habitat` | `ocean.rs`, `ambient_life.rs` | Time, motion policy, phase and context percentage | |
| 25 | | `Theme::tui`, `TuiPalette` | `crates/palette/src/` | Terminal capabilities and the selected native theme | |
| 26 | |
| 27 | These retain the native layout or authored visual behavior while adapting |
| 28 | application types into portable display facts. `InstrumentSurface` uses a |
| 29 | one-cell horizontal margin at 44 columns and a one-cell vertical margin at 24 |
| 30 | rows. Its title sits on the top rule; whole action hints wrap along the bottom. |
| 31 | `SessionList` keeps the numbered shortcuts, current/fork/archived labels, |
| 32 | 32-cell title cap and native scroll rail. Your app loads sessions and handles |
| 33 | resume, search, rename and deletion. |
| 34 | |
| 35 | The current main terminal has a conversation followed by pending input, |
| 36 | composer, posture, workflow progress, metrics and the workbar. Its default |
| 37 | layout has no top header or permanent Files sidebar. `Workbar` is the tabbed |
| 38 | Tasks/Fleet/Jobs/Files/Notes/Context/Git/Cost dock; `WorkflowProgress` is the |
| 39 | separate, borderless workflow strip. |
| 40 | |
| 41 | ```rust |
| 42 | use codewhale_ratatui::{ |
| 43 | InstrumentSurface, KeyHint, Paint, PickerState, SessionList, SessionRow, |
| 44 | Theme, |
| 45 | }; |
| 46 | |
| 47 | let theme = Theme::detect().tui(); |
| 48 | let sessions = SessionList::new(vec![ |
| 49 | SessionRow::new("4a80c752-28b1", "Review authentication") |
| 50 | .messages(18) |
| 51 | .mode("Work") |
| 52 | .updated("2026-10-01 14:12 (2m ago)") |
| 53 | .current(true), |
| 54 | ]).state(PickerState::new(0)); |
| 55 | |
| 56 | let surface = InstrumentSurface::new("sessions").actions(vec![ |
| 57 | KeyHint::new("Enter", "resume"), |
| 58 | KeyHint::new("/", "search"), |
| 59 | KeyHint::new("Esc", "close"), |
| 60 | ]); |
| 61 | |
| 62 | // In your rendering callback: |
| 63 | // let body = surface.draw(area, buffer, &theme); |
| 64 | // sessions.paint(body, buffer, &theme); |
| 65 | // Use sessions.hitboxes(body, &theme) to connect mouse selection to your state. |
| 66 | ``` |
| 67 | |
| 68 | ## Native view recipes |
| 69 | |
| 70 | Run `cargo run --example gallery` and choose a recipe. The recipe functions in |
| 71 | [`src/gallery/native_views.rs`](src/gallery/native_views.rs) are also small |
| 72 | integration examples you can adapt. These are **example compositions** of |
| 73 | native templates and caller data, rather than exported application controllers. |
| 74 | |
| 75 | | Recipe | Native shape and reusable parts | |
| 76 | | --- | --- | |
| 77 | | `view-sessions`, `view-sessions-narrow`, `view-sessions-compact`, `view-sessions-empty` | `InstrumentSurface` + `SessionList`; history left 56%, list right 44%; narrow rooms stack, short rooms retain the list | |
| 78 | | `view-settings`, `view-settings-narrow` | Native Settings category/search header, Display rows, optional groups and fact inspector; footer preview uses `PostureBar` | |
| 79 | | `view-commands` | Native centered palette; filter/count/scope header, section heading and aligned command descriptions | |
| 80 | | `view-models`, `view-models-narrow` | Instrument title/catalog action, provider line, model table and reasoning pane; native list/detail split and 30-cell effort pane | |
| 81 | | `view-providers` | Instrument title/catalog action, active provider marker and list/detail layout | |
| 82 | | `view-theme` | Native selectable theme order, numbered choices and five swatches, including the Underwater water column | |
| 83 | | `view-mode` | Native centered choice: Work, Plan, Operate, each on one row with its original hint | |
| 84 | | `view-status` | Native centered footer configuration with checkboxes and the current status-item labels | |
| 85 | | `view-file-picker` | Instrument with the `@ attach` match title, query, relevance field and paths | |
| 86 | | `view-fleet-dock`, `view-jobs-dock`, `view-files-dock`, `view-context-dock`, `view-git-dock`, `view-cost-dock` | Native `Workbar` panels in a side placement beside conversation and composer | |
| 87 | |
| 88 | The Settings recipe supplies five Appearance rows. Model/provider recipes |
| 89 | supply a small configured list. Catalog discovery, provider sign-in, connection |
| 90 | tests, routing, settings persistence, session preview parsing and filesystem |
| 91 | scanning belong to the host. The fleet **dock** recipe demonstrates the workbar |
| 92 | Fleet panel; the separate `/fleet` roster remains a host-owned room. |
| 93 | |
| 94 | ## Every current modal |
| 95 | |
| 96 | The current `ModalKind` enum has **33** variants. “Recipe reuse” means that the |
| 97 | named preview shows reusable visual parts for that room, not a copy of its |
| 98 | runtime or every state. Application-specific rooms remain in Codewhale; this |
| 99 | catalog connects them to the kit without introducing another controller. |
| 100 | |
| 101 | <!-- modal-inventory:start --> |
| 102 | | Modal kind | Native source | Reusable parts | Gallery recipe / coverage | |
| 103 | | --- | --- | --- | --- | |
| 104 | | `PetHabitat` | `pet_watch/habitat.rs`, `ambient_life.rs` | `Habitat`, `FishSchool`, `Jellyfish`, `BubbleField`, `Whale` | `habitat-scene`: extracted marine visuals; pet interaction belongs to the host | |
| 105 | | `Approval` | `approval/view.rs` | `ApprovalCard`, `ApprovalState`, `KeyHint` | `approval-command`, `approval-patch`: approval composition; host owns policy | |
| 106 | | `Elevation` | `approval/elevation.rs` | `ApprovalCard`, `KeyHint` | `approval-elevation`: recipe reuse for the elevation subject and choices | |
| 107 | | `UserInput` | `user_input.rs` | `Form`, `TextInput`, `Picker`, `KeyHint` | `form`: recipe reuse; host supplies the question schema and answers | |
| 108 | | `CommandPalette` | `command_palette.rs` | `InstrumentSurface::draw_footer`, `List`, `Theme` | `view-commands`: native palette composition | |
| 109 | | `Help` | `views/help.rs` | `KeyHints`, `Keymap`, `List`, `Transcript` | `view-commands`, `transcript-prose`: recipe reuse for discovery and grouped help; host supplies commands | |
| 110 | | `SubAgents` | `views/mod.rs::SubAgentsView`, `agent_details.rs` | `Workbar`, `AgentCard`, `Transcript` | `workbar-fleet`, `view-fleet-dock`: extracted agent rows; full manager and details are host-owned | |
| 111 | | `Pager` | `pager.rs`, `agent_details.rs` | `Transcript`, `CodeBlock`, `InstrumentSurface`, `Diff` | `transcript-prose`, `transcript-code`, `diff`: content recipe reuse; host owns paging and copy | |
| 112 | | `LiveTranscript` | `live_transcript.rs` | `Transcript`, `Message`, `ToolCard`, `TerminalShell` | `transcript-prose`, `showcase-work`: content recipe reuse; host streams and scrolls | |
| 113 | | `SessionPicker` | `session_picker.rs` | `InstrumentSurface`, `SessionList`, `SessionRow`, `PickerState` | `view-sessions` and its three responsive variants: native composition and extracted rows | |
| 114 | | `Config` | `views/mod.rs::ConfigView` | `InstrumentSurface`, `Theme`, `PostureBar`, setting display facts | `view-settings`, `view-settings-narrow`: native Settings shell composition | |
| 115 | | `ModelPicker` | `model_picker.rs` | `InstrumentSurface`, `List`, `Theme` | `view-models`, `view-models-narrow`: configured-model composition; host owns catalog, effort choices and apply | |
| 116 | | `ProviderPicker` | `provider_picker.rs` | `InstrumentSurface`, `List`, `Theme` | `view-providers`: native provider-list composition; host owns credentials and discovery | |
| 117 | | `ModePicker` | `views/mode_picker.rs` | `List`, `ListRow`, `InstrumentSurface::draw_footer`, `centered` | `view-mode`: native three-mode composition | |
| 118 | | `FleetRoster` | `views/fleet_roster.rs` | `List`, `AgentCard`, `InstrumentSurface::draw_footer` | `view-fleet-dock`: agent-fact recipe reuse, not the separate operator/member roster | |
| 119 | | `FleetSetup` | `views/fleet_setup.rs` | `Form`, `TextInput`, `Picker`, `KeyHint` | `form`, `view-providers`: editing and route-choice recipe reuse; host saves team definitions | |
| 120 | | `FleetList` | `views/fleet_list.rs` | `InstrumentSurface`, `List`, `EmptyState` | `view-sessions`, `view-fleet-dock`: list/agent recipe reuse; host owns team selection | |
| 121 | | `FleetDetail` | `views/fleet_detail.rs` | `InstrumentSurface`, `List`, `AgentCard`, `Transcript` | `view-fleet-dock`, `transcript-prose`: member/detail recipe reuse | |
| 122 | | `HotbarSetup` | `hotbar/setup.rs` | `Form`, `Picker`, `KeyHint` | `form`, `view-mode`: recipe reuse for bound choices; host owns hotbar commands | |
| 123 | | `SetupWizard` | `setup/mod.rs` | `Form`, `TextInput`, `Picker`, `NativeComposer` | `form`, `view-providers`, `native-composer`: setup building blocks; host controls steps | |
| 124 | | `FilePicker` | `file_picker.rs` | `InstrumentSurface`, `Theme`, text fitting | `view-file-picker`: native path-picker composition; host supplies scan results and relevance | |
| 125 | | `StatusPicker` | `views/status_picker.rs`, `../config.rs::StatusItem` | `InstrumentSurface::draw_footer`, `Theme`, `centered`, `MetricsLine` | `view-status`: native checkbox composition; host stores the chosen fields | |
| 126 | | `FeedbackPicker` | `feedback_picker.rs` | `Form`, `TextInput`, `Picker`, `KeyHint` | `form`, `text-input-typed`: feedback-input recipe reuse; submission belongs to the host | |
| 127 | | `ThemePicker` | `theme_picker.rs`, `crates/palette/src/ids.rs` | `InstrumentSurface`, `TuiPalette`, `Theme`, `OceanRamp` | `view-theme`: native theme-list composition; host previews, saves and reverts | |
| 128 | | `ContextMenu` | `context_menu.rs` | `List`, `Picker`, `KeyHint`, `Theme` | `view-commands`: action-choice recipe reuse; host supplies the target's actions | |
| 129 | | `ContextInspector` | `context_inspector.rs` | `InstrumentSurface`, `List`, `Transcript`, `Workbar` | `view-context-dock`, `instrument-surface`: context-fact recipe reuse; host provides the source map | |
| 130 | | `SkillsManager` | `views/skills_manager.rs` | `InstrumentSurface`, `List`, `SettingDetail`, `EmptyState` | `view-providers`: list/inspector recipe reuse; host discovers and enables skills | |
| 131 | | `Extensions` | `views/extensions.rs` | `InstrumentSurface`, `List`, `Transcript`, `EmptyState` | `view-providers`, `view-commands`: inventory/discovery recipe reuse; mutations remain in host controllers | |
| 132 | | `WorktreeManager` | `worktree_manager.rs` | `InstrumentSurface`, `List`, `Form`, `Diff` | `view-sessions`, `diff`: list/comparison recipe reuse; host owns Git operations | |
| 133 | | `WorkflowsManager` | `views/workflows_manager.rs` | `InstrumentSurface`, `List`, `WorkflowProgress`, `WorkflowTree` | `workflow-progress-live`, `workflow-tree`: run-content recipe reuse; host reads the journal and cancels runs | |
| 134 | | `Automations` | `views/automations.rs` | `InstrumentSurface`, `List`, `Form`, `KeyHint` | `view-sessions`, `form`: schedule-list/editor recipe reuse; host owns scheduling and mutations | |
| 135 | | `LaunchResumeConfirm` | `launch_resume_confirm.rs` | `Dialog`, `KeyHint`, `SessionRow` | `dialog`, `session-list`: confirmation recipe reuse; host performs the resume | |
| 136 | | `RouterSetup` | `views/router_setup.rs` | `InstrumentSurface`, `Form`, `Picker`, `KeyHint` | `view-models`, `form`: route/choice recipe reuse; host owns router tests and configuration | |
| 137 | <!-- modal-inventory:end --> |
| 138 | |
| 139 | ## The work dock is a view family too |
| 140 | |
| 141 | `work_surface/model.rs` projects all eight tabs into row facts; |
| 142 | `work_surface/render/mod.rs` paints them. |
| 143 | `work_surface/render/rows.rs` and `layout.rs` own their columns and placement. |
| 144 | The kit preserves those renderers instead of giving each tab a new card design. |
| 145 | |
| 146 | | Native work panel | Kit part | Gallery | |
| 147 | | --- | --- | --- | |
| 148 | | Tasks | `WorkbarPanel::Tasks`, task marks, goal and progress | `workbar-tasks` | |
| 149 | | Fleet | `WorkbarPanel::Fleet`, `WorkbarAgent` with responsive columns | `workbar-fleet`, `view-fleet-dock` | |
| 150 | | Jobs | `WorkbarPanel::Jobs`, status and job details | `workbar-jobs`, `view-jobs-dock` | |
| 151 | | Files | `WorkbarPanel::Files`, grouped edited/read rows | `workbar-files`, `view-files-dock` | |
| 152 | | Notes | `WorkbarPanel::Notes`, note text and actions | `workbar-notes` | |
| 153 | | Context | `WorkbarPanel::Context`, budget and source facts | `workbar-context`, `view-context-dock` | |
| 154 | | Git | `WorkbarPanel::Git`, branch, changes and commit facts | `workbar-git`, `view-git-dock` | |
| 155 | | Cost | `WorkbarPanel::Cost`, session/agent/cache facts | `workbar-cost`, `view-cost-dock` | |
| 156 | |
| 157 | Choose bottom, top, left or right placement. The same public row types work in |
| 158 | each placement. Host input selects the row and dispatches its action; the |
| 159 | library does not run tools, inspect Git, read files, or infer prices. |
| 160 |