Command Line Progress Bar
cli-progress is a robust and highly customizable library for displaying interactive progress bars in Node.js command-line and terminal applications. Currently stable at version 3.12.0, it sees active development with several releases per year, ensuring continuous improvement and bug fixes. Key features include full control over output formatting, support for both single and multiple concurrent progress bars, and the ability to define custom tokens for displaying additional data (payloads). It offers various presets for quick styling and operates without requiring callbacks, being designed as an externally controlled UI widget suitable for both asynchronous and synchronous tasks. Unlike many alternatives, its focus on external control provides flexibility, and it includes features like FPS limiting and TTY/NOTTY mode handling.
Common errors
-
ReferenceError: colors is not defined
cause The `ansi-colors` package, which is used for colorizing the progress bar, has not been installed.fixInstall the `ansi-colors` package: `npm install ansi-colors` or `yarn add ansi-colors`. -
TypeError: cliProgress.SingleBar is not a constructor
cause Attempting to use ES module named imports for `SingleBar` (e.g., `import { SingleBar } from 'cli-progress';`) when 'cli-progress' is a CommonJS module.fixFor ESM, use a default import for the main module object: `import cliProgress from 'cli-progress';` and then access `SingleBar` as a property: `new cliProgress.SingleBar(...)`. For CommonJS, use `const cliProgress = require('cli-progress');`. -
ETA displays as 'INF' or 'NULL'
cause This can happen if the progress bar is initialized with zero total and current values (0/0), if the ETA calculation buffer (`etaBuffer`) is too small for long processes, or if progress updates are too infrequent.fixEnsure `start()` is called with a meaningful total, increase the `etaBuffer` option in the constructor for long-running tasks, and ensure regular updates to the progress value.
Warnings
- breaking Synchronous updates on MultiBar instances could cause unexpected behavior prior to v3.3.1. The fix in v3.3.1 effectively limited synchronous updates to SingleBar instances to prevent these issues.
- gotcha Colorized progress bars (e.g., using `colors.cyan('{bar}')`) will throw a `ReferenceError` if the `ansi-colors` package is not manually installed, as it is an optional peer dependency for styling.
- gotcha The maximum displayed ETA value has been adjusted in different versions (e.g., limited to 100000s in v2.1.0, then to 1e7 seconds in v3.9.0). If the calculated ETA exceeds this limit, it will display as 'INF'.
- gotcha For very long-running processes or processes with infrequent updates, the ETA calculation may incorrectly display 'INF' if the `etaBuffer` option is not sufficiently large to capture enough historical data points.
Install
-
npm install cli-progress -
yarn add cli-progress -
pnpm add cli-progress
Imports
- cliProgress
import { cliProgress } from 'cli-progress';import cliProgress from 'cli-progress';
- SingleBar
import { SingleBar } from 'cli-progress';const cliProgress = require('cli-progress'); const bar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic); - MultiBar
import { MultiBar } from 'cli-progress';const cliProgress = require('cli-progress'); const multiBar = new cliProgress.MultiBar({}, cliProgress.Presets.shades_classic); - Presets
const { Presets } = require('cli-progress');import cliProgress from 'cli-progress'; const theme = cliProgress.Presets.shades_classic;
Quickstart
const cliProgress = require('cli-progress');
const colors = require('ansi-colors'); // Install 'ansi-colors' manually: npm install ansi-colors
// Create new progress bar instance
const b1 = new cliProgress.SingleBar({
format: 'CLI Progress |' + colors.cyan('{bar}') + '| {percentage}% || {value}/{total} Chunks || Speed: {speed}',
barCompleteChar: '\u2588',
barIncompleteChar: '\u2591',
hideCursor: true
});
// Initialize the bar with total 200, start value 0, and a custom payload token 'speed'
b1.start(200, 0, {
speed: "N/A"
});
let value = 0;
const timer = setInterval(() => {
value += 5;
b1.update(value, { speed: `${(Math.random() * 10).toFixed(2)} MB/s` });
if (value >= b1.getTotal()) {
clearInterval(timer);
b1.stop();
console.log('Progress complete!');
}
}, 100);