TERMINAL-NATIVE CHARTS

Recharts for
your terminal

Sparklines, line, bar, scatter, candlestick. Composable API, deterministic snapshots, zero deps.

bun add @crafter/charts v0.2.1 · <50KB · 15 chart types · TypeScript
METRICS
cpu
▄▅▆▇███▇▆▅▃▂▁   ▁▂
mem
 ▁▁▂▃▃▄▄▅▅▆▆▆▇▇▇██
err
▂▂▁▂▁▁ ▂▂███  ▁▂ ▂
OHLC
    120┤            ██
    115┤         ██ ██
    110┤    ██ ██  
    105┤██ ██ ██     
    100┤██                
REVENUE
⡔⠉⠉⠢⡀⡰⠉    ⠑⢄    
     60┤      ⠈⢆⠢⢄      ⢀⡠⠔
     40┤  ⠱⡀    ⡠⠃ ⠘⠤⣀⡠⠔⠁   
         rev   cos
SYSTEM
CPU  ████░░░░░░ 38%
MEM  ██████░░░░ 62%
DISK ████████░░ 84%

●●●○○○○○ 38%
●●●●●○○○ 62%
●●●●●●●○ 84%

Install

bun add @crafter/charts
import { plot, chart, renderToAnsi, sparkline } from "@crafter/charts";

// One-liner — just pass an array
console.log(plot([1, 5, 3, 7, 2, 8, 6, 9, 4, 10]));

// Multi-series
console.log(plot([prices, volumes], { height: 12 }));

// Full control
const c = chart({ width: 60, height: 14, charset: "braille" })
  .data(rows, { xKey: "x" })
  .yAxis({ format: v => "$" + v.toFixed(0) })
  .yDomain([0, 200])
  .line({ key: "price", color: "green", label: "Price" });

console.log(renderToAnsi(c));

Examples

PLOT()one array in, chart out
plot([sin, cos], { height: 10 })⣀⠤⠒⠊⠉⠉⠉⠉⠑⠢⢄                                       ⣀⠤⠒⠉⠉⢀⠤⠊           ⠉⠢⡀                                 ⡠⠒⠉     
     80┤  ⢀⠔⠁               ⠈⠒⢄                             ⡠⠊⢀⠔⠁                    ⠑⡄                         ⡠⠊                       ⠈⠢⢄                     ⡠⠊            
     60┤                           ⠑⢄                ⢀⠤⠊⠉⠢⡀           ⣀⠔⠁⠉⠒⠢⢄                      ⣀⠤⠒⠊⠉⠒⠤⡀⢄⣀⣀⣀⣀⣀⡠⠔⠊             ⣀⠔⠊⠉⠉⠒
     40┤    ⠑⠢⢄                ⢀⠔⠉       ⠈⠑⠤⡀                ⢀⠔⠉⠣⡀            ⢀⠔⠁            ⠈⠢⡀            ⢀⠔⠁⠈⠢⣀        ⢀⠔⠁                ⠈⠢⣀        ⡠⠔⠁⠑⠢⢄⣀⣀⣀⠤⠒⠁                     ⠑⠢⢄⣀⣀⣀⠤⠊             
        ┴───────────────┴──────────────┴───────────────┴──────────────
        0              10             20              30              
         revenue   costs                                            
SPARKLINES6 inline variants
line       ▅▆▇████▇▇▆▅▃▃▂▂▁▁     ▁▁▂▃▅▅▅▆▆▆▆▅▅▅
column     ▄▆▇████▆▅▅▇████▇▅▄▆▇███
win/loss   
bar 90%     90%
bar 45%     45%
bar 15%     15%
AREAmulti-line, filled
  ▂▄▆▇██▇▅▃▁               ▁▄▆▇██▇▆▄▁             
▄▇██████████▆▃          ▁▄▇██████████▆▃           
███████████████▅▃▁   ▂▄▆████████████████▅▃▁   ▁▃▆█
                 ▁▃▄▅▆▇█████▇▆▅▄▃▁                
            ▂▃▅▆███████████████████▆▅▃▂           
  ▁▁▂▂▃▄▅▆▇█████████████████████████████▇▆▅▄▃▂▂▁▁ 
                                     ▂▃▄▆▇▇████▇▇▆
                   ▁▃▄▅▆▇▇▇▆▆▆▅▅▅▅▆▇██████████████
 ▁▃▄▅▅▅▅▅▅▄▄▄▄▄▅▆▇████████████████████████████████
BOX CHARSETclassic ╭╮╰╯─│
╭─────╮╭──╯     ╰╮╭─╯         ╰─╮                   
     60┤  ╭╯             ╰╮──╯               ╰─╮╰╮               
     40┤                     ╰─╮            ╰╮          ╭╯╰─╮     ╭──╯╰─────╯    
