feat(hints): route hints + brand header to stderr; drop TTY suppression#109
Merged
Conversation
This was referenced May 18, 2026
The advisory `hint:` lines and `🦖 roar <sub>` brand banner used to self-suppress in non-TTY contexts (CI, redirected output, agent capture). That kept stdout clean for pipelines but blinded agents like Claude Code / Cursor — which capture roar's output programmatically and benefit most from the `next: roar show …` style nudges. Trade the stream choice for the suppression: - **Stream**: hints and the brand header now go to **stderr** via `click.echo(..., err=True)`. stdout stays machine-clean for pipes and redirects without needing a TTY-suppression gate. - **Gate**: `hints_should_print()` drops the `sys.stdout.isatty()` check. Hints fire whenever `hints.enabled = true` (default) and `output.verbosity != "quiet"`. - **Color/emoji**: ANSI styling now keys off `sys.stderr.isatty()`, so captured logs stay plain (no escape sequences in CI output). - **`run_report.next_steps_hint`** drops its parallel `pipe_mode` check — same reasoning. Its presenter already streams to stderr by default; the suppression was the only thing hiding the hint from agents. Behavior change to surface in release notes: CI logs that captured roar output without explicitly setting `hints.enabled = false` will start showing hint lines on stderr. Escape valve is the same as before — `roar config set hints.enabled false` or `output.verbosity = quiet`. Tests: - `test_cli_format.py` (new) — locks in the stream invariant directly: hints go to stderr, brand header goes to stderr, gate honors config-disable and quiet-verbosity, and the TTY check is gone. - `test_init_hints_appear_in_non_tty_on_stderr` — agent visibility regression guard. Asserts hints in `result.stderr` AND absent from `result.stdout`. - `test_init_brand_header_appears_in_non_tty_on_stderr` — same shape for the banner. - `test_next_steps_hint_appears_in_pipe_mode_for_agents_and_ci` (run_report) — repurposed from the old `_silent_in_pipe_mode` test; asserts the line shows up under pipe caps. - Existing query-error test updated to use `result.stdout` (which excludes the now-stderr-bound banner) for its exact-match assertion. 942 unit tests passing, 1 pre-existing skipped. ruff + mypy clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
18726ec to
8f3d554
Compare
TrevorBasinger
approved these changes
May 19, 2026
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.
Summary
The advisory `hint:` lines and the `🦖 roar ` brand header used to self-suppress in non-TTY contexts (CI, redirected output, agent capture). Stdout stayed clean for pipelines, but agents like Claude Code that capture roar output programmatically saw zero of the nudges — exactly the audience that benefits most.
This swaps the suppression for the stream choice:
User-visible change
CI users who captured roar output without explicitly setting `hints.enabled = false` will start seeing hints on stderr. The escape valve hasn't changed:
```
roar config set hints.enabled false
or
roar config set output.verbosity quiet
```
Worth a release-note line.
Why this shape
Test plan
🤖 Generated with Claude Code