termgraph: block-character bars, ANSI colours that will not paste, and a cut-off help block
A Python command-line and library that draws basic graphs in the terminal
At a glance
- What is it?
- termgraph draws bar charts, histograms, stacked and calendar heatmaps in a terminal from a two column text file, and ships the same thing as a Python library with four chart classes. It has one runtime dependency, a development workflow built on just and uv, and a printed argument list that stops in the middle of a flag name.
- Who is it for?
- termgraph is a good fit when the data already lives in a text file and you want a picture in the terminal rather than a file to open, which is exactly the problem it was written for, and the library form means the same renderer works inside a script that prints a status line. Two things to know before you rely on it.
- 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?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One runtime dependency, one console script, and a Python floor of 3.9
The packaging is small enough to read in one sitting. The runtime dependency list contains a single entry, colorama at 0.4.6 or later, which is what makes the colour output work on Windows terminals. Everything else needed to build, test, lint and publish sits in a development dependency group.
requires-python = ">=3.9"
dependencies = [
"colorama>=0.4.6",
]The command is wired to a single function:
[project.scripts]
termgraph = "termgraph.termgraph:main"so the module layout is a package containing a termgraph module with a main entry point, which is also how the justfile runs it. The build backend is hatchling, while the development workflow uses uv rather than pip, with a separate recipe for a production-only sync.
The classifiers tell you what the author declared rather than what is measured. They list Development Status 5, Production/Stable, the console environment, and Python 3.9 through 3.12, even though the requirement itself is open ended above 3.9, so a newer interpreter is allowed by the metadata but untested by the classifier list.
The printed usage block stops halfway through a flag name
The argument list in the documentation ends mid-word:
usage: termgraph [-h] [options] [filename]
positional arguments:
filename data file name (comma or space separated). Defaults to stdin.
options:
-h, --help show this help message and exit
--title TITLE Title of graph
--width WIDTH width of graph in characters default:50
--format FORMAT format specifier to use.
--suffix SUFFIX string to add as a suffix to all data points.
--no-labels Do not print the label column
--no-values Do not print the values at end
--space-betweeThe last visible entry is `--space-betwee`, which is the flag the colour example uses as `--space-between`. So the help text is incomplete at exactly the point where the remaining options would begin.
That matters because most of the interesting flags appear only in the examples. `--color` with a brace-delimited value, `--stacked`, `--custom-tick`, `--calendar` and `--start-dt` are all demonstrated in worked invocations and none of them is in the printed list. Run `termgraph -h` for the real set rather than trusting the block above.
The input format itself is simple by design: two columns, comma or space separated, the first holding labels and the second holding numbers, and with no filename the data is read from standard input.
The library spells its options with underscores and the command line with hyphens
The same chart can be drawn from Python, and the two surfaces do not use the same vocabulary. The class list is short: BarChart, StackedChart, VerticalChart and HistogramChart, all constructed from the same pair of objects.
from termgraph import Data, Args, BarChart
data = Data([[10], [25], [50], [40]], ["Q1", "Q2", "Q3", "Q4"])
args = Args(
title="Quarterly Sales",
width=50,
format="{:.0f}",
suffix="K"
)
chart = BarChart(data, args)
chart.draw()Data takes a list of rows and a list of labels. Args takes keyword arguments, and the quick reference lists them as `title`, `width`, `format`, `suffix`, `no_labels`, `no_values` and `colors`. Two of those are spelled with underscores in Python and with hyphens on the command line as `--no-labels` and `--no-values`, so a flag copied from one surface needs translating before it works in the other.
The colours option differs in kind rather than spelling. In Python it is a list of colour names, while the command line takes a single brace-delimited argument, as in `--color {cyan/yellow}` or `--color {green,magenta}`. The width default is 50 characters on both surfaces, and the number format default is given as `{:<5.2f}`.
Bars are block characters, and the tick mark can be an emoji
The rendering is block characters scaled to the width you ask for, which is where the design came from. The stated background is a text file of data that needed looking at quickly, after scripts in R produced graph files that then had to be opened, a two step process. Seeing command-line sparklines made the same idea possible with block characters instead.
The default output pairs a heavy block with a light one, using the heavy character for most values and the light character for the smallest entry in the sample, so a bar of length one is still visible. Values are printed at the end of each line, and the label column can be suppressed.
The tick character is configurable, which is where the emoji feature comes from:
termgraph data/ex1.dat --custom-tick "🏃" --width 20 --title "Running Data"Two things to notice about that example. The width drops to 20, so the same data produces half as many characters per bar, and the emoji occupies more cells than a block character does, so the bar no longer lines up with the value column. Emoji ticks are a demonstration that the tick is a string, not a special case.
Colour charts embed ANSI escape codes, so their output does not paste cleanly
There is a warning attached to colour mode in the documentation, and it is the one limitation stated outright: colour charts use ANSI escape codes, so you may not be able to copy and paste from the terminal into other uses.
termgraph data/ex4.dat --color {cyan/yellow} --space-betweenThe value syntax takes a group of names inside braces, separated by a slash. The stacked example takes a comma instead:
termgraph data/ex7.dat --color {green,magenta} --stackedSo two different separators appear in two examples in the same section, which is worth knowing before you conclude your shell mangled the argument.
For anything that ends up in a document, a ticket or a chat message, plain output is the safe path. Multi-variable and stacked charts are where colour earns its place, and those are also the cases where the escape codes travel with the text if you copy it.
Calendar heatmaps require dates in the first column and an explicit start date
The calendar mode is the one chart type with a strict input requirement rather than a formatting option. The first column has to be a date in yyyy-mm-dd form, and the invocation names the start date explicitly:
termgraph --calendar --start-dt 2017-07-01 data/cal.datNothing in the argument reference explains what happens to a file whose dates are in another order or another format, so the requirement is best treated as a hard constraint when preparing data.
The value column still behaves like every other chart, which means width, format, suffix and label suppression all still apply. The calendar is a layout choice over date labels rather than a separate renderer, which is also why it appears in the graph type list alongside histograms and stacked charts instead of in its own section.
That list is worth reading as the whole capability set of the tool: bar graphs, colour charts, multi-variable, stacked charts, histograms, horizontal or vertical orientation, calendar heatmaps and emoji ticks.
The justfile has a publish recipe and three different ways to run the tests
Development runs through just recipes backed by uv, and the file shows how wide the workflow is. Running just with no arguments lists the recipes rather than doing anything.
The install recipes split the two audiences: one syncs with the development group, the other syncs production dependencies only. There is a clean recipe that removes build directories, egg info, coverage output and the pytest and ruff caches, plus find commands for stray bytecode.
Testing has three entry points. One runs pytest through uv, one adds verbosity, one takes a single file. The third is different in kind: a module recipe runs three standalone scripts named module-test1.py through module-test3.py as executables, which is a different shape from the pytest suite that the test paths configuration points at.
Quality has two more layers, ruff for linting and formatting and mypy for type checking, combined in a check recipe that runs both. The release path is build, then twine check on the built distributions, then twine upload, with the publish recipe depending on both earlier steps so an unchecked artefact cannot reach PyPI. The lint configuration itself only sets a target Python version, and pytest runs with strict markers and strict config enabled.
The metadata says production stable, and the last commit is dated 25 March 2026
The last three releases are Termgraph v0.7.4 on 27 October 2025, v0.7.5 on 8 December 2025 and v0.7.6 on 25 March 2026, and the default branch was last pushed on 25 March 2026 as well. The tag and the final commit share the same moment, so nothing has landed since the newest release.
What that means for planning is that there is no unreleased work on the branch to wait for, and no recent commit stream to expect fixes from. The package classifiers describe the project as Production/Stable at version five, which is a declaration in the metadata rather than a release cadence, and the release history behind it is three patch versions across about five months inside the 0.7 series.
The project version in the manifest is 0.7.6, matching the newest tag. Documentation lives in a docs directory with a getting started page and separate pages for the data class, the chart classes and the args configuration, so the library surface is documented further than the command line is. Licensing is MIT with the text in a LICENSE.txt file, and contributions are handled through GitHub issues with a development workflow section in the contributing guide.
Editorial conclusion
termgraph is a good fit when the data already lives in a text file and you want a picture in the terminal rather than a file to open, which is exactly the problem it was written for, and the library form means the same renderer works inside a script that prints a status line. Two things to know before you rely on it. Colour output carries ANSI escape codes, so anything you copy out of a coloured chart into a document will bring its escape sequences with it, which the documentation warns about directly. And the argument list printed in the README is incomplete, stopping inside a flag name, so treat the examples rather than the help text as the reference for options like colour, stacked mode, calendar mode and custom ticks. The version to pin is 0.7.6, the last release, and the classifiers call the project production stable while the last commit is dated 25 March 2026.
Frequently asked questions
How do I install and run termgraph?
It is published as the termgraph console script, requires Python 3.9 or later, and depends only on colorama. Run termgraph against a two column data file, or pass no filename to read from stdin, and use termgraph -h for the argument list.
What chart types does termgraph support?
Bar graphs, colour charts, multi-variable charts, stacked charts, histograms, horizontal or vertical orientation, calendar heatmaps, and emoji as a custom tick mark. In the Python API they are the BarChart, StackedChart, VerticalChart and HistogramChart classes.
What are the default width and number format in termgraph?
Width defaults to 50 characters and the number format specifier defaults to {:<5.2f}. Both can be overridden, on the command line with --width and --format and in Python through the Args class.
How does termgraph draw a calendar heatmap?
Use --calendar with a --start-dt value. The first column of the data file has to be a date in yyyy-mm-dd form.
Why does termgraph output look wrong after copying it out of the terminal?
Colour charts use ANSI escape codes, and the documentation warns that these may not copy and paste from the terminal into other uses.
When was the latest termgraph release published?
Version 0.7.6 was published on 25 March 2026, and the default branch was last pushed on the same day. The two releases before it were 0.7.5 on 8 December 2025 and 0.7.4 on 27 October 2025.
Official sources
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.
[](https://hysenlabs.com/projects/mkaz-termgraph)