CLI tool
schollz/progressbar avatar
schollz/progressbar

schollz/progressbar: a thread-safe Go progress bar that stays on one line

A really basic thread-safe progress bar for Golang applications

4,709 stars258 forksGoMIT

At a glance

What is it?
schollz/progressbar is a small MIT-licensed Go library that draws a progress bar or spinner in the terminal. It is built for CLI and network tools that need a bar on every OS, and it deliberately refuses multi-line output.
Who is it for?
Adopt schollz/progressbar if you are writing a Go CLI or downloader and want a bar that works on Windows, macOS and Linux without terminal-specific code. Skip it if you need multi-line or concurrent bars, since the README states multi-line output is not planned.
Can I use it commercially?
Yes. MIT 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 11 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 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What schollz/progressbar solves, and who it is for

Go command-line tools that copy files, fetch URLs or loop over thousands of records usually want to show how far along they are. The standard library gives you fmt and not much else, and terminal escape sequences differ enough across Windows, macOS and Linux that hand-rolling a bar is a distraction from the actual program. schollz/progressbar exists to remove that distraction. The README is blunt about its origin: the author needed a progress bar for croc, the file-transfer tool, and "everything I tried had problems, so I made another one."

The intended user is a Go developer shipping a terminal program who wants a bar in a few lines and does not want to think about ANSI codes, cursor movement or whether the target is a TTY. The library is MIT licensed, which places almost no conditions on how you ship it. It is not a GUI widget, not a web component and not a logging framework. If your output is HTML, a desktop window or a Jupyter notebook, this is the wrong library.

How the bar is drawn, and why it refuses multi-line output

The mechanism is deliberately small. You create a bar with a total count, call Add on every unit of work, and the bar redraws itself in place. Because it implements io.Writer, it can also count bytes for you: wrap it around a stream and it infers progress from the number of bytes written rather than from your own counter. That is the same code path whether you are reading from an HTTP response, a file or a pipe.

Width, description, theme, colour codes and the output writer are all configurable through Option values, and the package documentation lists them. Spinners are not a separate type: a bar created with length -1 becomes a spinner, which is how the library handles a download whose Content-Length is unknown. The spinner glyphs live in spinners.go and the README credits @briandowns for compiling that list.

The design constraint worth understanding is the single-line rule. The README states that multi-line outputs are not planned, and links to the open issue about it. That is a conscious trade for OS independence: one line redrawn in place behaves the same in a Windows console and a Unix terminal, while multi-line layouts depend on cursor positioning that varies by terminal. If you need several bars at once, for parallel downloads or worker pools, this library will not give you that layout.

Installing schollz/progressbar and drawing your first bar

The module path carries the major version suffix, so the import is github.com/schollz/progressbar/v3. The README gives one install command:

bash
go get -u github.com/schollz/progressbar/v3

After that, the basic example from the README creates a bar with a total of 100 and advances it one step at a time. Run it in a terminal and you should see a single line redrawn as the loop proceeds:

go
bar := progressbar.Default(100)
for i := 0; i < 100; i++ {
    bar.Add(1)
    time.Sleep(40 * time.Millisecond)
}

For I/O, the README shows the writer pattern: pass the expected byte count and a description, then copy through io.MultiWriter so the bytes go both to the destination file and to the bar. The bar then advances from the bytes written, with no manual counter.

go
bar := progressbar.DefaultBytes(
    resp.ContentLength,
    "downloading",
)
io.Copy(io.MultiWriter(f, bar), resp.Body)

If the server does not send a Content-Length, the README suggests setting that length to -1, which turns the bar into a spinner. Customisation goes through NewOptions: the README's example sets the writer to an ANSI stdout, enables colour codes, shows bytes, sets a width of 15 and defines a Theme with Saucer, SaucerHead, SaucerPadding, BarStart and BarEnd fields. The README notes that the ANSI writer option requires installing github.com/k0kubun/go-ansi, which is already listed in the module's go.mod.

Where schollz/progressbar stops being the right tool

The single-line decision is the main limitation, and it is a real one rather than a documentation gap. A program that runs several workers in parallel and wants a bar per worker cannot express that here. The README points at issue 6 for multi-line output and states there is no plan to support it, so this is a boundary rather than a pending feature.

