Skip to content

fix(cli): honor NO_COLOR, add --no-color, disable colors when stdout is not a TTY (#1281)#1303

Open
maxmilian wants to merge 1 commit into
colbymchenry:mainfrom
maxmilian:fix/1281-no-color
Open

fix(cli): honor NO_COLOR, add --no-color, disable colors when stdout is not a TTY (#1281)#1303
maxmilian wants to merge 1 commit into
colbymchenry:mainfrom
maxmilian:fix/1281-no-color

Conversation

@maxmilian

Copy link
Copy Markdown
Contributor

Fixes #1281

Problem

Human-format output (query, status, callers, callees, impact, files, …) embedded ANSI color codes unconditionally: piping to a file or another tool captured the escapes, and the standard escape hatch (https://no-color.org) was ignored — NO_COLOR=1 produced byte-identical output. For agent/tooling consumers the escapes are wasted bytes and transcript noise, and the workaround (--json) is ~5× the bytes of the human format.

Fix

All CLI coloring already flows through the colors palette in src/bin/codegraph.ts (plus a mini-palette in src/upgrade/index.ts), so the fix is one shared gate — colorEnabled() in a new src/ui/colors.ts:

  1. --no-color anywhere on the command line disables color — it's stripped from argv before commander parses (same pre-parse intercept pattern as -v), so it also works after subcommands (codegraph query foo --no-color) where commander would otherwise reject it as an unknown option; still registered on the program so it shows in --help
  2. a non-empty NO_COLOR environment variable disables color (an empty NO_COLOR does not, per the spec)
  3. otherwise color renders only when stdout is a TTY — piped/redirected output is escape-free by default

With color disabled the palette collapses to empty strings, so every existing colors.X interpolation and chalk.X() helper becomes a plain-text no-op — no call sites change.

Verification

  • New __tests__/cli-no-color.test.ts (5 tests, end-to-end against the built binary, red before / green after): piped query/status/callers output must be escape-free; NO_COLOR=1 honored; --no-color accepted after a subcommand; empty NO_COLOR does not disable color
  • Full suite: 142 files / 2405 passed (npm run build && npm test)
  • TTY regression check: under a pseudo-TTY (script -q /dev/null …), query output still renders colors; --help lists the new flag
  • CHANGELOG entry under [Unreleased] → Fixes

Notes

  • src/ui/shimmer-worker.ts (index progress animation) still writes ANSI cursor control when piped — that's a rendering concern distinct from command output and untouched here; happy to follow up separately if wanted.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XWwajmLbgJbK6JBCY8nKfk

…is not a TTY (colbymchenry#1281)

Human-format output (query, status, callers, callees, impact, files, …)
embedded ANSI color codes unconditionally: piping to a file or another
tool captured the escapes, and the no-color.org escape hatch was ignored
(NO_COLOR=1 produced byte-identical output).

All CLI coloring already flows through the colors palette in
src/bin/codegraph.ts (and a mini-palette in src/upgrade/index.ts), so
the fix is a single shared gate (src/ui/colors.ts):

- --no-color anywhere on the command line disables color (stripped
  before commander parses, same pre-parse intercept pattern as -v, so
  it also works after subcommands)
- a non-empty NO_COLOR environment variable disables color
- otherwise color is enabled only when stdout is a TTY

With color disabled the palette collapses to empty strings, so every
existing colors.X interpolation and chalk.X() helper becomes a
plain-text no-op — no call sites change.

Exercised end-to-end against the built binary: piped query/status/
callers output must be escape-free, NO_COLOR is honored, --no-color is
accepted after a subcommand, and an empty NO_COLOR does not disable
color (per spec).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWwajmLbgJbK6JBCY8nKfk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NO_COLOR / --no-color not honored — ANSI escapes ship in piped output of all list commands

1 participant