Make terminals a little more colorful 🌈
[ANSI S]tyles


ANSI color library for use in terminals, CI environments, and Chromium-based browsers.
Ansis is focused on small size and speed while providing rich functionality and handling edge cases.
import { red, cyan, bold, hex, rgb } from 'ansis';
console.log(bold.bgRed` FAIL `);
console.log(red`✖ Error: ${cyan`file.js`} not found`);
console.log(hex('#FF75D1').bold`Pink`);
console.log(rgb(224, 17, 95).italic`Ruby`);
🔗 Shortcuts
✨ Highlights
🎨 Colors - 16 · 256 · Truecolor (hex/rgb) · Named colors (orange, pink ...)
✍️ Syntax - Chained · Template literals · Nested templates
⚙️ Works - ESM · CJS · TS · Node 10+ · Bun · Deno · CI · Chromium browsers
🧠 Smart - Auto color detection · Fallback (truecolor → 256 → 16 → b&w) · NO_COLOR · FORCE_COLOR
📦 Tiny - 5.8 kB · Drop-in replacement for Chalk (44 kB)
Ansis is the fastest when using 2 or more styles, which is the common real-world use case.
| Library |
1 style |
2+ styles |
ansis |
60M ops/sec |
🏆 60M ops/sec |
picocolors |
🏆 109M ops/sec |
58M ops/sec |
chalk |
55M ops/sec |
47M ops/sec |
util.styleText |
0.5M ops/sec |
0.5M ops/sec |
📊 Full benchmarks →
💡 Features
🎨 Colors & Styles
✍️ Syntax
🛠️ Utilities
- Strip ANSI codes:
ansis.strip(red('text')) → plain 'text'
- Hyperlink:
blue.link('https://...', 'Click here'), link('https://...')
- Raw escape codes:
open / close - `${red.open}Error${red.close} file not found`
💻 Environment
⚙️ Compatibility
🎯 You might also like
ansilight - Truecolor syntax highlighter for the terminal with 256 highlight.js themes
flaget - CLI argument parsing. A smaller (5 kB) and faster alternative to yargs-parser (85 kB)
⚖️ Alternatives
chalk, picocolors, colorette, kleur, ansi-colors, kolorist, cli-color, colors-cli, colors.js, tinyrainbow
Since Node.js 22 supports ANSI styling natively via util.styleText(), it is recommended for simple use cases where 16 colors are enough and top performance is not critical.
See styleText() limitations.
✅ Compare features 📊 Benchmarks 🧩 Handling edge cases
Install
npm install ansis
For Node.js 10–12+ use special build npm install ansis@node10
Usage
ESM
import ansis, { red, bold, fg, hex, rgb } from 'ansis';
CJS
const ansis = require('ansis');
const { red, bold, fg, hex, rgb } = require('ansis');
Chained syntax
All colors, styles and functions are chainable. Each color or style can be combined in any order.
import { red, bold, hex } from 'ansis';
red.bold`text`;
hex('#FF75D1').bgCyan.bold`text`;
bold.hex('#FF75D1').bgCyan`text`;
Template literals
Omit parentheses to keep your code clean:
import { red, yellow, green } from 'ansis';
red`Error`;
red`Red ${yellow`Yellow ${green`Green`} Yellow`} Red`;
Escape sequences work exactly as in regular strings:
red`Hello\nWorld`;
red`prev\\next`;
ANSI Styles
dim bold italic underline strikethrough inverse visible hidden reset
ANSI 16 colors
There are 16 basic colors: 8 standard and 8 bright variants.
| Example |
Color |
Background |
Bright Example |
Bright Color |
Bright Background |
 |
black |
bgBlack |
 |
gray |
bgGray |
 |
red |
bgRed |
 |
redBright |
bgRedBright |
 |
green |
bgGreen |
 |
greenBright |
bgGreenBright |
 |
yellow |
bgYellow |
 |
yellowBright |
bgYellowBright |
 |
blue |
bgBlue |
 |
blueBright |
bgBlueBright |
 |
magenta |
bgMagenta |
 |
magentaBright |
bgMagentaBright |
 |
cyan |
bgCyan |
 |
cyanBright |
bgCyanBright |
 |
