npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

best-cli-loaders

v1.0.2

Published

Beautiful terminal spinners, progress bars, and task runners. Zero dependencies.

Readme

best-cli-loaders

Beautiful terminal spinners, progress bars, and task runners. Zero dependencies.

npm version license

  • Spinners with 80+ built-in animations
  • Progress bars with ETA, speed, and custom formats
  • Multi-progress for concurrent spinners/bars
  • Task lists with nested subtasks, retry, skip, and rollback
  • Full TypeScript support with ESM + CJS dual format
  • Zero dependencies
  • Node.js 18+

Install

npm install best-cli-loaders

Spinner

  ✔ Data loaded successfully!
  ✖ Connection refused
  ⚠ Config file missing, using defaults
  ℹ Running v1.0.0
  ⠹ Installing packages...
import { spinner } from 'best-cli-loaders';

const s = spinner({ text: 'Loading...', spinner: 'dots' });
s.start();
s.text = 'Still loading...';
s.succeed('Done!');    // ✔ Done!
s.fail('Error!');      // ✖ Error!
s.warn('Warning');     // ⚠ Warning
s.info('FYI');         // ℹ FYI

Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | text | string | '' | Display text | | spinner | string \| { frames, interval } | 'dots' | Spinner name or custom definition | | color | ColorName | 'cyan' | Spinner color | | prefixText | string | '' | Text before spinner | | suffixText | string | '' | Text after main text | | indent | number | 0 | Left indent spaces | | stream | WritableStream | stderr | Output stream | | isEnabled | boolean | auto | Override TTY detection |

Available Spinners (80+)

