progressbar
A thread-safe, dependency-light progress bar and spinner library for Go CLI applications.
Repository Health
Technical Analysis
progressbar is a minimal, thread-safe Go library for rendering progress bars and spinners in terminal applications. It implements the io.Writer interface, so it can track bytes written to any stream automatically, making it a natural fit for wrapping HTTP downloads, file copies, or other I/O-heavy operations. When the total size isn’t known in advance, an indeterminate bar automatically becomes a customizable spinner instead of guessing at a percentage.
Originally built for the author’s own croc file-transfer tool, progressbar aims to work consistently across every OS without relying on multi-line terminal control sequences that behave inconsistently between platforms. It exposes over two dozen functional options for customizing width, color, theme, throttling, byte/rate display, and completion callbacks, letting consumers dial in exactly how much detail they want without forking the library.
What You Get
- A ProgressBar type safe for concurrent use from multiple goroutines via an internal mutex
- An io.Writer implementation for tracking bytes copied through io.Copy or an HTTP response body
- Automatic conversion to an indeterminate spinner (76 built-in styles) when max length is -1
- Over two dozen functional options for width, color, theme, throttling, and completion callbacks
- Byte-rate, ETA, and iterations-per-second display modes for long-running operations
Common Use Cases
- Showing download progress while streaming an HTTP response body to disk
- Displaying a spinner for tasks with an unknown or unbounded duration
- Tracking iteration progress in batch-processing or data-migration CLI scripts
- Reporting multi-step build or deployment progress with per-step descriptions
Under The Hood
Architecture
The module is a single flat package (github.com/schollz/progressbar/v3) with three files: progressbar.go (the core ProgressBar/state/config types and rendering logic), spinners.go (a map of 76 spinner frame sets indexed by int), and a large test file. There are no internal subpackages — the design is intentionally monolithic and single-purpose. NewOptions/NewOptions64 build a config via variadic Option functions; Add/Add64/Set64 mutate state under a mutex, then call the render path to compute percent and saucer size and write the formatted line to config.writer (defaulting to stderr). Because every Option function and the render path close over the same struct, changing the core state/config split would ripple through the whole file, trading modularity for a small, auditable single-file core.
Tech Stack
A Go 1.25 module with a deliberately small dependency set: rivo/uniseg and chengxilo/virtualterm for terminal-width-aware rune measurement (so wide/CJK characters render correctly), mitchellh/colorstring for ANSI color parsing, golang.org/x/term for terminal size detection, and k0kubun/go-ansi as an optional writer for Windows ANSI support. Tests use stretchr/testify. There is no web framework, ORM, or database involved — this is a pure terminal-rendering library whose only I/O is stdout/stderr or a caller-supplied io.Writer. CI runs go mod tidy -diff, go vet, and go test -race -cover.
Code Quality
A single large test file provides extensive coverage — the README advertises roughly 84% via gocover.io — exercising option combinations, byte-rate formatting, spinner behavior, and concurrent updates; CI runs tests with the race detector enabled, showing real attention to the library’s thread-safety claims. Error handling is idiomatic Go: functions return typed errors (e.g. for invalid option combinations or exceeding the configured maximum) rather than panicking or silently ignoring bad input. Naming is consistent, exported symbols carry standard Go doc comments, and a golangci-lint config plus go vet run in CI.
API Design
Default()/DefaultBytes() cover the common case with zero configuration, while NewOptions() accepts a flat list of functional options for everything else, avoiding a config struct callers must learn up front. Because ProgressBar implements io.Writer, it composes directly with io.Copy and io.MultiWriter with no adapter code required to track a download or file copy — a genuinely low-boilerplate integration point compared to libraries that require a manual increment call per read. The tradeoff is a large, flat option surface rather than a fluent builder, which is idiomatic Go but leans on godoc rather than method chaining for discoverability.
Used by 5 apps in this directory
Glasskube
Developer Tools · Devops
A next-generation Kubernetes package manager with a GUI, CLI, and native GitOps integration that makes deploying cluster workloads 20x faster than Helm.
SpiceDB
Security · Authentication · Databases
An open source, Google Zanzibar-inspired authorization database that models permissions as relationships and evaluates fine-grained access checks at massive scale with single-digit millisecond latency.
Teleport
Security · Authentication
Zero-trust infrastructure access platform that replaces credentials and VPNs with short-lived certificates, SSO, and identity-aware proxies for SSH, Kubernetes, databases, RDP, and AI agents.
Vikunja
Project Management
Self-hosted task management with natural-language quick-add, multiple views, and a fully documented REST API — your tasks, your infrastructure, zero lock-in.
Wakapi
Developer Tools · Analytics
Self-hosted WakaTime-compatible coding statistics backend that gives developers full control over their coding activity data.