white |
bgWhite |
 |
whiteBright |
bgWhiteBright |
ANSI 256 colors
- Foreground:
fg(code) - chalk.ansi256(code) equivalent
- Background:
bg(code) - chalk.bgAnsi256(code) equivalent
import { bold, fg, bg } from 'ansis';
fg(96)`Bright Cyan`;
bg(105).fg(96)`Cyan text on magenta background`;
bold.fg(96).underline`Bold underline Bright Cyan`;
256 color codes
See ANSI color codes.
Fallback
If a terminal supports only 16 colors then ANSI 256 colors will be interpolated into base 16 colors.
Truecolor
- Foreground:
hex() rgb()
- Background:
bgHex() bgRgb()
import { bold, hex, rgb, bgHex } from 'ansis';
hex('#E0115F').bold`Bold Ruby`;
rgb(224, 17, 95).italic`Italic Ruby`;
bold.hex('#E0115F').bgHex('#96C')`Ruby text on amethyst background`;
See also named truecolors.
Fallback
Ansis automatically interpolates to the best available color level.
Truecolor → 256 colors → 16 colors → no colors (b&w)

Named truecolors
Register any hex color as a named style via extend().
Background methods bg* are generated automatically.
import { Ansis } from 'ansis';
const myTheme = {
orange: '#ffa500',
pink: '#ffc0cb',
};
const color = new Ansis().extend(myTheme);
color.orange.bold`orange bold`;
color.bgOrange`orange background`;
color.pink`pink foreground`;
color.bgPink`pink background`;
color.red`built-in red still works`;
For extended styles, create a new Ansis instance and call extend() on it.


