Progress bars
Show the right feedback at the right time — progress bars for known totals, spinners for unknown waits.
- Explain when to show a progress bar versus a spinner
- Describe what information a good progress bar conveys (count, total, percentage, ETA)
- Understand why progress feedback reduces perceived wait time
Any operation that takes more than a second or two needs feedback. Without it, users cannot tell whether the program is working, stuck, or crashed. A blank terminal during a 30-second file scan feels broken even when everything is fine.
Bar or spinner?
The choice depends on one question: do you know the total?
Use a progress bar when you know how many items you will process. Scanning a
list of 500 files, loading 1,000 database rows, downloading a file with a known
size — all of these have a definite total. A bar can show 342/500 (68%) ETA 4s,
which tells the user exactly where they are and when they will be done.
Use a spinner when the duration is unknown. Waiting for a network response, running a subprocess of unpredictable length, or polling until a condition is met — in these cases you cannot compute a percentage. A spinner honestly conveys "still working" without pretending to know more than it does. Showing a bar that jumps to 100% and then keeps spinning is worse than a spinner, because it lies.
What a good progress bar shows
A minimal progress bar shows a percentage. A good progress bar shows all of:
| Column | Why it helps |
|---|---|
| Current count | Tells you exactly where you are: 342/500 |
| Visual bar | Gives an at-a-glance sense of how far along |
| Percentage | Quantifies the bar: 68% |
| Elapsed time | Confirms the program is still running |
| ETA | Tells you when to come back |
| Current item | Shows the file/task being processed right now |
Not all of these are always useful. For a two-second operation, ETA is noise. For a twenty-minute batch job, ETA is essential.
The psychology of waiting
Research on perceived wait time consistently shows that feedback makes waits feel shorter. Users who see a progress bar tolerate much longer waits than users who see nothing. The explanation is simple: uncertainty is stressful. A bar converts "I don't know what's happening" into "I know what's happening and approximately when it will end."
This is not a cosmetic concern. It is the difference between users trusting your tool and users killing the process and filing a bug report.
When to omit progress entirely
If the operation takes less than about 500 ms, a progress bar flashes briefly and
vanishes — more disorienting than helpful. At that speed, just let it finish. Many
CLI tools print a summary line after completion (Built 42 files in 0.3s) instead
of showing a bar for very fast operations.
Never show a progress bar that does not move. A bar stuck at 0% for 30 seconds is more alarming than no bar at all. If you cannot update the bar during the operation (e.g. in a single blocking call), use a spinner instead.
Where to go next
Next: Rich progress — using rich.progress.track(), Progress(), and
Console.status() to add the right kind of feedback to your tools.