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.