Example: extend with CSS color names
import { Ansis } from 'ansis';
import colorNames from 'css-color-names';
const color = new Ansis().extend(colorNames);
color.pink('Pink foreground');
color.bgPink('Pink background');
Need help picking a color name? Try the Name that Color tool - paste a hex and get its closest color name.
Hyperlink
OSC 8 hyperlinks are now supported by many terminal emulators.
Use link(url, text?) to create a terminal hyperlink. If text is omitted, the URL itself is used as the visible label.
link(url, text) - link URL + optional link text
link(url) - URL as both target and text
import { blue, link } from 'ansis';
link('https://example.com');
blue.underline.link('https://example.com', 'Click here');
Call link() last in the chain:
blue.underline.link(...);
blue.link(...).underline;
In unsupported terminals text is shown without a link.
Color support
Ansis automatically detects the supported color level:
0 – No color
1 – Basic ANSI (16 colors)
2 – Extended ANSI (256 colors)
3 – Truecolor (16 million colors)
Check the detected level at runtime:
import ansis from 'ansis';
console.log(ansis.level);
console.log(ansis.isSupported());
Create an Ansis instance directly when you need to override color detection:
import { Ansis } from 'ansis';
const noColor = new Ansis(0); // always plain text, no ANSI codes
const basicColor = new Ansis(1); // 16 colors; hex/rgb fall back to nearest
const autoColor = new Ansis(); // auto-detect using globalThis
console.log(noColor.red`foo`); // plain text, no ANSI codes
console.log(basicColor.hex('#FFAB40')`Orange`); // falls back to yellowBright
The constructor also accepts a mock globalThis object to control auto-detection in custom runtimes:
const color = new Ansis({
process: {
env: { FORCE_COLOR: '1' }, // COLORTERM, TERM, CI, NO_COLOR, FORCE_COLOR
argv: ['node', 'app.js'], // --no-color, --color
stdout: { isTTY: false },
platform: 'linux',
},
});
console.log(color.level); // 1
Example: disable colors via custom CLI flag, e.g. --save-to-log
import { Ansis } from 'ansis';
/**
* @param {boolean} noColors Disable colors for non-terminal output.
* @return {Ansis} Default or custom instance
*/
function safeAnsis(noColors) {
return noColors
? new Ansis(0) // disable colors
: new Ansis(); // auto/detect color support
}
// handle a special CLI flag to disable colors
const ansis = safeAnsis(process.argv.includes('--save-to-log'))
Auto-detection
Ansis detects color support from the runtime environment in this order:
-
Chromium browser-like runtimes
- detected first -> truecolor
-
Dumb terminal
-
COLORTERM
truecolor or 24bit -> truecolor
ansi256 -> 256 colors
ansi -> 16 colors
-
CI environment (not TTY)
- GitHub Actions -> truecolor
- other CI environments -> 16 colors
-
Windows
- Windows terminals since Windows 10 build 14931 (released 2016) -> truecolor
-
256-color terminals
- known 256-color terminals -> 256 colors
-
Fallback
- unknown terminals -> 16 colors
Colors are enabled only for a TTY, CI, and the PM2 and Next.js runtimes.
Output to a pipe or a file has no colors, even when COLORTERM is set.
To explicitly enable colors in non-TTY environments, use FORCE_COLOR.
Supported terminals and CI environments
| Terminal |
ANSI 16 colors |
ANSI 256 colors |
True Color |
env. TERM |
env. COLORTERM |
Specifically ENV variables |
| Azure CI |
✅ |
❌ |
❌ |
|
|
TF_BUILD AGENT_NAME |
| GitHub CI |
✅ |
✅ |
✅ |
|
|
CI, GITHUB_ACTIONS |
| GitTea CI |
✅ |
✅ |
✅ |
|
|
CI, GITEA_ACTIONS |
| GitLab CI |
✅ |
❌ |
❌ |
|
|
CI, GITLAB_CI |
| Travis CI |
✅ |
❌ |
❌ |
|
|
TRAVIS |
PM2 not isTTY |
✅[^1] |
✅[^1] |
✅[^1] |
|
|
PM2_HOME pm_id |
Next.js edge runtime |
✅[^1] |
✅[^1] |
✅[^1] |
|
|
NEXT_RUNTIME=‘edge’ NEXT_RUNTIME=‘experimental-edge’ |
JetBrains TeamCity >=2020.1.1 |
✅ |
✅ |
❌ |
|
|
TEAMCITY_VERSION |
| JetBrains IDEA |
✅ |
✅ |
✅ |
xterm-256color |
|
TERMINAL_EMULATOR=‘JetBrains-JediTerm’ |
| VS Code |
✅ |
✅ |
✅ |
xterm-256color |
truecolor |
|
Windows Terminal |
✅ |
✅ |
✅[^2] |
|
|
|
Windows PowerShell |
✅ |
✅ |
✅[^2] |
|
|
|
| macOS Terminal |
✅ |
✅ |
❌ |
xterm-256color |
|
|
| iTerm |
✅ |
✅ |
✅ |
xterm-256color |
truecolor |
|
| Kitty |
✅ |
✅ |
✅ |
xterm-kitty |
truecolor |
|
| KDE Konsole |
✅ |
✅ |
✅ |
xterm-256color |
truecolor |
|
- ^1 Colors supported depends on actual output destination.
TERM=dumb disables colors before PM2 and Next.js detection.
- ^2: The Windows terminal supports true color since Windows 10 revision 14931 (2016-09-21).
See also:
Environment & CLI options
Ansis detects color support automatically, but you can override it with environment variables and CLI flags.
Priority order, from lowest to highest:
- auto-detection
NO_COLOR
- CLI color flags
FORCE_COLOR
Environment variables
NO_COLOR
Set to any non-empty value (1, true) to disable color output (see no-color.org):
NO_COLOR=1 node app.js
FORCE_COLOR
Force or override color support via environment variable (see force-color.org).
| Value |
Behavior |
0 or false |
Disable colors (level 0) |
1 |
Force 16 colors (level 1) |
2 |
Force 256 colors (level 2) |
3 |
Force truecolor (level 3) |
true or any other string |
Detect the level for any output, fallback to 16 colors |
Ansis differs from the original force-color.org rule in a few cases:
-
FORCE_COLOR=0 disables colors.
This matches Node.js,
but the original force-color.org rule enables colors when the value is a non-empty string, regardless of the actual value.
-
FORCE_COLOR=true and an empty value enable colors.
This matches Node.js,
but the original force-color.org rule ignores an empty string.
TERM
TERM identifies the current terminal type and is used during auto-detection.
| Value |
Behavior |
dumb |
Disable colors during auto-detection |
*-256color |
Enable 256 colors when no earlier auto-detection check matched |
| other known terminal names |
Enable 16 colors when the output environment is supported |
Examples of TERM values with 256-color support: screen-256color, xterm-256color, rxvt-256color, putty-256color, mintty-256color, linux-256color, tmux-256color, ansi-256color.
TERM=dumb has higher priority than COLORTERM, CI detection, PM2, Next.js edge runtime, and platform-specific defaults.
To explicitly override auto-detection, use FORCE_COLOR.
COLORTERM
COLORTERM hints at how many colors a terminal can show. It does not turn colors on by itself. Ansis uses it to choose the color level when color output is supported.
| Value |
Level |
ansi |
16 colors (level 1) |
ansi256 |
256 colors (level 2) |
truecolor or 24bit |
Truecolor (level 3) |
Some terminals (iTerm, VS Code, xterm-kitty, KDE Konsole, and others) set COLORTERM=truecolor in addition to a TERM value that only advertises 256-color support, for example TERM=xterm-256color.
CLI flags
Pass --no-color or --color directly to your script:
./app.js # auto-detect
./app.js --no-color # disable colors
./app.js --color # enable colors (useful when piping output)
If multiple CLI color flags are present, the last one wins:
--color --no-color -> --no-color
--no-color --color -> --color
Quick reference
node app.js # auto-detect
node app.js > log.txt # no colors (non-TTY)
NO_COLOR=1 node app.js # force off
FORCE_COLOR=0 node app.js # force off
FORCE_COLOR=1 node app.js > log.txt # force 16 colors
FORCE_COLOR=2 node app.js > log.txt # force 256 colors
FORCE_COLOR=3 node app.js > log.txt # force truecolor
FORCE_COLOR=true node app.js > log.txt # detect the level, fallback to 16 colors
node app.js --no-color # disable via flag
node app.js --color > log.txt # detect the level via flag, fallback to 16 colors
Edge cases
Break style at New Line
Ansis and Chalk add a style break at each new line to correctly display multi-line text.
However, Picocolors doesn’t handle this case.
ansis.bgRed('\n ERROR \n') + ansis.cyan('The file not found!')
chalk.bgRed('\n ERROR \n') + chalk.cyan('The file not found!')
pico.bgRed('\n ERROR \n') + pico.cyan('The file not found!')

