piccolore
Piccolore is a tiny, zero-dependency ESM library for adding ANSI colors and text styles to terminal output. It is a temporary fork of picocolors that keeps the same small functional API while targeting ESM and non-Node runtimes. You call helpers such as blue(), bold(), or bgRed() around text, or create an explicitly enabled or disabled color set. It covers the standard 16-color ANSI palette and common modifiers, not RGB colors, terminal layout, prompts, or log formatting.
Piccolore is a clean, tiny option when ESM and non-Node portability are the exact requirements. Most Node projects should install picocolors instead because this package explicitly calls itself a temporary fork and remains pre-1.0.
Use it if
- You publish an ESM-only command-line tool and want a terminal color dependency with no runtime dependencies
- You need the picocolors-style function API in a runtime where importing Node built-ins is undesirable
- You only need standard ANSI colors, bright variants, backgrounds, and basic text modifiers
- You want to force color behavior explicitly in tests or a non-Node runtime with createColors(true) or createColors(false)
- You want a durable default dependency: the repository describes piccolore as a temporary fork of picocolors, and 0.1.3 is still a pre-1.0 release
- Your package must support CommonJS require(): the published package declares type module and exposes only an ESM entry point
- You need 256-color, truecolor, hex, or RGB output: the shipped type definitions expose only fixed ANSI colors and bright variants
- You expect chainable styling such as color.bold.blue(text): piccolore uses plain functions, so styles must be nested
- You only target Node and have no reason to leave picocolors: piccolore identifies itself as a fork, has 3 GitHub stars, and documents no extra formatting features beyond its portability and ESM packaging
Setup reality
Installation is only npm install piccolore, with no peer or runtime dependencies and no native build. The important constraint appears at import time: the package is ESM-only, so require('piccolore') is not a supported entry path. The default export decides whether colors are enabled while the module initializes. It checks NO_COLOR, --no-color, FORCE_COLOR, --color, Windows, stdout.isTTY, TERM, and CI. Set environment variables or command flags before the process starts, not after importing the module. In browser, worker, and other non-Node runtimes, globalThis.process may be absent; the package still loads, but automatic detection generally resolves to no color. Use createColors(true) only when the output consumer understands ANSI escapes. There is no configuration file, color-level negotiation, RGB API, or chainable builder. Compose styles by nesting calls, and remember that disabled helpers still coerce values to strings. The implementation repairs nested occurrences of its own closing codes, which makes same-style nesting safe. Tests should normally use createColors(false) for stable plain-text snapshots or createColors(true) when asserting exact escape sequences. Because the README calls this a temporary fork and the API is still 0.x, pinning an exact version or choosing picocolors directly is sensible for a widely reused package.
Patterns
Color a line of terminal textcolor-basic-text
import pc from 'piccolore';
console.log(pc.blue('Build started'));The default export enables or disables ANSI escapes from the process environment when the module loads.
Combine a color with bold textcombine-color-and-weight
import pc from 'piccolore';
console.log(pc.bold(pc.green('Build passed')));Styles are functions, not chainable properties. Nest calls instead of writing pc.bold.green(...).
Give log levels consistent colorsformat-status-lines
import pc from 'piccolore';
const status = {
info: (text) => pc.cyan(`info ${text}`),
warn: (text) => pc.yellow(`warn ${text}`),
error: (text) => pc.red(`error ${text}`),
};
console.log(status.warn('Cache is stale'));Piccolore only styles strings; timestamps, prefixes, and log routing remain your application's responsibility.
Use foreground and background colorsstyle-background
import pc from 'piccolore';
const badge = pc.bgRed(pc.white(pc.bold(' FAILED ')));
console.error(badge);Only fixed ANSI background colors and bright variants are available; there is no hex or RGB background helper.
Use bright ANSI variantsuse-bright-colors
import pc from 'piccolore';
console.log(pc.cyanBright('new release'));
console.log(pc.bgBlueBright(pc.black(' preview ')));Old or limited terminals may render bright colors like their standard counterparts; the library does not negotiate color depth.
Force colors for a known ANSI consumerforce-colors
import { createColors } from 'piccolore';
const color = createColors(true);
const message = color.magenta(color.bold('always colored'));
process.stdout.write(message + '\n');Forced output contains escape codes even when redirected to a file. Use it only when the destination supports ANSI.
Create a plain-text formatterdisable-colors
import { createColors } from 'piccolore';
const color = createColors(false);
console.log(color.red(color.bold('plain text'))); // plain textDisabled functions still stringify their input, so the same formatting path can serve colored and plain output.
Keep test snapshots free of escape codessnapshot-output
import { createColors } from 'piccolore';
import { expect, test } from 'vitest';
const pc = createColors(false);
test('status message', () => {
expect(pc.green(pc.bold('ok'))).toBe('ok');
});An explicit disabled instance is more predictable than relying on whether the test runner happens to expose a TTY.
Branch on detected color supportcheck-color-support
import pc from 'piccolore';
if (pc.isColorSupported) {
console.log(pc.green('Color is active'));
} else {
console.log('Color is disabled');
}Detection is a boolean, not a color-depth level; it does not distinguish 16-color, 256-color, and truecolor terminals.
Disable colors from the command linerespect-no-color
NO_COLOR=1 node ./cli.mjs
node ./cli.mjs --no-colorBoth forms are read during module initialization. Setting process.env.NO_COLOR after importing piccolore is too late for the default export.
Request colors in redirected outputenable-color-flag
FORCE_COLOR=1 node ./cli.mjs
node ./cli.mjs --colorNO_COLOR and --no-color take precedence in the shipped detection expression, even when a force setting is also present.
Format numbers and booleansformat-non-string-values
import pc from 'piccolore';
console.log('count:', pc.yellow(42));
console.log('cached:', pc.cyan(false));
console.log('missing:', pc.dim(null));The type declarations accept string, number, boolean, null, and undefined; all are converted with String semantics.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| picocolors | npm | You want the established upstream-style package and only need its tiny ANSI helper API |
| chalk | npm | You want chainable styles, richer color levels, and a much larger documentation and user ecosystem |
| kleur | npm | You want a small, fast API with chainable color and modifier calls |
| colorette | npm | You want a compact zero-dependency color library with explicit color enablement controls |