Skip to content
Published on

ターミナルTUIルネサンス — GUIを離れターミナルに帰ってくる開発者たち

Authors

はじめに — なぜ再びターミナルなのか

最近、Hacker NewsとGeekNewsでSlumberというターミナルベースのHTTPクライアントが紹介され、好評を得ました。Postmanの座をターミナルの中で置き換えようというツールですが、コメント欄の雰囲気が興味深いものでした。「またTUIか?」ではなく「ついにこの領域にも使えるTUIが出た」という歓迎一色だったのです。lazygit、k9s、btopといったツールが数万のGitHubスターを積み上げてきた流れの延長線上にあります。

TUI(Text-based User Interface)が再び盛り上がるのには構造的な理由があります。

第一に、リモート開発がデフォルトになりました。 開発環境がクラウドVM、コンテナ、SSHの向こう側に移ったことで、「どこでも同じツール」の価値が高まりました。GUIのフォワーディングは苦痛ですが、TUIはSSHさえ通れば終わりです。

第二に、キーボードワークフローの再評価です。 マウスとの往復なしに手がホームポジションに留まる作業の流れは、一度身につくと戻れません。vimキーバインドが事実上の標準インターフェースになったことで、ツール間の学習の転移も容易になりました。

第三に、2026年の新しい変数ですが、AIコーディングエージェントとターミナルの相性です。Claude Codeのようなエージェントがターミナルで動く時代に、開発者の他のツールも同じターミナルマルチプレクサの中にあれば、コンテキストスイッチが消えます。エージェントが左ペインでコードを直している間、右ペインのlazygitでdiffをレビューする光景は、もはや日常です。GUIアプリにはこのループに入り込む席がありません。

この記事ではSlumberを皮切りに、カテゴリ別ベストTUI、組み合わせワークフロー、そしてratatui/bubbleteaで自作してみる入門まで扱います。

Slumber — ターミナルのPostman

SlumberはRustで書かれたHTTPクライアントで、3つの形態を同時に提供するのが特徴です。同じ設定ファイル1つで、TUI(対話的な探索)、CLI(スクリプト/CI用)、ライブラリ(Rustコードから呼び出し)として使えます。

核心概念はrecipeです。リクエストをYAMLファイルに宣言的に定義しておき、再利用します。Postmanコレクションのテキストファイル版と考えればよいでしょう。当然gitでバージョン管理でき、コードレビューも可能です。

# slumber.yml — プロジェクトルートに置けば自動認識
profiles:
  local:
    data:
      host: http://localhost:8000
  production:
    data:
      host: https://api.example.com

requests:
  login: !request
    method: POST
    url: "{{host}}/auth/login"
    body: !json { "username": "demo", "password": "hunter2" }

  list_users: !request
    method: GET
    url: "{{host}}/users"
    authentication: !bearer "{{chains.auth_token}}"
    query:
      - page=1
      - limit=20

chains:
  auth_token:
    source: !request
      recipe: login
    selector: $.token

上の設定のchainsがSlumberの強みです。「loginリクエストのレスポンスからJSONPathでトークンを抜き出し、次のリクエストのBearerヘッダーに入れる」という依存関係を宣言だけで処理します。使い方はこうです。

# TUIモード — 対話的に探索、プロファイル切り替え、レスポンス確認
slumber

# CLIモード — 同じrecipeをスクリプト/CIで実行
slumber request --profile production list_users

# レスポンスだけ抜き出してパイプラインへ
slumber request login | jq .token

「チームメンバーと共有可能な宣言的リクエスト定義+ターミナルで即実行」という組み合わせは、Postmanのライセンス問題とElectronアプリ疲れにうんざりしたチームにとって、十分に魅力的な代替案です。

カテゴリ別ベストTUI

git — lazygit

TUIルネサンスの看板スターです。ステージング、コミット、ブランチ、リベース、スタッシュをすべてショートカットで処理します。

# インストール
brew install lazygit          # macOS
sudo apt install lazygit      # Ubuntu 25.10+

# よく使う流れ: ファイル別/ハンク別ステージング
# ファイルパネルで space = ファイルのトグル、enter = ハンク単位に入る
# コミットは c、プッシュは P、インタラクティブリベースはブランチで r

特にハンク単位のステージングとインタラクティブリベースが圧巻です。git rebase -iのエディタ編集を矢印キーとショートカットで置き換える体験は、CLIのgitに戻れなくさせます。AIエージェントが作ったコミットをレビューしてsquashで整理する用途にも最適です。

Kubernetes — k9s

クラスタ運用者の必需品です。kubectlコマンドを暗記する必要なく、リソース間を高速に航海します。