Nested template strings
Only Ansis handles this very useful use case.
ansis.red`R ${ansis.green`G ${ansis.blue`B`} G`} R`
chalk.red`R ${chalk.green`G ${chalk.blue`B`} G`} R`
pico.red`R ${pico.green`G ${pico.blue`B`} G`} R`

Handling arguments
Compare how different libraries handle various input arguments in their functions.
ansis.red()
chalk.red()
pico.red()
ansis.red(undefined)
chalk.red(undefined)
pico.red(undefined)
ansis.red(null)
chalk.red(null)
pico.red(null)
ansis.red('')
chalk.red('')
pico.red('')
ansis.reset()
chalk.reset()
pico.reset()
| Library |
c.reset() |
c.red() |
c.red(undefined) |
c.red(null) |
c.red('') |
ansis |
✅\e[0m |
✅'' |
✅'' |
✅'' |
✅'' |
chalk |
❌'' |
✅'' |
❌'undefined' |
❌'null' |
✅'' |
picocolors |
❌undefined |
❌'undefined' |
❌'undefined' |
❌'null' |
❌'ESC' |
tinyrainbow |
❌undefined |
❌'undefined' |
❌'undefined' |
❌'null' |
❌'ESC' |
colorette |
❌'' |
✅'' |
✅'' |
❌'null' |
✅'' |
kleur |
❌[object] |
❌[object] |
❌[object] |
❌'null' |
❌'ESC' |
ansi-colors |
❌'' |
✅'' |
✅'' |
✅'' |
✅'' |
kolorist |
❌undefined |
❌'undefined' |
❌'undefined' |
❌'null' |
❌'ESC' |
colors.js |
❌'' |
✅'' |
❌'undefined' |
❌'null' |
✅'' |
cli-color |
❌- |
❌'ESC' |
❌'ESC' |
❌'ESC' |
❌'ESC' |
colors-cli |
❌- |
❌ Error |
❌'undefined' |
❌'null' |
❌'ESC' |
Legend:
- ✅
'' - Returns an empty string without ANSI escape codes. This is the correct and expected behavior.
- ✅
\e[0m - Returns the reset escape code.
- ❌
'ESC' - Returns an empty string containing ANSI escape codes, e.g., \e[31m\e[39m.
- ❌
'undefined' - Returns the styled string undefined.
- ❌
'null' - Returns the styled string null.
- ❌
[object] - Returns an object of the library instance.
- ❌
- - The feature is not supported.
- ❌
Error - Causes a fatal error.
Other arguments are correctly handled by all libraries:
c.red(0)
c.red(false)
c.red(true)
c.red(5/'1px')
c.red(1/0)
Ansis vs styleText()
Since Node v22, the built-in util.styleText()
has been officially introduced, supporting standard modifiers - the basic 16 colors and styles.
Where it works
Ansis
✅ Node v10+
✅ Chromium-based browsers and Safari
⚠️ Firefox DevTools don’t render ANSI escape sequences
styleText
✅ Node v22+ (native)
❌ No browser support (Node only)
In practical benchmarks, styleText() is 100x slower than Ansis:
ansis.red('text');
styleText('red', 'text');
See full benchmarks.
Color support detection
Ansis
- Auto-detects terminal, TTY, CI and browser color support with automatic fallback
- Supports
NO_COLOR FORCE_COLOR COLORTERM --no-color --color
ansis.level returns the detected color level
styleText
- Auto-detects terminal color support
- Supports only
NO_COLOR FORCE_COLOR NODE_DISABLE_COLORS
Simple styling
import { green } from 'ansis';
import { styleText } from 'node:util';
green`Success!`;
styleText('green', 'Success!');
green.bold`Success!`;
styleText(['green', 'bold'], 'Success!');
Nested styling
import { red, cyan } from 'ansis';
import { styleText } from 'node:util';
red`Error: ${cyan.bold`file.js`} not found!`;
styleText('red', `Error: ${styleText(['cyan', 'bold'], 'file.js')} not found!`);
Truecolor
Ansis: hex() rgb()
styleText: Limited to 16 ANSI colors.
Compatibility
Check the minimum version of your tool required for compatibility with the latest Ansis.
| Tool |
Version |
Compatibility |
Supports |
| Node.js |
v14+ |
✅ Full support |
CJS, ESM |
| Deno |
v2.0+ |
✅ Full support |
CJS, ESM |
| TypeScript/tsc |
v5.0+ |
✅ Full support |
CJS, ESM |
| esbuild |
v0.8+ |
✅ Full support |
CJS, ESM |
| swc |
v1.2+ |
✅ Full support |
CJS, ESM, FAUX |
| tsup |
v4.0+ |
✅ Full support |
CJS, ESM, FAUX |
| tsx |
v3.0+ |
✅ Full support |
CJS, ESM |
| Rollup |
v2.0+ |
✅ Full support |
CJS, ESM |
| Rolldown |
v1.0.0-beta.8+ |
✅ Full support |
CJS, ESM |
| Vite |
v2.5+ |
✅ Full support |
ESM |
| Turbo |
v1.0+ |
✅ Full support |
CJS, ESM |
| Webpack |
v5.0+ |
✅ Full support |
CJS, ESM |
Supports:
- CJS: CommonJS module support.
- ESM: ECMAScript module support.
- FAUX: Fake or non-standard approach to module resolution (seen in swc).
Browser Compatibility for ANSI Codes
| Browser |
Version |
Colors Supported |
| Chrome |
v20+ |
TrueColor (16M) |
| Safari |
v10+ |
TrueColor (16M) |
| Edge |
v12+ |
TrueColor (16M) |
| Opera |
v12+ |
TrueColor (16M) |
| Brave |
v1.0+ |
TrueColor (16M) |
| Vivaldi |
v1.0+ |
TrueColor (16M) |
Firefox doesn’t natively support ANSI codes in the developer console.
⭐️ Star History
If you find this useful, please ⭐️ the repo.

License
ISC
评论