TUI: replace the wizard-replay ⌥s with a proper settings card - #1069
Merged
Conversation
codyde
added a commit
that referenced
this pull request
Aug 11, 2026
Stacking #1069 on #1072 crosses three changes: harness_blurb gains the railway arm. The extracted helper had `_ => "xAI's Grok"` as its catch-all, and with railway now leading HARNESSES that fallback would have labelled Railway's own agent as Grok. Every harness is named, and the catch-all says nothing rather than guessing. The settings card's "create a project" row carries a workspace, since CreateDefaultProject now takes one. It lists one row per workspace — identical wording with a single workspace, named with several — rather than defaulting to the first, which is the bug #1072 set out to fix. The menu footer drops both `^t` (onto the target line, #1072) and `⌥t` (onto the settings card, #1069), leaving `⌥s settings`.
codyde
force-pushed
the
railway/settings-menu
branch
from
August 11, 2026 04:53
2e58116 to
afa9c4f
Compare
codyde
changed the base branch from
master
to
railway/ca-workspace-first-onboarding-and-railway-agent
August 11, 2026 04:53
codyde
force-pushed
the
railway/ca-workspace-first-onboarding-and-railway-agent
branch
from
August 11, 2026 04:57
1acc18b to
0afa4b1
Compare
codyde
added a commit
that referenced
this pull request
Aug 11, 2026
Stacking #1069 on #1072 crosses three changes: harness_blurb gains the railway arm. The extracted helper had `_ => "xAI's Grok"` as its catch-all, and with railway now leading HARNESSES that fallback would have labelled Railway's own agent as Grok. Every harness is named, and the catch-all says nothing rather than guessing. The settings card's "create a project" row carries a workspace, since CreateDefaultProject now takes one. It lists one row per workspace — identical wording with a single workspace, named with several — rather than defaulting to the first, which is the bug #1072 set out to fix. The menu footer drops both `^t` (onto the target line, #1072) and `⌥t` (onto the settings card, #1069), leaving `⌥s settings`.
codyde
force-pushed
the
railway/settings-menu
branch
from
August 11, 2026 04:57
afa9c4f to
7ccbd80
Compare
codyde
changed the base branch from
railway/ca-workspace-first-onboarding-and-railway-agent
to
master
August 11, 2026 05:05
codyde
added a commit
that referenced
this pull request
Aug 11, 2026
Stacking #1069 on #1072 crosses three changes: harness_blurb gains the railway arm. The extracted helper had `_ => "xAI's Grok"` as its catch-all, and with railway now leading HARNESSES that fallback would have labelled Railway's own agent as Grok. Every harness is named, and the catch-all says nothing rather than guessing. The settings card's "create a project" row carries a workspace, since CreateDefaultProject now takes one. It lists one row per workspace — identical wording with a single workspace, named with several — rather than defaulting to the first, which is the bug #1072 set out to fix. The menu footer drops both `^t` (onto the target line, #1072) and `⌥t` (onto the settings card, #1069), leaving `⌥s settings`.
codyde
force-pushed
the
railway/settings-menu
branch
from
August 11, 2026 05:15
7ccbd80 to
04e4ed8
Compare
codyde
changed the base branch from
master
to
railway/ca-workspace-first-onboarding-and-railway-agent
August 11, 2026 05:29
codyde
force-pushed
the
railway/ca-workspace-first-onboarding-and-railway-agent
branch
from
August 11, 2026 05:52
8c563ef to
3da2073
Compare
Base automatically changed from
railway/ca-workspace-first-onboarding-and-railway-agent
to
master
August 11, 2026 05:54
⌥s used to replay the whole first-run wizard, and ⌥t cycled the theme blind — two chords, one of them a four-step flow, to change one answer. ⌥s now opens a settings card showing every preference from agent-prefs.json with its current value: coding agent, default project, skills sync, and theme. Values with a handful of options cycle in place with ←/→ and save on every change (merged over the file on disk, so the skills exclude list survives). The theme applies to the whole screen as it cycles, exactly like the wizard's theme step, which is why ⌥t retires. The default project opens the wizard's project question as a sub-card — including "create a project" and "decide later" — and comes straight back. A last row replays first-run setup for anyone who wants the guided walk. The wizard itself is unchanged and remains the first-run flow.
One modifier family for the TUI's own chords: ⌥f, ⌥], ⌥s, and now ⌥esc to stop typing in a session. The trade is symmetric — both spellings need the enhanced keyboard protocol to be reportable at all, and both degrade to a bare Escape without it, which is why `^]` and `^o` keep working everywhere.
shift+enter is the newline every text field gives you, and the harnesses running in a session bind it that way. Claiming it for "leave the TUI and connect full screen" meant the TUI took a key the agent needed. Full screen moves to ⌥enter, joining the ⌥ family the other chords now use. `f` stays as the fallback for terminals that send no modifier with Enter — and ⌥enter needs one less than shift+enter did: a terminal with Option-as-Meta sends ESC CR, which parses as Alt+Enter without the enhanced keyboard protocol shift+enter required. The binding only ever fired with the tree focused, so this is about which key the TUI reserves rather than what a focused pane forwards; a test now pins shift+enter as untouched from either focus.
Stacking #1069 on #1072 crosses three changes: harness_blurb gains the railway arm. The extracted helper had `_ => "xAI's Grok"` as its catch-all, and with railway now leading HARNESSES that fallback would have labelled Railway's own agent as Grok. Every harness is named, and the catch-all says nothing rather than guessing. The settings card's "create a project" row carries a workspace, since CreateDefaultProject now takes one. It lists one row per workspace — identical wording with a single workspace, named with several — rather than defaulting to the first, which is the bug #1072 set out to fix. The menu footer drops both `^t` (onto the target line, #1072) and `⌥t` (onto the settings card, #1069), leaving `⌥s settings`.
codyde
force-pushed
the
railway/settings-menu
branch
from
August 11, 2026 05:56
04e4ed8 to
2007c25
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
⌥sused to replay the entire first-run wizard, and⌥tcycled the theme blind — two chords on the main screen, one of them a four-step flow, to change a single answer.⌥snow opens a settings card listing every preference fromagent-prefs.jsonwith its current value beside it:←/→(enter also steps forward). The theme repaints the whole screen as it cycles, like the wizard's theme step.excludelist survives; esc is only ever "close" — no dirty state, no confirm.Retired
⌥tis gone — the theme now lives (and persists, which⌥tnever did) on the settings card. Its composed form†falls through as plain text like any unclaimed Option-character.⌥s settingsinstead of⌥t theme · ⌥s setup.Implementation
tui/settings.rsmodel mirroringwizard.rs's shape (Action enum, busy/error, narrative tests); reuseswizard::Outcome/ProjectOptionand newly-extractedproject_options()/harness_blurb().Screen::Settings+Effect::SaveSettings, handled in the event loop next toSaveSetup;Message::ProjectCreatednow routes to whichever of wizard/settings is open.render_panel; the one shared tweak is that a row's dim tag brightens while its row is selected.Appgainsskills_enabled, mirrored from prefs at startup so the card opens showing the saved answer.Testing
cargo test cloud_agent: 256 passed (includes new settings model, key-routing, and draw tests).cargo fmt --check,cargo clippy: clean in touched files.auth_simtests, which also fail on a cleanorigin/mastercheckout in this environment (they pick up the machine's real Railway credentials).Also: ⌥esc replaces shift+esc
Standardizing the TUI's own chords on one modifier family (
⌥f,⌥],⌥s,⌥esc): releasing a focused session is now⌥esc / ^]instead ofshift+esc / ^]. The trade is symmetric — both spellings require the enhanced keyboard protocol to be reportable at all (a plain terminal folds either into a bare Escape meant for the agent, and crossterm parses classicESC ESCas plain Esc), so^]and^oremain the universal fallbacks. One platform note: Alt+Esc is an OS shortcut on Windows, where^]is the way out.Also: ⌥enter replaces shift+enter for full screen
shift+enteris the newline every text field gives you, and the harnesses running in a session bind it that way — so the TUI shouldn't reserve it. "Leave the TUI and connect full screen" moves to⌥enter, joining the same⌥family;fstays as the fallback for terminals that send no modifier with Enter.⌥enteris actually more reportable than the chord it replaces: a terminal with Option-as-Meta sendsESC CR, which crossterm parses as Alt+Enter with no enhanced keyboard protocol needed, whereas shift+enter strictly required it.Note this binding only ever fired with the tree focused — a focused session already forwards everything except
⌥f/⌥]/the release chords — so this is about which key the TUI reserves, not about what the pane passes through. A test now pins shift+enter as unclaimed from either focus.Follow-up worth a separate PR
Freeing the binding is necessary but not sufficient for shift+enter to insert a newline in an embedded pane.
session::encode_keycurrently discards the shift modifier (let _ = shift;) and encodesEnteras a bare\rregardless, so a harness inside the pane sees shift+enter and plain enter as the same byte and submits. Making it a newline means encoding it distinguishably — either kitty CSI-u (\x1b[13;2u, only understood if the harness negotiated that protocol, and literal garbage if it didn't) or translating it toESC CR, the alt+enter newline chord harnesses already accept. That's a change to what bytes reach the agent, so it isn't bundled here. Full-screen sessions are unaffected either way — they bypass the emulator entirely.