Summary
FORCE_COLOR=0 is treated as "enable colors" by picocolors, when it should mean "disable colors." This is inconsistent with the behavior of chalk and the FORCE_COLOR spec.
Current Behavior
// FORCE_COLOR=0 node test.js
const pc = require('picocolors');
console.log(pc.isColorSupported); // true
console.log(JSON.stringify(pc.green('hello'))); // "\u001b[32mhello\u001b[39m"
Colors are enabled because the detection logic uses !!env.FORCE_COLOR, and !!"0" is true in JavaScript:
let isColorSupported =
!(!!env.NO_COLOR || argv.includes("--no-color")) &&
(!!env.FORCE_COLOR || argv.includes("--color") || ...)
// ^^^^^^^^^^^^^^^^ "0" is truthy
Expected Behavior
FORCE_COLOR=0 should disable colors, matching chalk's behavior:
// chalk with FORCE_COLOR=0
const chalk = require('chalk');
console.log(chalk.level); // 0
console.log(JSON.stringify(chalk.green('hello'))); // "hello" (no ANSI codes)
Per the FORCE_COLOR spec:
FORCE_COLOR=0 → disable colors
FORCE_COLOR=1 → enable basic colors
FORCE_COLOR=2 → enable 256 colors
FORCE_COLOR=3 → enable truecolor
Suggested Fix
Check the value of FORCE_COLOR rather than just its existence:
let isColorSupported =
!(!!env.NO_COLOR || argv.includes("--no-color")) &&
(env.FORCE_COLOR !== '0') &&
((env.FORCE_COLOR && env.FORCE_COLOR !== '') || argv.includes("--color") || p.platform === "win32" || ((p.stdout || {}).isTTY && env.TERM !== "dumb") || !!env.CI)
Impact
This is a behavioral difference from chalk that causes regressions when projects migrate from chalk to picocolors. For example, CI environments and tools like Homebrew set FORCE_COLOR=0 to get parseable plain text output, and this breaks after migration.
Environment
- picocolors v1.1.1
- Node.js v22+
Note: The fix in v1.1.1 (#87) addressed empty strings in FORCE_COLOR/NO_COLOR, but did not address the FORCE_COLOR=0 case.
Summary
FORCE_COLOR=0is treated as "enable colors" by picocolors, when it should mean "disable colors." This is inconsistent with the behavior of chalk and the FORCE_COLOR spec.Current Behavior
Colors are enabled because the detection logic uses
!!env.FORCE_COLOR, and!!"0"istruein JavaScript:Expected Behavior
FORCE_COLOR=0should disable colors, matching chalk's behavior:Per the FORCE_COLOR spec:
FORCE_COLOR=0→ disable colorsFORCE_COLOR=1→ enable basic colorsFORCE_COLOR=2→ enable 256 colorsFORCE_COLOR=3→ enable truecolorSuggested Fix
Check the value of
FORCE_COLORrather than just its existence:Impact
This is a behavioral difference from chalk that causes regressions when projects migrate from chalk to picocolors. For example, CI environments and tools like Homebrew set
FORCE_COLOR=0to get parseable plain text output, and this breaks after migration.Environment
Note: The fix in v1.1.1 (#87) addressed empty strings in
FORCE_COLOR/NO_COLOR, but did not address theFORCE_COLOR=0case.