Chartli — CLI для графиков в терминале из обычных чисел

· 6 мин чтения
cli terminal typescript visualization skills
📂 Исходный код на GitHub

CLI для отрисовки графиков в терминале по числовым текстовым данным. Поддерживает восемь типов графиков (ascii, spark, bars, columns, heatmap, unicode, braille, svg), подписи осей и режим чтения из stdin. Содержит скилл для установки в ИИ-агентов.

Chartli — CLI для графиков в терминале из обычных чисел

Есть класс задач, где ИИ-агенту нужно не прочитать числа, а увидеть их: сравнить два ряда, найти пик, увидеть, как распределены значения. Обычно для этого приходится открывать браузер, звать Python и строить картинку. Chartli решает задачу заметно проще: это CLI на TypeScript, который превращает текстовый файл с числами в график прямо в терминале.

Работает без установки через npx, распространяется через npm, собирается на tsup. В репозитории лежит готовый скилл для агентов, который добавляется одной командой npx skills add ahmadawais/chartli.

Зачем это нужно агенту

Агент, который получил отчёт о метриках, обычно распечатывает сырые числа: 42, 58, 91, 87. В такой строке шука не разглядеть. Chartli даёт то же самое в виде ASCII-графика, и агент может положить его прямо в свой ответ в чате — без картинок, без браузера, без Python-окружения.

Набор из восьми типов графиков покрывает почти все типовые случаи: линия, спарклайн, горизонтальные полосы, вертикальные столбцы, тепловая карта, unicode-полосы, шрифт Брайля и SVG для экспорта.

Установка

Мгновенный запуск без установки:

npx chartli --help

Глобальная установка:

npm i -g chartli

Скилл для ИИ-агентов:

npx skills add ahmadawais/chartli

Файл с описанием скилла лежит в репозитории: skills/chartli/SKILL.md.

Формат входных данных

На входе — текстовый файл с числами, разделёнными пробелами или табами. Первая строка может быть заголовком:

day sales costs profit
1 10 8 2
2 14 9 5
3 12 11 3

Файл не обязателен. Если путь не передан, chartli читает данные из stdin:

printf 'x y\n1 10\n2 20\n3 15\n' | npx chartli -t ascii -w 24 -h 8

Пример файла с данными можно посмотреть в репозитории: examples/assets/image-data.txt.

Типы графиков

Тип Ключ Что рисует
ASCII-линия ascii График из символов с осями и точками
Спарклайн spark Компактные полоски в несколько символов, одна на ряд
Горизонтальные полосы bars Полосы в строки со значением справа
Столбцы columns Вертикальные столбцы из блоков
Тепловая карта heatmap Сетка символов, где плотность символа кодирует значение
Unicode-полосы unicode Столбцы из символов восходящей плотности
Шрифт Брайля braille Плотная картинка точками Braille-паттернов
SVG svg Настоящий векторный файл

Тип задаётся ключом -t (или --type), по умолчанию используется ascii.

Управление выводом

Полный список ключей выглядит так:

Usage: chartli [options] [file]

Render terminal charts from numeric data

Arguments:
  file                   Input file (reads from stdin if not provided)

Options:
  -v, --version          Output the version number
  -t, --type <type>      Chart type: svg, ascii, unicode, braille, spark, bars,
                         columns, heatmap (default: "ascii")
  -w, --width <number>   Chart width
  -h, --height <number>  Chart height
  -m, --mode <mode>      SVG mode: circles or lines (default: "circles")
  --x-axis-label <label> Title to render for the x-axis
  --y-axis-label <label> Title to render for the y-axis
  --x-labels <labels>    Comma-separated labels for x-axis ticks or row labels
  --series-labels <labels>
                         Comma-separated labels for plotted series or categories
  --data-labels          Show raw values near plotted data when supported
  --first-column-x       Treat the first numeric column as x labels instead of a
                         plotted series
  --help                 Display help for command

Ширина и высота задаются в символах, а не в пикселях. Для SVG размер задаётся в тех же единицах, но результат удобно выгружать в файл.

Подписи осей и значения

