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

zeptospin

v1.0.0

Published

Ultra-lightweight, zero-dependency terminal spinner with built-in cursor safety and CI detection.

Readme

zeptospin ⚡️

npm version npm downloads bundle size license

Ultra-lightweight (~1.5kB minified + gzipped), zero-dependency, type-safe terminal spinner for Node.js.

Highly optimized, pure TypeScript/JavaScript terminal spinner. It behaves similarly to ora and yocto-spinner, but has zero external dependencies (no picocolors, cli-spinners, or chalk), built-in process exit/SIGINT cursor safety, and clean CI log output.


Features

  • 📦 Sub-2kB weight: Extremely small install footprint.
  • 🎨 Built-in ANSI Colors: Tiny color utility built directly in the library.
  • 🚀 Zero Dependencies: Safely import without polluting your node_modules.
  • 🛡️ Cursor & Signal Safety: Listens to exit signals (SIGINT, SIGTERM, uncaughtException) to automatically restore the terminal cursor if aborted mid-run.
  • 📺 CI / Non-TTY Detection: Automatically detects non-interactive terminals or CI environments and falls back to a clean list-like output instead of animating.
  • 🛠️ Fully Typed: Written in TypeScript with standard ESM and CommonJS support.
  • 🎁 Preset Animations: Built-in classic animations like dots, line, pulse, and arrow.
  • 🤝 Promise Wrapper: Easily wrap any async operation to automatically spin and resolve.

Install

npm install zeptospin

Usage

import { zeptospin } from 'zeptospin';

// Create and start the spinner
const spinner = zeptospin('Loading user profile...').start();

// Perform some async task
await delay(1500);

// Resolve with success
spinner.success('Profile loaded successfully!');

All Resolution Types

const spinner = zeptospin('Working...').start();

spinner.success('Done!');  // ✔ Done!
spinner.error('Failed!');  // ✖ Failed!
spinner.warn('Warning!');  // ⚠ Warning!
spinner.info('Info!');     // ℹ Info!

Dynamic Resolution Overrides

You can pass an options object to final state methods to override both the text and the status symbol (e.g. using custom emojis or icons):

spinner.success({ text: 'Deploy complete!', symbol: '🚀' }); // 🚀 Deploy complete!
spinner.error({ text: 'Service crashed!', symbol: '💥' });   // 💥 Service crashed!

Promise Tracking with spinPromise

Track a promise's lifecycle automatically. The spinner starts on invocation and resolves into a checkmark or error symbol when the promise finishes:

import { spinPromise } from 'zeptospin';

// Runs async task, automatically outputting success or error symbols upon completion
const result = await spinPromise(fetchUserData(userId), {
  text: 'Connecting to database...',
  successText: 'User database fetched!',
  errorText: 'Failed to retrieve database!',
  color: 'magenta'
});

Presets and Customization

You can choose from built-in animation presets ('dots' | 'line' | 'pulse' | 'arrow') or specify custom frames:

import { zeptospin } from 'zeptospin';

// Using a built-in 'pulse' preset
const spinner = zeptospin({
  text: 'Compiling project...',
  type: 'pulse', // ░ ▒ ▓ █ ▓ ▒ ░
  color: 'green'
}).start();

// Custom frames and interval
const customSpinner = zeptospin({
  text: 'Downloading assets...',
  frames: ['◐', '◓', '◑', '◒'],
  interval: 150,
  color: 'blue'
}).start();

API

zeptospin(optionsOrText?) or createSpinner(optionsOrText?)

Instantiates and returns a new ZeptoSpin instance.

Options

  • text (string): The text to display next to the spinner.
  • color (string): The color of the spinner frame. Options: 'red' | 'green' | 'yellow' | 'blue' | 'magenta' | 'cyan' | 'white' | 'gray'. Default: 'cyan'.
  • stream (NodeJS.WriteStream): The terminal stream to write to. Default: process.stderr.
  • frames (string[]): Array of frames to animate. Default: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'].
  • interval (number): Frame duration in milliseconds. Default: 80.
  • type (string): Built-in animation preset. Options: 'dots' | 'line' | 'pulse' | 'arrow'.
  • silent (boolean): If true, the spinner will be silent and won't write to the stream.
  • successText (string): Default final success text when using spinPromise.
  • errorText (string): Default final error text when using spinPromise.

Instance Methods

.start(text?)

Starts the spinner animation. If text is passed, it updates the text.

.stop()

Stops the spinner animation and cleans up intervals. If interactive, it clears the line and restores the cursor.

.update(optionsOrText)

Dynamically update any spinner configuration on the fly:

spinner.update('Still working...');
spinner.update({ color: 'green', text: 'Almost there!', type: 'line' });

.success(optionsOrText?)

Stops the spinner, clears the line, prints success symbol with text, and restores the cursor. Accepts string text or { text, symbol } overrides.

.error(optionsOrText?)

Stops the spinner, clears the line, prints error symbol with text, and restores the cursor. Accepts string text or { text, symbol } overrides.

.warn(optionsOrText?)

Stops the spinner, clears the line, prints warning symbol with text, and restores the cursor. Accepts string text or { text, symbol } overrides.

.info(optionsOrText?)

Stops the spinner, clears the line, prints info symbol with text, and restores the cursor. Accepts string text or { text, symbol } overrides.

.stopAndPersist(symbol, text?)

Stops the spinner, clears the line, prints a custom prefix symbol followed by text, and restores the cursor.


Utility Functions

spinPromise(promise, optionsOrText)

Wraps a promise to run a spinner during its execution. Returns the resolved promise value or throws the rejected error.


License

MIT © 2026