Open-source project
cheggaaa/pb avatar
cheggaaa/pb

cheggaaa/pb: A Terminal Progress Bar Library for Go

Console progress bar for Golang

3,728 stars274 forksGoBSD-3-Clause

At a glance

What is it?
cheggaaa/pb is a Go library that renders configurable progress bars in the terminal. It supports template-based rendering, byte-formatted counters, I/O proxy readers for tracking file transfers, and a pool API for displaying multiple bars simultaneously.
Who is it for?
cheggaaa/pb is a solid choice for Go programs that need a terminal progress bar for counted operations or I/O transfers. It fits well when your needs match its built-in templates or can be covered by the text/template engine.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 9 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What cheggaaa/pb Solves and Who Uses It

Command-line tools that process large numbers of items or copy large files face a display problem: the user has no feedback on progress without manual print statements. cheggaaa/pb provides a terminal progress bar that handles this without custom rendering logic. It tracks the current count against a total, calculates throughput, and renders a bar with configurable format in the terminal.

The library targets Go developers writing CLI tools, data processing scripts, file copy utilities, or any program with a measurable operation where user feedback during execution matters. The import path is `github.com/cheggaaa/pb/v3` and the last push was on 2026-09-21.

The library is licensed under BSD-3-Clause. It requires Go 1.12 or later, as specified in `go.mod`.

Installation and a First Progress Bar

The module is fetched with the standard Go toolchain:

code
go get github.com/cheggaaa/pb/v3

The simplest usage is a two-line setup. `pb.StartNew(count)` creates a bar with a given total and starts rendering immediately. Calling `bar.Increment()` advances the counter by one. `bar.Finish()` stops the bar when the operation completes.

The README's quick-start example iterates 100,000 times with a one-millisecond delay per iteration and produces output in the form:

code
37158 / 100000 [---------------->_______________________________] 37.16% 916 p/s

The bar shows the current count, the total, a visual fill indicator, the percentage, and the rate in operations per second. All of these fields are included by default without any configuration.

Configuration: Rates, Writers, and Byte Formatting

The bar object exposes several configuration methods that can be chained before calling `Start()`:

Go
bar := pb.New(count)
bar.SetRefreshRate(time.Second)
bar.SetWriter(os.Stdout)
bar.Set(pb.Bytes, true)
bar.Set(pb.SIBytesPrefix, true)
bar.Start()

`SetRefreshRate` controls how often the bar redraws. The default is 200 milliseconds; setting it to `time.Second` reduces terminal flicker for fast operations.

`SetWriter` overrides the output destination. The default is `os.Stderr`, which is appropriate when `os.Stdout` carries actual output. Redirecting to `os.Stdout` is an option when the terminal is the only consumer.

Setting `pb.Bytes` to `true` formats the counter as bytes with IEC prefixes (B, KiB, MiB, GiB). Setting `pb.SIBytesPrefix` to `true` switches to SI prefixes (B, kB, MB, GB) instead. These two options are mutually exclusive choices for the same byte-count display.

Tracking I/O Operations with the Proxy Reader

For file copy or download operations where the unit of progress is bytes read rather than discrete items, the library provides a proxy reader that wraps any `io.Reader` and advances the bar as data flows through it:

Go
bar := pb.Full.Start64(limit)
barReader := bar.NewProxyReader(reader)
io.Copy(writer, barReader)
bar.Finish()

The `Start64` method accepts an `int64` total, suitable for file sizes. The proxy reader intercepts all reads and updates the bar counter transparently. The actual copy call, `io.Copy`, does not need to know about the progress bar.

This approach works with any `io.Reader`, including network connections, archive readers, or compressed streams. The bar reports throughput in bytes per second using the same mechanism it uses for operations-per-second counts.

Custom Templates and Unicode Fills

The bar's rendering is based on Go's standard `text/template` package. All available display elements are described in `v3/element.go`. The built-in templates (`pb.Default`, `pb.Simple`, `pb.Full`) are pre-composed sets of these elements, but any combination can be assembled into a custom template string.

