pb

A terminal progress bar library for Go with customizable templates, byte-aware formatting, and proxy readers/writers for tracking I/O.

Library
Go
vv3.2.1
3,724stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
74/100Good
Development Activity84
Maintenance48
Community64
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture78
Code Quality74
Innovation66
Learning Curve85

pb is a lightweight Go library for rendering progress bars in terminal applications. It ships a set of ready-made presets (Default, Simple, Full) alongside a template engine that lets you compose fully custom bars from reusable elements such as percent, counters, speed, remaining/elapsed time, and the bar glyph itself, with color support via fatih/color.

Beyond simple counters, pb includes a NewProxyReader/NewProxyWriter pair that wraps any io.Reader or io.Writer so byte-oriented operations — file downloads, copies, uploads — automatically drive the bar’s progress and switch it into byte-formatted output (KiB/MiB or SI kB/MB). Terminal width detection is handled per-platform (Linux, BSD, Windows, Plan9, AIX, Solaris) through an internal termutil package, and adaptive elements resize themselves to fill whatever space the terminal provides.

The library has been stable and widely used since 2012, with the current v3 module (imported as github.com/cheggaaa/pb/v3) representing a rewrite of the original API that added the template-based element system and cleaner concurrency handling around a single mutex-guarded state.

What You Get

  • Ready-to-use presets (Default, Simple, Full) for common progress-bar layouts with zero configuration
  • A template engine with composable elements (bar, percent, counters, speed, rtime, etime, string, cycle) for building custom displays
  • Byte-aware formatting (IEC KiB/MiB or SI kB/MB) for tracking file and network transfer progress
  • NewProxyReader and NewProxyWriter wrappers that drive progress automatically from io.Reader/io.Writer operations
  • Cross-platform terminal width detection (Linux, BSD, Windows, Plan9, Solaris, AIX) with graceful fallback
  • Thread-safe operation via atomic counters and mutex-guarded state, safe to update from multiple goroutines
  • Optional Unicode progress glyphs via the UNICODE_PROGRESS_BAR environment variable
  • A RegisterElement API for adding entirely custom template elements

Common Use Cases

  • Showing download/upload progress for CLI tools that fetch or transfer files
  • Displaying batch job progress (e.g., processing N records) in long-running command-line scripts
  • Wrapping io.Copy operations to report byte-level progress without changing the copy logic
  • Building custom terminal dashboards with multiple concurrent progress bars via the pool sub-API
  • Providing ETA and throughput (items/sec or bytes/sec) feedback during data migrations or imports

Under The Hood

Architecture The library centers on a single ProgressBar struct (v3/pb.go) whose state is guarded by a sync.RWMutex for the counters/config and a separate sync.Mutex (rm) that serializes rendering, while current/total are updated with sync/atomic so Add/Increment calls from worker goroutines never block the render path. Rendering itself is delegated to text/template (getTemplate in template.go) executed against a State wrapper that exposes read-only accessors (Total, Value, Width, IsFinished) to templates and elements, keeping bar logic decoupled from presentation; a background goroutine (writer) ticks on refreshRate and pushes rendered frames to the configured io.Writer, with a finish channel used to synchronize shutdown in Finish(). Custom display logic plugs in through the Element interface and a global elements map (element.go), with an adaptiveWrap mechanism that defers width-dependent elements (like the bar glyph itself) to a second pass once static content width is known — a deliberately narrow but effective solution to the “bar must fill remaining terminal width” problem.

Tech Stack Written in Go (module github.com/cheggaaa/pb/v3, requiring Go 1.25 in the current go.mod) with a small, focused dependency set: github.com/fatih/color for ANSI color output, github.com/mattn/go-colorable and github.com/mattn/go-isatty for cross-platform TTY/color detection, github.com/mattn/go-runewidth and github.com/clipperhouse/uax29/v2 for correct terminal cell-width calculation of Unicode strings, github.com/VividCortex/ewma for exponentially-weighted moving-average speed calculation, and golang.org/x/sys for platform syscalls. Terminal width detection is implemented per-OS in the internal termutil package (separate files per platform: Linux, BSD, Windows, Plan9, Solaris, AIX, plus a stub fallback), compiled in via Go build tags rather than runtime branching.

Code Quality The v3 package ships table-style unit tests alongside most core files (pb_test.go, element_test.go, template_test.go, util_test.go, preset_test.go, io_test.go), and CI (.github/workflows/) runs go test -v ./... against the v3 module on every push and PR to master. Error handling is explicit and typed: ProgressBar carries an internal err field surfaced through Err()/SetErr() rather than panicking, and template execution failures are captured rather than propagated as fatal errors, though a render-time recover() is used as a defensive backstop for template panics. Naming is consistent and idiomatic Go (exported types/methods documented with standard doc comments), and there is no linter config or static-analysis step visible in CI beyond go test.

What Makes It Unique Rather than hardcoding a fixed set of progress-bar layouts, pb exposes its rendering as a text/template-driven pipeline where every visual piece — bar glyph, percentage, counters, speed, timers — is a registered Element that any consumer can override or extend via RegisterElement, and the adaptive-width mechanism lets a single bar element auto-fill whatever terminal space remains after the rest of the template is rendered. Combined with byte-aware Proxy readers/writers that require no additional wiring to track I/O throughput, this gives pb a template-first customization model that is less common among comparable Go progress-bar libraries, most of which expose only a fixed handful of preset styles.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search