LINE CHARTbraille, 4x sub-pixel
⢀⠤⠒⠊⠉⠉⠒⠢⢄
     80┤      ⢀⠔⠁       ⠈⠢⡀⡠⠃           ⠈⠢⡀⢀⠜               ⠱⡀⢠⠃                 ⠘⢄
     60┤ ⢠⠃                                               ⡰⠁                                               ⠱⡀                      
     40┤                          ⠱⡀                   ⢀⠎⠑⡄                 ⡰⠁⠈⢢               ⠑⡄           ⢀⠎
     20┤                               ⠈⠢⡀       ⢀⡠⠃⠈⠑⠢⢄⣀⣀⡠⠒⠁
        ┴────────────┴────────────┴────────────┴────────────
        0           10           20           30
BAR CHARTvertical
    500┤                                █████████████████████         ███████
    400┤                ███████         ██████████████ ███████ ███████ ██████████████ ███████ ███████ ███████
    300┤                ███████ ███████ ███████ ██████████████ ███████ ███████ ███████ ██████████████ ███████ ███████ ███████ ███████
    200┤        ███████ ███████ ███████ ███████ ██████████████ ███████ ███████ ███████ ███████ ███████
FIXED DOMAIN.yDomain([0, 25])
     25┤
       │
     20┤
       │
     15┤   ⣀⠤⠔⠊⠉⠉⠉⠉⠑⠢⠤⡀                     ⢀⠤⠒⠊⠉⠉
     10┤⣀⠔⠉           ⠈⠒⢄                ⢀⠤⠒⠁⠉⠢⣀           ⣀⠔⠁
      5┤                    ⠉⠒⠢⢄⣀⣀⣀⡠⠔⠊⠉
       │
      0┤
SCATTERbraille 8x resolution
                                        ⠄⠠                                          
     80┤                                               
     60┤                                                                         
     40┤                                              
CANDLESTICKOHLC, green/red

    130┤                                                ████ ████  ████     ████ ████      ████ ████   
    120┤                   ████ ████ ████ ████      ████ ████     ████ ████       ████     ████ ████   ████ ████   
    110┤████ ████
HEATMAPcommit activity
   M T W T F S S 
W1 ░░░░▓▓██▒▒▒▒▒▒
W2 ▒▒░░██▒▒░░▒▒  
W3 ░░░░▒▒██▒▒▒▒▒▒
W4   ▒▒▓▓▒▒▒▒░░▒▒
HISTOGRAMdistribution
░░░░░░░░░░░░░░░░░░░░░██████░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░█████████░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░███████████████░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░██████████████████░░░░░░░░░░░░
░░░░░░░░░░░░█████████████████████░░░░░░░░░░░░
░░░░░░░░░░░░█████████████████████░░░░░░░░░░░░
░░░░░░░░░██████████████████████████████░░░░░░
█████████████████████████████████████████████
6──────────────────────────────────────────92
GAUGE + DONUTauto-color by threshold
CPU   ██████░░░░░░░░░░░░░░ 23%
MEM   ██████████████░░░░░░ 67%
DISK  ██████████████████░░ 91%

CPU   ●●○○○○○○ 23%
MEM   ●●●●●○○○ 67%
DISK  ●●●●●●●○ 91%

API

plot(data, opts?)

One array in, chart out. Multi-series, domain control, auto-everything.

plot([1, 5, 3, 7, 2, 8])  // one array, done
plot([sin, cos], { height: 12 })  // multi-series
plot(data, { min: 0, max: 100 })  // fixed domain

sparkline / sparkColumn / sparkBar / sparkWinLoss / sparkArea

6 inline variants. Line, column (with negatives), progress bar, win/loss, area (multi-line).

sparkline([1, 5, 3, 7], { color: "green" })
sparkColumn([5, -3, 7, -1], { color: "blue", negColor: "red" })
sparkBar(75, 100, { width: 20, showPercent: true })
sparkWinLoss([1, -1, 1, 1, -1])
sparkArea(data, { width: 40, color: "cyan" })

chart(opts?)

Full builder. Chain .data(), .line(), .bar(), .scatter(), .candlestick(), .yDomain(), .xAxis(), .yAxis().

chart({ width: 60, height: 14, charset: "box" })
  .data(rows, { xKey: "ts" })
  .yAxis({ format: v => "$" + v })
  .yDomain([0, 200])
  .line({ key: "price", color: "green", label: "Price" })

renderToAnsi / renderToString / renderToHtml

Three output targets. ANSI for terminal, string for CI snapshots, HTML for web.

charset: "braille" | "box" | "ascii" | "block"

Braille = 8x sub-pixel. Box = classic ╭╮╰╯─│ look. ASCII = max compatibility.

.yDomain([min, max])

Fix the y-axis scale. Essential for dashboards with multiple charts that share a range.

Built for the agent era

0

Zero dependencies

No runtime deps. Works with Bun and Node.

<50KB

Tiny footprint

Entire library under 50KB published.

TS

TypeScript strict

Fully typed. No any.

=

Deterministic

renderToString() is byte-stable. Use with toMatchSnapshot().

Braille rendering

4x2 sub-pixel per character. 8x resolution vs ASCII.

Auto-sized

Detects terminal width. Responsive by default.