GrafExTerm

A terminal UI for Grafana dashboards, built on Drafter.

GrafExTerm reads Grafana dashboard JSON directly — no Grafana server required at runtime for layout — and queries your Prometheus (and Loki, for logs panels) datasources live. It renders panels as interactive terminal widgets: tables with sortable/resizable columns, timeseries charts, heatmaps, pie charts, bar gauges, logs, stat panels with sparkline backgrounds, gauges, and more.

Work in progress. Core functionality is stable; some panel types and Grafana features are not yet implemented.

Features

Panel support

Grafana type Status
table Full — instant queries, organize transform, color rules, column management
stat Full — threshold color, unit formatting, sparkline background
timeseries / graph Full — multi-series, axes, percent scaling, value readout
gauge Rendered
bargauge One meter per series, reduceOptions.calcs, min/max, threshold colours
piechart One slice per series, reduceOptions.calcs, legend and percentages
heatmap Prometheus histogram buckets (le) de-accumulated per bucket, or one row per series
logs Loki query_range, showTime, wrapLogMessage, maxDataPoints as the line limit
row Collapsible section headers
Others Placeholder shown

Requirements

Installation

Add GrafExTerm to a project:

def deps do
  [
    {:graf_ex_term, "~> 0.1"}
  ]
end

Or run it from a clone:

git clone https://github.com/jaman/graf_ex_term
cd graf_ex_term
mix deps.get
mix graf_ex_term

When a drafter checkout sits next to graf_ex_term, it is used in place of the Hex package.

Try it without Prometheus

mix graf_ex_term.demo

Opens the showcase dashboard, which uses every panel type GrafExTerm draws, on generated data. Nothing is read from or written to your saved dashboard list. Any dashboard can use the generator by pointing a datasource at %{type: :demo}; see GrafExTerm.Datasource.Demo for the metric names it answers.

Configuration

config/config.exs:

config :graf_ex_term,
  theme: "tokyo-night",   # any Drafter theme name
  height_ratio: 3         # terminal rows per Grafana grid unit

config/runtime.exs reads these environment variables:

Variable Setting Default
PROMETHEUS default Prometheus URL http://localhost:9090
LOKI default Loki URL for logs panels http://localhost:3100
GRAF_EX_TERM_THEME Drafter theme gruvbox-dark
GRAF_EX_TERM_HEIGHT_RATIO terminal rows per Grafana grid unit 3
GRAF_EX_TERM_REFRESH_MS refresh interval when the dashboard sets none 30000
GRAF_EX_TERM_TIME_RANGE seconds of history shown, overriding the dashboard's own time range the dashboard's time, else 3600
GRAF_EX_TERM_CHART_RESOLUTION samples per panel before the terminal width is known 300
GRAF_EX_TERM_STAT_FONTS fonts for stat numbers, largest first, comma separated; the first that fits the panel is used. Built-in: block, compact, tall, pixel, braille; bundled FIGlet: banner, big, blocks, bubble, digital, ivrit, lean, mini, script, shadow, slant, small, smscript, standard, term braille,mini,compact
GRAF_EX_TERM_RENDERER chart renderer: text, braille, half, quad, sextant, octant, auto, pixel, kitty, iterm2, sixel Drafter's choice (text)

:max_concurrent_queries (default 8) and :query_timeout_ms (default 30000) bound the scheduler's parallel panel queries.

Adding dashboards

  1. Export your Grafana dashboard as JSON (Dashboard settings → JSON model).
  2. Save it locally or host it at an HTTP URL.
  3. Press a in GrafExTerm and enter the path or URL:
    • Local file: file:///path/to/dashboard.json
    • HTTP: http://grafana.internal/api/dashboards/uid/abc123
  4. If the dashboard uses named datasource variables (e.g. DS_PROMETHEUS), you will be prompted to map them to actual Prometheus URLs.

Dashboard list and datasource mappings are saved to ~/.config/graf_ex_term/dashboards.json.

Usage

Global keys

Key Action
Tab / Shift+Tab Move focus between panels
a Add a dashboard
f Toggle the per-column table selector
b Hide or show the dashboard list
r Force-refresh the active dashboard
q Quit

Tables

Action Effect
↑ / ↓ Navigate rows
Enter or click row Select/deselect row (toggles)
Space Toggle selection on highlighted row
Select multiple rows Charts filter to union of matching series
Deselect all Charts return to full view
Click column header Sort ascending → descending → unsorted
+ / - Resize focused column
Shift+← / Shift+→ Reorder focused column
Expand Columns section Toggle individual column visibility

Column visibility, widths, and column order are saved automatically and restored on next launch.

Charts

Click a timeseries chart (or hover over it, in apps with hover enabled) to place a cursor: the column is highlighted and the title row shows the sample time and each series' value there. Esc hides it. With GRAF_EX_TERM_RENDERER=auto charts are drawn as images on terminals that support kitty, iTerm2 or sixel graphics, with the axes and title drawn as text around them.

Stat panels

Panels configured with graphMode: area in Grafana show the metric's recent history as a braille sparkline rendered behind the large number. The sparkline and number color both reflect the active threshold.

Architecture

GrafExTerm
├── Dashboard
│   ├── Loader       — fetch JSON from file:// or http://
│   ├── Parser       — Grafana JSON → typed structs
│   ├── Store        — GenServer; persists dashboard list and per-panel settings
│   └── Types        — Panel, Target, GridPos, etc.
├── Datasource
│   ├── Prometheus   — query/4, instant_query/3
│   └── Loki         — query/4 for logs panels
├── Refresh
│   ├── Scheduler    — per-dashboard GenServer; concurrent, incremental fetches
│   ├── QueryWindow  — per-panel from/to/step sized to the panel's width
│   ├── SeriesWindow — appends a fetched tail to held series
│   └── DataCache    — version-stamped cache for poll-based diffing
├── Variable
│   ├── Manager      — resolves Grafana template variables
│   └── Substitution — interpolates $var / ${var} in query expressions
├── Panel
│   ├── Renderer     — dispatches to type-specific renderers
│   ├── Table        — prepare/3, render/5; organize transform, color rules
│   ├── Stat         — threshold color, Format-based unit display, sparkline
│   ├── Prepare      — turns cached data into render-ready form once per arrival
│   ├── Timeseries   — multi-series chart, axis scaling, time labels
│   ├── Heatmap      — bucket matrix from histogram series
│   ├── Piechart / Bargauge / Logs
│   ├── Reduce       — Grafana reduceOptions.calcs
│   ├── ColorRules   — builds color_fn closures from fieldConfig
│   └── ...
├── Layout
│   └── GridMapper   — maps Grafana grid positions to Drafter layout tree
└── Screen
    └── Main         — top-level Drafter.App; state, event handling, rendering