Terminal plotting in Python using Unicode Braille characters, block elements, or ASCII. Zero dependencies. Designed for CLI workflows and AI coding assistants like Claude Code.
Inspired by the R plotcli package and Julia's UnicodePlots.jl.
# With uv (recommended)
uv tool install plotcli
# With pip
pip install plotcli
# Or run directly without installing
uvx plotcli fn "sin(x)" 0 6.28# Pipe data
echo "1 4 9 16 25 36 49 64 81 100" | plotcli line
# Plot a math function
plotcli fn "sin(x)" 0 6.28
# From a Python expression
plotcli scatter -e "[(x, x**2) for x in range(50)]"
# From a CSV file
plotcli line -f data.csv -x time -y value
# Pipe from other commands
seq 100 | awk '{print sin($1/10)}' | plotcli lineecho "1 4 9 16 25 36 49 64 81 100" | plotcli line --title "Squares" Squares
┌───────────────────────────────────────────────────────┐
100 ┤ ⢀⠤⠊│
│ ⡠⠒⠁ │
80.2 ┤ ⡠⠔⠉ │
│ ⡠⠔⠉ │
60.4 ┤ ⢀⡠⠔⠉ │
│ ⣀⠤⠒⠁ │
y │ ⢀⡠⠔⠊ │
40.6 ┤ ⣀⠤⠔⠊⠁ │
│ ⣀⠤⠒⠉ │
20.8 ┤ ⣀⡠⠤⠒⠊⠉ │
│ ⢀⣀⡠⠤⠔⠒⠊⠉ │
1 ┤⣀⣀⣀⡠⠤⠤⠤⠔⠒⠊⠉⠁ │
└───────────────────────────────────────────────────────┘
0 2.25 4.5 6.75 9
x
plotcli fn "sin(x)" 0 6.28 --title "Sine Wave" Sine Wave
┌───────────────────────────────────────────────────────┐
1 ┤ ⣀⠴⠒⠋⠉⠉⠙⠒⠤⣀ │
│ ⢀⡴⠋⠁ ⠈⠳⢄ │
0.6 ┤ ⢀⡤⠋ ⠑⣄ │
│ ⢠⠊ ⠈⠱⡄ │
f 0.2 ┤ ⢀⠜⠁ ⠘⢆ │
( │⢠⠊ ⠱⡄ │
x │⠁ ⠘⢆ ⣠⠋│
) -0.2 ┤ ⠱⡄ ⡔⠁ │
│ ⠈⢆⡀ ⡠⠋ │
-0.6 ┤ ⠙⢄ ⣠⠚⠁ │
│ ⠑⢦⡀ ⢀⣠⠞⠁ │
-1 ┤ ⠉⠒⠤⣄⣀⣀⣠⠤⠖⠋ │
└───────────────────────────────────────────────────────┘
0 1.57 3.14 4.71 6.28
x
Built-in math: sin, cos, tan, sqrt, log, exp, pi, e, and Python's math module.
plotcli fn "exp(-x/5) * cos(x*2)" 0 15 --title "Damped Oscillation"
plotcli fn "x**3 - 3*x" -3 3 --title "Cubic"
plotcli fn "log(x)" 0.1 10 --title "Logarithm"plotcli hist -e "[random.gauss(0,1) for _ in range(500)]" --title "Normal Distribution" Normal Distribution
┌───────────────────────────────────────────────────────┐
62 ┤ ⣿⡇ │
│ ⣿⡇⢸⣿ │
49.6 ┤ ⢰⣶ ⣿⡇⢸⣿ ⣿⡇⢰⣶ │
│ ⢸⣿ ⣿⡇⢸⣿ ⣿⡇⢸⣿ │
c 37.2 ┤ ⢸⣿ ⢰⣶ ⣿⡇⢸⣿ ⣿⡇⢸⣿ │
o │ ⣀⡀⢸⣿ ⢸⣿ ⣿⡇⢸⣿ ⣿⡇⢸⣿ │
u │ ⢰⣶ ⣿⡇⢸⣿ ⢸⣿ ⣿⡇⢸⣿ ⣿⡇⢸⣿ │
n 24.8 ┤ ⢸⣿ ⣿⡇⢸⣿ ⢸⣿ ⣿⡇⢸⣿ ⣿⡇⢸⣿ ⣀⡀ ⣤⡄ │
t │ ⣶⡆⢸⣿ ⣿⡇⢸⣿ ⢸⣿ ⣿⡇⢸⣿ ⣿⡇⢸⣿ ⣿⡇ ⣿⡇ │
12.4 ┤ ⢰⣶ ⣿⡇⢸⣿ ⣿⡇⢸⣿ ⢸⣿ ⣿⡇⢸⣿ ⣿⡇⢸⣿ ⣿⡇ ⣿⡇⢠⣤ ⣶⡆ │
│ ⣀⡀⢸⣿ ⢠⣤ ⣿⡇⢸⣿ ⣿⡇⢸⣿ ⢸⣿ ⣿⡇⢸⣿ ⣿⡇⢸⣿ ⣿⡇ ⣿⡇⢸⣿ ⣿⡇⢠⣤ ⣤⡄ │
0 ┤⣶ ⣿⡇⢸⣿ ⢸⣿ ⣿⡇⢸⣿ ⣿⡇⢸⣿ ⢸⣿ ⣿⡇⢸⣿ ⣿⡇⢸⣿ ⣿⡇ ⣿⡇⢸⣿ ⣿⡇⢸⣿ ⣿⡇ ⣀⡀⢀⣀ ⣶│
└───────────────────────────────────────────────────────┘
-2.48 -1.06 0.36 1.78 3.2
x
plotcli density -e "[random.gauss(0,1) for _ in range(1000)]" --title "Kernel Density" Kernel Density
┌───────────────────────────────────────────────────────┐
0.38 ┤ ⢀⠤⠒⠊⠉⠉⠢⢄ │
│ ⢰⠁ ⢣ │
0.3 ┤ ⢠⠃ ⢣ │
d │ ⡎ ⢣ │
e 0.23 ┤ ⡜ ⢣ │
n │ ⡰⠁ ⠑⡄ │
s │ ⢀⠎ ⠘⡄ │
i 0.15 ┤ ⢀⠎ ⠱⡀ │
t │ ⢀⠎ ⢣ │
y 0.08 ┤ ⢠⠊ ⠱⡀ │
│ ⢀⠤⠒⠁ ⠈⠑⠤⡀ │
1.7e-05 ┤⣀⣀⣀⣀⣀⣀⣀⡠⠤⠔⠊⠁ ⠈⠑⠢⠤⠤⢄⣀⣀⣀⣀⣀⣀│
└───────────────────────────────────────────────────────┘
-4.01 -2.01 -0.02 1.97 3.96
x
plotcli boxplot \
-e "[[random.gauss(m, 1+i*0.3) for _ in range(100)] for i, m in enumerate([0, 3, 7])]" \
--title "Boxplots" Boxplots
┌───────────────────────────────────────────────────────┐
10.45 ┤ ⠈⠉⢹⠉⠉ │
│ ⢸ │
7.83 ┤ ⡖⠒⠒⠒⠚⠒⠒⠒⠒⡆ │
│ ⢀ ⡏⠉⠉⠉⠉⠉⠉⠉⠉⡇ │
v 5.22 ┤ ⠐⠒⢲⠒⠒ ⠉⠉⠉⠉⢹⠉⠉⠉⠉⠁ │
a │ ⢸ ⢸ │
l │ ⣖⣒⣒⣒⣚⣒⣒⣒⣒⡆ ⢀⣀⣸⣀⣀ │
u 2.6 ┤ ⠒⠒⡖⠒⠂ ⠧⠤⠤⠤⢤⠤⠤⠤⠤⠇ ⠐ │
e │ ⢀⣀⣀⣀⣀⣇⣀⣀⣀⣀ ⢸ │
-0.02 ┤ ⢸⣒⣒⣒⣒⣒⣒⣒⣒⣺ ⠐⠒⠚⠒⠒ │
│ ⡇ │
-2.63 ┤ ⠉⠉⡉⠉⠁ │
└───────────────────────────────────────────────────────┘
box_1 box_2 box_3
x
plotcli scatter \
-e "[(x, x**1.5 + random.gauss(0,5)) for x in range(40)]" \
--title "Noisy Power Law"plotcli heatmap \
-e "[[math.sin(r/3+c/3) for c in range(20)] for r in range(10)]" \
--title "Heatmap"Three rendering backends with different resolution/compatibility tradeoffs:
plotcli fn "sin(x)" 0 6.28 --canvas brailleUses Unicode Braille patterns (U+2800-U+28FF). Each character cell contains a 2x4 dot grid, giving 8x the effective resolution of ASCII.
plotcli fn "sin(x)" 0 6.28 --canvas block Block Canvas
┌───────────────────────────────────────────────────────┐
1 ┤ ▄▄█▀▀▀▀█▄▄ │
│ ▄█▀ ▀▀▄ │
0.6 ┤ ▄▀▀ █▄ │
│ ▄█▀ █▄ │
f 0.2 ┤ █▀ ▀█▄ │
( │▄█ █▄ │
x │▀ ▀█ █▀│
) -0.2 ┤ █▄ ▄█ │
│ ▀█ ▄█▀ │
-0.6 ┤ ▀█ ▄▄▀ │
│ ▀█▄ ▄█▀ │
-1 ┤ ▀▀█▄▄▄▄█▀▀ │
└───────────────────────────────────────────────────────┘
Uses half-block characters (▀ ▄ █) for 2x vertical resolution.
plotcli fn "sin(x)" 0 6.28 --canvas ascii ASCII Canvas
┌───────────────────────────────────────────────────────┐
1 ┤ ******** │
│ **** **** │
0.6 ┤ *** *** │
│ *** *** │
f 0.2 ┤ ** ** │
( │** ** │
x │* ** **│
) -0.2 ┤ ** ** │
│ *** *** │
-0.6 ┤ *** *** │
│ **** **** │
-1 ┤ ******** │
└───────────────────────────────────────────────────────┘
Works in any terminal. Uses * for data points.
| Method | Example |
|---|---|
| Pipe values | echo "1 4 9 16" | plotcli line |
| Pipe lines | seq 50 | plotcli line |
| x,y pairs | echo -e "1,2\n3,4\n5,6" | plotcli scatter -d "," |
| Expression | plotcli line -e "[x**2 for x in range(20)]" |
| Tuple list | plotcli scatter -e "[(x, sin(x)) for x in range(50)]" |
| CSV file | plotcli line -f data.csv -x time -y price |
| JSON | echo '[1,4,9,16]' | plotcli line -j |
| Math function | plotcli fn "sin(x)*exp(-x/5)" 0 20 |
| Shell pipeline | curl -s api | jq '.[].value' | plotcli line |
-W, --width Canvas width in characters (auto-detected)
-H, --height Canvas height in characters (auto-detected)
-t, --title Plot title
--x-label X-axis label
--y-label Y-axis label
-c, --color Series color (red, green, blue, yellow, magenta, cyan, ...)
--canvas braille (default), block, or ascii
--xlim MIN MAX X-axis limits
--ylim MIN MAX Y-axis limits
--bins N Number of histogram bins
--no-legend Hide legend
-d, --delimiter Input delimiter
-j, --json Parse stdin as JSON
-e, --eval Python expression for data
-f, --file CSV/TSV file path
-x, --x-col X column name or index
-y, --y-col Y column name or index
plotcli is designed for AI-assisted CLI workflows. Claude Code can generate and display plots inline:
> Plot a sine wave
$ plotcli fn "sin(x)" 0 6.28 --title "Sine Wave"
> Show me the distribution of file sizes in this directory
$ find . -type f -exec stat -f%z {} \; | plotcli hist --title "File Sizes" --bins 20
> Visualize the CSV data
$ plotcli scatter -f measurements.csv -x temperature -y pressure --title "T vs P"
To make plotcli available globally for Claude Code:
uv tool install plotcli # install globally via uv
# or
pip install plotcli # install globally via pipimport plotcli
# Quick one-liners
plotcli.line(range(10), [x**2 for x in range(10)], title="Squares").show()
plotcli.scatter(xs, ys, title="My Data", canvas_type="braille").show()
plotcli.histogram(data, bins=20, title="Distribution").show()
plotcli.density(data, title="KDE").show()
plotcli.boxplot([group_a, group_b], names=["A", "B"]).show()
plotcli.function_plot("sin(x)*x", 0, 10).show()
# Multi-series
from plotcli import Plot
p = Plot(title="Comparison", width=60, height=15)
p.add(x1, y1, "line", color="blue", name="model")
p.add(x2, y2, "scatter", color="red", name="data")
p.show()
# Get string output (no print)
output = p.render()LGPL-3.0 (same as the original R plotcli)
Python port inspired by plotcli by Claas Heuer, which was in turn inspired by UnicodePlots.jl.