mpb: A Go Progress Bar Library for Concurrent CLI Workloads
multi progress bar for Go cli applications
At a glance
- What is it?
- mpb renders multiple progress bars in Go terminal apps, with dynamic totals, bar removal, and synchronized decorator widths. It suits concurrent tasks but has a narrow scope and a permissive license.
- Who is it for?
- Adopt mpb if you build Go CLI tools with concurrent operations that need clear visual progress feedback and you value a public-domain license. Avoid it if you need a full terminal UI library or if your progress bars must handle complex layouts beyond synchronized decorators.
- Can I use it commercially?
- Yes. Unlicense 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 15 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 14, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What mpb Solves and Who Needs It
mpb addresses a specific gap in Go's standard library: there is no built-in way to render progress bars, let alone several at once. For CLI applications that process files, download batches, or run parallel workers, a single bar is often misleading because it cannot show per-task progress. mpb is for developers who need multiple bars in one terminal view, each tracking a separate operation, with the ability to update totals while the bar is running. The README lists features that target exactly this: multiple bars, dynamic totals, dynamic add and remove, cancellation, and predefined decorators. This is not a general-purpose terminal UI toolkit. It is a focused library for one job, and it does that job with a small API surface. The target user is a Go developer who wants to add progress feedback to a concurrent CLI tool without building the rendering logic from scratch.
The Mechanism: Container, Bars, and Decorators
The core abstraction is a container, created with mpb.New(), that manages all bars. You then create bars via p.New() or p.AddBar(), passing a total and a set of options. The container handles layout and rendering, so each bar inherits the container's width unless overridden. The example shows mpb.WithWidth(64) to set a fixed width for the container. Bars are rendered with a BarFillerBuilder, which defines the visual style: left bound, filler character, tip, padding, and right bound. The README shows a custom style with box-drawing characters like ╢ and ▟. Decorators are functions that prepend or append text to a bar, such as a name, percentage, or elapsed time. The key mechanism for alignment is decor.WCSyncSpace, which enables column width synchronization across bars. This matters when you have multiple bars with different name lengths; without synchronization, the percentage columns would not line up. The container also supports a WaitGroup via mpb.WithWaitGroup(&wg), so p.Wait() blocks until all bars are done. This ties the rendering lifecycle to the actual work, which is a clean design.
Getting It Running: Commands and Config
To use mpb, you add it as a dependency with the Go module system. The import path is github.com/vbauerster/mpb/v8, and the package is imported as mpb. The README shows a minimal single-bar example: create a container with mpb.New(mpb.WithWidth(64)), then call p.New(int64(total), mpb.BarStyle().Lbound("╢").Filler("▌").Tip("▌").Padding("░").Rbound("╟"), mpb.PrependDecorators(decor.Name(name), decor.Percentage(decor.WCSyncSpace))). For multiple bars, you add a sync.WaitGroup and pass it to mpb.WithWaitGroup(&wg). Each bar is added with p.AddBar(int64(total), ...). The documentation also points to examples for dynamic totals (dynTotal), queueing (queueBar), and I/O integration (io). The API is idiomatic Go: options are functions that modify a config struct. The version v8 is the current major release, so the API is stable within that series. To run the examples, you clone the repository and use go run on the example directories, such as _examples/singleBar/main.go.
A Real Limitation: Scope and Complexity
mpb is not a terminal UI framework. It does not handle input, mouse events, or complex layouts beyond a vertical stack of bars. If you need to display tables, interactive menus, or mixed content, mpb is the wrong tool. Another limitation is the dynamic total feature. While it is a headline feature, it requires careful coordination with the work being done. The total must be updated at the right time, and if you misjudge the timing, the bar can show incorrect progress or stall. The README does not document error handling for invalid totals or negative increments, so you must test that yourself. Also, the library's rendering depends on terminal capabilities. It uses ANSI escape codes, so it will not work in environments that do not support them, such as some CI logs or plain text output. For those cases, you would need to disable bars or use a fallback, which the library does not provide out of the box.
The Alternative: Standard Library or Full TUI Suites
The most direct alternative is to write your own progress bar with fmt.Printf and carriage returns. That gives you full control but requires you to handle terminal width, redraws, and concurrency yourself. It is viable for a single bar but becomes painful for multiple bars. On the other end, libraries like tview or termui offer full terminal UI capabilities, including panels, tables, and mouse support. They are much heavier and have a different API model. The difference in approach is that mpb is purpose-built for progress bars and nothing else, while TUI suites give you a canvas on which you can draw anything. If your only need is progress bars, mpb is simpler to integrate and has a smaller footprint. If you anticipate needing other UI elements later, a TUI suite might save you a rewrite, but it will add complexity from the start. The choice depends on whether you want a specialized tool or a general one.
Maintenance and License Implications
The repository shows active maintenance. The last push is recent, and the v8.16.0 release is dated after the previous releases, indicating a steady release cadence. The project uses GitHub Actions for testing and linting, as shown in the README badges. This suggests a maintained codebase with automated checks. The license is Unlicense, which is a public-domain dedication. This means you can use, modify, and distribute the code without restrictions, and you do not need to include attribution. That is a significant advantage for commercial or closed-source projects. However, the Unlicense comes with no warranty, so you must rely on your own testing. The upgrade cost is tied to the v8 API. Since the project is on v8, breaking changes are unlikely within that major version, but you should check the release notes when upgrading. The examples in the README are a good starting point for migration, as they show the current API.
When mpb Is the Wrong Tool
mpb is the wrong tool when your progress reporting must be machine-readable or logged rather than visually rendered. If you need to output progress to a file or a CI system that strips ANSI codes, mpb's output will be garbage. You would be better off writing structured logs with timestamps and percentages. Also, if your progress bars need to display variable-width content that changes during execution, such as file names that grow, the synchronized width feature can become a constraint. The bar widths are fixed at creation time, so dynamic content may be truncated. There is no mention of auto-resizing or wrapping. For those cases, you might need a custom decorator that truncates text, but the library does not provide that out of the box. Finally, if you are building a GUI application, mpb is irrelevant because it targets the terminal only.
Editorial conclusion
Adopt mpb if you build Go CLI tools with concurrent operations that need clear visual progress feedback and you value a public-domain license. Avoid it if you need a full terminal UI library or if your progress bars must handle complex layouts beyond synchronized decorators. Before adopting, verify the version compatibility with your Go runtime and test the dynamic total behavior with your specific workload, as the API expects careful management of totals and wait groups.
Community notes