The second constraint is the terminal itself. The library writes to a writer you supply, and the README's customisation example swaps in an ANSI-aware stdout, which implies that plain output and colour output are not identical paths. The README does not document what happens when the destination is a file, a pipe or a CI log rather than a TTY; it only says the bar should work on every OS without problems. If your program's output is routinely captured to a log file, the redraw behaviour is something you should check against your own environment rather than assume.

Third, the feature set is intentionally narrow. There is no built-in hook for structured logging, no metrics export and no notion of nested or hierarchical progress. If your interface needs a tree of stages, you are composing that yourself on top of Add calls. None of this is a defect in what the library set out to do, but it does mean the library is a terminal primitive, not a progress-reporting framework.

How it compares with tqdm-style progress libraries

The closest mental model for most developers is Python's tqdm, which the search data shows people asking about alongside generic progress-bar questions. The difference in approach is worth stating plainly. tqdm is a Python library whose default behaviour is to write a new line and rely on carriage returns for in-place updates, and it ships a wide surface of integrations. schollz/progressbar is a Go library with a much smaller API: a bar, a writer, options, a theme and a spinner set. It does not try to be a general instrumentation layer.

A second comparison point is the standard library. Go's own packages give you no progress primitive at all, so the realistic alternative for a Go developer is either writing the escape sequences yourself or picking another Go progress library. Writing it yourself is viable for the simplest case, a counter printed with fmt, but you then own the cross-platform behaviour that this library was created to handle. The README's framing of the problem is exactly that: the author tried existing options and found problems, which is why the OS-agnostic single-line approach was chosen.

One thing the library does share with tqdm-style tools is the unknown-length case. Rather than requiring you to know the total, you pass -1 and get a spinner, which keeps the call site the same shape whether or not the length is known.

Maintenance, versioning and licence cost

The repository is not archived and the last push was on 2026-09-19, four days before this writing. Releases are infrequent but real: v3.19.1 on 2026-06-30, v3.19.0 on 2025-12-26 and v3.18.0 on 2025-01-09. The gap between v3.18.0 and v3.19.0 is roughly a year, which tells you the API is stable rather than fast-moving. A stable API is good news for adopters and bad news for anyone waiting on a new feature.

The module declares go 1.25.0 in go.mod, so you need a Go toolchain at or above that version. Beyond the standard library, the dependency list is short: chengxilo/virtualterm, k0kubun/go-ansi, mitchellh/colorstring, rivo/uniseg and golang.org/x/term, plus testify for tests. That is a modest surface to audit, and the README badge reports 84 percent coverage, though coverage numbers say nothing about whether the paths you care about are the covered ones.

The licence is MIT, which permits commercial and closed-source use with the usual requirement to keep the copyright and permission notice. That is a permissive arrangement, but it is not legal advice; check your own organisation's policy if you redistribute the library in a product.

Editorial conclusion

Adopt schollz/progressbar if you are writing a Go CLI or downloader and want a bar that works on Windows, macOS and Linux without terminal-specific code. Skip it if you need multi-line or concurrent bars, since the README states multi-line output is not planned. Before committing, check the Option list on pkg.go.dev for the exact writer, width and theme options your interface needs, and confirm the module path github.com/schollz/progressbar/v3 matches your go.mod.

Frequently asked questions

What is schollz/progressbar in simple terms?

It is a Go library that draws a progress bar in the terminal. You give it a total, call Add as work completes, and it redraws a single line; a total of -1 turns the bar into a spinner.

How do I install schollz/progressbar?

The README gives one command: go get -u github.com/schollz/progressbar/v3. The module path includes the v3 suffix, so imports use github.com/schollz/progressbar/v3.

Can schollz/progressbar show progress for a download?

Yes. The library implements io.Writer, so the README's example creates a bar with progressbar.DefaultBytes(resp.ContentLength, "downloading") and copies the response body through io.MultiWriter into both the destination file and the bar.

Does schollz/progressbar support multiple bars at once?

No. The README states that multi-line outputs are not planned, and links to issue 6 on that topic, so parallel bars are outside what this library provides.

What happens if the total length is unknown?

Any bar with length -1 is automatically converted to a spinner with a customizable spinner type, according to the README. The README's download example can be run with resp.ContentLength set to -1 to see this.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. schollz/progressbar on GitHub
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/schollz-progressbar.svg)](https://hysenlabs.com/projects/schollz-progressbar)