feat(cli): first-run onboarding with theme picker and live diff preview#265
Conversation
…iff preview Adds a one-time welcome flow that fires on first interactive launch: banner with version and ASCII monogram, arrow-key theme picker, and a live diff preview pane that re-paints in the highlighted theme so users can compare options before committing. The selection persists to ~/.config/agent-code/config.toml under [ui].theme via the existing secret-preserving atomic write helper, and a sentinel file at ~/.config/agent-code/.onboarding-complete (XDG-aware) ensures we only prompt once. The picker is reachable mid-session through the /theme slash command, which now opens the same component instead of just printing the current value. Adds four accessibility-focused themes alongside the existing palette: dark-colorblind and light-colorblind built on the Okabe-Ito palette (distinguishable for protanopia, deuteranopia, and tritanopia), plus dark-ansi and light-ansi restricted to the 16 standard ANSI codes for terminals without truecolour. Headless paths (--prompt, --serve, --acp, non-TTY stdin/stdout) skip the picker and still drop the sentinel so they never re-prompt. Includes unit tests for sentinel detection, atomic config persistence that preserves unrelated keys, every-named-theme-resolves tripwire, the Okabe-Ito hex coverage assertion, and the ANSI-only palette restriction. Documentation updated in docs/quickstart.mdx and docs/reference/commands.mdx.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 39c285d160
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if cli.prompt.is_none() | ||
| && !cli.dump_system_prompt | ||
| && !cli.serve | ||
| && !cli.acp | ||
| && cli.command.is_none() |
There was a problem hiding this comment.
Mark onboarding complete for non-interactive CLI modes
run_first_run() is only invoked when --prompt, --serve, --acp, and subcommands are all absent, so these non-interactive entrypoints never execute mark_onboarded(). That means a user who first uses agent --prompt ... (or serve/acp) will still be prompted later in an interactive session, contradicting the intended "skip but still record" behavior and the onboarding skip comments.
Useful? React with 👍 / 👎.
| let chosen = | ||
| pick_theme(default_theme_for_picker()).unwrap_or_else(|| DEFAULT_THEME.to_string()); | ||
|
|
||
| if let Err(e) = persist_theme(&chosen) { | ||
| tracing::warn!("could not persist theme '{chosen}': {e}"); |
There was a problem hiding this comment.
Preserve existing theme when user skips first-run picker
When the picker is cancelled (Esc/Ctrl+C), this path substitutes DEFAULT_THEME ("auto") and still persists it, which overwrites any pre-existing [ui].theme value for users who already had a configured theme but no onboarding sentinel yet. Skipping onboarding should not mutate an existing theme setting; otherwise "cancel" acts like an implicit reset.
Useful? React with 👍 / 👎.
Summary
~/.config/agent-code/config.tomlunder[ui].themevia the existing secret-preserving atomic write helper.dark-colorblindandlight-colorblindbuilt on the Okabe-Ito palette (distinguishable for protanopia, deuteranopia, and tritanopia), plusdark-ansiandlight-ansirestricted to the 16 standard ANSI codes for terminals without truecolour./theme, which now opens the picker component instead of printing the current value. A sentinel file at~/.config/agent-code/.onboarding-complete(XDG-aware) ensures the prompt only fires once. Headless paths (--prompt,--serve,--acp, non-TTY stdin/stdout) skip the picker and still drop the sentinel so they never re-prompt.Test plan
cargo check --all-targetscleancargo clippy --all-targets -- -D warningscleancargo fmt --all -- --checkcleancargo test -p agent-codepasses (198 unit tests + integration tests)cargo test -p agent-code-libpasses (excluding pre-existing bwrap sandbox failures unrelated to this change — they require uid-map permissions)mark_onboardedcreates parent dir, atomic config persistence preserves unrelated keys, theme resolver completeness tripwire, Okabe-Ito hex coverage assertion, ANSI-only palette restriction, picker option ↔ theme name consistencyagentwith no sentinel → verify welcome banner, picker, live diff preview, persistence toconfig.toml, sentinel drop, no re-prompt on second launch/thememid-session → verify picker opens, selection updates the live REPL theme and the config fileagent→ verify no picker, sentinel still dropped