Termic is our library for command-line apps on Node.js. It styles terminal output with colours, themes and progress animations. It has no dependencies and does not extend String.prototype.
Ordinary console tools all look alike: white text and the odd red error. We wanted good-looking output to take one line of code, not a side project.
Install
npm install termicFirst example
const { cli, colors, styler } = require("termic");
cli.println("Hello World");
cli.println(styler.color.red.background.green.italic.underline("Hello World"));Styles chain together and apply in the order you write them. The string itself stays untouched: you get a plain string with escape codes.
Colours
Named colours, RGB and HEX work the same for text and background:
styler.color.red.underline("Hello");
styler.color.hex("#ffffff").bold("Hello");
styler.color.rgb([255, 255, 0])("Hello");
styler.background.red.underline("Hello");
styler.background.hex("#ffffff").underline("Hello");
styler.background.rgb([255, 255, 0]).underline("Hello");The library detects what the terminal supports, including 256 colours and Truecolor.
Modifiers
| Modifier | What it does |
|---|---|
bold | Bold text |
dim | Dimmed text |
italic | Italic, not supported everywhere |
underline | Underline, not supported everywhere |
doubleline | Double underline |
inverse | Swaps text and background colours |
hidden | Invisible text |
crossedout | Strikethrough |
reset | Resets the style |
Themes
A theme is just a variable. Define styles once and use them across your app:
const { cli, styler } = require("termic");
const error = styler.color.red;
const warning = styler.color.orange;
cli.println(error("Error!"));
cli.println(warning("Warning!!!"));Animations and progress
For long tasks there is a renderer that updates several elements on one line. Here is a file copy with an indicator:
const fs = require("node:fs");
const { styler, renderer, animations } = require("termic");
const source = "example.txt";
const target = "example_copy.txt";
const bar = renderer.progress(animations.animation1);
const label = renderer.progress({ frames: ["Copying"] });
const DONE = styler.color.rgb([24, 24, 24]).background.green.bold(" DONE ");
fs.stat(source, (err, stat) => {
let copied = 0;
const stream = fs.createReadStream(source);
stream.on("data", (chunk) => {
copied += chunk.length;
bar.set(((copied / stat.size) * 100).toFixed(2));
});
stream.on("end", () => {
bar.end(DONE);
label.end("Copied");
});
stream.pipe(fs.createWriteStream(target));
});
renderer.render([
[styler.bold("Copying files:")],
[" ", bar, label, animations.simpleDots],
]);Ready-made animations such as animations.dots are included, and your own is a plain object:
const spinner = { interval: 80, frames: ["-", "\\", "|", "/"] };Formatting values
cli.println prints more than strings: numbers, functions, objects, classes, symbols, null and undefined, much like console.log:
const { println } = require("termic").cli;
println({ hello: () => {}, nested: { key: "value" } });
println(Symbol("id"));
println(class Example {});What's next
The project is in development: we are fixing bugs and planning new features. Suggestions and bug reports are welcome on GitHub. Termic is released under the MIT license and is free for any project.