feat: CLI friendliness — warm output, --color, spinners, friendly empty-states - #73
Merged
Conversation
owo-colors/indicatif are full-feature (bin-only) deps; the lean retrieval lib is untouched. ui owns kibble's color/visual language via pure, tested formatters gated on TTY + NO_COLOR + --color. No command output changed yet.
…ted) Review caught: init_color derived one global from stdout's TTY, but warn/err/ hint print to stderr — so 'cmd 2>log' (stdout still TTY) would leak ANSI into log, and '>out' would wrongly suppress interactive error color. Split into COLOR_STDOUT/COLOR_STDERR, each gating on its own stream. + cover fmt_warn.
Route high-traffic command output through ui (index/search/crawl/extract/ ingest/build); add try:-hints; bare 'kibble' greets and points to init; 'no results' nudges. Piped/--json output stays byte-identical (gated).
Review caught two issues in the warmed output: - index/extract messages hardcoded 'data/index'/'data/extracted' even when overridden ([index].dir / --out), so they lied about where files went. Now index reports the resolved cfg.index.dir and extract reports the real --out. - bare 'kibble | cat' leaked one 🦴; move the greeting into ui::greet() which shows the accent only when stdout is colored (piped = emoji-free).
…ract) indicatif spinner on stderr, gated by the same TTY/color decision so it never shows when piped or --json. Purely visual; clears before the final ok line.
Final-review gap: the 'non-negotiable' invariant (piped/--json → no ANSI/ emoji) was only manually verified. Add an integration test that shells the binary with piped stdio and asserts zero ANSI/bone-emoji across init/index/ search/search --json/bare — so a future ui::ok slipping onto a data path fails CI.
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.
Sub-project B of "make kibble adoptable": make the first-run feel delightful. Distribution (A) got people in the door; this makes them stay.
What's in it (6 commits)
uimodule (src/ui.rs, bin-only) — owns kibble's color/visual language with per-stream gating (stdout and stderr decide independently, socmd 2>lognever leaks ANSI into the log). owo-colors,full-gated → the leanretrievallib is untouched.--color=auto/always/neverglobal flag (+NO_COLORrespected).[index].dir, extract the real--out).kibblegreets and points tokibble init;searchno-match nudges.full-gated) on the 5 long ops — stderr, TTY-gated, cleared before the result line.The non-negotiable: machine safety
Piped /
--json/ non-TTY output is byte-identical to before — no color, no emoji. Enforced by per-stream gating and now guarded by an integration test (tests/machine_safety.rs) that shells the binary piped and asserts zero ANSI/emoji.Verification
cargo test: 386 + 3 (ui) + integration incl. the new machine-safety test — all pass.cargo clippy --all-targets -- -D warningsclean. Lean build compiles; owo-colors + indicatif absent from the lean graph.--color=alwaysforces color even piped;--color=never/NO_COLORforce plain.Known follow-up (non-blocking)
caps/asknot-found messages emit lib-side (not bin-side), so they can't route through the bin-onlyuimodule without hoisting emission. Left warm-uniform as a follow-up; they're already plain/correct today.🤖 Generated with Claude Code