k9s                       # 起動
# :pods       → Pod一覧 (コロンでリソース切り替え)
# /error      → 一覧のフィルタリング
# l           → ログ、s → シェルに入る、d → describe
# ctrl-d      → 削除、:ctx → コンテキスト切り替え

障害対応中に「Pod一覧 → ログ → イベント → ノード状態」を行き来する速度は、kubectlのタイピングやWebダッシュボードとは比較になりません。

Docker — lazydocker

lazygit作者によるDocker版です。コンテナ/イメージ/ボリュームの状態とログ、統計を1画面で見られます。docker compose環境で「どのサービスがなぜ死んだか」を確認する最短経路です。

データベース — rainfrog、harlequin

rainfrogはPostgreSQL中心の軽量クエリエクスプローラ、harlequinはDuckDB/SQLite/Postgresなどをサポートする「ターミナルSQL IDE」に近い存在です。どちらもvimキーバインドでクエリ編集と結果探索ができます。

harlequin mydata.duckdb       # DuckDBファイルを開く
rainfrog --url postgres://user@localhost/mydb

ファイルマネージャ — yazi

Rustで書かれた次世代ファイルマネージャです。非同期IOのおかげで巨大なディレクトリでも止まらず、画像プレビュー(グラフィックプロトコル対応ターミナル)、一括リネーム、zoxide連携まで備えています。

モニタリング — btop

htopの精神的後継者です。CPU/メモリ/ディスク/ネットワーク/プロセスを、マウスもサポートする美麗な画面で表示します。GPUモニタリングにも対応しています。

一目でわかる推奨リスト

カテゴリツール一言説明
gitlazygitハンクステージングとリベースの決定版
Kubernetesk9sクラスタ航海の標準
Dockerlazydockercompose環境デバッグの最短経路
HTTPslumberrecipeベース、TUI/CLI/ライブラリの3形態
DBharlequinターミナルのSQL IDE
ファイルyazi非同期+プレビュー+一括操作
モニタリングbtop美しく速いシステムダッシュボード
ファジーファインダーfzfあらゆるリストの万能インターフェース
マルチプレクサtmux、zellijすべてのTUIを収める器

fzf — リストのあるところにfzfあり

fzfは単独のツールというより、「どんなリストでも受け取って対話的セレクタに変える」ビルディングブロックです。レシピをいくつか覚えるだけで体感が変わります。

# 1. ブランチのファジーチェックアウト
git branch --all | grep -v HEAD | fzf | sed 's/.* //' | xargs git checkout

# 2. プロセスを選んでkill
ps -ef | fzf -m | awk '{print $2}' | xargs kill -9

# 3. 履歴検索はデフォルトのキーバインドで (ctrl-r)
# シェル統合を有効にすると ctrl-r/ctrl-t/alt-c が使える
eval "$(fzf --bash)"   # bashの場合、zshは fzf --zsh

# 4. ripgrepと組み合わせたコード検索+プレビュー
rg --line-number --no-heading . | fzf --delimiter : \
  --preview 'bat --color=always --highlight-line {2} {1}'

# 5. SSH先のファジー選択
grep -E '^Host ' ~/.ssh/config | awk '{print $2}' | fzf | xargs -o ssh

ポイントは「fzfを学ぶ」というより「パイプラインの最後にfzfを付ける習慣」を身につけることです。

マルチプレクサ — tmuxとzellij

TUIツールたちを収める器がマルチプレクサです。SSHセッションが切れても作業が生き残り(detach/attach)、画面を分割して複数のTUIを同時に表示できます。

tmuxは標準ですが設定の参入障壁があり、zellijはデフォルトが親切な現代的代替です。画面下部にショートカットのヒントが常に表示されており、学習曲線がなだらかです。

# tmuxの核心だけ
tmux new -s work          # セッション作成
# prefix(ctrl-b) + % : 縦分割、" : 横分割、d : detach
tmux attach -t work       # 再接続

# zellij — レイアウトファイルで開発環境をコード化
zellij --layout dev.kdl
# dev.kdl — 一度に立ち上がる開発環境レイアウトの例
layout {
    pane split_direction="vertical" {
        pane command="nvim"
        pane split_direction="horizontal" {
            pane command="lazygit"
            pane command="btop"
        }
    }
}

組み合わせワークフロー — あるバックエンド開発者の午前

ツールは組み合わせてこそ価値が増します。架空の、しかし典型的なシナリオでまとめてみます。

