alive-progress renders animated terminal progress bars. pip install alive-progress. Basic: from alive_progress import alive_bar. with alive_bar(total) as bar: for item in items: process(item); bar(). Manual: with alive_bar(100) as bar: bar(10) — advance by 10. Unknown total: with alive_bar() as bar: bar(). Title: with alive_bar(total, title="Processing") as bar:. Bar style: with alive_bar(total, bar="smooth") as bar:. bar="classic", "blocks", "bubbles", "filling", "notes", "ruler". Spinner: spinner="classic", "dots", "waves", "stars", "triangles", "wait". Stats: with alive_bar(total, stats=True) as bar: — shows rate and ETA. stats="(eta:{eta} rate:{rate})". Elapsed: elapsed=True. Text: bar.text("Processing {item}") or bar.text = f"item {i}". Receipt: with alive_bar(total, receipt=True) as bar: — final summary line. Force CI: with alive_bar(total, force_tty=True) as bar: — output even when not TTY. Disable: with alive_bar(total, disable=not sys.stdout.isatty()) as bar:. Dual line: with alive_bar(total, dual_line=True) as bar: bar.text = "detail". Theme: with alive_bar(total, theme="smooth") as bar:. theme="classic", "musical". Monitor: with alive_bar(total, monitor=True) as bar: — shows count. monitor="{count} / {total} [{percent:.0f}%]". Config: from alive_progress import config_handler; config_handler.set_global(spinner="dots", bar="smooth"). Claude Code generates alive_bar wrappers, dual-line status displays, and batch processing pipelines.
CLAUDE.md for alive-progress
## alive-progress Stack
- Version: alive-progress >= 3.1 | pip install alive-progress
- Basic: with alive_bar(len(items), title="Label") as bar: ... bar()
- Manual: bar(n) to advance by n steps; bar(0) to pulse without advancing
- Unknown: with alive_bar() as bar: bar() — spinner only, no ETA
- Text: bar.text = f"current: {item}" — live status below the bar
- Style: bar="smooth" | spinner="dots" | theme="smooth"
- CI: force_tty=True | disable=not sys.stdout.isatty()
alive-progress Animation Pipeline
# app/progress_alive.py — alive-progress bar patterns
from __future__ import annotations
import sys
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path
from typing import Any, Callable, Iterable, Iterator
from alive_progress import alive_bar, config_handler
# ─────────────────────────────────────────────────────────────────────────────
# Global config (optional — set project-wide defaults)
# ─────────────────────────────────────────────────────────────────────────────
config_handler.set_global(
spinner="dots",
bar="smooth",
elapsed=True,
stats=True,
receipt=True,
force_tty=False, # set True in CI if you want progress in logs
)
# ─────────────────────────────────────────────────────────────────────────────
# 1. Basic iteration — wrapping a loop
# ─────────────────────────────────────────────────────────────────────────────
def process_items(items: list[Any]) -> list[Any]:
"""
alive_bar wraps a total count. Call bar() once per completed item.
Shows animated spinner, filled bar, items/sec rate, and ETA.
"""
results = []
with alive_bar(len(items), title="Processing", bar="smooth") as bar:
for item in items:
time.sleep(0.02) # simulate work
results.append({"item": item, "done": True})
bar()
return results
# ─────────────────────────────────────────────────────────────────────────────
# 2. Manual advance — progress += N per step
# ─────────────────────────────────────────────────────────────────────────────
def process_batches(records: list[dict], batch_size: int = 50) -> list[dict]:
"""
bar(n) advances the bar by n units — useful when each iteration
processes a variable number of records.
"""
results: list[dict] = []
batches = [records[i:i + batch_size] for i in range(0, len(records), batch_size)]
with alive_bar(len(records), title="Batch processing", bar="blocks") as bar:
for batch in batches:
time.sleep(0.01 * len(batch))
results.extend({"processed": True, **r} for r in batch)
bar(len(batch)) # advance by actual batch size
bar.text = f"batch size={len(batch)}"
return results
# ─────────────────────────────────────────────────────────────────────────────
# 3. Unknown total — spinner only
# ─────────────────────────────────────────────────────────────────────────────
def stream_events(event_count: int = 20) -> list[dict]:
"""
When total is unknown, omit the total argument.
alive_bar shows an animated spinner and elapsed time, no ETA.
"""
events: list[dict] = []
with alive_bar(title="Streaming events", spinner="waves") as bar:
for i in range(event_count):
time.sleep(0.05)
events.append({"id": i, "type": "user.action"})
bar()
bar.text = f"event #{i}"
return events
# ─────────────────────────────────────────────────────────────────────────────
# 4. Dual-line display — bar + status line
# ─────────────────────────────────────────────────────────────────────────────
def train_epochs(
epochs: int = 5,
steps_per_epoch: int = 20,
) -> list[dict]:
"""
dual_line=True shows a second line below the bar for detailed status.
Use bar.text for the status line — it updates live without clearing.
"""
history: list[dict] = []
with alive_bar(
epochs * steps_per_epoch,
title="Training",
dual_line=True,
bar="filling",
spinner="stars",
) as bar:
for epoch in range(epochs):
epoch_loss = 0.0
for step in range(steps_per_epoch):
time.sleep(0.005)
loss = 1.0 / (epoch * steps_per_epoch + step + 1) + 0.01
epoch_loss += loss
bar()
bar.text = f"epoch={epoch+1} step={step+1} loss={loss:.4f}"
avg_loss = epoch_loss / steps_per_epoch
history.append({"epoch": epoch + 1, "loss": round(avg_loss, 4)})
return history
# ─────────────────────────────────────────────────────────────────────────────
# 5. Byte download simulation
# ─────────────────────────────────────────────────────────────────────────────
def simulate_download(total_bytes: int = 1_048_576) -> None:
"""
Combine bar(chunk) with bar.text showing transfer speed for file downloads.
"""
chunk_size = 65_536 # 64 KB chunks
received = 0
with alive_bar(
total_bytes,
title="Downloading",
bar="bubbles",
stats="({rate}/s)",
monitor="{count}/{total} bytes",
) as bar:
while received < total_bytes:
chunk = min(chunk_size, total_bytes - received)
time.sleep(0.02)
received += chunk
bar(chunk)
bar.text = f"{received // 1024} KB / {total_bytes // 1024} KB"
# ─────────────────────────────────────────────────────────────────────────────
# 6. concurrent.futures — progress on parallel tasks
# ─────────────────────────────────────────────────────────────────────────────
def _fetch(url: str) -> dict:
time.sleep(0.05)
return {"url": url, "status": 200}
def parallel_fetch(urls: list[str], max_workers: int = 8) -> list[dict]:
"""
Wrap as_completed with alive_bar — bar advances each time a future resolves.
"""
results: list[dict] = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {executor.submit(_fetch, url): url for url in urls}
with alive_bar(len(futures), title="Fetching", bar="notes") as bar:
for future in as_completed(futures):
try:
results.append(future.result())
except Exception as exc:
bar.text = f"ERROR: {exc}"
finally:
bar()
return results
# ─────────────────────────────────────────────────────────────────────────────
# 7. CI-safe wrapper — disable when not interactive
# ─────────────────────────────────────────────────────────────────────────────
def progress_iter(
items: Iterable[Any],
total: int | None = None,
title: str = "Working",
force_tty: bool = False,
) -> Iterator[Any]:
"""
Yields items from an iterable, showing progress.
In CI (non-TTY), force_tty=False suppresses animation — no garbled output.
Pass force_tty=True to keep progress in CI logs.
"""
is_tty = sys.stdout.isatty() or force_tty
items_list = list(items)
actual_total = total or len(items_list)
with alive_bar(
actual_total,
title=title,
disable=not is_tty,
force_tty=force_tty,
) as bar:
for item in items_list:
yield item
bar()
# ─────────────────────────────────────────────────────────────────────────────
# 8. File processing pipeline
# ─────────────────────────────────────────────────────────────────────────────
def process_directory(
directory: Path,
pattern: str = "*.txt",
processor: Callable[[Path], Any] | None = None,
) -> list[dict]:
"""Process all matching files with a progress bar showing file names."""
if processor is None:
processor = lambda p: {"path": str(p), "size": p.stat().st_size}
files = list(directory.glob(pattern))
results: list[dict] = []
with alive_bar(len(files), title=f"Processing {pattern}", dual_line=True) as bar:
for f in files:
bar.text = f.name
try:
results.append(processor(f))
except Exception as exc:
bar.text = f"ERROR {f.name}: {exc}"
finally:
bar()
return results
# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
print("=== Basic iteration ===")
results = process_items(list(range(15)))
print(f" Processed {len(results)} items")
print("\n=== Dual-line training ===")
history = train_epochs(epochs=3, steps_per_epoch=10)
for h in history:
print(f" epoch={h['epoch']} loss={h['loss']}")
print("\n=== Parallel fetch ===")
urls = [f"https://api.example.com/{i}" for i in range(12)]
fetched = parallel_fetch(urls, max_workers=4)
print(f" Fetched {len(fetched)} URLs")
print("\n=== Download ===")
simulate_download(total_bytes=262_144)
print("\n=== CI-safe iterator ===")
for item in progress_iter(range(8), title="CI test", force_tty=True):
time.sleep(0.02)
print(" Done")
For the tqdm alternative — tqdm is the most widely-used Python progress library with native pandas.progress_apply, asyncio, and concurrent.futures integrations, while alive-progress renders smoother animated spinners using ANSI escape sequences, provides dual_line=True for a two-line display (bar + live status text), and shows a clean formatted receipt summary at completion — the visual difference is most apparent in terminal emulators with full ANSI support where alive-progress animations are noticeably smoother. For the print(f"{i}/{total}") alternative — manual print-based progress clutters stdout with one line per item, cannot show ETA or throughput, and cannot be easily suppressed in CI, while with alive_bar(total, disable=not sys.stdout.isatty()) as bar: outputs a single updating line in interactive mode and nothing at all in CI piped environments. The Claude Skills 360 bundle includes alive-progress skill sets covering alive_bar with total count, manual bar(n) advancement by variable step sizes, unknown total spinner mode, dual_line with bar.text status, bar/spinner/theme style selection, receipt completion summary, force_tty and disable for CI output control, concurrent.futures as_completed wrapping, byte-level download progress with monitor format, progress_iter generator wrapper, and config_handler.set_global for project-wide defaults. Start with the free tier to try animated progress bar code generation.