The `bar` element accepts up to seven parts: left border, fill character, current position indicator, empty character, right border, and two optional parts for the empty left border and the finished right border. Color functions like `red`, `green`, `blue`, and `rndcolor` are available within templates.

An example custom template from the README combines color functions, a custom spinner, and named string elements:

Go
tmpl := `{{ red "With funcs:" }} {{ bar . "<" "-" (cycle . "↖" "↗" "↘" "↙" ) "." ">"}} {{speed . | rndcolor }} {{percent .}} {{string . "my_green_string" | green}} {{string . "my_blue_string" | blue}}`
bar := pb.ProgressBarTemplate(tmpl).Start64(limit)
bar.Set("my_green_string", "green").Set("my_blue_string", "blue")

Setting the environment variable `UNICODE_PROGRESS_BAR=true` enables built-in Unicode glyphs for the bar fill when the terminal font supports them. This replaces ASCII characters with Unicode block elements for a smoother visual.

Multiple Bars with the Pool API

The library includes a pool API for displaying multiple progress bars simultaneously, implemented in `pool.go` for Unix systems and `pool_win.go` for Windows. The pool manages terminal cursor positioning so each bar updates in its own row without overwriting the others.

The pool API is useful for tools that process multiple files or streams concurrently, where each item has its own bar. It handles the terminal control sequences needed to move the cursor between rows on update.

The repository also includes example test files for copy operations (`example_copy_test.go`) and multiple bars (`example_multiple_test.go`), which serve as practical references for these use cases.

Limitations and Comparison with vbauerster/mpb

cheggaaa/pb operates under the assumption that the total count is known before the bar starts. If the total is not known until after work begins, the bar cannot show percentage or estimated time remaining, only throughput. The API does not expose a mechanism for updating the total mid-run.

Template errors surface only after the template is set. The `bar.Err()` method should be called after `SetTemplateString` to catch template parse errors, but this is an explicit check the developer must remember to add. There is no panic or compile-time error for a malformed template string.

The library does not support colors in bar fills natively; color is applied through template functions that wrap text elements. This means gradient fills or per-segment coloring require custom element implementations.

vbauerster/mpb is an alternative Go progress bar library that takes a different approach. It is designed around goroutine-safe updates and provides a dedicated `Progress` object that manages multiple bars with fine-grained control over each bar's rendering. mpb exposes more customization points for advanced use cases, including dynamic totals and bar decoration functions. The trade-off is a more complex API. cheggaaa/pb is simpler to use for the common case of a single bar with a known total, while mpb is better suited when multiple goroutines update different bars concurrently.

Editorial conclusion

cheggaaa/pb is a solid choice for Go programs that need a terminal progress bar for counted operations or I/O transfers. It fits well when your needs match its built-in templates or can be covered by the text/template engine. If you need advanced concurrent rendering, color gradient fills, or fine-grained control over bar positioning across goroutines, vbauerster/mpb offers more options at the cost of additional complexity.

Frequently asked questions

How do I import cheggaaa/pb v3 in a Go project?

Run go get github.com/cheggaaa/pb/v3 to add the module. In your source file, import it as github.com/cheggaaa/pb/v3. The v3 import path is required; the v1 API is still present in the root package under a separate README_V1.md.

Can cheggaaa/pb track progress for file copy operations?

Yes. The library provides a proxy reader through bar.NewProxyReader(reader), which wraps any io.Reader and advances the bar as bytes pass through it. Pass the proxy reader to io.Copy instead of the original reader, and the bar updates automatically.

How do I display multiple progress bars at once with cheggaaa/pb?

The library includes a pool API in pool.go. The pool manages multiple bars with proper cursor positioning so each bar updates in its own terminal row. See the example_multiple_test.go file in the repository for a working reference.

Official sources

  1. cheggaaa/pb on GitHub
  2. Issues
  3. License: BSD-3-Clause
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cheggaaa-pb.svg)](https://hysenlabs.com/projects/cheggaaa-pb)