┌────────────────────────── tmux: workセッション ──────────────────────┐
│ ┌───────────────┬──────────────────┬───────────────────────────┐  │
│ │  pane 1       │  pane 2          │  pane 3                   │  │
│ │  nvim         │  AIコーディング     │  k9s (ステージングクラスタ)   │  │
│ │  (コードレビュー)│  エージェント      │  + lazygit (コミットレビュー) │  │
│ └───────────────┴──────────────────┴───────────────────────────┘  │
└──────────────────────────────────────────────────────────────────────┘
  1. 出勤後、tmux attach一発で昨日の画面にそのまま復帰します。
  2. 夜間アラートで入ってきたAPIの5xxを調査します。k9sで該当Podのログを開き、エラーパターンを確認します。
  3. 再現のためSlumber TUIを立ち上げ、productionプロファイルで問題のエンドポイントを呼び出し、recipeをlocalプロファイルに切り替えて修正候補を検証します。
  4. 修正作業そのものはAIエージェントに委任し、その間lazygitでエージェントが積み上げるコミットのdiffをハンク単位でレビューします。
  5. 怪しいクエリ性能はharlequinでステージングDBに接続し、実行計画を確認します。
  6. マージ前にfzfでブランチを選んでチェックアウトし、CIが回っている間にbtopでローカル負荷を確認します。

この全過程で手はキーボードを離れず、画面はターミナル1つを離れません。SSHで接続したリモート開発マシンでも体験が完全に同一だという点が核心です。

自分で作ってみる — ratatuiとbubbletea入門

TUIルネサンスのもう1つの原動力はフレームワークの成熟です。Rustのratatuiとgoのbubbleteaが二大山脈です。

ratatui (Rust) — 即時モードレンダリング

ratatuiは毎フレームUIを描き直すimmediate mode方式です。ミニカウンターの例です。

use crossterm::event::{self, Event, KeyCode};
use ratatui::{
    widgets::{Block, Borders, Paragraph},
    DefaultTerminal,
};

fn main() -> std::io::Result<()> {
    let mut terminal = ratatui::init();
    let result = run(&mut terminal);
    ratatui::restore();
    result
}

fn run(terminal: &mut DefaultTerminal) -> std::io::Result<()> {
    let mut count = 0i64;
    loop {
        terminal.draw(|frame| {
            let body = Paragraph::new(format!("count: {count}  (j/kで増減, qで終了)"))
                .block(Block::default().title("mini-counter").borders(Borders::ALL));
            frame.render_widget(body, frame.area());
        })?;
        if let Event::Key(key) = event::read()? {
            match key.code {
                KeyCode::Char('j') => count -= 1,
                KeyCode::Char('k') => count += 1,
                KeyCode::Char('q') => return Ok(()),
                _ => {}
            }
        }
    }
}

bubbletea (Go) — Elmアーキテクチャ

bubbleteaはModel(状態) → Update(メッセージ処理) → View(レンダリング)のElmアーキテクチャに従います。

package main

import (
    "fmt"
    "os"

    tea "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) {
    if key, ok := msg.(tea.KeyMsg); ok {
        switch key.String() {
        case "k":
            m.count++
        case "j":
            m.count--
        case "q":
            return m, tea.Quit
        }
    }
    return m, nil
}

func (m model) View() string {
    return fmt.Sprintf("count: %d  (j/kで増減, qで終了)\n", m.count)
}

func main() {
    if _, err := tea.NewProgram(model{}).Run(); err != nil {
        os.Exit(1)
    }
}

どちらのフレームワークも30分あれば動くプロトタイプが作れます。社内デプロイ状況ボード、オンコールチェックリスト、ログフィルタのような「チーム専用マイクロツール」をTUIで作り、配布バイナリ1つで配るパターンがどんどん一般化しています。AIエージェントに「このCLIをbubbletea TUIで包んで」と頼むのにも適した、よく定型化されたタスクでもあります。

一緒に入れるとよい周辺ツール

本文で扱った核心ツール以外に、一緒にインストールするとシナジーが生まれる周辺ツールも整理しておきます。

ツール領域一言説明
atuinシェル履歴履歴をSQLiteに保存、マシン間同期と強力な検索
zoxideディレクトリ移動cdの学習型代替、よく行くパスへジャンプ
batファイル閲覧シンタックスハイライト付きcat、fzfプレビューの相棒
diveDockerイメージイメージのレイヤー別容量と変更の分析
lnavログフォーマット自動認識のログナビゲータ、SQLクエリ対応
dustディスクduの可視化版、大きなディレクトリを一目で
glowMarkdownターミナルでREADMEを美しくレンダリング
postingHTTPTextualベースのもう1つのTUI HTTPクライアント
# インストール例 (Homebrew)
brew install atuin zoxide bat dive lnav dust glow

# atuin: ctrl-rを同期される検索UIに置き換え
atuin import auto
eval "$(atuin init zsh)"

