Содержание урока · 12 разделов
- Bubble Tea — TUI go библиотека: что под капотом
- Кто строит на Bubble Tea
- TUI против GUI и CLI: где место Bubble Tea
- Зачем elm архитектура в терминале
- Экосистема Charm: bubbles, lipgloss и компания
- Карта экосистемы Charm
- Терминал как платформа: что он умеет
- Почему не ncurses и не tview
- Что дальше по курсу
- Песочница урока
- Коротко: что запомнить
- Вопросы и ответы
Половина рабочего дня разработчика проходит в терминале — и всё же самые любимые инструменты там не «печатают строчки», а живут: k9s рисует таблицы подов и отвечает на клавиши, lazygit превращает git в навигацию стрелками, gh-dash показывает pull request'ы как ленту интерфейса, а не плоскую выдачу curl. Разница не в красоте, а в модели: скрипт печатает и умирает, интерфейс держит состояние, ждёт события и перерисовывается. Bubble Tea — способ писать такие программы на Go без борьбы с ANSI-кодами и сырыми потоками ввода. Экраны этого курса можно потрогать в песочнице урока — там вкладка с виртуальным терминалом; полноценные же программы всё равно запускаются локально, потому что настоящему TUI нужен настоящий терминал. Сначала посмотрим на ландшафт: кто, зачем и на чём.
Bubble Tea — TUI go библиотека: что под капотом#
Bubble Tea — фреймворк для терминальных интерфейсов на чистом Go: пакет bubbletea go-проект подключает одной строкой импорта — github.com/charmbracelet/bubbletea. Автор — компания Charmbracelet Кристиана Рочи, фреймворк вышел в 2020 году и с тех пор перерос статус эксперимента: сегодня это де-факто стандартный ответ на вопрос «как сделать TUI-приложение на Go». «Чистый Go» здесь важное слово: без cgo, без зависимости от ncurses, со статическим бинарником на выходе. Программа работает по SSH ровно так же, как локально, — терминал есть терминал. Идею подсмотрели у Elm и Haskell: архитектура Model-Update-View оказалась настолько удачной, что фреймворк прижился далеко за пределами своей ниши. Отрисовка устроена экономно: после каждого события фреймворк сравнивает новый кадр со старым и обновляет только изменившиеся строки — на типичный инструмент это стоит микросекунды. API ядра годами живёт в первой мажорной версии — примеры из туториалов двухлетней давности собираются без правок. Сам фреймворк намеренно мал: он берёт на себя цикл событий, ввод и отрисовку, а компоненты, стили и формы вынесены в соседние библиотеки — до них дойдём ниже.
Кто строит на Bubble Tea#
- gh-dash (dlvhdr/gh-dash) — популярное расширение GitHub CLI: список PR и issues с фильтрами, деталями и ревью прямо в терминале
- gum от Charm — набор готовых бинарников для shell-скриптов: выбор, ввод, подтверждение, спиннеры; внутри каждого — Bubble Tea
- Soft Serve — git-сервер с TUI-панелью управления, тоже из Charmbracelet
- AWS Copilot CLI — интерактивные подсказки и панели деплоя построены на Bubble Tea, Charm публиковал об этом отдельный кейс
- k9s — знаменитая панель Kubernetes на самом деле сделана на tview, не на Bubble Tea; класс задач тот же, а путают их часто
- Сотни утилит в подборках awesome-tui: мониторы, чаты, менеджеры задач, интерактивные генераторы — и внутренние инструменты команд, которых нет в подборках
TUI против GUI и CLI: где место Bubble Tea#
Способов дать пользователю интерфейс три, и у каждого своя ниша. CLI печатает, ждёт ввод и завершается — идеально для пайплайнов и автоматизации. GUI (например, на fyne — у нас есть отдельный курс: знакомство с Fyne) даёт окна и мышь, но требует дисплея, графических библиотек и сборки под каждую платформу. TUI-приложение живёт посередине: оно реагирует на клавиши и мышь, как GUI, но рисуется символами и работает там, куда GUI не доберётся — на сервере без иксов, в docker-контейнере, в SSH-сессии с ноутбука. Моё правило: инструмент для разработчиков, который обязан запускаться на сервере, — почти всегда кандидат на TUI. Нужны курсор, файловый диалог и пиксели — берите GUI и не мучайте терминал, он этого не простит.
Зачем elm архитектура в терминале#
Классический GUI-фреймворк предлагает колбэки: кнопка нажата — вызовись сюда, таймер тикнул — сюда. На форме из трёх полей это терпимо. На панели с десятью экранами колбэки начинают менять состояние кто попало и в каком попало порядке, а отладка превращается в археологию: кто именно испортил поле модели, ищется часами. Elm-архитектура (та самая, из языка Elm; Redux — её младший родственник) разрешает проблему жёстко. Всё состояние приложения живёт в одном значении — модели. Каждое событие — обычное значение-сообщение. Единственная функция Update получает сообщение и возвращает новую модель. Единственная функция View рисует модель в строку. Никаких скрытых мутаций из четырёх углов программы: поток «событие → Update → View» один, и он помещается в голову целиком. Для терминала это совпадение особенно удачно — событий много, и все они асинхронные: клавиши, мышь, resize окна, ответы сети, таймеры.
Первый взгляд: программа целиком
GOpackage main
import (
"fmt"
"os"
"github.com/charmbracelet/bubbletea"
)
type model struct {
count int
}
func (m model) Init() tea.Cmd {
return nil
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "up":
m.count++
case "down":
m.count--
case "q", "ctrl+c":
return m, tea.Quit
}
}
return m, nil
}
func (m model) View() string {
return fmt.Sprintf(
"Счёт: %d\n\n↑ больше, ↓ меньше, q — выход\n",
m.count,
)
}
func main() {
if _, err := tea.NewProgram(model{}).Run(); err != nil {
fmt.Println("Ошибка:", err)
os.Exit(1)
}
}Вся программа — три метода и одна строка запуска. Init() объявляет, что нужно сделать при старте (здесь — ничего), Update получает любое событие и переключается по его типу, View рисует модель в строку, а фреймворк сам печатает её и перерисовывает при изменениях. Ветки q и ctrl+c возвращают tea.Quit — команду завершить цикл. tea.NewProgram создаёт программу, Run блокирует main до выхода. В песочнице сайта этот код не запустится: Bubble Tea требует настоящий терминал. Локально — go mod init, go get github.com/charmbracelet/bubbletea, go run main.go.
Экосистема Charm: bubbles, lipgloss и компания#
Bubble Tea — не одинокая библиотека, а центр целой экосистемы. bubbles — официальный набор компонентов: список с фильтрацией, текстовые поля, таблицы, спиннеры, прогресс-бары. Всё это тоже модели, встраиваемые в вашу, — в курсе им посвящено несколько уроков, включая готовые списки. Lip Gloss — стилизация: цвета, рамки, отступы, выравнивание; верстка терминального интерфейса, предсказуемая как CSS с жёсткими правилами — основы разберём в отдельном уроке. Дальше по списку: glamour рендерит markdown в терминале, huh собирает формы, gum предлагает готовые команды для скриптов, vhs записывает демо-гифки. Практический вывод: прежде чем писать список задач своими руками, проверьте bubbles; прежде чем собирать ANSI-коды цветов конкатенацией, откройте Lip Gloss. Обе проблемы давно решены, и решены лучше, чем получится с первого раза у вас.
Карта экосистемы Charm#
| Пакет или проект | Что делает | Когда пригождается |
|---|---|---|
| bubbletea | ядро: цикл событий, Model, Update, View, ввод | каркас любого TUI-приложения |
| bubbles | готовые компоненты: list, textinput, table, spinner, progress | чтобы не писать список задач самому |
| lipgloss | цвета, рамки, отступы, выравнивание | любой интерфейс сложнее одной строки |
| glamour | рендер markdown в терминале | просмотр README, справки, changelog |
| huh | формы: поля, выбор, подтверждения | мастера настройки, ввод данных |
| vhs | запись GIF из сценария терминала | демо для README проекта |
Терминал как платформа: что он умеет#
Недооценённый факт: современный терминал — платформа с возможностями, о которых GUI-разработчик даже не задумывается. Он умеет цвета и стили — 256 цветов и truecolor почти везде, юникодную графику для рамок, события resize окна, а с включённым режимом — даже мышь: клики, движение, колесо. Bubble Tea берёт всё это на себя: фреймворк переводит терминал в нужные режимы, читает сырые байты ввода, собирает их в понятные сообщения и перерисовывает только изменившиеся строки. Вам остаются три метода и здравый смысл. Обратная сторона: у терминала есть причуды. Одни и те же комбинации клавиш в разных эмуляторах приходят по-разному, поддержка мыши зависит от самого эмулятора, а что-то не различается в принципе. Это не баг фреймворка, а природа платформы: вы пишете не под операционную систему, а под сотню эмуляторов от macOS Terminal до Windows Terminal. Капризы клавиатуры подробно разберём в четвёртом уроке курса. Здесь же отметим только приятное: всё это богатство доступно без единой строчки кода настройки — вы подключаете пакет и сразу работаете с сообщениями, а не с байтами и ioctl.
Почему не ncurses и не tview#
Выбор у Go-разработчика шире, и честнее обсудить альтернативы сразу. ncurses — C-библиотека возрастом в десятилетия: мощная, но с cgo, ручным управлением окнами и чуждым Go циклом жизни. tview — зрелый виджетный фреймворк, на нём сделан k9s: таблицы, деревья и формы доступны из коробки, модель событий ближе к классическим GUI. Bubble Tea берёт другим: крошечное ядро, View — просто строка, вся логика — чистые функции над состоянием. Спорный момент скажу честно: перерисовывать весь View после каждого события выглядит расточительно, и я долго относился к этому скептически, ожидая мерцания и тормозов. Практика умерила пыл в обе стороны. Перерисовка на деле дешевле, чем кажется, — фреймворк обновляет только изменившиеся строки. Но для гигантских таблиц на десятки тысяч строк разница достижима: замеряйте, прежде чем строить монолит на одном экране. Для типичного инструмента — панели, чата, меню — запас прочности огромный.
Курс написан по актуальной версии v1.x пакета github.com/charmbracelet/bubbletea — именно её поставит go get по умолчанию. API ядра — Model, Update, View, Program — стабилен годами: код из ранних туториалов собирается без переделок.
Интерактивы уроков — тесты, «заполни пропуск», «собери программу» — засчитывают XP и проверяют понимание даже без запуска кода. Но TUI нельзя выучить глазами: копируйте примеры в локальный проект, запускайте и ломайте их намеренно. Стартовый набор: свежий Go, любой терминал, пять минут на go mod init и go get github.com/charmbracelet/bubbletea. Дальше только практика: понажимайте клавиши, измените строки, сломайте ветку Update и посмотрите, что случится.
Проверка: кто есть кто
Какой из этих инструментов построен на Bubble Tea?
Проверка: специфика TUI
Чем TUI-приложение принципиально отличается от GUI?
Что нарисует View?
Прочитайте код и выберите, что он выведет:
type model struct{ count int }
func initialModel() model { return model{count: 1} }
func (m model) View() string {
return fmt.Sprintf("Счёт: %d\n", m.count)
}
// Пользователь нажал: ↑, ↓, ↑, ↑Восстановите каркас программы
Впишите недостающие детали: имя пакета, путь импорта, метод старта и команду выхода.
Соберите минимальный каркас
Расставьте строки каркаса Bubble Tea в правильном порядке — от объявления пакета до запуска. Метод View не случайно отсутствует: его добавим во втором уроке, а пока просто восстановите порядок остальных частей.
Строки
Ваша программа
Нажимайте на строки слева, чтобы собрать программу
Карточки: словарь Bubble Tea
Что дальше по курсу#
Дальше — практика. Второй урок собирает счётчик целиком: каждая строка Model, Update и View с разбором и типичными ошибками новичка. Третий — про tea.Program: полный экран, мышь, отправка сообщений снаружи и то, как программа завершается. Потом придут команды tea.Cmd для асинхронных операций и компоненты bubbles. Полная программа — 25 уроков от «Hello, TUI» до итоговой панели задач — лежит на странице курса Bubble Tea. И напомню про запуск: примеры рассчитаны на локальный Go и настоящий терминал. Установить зависимость и собрать программу занимает минут пять, а ощущение живого интерфейса на собственном экране не заменит ни один скринкаст.
Песочница урока
Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.
Виртуальный терминал
модель Bubble Tea · Model → Update → ViewОтредактируйте модель, Update или View — и нажмите «Собрать модель»: код разберётся и начнёт отвечать на клавиши, как настоящий tea.Program.
Клавиатура — обработано в Update
модель собрана: steps []string (3) · step int = 0
программа работает — нажмите клавишу ниже
Коротко: что запомнить
- Bubble Tea — фреймворк TUI от Charmbracelet (Go, 2020): цикл событий, Model, Update, View и ничего лишнего.
- Elm-архитектура: всё состояние в модели, события — сообщения, Update возвращает новую модель, View рисует строку.
- На Bubble Tea сделаны gh-dash, gum, Soft Serve и AWS Copilot CLI; k9s — сосед на tview, класс задач тот же.
- TUI занимает нишу между CLI и GUI: интерактивность как у GUI, но работает по SSH без дисплея.
- Экосистема: bubbles — компоненты, Lip Gloss — стили; рядом glamour, huh, gum, vhs.
- Перерисовка всего View после каждого события дешевле, чем кажется; для гигантских таблиц — замеряйте.
- Примеры курса запускаются локально: нужен настоящий терминал, песочница показывает логику на виртуальном.
Домашнее задание
Установите Bubble Tea локально: mkdir tui-lab, затем go mod init tui-lab и go get github.com/charmbracelet/bubbletea. Соберите программу из урока, запустите и понажимайте стрелки. Потом сломайте её нарочно: уберите ветку ctrl+c и попробуйте выйти. Опишите словами, что происходит и почему — этот вывод понадобится в четвёртом уроке.
Личные заметкиПусто
Вопросы и ответы по уроку
Что такое Bubble Tea простыми словами?
Библиотека для Go, которая превращает терминал в платформу для интерфейсов: собирает клавиши и события в понятные сообщения, а вам оставляет три метода — модель состояния, обновление и отрисовку строки.
Чем Bubble Tea отличается от tview?
tview — виджетный фреймворк, близкий к классическим GUI: таблицы и формы из коробки, модель событий с колбэками. Bubble Tea — Elm-архитектура с чистыми функциями над состоянием: меньше готовых виджетов, больше дисциплины состояния, проще тесты и предсказуемый поток данных.
Можно ли запускать Bubble Tea программы по SSH?
Да, это одна из главных причин брать TUI: программа рисуется символами и требует только терминал. Соберите статический бинарник, положите на сервер — интерфейс работает в SSH-сессии без установки зависимостей.
Термины урока
Ключевые понятия из этого урока — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылки на практику.
Сравните с альтернативами
Практический вопрос после первых уроков: а почему именно эта библиотека? Мы разобрали конкурентов по одним критериям, с кодом одной задачи рядом и персональным подбором под ваши приоритеты.
Изучайте дальше
Следующая ступень учебного пути
Zap: структурное логирование на Go
Интерактивный курс Zap — быстрого логгера для Go: уровни, поля, JSON, ротация, интеграции с Gin, GORM и gRPC. 25 уроков с примерами и итоговым проектом.
- Писать структурные логи с полями вместо строк
- Выбирать между Logger и SugaredLogger осознанно
- Настраивать энкодеры, выводы и ротацию файлов
- Разбираться в zapcore: Core, Encoder, WriteSyncer, LevelEnabler