Без дополнительных ключей график выглядит технически, но понятно. Чтобы получить «человеческий» вид, есть несколько флагов:

  • --x-axis-label и --y-axis-label — заголовки осей
  • --x-labels — явные метки делений оси X, перечисленные через запятую
  • --series-labels — заменяют служебные имена вроде S1 и C1 на свои
  • --data-labels — печатает исходное значение рядом с точкой там, где это поддерживается
  • --first-column-x — первая числовая колонка становится метками оси X, а не отдельным рядом

Ключ --first-column-x удобен, когда в первой колонке лежит домен вроде дня, месяца или года. Тогда chartli сам подхватывает заголовки: первая ячейка шапки становится заголовком оси X, остальные — именами рядов, а для двухколоночных данных вторая ячейка становится заголовком оси Y.

npx chartli examples/assets/weekly-signups.txt -t ascii -w 28 -h 8 --first-column-x --data-labels
        signups
    91 │                      ●   87
       │                     91    ●
       │            73
       │             ●   68
  66.5 │   58             ●
       │    ●   49
       │42       ●
    42 │●
       └────────────────────────────
        1   2    3   4   5   6    7
                    day

Примеры таких файлов: weekly-signups.txt и weekly-metrics.txt.

Несколько типов на одних и тех же данных

Один и тот же файл с четырьмя колонками (day, sales, costs, profit) даёт разные картинки в зависимости от типа:

Спарклайны:

day    ▁▂▃▄▅▆
sales  ▁▄▂▇▅█
costs  ▁▂▄▃▆▅
profit ▁▄▂▇▂▇

Горизонтальные полосы:

day    |███████████████████         | 0.67
sales  |▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓| 1.00
costs  |▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒             | 0.53
profit |░░░░░░░░░░░░░░░░░░░░░░░     | 0.83

Столбцы:

         ▓             ░
         ▓             ░
  █      ▓             ░
  █      ▓      ▒      ░
  █      ▓      ▒      ░
  █      ▓      ▒      ░
  █      ▓      ▒      ░
───────────────────────────
 day   sales  costs  profit

Тепловая карта:

    day sales costs profit
R01
R02 ░ ▒ ░ ▒
R03 ░ ░ ▒ ░
R04 ▒ ▓ ░ ▓
R05 ▒ ▒ ▓ ░
R06 ▓ █ ▒ ▓

Экспорт в SVG

Для отчётов и документации есть режим svg. В нём два варианта отрисовки точек: круги (--mode circles, по умолчанию) и линии (--mode lines). Вывод идёт в stdout, поэтому сохранить его можно обычным перенаправлением:

npx chartli examples/assets/image-data.txt -t svg -m lines -w 320 -h 120 \
  | sed -n '/^<?xml/,$p' > output.svg

Результат — обычный SVG с полилиниями:

<?xml version='1.0'?>
<svg xmlns='http://www.w3.org/2000/svg' width='650' height='120' version='1.1'>
  <polyline ... />
  <polyline ... />
  <polyline ... />
  <polyline ... />
</svg>

Скилл для агентов

В репозитории есть каталог skills/ с готовым описанием навыка. После установки агент получает готовые шаблоны команд, список поддерживаемых типов и описание формата входных данных. Для агента это удобно: он не придумывает параметры, а берёт их из скилла.

Шаблон вызова из скилла выглядит так:

npx chartli <file> -t <type> [--width N] [--height N] [--mode circles|lines] \
  [--x-axis-label LABEL] [--y-axis-label LABEL] [--x-labels a,b,c] \
  [--series-labels foo,bar] [--data-labels] [--first-column-x]

В репозитории есть набор готовых примеров, которые запускаются скриптами из package.json — например, pnpm run example:all-kitchen-sink прогоняет все типы на всех наборах данных. Полный список файлов с данными: examples/assets/.

Технические детали

  • Язык: TypeScript, сборка через tsup, бинарник chartli
  • Зависимости: commander (разбор ключей), zod (валидация), ora и @clack/prompts (интерактивные элементы), picocolors (цвета)
  • Тесты: vitest, линтер: biome
  • Версия на момент публикации: 1.0.0

О лицензии стоит сказать прямо: README заявляет Apache-2.0, но файла LICENSE в репозитории нет, и в package.json поле license тоже не заполнено. Если лицензия критична для вашего проекта, уточните это у автора — проект делал Ахмад Авайс (Ahmad Awais) с использованием Command Code.

Источник: https://github.com/ahmadawais/chartli