A lightweight, singleton-based CLI multi-spinner library for Node.js. Run multiple spinners simultaneously without visual corruption, with automatic console interception.
- 🔄 Multiple Concurrent Spinners - Run as many spinners as you need
- 🎨 Customizable Colors - 17 color options for spinner customization
- 📝 Console Interception -
console.logand friends work seamlessly without breaking spinners - ✨ Final States - Complete spinners with success, failure, warning, or info icons
- 🧹 Automatic Cleanup - Graceful handling of process exit, SIGINT, and SIGTERM
- 📦 Singleton Architecture - Centralized render management for flicker-free output
npm install @shoru/spindlenpm install @shoru/spindleRequires Node.js 18+
import { spindle } from '@shoru/spindle';
const spinner = spindle('Loading...').start();
// Do some async work
await someAsyncTask();
spinner.succeed('Done!');import { spindle, Spindle } from '@shoru/spindle';
// Using factory function (recommended)
const spinner = spindle('Initial text');
// Using constructor
const spinner = new Spindle('Initial text');Starts the spinner. Optionally updates the text.
spinner.start();
spinner.start('New loading message...');Stops the spinner without displaying a final message.
spinner.stop();Stops with a green checkmark (✔).
spinner.succeed('Task completed successfully');Stops with a red cross (✖).
spinner.fail('Task failed');Stops with a yellow warning sign (⚠).
spinner.warn('Task completed with warnings');Stops with a blue info icon (ℹ).
spinner.info('Additional information');Get or set the spinner text. Both properties are interchangeable.
spinner.text = 'Downloading files...';
console.log(spinner.text); // 'Downloading files...'Get or set the spinner color.
spinner.color = 'magenta';Check if the spinner is currently active.
if (spinner.isSpinning) {
spinner.succeed('Finished');
}| Standard | Bright |
|---|---|
black |
gray/grey |
red |
redBright |
green |
greenBright |
yellow |
yellowBright |
blue |
blueBright |
magenta |
magentaBright |
cyan |
cyanBright |
white |
whiteBright |
Default:
cyan
The RendererManager singleton coordinates all active spinners. You typically don't need to interact with it directly, but it's available for advanced use cases.
import { RendererManager } from '@shoru/spindle';
// Check if any spinners are active
if (RendererManager.isActive()) {
console.log('Spinners are running');
}
// Get count of active spinners
const count = RendererManager.getActiveCount();
// Force reset all spinners (use with caution)
RendererManager.reset(true);Full TypeScript support with exported types:
import {
Spindle,
spindle,
SpinnerColor,
FinalState,
TaskState,
Renderable
} from '@shoru/spindle';
const color: SpinnerColor = 'cyan';
const state: FinalState = 'completed';- Singleton Renderer: A single
RendererManagercoordinates all spinner instances - Console Interception: When spinners are active, console methods are intercepted and buffered
- Unified Rendering: All spinners render to a single output using
log-update - Clean Output: Buffered logs are flushed above the spinner display
- Graceful Cleanup: Process signals trigger proper cleanup to restore console state
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create feature branch
git checkout -b feature/amazing-feature - Commit changes
git commit -m 'Add amazing feature' - Push
git push origin feature/amazing-feature - Open Pull Request
This project is licensed under the MIT License — see the LICENSE file for details.
Made with ❤️ for the Node.js CLI community