mrkeyoor.com_
Wed 23 Sept 00:34 UTC
npmCLI & Toolingupdated 22 Sept 2026

cli-color review

cli-color 2.0.4 is a CommonJS toolkit for producing ANSI-styled terminal strings and control sequences. Its callable styles can be chained, nested, and saved for reuse. The same package also strips or slices styled text, lays out columns, moves the cursor, erases terminal regions, reads the window size, and runs a one-character throbber. Version 2.0.4 adds no user-facing feature; its release notes describe dependency and license maintenance. Our browser build measured 51.8 KB minified and 17.5 KB gzipped, which is a lot if a project only wants colored labels.

Verdict

cli-color 2.0.4 installed in 2.8 seconds but left 15 packages and 5 MB in our sandbox, so it earns its place only when a CLI uses its column, slice, or cursor helpers as well as color. For colored labels alone, install a smaller formatter with modern types and terminal detection.

We installed it

Lab card: what happened when we installed cli-colorScreenshot of cli-color documentation
Install✓ · 2.8s15 packages on disk · 5 MB
ImportESM import works · require() works · CommonJS package
Browser17.5 KBgzipped (51.8 KB minified), bundled with esbuild
Typesno TypeScript types found
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does cli-color install cleanly?

Yes. In a fresh container with an empty cache, npm install cli-color finished in 3 seconds, leaving 15 packages and 5 MB on disk. npm audit reported no known vulnerabilities.

How much does cli-color add to a browser bundle?

