Spinnerยถ
An indeterminate progress spinner for blocking work whose duration is unknown: a subprocess, a network call, a long query. Where click.progressbar needs a known length or an iterable to advance through, Spinner simply signals that something is happening.
It animates on a background thread, so the calling thread stays free to block on the work itself:
from time import sleep
from click_extra import Spinner
with Spinner("Brewing tea"):
sleep(5)
The spinner draws to stderr and is a no-op whenever that stream is not a terminal (a pipe, a file, a CI log), so redirected output and machine-readable formats stay clean. Reassign its label while it runs to reflect the current step, and set a delay so it only appears once an operation is genuinely slow.
Use as a decoratorยถ
A Spinner doubles as a decorator, with or without parentheses. @Spinner wraps a function directly; @Spinner("โฆ") configures the spinner first. Either way the function spins for the duration of every call and returns its result untouched.
@Spinner # Bare form: a default spinner.
def roast(batch):
sleep(5)
return batch
@Spinner("Roasting coffee", timer=True) # Configured form.
def roast_slowly(batch):
sleep(5)
return batch
The one instance is shared across calls, which is right for sequential use; give concurrent callers their own spinner.
Spin directionยถ
Pass reverse=True to rotate the other way. It works with the default frames or any custom sequence:
with Spinner("Chilling lemonade", reverse=True):
sleep(5)
The animation source is just a sequence of strings. click_extra.spinner ships the default Braille SPINNER_FRAMES and a plain ASCII_SPINNER_FRAMES for terminals without Unicode glyphs; pass your own to frames for anything else.
Spinner catalogยถ
SPINNERS is a catalog of around 90 ready-made animations, each a SpinnerPreset bundling the frames and the interval they were tuned for. They are ported from cli-spinners, the de-facto reference collection. Pick one with spinner=:
from click_extra import Spinner, SPINNERS
with Spinner("Brewing tea", spinner=SPINNERS["moon"]):
sleep(5)
The preset sets both the frames and the interval; an explicit frames= or interval= still overrides it. Because the spinner redraws the whole line instead of backspacing, the multi-character animations (bouncingBar, pong, shark, โฆ) render correctly here, unlike in the upstream renderers that had to drop them.
Full inventoryยถ
Every style is browsable from the CLI. On an interactive terminal click-extra spinner animates a live tour of the selection (--all for the whole catalog, --random N for a sample, or --select name1,name2 for specific ones); --table prints the reference table below instead of animating. The Frames column previews each animation, and the Tour column is the dwell time the live tour spends on each: three full cycles, clamped to two-to-three seconds:
$ click-extra --color spinner --all --table
โญโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโฎ
โ Name โ Frames โ Interval โ Tour โ
โโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโค
โ dots โ โ โ โ น โ ธ โ ผ โ ด โ ฆ โ ง โ โ โ 0.08s โ 2.4s โ
โ dots2 โ โฃพ โฃฝ โฃป โขฟ โกฟ โฃ โฃฏ โฃท โ 0.08s โ 2.0s โ
โ dots3 โ โ โ โ โ โ โ ฆ โ ด โ ฒ โ ณ โ โ 0.08s โ 2.4s โ
โ dots4 โ โ โ โ โ โ โ ธ โ ฐ โ โ ฐ โ ธ โ โ โ โ โ 0.08s โ 3.0s โ
โ dots5 โ โ โ โ โ โ โ โ โ ฒ โ ด โ ฆ โ โ โ โ โ โ โ โ 0.08s โ 3.0s โ
โ dots6 โ โ โ โ โ โ โ โ โ โ ฒ โ ด โ ค โ โ โ ค โ ด โ ฒ โ โ โ โ โ โ โ โ โ 0.08s โ 3.0s โ
โ dots7 โ โ โ โ โ โ โ โ โ โ โ ฆ โ ค โ โ โ ค โ ฆ โ โ โ โ โ โ โ โ โ โ 0.08s โ 3.0s โ
โ dots8 โ โ โ โ โ โ โ โ โ โ โ ฒ โ ด โ ค โ โ โ ค โ โ โ ค โ ฆ โ โ โ โ โ โ โ โ โ โฆ (+1) โ 0.08s โ 3.0s โ
โ dots9 โ โขน โขบ โขผ โฃธ โฃ โกง โก โก โ 0.08s โ 2.0s โ
โ dots10 โ โข โข โข โก โก โก โก โ 0.08s โ 2.0s โ
โ dots11 โ โ โ โ โก โข โ โ โ โ 0.1s โ 2.4s โ
โ dots12 โ โขโ โกโ โ โ โขโ โกโ โ
โ โขโ โกโ โ โ โขโ โกโ โ โ โขโ โกโ โ โ โ โ โ โ โ โ โ โ โฆ (+37) โ 0.08s โ 4.5s โ
โ dots13 โ โฃผ โฃน โขป โ ฟ โก โฃ โฃง โฃถ โ 0.08s โ 2.0s โ
โ dots14 โ โ โ โ โ โ โ น โ โขธ โ โฃฐ โขโฃ โฃโฃ โฃโก โฃโ โกโ โ โ โ โ โ 0.08s โ 2.9s โ
โ dots8Bit โ โ โ โ โ โ โ
โ โ โก โก โก โก โก โก
โก โก โ โ โ โ โ โ โ โ โก โก โก โก โฆ (+228) โ 0.08s โ 20.5s โ
โ dotsCircle โ โข โ โ โ โ โ โ ฑ โกฑ โขโกฐ โขโก โขโก โ 0.08s โ 2.0s โ
โ sand โ โ โ โ โก โก โก โก โฃ โฃ โฃ โฃ โฃ โฃ โฃค โฃฅ โฃฆ โฃฎ โฃถ โฃท โฃฟ โกฟ โ ฟ โข โ โก โ โ ซ โข โฆ (+7) โ 0.08s โ 3.0s โ
โ line โ - \ | / โ 0.13s โ 2.0s โ
โ line2 โ โ - โ โ โ - โ 0.1s โ 2.0s โ
โ rollingLine โ / - \ | | \ - / โ 0.08s โ 2.0s โ
โ pipe โ โค โ โด โ โ โ โฌ โ โ 0.1s โ 2.4s โ
โ simpleDots โ . .. ... โ 0.4s โ 3.0s โ
โ simpleDotsScrolling โ . .. ... .. . โ 0.2s โ 3.0s โ
โ star โ โถ โธ โน โบ โน โท โ 0.07s โ 2.0s โ
โ star2 โ + x * โ 0.08s โ 2.0s โ
โ flip โ _ _ _ - ` ` ' ยด - _ _ _ โ 0.07s โ 2.5s โ
โ hamburger โ โฑ โฒ โด โ 0.1s โ 2.0s โ
โ growVertical โ โ โ โ โ
โ โ โ โ
โ โ โ 0.12s โ 3.0s โ
โ growHorizontal โ โ โ โ โ โ โ โ โ โ โ โ โ โ 0.12s โ 3.0s โ
โ balloon โ . o O @ * โ 0.14s โ 2.9s โ
โ balloon2 โ . o O ยฐ O o . โ 0.12s โ 2.5s โ
โ noise โ โ โ โ โ 0.1s โ 2.0s โ
โ bounce โ โ โ โ โ โ 0.12s โ 2.0s โ
โ boxBounce โ โ โ โ โ โ 0.12s โ 2.0s โ
โ boxBounce2 โ โ โ โ โ โ 0.1s โ 2.0s โ
โ triangle โ โข โฃ โค โฅ โ 0.05s โ 2.0s โ
โ binary โ 010010 001100 100101 111010 111101 010111 101011 111000 โฆ (+2) โ 0.08s โ 2.4s โ
โ arc โ โ โ โ โ โก โ โ 0.1s โ 2.0s โ
โ circle โ โก โ โ โ 0.12s โ 2.0s โ
โ squareCorners โ โฐ โณ โฒ โฑ โ 0.18s โ 2.2s โ
โ circleQuarters โ โด โท โถ โต โ 0.12s โ 2.0s โ
โ circleHalves โ โ โ โ โ โ 0.05s โ 2.0s โ
โ squish โ โซ โช โ 0.1s โ 2.0s โ
โ toggle โ โถ โท โ 0.25s โ 2.0s โ
โ toggle2 โ โซ โช โ 0.08s โ 2.0s โ
โ toggle3 โ โก โ โ 0.12s โ 2.0s โ
โ toggle4 โ โ โก โช โซ โ 0.1s โ 2.0s โ
โ toggle5 โ โฎ โฏ โ 0.1s โ 2.0s โ
โ toggle6 โ แ แ โ 0.3s โ 2.0s โ
โ toggle7 โ โฆพ โฆฟ โ 0.08s โ 2.0s โ
โ toggle8 โ โ โ โ 0.1s โ 2.0s โ
โ toggle9 โ โ โ โ 0.1s โ 2.0s โ
โ toggle10 โ ใ ใ ใ โ 0.1s โ 2.0s โ
โ toggle11 โ โง โง โ 0.05s โ 2.0s โ
โ toggle12 โ โ โ โ 0.12s โ 2.0s โ
โ toggle13 โ = * - โ 0.08s โ 2.0s โ
โ arrow โ โ โ โ โ โ โ โ โ โ 0.1s โ 2.4s โ
โ arrow2 โ โฌ โ โก โ โฌ โ โฌ
โ โ 0.08s โ 2.0s โ
โ arrow3 โ โนโนโนโนโน โธโนโนโนโน โนโธโนโนโน โนโนโธโนโน โนโนโนโธโน โนโนโนโนโธ โ 0.12s โ 2.2s โ
โ bouncingBar โ [ ] [= ] [== ] [=== ] [====] [ ===] [ ==] [ =] โฆ (+8) โ 0.08s โ 3.0s โ
โ bouncingBall โ ( โ ) ( โ ) ( โ ) ( โ ) ( โ) ( โ ) โฆ (+4) โ 0.08s โ 2.4s โ
โ smiley โ ๐ ๐ โ 0.2s โ 2.0s โ
โ monkey โ ๐ ๐ ๐ ๐ โ 0.3s โ 3.0s โ
โ hearts โ ๐ ๐ ๐ ๐ ๐ โ 0.1s โ 2.0s โ
โ clock โ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ โ 0.1s โ 3.0s โ
โ earth โ ๐ ๐ ๐ โ 0.18s โ 2.0s โ
โ material โ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โฆ (+90) โ 0.017s โ 3.0s โ
โ moon โ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ โ 0.08s โ 2.0s โ
โ runner โ ๐ถ ๐ โ 0.14s โ 2.0s โ
โ pong โ โโ โ โโ โ โ โ โ โ โ โ โ โก โ โฆ (+25) โ 0.08s โ 3.0s โ
โ shark โ โ|\____________โ โ_|\___________โ โ__|\__________โ โฆ (+23) โ 0.12s โ 3.1s โ
โ dqpb โ d q p b โ 0.1s โ 2.0s โ
โ weather โ โ โ โ ๐ค โ
๐ฅ โ ๐ง ๐จ ๐ง ๐จ ๐ง ๐จ โ ๐จ ๐ง ๐จ โ โฆ (+5) โ 0.1s โ 3.0s โ
โ christmas โ ๐ฒ ๐ โ 0.4s โ 2.4s โ
โ grenade โ ุ โฒ ยด โพ โธ โธ | โ โ เทด โ โ 0.08s โ 3.0s โ
โ point โ โโโ โโโ โโโ โโโ โโโ โ 0.125s โ 2.0s โ
โ layer โ - = โก โ 0.15s โ 2.0s โ
โ betaWave โ ฯฮฒฮฒฮฒฮฒฮฒฮฒ ฮฒฯฮฒฮฒฮฒฮฒฮฒ ฮฒฮฒฯฮฒฮฒฮฒฮฒ ฮฒฮฒฮฒฯฮฒฮฒฮฒ ฮฒฮฒฮฒฮฒฯฮฒฮฒ ฮฒฮฒฮฒฮฒฮฒฯฮฒ ฮฒฮฒฮฒฮฒฮฒฮฒฯ โ 0.08s โ 2.0s โ
โ fingerDance โ ๐ค ๐ค ๐ โ ๐ค ๐ โ 0.16s โ 2.9s โ
โ fistBump โ ๐คใใใใ๐ค ๐คใใใใ๐ค ๐คใใใใ๐ค ใ๐คใใ๐คใ โฆ (+3) โ 0.08s โ 2.0s โ
โ soccerHeader โ ๐งโฝ ๐ง ๐ง โฝ ๐ง ๐ง โฝ ๐ง โฆ (+9) โ 0.08s โ 2.9s โ
โ mindblown โ ๐ ๐ ๐ฎ ๐ฎ ๐ฆ ๐ฆ ๐ง ๐ง ๐คฏ ๐ฅ โจ โ 0.16s โ 3.0s โ
โ speaker โ ๐ ๐ ๐ ๐ โ 0.16s โ 2.0s โ
โ orangePulse โ ๐ธ ๐ถ ๐ ๐ ๐ถ โ 0.1s โ 2.0s โ
โ bluePulse โ ๐น ๐ท ๐ต ๐ต ๐ท โ 0.1s โ 2.0s โ
โ orangeBluePulse โ ๐ธ ๐ถ ๐ ๐ ๐ถ ๐น ๐ท ๐ต ๐ต ๐ท โ 0.1s โ 3.0s โ
โ timeTravel โ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ โ 0.1s โ 3.0s โ
โ aesthetic โ โฐโฑโฑโฑโฑโฑโฑ โฐโฐโฑโฑโฑโฑโฑ โฐโฐโฐโฑโฑโฑโฑ โฐโฐโฐโฐโฑโฑโฑ โฐโฐโฐโฐโฐโฑโฑ โฐโฐโฐโฐโฐโฐโฑ โฐโฐโฐโฐโฐโฐโฐ โฆ (+1) โ 0.08s โ 2.0s โ
โ dwarfFortress โ โโโโโโยฃยฃยฃ โบโโโโโโยฃยฃยฃ โบโโโโโโยฃยฃยฃ โบโโโโโโยฃยฃยฃ โฆ (+129) โ 0.08s โ 10.6s โ
โ fish โ ~~~~~~~~~~~~~~~~~~~~ > ~~~~~~~~~~~~~~~~~~ โฆ (+25) โ 0.08s โ 3.0s โ
โฐโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโฏ
Bell on completionยถ
Set beep=True to ring the terminal bell once when the spinner stops, handy for a long task you walk away from. It rings only when the spinner was actually shown, so redirected or non-interactive runs stay quiet:
with Spinner("Baking bread", beep=True):
sleep(5)
Printing while spinningยถ
Because the spinner draws to stderr, results written to stdout never collide with the animation. To emit a line on the same stream as the spinner, use echo(): it erases the current frame, prints the message above the spinner, and lets the animation carry on underneath. A bare print would instead leave a frame glyph stranded mid-line.
with Spinner("Picking apples") as spinner:
for basket in range(3):
sleep(2)
spinner.echo(f"Filled basket {basket}")
Parallel workยถ
A Spinner drives a single line, so a pool of concurrent tasks does not need one apiece: one spinner can report on them all. The simplest way is to let the main thread update it as the tasks finish, through concurrent.futures.as_completed.
Update the label for a running count:
from concurrent.futures import ThreadPoolExecutor, as_completed
from time import sleep
from click_extra import Spinner
cities = ["Cairo", "Lima", "Oslo", "Paris", "Tokyo"]
def fetch(city):
sleep(1) # The blocking call: a download, a query, a subprocess.
return city
with Spinner(f"Fetching forecasts (0/{len(cities)})") as spinner:
with ThreadPoolExecutor() as pool:
futures = [pool.submit(fetch, city) for city in cities]
for done, _ in enumerate(as_completed(futures), 1):
spinner.label = f"Fetching forecasts ({done}/{len(cities)})"
Or echo() a line as each task lands, leaving a trail of finished work that scrolls up while the spinner keeps turning below it:
with Spinner("Fetching forecasts") as spinner:
with ThreadPoolExecutor() as pool:
futures = {pool.submit(fetch, city): city for city in cities}
for future in as_completed(futures):
spinner.echo(f"โ {futures[future]}")
Both label and echo() are safe to touch while the animation runs, so a worker thread can stream its own progress mid-task rather than only reporting on completion. A genuine spinner per task, several rotating at once on their own lines, is a separate capability: it needs a coordinated multi-line region, which Spinner does not attempt.
Styling and colorยถ
The spinnerโs glyph, label and timer are painted with a Style instance: the very type Click Extraโs theme system is built on. The simplest customization is a foreground color:
from click_extra import Spinner, Style
with Spinner("Counting sheep", style=Style(fg="cyan")):
sleep(5)
A Style carries far more than a foreground color. Add a background with bg, and text attributes like bold, dim, italic, underline, blink or reverse, and combine them freely:
with Spinner("Counting sheep", style=Style(fg="bright_white", bg="blue", bold=True)):
sleep(5)
Colors accept any form click.style understands: ANSI names ("red", "bright_magenta"), 256-color indexes, #rrggbb hex strings, or (r, g, b) tuples. A Style carrying an unrenderable color or attribute is rejected with a ValueError at construction, so a typo fails fast instead of silently dying on the animation thread.
Color follows the terminal, not the spinnerยถ
Color is decoupled from the animation: under --no-color or NO_COLOR the spinner keeps spinning, just in plain text (the --progress section below explains the rationale). Inside a Click Extra CLI the color follows the reconciled --color/--no-color flag; standalone it honors FORCE_COLOR, then NO_COLOR, then falls back to whether the terminal is interactive.
The same Style type colors the ok() / fail() finishers: they default to the themeโs success/error style and take a style= override, covered in the Success and failure section below.
Success and failureยถ
Stopping the spinner (or leaving its context) erases it. To leave a result on screen instead, finish with ok() or fail(): each replaces the final frame with a kept line. The marker defaults to the themeโs success/error glyph (โ / โ), painted with the active themeโs success/error Style, so a finished spinner matches the rest of a themed CLI.
with Spinner("Baking bread") as spinner:
sleep(5)
spinner.ok() # โ Baking bread
Pass your own marker (spinner.ok("done")) or override the paint with a Style (spinner.fail(style=Style(fg="bright_red"))). Color is stripped under --no-color/NO_COLOR; off a terminal the line is still written, so the outcome is recorded in logs and pipes.
Because the finisher is written even when the spinner never appeared (a call shorter than the delay, a pipe, a non-terminal), gate it on the shown property when you only want it after a spinner the reader actually saw:
with Spinner("Baking bread") as spinner:
bake()
if spinner.shown:
spinner.ok()
Elapsed timeยถ
Set timer=True to append the running wall-clock time to the spinner, and to any ok()/fail() line:
with Spinner("Simmering stock", timer=True) as spinner:
sleep(5)
spinner.ok() # โ Simmering stock (5.0s)
The default format is compact: 2.3s, then 1:05, then 1:02:03. For anything else, pass a callable instead of True: it receives the elapsed seconds and returns the string to show:
with Spinner("Simmering stock", timer=lambda s: f"{s / 60:.0f} min") as spinner:
sleep(5)
spinner.ok() # โ Simmering stock (0 min)
Read the elapsed time any moment from the elapsed_time property, which freezes once the spinner stops.
The --progress optionยถ
click_extra.command and click_extra.group add a --progress/--no-progress flag to every CLI by default. It resolves to a single boolean at ctx.meta["click_extra.progress"], which a command reads to decide whether to start a Spinner:
from click_extra import Spinner, command, pass_context
from click_extra.context import PROGRESS
@command
@pass_context
def harvest(ctx):
"""Pick apples, showing a spinner when progress is enabled."""
with Spinner("Picking apples", enabled=None if ctx.meta[PROGRESS] else False):
sleep(5)
Spinner display is decoupled from color. A spinner is an interactivity concern, not a color one: it is driven by cursor-control codes, which the NO_COLOR standard explicitly does not govern. So --no-color and NO_COLOR strip the spinnerโs color but keep it spinning, the same way cargo, npm, pip, Rich, indicatif and ora gate progress on the terminal rather than on color.
The resolved value is False only for non-interactive output (a pipe, a TERM=dumb terminal, or CI: handled by the widgetโs own check when you pass enabled=None) and for explicit intent (--no-progress or --accessible, the latter so a screen reader is never handed a spinning glyph).
Progress barsยถ
The same --progress/--no-progress flag also gates Clickโs determinate progress bar. click_extra.progressbar is a drop-in for click.progressbar: it reads the resolved flag and hides the bar when progress is off, so a single --no-progress (or --accessible) silences both the indeterminate spinner and the determinate bar.
from click_extra import command, progressbar
@command
def harvest():
"""Pick apples behind a determinate progress bar."""
with progressbar((1, 2, 3), label="Picking apples") as bar:
for _ in bar:
pass
$ harvest
Picking apples
$ harvest --no-progress
The hidden argument stays authoritative: pass an explicit hidden=True or hidden=False to force the bar regardless of the flag, mirroring how an explicit color= overrides ctx.color on click.echo. Color is handled upstream too, since Click renders the bar through click.echo: --no-color and NO_COLOR strip its ANSI without any extra wiring.
click_extra.spinner APIยถ
classDiagram
ExtraOption <|-- ProgressOption
tuple <|-- SpinnerPreset
An indeterminate terminal spinner for long-running, blocking work.
Click ships click.progressbar(), but it is determinate: it needs a known
length or an iterable to advance through. Some work has no measurable progress:
a blocking subprocess, a network round-trip, a query whose duration is unknown.
For those, the only honest feedback is โsomething is happeningโ.
Spinner fills that gap. It animates a small frame sequence on a daemon
thread, so the caller can stay blocked in a single call (communicate(),
urlopen(), โฆ) while the spinner keeps turning:
from time import sleep
from click_extra import Spinner
with Spinner("Brewing tea"):
sleep(5) # A blocking call with no measurable progress.
Caution
The spinner draws with carriage returns and ANSI control codes, so it is a
no-op whenever its output stream is not a TTY (a pipe, a file, a captured
test buffer, a CI log), unless enabled is forced. This keeps redirected
output and machine-readable formats clean.
Note
On Windows, Spinner.start() enables the consoleโs virtual-terminal
processing so the ANSI control codes animate in place rather than print
literally (โ โ[0m โฆ โ[K). Modern terminals (Windows Terminal, recent
conhost) already have it on; this just covers older consoles.
- class click_extra.spinner.Spinner(label='', *, frames=None, spinner=None, reverse=False, interval=None, delay=0.0, style=None, timer=False, stream=None, enabled=None, hide_cursor=True, beep=False)[source]
Bases:
objectA thread-animated, indeterminate progress spinner usable as a context manager.
The animation runs on a background daemon thread, leaving the calling thread free to block on the actual work. Entering the context (or calling
start()) begins the animation; leaving it (or callingstop()) halts the thread and erases the spinner line so it never lingers above the next output.Note
A single
Spinnerinstance drives one animation at a time. mpm and similar tools run their subprocesses sequentially, so one shared instance whoselabelis reassigned between steps is enough; for concurrent work, use one instance per thread.Configure (but do not start) the spinner.
- Parameters:
label (
str|Callable[...,Any]) โ text shown after the spinner glyph. As a special case, a bare@Spinnerdecorator passes the wrapped function here instead; it is detected and the label defaults to empty.frames (
Sequence[str] |None) โ the animation frames, cycled in order. Defaults toSPINNER_FRAMES, or thespinnerpresetโs frames when given.spinner (
SpinnerPreset|None) โ aSpinnerPresetfrom theSPINNERScatalog (spinner=SPINNERS["moon"]), supplying both frames and a tuned interval. An explicitframesorintervalstill overrides it.reverse (
bool) โ cycle the frames backwards, spinning the animation the other way. Set it when the rotation runs counter to what you expect; it composes with any customframes.interval (
float|None) โ seconds between two frames. Defaults to0.1, or thespinnerpresetโs interval when given.delay (
float) โ seconds to wait before drawing the first frame. A non-zero delay keeps the spinner silent for calls that finish quickly, so it only surfaces once an operation is genuinely slow.style (
Style|None) โ aStyleapplied to the spinner glyph, label and timer (Style(fg="cyan", bold=True)). Color is decoupled from animation:--no-color/NO_COLORstrip it while the spinner keeps spinning (seeProgressOption).timer (
bool|Callable[[float],str]) โ append the elapsed wall-clock time to the spinner, and to any finalok()/fail()line.Trueuses the default compact format (2.3s,1:05, then1:02:03). Pass a callable(seconds: float) -> strto format the duration yourself, liketimer=lambda s: f"{s / 60:.0f}m"for whole minutes.stream (
IO[str] |None) โ where to draw; defaults tosys.stderrso the spinner never mixes intostdoutdata.enabled (
bool|None) โ force the spinner on or off.None(the default) auto-detects, animating only whenstreamis a TTY.hide_cursor (
bool) โ hide the text cursor while spinning and restore it on stop.beep (
bool) โ ring the terminal bell once when the spinner stops. It fires only when the spinner was active, so a disabled or redirected spinner stays silent.
- Raises:
ValueError โ if
stylecarries a color or attribute that cannot be rendered.
- label: str
Text drawn after the spinner glyph.
Reassign it at any time while the spinner runs to reflect the current step; the animation thread reads it afresh on every frame.
- property elapsed_time: float
Seconds elapsed since
start(), frozen oncestop()is called.Returns
0.0before the spinner has started.
- property shown: bool
Whether the spinner has drawn at least one frame to its stream.
Trueonly once an animation frame was actually rendered. It staysFalsefor a disabled spinner (off a TTY, on aTERM=dumbterminal, or withenabled=False) and for a call that finishes withindelay, before the first frame. Reset bystart().Use it to gate output that should mirror the spinnerโs visibility.
ok()andfail()write their line unconditionally, so an outcome is still recorded in a pipe or log; guard them withshownwhen you only want the finisher on screen after a spinner the user actually saw:with Spinner("Baking bread") as spinner: bake() if spinner.shown: spinner.ok()
- start()[source]
Begin animating on a background thread, unless the spinner is disabled.
A disabled spinner (non-TTY stream, or
enabled=False) returns at once without spawning a thread or emitting anything (but still records the start time, so a laterok()/fail()can report a duration).- Return type:
- stop()[source]
Halt the animation and erase the spinner line.
Idempotent and safe to call when the spinner never started. Restores the cursor and clears the line only if the animation actually drew to the terminal.
- Return type:
- echo(message='')[source]
Print
messageon its own line above the running spinner.Clickโs
click.progressbar()and a bareprintboth fight the animation: a frame drawn between the cursor returns and the text mangles the line.echo()takes the same draw lock as the animation thread, erases the in-progress frame, writesmessagefollowed by a newline, and lets the next tick redraw the spinner underneath. It is safe to call from another thread while the spinner runs.Output goes to the spinnerโs own
stream(stderrby default), so results written tostdoutnever need it. When the spinner is not animating (disabled, or a non-TTY stream), it degrades to a plain write ofmessagewith no control codes.- Return type:
- ok(symbol=None, *, style=None)[source]
Stop the spinner and leave a persistent success line on screen.
Where
stop()erases the spinner,ok()replaces the final frame withsymbolfollowed by the current label (and the elapsed time whentimeris set), then keeps that line.symboldefaults to the themed success glyphOK_GLYPH(โ), painted with the active themeโssuccessslot unlessstyleoverrides it. Color is stripped under--no-color/NO_COLOR; the glyph stays.- Return type:
- class click_extra.spinner.ProgressOption(param_decls=None, is_flag=True, default=True, is_eager=True, expose_value=False, help='Show progress indicators during long operations. Disabled for non-interactive output (pipes, dumb terminals, CI) and by --accessible.', **kwargs)[source]
Bases:
ExtraOptionA pre-configured
--progress/--no-progressflag gating spinner display.Resolves to a single boolean published at
ctx.meta[click_extra.context.PROGRESS], which a CLI reads to decide whether to start aSpinner. The default isTrue;--accessiblelowers it toFalse(viadefault_map) so a screen reader is never handed a spinning glyph.Note
Spinner display is intentionally decoupled from color, even though both emit ANSI. A spinner is an interactivity concern, not a color one: it is built from cursor-control codes (hide-cursor, carriage return, clear-line), which the NO_COLOR standard explicitly does not govern โ it โonly signals the userโs intention regarding adding ANSI color to text outputโ. So
--no-color/NO_COLORstrip the spinnerโs colors but never hide it.This matches how the wider ecosystem treats the two axes as orthogonal: cargo, npm, pip, Rich, indicatif and ora all gate progress on the terminal (and a dedicated
--progress/--quietknob), whileNO_COLORonly affects color. Rich usesTERM=dumbโ notNO_COLORโ as the signal to drop cursor-moving features like progress bars.The spinner is therefore silenced by two things only, neither of them color:
non-interactive output โ a pipe, file, CI log, or
TERM=dumbterminal that cannot move the cursor (seeSpinner._resolve_enabled);explicit intent โ
--no-progressor--accessible.
This option is eager. It no longer reads
ctx.color, so its position relative toColorOptionis not load-bearing.- set_progress(ctx, param, value)[source]
Publish whether progress spinners may be shown.
Stores the resolved
--progressflag atPROGRESS. Deliberately independent of color: see theProgressOptionnote for why a spinner is gated on interactivity (TTY /TERM=dumb) and--accessible, never on--no-color/NO_COLOR.- Return type:
- click_extra.spinner.progressbar(iterable=None, length=None, label=None, hidden=None, **kwargs)[source]
Drop-in for
click.progressbar()honoring--progress/--no-progress.Clickโs own progress bar is determinate, the counterpart to the indeterminate
Spinner. This thin wrapper gates it on the samePROGRESSflag the spinner uses, so a single--no-progress(or--accessible, which lowers theprogressdefault) silences both.- Parameters:
hidden (
bool|None) โ tri-state. Left at its defaultNone, the bar follows the resolved--progressflag: hidden when the user (or--accessible) turned progress off, shown otherwise. An explicitTrueorFalseforces the bar regardless, mirroring how an explicitcolor=argument overridesctx.coloronclick.echo(). With no active context (the bar used outside a Click command) it defaults to shown.- Return type:
ProgressBar[TypeVar(V)]
Note
Only
--no-progressis wired here. Color is already handled upstream: Click renders the bar throughclick.echo(), whosecolor=Noneresolves againstctx.color, so--no-color/NO_COLORstrip the barโs ANSI without any work from this wrapper.
The bundled catalog of terminal spinner presets.
Ported from cli-spinners, with frame intervals converted from milliseconds to seconds.
- click_extra.spinner_presets.ASCII_SPINNER_FRAMES: Final = ('-', '\\', '|', '/')
Plain ASCII animation frames, for terminals or fonts lacking Unicode glyphs.
- click_extra.spinner_presets.SPINNER_FRAMES: Final = ('โ ', 'โ ', 'โ น', 'โ ธ', 'โ ผ', 'โ ด', 'โ ฆ', 'โ ง', 'โ ', 'โ ')
Default animation frames: the ubiquitous Braille-dots spinner.
Ten frames give a smooth rotation in any UTF-8 terminal. Fall back to
ASCII_SPINNER_FRAMESwhere Braille glyphs are unavailable.
- class click_extra.spinner_presets.SpinnerPreset(frames: tuple[str, ...], interval: float)[source]
Bases:
NamedTupleA named spinner animation: its frames and the interval they look best at.
The
SPINNERScatalog is ported from cli-spinners, with intervals converted from milliseconds to seconds. Pass one toSpinnervia itsspinnerargument.Create new instance of SpinnerPreset(frames, interval)
- interval: float
Seconds between two frames, tuned per spinner upstream.
- click_extra.spinner_presets.SPINNERS: Final = {'aesthetic': (('โฐโฑโฑโฑโฑโฑโฑ', 'โฐโฐโฑโฑโฑโฑโฑ', 'โฐโฐโฐโฑโฑโฑโฑ', 'โฐโฐโฐโฐโฑโฑโฑ', 'โฐโฐโฐโฐโฐโฑโฑ', 'โฐโฐโฐโฐโฐโฐโฑ', 'โฐโฐโฐโฐโฐโฐโฐ', 'โฐโฑโฑโฑโฑโฑโฑ'), 0.08), 'arc': (('โ', 'โ ', 'โ', 'โ', 'โก', 'โ'), 0.1), 'arrow': (('โ', 'โ', 'โ', 'โ', 'โ', 'โ', 'โ', 'โ'), 0.1), 'arrow2': (('โฌ๏ธ ', 'โ๏ธ ', 'โก๏ธ ', 'โ๏ธ ', 'โฌ๏ธ ', 'โ๏ธ ', 'โฌ ๏ธ ', 'โ๏ธ '), 0.08), 'arrow3': (('โนโนโนโนโน', 'โธโนโนโนโน', 'โนโธโนโนโน', 'โนโนโธโนโน', 'โนโนโนโธโน', 'โนโนโนโนโธ'), 0.12), 'balloon': ((' ', '.', 'o', 'O', '@', '*', ' '), 0.14), 'balloon2': (('.', 'o', 'O', 'ยฐ', 'O', 'o', '.'), 0.12), 'betaWave': (('ฯฮฒฮฒฮฒฮฒฮฒฮฒ', 'ฮฒฯฮฒฮฒฮฒฮฒฮฒ', 'ฮฒฮฒฯฮฒฮฒฮฒฮฒ', 'ฮฒฮฒฮฒฯฮฒฮฒฮฒ', 'ฮฒฮฒฮฒฮฒฯฮฒฮฒ', 'ฮฒฮฒฮฒฮฒฮฒฯฮฒ', 'ฮฒฮฒฮฒฮฒฮฒฮฒฯ'), 0.08), 'binary': (('010010', '001100', '100101', '111010', '111101', '010111', '101011', '111000', '110011', '110101'), 0.08), 'bluePulse': (('๐น ', '๐ท ', '๐ต ', '๐ต ', '๐ท '), 0.1), 'bounce': (('โ ', 'โ ', 'โ ', 'โ '), 0.12), 'bouncingBall': (('( โ )', '( โ )', '( โ )', '( โ )', '( โ)', '( โ )', '( โ )', '( โ )', '( โ )', '(โ )'), 0.08), 'bouncingBar': (('[ ]', '[= ]', '[== ]', '[=== ]', '[====]', '[ ===]', '[ ==]', '[ =]', '[ ]', '[ =]', '[ ==]', '[ ===]', '[====]', '[=== ]', '[== ]', '[= ]'), 0.08), 'boxBounce': (('โ', 'โ', 'โ', 'โ'), 0.12), 'boxBounce2': (('โ', 'โ', 'โ', 'โ'), 0.1), 'christmas': (('๐ฒ', '๐'), 0.4), 'circle': (('โก', 'โ', 'โ '), 0.12), 'circleHalves': (('โ', 'โ', 'โ', 'โ'), 0.05), 'circleQuarters': (('โด', 'โท', 'โถ', 'โต'), 0.12), 'clock': (('๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ '), 0.1), 'dots': (('โ ', 'โ ', 'โ น', 'โ ธ', 'โ ผ', 'โ ด', 'โ ฆ', 'โ ง', 'โ ', 'โ '), 0.08), 'dots10': (('โข', 'โข', 'โข', 'โก', 'โก', 'โก', 'โก '), 0.08), 'dots11': (('โ ', 'โ ', 'โ ', 'โก', 'โข', 'โ ', 'โ ', 'โ '), 0.1), 'dots12': (('โขโ ', 'โกโ ', 'โ โ ', 'โขโ ', 'โกโ ', 'โ โ ', 'โขโ ', 'โกโ ', 'โ โ ', 'โขโ ', 'โกโ ', 'โ โ ', 'โขโ ', 'โกโ ', 'โ โ ', 'โ โ ', 'โ โ ', 'โ โ ', 'โ โ ', 'โ โ ฉ', 'โ โข', 'โ โก', 'โขโ ฉ', 'โกโข', 'โ โก', 'โขโ ฉ', 'โกโข', 'โ โก', 'โขโ จ', 'โกโข', 'โ โก', 'โขโ ', 'โกโข', 'โ โก', 'โขโ ', 'โกโ ', 'โ โ ', 'โ โ ', 'โ โ ', 'โ โ ', 'โ โ ', 'โ โ ฉ', 'โ โข', 'โ โก', 'โ โ ฉ', 'โ โข', 'โ โก', 'โ โ ฉ', 'โ โข', 'โ โก', 'โ โ จ', 'โ โข', 'โ โก', 'โ โ ', 'โ โข', 'โ โก'), 0.08), 'dots13': (('โฃผ', 'โฃน', 'โขป', 'โ ฟ', 'โก', 'โฃ', 'โฃง', 'โฃถ'), 0.08), 'dots14': (('โ โ ', 'โ โ ', 'โ โ น', 'โ โขธ', 'โ โฃฐ', 'โขโฃ ', 'โฃโฃ', 'โฃโก', 'โฃโ ', 'โกโ ', 'โ โ ', 'โ โ '), 0.08), 'dots2': (('โฃพ', 'โฃฝ', 'โฃป', 'โขฟ', 'โกฟ', 'โฃ', 'โฃฏ', 'โฃท'), 0.08), 'dots3': (('โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ฆ', 'โ ด', 'โ ฒ', 'โ ณ', 'โ '), 0.08), 'dots4': (('โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ธ', 'โ ฐ', 'โ ', 'โ ฐ', 'โ ธ', 'โ ', 'โ ', 'โ ', 'โ '), 0.08), 'dots5': (('โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ฒ', 'โ ด', 'โ ฆ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ '), 0.08), 'dots6': (('โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ฒ', 'โ ด', 'โ ค', 'โ ', 'โ ', 'โ ค', 'โ ด', 'โ ฒ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ '), 0.08), 'dots7': (('โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ฆ', 'โ ค', 'โ ', 'โ ', 'โ ค', 'โ ฆ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ '), 0.08), 'dots8': (('โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ฒ', 'โ ด', 'โ ค', 'โ ', 'โ ', 'โ ค', 'โ ', 'โ ', 'โ ค', 'โ ฆ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ '), 0.08), 'dots8Bit': (('โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โก', 'โก', 'โก', 'โก', 'โก', 'โก ', 'โก', 'โก', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โก', 'โก', 'โก', 'โก', 'โก', 'โก', 'โก', 'โก', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โก', 'โก', 'โก', 'โก', 'โก', 'โก', 'โก', 'โก', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โ ', 'โก', 'โก', 'โก', 'โก', 'โก', 'โก', 'โก', 'โก', 'โ ', 'โ ก', 'โ ข', 'โ ฃ', 'โ ค', 'โ ฅ', 'โ ฆ', 'โ ง', 'โก ', 'โกก', 'โกข', 'โกฃ', 'โกค', 'โกฅ', 'โกฆ', 'โกง', 'โ จ', 'โ ฉ', 'โ ช', 'โ ซ', 'โ ฌ', 'โ ญ', 'โ ฎ', 'โ ฏ', 'โกจ', 'โกฉ', 'โกช', 'โกซ', 'โกฌ', 'โกญ', 'โกฎ', 'โกฏ', 'โ ฐ', 'โ ฑ', 'โ ฒ', 'โ ณ', 'โ ด', 'โ ต', 'โ ถ', 'โ ท', 'โกฐ', 'โกฑ', 'โกฒ', 'โกณ', 'โกด', 'โกต', 'โกถ', 'โกท', 'โ ธ', 'โ น', 'โ บ', 'โ ป', 'โ ผ', 'โ ฝ', 'โ พ', 'โ ฟ', 'โกธ', 'โกน', 'โกบ', 'โกป', 'โกผ', 'โกฝ', 'โกพ', 'โกฟ', 'โข', 'โข', 'โข', 'โข', 'โข', 'โข ', 'โข', 'โข', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ ', 'โฃ', 'โฃ', 'โข', 'โข', 'โข', 'โข', 'โข', 'โข', 'โข', 'โข', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โข', 'โข', 'โข', 'โข', 'โข', 'โข', 'โข', 'โข', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โข', 'โข', 'โข', 'โข', 'โข', 'โข', 'โข', 'โข', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โข ', 'โขก', 'โขข', 'โขฃ', 'โขค', 'โขฅ', 'โขฆ', 'โขง', 'โฃ ', 'โฃก', 'โฃข', 'โฃฃ', 'โฃค', 'โฃฅ', 'โฃฆ', 'โฃง', 'โขจ', 'โขฉ', 'โขช', 'โขซ', 'โขฌ', 'โขญ', 'โขฎ', 'โขฏ', 'โฃจ', 'โฃฉ', 'โฃช', 'โฃซ', 'โฃฌ', 'โฃญ', 'โฃฎ', 'โฃฏ', 'โขฐ', 'โขฑ', 'โขฒ', 'โขณ', 'โขด', 'โขต', 'โขถ', 'โขท', 'โฃฐ', 'โฃฑ', 'โฃฒ', 'โฃณ', 'โฃด', 'โฃต', 'โฃถ', 'โฃท', 'โขธ', 'โขน', 'โขบ', 'โขป', 'โขผ', 'โขฝ', 'โขพ', 'โขฟ', 'โฃธ', 'โฃน', 'โฃบ', 'โฃป', 'โฃผ', 'โฃฝ', 'โฃพ', 'โฃฟ'), 0.08), 'dots9': (('โขน', 'โขบ', 'โขผ', 'โฃธ', 'โฃ', 'โกง', 'โก', 'โก'), 0.08), 'dotsCircle': (('โข ', 'โ โ ', 'โ โ ', 'โ โ ฑ', ' โกฑ', 'โขโกฐ', 'โขโก ', 'โขโก'), 0.08), 'dqpb': (('d', 'q', 'p', 'b'), 0.1), 'dwarfFortress': ((' โโโโโโยฃยฃยฃ ', 'โบโโโโโโยฃยฃยฃ ', 'โบโโโโโโยฃยฃยฃ ', 'โบโโโโโโยฃยฃยฃ ', 'โบโโโโโโยฃยฃยฃ ', 'โบโโโโโโยฃยฃยฃ ', 'โบโโโโโโยฃยฃยฃ ', 'โบโโโโโโยฃยฃยฃ ', 'โบโโโโโโยฃยฃยฃ ', 'โบ โโโโโยฃยฃยฃ ', ' โบโโโโโยฃยฃยฃ ', ' โบโโโโโยฃยฃยฃ ', ' โบโโโโโยฃยฃยฃ ', ' โบโโโโโยฃยฃยฃ ', ' โบโโโโโยฃยฃยฃ ', ' โบโโโโโยฃยฃยฃ ', ' โบโโโโโยฃยฃยฃ ', ' โบโโโโโยฃยฃยฃ ', ' โบ โโโโยฃยฃยฃ ', ' โบโโโโยฃยฃยฃ ', ' โบโโโโยฃยฃยฃ ', ' โบโโโโยฃยฃยฃ ', ' โบโโโโยฃยฃยฃ ', ' โบโโโโยฃยฃยฃ ', ' โบโโโโยฃยฃยฃ ', ' โบโโโโยฃยฃยฃ ', ' โบโโโโยฃยฃยฃ ', ' โบ โโโยฃยฃยฃ ', ' โบโโโยฃยฃยฃ ', ' โบโโโยฃยฃยฃ ', ' โบโโโยฃยฃยฃ ', ' โบโโโยฃยฃยฃ ', ' โบโโโยฃยฃยฃ ', ' โบโโโยฃยฃยฃ ', ' โบโโโยฃยฃยฃ ', ' โบโโโยฃยฃยฃ ', ' โบ โโยฃยฃยฃ ', ' โบโโยฃยฃยฃ ', ' โบโโยฃยฃยฃ ', ' โบโโยฃยฃยฃ ', ' โบโโยฃยฃยฃ ', ' โบโโยฃยฃยฃ ', ' โบโโยฃยฃยฃ ', ' โบโโยฃยฃยฃ ', ' โบโโยฃยฃยฃ ', ' โบ โยฃยฃยฃ ', ' โบโยฃยฃยฃ ', ' โบโยฃยฃยฃ ', ' โบโยฃยฃยฃ ', ' โบโยฃยฃยฃ ', ' โบโยฃยฃยฃ ', ' โบโยฃยฃยฃ ', ' โบโยฃยฃยฃ ', ' โบโยฃยฃยฃ ', ' โบ ยฃยฃยฃ ', ' โบยฃยฃยฃ ', ' โบยฃยฃยฃ ', ' โบโยฃยฃ ', ' โบโยฃยฃ ', ' โบโยฃยฃ ', ' โบโยฃยฃ ', ' โบโยฃยฃ ', ' โบโยฃยฃ ', ' โบ ยฃยฃ ', ' โบยฃยฃ ', ' โบยฃยฃ ', ' โบโยฃ ', ' โบโยฃ ', ' โบโยฃ ', ' โบโยฃ ', ' โบโยฃ ', ' โบโยฃ ', ' โบ ยฃ ', ' โบยฃ ', ' โบยฃ ', ' โบโ ', ' โบโ ', ' โบโ ', ' โบโ ', ' โบโ ', ' โบโ ', ' โบ ', ' โบ &', ' โบ โผ&', ' โบ โผ &', ' โบโผ &', ' โบโผ & ', ' โผ & ', ' โบ & ', ' โผ & ', ' โบ & ', ' โผ & ', ' โบ & ', 'โผ & ', ' & ', ' & ', ' & โ ', ' & โ ', ' & โ ', ' & ยฃ ', ' & โยฃ ', ' & โยฃ ', ' & โยฃ ', ' & ยฃยฃ ', ' & โยฃยฃ ', ' & โยฃยฃ ', '& โยฃยฃ ', '& ยฃยฃยฃ ', ' โยฃยฃยฃ ', ' โยฃยฃยฃ ', ' โยฃยฃยฃ ', ' โยฃยฃยฃ ', ' โโยฃยฃยฃ ', ' โโยฃยฃยฃ ', ' โโยฃยฃยฃ ', ' โโยฃยฃยฃ ', ' โโโยฃยฃยฃ ', ' โโโยฃยฃยฃ ', ' โโโยฃยฃยฃ ', ' โโโยฃยฃยฃ ', ' โโโโยฃยฃยฃ ', ' โโโโยฃยฃยฃ ', ' โโโโยฃยฃยฃ ', ' โโโโยฃยฃยฃ ', ' โโโโโยฃยฃยฃ ', ' โโโโโยฃยฃยฃ ', ' โโโโโยฃยฃยฃ ', ' โโโโโยฃยฃยฃ ', ' โโโโโโยฃยฃยฃ ', ' โโโโโโยฃยฃยฃ ', ' โโโโโโยฃยฃยฃ ', ' โโโโโโยฃยฃยฃ ', ' โโโโโโยฃยฃยฃ '), 0.08), 'earth': (('๐ ', '๐ ', '๐ '), 0.18), 'fingerDance': (('๐ค ', '๐ค ', '๐ ', 'โ ', '๐ค ', '๐ '), 0.16), 'fish': (('~~~~~~~~~~~~~~~~~~~~', '> ~~~~~~~~~~~~~~~~~~', 'ยบ> ~~~~~~~~~~~~~~~~~', '(ยบ> ~~~~~~~~~~~~~~~~', '((ยบ> ~~~~~~~~~~~~~~~', '<((ยบ> ~~~~~~~~~~~~~~', '><((ยบ> ~~~~~~~~~~~~~', ' ><((ยบ> ~~~~~~~~~~~~', '~ ><((ยบ> ~~~~~~~~~~~', '~~ <>((ยบ> ~~~~~~~~~~', '~~~ ><((ยบ> ~~~~~~~~~', '~~~~ <>((ยบ> ~~~~~~~~', '~~~~~ ><((ยบ> ~~~~~~~', '~~~~~~ <>((ยบ> ~~~~~~', '~~~~~~~ ><((ยบ> ~~~~~', '~~~~~~~~ <>((ยบ> ~~~~', '~~~~~~~~~ ><((ยบ> ~~~', '~~~~~~~~~~ <>((ยบ> ~~', '~~~~~~~~~~~ ><((ยบ> ~', '~~~~~~~~~~~~ <>((ยบ> ', '~~~~~~~~~~~~~ ><((ยบ>', '~~~~~~~~~~~~~~ <>((ยบ', '~~~~~~~~~~~~~~~ ><((', '~~~~~~~~~~~~~~~~ <>(', '~~~~~~~~~~~~~~~~~ ><', '~~~~~~~~~~~~~~~~~~ <', '~~~~~~~~~~~~~~~~~~~~'), 0.08), 'fistBump': (('๐ค\u3000\u3000\u3000\u3000๐ค ', '๐ค\u3000\u3000\u3000\u3000๐ค ', '๐ค\u3000\u3000\u3000\u3000๐ค ', '\u3000๐ค\u3000\u3000๐ค\u3000 ', '\u3000\u3000๐ค๐ค\u3000\u3000 ', '\u3000๐คโจ๐ค\u3000\u3000 ', '๐ค\u3000โจ\u3000๐ค\u3000 '), 0.08), 'flip': (('_', '_', '_', '-', '`', '`', "'", 'ยด', '-', '_', '_', '_'), 0.07), 'grenade': (('ุ ', 'โฒ ', ' ยด ', ' โพ ', ' โธ', ' โธ', ' |', ' โ', ' โ', ' เทด ', ' โ', ' ', ' ', ' '), 0.08), 'growHorizontal': (('โ', 'โ', 'โ', 'โ', 'โ', 'โ', 'โ', 'โ', 'โ', 'โ', 'โ', 'โ'), 0.12), 'growVertical': (('โ', 'โ', 'โ', 'โ ', 'โ', 'โ', 'โ', 'โ ', 'โ', 'โ'), 0.12), 'hamburger': (('โฑ', 'โฒ', 'โด'), 0.1), 'hearts': (('๐ ', '๐ ', '๐ ', '๐ ', '๐ '), 0.1), 'layer': (('-', '=', 'โก'), 0.15), 'line': (('-', '\\', '|', '/'), 0.13), 'line2': (('โ ', '-', 'โ', 'โ', 'โ', '-'), 0.1), 'material': (('โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ', 'โโโโโโโโโโโโโโโโโโโโ'), 0.017), 'mindblown': (('๐ ', '๐ ', '๐ฎ ', '๐ฎ ', '๐ฆ ', '๐ฆ ', '๐ง ', '๐ง ', '๐คฏ ', '๐ฅ ', 'โจ ', '\u3000 ', '\u3000 ', '\u3000 '), 0.16), 'monkey': (('๐ ', '๐ ', '๐ ', '๐ '), 0.3), 'moon': (('๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ '), 0.08), 'noise': (('โ', 'โ', 'โ'), 0.1), 'orangeBluePulse': (('๐ธ ', '๐ถ ', '๐ ', '๐ ', '๐ถ ', '๐น ', '๐ท ', '๐ต ', '๐ต ', '๐ท '), 0.1), 'orangePulse': (('๐ธ ', '๐ถ ', '๐ ', '๐ ', '๐ถ '), 0.1), 'pipe': (('โค', 'โ', 'โด', 'โ', 'โ', 'โ', 'โฌ', 'โ'), 0.1), 'point': (('โโโ', 'โโโ', 'โโโ', 'โโโ', 'โโโ'), 0.125), 'pong': (('โโ โ', 'โโ โ', 'โ โ โ', 'โ โ โ', 'โ โก โ', 'โ โ โ', 'โ โ โ', 'โ โ โ', 'โ โ โ', 'โ โ โ', 'โ โก โ', 'โ โ โ', 'โ โ โ', 'โ โ โ', 'โ โ โ', 'โ โ โ', 'โ โกโ', 'โ โ โ', 'โ โ โ', 'โ โ โ', 'โ โ โ', 'โ โ โ', 'โ โก โ', 'โ โ โ', 'โ โ โ', 'โ โ โ', 'โ โ โ', 'โ โ โ', 'โ โก โ', 'โโ โ'), 0.08), 'rollingLine': (('/ ', ' - ', ' \\ ', ' |', ' |', ' \\ ', ' - ', '/ '), 0.08), 'runner': (('๐ถ ', '๐ '), 0.14), 'sand': (('โ ', 'โ ', 'โ ', 'โก', 'โก', 'โก', 'โก ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃ', 'โฃค', 'โฃฅ', 'โฃฆ', 'โฃฎ', 'โฃถ', 'โฃท', 'โฃฟ', 'โกฟ', 'โ ฟ', 'โข', 'โ ', 'โก', 'โ ', 'โ ซ', 'โข', 'โ ', 'โ ', 'โก', 'โ ', 'โ ', 'โ ก', 'โข'), 0.08), 'shark': (('โ|\\____________โ', 'โ_|\\___________โ', 'โ__|\\__________โ', 'โ___|\\_________โ', 'โ____|\\________โ', 'โ_____|\\_______โ', 'โ______|\\______โ', 'โ_______|\\_____โ', 'โ________|\\____โ', 'โ_________|\\___โ', 'โ__________|\\__โ', 'โ___________|\\_โ', 'โ____________|\\โ', 'โ____________/|โ', 'โ___________/|_โ', 'โ__________/|__โ', 'โ_________/|___โ', 'โ________/|____โ', 'โ_______/|_____โ', 'โ______/|______โ', 'โ_____/|_______โ', 'โ____/|________โ', 'โ___/|_________โ', 'โ__/|__________โ', 'โ_/|___________โ', 'โ/|____________โ'), 0.12), 'simpleDots': (('. ', '.. ', '...', ' '), 0.4), 'simpleDotsScrolling': (('. ', '.. ', '...', ' ..', ' .', ' '), 0.2), 'smiley': (('๐ ', '๐ '), 0.2), 'soccerHeader': ((' ๐งโฝ๏ธ ๐ง ', '๐ง โฝ๏ธ ๐ง ', '๐ง โฝ๏ธ ๐ง ', '๐ง โฝ๏ธ ๐ง ', '๐ง โฝ๏ธ ๐ง ', '๐ง โฝ๏ธ ๐ง ', '๐ง โฝ๏ธ๐ง ', '๐ง โฝ๏ธ ๐ง ', '๐ง โฝ๏ธ ๐ง ', '๐ง โฝ๏ธ ๐ง ', '๐ง โฝ๏ธ ๐ง ', '๐ง โฝ๏ธ ๐ง '), 0.08), 'speaker': (('๐ ', '๐ ', '๐ ', '๐ '), 0.16), 'squareCorners': (('โฐ', 'โณ', 'โฒ', 'โฑ'), 0.18), 'squish': (('โซ', 'โช'), 0.1), 'star': (('โถ', 'โธ', 'โน', 'โบ', 'โน', 'โท'), 0.07), 'star2': (('+', 'x', '*'), 0.08), 'timeTravel': (('๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ ', '๐ '), 0.1), 'toggle': (('โถ', 'โท'), 0.25), 'toggle10': (('ใ', 'ใ', 'ใ'), 0.1), 'toggle11': (('โง', 'โง'), 0.05), 'toggle12': (('โ', 'โ'), 0.12), 'toggle13': (('=', '*', '-'), 0.08), 'toggle2': (('โซ', 'โช'), 0.08), 'toggle3': (('โก', 'โ '), 0.12), 'toggle4': (('โ ', 'โก', 'โช', 'โซ'), 0.1), 'toggle5': (('โฎ', 'โฏ'), 0.1), 'toggle6': (('แ', 'แ'), 0.3), 'toggle7': (('โฆพ', 'โฆฟ'), 0.08), 'toggle8': (('โ', 'โ'), 0.1), 'toggle9': (('โ', 'โ'), 0.1), 'triangle': (('โข', 'โฃ', 'โค', 'โฅ'), 0.05), 'weather': (('โ๏ธ ', 'โ๏ธ ', 'โ๏ธ ', '๐ค ', 'โ ๏ธ ', '๐ฅ ', 'โ๏ธ ', '๐ง ', '๐จ ', '๐ง ', '๐จ ', '๐ง ', '๐จ ', 'โ ', '๐จ ', '๐ง ', '๐จ ', 'โ๏ธ ', '๐ฅ ', 'โ ๏ธ ', '๐ค ', 'โ๏ธ ', 'โ๏ธ '), 0.1)}
Named spinner animations ported from cli-spinners, keyed by name.
Each value is a
SpinnerPresetbundling frames and a tuned interval. Select one withSpinnerโsspinnerargument:from click_extra import Spinner, SPINNERS with Spinner("Brewing tea", spinner=SPINNERS["moon"]): ...
Unlike the upstream
\b-based renderers,Spinnerredraws the whole line, so the multi-character animations (bouncingBar,pong,shark, โฆ) render correctly here.