| Name | Frames | Interval | |------|--------|----------| | dots | ⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏ | 80ms | | dots2 | ⣾ ⣽ ⣻ ⢿ ⡿ ⣟ ⣯ ⣷ | 80ms | | dots3 | ⠋ ⠙ ⠚ ⠞ ⠖ ⠦ ⠴ ⠲ ⠳ ⠓ | 80ms | | dots4 | ⠄ ⠆ ⠇ ⠋ ⠙ ⠸ ⠰ ⠠ ⠰ ⠸ ⠙ ⠋ ⠇ ⠆ | 80ms | | dots5 | ⠋ ⠙ ⠚ ⠒ ⠂ ⠂ ⠒ ⠲ ⠴ ⠦ ⠖ ⠒ ⠐ ⠐ ⠒ ⠓ ⠋ | 80ms | | dots6 | ⠁ ⠉ ⠙ ⠚ ⠒ ⠂ ⠂ ⠒ ⠲ ⠴ ⠤ ⠄ … | 80ms | | dots7 | ⠈ ⠉ ⠋ ⠓ ⠒ ⠐ ⠐ ⠒ ⠖ ⠦ ⠤ ⠠ … | 80ms | | dots8 | ⠁ ⠁ ⠉ ⠙ ⠚ ⠒ ⠂ ⠂ ⠒ ⠲ ⠴ ⠤ … | 80ms | | dots9 | ⢹ ⢺ ⢼ ⣸ ⣇ ⡧ ⡗ ⡏ | 80ms | | dots10 | ⢄ ⢂ ⢁ ⡁ ⡈ ⡐ ⡠ | 80ms | | dots11 | ⠁ ⠂ ⠄ ⡀ ⢀ ⠠ ⠐ ⠈ | 100ms | | dots12 | ⢀⠀ ⡀⠀ ⠄⠀ ⢂⠀ ⡂⠀ ⠅⠀ ⢃⠀ ⡃⠀ … | 80ms | | line | - \ \| / | 130ms | | line2 | ⠂ - – — – - | 100ms | | pipe | ┤ ┘ ┴ └ ├ ┌ ┬ ┐ | 100ms | | simpleDots | . .. ... (space) | 400ms | | simpleDotsScrolling | . .. ... .. . (space) | 200ms | | star | ✶ ✸ ✹ ✺ ✹ ✷ | 70ms | | star2 | + x * | 80ms | | flip | _ _ _ - \ ` ' ´ - _ _ _| 70ms | |hamburger|☱ ☲ ☴| 100ms | |growVertical|▁ ▃ ▄ ▅ ▆ ▇ ▆ ▅ ▄ ▃| 120ms | |growHorizontal|▏ ▎ ▍ ▌ ▋ ▊ ▉ ▊ ▋ ▌ ▍ ▎| 120ms | |balloon|(space) . o O @ * (space)| 140ms | |balloon2|. o O ° O o .| 120ms | |noise|▓ ▒ ░| 100ms | |bounce|⠁ ⠂ ⠄ ⠂| 120ms | |boxBounce|▖ ▘ ▝ ▗| 120ms | |boxBounce2|▌ ▀ ▐ ▄| 100ms | |triangle|◢ ◣ ◤ ◥| 50ms | |arc|◜ ◠ ◝ ◞ ◡ ◟| 100ms | |circle|◡ ⊙ ◠| 120ms | |squareCorners|◰ ◳ ◲ ◱| 180ms | |circleQuarters|◴ ◷ ◶ ◵| 120ms | |circleHalves|◐ ◓ ◑ ◒| 50ms | |squish|╫ ╪| 100ms | |toggle|⊶ ⊷| 250ms | |toggle2|▫ ▪| 80ms | |toggle3|□ ■| 120ms | |toggle4|■ □ ▪ ▫| 100ms | |toggle5|▮ ▯| 100ms | |toggle6|ဝ ၁| 300ms | |toggle7|⦾ ⦿| 80ms | |toggle8|◍ ◌| 100ms | |toggle9|◉ ◎| 100ms | |toggle10|㊂ ㊀ ㊁| 100ms | |toggle11|⧇ ⧆| 50ms | |toggle12|☗ ☖| 120ms | |toggle13|= * -| 80ms | |arrow|← ↖ ↑ ↗ → ↘ ↓ ↙| 100ms | |arrow2|▹▹▹▹▹ ▸▹▹▹▹ ▹▸▹▹▹ ▹▹▸▹▹ ▹▹▹▸▹ ▹▹▹▹▸| 80ms | |arrow3|▸▸▸▸▸ ▷▸▸▸▸ ▷▷▸▸▸ ▷▷▷▸▸ ▷▷▷▷▸ ▷▷▷▷▷| 120ms | |bouncingBar|[ ] [= ] [== ] [=== ] [ ===] …| 80ms | |bouncingBall|( ● ) ( ● ) ( ● ) …| 80ms | |smiley|😄 😝| 200ms | |monkey|🙈 🙈 🙉 🙊| 300ms | |hearts|💛 💙 💜 💚 ❤️| 100ms | |clock|🕛 🕐 🕑 🕒 🕓 🕔 🕕 🕖 🕗 🕘 🕙 🕚| 100ms | |earth|🌍 🌎 🌏| 180ms | |moon|🌑 🌒 🌓 🌔 🌕 🌖 🌗 🌘| 80ms | |runner|🚶 🏃| 140ms | |pong|▐⠂ ▌ ▐ ⠂ ▌ ▐ ⡀ ▌ …| 80ms | |shark|▐|\___________▌ ▐|\___________▌ …| 120ms | |dqpb|d q p b| 100ms | |weather|☀️ ☀️ ☀️ 🌤 ⛅️ 🌥 ☁️ 🌧 🌨 ⛈ …| 100ms | |christmas|🌲 🎄| 400ms | |grenade|، ## ´ ‾ ⸌ ⸊ | ⁎ ⁕ …| 80ms | |point|∙∙∙ ●∙∙ ∙●∙ ∙∙● ∙∙∙| 125ms | |layer|- = ≡| 150ms | |betaWave|ρβ________β ρβ______β ρβ____β| 80ms | |aesthetic|▰▱▱▱▱▱▱ ▰▰▱▱▱▱▱ ▰▰▰▱▱▱▱ ▰▰▰▰▱▱▱ …| 80ms | |binary|010010 001100 100101 111010 001011 110001| 80ms | |fistBump|🤜    🤛 → 🤜🤛 → 🤜✨🤛| 80ms | |fingerDance|🤘 🤟 🖖 ✋ 🤚 👆| 160ms | |mindblown|😐 😐 😮 😮 😦 😧 🤯 💥 ✨` | 160ms |


Progress Bar

  ████████████████████████████░░░░░░░░░░░░  73% | ETA: 2.1s | 73/100
  ████████████████████████████████████████  100% | 100/100
  ████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░  30% | ETA: 5.4s | 30/100
import { progress } from 'best-cli-loaders';

const bar = progress({
  total: 100,
  format: '{bar} {percentage}% | ETA: {eta}s | {value}/{total}',
  barSize: 40,
});
bar.start();
bar.update(50);
bar.increment(10);
bar.stop();

Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | total | number | required | Total value | | format | string | '{bar} {percentage}% \| ETA: {eta}s \| {value}/{total}' | Template string | | barSize | number | 40 | Character width of bar | | barCompleteChar | string | '█' | Filled character | | barIncompleteChar | string | '░' | Empty character | | color | ColorName | 'cyan' | Bar color | | hideCursor | boolean | true | Hide cursor during progress | | clearOnComplete | boolean | false | Clear line when done |

