12k
All articles

Является ли OpenTUI реальной альтернативой Ink?

OpenTUI против Ink: сравните скорость TUI, ограничения рантайма, встроенные компоненты и затраты на миграцию для потоковых CLI и дашбордов.

OpenReplay Team
OpenReplay Team
Является ли OpenTUI реальной альтернативой Ink?

OpenTUI — это реальная альтернатива Ink для терминальных интерфейсов, которые перерисовываются непрерывно: потоковый вывод агентов, просмотрщики логов, живые дашборды. Однако его требования к передовым версиям рантаймов и постоянная смена релизов в ветке 0.x делают Ink более безопасным выбором по умолчанию для CLI, который вы публикуете для обычных пользователей Node.

Если вы когда-нибудь наблюдали, как ваш собственный дашборд на Ink начинает подтормаживать под нагруженным потоком логов, вам уже понятно, почему люди ищут альтернативы. Именно этот разрыв и был призван закрыть OpenTUI.

Далее к обеим библиотекам применяются одни и те же критерии: где упирается в потолок рендерер Ink, что меняет архитектура OpenTUI, как выглядит один и тот же небольшой UI в каждой из них, какой продакшен-опыт заслужил OpenTUI и во что обойдётся переход с точки зрения рантайма, экосистемы и стабильности. В конце — рекомендация.

Ключевые выводы

  • OpenTUI рендерит через нативное ядро, написанное на Zig, доступное из TypeScript через FFI, с flexbox-раскладкой на Yoga и биндингами как для React, так и для Solid.
  • Ink по умолчанию ограничивает перерисовку до 30 fps, что настраивается через опцию рендеринга maxFps; цифра «32 FPS», которая гуляет по интернету, — это неверное прочтение интервала троттлинга в 32 миллисекунды в исходном коде Ink.
  • CLI на OpenTUI требует, чтобы каждый конечный пользователь запускал Bun 1.3+ или Node.js 26.4+ с экспериментальным флагом --experimental-ffi, и это ограничение на распространение, а не просто шаг локальной настройки.
  • OpenTUI рендерит терминальный интерфейс OpenCode в продакшене через свой Solid-реконсилятор, заменив реализацию на Go и Bubble Tea.
  • Линейка OpenTUI 0.5.x выпускает по несколько релизов в месяц, тогда как Ink меняется гораздо медленнее: его последний ломающий релиз, Ink 7, поднял минимальные требования до Node 22 и React 19.2, оставив API компонентов без изменений. У Ink также значительно более обширная экосистема сообщественных компонентов.

Где упирается в потолок рендерер Ink?

Потолок Ink — это его троттлинг рендеринга: по умолчанию он ограничивает перерисовку до 30 кадров в секунду, и любое обновление состояния сверх этого бюджета ждёт следующего кадра. Об основах Ink см. более ранний гайд по созданию терминальных интерфейсов с Node.js, который рекомендовал Ink в декабре 2025 года, до того как OpenTUI стал серьёзным вариантом; данная статья — обновление того вердикта.

Троттлинг задокументирован, это не фольклор. Исторически в Ink интервал троттлинга в 32 миллисекунды был жёстко прописан вокруг функции рендеринга — именно отсюда и растёт широко повторяемая цифра «ограничение в 32 FPS»: 32 — это интервал в миллисекундах, а вытекающая из него частота — потолок в 30 кадров в секунду. Текущий Ink выставляет это как опцию рендеринга maxFps со значением 30 по умолчанию, наряду с опцией incrementalRendering, которая ограничивает каждую перерисовку только изменившимися строками. То есть ограничение регулируемое. Что не регулируется — это архитектура: каждый кадр компонуется в JavaScript, диффится как строки и записывается в stdout тем же циклом событий, который выполняет логику вашего приложения.

Для спиннера, формы или прогресс-бара всё это незаметно. Заметным это становится при потоковом выводе: токены модели поступают быстрее бюджета кадра, просмотрщик логов следит за нагруженным сервисом, дашборд перерисовывает большие области. Есть ещё и порог по памяти. Процесс Ink несёт на себе рантайм Node плюс реконсилятор React ради, возможно, нескольких строк вывода; надёжных публичных измерений этих накладных расходов не существует, поэтому к любой конкретной цифре в мегабайтах, которую вы встретите, стоит относиться с недоверием.

Что добавляет OpenTUI?

OpenTUI полностью выносит рендеринг из JavaScript. Его ядро написано на Zig и нативно обрабатывает экранный буфер, отрисовку и парсинг ввода; TypeScript обращается к нему через FFI — bun:ffi в Bun или экспериментальный FFI в Node. Раскладка остаётся привычной: определение размеров и позиционирование выполняются через flexbox на базе Yoga, тот же движок, что использует Ink, поэтому flexDirection, flexGrow и им подобные переносятся напрямую.

