2026-07-04

我又做了一個終端 Unterm:預設使用者不是人

先說個數:過去半年,我終端裡跑的命令,八成以上不是我敲的。 是 Claude Code、是 Codex、是一堆 agent,一天到晚在裡面幹活,一個任務經常跑好幾個小時。

問題就出在這裡。我在用的這些終端——iTerm、Windows Terminal、Warp——全是照「一個人坐著敲」設計的:敲一行、看一眼、再敲一行。 主要使用者從我變成 agent 之後,這個預設假設在好幾個地方直接失效了。我一個坑一個坑撞過去,最後乾脆自己做了一個終端,叫 Unterm

真正讓我動手的,是有一週我盯著自己的時間去向,發現大半天都花在給 agent 當網路運維、當安全審核、當視窗調度員——這些事沒有一件是「產品」本身,但沒人替我擋,我就只能自己做個東西把它們擋掉。

下面是我撞到的坑,和每個坑的填法。

Unterm 是什麼,名字怎麼來的

一句話:Unterm 是一個讓外部 AI agent 直接操控的終端unterm.app,開源,GitHub zhitongblog/unterm)。

它跟「內建了 AI 的終端」不是一回事。它自己不帶聊天框,而是把整個終端透過 MCP 協定開放出去,讓 agent 來開、來敲、來讀。我給它寫的 slogan,就一句:

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 是「解放」——把打字這件事從人的雙手裡解放出來,交給 AI。 我做它的時候腦子裡就一個畫面:這台終端不是給我這雙手用的,是給 agent 用的,我退到後面盯著就行。名字說的就是這件事。

一、代理:讓 agent 看不見那堵牆

我在國內,agent 幹活八成要出牆:裝套件、git clone、拉模型權重、呼叫各家 API。

普通終端裡,這事得我手動 export HTTPS_PROXY,一個 shell 設一次。可 agent 一開新視窗、一 fork 子行程,代理就丟了,然後卡住、逾時、報一句 network error麻煩的是它不知道這是網路問題,只會以為是自己命令寫錯了,於是改命令、換源、重試,越弄越亂。有次我讓它半夜拉個模型權重,第二天一看,它在一條早就掛掉的代理上重試了四十多分鐘,日誌刷滿螢幕,一個位元組都沒下下來。

所以我把代理做進了終端本身。Unterm 內建一個接 Clash 的代理層,所有 session 預設走同一套路由。我配了一池節點(現在是八條給 Gemini、GPT 調過的新加坡線路),終端每半分鐘自己測一遍,哪條快走哪條;正在用的那條掛了,自動切到池子裡最快的活節點。 而且代理是設到作業系統那一層的(Windows 改登錄檔、macOS 走 scutil、Linux 設環境變數),不是每個 shell 單設——之後開出來的每個視窗,天生就帶著代理。

還有些細節是被 agent 逼出來的。比如 localhost 和內網位址不能走代理,否則 agent 連自己在本機起的服務都連不上——這套 no-proxy 規則得預設配好,不能等 agent 去踩了才補。再比如節點池不該我手動維護:Unterm 直接讀 Clash 裡的分組和每個節點的即時延遲,我在介面上點幾下就搭出一個輪換池,哪些節點進池、多久輪一次,都不用去手改設定檔。

它不是萬能的:整池線路都被限速,我照樣沒辙。 但「單條節點又抽風了」這種一天碰八回的破事,它自己就切過去了,不用我管。

二、安全:把機器交給 AI,等於把 rm -rf 也交出去

給 agent 一個裸終端,等於把整台機器交給它。rm -rfgit push --forceDROP TABLE——一行敲錯,東西就沒了,而且它跑得比你反應快。普通終端不知道背後坐的是 AI,把 agent 和我當成同一雙手。

我不想在兩個極端裡二選一:要麼放它裸奔,提心吊膽;要麼每條命令我手動確認,那等於我自己在敲。所以 Unterm 在中間加了幾道關:

預設是「保守」那一檔:一個剛接進來、我還沒授信的 agent,寫什麼都得先過我這關;等我看它跑幾輪、確認靠譜,再把它常用的那些安全命令整類放開。磨合期它是慢一點,但不會一上來就把我嚇一身汗。

帶 agent 久了,你一定會碰上它信心十足地敲一條 rm -rf 去「清快取」、路徑卻拼錯一截的時刻。人在按 Enter 前會頓半秒,agent 不會——這道閘,得終端替它補上。

三、錄製:agent 跑完,我要能倒帶看它幹了啥

這是我用得最多、也最不敢沒有的一個功能。

agent 無人值守跑三個小時,你回來想知道它到底幹了什麼。光看它自己寫的總結不行——它可能漏、可能美化、甚至可能圓謊。 你要的是原始記錄:每一條命令、每一段輸出,原樣都在。

所以 Unterm 把整個工作階段從頭到尾錄下來:agent 敲了什麼、終端回了什麼,全存成一份能回放的記錄,之後能像錄影一樣倒帶重看,也能把歷史一條條列出來翻。錄的時候會自動把 token、金鑰遮罩,免得這份記錄本身變成新的洩密口子。

它就是 agent 的黑盒子:出了問題,倒帶看它哪一步走歪了;跑得漂亮,就留著當 demo 或者覆盤素材。

舉個上週的事:一個 agent 把一批測試跑掛了,還理直氣壯說「修好了」。我把工作階段倒帶到它動手改程式碼那一段,幾分鐘就看清了——它為了讓測試變綠,偷偷把一個斷言註解掉了。 要是只有它自己寫的那份總結,我根本抓不到這一手。記錄還能整段匯出,我拿它當過好幾次「AI 到底是怎麼幹活的」的講解素材。

我敢讓 agent 無人值守跑,底氣有一半是這份能倒帶的記錄給的。

四、並行:我早就不只開一個 agent

現在的常態是三四個 agent 同時跑:一個弄前端,一個啃資料庫遷移,一個補測試。普通終端裡,這就是三四個黑框,我 alt-tab 來回切,切著切著就忘了誰在等我拍板、誰已經掛了在乾等。

Unterm 把「管一群」做順了:

具體到一個早上大概是這樣:開三個視窗,分別派「把登入頁按新設計重做」「把訂單表遷到新 schema」「給結算邏輯補測試」,再廣播一句「每十分鐘把進度貼出來」,然後我自己去回訊息。回來掃一眼三個視窗的狀態,誰卡了就進哪個視窗跟它聊兩句,沒卡的接著放它跑。我從『一個個盯』變成了『掃一眼一排』。

我現在的活兒本來就不是寫程式,是編排一隊 agent(這事我在上一篇裡講過)。而編排的前提,是手裡得有個稱手的指揮台,不是四個互相不認識、還得我用腦子記著誰是誰的黑框。

五、視窗: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 就把它建了出來。說得清,它就建得出來——我一直是這麼幹活的。

世界需不需要又一個終端,我不知道。反正我需要。

延伸閱讀

討論

無需登入,匿名即可發言,請友善。
載入中…