CLI tool
sindresorhus/cli-spinners avatar
sindresorhus/cli-spinners

cli-spinners: the product is a JSON file, and the random example shows the wrong spinner

Spinners for use in the terminal

2,943 stars132 forksJavaScriptMIT

At a glance

What is it?
A terminal animation package that ships three files, one of which is the data everyone actually wants, that points you at its author's other module for the interesting part, that keeps its linter in a script named with a leading double slash so the plain test command skips it, and whose random picker example prints the output of a named spinner.
Who is it for?
cli-spinners is worth using directly if you are writing something in any language and want a vetted set of terminal animations, because the data is plain JSON and the module around it is three lines of import. Take it for the frames rather than for the package, and read the interval alongside the frames, since the recommended timing is part of what makes a spinner look right rather than frantic.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 56 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • sindresorhus/cli-spinners2,943 ★ · +8
Star history
Repository2026-09-242026-11-13
sindresorhus/cli-spinners2.9k2.9k

8 Stars in the last 50 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The payload is one JSON file and the module is a wrapper

The readme is unusually direct about what this package is. The list of spinners is just a JSON file, and it can be used wherever. Three lines later it tells you that you probably want to use one of these spinners through another package, which is the same author's terminal spinner module. So the useful artefact is a data file, and the npm package exists to give that data a name, a version and a type declaration. The manifest confirms the shape: only three files are published, the module, its type declaration and the JSON. There is no build step in the shipped output and no runtime dependency list at all, which is why the page can say the data can be used wherever without hedging. For anyone not writing Node, the honest reading is that you are welcome to copy the JSON into your own project and skip the package entirely.

sh
npm install cli-spinners

Two fields per spinner, and timing is part of the design

Every entry has the same two fields, and the readme explains each in a sentence. The interval is the intended time per frame, in milliseconds. The frames are the array of characters to show in sequence. That is the whole schema, and the worked example makes the point better than the prose does: the spinner named for dots consists of ten frames drawn from the braille block, recommended to run at eighty milliseconds per frame. The braille characters matter, because they are what let a single cell cycle through ten shapes without the line jumping, which is why a spinner built from ordinary letters looks ragged and one built from braille does not. The tagline claims seventy or more spinners, and since each is a handful of characters and a number, the whole data file is small enough that reading it end to end is a reasonable way to choose one.

The random example prints a named spinner's output

There are two code examples, and the second one has a copy and paste error that is worth catching before you rely on it. The first shows how to log a named spinner and then displays the shape of the result as a comment. The second shows how to get a random spinner and logs it, but the comment underneath showing the output is character for character the same object as the first example, down to the same ten frames at the same interval. A random pick returning the specific spinner used as the deterministic example above it is unlikely, so the comment is a copy rather than a real result. The shape it shows is still correct, which is why the mistake survives: it teaches the right structure while claiming to demonstrate randomness.

Six ports, and that is the argument for the data-only design

The related section lists a same-language module by the author and then six ports maintained by other people. There is a Swift port, a Python port, a Rust port, a Go port, a Bash port and a Neovim plugin. Six implementations across five languages, none of them a dependency of this package. That list is the practical argument for shipping plain JSON: a port does not have to reimplement an animation loop, a terminal abstraction or a stream writer, because the hard part of a spinner is the frames and the timing, and those are data. It also explains the recommendation to use the author's other module for Node, since the interesting code in that package is the part this one deliberately leaves out.

js
import {randomSpinner} from 'cli-spinners';

console.log(randomSpinner());

The linter is a script whose name comments itself out

The scripts section has two test entries and the trick is in the names. One is called test and runs the test runner followed by a type check of the declaration file. The other is called with two forward slashes in front of the word test, and runs the linter first, then the same two steps. A script whose name begins with a slash is not something anybody can type by accident, so this is a way of keeping the full pipeline available and documented while making sure the command a developer reaches for first does not lint. The reasoning is sound, since linting on every local test run is a common irritation, but the mechanism is unusual enough that a contributor will not find it without reading the manifest. The same section records a script that records a terminal cast of all the spinners, and its title is singular where the package is plural.

An empty centred paragraph where the animation was

Under the tagline there is a centred paragraph element containing three line breaks and nothing else. It is the shape markdown leaves behind when an image is removed from between the tags, and it is a small piece of evidence about how the page is maintained. The preview section then admits that the header animation is outdated and sends you to a live demonstration hosted on a code playground instead. The repository carries both a GIF and an SVG of the same spinner, so the outdated artefact is still committed alongside a vector version of it. None of this affects the package. It does mean the page's most prominent visual is one the author has flagged as wrong, and that the live version lives on a third-party site whose longevity nobody controls.

Node 18.20, no homepage, and a licence file with no extension

The manifest is small enough to read as a description of the project's priorities. The engine requirement is Node 18.20 or above, which is a precise floor rather than a vague recent version. The package is marked as having no side effects, so a bundler can drop it if it decides the import is unused. There is no homepage field, and the repository metadata carries no homepage either, so the only durable addresses are the repository itself and a funding link. The licence file at the root is named with no extension at all, which several automated licence scanners will not find, though the manifest declares the licence as MIT in the usual way. The readme is also in lower case, which is the npm convention and not what a generic tool expects. All three are conventions that work and that a first-time contributor can trip over.

Editorial conclusion

cli-spinners is worth using directly if you are writing something in any language and want a vetted set of terminal animations, because the data is plain JSON and the module around it is three lines of import. Take it for the frames rather than for the package, and read the interval alongside the frames, since the recommended timing is part of what makes a spinner look right rather than frantic. Use the author's spinner module for Node if you want the terminal handling done for you, and copy the JSON if you are not in Node at all. Ignore the random picker example in the readme when you are checking the shape of the output, because it prints a named spinner's result. And pin the package, since it is three files and a data file, and therefore trivial to vendor if it ever stops being published.

Frequently asked questions

What is cli-spinners?

A package of seventy or more spinner definitions for use in the terminal. The list is just a JSON file that can be used anywhere, and the page suggests using a spinner through the author's ora package. Each spinner carries a recommended interval in milliseconds and an array of frames.

How do I install cli-spinners?

With npm install cli-spinners. Only three files are published: the module, its type declaration and the JSON data file, and the package declares no runtime dependencies.

What does randomSpinner() return in cli-spinners?

A random spinner, in the same shape as the named entries: an interval in milliseconds and an array of frames. The readme's example for it displays the same output as its named-spinner example, so treat the comment as illustrative rather than as a real result.

Which Node version does cli-spinners require?

Node 18.20 or above, according to the engine requirement in the package manifest. The package is an ES module and exposes a single entry point carrying both its types and its implementation.

Are there ports of cli-spinners to other languages?

Yes, the page lists ports for Swift, Python, Rust, Go and Bash, plus a Neovim plugin, none of which are dependencies of this package. It also lists the author's own Node module for using a spinner with terminal handling.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. sindresorhus/cli-spinners on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sindresorhus-cli-spinners.svg)](https://hysenlabs.com/projects/sindresorhus-cli-spinners)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/sindresorhus-cli-spinners.svg)](https://hysenlabs.com/projects/sindresorhus-cli-spinners)

Was this useful?