ターミナルをまた作った Unterm:デフォルトのユーザーは人間じゃない
先に数字だけ言う:この半年、ターミナルで走ったコマンドの八割以上は私が打ったものじゃない。 Claude Code、Codex、各種 agent が、一日中の中で働いて、一つのタスクが何時間も走ることはざらだ。
問題はそこにある。私が使っていたターミナル――iTerm、Windows Terminal、Warp――は全部「一人が座って打つ」前提で設計されている:一行打って、一眼見て、また一行打つ。 主なユーザーが私から agent に変わったとき、この前提はいくつかの場所で正面からぶつかった。一つ一つ穴に落ちていって、最後は自分でターミナルを作った。名前は Unterm だ。
実際に手を動かすきっかけになったのは、ある週に自分の時間の使い方を眺めていたら、大半が agent のネット運用係、セキュリティ審査係、ウィンドウ管理係に費やされていると気づいたことだ――その一つも「プロダクト」そのものじゃない。でも誰も代わりにやってくれないから、自分で何か作って塞ぐしかなかった。
下は私が落ちた穴と、各穴の埋め方だ。
Unterm は何か、名前はどこから来たか
一言で:Unterm は外部の AI agent が直接操控するターミナルだ(unterm.app、オープンソース、GitHub zhitongblog/unterm)。
「AI を内蔵したターミナル」とは違う。チャット欄は持たない。その代わり、ターミナル全体を MCP プロトコルで開放して、agent が開き、打ち、読めるようにする。私がつけたスローガンは一言:
The terminal that runs every AI coding agent. (すべての AI コーディング agent を動かせるターミナル。)
裏にある主張も一言:
ターミナルは AI を中に入れる必要はない。AI に操縦してもらえればいい。
できることとして:Claude Code、Codex CLI、Gemini CLI、OpenCode、Aider をワンクリックでインストール;ローカルファースト、オープンソース、スクリプト化可能(unterm-cli 付き);インターフェースは九言語対応。
実際に使うとこうなる:Claude Code に「このプロジェクトのビルドを走らせて、落ちたらログを自分で見て直して」と一言言うと、MCP 経由で Unterm に接続して、自分でウィンドウを開いてコマンドを打って画面の出力を読んで、エラーが出れば自分で直し続ける――チャットとターミナルの間をコピペで往復する必要がない。ターミナルが初めて agent の手になった。私が手動で出力を運ぶ中継所じゃなくなった。 見たいときに一眼見る、見たくないときは勝手に進む。
名前はシンプルだ。Un + term。term は terminal;Un は「解放(liberation)」――キーを打つという行為を人の手から解放して、AI に渡す。 作っているとき頭にあったのは一つの絵:このターミナルは私のこの両手のためにあるんじゃない、agent のためにある、私は後ろに退いて見ていればいい。名前はそれを言っている。
一、プロキシ:agent に「壁」を見せない
私は中国にいるから、agent が動くとき八割はネット越えが要る:パッケージのインストール、git clone、モデルの重みのダウンロード、各種 API の呼び出し。
普通のターミナルでは、これは手動で export HTTPS_PROXY してやる必要がある、shell ごとに一回。でも agent が新しいウィンドウを開いたり子プロセスをフォークしたりすると、プロキシが消えて、詰まって、タイムアウトして、network error が一行出る。厄介なのは、それがネットワークの問題だと agent には分からないこと――自分のコマンドが間違っていると思って、コマンドを変えてソースを変えてリトライして、どんどんおかしくなっていく。ある夜、モデルの重みを夜中にダウンロードさせておいたら、翌朝見たら、すでに死んでいたプロキシで四十分以上リトライを繰り返していて、ログは画面いっぱいで、一バイトもダウンロードできていなかった。
だからプロキシをターミナル本体の中に入れた。Unterm は Clash と連携するプロキシ層を内蔵していて、全セッションがデフォルトで同じルーティングを使う。私はノードのプールを設定した(今は Gemini と GPT 用に調整したシンガポール回線八本)、ターミナルが三十秒ごとに自分でテストして、速い方を使う;使っている回線が落ちたら、プール内の最速の生きているノードに自動で切り替える。 しかもプロキシは OS レベルに設定してある(Windows はレジストリ書き換え、macOS は scutil 経由、Linux は環境変数)、shell ごとに設定するんじゃなく――その後に開いたどのウィンドウも、生まれながらにプロキシを持っている。
細かい点は agent に踏まされて出てきたものだ。例えば localhost と内部ネットワークアドレスはプロキシを通さないようにしないと、agent が自分でローカルに立ち上げたサービスに繋がれなくなる――この no-proxy ルールはデフォルトで設定しておかないと、agent が踏んでから補うことになる。例えばノードプールは手動で管理したくない:Unterm が Clash 内のグループと各ノードのリアルタイムの遅延を直接読んで、インターフェースで数クリックでローテーションプールが組めて、どのノードをプールに入れるか、どれくらいの頻度でローテーションするかは設定ファイルを手書きする必要がない。
万能じゃない:プール全体の回線が絞られたら、どうしようもない。 でも「一本のノードがまたおかしくなった」という一日に八回起きる面倒は、自分で切り替えてくれる、私が管理しなくていい。
二、セキュリティ:マシンを AI に渡すのは rm -rf も渡すのと同じ
agent に裸のターミナルを渡すのは、マシン全体を渡すのと同じだ。rm -rf、git push --force、DROP TABLE――一行間違えると、ものが消える。しかも agent は人間より反応が速い。普通のターミナルは後ろに座っているのが AI かどうかを知らない、agent と私を同じ一双の手として扱う。
二つの極端のどちらかを選びたくない:裸で放つと怖い;毎コマンド手動確認では自分が打っているのと同じだ。だから Unterm は中間にいくつかの関所を加えた:
- デフォルトは「提案」、直接実行しない:agent がコマンドを私の入力行に渡すが、代わりにエンターを押さない、私が Tab で通す。
- 段階的な許可:安全なコマンドのカテゴリ全体は自動で通して、
rm -rf、git push --force、DROP TABLEこの種の本当に危ないものだけを個別に止める。 - 身元が分離されている:各ウィンドウに独立した身元ファイルを紐付ける(GitHub / AWS / npm のトークン、git 身元、SSH キー)、agent が手にするのはこの圏定された身元で、私のマシン全体のキーチェーンじゃない。
- 明示的な信頼付与:どの agent を信頼するかは私が決める、信頼済みの書き込みだけが確認を免除される。
- エラーが読める:画面上のエラーらしき行をスキャンできて、本当の結果を見る、頭の中で補完するんじゃない。
デフォルトは「慎重」の档:接続したばかりで私がまだ信頼していない agent は、何を書いても私の関所を通す;何回か動かして安心したら、その agent がよく使う安全コマンドのカテゴリをまとめて開放する。慣らし期間は遅くなるが、最初から肝を冷やすことはない。
agent と長く付き合っていると必ず当たる瞬間:自信満々で rm -rf を一行打って「キャッシュを消す」と言うが、パスの一部を打ち間違えている。人間はエンターを押す前に半秒止まる、agent は止まらない――この関所はターミナルが代わりに補わないといけない。
三、録画:agent が終わったら巻き戻して何をしたか見たい
これが私が一番使っていて、なくてはならないと思っている機能だ。
agent が無人で三時間走って、戻ってきたとき何をしたか知りたい。それが自分で書いたまとめだけを見ていては駄目――漏れるかもしれないし、きれいに見せているかもしれないし、辻褄を合わせているかもしれない。 欲しいのは生の記録:コマンド一本一本、出力の一段一段、そのままある。
だから Unterm はセッション全体を頭から末尾まで録画する:agent が打ったもの、ターミナルが返したもの、全部再生できる記録として残して、後で動画みたいに巻き戻して見直せる、履歴を一行一行並べて見ることもできる。録画するとき token とキーを自動でマスクする、この記録自体が新しい漏洩口にならないように。
それは agent のブラックボックスレコーダーだ:問題が出たら、どのステップでおかしくなったか巻き戻して見る;うまく動いたら、デモや振り返り素材として残す。
先週の話:agent がテストのバッチを落として、しかも堂々と「直した」と言った。セッションをコード修正の部分まで巻き戻したら、数分で分かった――テストを緑にするために、断言を一つこっそりコメントアウトしていた。 agent 自身が書いたまとめしかなかったら、この手口は絶対に掴めなかった。記録はそのままエクスポートして、「AI って実際どうやって動いてるの」という話の素材として何度か使った。
agent を無人で走らせる度胸の半分は、この巻き戻せる記録が与えてくれる。
四、並列:もうとっくに agent を一個だけで動かしていない
今の日常は三四個の agent が同時に走っている:一個がフロントエンドをやって、一個がデータベースマイグレーションをかじって、一個がテストを補う。普通のターミナルだと、それは三四個の黒い枠で、alt-tab で切り替えて、切り替えているうちにどれが私の判断を待っていて、どれがもう落ちて待ちぼうけか忘れていく。
Unterm は「群れを管理する」ことをすんなりできるようにした:
- まとめて起動:一コマンドで新しいウィンドウを開いて、仕事を直接割り振る;
- ブロードキャスト:四つの agent 全部に「最新のコードを取ってきて、もう一度ビルドを走らせて」と言いたいとき、一コマンドを全ウィンドウに送る、一個ずつ四回貼らなくていい;
- 待機:仕事を割り振ったら、あるウィンドウが「終わった / エラーが出た」と言うまで待てる。
具体的にある朝の話:三つウィンドウを開いて、それぞれ「ログインページを新デザインで作り直して」「注文テーブルを新スキーマにマイグレーションして」「決済ロジックにテストを補って」と割り振って、「十分ごとに進捗を貼って」とブロードキャストして、自分はメッセージ返しに行く。戻ったら三つのウィンドウの状態を一眼で見て、詰まっているものがあればそのウィンドウに入って二言交わす、詰まっていないものはそのまま走らせる。「一個一個見張る」から「一列をさっと眺める」に変わった。
私の今の仕事はもとよりコードを書くことじゃなくて、agent の群れを編成することだ(これは前の記事で話した)。編成の前提は、手元に使い勝手のいい指揮台がある必要がある、互いに知らない四つの黒い枠で私が頭の中で誰が誰かを覚えているんじゃなく。
五、ウィンドウ:agent が増えるとデスクトップが荒れる
群れで走り始めると、乱れるのはコマンドじゃなくて空間だ:どのウィンドウがデプロイをやっていて、どれが手当たり次第に試した草稿で、どれを二時間前に送り出してまだ返事がない?頭で覚えようとすると、何個かで混乱する。
やったのは一番単純な秩序だ:
- ウィンドウに名前がある:alpha、bravo、charlie、覚えられない番号じゃなく。本当の話:この記事を書いているこの瞬間、私のマシンには Unterm のインスタンスが二つ生きている――alpha が doaipm のサイトディレクトリに開いていて、bravo がこのコンテンツリポジトリに開いている、一眼でどっちがどっちか分かる。
- レイアウトを保存して取り出せる:分割した面板、並べたウィンドウを workspace として保存して、翌日立ち上げたらそのまま復元される、毎日積み木を並べ直さなくていい。
- 名前で呼べる:agent が「デプロイのウィンドウを前に出して」と言えば、十数個の枠の中を漁らなくていい。
workspace 機能は小さく聞こえるが、使ってみると本当に便利だ:私は「記事を出す」固定レイアウトを一つ持っている――サイトディレクトリに一つのウィンドウ、コンテンツリポジトリに一つ、ビルドを走らせるのに一つ、ログを見るのに一つ――保存しておくと、毎朝作業開始でワンキーで復元できて、四つのウィンドウが cwd ごと元の位置にある、毎日また cd して並べ直す必要がない。
名前のない十二個のウィンドウと、各自の名前を呼び出せる一つの作業台、差はそれだけだ。
tmux と Warp は?
こう聞くかもしれない:tmux はとっくに複数パネルがあるし、Warp も AI を中に入れたじゃないか、お前は何を補ったんだ?
tmux は長年使ってきて、複数パネルはよくできている、でも本当に人間の十本の指向けに設計されている:後ろが agent かどうかを知らないし、そのコマンドがデータベースを消すかどうかを管理しないし、中国にいてネット越えのコマンドが全部タイムアウトで苦しんでいることも管理しない。Warp は別の路線で、AI アシスタントをターミナルに縫い込んだ――でもそれは「AI がターミナルの中にいる」であって、「ターミナルが AI に操縦される」じゃない:主役はまだ画面の前に座っている人間で、agent はせいぜい副運転手、プロキシと中国のネットワークの話も引き受けない。iTerm、Windows Terminal も毎日使っていて、良いターミナルだ――でも「良い」の基準はまだ「人間が使いやすい」:配色、フォント、ショートカット、分割表示、どれも「打っているのが agent だ」を一等市民として設計していない。
二つの路線とも悪くない、ただどちらも私のこの問いに答えていない:主役が人間から agent に変わったとき、ターミナル自体はどうあるべきか。 プロキシ、セキュリティの関所、巻き戻せる記録、群れの編成、名前でウィンドウを管理する――私にとってこれらは孤立したいくつかの機能点じゃなく、一つの問いのいくつかの面だ。
最後に
ターミナルは世の中にあふれていて、それでもまた一つ作るのは、自分でも説明が要ると思っている。
理由は一言:私は使い勝手のいいターミナルを作りたかったんじゃない、「デフォルトのユーザーが人間じゃない」ターミナルを作りたかった。 上の話の何一つロードマップから来ていない、全部あの時期に本当に私を苦しめたことだ。
もう一つ実のある点:Unterm 自体も、ターミナルの中で AI に大まかな言葉で語り聞かせて作ったものだ、本番コードは私が書いていない。「agent に操縦されて、自分でプロキシを切り替えて、rm -rf を止めて、まるごと再生できる」を明確に語れば、AI がそれを建てた。話せれば、建てられる――ずっとこうやって動いてきた。
世界がもう一つのターミナルを必要としているかどうか、分からない。でも私は必要だった。
関連記事
- 前の記事:実行者から編成者へ:新しい仕事は agent の群れを指揮すること
- Unterm 公式サイト / オープンソースリポジトリ:unterm.app · GitHub
zhitongblog/unterm
ディスカッション