mpb
A concurrency-safe Go library for rendering multiple progress bars in terminal applications, with dynamic totals and pluggable decorators.
Repository Health
Technical Analysis
mpb renders one or more progress bars in Go command-line applications without requiring callers to manage locks themselves. Each Progress container and each Bar owns a private goroutine that only ever mutates its own state in response to closures sent over a channel, so adding, removing, or updating bars from multiple goroutines is safe by construction rather than by convention.
Bars support dynamic totals that can change mid-render, queued bars that start only after another completes, and a decorator system (decor package) for composing elapsed time, EWMA-smoothed ETA, percentage, and byte-count displays on either side of a bar. The library ships as a dependency-light, dependency-injected set of functional options (ContainerOption, BarOption), making it straightforward to drop into CLI tools that need multi-bar progress reporting for parallel downloads, builds, or batch jobs.
What You Get
- Concurrency-safe multi-bar rendering — each container and bar runs its own goroutine, reachable only via channel-sent state-mutation closures
- Dynamic totals — a bar’s total can be changed after creation, useful when work size isn’t known upfront
- Composable decorators — prepend/append elapsed time, EWMA-based ETA, percentage, and byte-count displays from the
decorsubpackage - Queued and dependent bars — a bar can be configured to start only once another bar completes, via
BarQueueAfter - Graceful cancellation — the whole render process can be cancelled via context, unblocking any goroutines waiting on
Wait() - io.Reader/io.Writer/io.ReadSeeker proxies — wrap an existing reader or writer so its progress is tracked automatically as bytes flow through it
Common Use Cases
- Showing per-file progress bars while downloading multiple files concurrently
- Tracking progress of parallel worker goroutines processing a batch job
- Wrapping an HTTP response body or file reader so upload/download progress is reported without manual byte counting
- Building CLI tools (package managers, build tools, backup utilities) that need multiple simultaneous progress indicators
- Chaining dependent long-running steps where one progress bar should only start after a prior one finishes
Under The Hood
Architecture
mpb uses a channel/goroutine-driven actor-like model: Progress.serve runs a monitor goroutine that owns a pState (holding a priority queue of *Bar via heapManager), and all mutation happens by sending closures over an operateState chan func(*pState) — communicating by sharing memory via channels rather than locks. Each Bar similarly owns a private goroutine reachable only via its own operateState chan func(*bState), so bar-local state (decorators, filler, counters) is never touched concurrently from outside. Rendering is decoupled from mutation: a ticker-driven renderReq channel triggers periodic frame draws that flow through frameCh to a cupwriter-backed ConsoleWriter for ANSI redraw. The core abstraction — state mutation as a function value sent over a channel — is pervasive; changing it would ripple through nearly every public method across bar.go, progress.go, and heap_manager.go. Options follow the standard functional-options pattern (ContainerOption, BarOption).
Tech Stack
Built for Go 1.25 with a deliberately small dependency set: github.com/VividCortex/ewma for EWMA-smoothed ETA calculation, github.com/acarl005/stripansi and github.com/mattn/go-runewidth for terminal-width-aware string measurement that accounts for ANSI codes and wide runes, and github.com/vbauerster/cupwriter for cursor-aware terminal redraws. Indirect tooling includes golang.org/x/tools/cmd/stringer, invoked via go:generate to produce stringer methods for enum-like types (e.g. byte-size units in decor/). CI runs the test suite across stable and oldstable Go on Ubuntu, macOS, and Windows, with a separate golangci-lint workflow.
Code Quality
The repository carries an extensive test suite alongside its implementation files — bar_test.go, progress_test.go, a substantial draw_test.go, decorators_test.go, and proxy-reader/writer/read-seeker tests, plus dedicated tests under decor/ and internal/ for ETA, percentage, and size-formatting logic, with a benchmark file (barbench_test.go) and godoc-verified example_test.go. Error handling favors explicit, typed errors (a generic ErrDone[T] for use-after-Wait() misuse) and context-based cancellation over swallowed errors. Naming is consistent and idiomatic Go throughout, and golangci-lint runs in CI on every push and pull request.
API Design
The public API is a small, composable functional-options surface: mpb.New(...ContainerOption) for the container and p.AddBar(total, ...BarOption)/p.New(...) for bars, with decorators supplied separately via mpb.PrependDecorators/AppendDecorators from the decor subpackage. This keeps a single-bar quick start to a handful of lines while still exposing width syncing, dynamic totals, and queueing for advanced cases. Every exported type and function carries a godoc comment, and the _examples/ directory has 20+ runnable, narrowly-scoped programs (single bar, multiple bars, dynamic total, queued bar, I/O proxying, spinners) that double as the primary onboarding path alongside the README.
Used by 2 apps in this directory
Dolt
Databases · Data Engineering · Developer Tools
The SQL database you can branch, merge, diff, and clone — Git for your data, MySQL-compatible and ready for multi-agent AI workflows.
tau
Devops
Open-source, Git-native platform-as-a-service for building, deploying, and scaling fullstack apps on your own infrastructure with no DevOps required.