Relationships
#2414 swamp --version emits ANSI escapes when piped, and --no-color does not suppress them
Opened by skunk-ape · 9/23/2026· Shipped 9/23/2026
Description
swamp --version writes ANSI escape sequences even when stdout is not a
terminal, and the --no-color flag does not suppress them. Only the NO_COLOR
environment variable works.
Steps to Reproduce
swamp --version | cat -v
^[[1mswamp^[[22m ^[[94m20260922.011324.0-sha.2e949db5^[[39m
swamp --no-color --version | cat -v
^[[1mswamp^[[22m ^[[94m20260922.011324.0-sha.2e949db5^[[39m
NO_COLOR=1 swamp --version | cat -v
swamp 20260922.011324.0-sha.2e949db5Expected: the first two print a bare version string. Observed: both carry bold and bright-blue escapes.
Cause
src/cli/mod.ts:1653 registers the version flag with Cliffy's .version().
That is a standalone option: Cliffy prints the version and exits during
argument parsing, before .globalAction() runs. All of the colour handling
lives in that global action (src/cli/mod.ts:1675-1684), where --no-color
and NO_COLOR are read and setColorEnabled(false) is called. For
--version, that code never executes.
NO_COLOR works only incidentally, because the colour library reads the
environment variable itself without involving the CLI.
Two distinct defects sit behind the same symptom:
--no-colorhas no effect on any output Cliffy produces before the global action runs. The version flag is the clearest case; help output is worth checking for the same reason.- Colour is never disabled based on stdout being a pipe.
prettyOutputatsrc/cli/mod.ts:1685consultsisStdinTty()for log formatting, but nothing consults whether stdout is a terminal before enabling colour, so captured output keeps its escapes.
Impact
Any caller capturing the version gets escape codes in the value. Found in
scripts/build_attestation.ts, which records the result as
environment.swampVersion in the verification attestation — a document CI
parses and compares. The stored value currently reads:
"\u001b[1mswamp\u001b[22m \u001b[94m20260922.011324.0-sha.2e949db5\u001b[39m"The same applies to shell scripts assigning the version to a variable, and to version strings pasted into bug reports.
Suggested Fix
Decide colour before the Cliffy command is constructed, rather than inside the
global action: scan the raw arguments for the flag and check
Deno.stdout.isTerminal(), then call setColorEnabled(false) early. That
covers every path that exits before the action runs, including help.
Found while generating the verification attestation for swamp-club#1702.
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.