mrkeyoor.com_
Sat 08 Aug 21:58 UTC
npmCLI & Toolingupdated 08 Aug 2026

cli-color

cli-color is a CommonJS terminal formatting toolkit built around chainable ANSI style functions. It covers the basic and bright 16-color palettes, 256-color xterm codes, backgrounds, bold and other text modes, nested styles, ANSI-aware slicing and stripping, aligned columns, cursor movement, erasing, screen size, simple character art, and an interval-driven throbber. It returns strings and control sequences; your application decides when and where to write them.

Verdict

cli-color remains useful when an existing CLI relies on its unusual combination of styling, tables, slicing, and cursor controls. For a new CLI that only needs color, picocolors, Chalk, or Kleur has a smaller dependency and packaging surface; add separate width and terminal-control tools only when required.

API stability5/5The chainable formatter, named palettes, nested-style repair, xterm functions, raw control sequences, columns, strip, slice, length, art, window size, and throbber subpaths have stayed compatible across the 2.x line. Version 2.0's NO_COLOR behavior was the last declared breaking change in 2019, and the package still supports Node 0.10. This is a mature and predictable legacy API, though consumers should not interpret that stability as modern terminal capability coverage.
Docs4/5The README thoroughly demonstrates basic, combined, predefined, mixed, and nested styles; lists every basic and bright foreground and background; explains xterm fallback; documents cursor movement, erasing, screen size, ANSI-aware slice and length, art, columns, throbber, and NO_COLOR. It loses a point for not explaining the absence of TTY and color-depth detection, the screen-clearing meaning of reset, Unicode display-width errors, untrusted control characters, CommonJS and type constraints, or throbber cleanup on exceptional exits.
Maintenance3/5The latest release and repository push were both on 2024-02-29, with the release updating dependencies and license metadata. Earlier 2.x work removed a vulnerable ansi-regex dependency and fixed cursor-line movement, showing responsible maintenance when needed. The repository is not archived and has only 3 issues and pull requests combined, but the five latest commits are all from the 2024 release chores, no functional release has landed since 2022, and there is no visible move toward types, ESM, Unicode width, or modern capability detection.
Ecosystem3/5The package recorded 3,470,466 downloads in the measured week and has 675 GitHub stars, with an API broad enough to replace several small terminal helpers in legacy applications. It honors NO_COLOR and works across an unusually wide Node range. The current CLI styling ecosystem is centered more heavily on Chalk, picocolors, Kleur, ansi-colors, string-width, and dedicated prompt or table packages, which offer newer module formats, types, color detection, Unicode measurement, or far smaller dependency trees.

Use it if

  • You maintain a CommonJS CLI that already uses cli-color's chainable styles and terminal-control helpers
  • You want styling, ANSI-aware slicing, columns, cursor motion, screen erasing, and a throbber from one established package
  • You still support very old Node runtimes and accept the dependency stack needed to preserve that compatibility
  • Your output is trusted, mostly ASCII text and you explicitly disable control sequences for pipes, logs, and unsupported terminals
Skip it if

Setup reality

npm install cli-color adds a CommonJS package with no native build, peer dependency, credentials, or configuration file. It declares Node >=0.10, which explains its five direct compatibility-oriented dependencies and old module shape. require('cli-color') eagerly exposes styling plus columns, movement, erasing, slicing, length, art, throbber, reset, and window-size helpers; individual subpaths such as cli-color/strip also work because there is no exports map. A style is a callable object, and chaining properties builds a memoized formatter. Multiple arguments are joined with one space. Nested styles are repaired by reopening outer styles after inner closing codes. The only automatic color policy is NO_COLOR, checked each time a formatter runs. There is no TTY detection, so redirected output and CI logs receive ANSI by default unless your program sets NO_COLOR or chooses plain output itself. Conversely, terminals that support color cannot be forced through a documented public option when NO_COLOR is inherited incorrectly. xterm codes are clamped to 0 through 255 and mapped down to basic colors on Windows rather than negotiated with the terminal. Cursor, erase, beep, and reset values are raw control sequences; reset clears the screen and moves the cursor, not merely text styling. Guard interactive operations with process.stdout.isTTY and never send them into machine-readable output. Styling does not sanitize input, so untrusted ESC, BEL, carriage-return, backspace, and other controls can still alter a terminal. ANSI-aware length and slice helpers understand escape codes but not display-cell width or grapheme clusters. The columns helper inherits that limitation. The throbber owns a setInterval and backspaces over one character; call stop on success, failure, and shutdown or the timer can keep the process alive and corrupt later output. Version 2.0.4 was a 2024 dependency and license maintenance release, with no functional release since the 2022 cursor-line fix.