Format Tokens

{bar}, {percentage}, {value}, {total}, {eta}, {elapsed}, {speed}


Multi-Progress

  ✔ Package A downloaded
  ⠼ Downloading package B...
  ████████████████████░░░░░░░░░░░░░░░░░░░░ 50%
  ⠧ Compiling assets...

Render multiple spinners or progress bars simultaneously.

import { multi, spinner, progress } from 'best-cli-loaders';

const m = multi();
const s1 = m.add(spinner({ text: 'Task 1' }).start());
const s2 = m.add(spinner({ text: 'Task 2' }).start());
const b1 = m.add(progress({ total: 100, format: 'Download {bar} {percentage}%' }));
b1.start();

// Update individually
s1.succeed('Task 1 done');
b1.update(100);
m.stop();

Task List

  ✔ Install dependencies
    → Installed 42 packages
  ✔ Build project
    ✔ Compile TypeScript
    ✔ Bundle assets
  ⠹ Run tests
    → 14/20 specs passed
  ↓ Optional cleanup
    [skipped]

Run sequential or concurrent tasks with nested subtasks, skip, retry, and rollback.

import { tasks } from 'best-cli-loaders';

await tasks([
  {
    title: 'Install dependencies',
    task: async (ctx, task) => {
      await install();
      task.output = 'Installed 42 packages';
    },
  },
  {
    title: 'Build project',
    task: async (ctx, task) => {
      return task.newListr([
        { title: 'Compile TS', task: async () => { await compile(); } },
        { title: 'Bundle',     task: async () => { await bundle(); } },
      ]);
    },
  },
  {
    title: 'Optional cleanup',
    skip: (ctx) => ctx.skipCleanup ? 'Skipped by user' : false,
    task: async () => { await cleanup(); },
  },
], {
  concurrent: false,
  exitOnError: true,
  ctx: { skipCleanup: false },
});

Task Definition

| Property | Type | Description | |----------|------|-------------| | title | string | Display title | | task | (ctx, task) => Promise<void \| TaskList> | Async function | | skip | (ctx) => string \| boolean | Return truthy to skip | | retry | { times, delay? } | Auto-retry on failure | | enabled | (ctx) => boolean | Conditional enable | | rollback | (ctx) => Promise<void> | Cleanup on failure |

List Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | concurrent | boolean | false | Run tasks in parallel | | exitOnError | boolean | true | Stop on first failure | | ctx | object | {} | Shared context | | renderer | 'default' \| 'verbose' \| 'silent' | 'default' | Output mode |


Colors

  red  green  blue  cyan  yellow  magenta  white  gray

  bold text    dim text    italic text    underline text

  bold(red('Error!'))      bold(green('Success!'))

  rgb(255,128,0)    hex('#ff6699')    hex('#00ccff')

Built-in ANSI color functions with auto-detection.

import { red, green, bold, dim, rgb, hex } from 'best-cli-loaders';

console.log(bold(red('Error!')));
console.log(dim('subtle text'));
console.log(rgb(255, 128, 0)('orange text'));
console.log(hex('#ff6600')('hex color'));

Respects NO_COLOR, FORCE_COLOR, and TERM environment variables.


Themes

import { themes } from 'best-cli-loaders';

console.log(themes.default);   // cyan spinner, ✔/✖/⚠/ℹ icons
console.log(themes.minimal);   // white spinner, ✓/✗/!/i icons
console.log(themes.colorful);  // magenta spinner, emoji icons
console.log(themes.ocean);     // cyan spinner, ocean emoji icons

API Reference

Exports

// Factory functions
spinner(options?)     // → Spinner
progress(options)     // → ProgressBar
multi(options?)       // → MultiProgress
tasks(defs, options?) // → Promise<Ctx>

// Classes
Spinner, ProgressBar, MultiProgress

// Colors & styles
red, green, blue, cyan, magenta, yellow, white, gray
brightRed, brightGreen, brightYellow, brightBlue, brightMagenta, brightCyan, brightWhite
bgRed, bgGreen, bgBlue, bgCyan, bgMagenta, bgYellow, bgWhite, bgBlack
bold, dim, italic, underline, strikethrough, inverse, hidden
rgb, hex, ansi256, bgRgb, bgHex, bgAnsi256
colorByName, getColorLevel, setColorLevel

// Utilities
cursor, StreamWriter, spinners, themes

License

MIT