Помимо рендерера значимы два дополнения. Во-первых, встроенные компоненты покрывают то, что Ink оставляет сторонним пакетам: фокусируемые Input и Textarea, Select, ScrollBox, подсветку синтаксиса на базе tree-sitter в Code, представление Diff и Markdown. Ещё два — текстовая таблица и встроенный терминал — существуют только как Core-renderables, поэтому React и Solid не могут обратиться к ним как к JSX-элементам. Во-вторых, выбор фреймворка: @opentui/react и @opentui/solid — оба полноценные биндинги, так что команды, предпочитающие мелкогранулярную реактивность для высокочастотных обновлений, не привязаны к реконсилятору React. Есть также интеграция с Three.js на WebGPU — курьёз для данного сравнения, к тому же доступный только в Bun.

Как выглядит один и тот же UI в Ink и OpenTUI?

Стоимость миграции проще всего увидеть, построив один интерфейс дважды: панель с рамкой, строка текста, клавиша, переключающая состояние, и корректный выход. Примеры ориентированы на Ink 7 и OpenTUI 0.5.x.

Ink, каркас через npx create-ink-app:

import React, { useState } from "react";
import { render, Box, Text, useApp, useInput } from "ink";

function App() {
  const [name, setName] = useState("world");
  const { exit } = useApp();

  useInput((input, key) => {
    if (key.escape) exit();
    if (input === "r") {
      setName((prev) => (prev === "world" ? "terminal" : "world"));
    }
  });

  return (
    <Box borderStyle="round" padding={1} flexDirection="column">
      <Text>Hello, {name}! Press r to toggle, Esc to quit.</Text>
    </Box>
  );
}

render(<App />);

OpenTUI, каркас через bun create tui --template react:

import { useState } from "react";
import { createCliRenderer } from "@opentui/core";
import { createRoot, useKeyboard, useRenderer } from "@opentui/react";

function App() {
  const [name, setName] = useState("world");
  const renderer = useRenderer();

  useKeyboard((key) => {
    if (key.name === "escape") renderer.destroy();
    if (key.name === "r") {
      setName((prev) => (prev === "world" ? "terminal" : "world"));
    }
  });

  return (
    <box style={{ border: true, padding: 1, flexDirection: "column" }}>
      <text>Hello, {name}! Press r to toggle, Esc to quit.</text>
    </box>
  );
}

const renderer = await createCliRenderer();
createRoot(renderer).render(<App />);

Разница между этими двумя примерами и есть руководство по миграции. Точка входа меняется с вызова render() в Ink на createCliRenderer() из @opentui/core плюс createRoot(renderer).render() из @opentui/react. Компоненты с заглавной буквы Box и Text становятся строчными интринсиками box и text, а имена элементов из более чем одного слова пишутся через дефис, как <ascii-font>. useInput и useApp из Ink отображаются на useKeyboard и renderer.destroy() в OpenTUI. Сам React переносится без изменений: и ink, и @opentui/react требуют React 19.2 или новее, а useState работает идентично. Модели фокуса различаются сильнее: Ink поставляет useFocus со встроенным перебором по Tab, тогда как OpenTUI выдаёт фокус через проп focused, которым вы управляете в состоянии.

Заслуга: OpenTUI рендерит OpenCode в продакшене

OpenTUI — не демо-проект. Он создан компанией Anomaly, стоящей за OpenCode, и README проекта заявляет OpenCode как продакшен-развёртывание, обслуживающее миллионы людей. Именно этот сценарий — агент для написания кода, отдающий потоком вывод модели, диффы и код с подсветкой синтаксиса в интерактивный терминал — как раз и есть та нагрузка, на которой проявляется троттлинг Ink. Родословная тоже важна: интерфейс OpenCode был переписан с Go и Bubble Tea на OpenTUI. Одна оговорка для пользователей React: TUI в OpenCode работает на реконсиляторе Solid, поэтому боевая обкатка в продакшене покрывает ядро и Solid-биндинг в большей степени, чем @opentui/react, который, в отличие от Core и Solid, не покрыт Node.js-веткой в CI.

Цена: churn, рантаймы и экосистема

Издержки сосредоточены в трёх местах, и та, что связана с рантаймом, — это проблема распространения, а не проблема опыта разработчика.

КритерийInk 7OpenTUI 0.5.x
РантаймNode 22+Bun 1.3+ или Node 26.4+ с --experimental-ffi, только ESM
РендерингJavaScript, 30 fps по умолчанию через maxFpsНативное ядро на Zig через FFI
РаскладкаYoga flexboxYoga flexbox
Встроенные компонентыBox, Text, Static; поля ввода через пакеты сообществаInput, Select, ScrollBox, Code, Diff, Markdown и другие
ФреймворкиReactReact и Solid
ЗрелостьМажорные версии с интервалом в годы; Ink 7 сломал только минимальные версии рантайма и события клавишПо несколько релизов в месяц в ветке 0.x