# zoxide: cdの代わりにz — 一度行ったパスは一部の入力でジャンプ
eval "$(zoxide init zsh)"
z blog   # 例: ~/projects/my-blog へジャンプ

これらのツールの共通点は導入リスクが低いことです。既存コマンド(cat、cd、du、ctrl-r)の場所に収まって即座に効果を出し、気に入らなければ元のコマンドに戻ればよいだけです。

よくある質問

うちのチームはIDE中心ですが、意味がありますか?

TUIはIDEを置き換えません。JetBrainsやVSCodeを使いながらでも、内蔵ターミナルパネルの中でlazygitとfzfはそのまま価値を発揮します。実際、最も一般的な組み合わせでもあります。

Windowsでも動きますか?

WSL2の中ではすべて動作します。ネイティブWindowsでもWindows Terminalとの組み合わせでlazygit、fzf、btopなど多くが移植されていますが、チーム標準にする前に検証が必要です。

SSHマルチホップ環境で遅くないですか?

TUIは画面全体ではなく変更部分だけを描き直すので、レイテンシには意外と強いです。パケットロスが多い環境ならmoshを組み合わせるのも手です。

AIエージェントが全部やってくれるのに、ツールを学ぶ必要がありますか?

エージェントの出力を検証するのは依然として人間の仕事です。diffのレビュー(lazygit)、クラスタ状態の確認(k9s)、リクエストの再現(slumber)は、その検証ループを高速にする核心ツールです。

ツールが多すぎて設定地獄が怖いです。

本文のツールは意図的にゼロコンフィグを志向しています。lazygit、k9s、btopはインストール直後のデフォルトだけで十分使えます。設定ファイルは不便を実際に感じてから触っても遅くありません。

導入ガイド — 段階的に、一度に1つずつ

全部を一気に変えようとして失敗するケースを多く見てきました。おすすめの順序は次のとおりです。

  1. 1週目: fzf。 シェル統合(ctrl-rの履歴検索)を有効にするだけで即効果が出ます。リスクはゼロ。
  2. 2週目: lazygit。 既存のgit知識がそのまま移行できるので学習コストが低く、効果は最大です。
  3. 3週目: tmuxまたはzellij。 最初は分割とdetach/attachだけ使います。設定チューニングの誘惑は後回しに。
  4. 4週目以降: ドメインツール。 Kubernetesを触るならk9s、API開発が多いならslumber、DB作業が多いならharlequinを追加します。
  5. 常に: 逃げ道を維持。 TUIでうまくいかない瞬間は、ためらわず元のCLI/GUIに戻ってください。ツールは宗教ではありません。

チーム導入なら、dotfilesリポジトリで設定を共有し、昼休みのデモ1回がドキュメント10枚より効果的です。

限界と批判的視点

バランスのため、TUIの弱点もはっきり指摘しておくべきです。

  • 学習曲線は実在します。 ショートカットベースのインターフェースは最初の1〜2週間の生産性低下を伴います。締め切り直前の導入は避けましょう。
  • アクセシビリティの問題は深刻です。 スクリーンリーダーはGUIのアクセシビリティツリーを読めますが、TUIのセルベース画面は意味構造を伝えにくい。視覚障害のある同僚がいるチームでは、TUI専用ワークフローの強制は排除的な決定になりかねません。
  • 発見可能性が低い。 GUIはメニューを眺めて機能を発見できますが、TUIはヘルプ(通常は疑問符キー)を積極的に開く必要があります。
  • ターミナル互換性の問題。 トゥルーカラー、画像プレビュー、マウスサポートはターミナルエミュレータごとに差があります。特にWindows環境が混ざるチームは事前検証が必要です。
  • すべての作業がテキストではない。 デザインレビュー、複雑なグラフ探索、ダッシュボード共有といった作業は依然としてGUI/Webが優れています。

「ターミナルに帰ろう」というスローガンではなく、「テキストとキーボードが本質である作業には、それに合った道具を使おう」が正確な結論です。

おわりに

TUIルネサンスはレトロ趣味ではありません。リモート開発の普遍化、キーボード中心ワークフローの再評価、そしてターミナルで動くAIエージェントという3つの流れが合流し、ターミナルが再び開発作業の重心になった結果です。Slumberのような新しいツールが登場し続け、ratatui/bubbleteaのエコシステムが成長していることは、この流れが一時的な流行ではない証左です。

今日1つだけ始めるなら、fzfのctrl-rを有効にすることをおすすめします。そして来週、lazygitを開いてみてください。1か月後、あなたのtmuxセッションの中には思った以上に多くのものが収まっているはずです。

参考資料