colors.js: ANSI styling for Node.js that extends String.prototype unless you import colors/safe
get colors in your node.js console
At a glance
- What is it?
- Marak/colors.js is a small JavaScript package for colouring and styling console output in Node.js. It ships two usage styles, one that adds getters to String.prototype and one that leaves it alone, and its package.json version string is 1.4.44-liberty-2.
- Who is it for?
- Use colors.js for a quick script or CLI where chained getters like 'text'.red.underline are convenient and you control the whole process. Choose colors/safe for libraries and shared code, because the default import changes String.prototype for everything running in the same process.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- Marak/colors.js5,155 ★ · -1
| Repository | 2026-10-21 | 2026-11-07 |
|---|---|---|
| Marak/colors.js | 5.2k | 5.2k |
-1 Stars in the last 17 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The default require adds color getters to every string in the process
colors.js offers two ways to use it, and the first one is the one the author prefers. After var colors = require('colors'), every string gains properties, so 'hello'.green prints green text and 'i like cake and pies'.underline.red prints red underlined text. Getters chain, which is why the README can write underline.red in either order.
That convenience works by extending String.prototype. The README says some people are afraid of that, and answers that anyone writing good code will never have an issue with the first approach. The practical consequence is shared state. Any other module running in the same Node.js process sees the same added properties, and a library that defines a property with one of the same names (red, bold, trap, random) would collide with it.
The install command is a single line:
npm install colorsThe package.json declares engines node >=0.1.90, a main of lib/index.js and a keywords list of ansi, terminal and colors. The version reads 1.4.44-liberty-2, the author is Marak Squires, and DABH is listed as a contributor. The repository has no GitHub releases, so the package.json and the npm package are the version sources.
colors/safe returns functions and leaves String.prototype untouched
The second style is imported from a different path:
var colors = require('colors/safe');
console.log(colors.green('hello')); // outputs green text
console.log(colors.red.underline('i like cake and pies')); // outputs red underlined text
console.log(colors.inverse('inverse the color')); // inverses the color
console.log(colors.rainbow('OMG Rainbows!')); // rainbow
console.log(colors.trap('Run the trap')); // Drops the bassEach style is now a function, and chaining still works through properties such as colors.red.underline. The README says this form will not touch the String native object, and the repository includes a safe.js file with a matching safe.d.ts for TypeScript types, next to index.d.ts for the default form.
For a package that other people install, safe is the lower-risk choice. A consumer of your library never sees string properties they did not ask for. The cost is noisier call sites, since colors.red('text') replaces 'text'.red.
The tests directory mirrors the two forms. The test script runs node tests/basic-test.js and node tests/safe-test.js, so both paths are exercised.
Eight style names and five extras sit beside the sixteen foreground and background colours
The colour list is regular. Text colours are black, red, green, yellow, blue, magenta, cyan, white, gray and grey. Bright text colours add brightRed through brightWhite, with no brightBlack. Backgrounds mirror both lists with a bg prefix, so bgBlack through bgGrey and bgBrightRed through bgBrightWhite.
Styles are reset, bold, dim, italic, underline, inverse, hidden and strikethrough. Whether a given terminal renders italic or strikethrough depends on that terminal, and the README says nothing about support, so test on the terminals your users have.
The extras are rainbow, zebra, america, trap and random. They are decorative. The README comments describe trap as dropping the bass, and it ends with a joke about a secret undocumented style you can summon if you find it. There is no documentation for that style, so nothing here describes it.
If you pick colours from the extras, remember they are not meaningful signals. Reserve red, yellow and green for error, warning and success so that output stays readable when colour is removed.
Colour turns itself off when the terminal cannot show it, and four flags override that
The package detects whether the terminal can use colours and enables or disables accordingly. When colours are disabled, the colour functions do nothing and return the text as given. That is what keeps log files and piped output clean.
The override is a command-line flag or an environment variable:
node myapp.js --no-color
node myapp.js --color=false
node myapp.js --color
node myapp.js --color=true
node myapp.js --color=always
FORCE_COLOR=1 node myapp.jsIn code, colors.enable() and colors.disable() do the same job. A CI system that strips colour can be forced to keep it with --color=always or FORCE_COLOR=1, and a log that ends up in a file can be cleaned with --no-color.
There is a gap to know about. The README does not say which of the flag and the environment variable wins when both are set, so avoid setting them in conflict.
String substitution works the same as normal console.log: console.log(colors.green('Hello %s'), name) prints Hello Marak when name is 'Marak'. The format string is the coloured part, and the substitution values are passed after it.
Themes map your own names like error and warn onto colours, and arrays combine styles
Custom themes let code say what a message is, not what colour it is. The call is colors.setTheme with an object. The README example defines silly as rainbow, input as grey, verbose as cyan, prompt as grey, info as green, data as grey, help as cyan, warn as yellow, debug as blue and error as red. After that, 'this is an error'.error prints red text and 'this is a warning'.warn prints yellow.
With the safe import the same theme becomes colors.error('this is an error'), and a single style can be saved in a variable: var error = colors.red; error('this is red').
Combining styles takes an array. The README shows colors.setTheme({ custom: ['red', 'underline'] }) followed by 'test'.custom.
The README does not say what happens when a theme name matches a built-in style such as bold or red, so the safest habit is to use names that are not colour words. A themes directory ships in the package files, alongside examples, lib, safe.js and the two type definition files.
License fields disagree, and the project asks you to read the roadmap
Two sources describe the license differently. The repository metadata lists it as NOASSERTION, which means no license could be matched automatically, while package.json states MIT. A LICENSE file sits in the root. If you redistribute or audit dependencies, read that file yourself and do not rely on either label.
The maintenance picture is mixed in what it exposes. The last push is dated 2026-10-21 and the repository is not archived. There are no GitHub releases, so activity is visible only through commits and the version string 1.4.44-liberty-2.
The README opens by pointing to a ROADMAP.md for upcoming features and releases, asks for issues as feedback, and says the develop branch carries the latest bleeding-edge updates. So master is not necessarily where new work lands.
Tooling is minimal: ESLint 5.2 with the Google config as dev dependencies, a Travis CI file, and two test files. There are no runtime dependencies listed in package.json, which keeps install size small. For a dependency used by many projects, pin the exact version in your lockfile and review any update before accepting it.
Editorial conclusion
Use colors.js for a quick script or CLI where chained getters like 'text'.red.underline are convenient and you control the whole process. Choose colors/safe for libraries and shared code, because the default import changes String.prototype for everything running in the same process. Before installing, check the exact version in your lockfile, since the package.json here reads 1.4.44-liberty-2 and the repository reports no GitHub releases.
Frequently asked questions
How do I install colors.js?
Run npm install colors, then use var colors = require('colors') or var colors = require('colors/safe').
What is the difference between colors and colors/safe?
The default import extends String.prototype so you can write 'hello'.green. The colors/safe import returns functions such as colors.green('hello') and does not touch the String native object.
How do I turn colors off in colors.js?
Run your script with --no-color or --color=false, or call colors.disable() in code. The package also auto-detects whether the terminal supports colours.
Official sources
Was this useful?