17.5 KB gzipped (51.8 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does cli-color work with both ESM and CommonJS?

Yes. Both import 'cli-color' and require('cli-color') worked in Node 22 in our run. The package is published as CommonJS.

Does cli-color include TypeScript types?

No type declarations were found in our install, so TypeScript users need their own declarations.

cli-color or picocolors: which should you use?

picocolors: Pick it for dependency-free color formatting when you do not need cursor or table helpers. cli-color 2.0.4 installed in 2.8 seconds but left 15 packages and 5 MB in our sandbox, so it earns its place only when a CLI uses its column, slice, or cursor helpers as well as color.

When should you not use cli-color?

You only need colored strings: our install pulled 15 packages onto disk, while picocolors, kleur, and ansi-colors publish with no runtime dependencies

API stability5/5cli-color 2.x has kept the same callable style objects, palette names, xterm functions, strip and slice utilities, column renderer, cursor controls, and throbber entry point since 2019. The last declared breaking change was 2.0's NO_COLOR behavior. Releases 2.0.2 through 2.0.4 contain a cursor-code fix and maintenance work rather than API redesign, and the package still declares Node >=0.10.
Docs4/5The README gives runnable examples for chained and nested styles, all named colors, xterm codes, reset and erase sequences, relative and absolute cursor motion, window dimensions, ANSI-preserving slices, stripping, columns, character art, and the throbber. It also states the NO_COLOR rule and Windows xterm fallback. It does not warn that TTY detection is the caller's job or explain Unicode display-width errors and timer cleanup.
Maintenance3/5Version 2.0.4 and the repository's latest push both landed on 2024-02-29. That release updated dependencies and license text, while 2.0.2 fixed cursor line movement in 2022. The repository is not archived and currently reports three issues and pull requests combined. There has been no functional release since 2022, and the package still lacks types, an exports map, display-cell measurement, and current terminal capability detection.
Ecosystem3/5npm recorded 3,685,298 downloads for cli-color during the latest measured week, and the GitHub repository has 675 stars. Its broad terminal API explains why older CLIs keep it installed. New projects have better-supported choices for separate jobs: Chalk and picocolors for styling, string-width for Unicode-aware measurement, and dedicated prompt or table packages for interactive output. cli-color's five direct dependencies and absent declarations narrow its fit.

Use it if

  • Your existing CommonJS CLI already depends on cli-color styles or its documented subpath modules
  • One dependency must cover color, ANSI-preserving slices, aligned columns, cursor movement, and a basic throbber
  • You support Node versions older than the engines required by newer terminal styling packages
  • Your application already owns TTY detection and can keep terminal controls out of redirected output
Skip it if

Setup reality

Our install of cli-color 2.0.4 finished in 2.8 seconds and left 15 packages using 5 MB on disk. npm audit reported 0 known vulnerabilities. The package itself is 116 KB unpacked, declares five direct dependencies and no peers, and requires no native build step.

There are no credentials or config files. It is CommonJS without an exports map; both require() and ESM import worked in our Node 22 sandbox. No TypeScript declarations were present. The declared engine is Node >=0.10, and much of the dependency tree supports that old baseline. Version 2.0.4 only refreshed dependencies and license metadata.

Color suppression is narrower than many developers expect. A formatter checks NO_COLOR, but cli-color does not decide whether stdout is a TTY. Pipes, CI logs, and files will receive escape codes unless the calling program disables styling. xterm values are limited to 0 through 255, with a basic-color fallback on Windows documented by the README.

The layout helpers remove ANSI codes before counting, yet they do not calculate terminal cell width. Emoji and wide characters can break columns or slices. Cursor movement, erase, reset, and throbber output should only reach an interactive terminal. The throbber starts an interval and writes backspaces, so every success, error, and shutdown path must call stop().

Patterns

Reuse named status formatters define-status-styles

const clc = require('cli-color');

const failure = clc.red.bold;
const warning = clc.yellow;
const success = clc.green;

console.error(failure('Error:'), 'request failed');
console.warn(warning('Warning:'), 'using defaults');
console.log(success('Done'));

Each chained style is a callable formatter object, so saving it once avoids rebuilding the same chain at each log call.

Put a bright phrase inside an outer color nest-styles

const clc = require('cli-color');

const line = clc.red(
  'failed ' + clc.whiteBright.bold('authentication') + ' check'
);
console.error(line);

cli-color reopens the outer red style after the nested formatter closes, so the trailing word stays red.

Keep ANSI codes out of redirected output disable-color-for-pipes

const clc = require('cli-color');

if (!process.stdout.isTTY) process.env.NO_COLOR = '1';
process.stdout.write(clc.cyan('build complete') + '\n');

NO_COLOR disables styles at formatting time, while cli-color itself does not inspect process.stdout.isTTY.

Apply a 256-color pair use-xterm-color

const clc = require('cli-color');

const badge = clc.xterm(202).bgXterm(236).bold;
console.log(badge(' DEPLOY '));

xterm() and bgXterm() accept values from 0 through 255; the README says Windows receives a nearby basic color when xterm colors are unsupported.

Store a plain copy of styled output strip-ansi

const clc = require('cli-color');
const strip = require('cli-color/strip');

const terminalLine = clc.red.bold('failed');
fileLogger.write(strip(terminalLine));

The strip subpath removes recognized ANSI sequences, but it does not sanitize every control character that untrusted input could contain.

Count characters without style bytes measure-styled-text

const clc = require('cli-color');

const label = clc.bold('Status') + ': ' + clc.green('ready');
console.log(clc.getStrippedLength(label));

getStrippedLength returns JavaScript string length after removing ANSI codes, not the number of display cells occupied by emoji or CJK text.

Cut a styled string without losing its colors slice-styled-text

const clc = require('cli-color');

const value = clc.bold('foo') + 'bar' + clc.red('hello');
process.stdout.write(clc.slice(value, 1, 7) + '\n');

slice closes and reopens known styles around the selected range, but its indices can split surrogate pairs and combining sequences.

Align a small terminal table render-columns

const clc = require('cli-color');

const output = clc.columns(
  [[clc.bold('Package'), clc.bold('Count')], ['alpha', 1200], ['beta', 42]],
  { sep: '  ', columns: [{ align: 'left' }, { align: 'right' }] }
);
process.stdout.write(output);

columns ignores ANSI bytes while padding cells, but wide Unicode characters can still make the rendered columns drift.

Replace one interactive progress line update-status-line

const clc = require('cli-color');

function renderStatus(text) {
  if (!process.stdout.isTTY) return process.stdout.write(text + '\n');
  process.stdout.write(clc.move.lineBegin + clc.erase.lineRight + clc.cyan(text));
}

renderStatus('Uploading 40%');

move.lineBegin and erase.lineRight emit terminal controls, so the non-TTY branch must avoid both sequences.

Write at a fixed terminal coordinate move-cursor

const clc = require('cli-color');

if (process.stdout.isTTY) {
  process.stdout.write(clc.move.to(0, 0));
  process.stdout.write(clc.bold('Top-left'));
}

move.to() accepts zero-based x and y values and converts them to the terminal's one-based coordinate sequence.

Clear the current line before repainting erase-current-line

const clc = require('cli-color');

if (process.stdout.isTTY) {
  process.stdout.write(clc.move.lineBegin + clc.erase.line);
  process.stdout.write(clc.green('ready'));
}

erase.line clears the whole current row; clc.reset is broader and clears the screen before moving the cursor home.

Stop the throbber even when work fails run-throbber

const setupThrobber = require('cli-color/throbber');
const clc = require('cli-color');

const spinner = setupThrobber((chunk) => process.stdout.write(chunk), 120, clc.cyan);
spinner.start();
try {
  await runTask();
} finally {
  spinner.stop();
  process.stdout.write('\n');
}

The throbber owns a setInterval timer and writes backspaces; stop() clears the timer and erases its current character.

Alternatives

PackageRegistryPick it when
picocolorsnpmPick it for dependency-free color formatting when you do not need cursor or table helpers.
chalknpmPick it for a modern ESM styling API with bundled TypeScript declarations and color-level handling.
kleurnpmPick it for a small chainable formatter with explicit enabled or disabled state.
ansi-colorsnpmPick it when a CommonJS CLI needs colors but none of cli-color's terminal layout features.

More cli & tooling guides

chalk · commander · typescript · esbuild · yargs · click · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.