CLI на Ink работает везде, где работает Node 22 или новее. CLI на OpenTUI накладывает требование передовых версий на каждого конечного пользователя: согласно матрице поддержки рантаймов, это означает Bun 1.3.0+ или Node.js 26.4.0+ с экспериментальным флагом FFI, только ESM, а CommonJS-require падает сразу. Для инструмента, публикуемого в npm и устанавливаемого незнакомыми людьми, это либо сужает вашу аудиторию, либо толкает вас к распространению в виде скомпилированного бинарника.

Стабильность — вторая издержка. Страница релизов показывает выпуск версий с v0.4.4 по v0.5.8 примерно за шесть недель. В ветке 0.x такой темп означает закрепление версий и постоянное отслеживание changelog. API Ink, напротив, остаётся стабильным на протяжении лет и мажорных версий. Третье — экосистема: у пакетов сообщества, рецептов и ответов на Stack Overflow для Ink пока нет эквивалента для OpenTUI, хотя более богатый набор встроенных компонентов OpenTUI частично компенсирует этот разрыв. По отладке примерный паритет: обе поддерживают React DevTools с DEV=true, а OpenTUI добавляет консольный оверлей и диагностику рендеринга.

Стоит ли переходить с Ink на OpenTUI?

Переходите сейчас, если ваш TUI перерисовывается непрерывно и вы контролируете рантайм: внутренний фронтенд для агента, просмотрщик логов для вашей собственной команды, что-либо распространяемое как скомпилированный бинарник, где требование Bun растворяется в сборке. Ядро на Zig, компоненты Code и Diff и возможность выбрать Solid — здесь это настоящие преимущества, а OpenCode доказывает работоспособность архитектуры в масштабе.

Оставайтесь на Ink, если публикуете CLI в npm для широкой аудитории Node, если ваш интерфейс — это формы, промпты и прогресс, а не непрерывные потоки, или если вы не можете себе позволить ломающие изменения между минорными версиями. Значение 30 fps по умолчанию в Ink настраивается через maxFps, а его список продакшен-внедрений — среди них Claude Code, Gemini CLI, GitHub Copilot CLI, Wrangler и Prisma — показывает, насколько далеко тянется троттлинговая модель. Bubble Tea и Ratatui остаются вариантами для команд, готовых уйти от TypeScript, что противоречит исходной посылке этого сравнения.

Заключение

OpenTUI заслуживает ярлык «реальной альтернативы» по архитектуре и продакшен-подтверждениям, а Ink сохраняет позицию выбора по умолчанию за счёт стабильности и охвата. Решающий вопрос не в том, какой рендерер быстрее, а в том, смогут ли ваши пользователи запустить ваш рантайм. Соберите прототип самого нагруженного экрана через bun create tui --template react, посмотрите на него под реальным потоком данных и позвольте ограничению рантайма, а не бенчмарку, принять решение.

Часто задаваемые вопросы

OpenTUI работает только на Bun или ещё и на Node.js?

Нет, OpenTUI не ограничен Bun. Работает Bun 1.3.0 и выше, а также Node.js 26.4.0 и выше — при условии, что ваше приложение на ESM и вы запускаете Node с экспериментальным флагом FFI; подключите Core через CommonJS require, и он выбросит ошибку. Некоторые части по-прежнему доступны только в Bun, среди них @opentui/three и плагины, загружаемые в рантайме, а поддержка FFI в Node сама по себе экспериментальная, так что Bun остаётся лучше протестированным путём.

Работает ли OpenTUI на Windows?

Да. Предсобранные пакеты нативного ядра поставляются для Windows x64 и Windows arm64, а также для macOS и в сборках под glibc и musl для Linux. На Windows собственное тестирование проекта идёт через Bun на x64, тогда как ветка приёмочных тестов для Node.js работает на Linux x64, поэтому попробуйте Windows-релиз в реальном терминале Windows до релиза, особенно если ваши пользователи на Node, а не на Bun.

Поддерживает ли OpenTUI React DevTools?

Да, несмотря на противоположные утверждения, гуляющие в интернете. Документация @opentui/react описывает установку react-devtools-core@7 как dev-зависимости, запуск npx react-devtools@7 и старт приложения с DEV=true для инспекции дерева компонентов. Ink поддерживает React DevTools таким же образом через DEV=true, так что инструменты отладки не являются значимым различием между этими двумя библиотеками.

Какой биндинг OpenTUI выбрать — React или Solid?

Выбирайте Solid для наиболее проверенного в продакшене пути: терминальный интерфейс OpenCode работает на реконсиляторе Solid, а у @opentui/solid есть покрытие CI под Node.js, которого нет у @opentui/react. Выбирайте React, если ваша команда уже работает с ним; биндинг требует React 19.2.0 или новее и поставляет хуки вроде useKeyboard и useTimeline. Учтите, что @opentui/solid жёстко фиксирует Solid ровно на версии 1.9.12.

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.