Patterns

Predefine reusable status stylesdefine-status-styles

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

const error = clc.red.bold;
const warn = clc.yellow;
const success = clc.green;

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

Predefining styles reuses the package's memoized formatter objects. Multiple arguments passed to one formatter are joined with spaces.

Nest one style inside anothernest-styles

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

cli-color detects its own ANSI closes and reopens the outer style after the inner formatter, so the final text returns to red.

Honor noninteractive output explicitlydisable-color-for-pipes

if (!process.stdout.isTTY) {
  process.env.NO_COLOR = '1';
}

const line = clc.cyan('build') + ' complete';
process.stdout.write(line + '\n');

cli-color checks NO_COLOR at each formatting call but does not check isTTY itself. Set policy before constructing output that may go to files, pipes, or log collectors.

Use a 256-color foreground and backgrounduse-xterm-color

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

Codes are clamped to 0 through 255. On Windows, the package maps xterm requests to nearby basic colors rather than detecting true 256-color capability.

Strip terminal formatting for a log sinkstrip-ansi

const formatted = clc.red.bold('failed');
const plain = clc.strip(formatted);

fileLogger.write(plain);

strip removes ANSI sequences matched by the package's built-in regex. It does not sanitize every possible terminal control character in arbitrary input.

Measure text without ANSI bytesmeasure-styled-text

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

The result is JavaScript string length after stripping ANSI, not terminal column width. Emoji, CJK text, combining marks, and tabs can occupy a different number of cells.

Slice text while preserving active stylesslice-styled-text

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

slice reopens and closes recognized styles around the selected visible range. Indices are UTF-16 code units, so avoid slicing through emoji or combining sequences.

Render an ANSI-aware tablerender-columns

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

columns supports multiline cells and ignores ANSI bytes for padding, but it still misaligns wide and combining Unicode characters because it uses stripped string length.

Rewrite one interactive status lineupdate-status-line

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

renderStatus('Uploading 40%');

Cursor and erase sequences should go only to an interactive terminal. Add a final newline when the operation finishes so the shell prompt starts cleanly.

Move to a zero-based terminal positionmove-cursor

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, then emits one-based terminal coordinates. The related clc.reset clears the entire screen before moving home.

Remove control characters from untrusted labelssanitize-terminal-input

function terminalText(value) {
  return String(value).replace(
    /[\u0000-\u0008\u000B-\u001F\u007F-\u009F]/gu,
    ''
  );
}

console.log(clc.yellow(terminalText(userSuppliedLabel)));

Styling does not neutralize embedded ESC, BEL, carriage return, or backspace. Choose an allowlist or stricter policy when displaying untrusted data in a terminal.

Stop a throbber on every exit pathrun-throbber

const spinner = clc.throbber(
  (chunk) => process.stdout.write(chunk),
  120,
  clc.cyan
);

spinner.start();
try {
  await runTask();
} finally {
  spinner.stop();
  process.stdout.write('\n');
}

The throbber uses setInterval and backspace. stop clears the timer and erases its current character; without it, the process may stay alive and later output can be overwritten.

Alternatives

PackageRegistryPick it when
picocolorsnpmUse a tiny dependency-free color formatter when cursor control, tables, and ANSI-aware slicing are unnecessary
chalknpmUse the mainstream ESM styling API when modern color-level detection, truecolor, and TypeScript support matter
kleurnpmUse a small chainable formatter with simple enabled or disabled control and no runtime dependencies
ansi-colorsnpmUse a dependency-free CommonJS styling alternative for an older CLI that does not need cli-color's layout helpers