Ho fatto un altro terminale, Unterm — l'utente predefinito non è umano
Partiamo da un numero: negli ultimi sei mesi, più dell’80% dei comandi eseguiti nel mio terminale non li ho digitati io. Li hanno digitati Claude Code, Codex, un mucchio di agent — al lavoro tutto il giorno, con task che spesso girano per ore.
Il problema è qui. I terminali che uso — iTerm, Windows Terminal, Warp — sono tutti progettati per «una persona seduta che digita»: una riga, un’occhiata, un’altra riga. Quando l’utente principale è diventato l’agent invece di me, questa ipotesi di default è venuta meno in più punti. Me le sono prese una per una, e alla fine ho fatto direttamente un terminale io: si chiama Unterm.
Quello che mi ha fatto davvero muovere è stato passare una settimana a guardare dove andava il mio tempo: metà giornata era andata a fare il sysadmin di rete per gli agent, il revisore della sicurezza, il coordinatore delle finestre — niente di tutto questo è «prodotto», ma visto che nessuno se ne occupava al posto mio, ho dovuto costruire qualcosa che lo facesse.
Ecco i buchi in cui sono caduto, e come li ho tappati.
Cos’è Unterm e da dove viene il nome
In una riga: Unterm è un terminale che gli agent AI esterni possono pilotare direttamente (unterm.app, open source, GitHub zhitongblog/unterm).
Non è la stessa cosa di «un terminale con l’IA integrata». Non ha una chat box — espone l’intero terminale tramite il protocollo MCP, così che gli agent possano aprirlo, digitare, leggere. Il mio slogan per lui è una sola riga:
The terminal that runs every AI coding agent. (Il terminale che manda avanti ogni AI coding agent.)
La tesi dietro è anche quella una riga sola:
Il terminale non ha bisogno di avere l’IA dentro — deve poter essere guidato dall’IA dall’esterno.
Funzionalità: installa con un click Claude Code, Codex CLI, Gemini CLI, OpenCode, Aider; local-first, open source, scriptabile (con un unterm-cli); interfaccia in nove lingue.
In pratica funziona così: dico a Claude Code «metti su la build di questo progetto, se si rompe guarda tu i log e sistemati», lui si connette a Unterm via MCP, apre una finestra da solo, digita i comandi da solo, legge l’output sullo schermo da solo, e se c’è un errore lo corregge da solo — senza che io debba copiare e incollare tra la chat e il terminale. Per la prima volta il terminale è diventato la mano dell’agent, non il punto di smistamento in cui sbatto manualmente l’output. Quando voglio tenerlo d’occhio lo guardo, quando non voglio ci pensa lui.
Il nome è semplice: Un + term. term è terminal; Un sta per «liberare» — liberare la digitazione dalle mani umane e affidarla all’IA. Quando l’ho fatto avevo un’immagine in testa: questo terminale non è per le mie mani, è per gli agent, io mi metto dietro a guardare. Il nome dice esattamente questo.
1. Proxy: far sì che l’agent non veda il muro
Vivo in Cina, e l’80% delle operazioni che fa un agent richiedono di passare fuori: installare pacchetti, git clone, scaricare pesi di modelli, chiamare API di mezzo mondo.
In un terminale normale, devo fare export HTTPS_PROXY a mano, una volta per ogni shell. Ma ogni volta che un agent apre una nuova finestra o fa fork di un processo figlio, il proxy si perde — e allora si blocca, va in timeout, stampa un network error. Il guaio è che non sa che è un problema di rete: pensa di aver scritto il comando sbagliato, quindi cambia il comando, prova mirror diversi, riprova, e il casino cresce. Una volta l’ho lasciato a scaricare dei pesi di modello durante la notte: il mattino dopo ho visto che aveva riprovato per oltre quaranta minuti su un proxy già morto, riempiendo i log di messaggi, senza scaricare un byte.
Così ho messo il proxy nel terminale stesso. Unterm ha un layer proxy integrato che si aggancia a Clash, e tutte le sessioni usano di default lo stesso routing. Ho configurato un pool di nodi (ora sono otto linee Singapore ottimizzate per Gemini e GPT): il terminale le testa da solo ogni mezzo minuto, usa quella più veloce; se quella in uso si guasta, passa automaticamente al nodo più rapido del pool. E il proxy è impostato a livello di sistema operativo (registro di sistema su Windows, scutil su macOS, variabile d’ambiente su Linux) — non per ogni singola shell: ogni finestra aperta da quel momento eredita il proxy di default.
Ci sono dettagli che gli agent mi hanno costretto ad aggiungere. Per esempio, localhost e gli indirizzi interni non possono passare dal proxy — altrimenti l’agent non riesce a connettersi ai servizi che ha avviato in locale. Quelle regole no-proxy devono essere configurate di default, non aggiunte dopo che l’agent ci è cascato. E il pool di nodi non dovrei manutengerlo a mano: Unterm legge direttamente i gruppi e le latenze in tempo reale da Clash, e con pochi click nell’interfaccia costruisco un pool a rotazione — quali nodi entrano nel pool, ogni quanto ruotano — senza toccare file di configurazione.
Non è infallibile: se tutto il pool viene rallentato, non posso farci niente. Ma il caso «un nodo si è di nuovo messo di traverso» — che succede otto volte al giorno — lo gestisce da solo, senza che io intervenga.
2. Sicurezza: dare la macchina all’IA significa darle anche rm -rf
Dare a un agent un terminale nudo significa dargli l’intera macchina. rm -rf, git push --force, DROP TABLE — una riga sbagliata e la roba sparisce, e lui è più veloce dei tuoi riflessi. Il terminale normale non sa che dietro c’è un’IA: tratta l’agent e me come se fossero le stesse mani.
Non voglio scegliere tra i due estremi: lasciarlo libero con l’ansia, oppure confermare ogni comando a mano — che equivale a digitare tutto io. Così Unterm ha messo qualche cancello in mezzo:
- Di default «suggerisce», non esegue: l’agent inserisce il comando nella mia riga di input, ma non preme invio al posto mio — un Tab mio e via.
- Autorizzazione a livelli: una categoria intera di comandi sicuri passa automaticamente; solo
rm -rf, force-push,DROP TABLE— quelli che possono fare danni veri — vengono fermati e chiesti a parte. - Identità isolata: ogni finestra ha un profilo di identità separato (token GitHub / AWS / npm, identità git, SSH key); l’agent ottiene quell’identità circoscritta, non l’intero portachiavi della mia macchina.
- Trust esplicito: decido io quale agent è affidabile; solo gli agent autorizzati possono scrivere senza conferma.
- Legge davvero gli errori: riesce a scansionare le righe sullo schermo che sembrano errori — vede il risultato reale, non lo immagina.
Il default è il livello «conservativo»: un agent appena connesso, che non ho ancora autorizzato, deve passare da me per qualsiasi scrittura. Una volta che l’ho visto girare qualche ciclo e ho confermato che è affidabile, sblocco in blocco la categoria di comandi sicuri che usa di solito. Nel periodo di rodaggio è un po’ più lento, ma almeno non mi fa saltare il cuore alla prima mossa.
Chi lavora con gli agent abbastanza a lungo ci cascherà per forza: l’agent che digita un rm -rf con piena sicurezza per «pulire la cache», ma con il percorso sbagliato di mezza riga. Una persona prima di premere invio fa una pausa di mezzo secondo; l’agent no — questo stop, il terminale lo deve aggiungere al suo posto.
3. Registrazione: quando l’agent ha finito, voglio poter riavvolgere
È la funzione che uso di più, e senza cui non saprei stare.
L’agent gira tre ore senza sorveglianza, e quando torni vuoi sapere cosa ha fatto davvero. Leggere solo il suo riassunto non basta — potrebbe aver omesso qualcosa, abbellito, o anche costruito una storia. Quello che vuoi è il log grezzo: ogni comando, ogni blocco di output, esattamente com’era.
Così Unterm registra l’intera sessione dall’inizio alla fine: cosa ha digitato l’agent, cosa ha risposto il terminale — tutto salvato in un log riproducibile, che puoi riavvolgere come un video o sfogliare riga per riga. Durante la registrazione, token e chiavi vengono automaticamente oscurati, così il log stesso non diventa un nuovo vettore di fuga di dati.
È la scatola nera dell’agent: se qualcosa va storto, riavvolgi e vedi dove ha deragliato; se è andato bene, lo tieni come demo o materiale di analisi.
Un esempio della settimana scorsa: un agent ha fatto fallire una serie di test, e poi ha dichiarato con piena sicurezza «risolto». Ho riavvolto la sessione fino al punto in cui aveva modificato il codice, e in pochi minuti è stato chiaro — per far diventare verdi i test aveva commentato silenziosamente un’asserzione. Se avessi avuto solo il suo riassunto, non l’avrei mai beccato. Il log si può esportare intero, e l’ho usato più volte come materiale di spiegazione per «come lavora davvero un’IA».
La metà della fiducia che mi permette di lasciare un agent a girare senza sorveglianza viene da questo log riavvolgibile.
4. Parallelismo: da un pezzo ormai non apro un agent solo
La normalità ormai è tre o quattro agent che girano insieme: uno sul frontend, uno sulla migrazione del database, uno a completare i test. In un terminale normale sono tre o quattro schermate nere, e io con alt-tab a saltare dall’una all’altra, perdendomi il filo di chi aspetta il mio ok e chi si è bloccato a fare niente.
Unterm ha reso fluido il «gestire un gruppo»:
- Lancio in blocco: un comando apre una nuova finestra e gli assegna il lavoro direttamente.
- Broadcast: voglio che tutti e quattro gli agent «tirino il codice nuovo e facciano girare la build»? Un comando a tutte le finestre, senza incollare quattro volte.
- Attesa selettiva: dopo aver assegnato il lavoro, posso aspettare che una certa finestra segnali «finito / errore» prima di tornarci.
In concreto, una mattina tipo è più o meno così: apro tre finestre, assegno «rifai la pagina di login con il nuovo design», «migra la tabella degli ordini al nuovo schema», «scrivi i test per la logica di checkout», poi mando in broadcast «posta un aggiornamento ogni dieci minuti», e vado a rispondere ai messaggi. Torno, do un’occhiata allo stato delle tre finestre, entro in quella bloccata e scambio due righe, le altre le lascio andare. Da «tenerle d’occhio una alla volta» sono passato a «scansionare una fila».
Il mio lavoro ormai non è scrivere codice — è orchestrare una squadra di agent (ne ho parlato nell’articolo precedente). E per orchestrare devi avere una plancia di comando che funziona, non quattro schermate nere che non si conoscono tra di loro e che devo tenere dritto io con la memoria.
5. Finestre: più agent ci sono, più il desktop va in caos
Quando girano in squadra, il casino non è nei comandi — è nello spazio: quale finestra sta facendo il deploy, quale è quella aperta al volo per provare una cosa, quale è quella a cui ho dato lavoro due ore fa e non ha ancora risposto? A tenerlo a mente, bastano in pochi e già si confonde tutto.
Ho messo in piedi l’ordine più elementare:
- Le finestre hanno nomi: alpha, bravo, charlie — non numeri che non ricordi. Fatto reale: mentre scrivo questo articolo, sulla mia macchina ci sono due istanze Unterm attive — alpha aperta nella directory del sito doaipm, bravo in questo repository di contenuti — e a un’occhiata so già chi è chi.
- Il layout si salva e si ricarica: pannelli smontati, finestre disposte — si salvano come workspace e il giorno dopo si riaprono identici, senza rimettere i pezzi insieme ogni volta.
- Si chiama per nome: l’agent può dire «porta in primo piano la finestra del deploy» e non devo frugare tra una dozzina di riquadri.
Il workspace sembra una funzione piccola — in pratica fa davvero risparmiare tempo: ho un layout fisso per «pubblicare un articolo» — una finestra sulla directory del sito, una sul repository di contenuti, una per la build, una per i log — salvato come workspace; ogni mattina apro tutto con un click, quattro finestre con la cwd già al posto giusto, senza dover rifare i cd e riordinare da capo.
La differenza tra dodici finestre anonime e una plancia in cui sai il nome di ognuna — è tutta qui.
E tmux? E Warp?
Ti chiederai: tmux ha già i multi-panel da anni, Warp ha già cucito l’IA dentro — cosa stai aggiungendo tu?
tmux l’ho usato per anni, fa benissimo i multi-panel, ma è progettato per le dieci dita di un essere umano: non sa se dietro c’è un agent, non gli importa se quel comando cancella il database, non sa che sei in Cina e ogni comando che deve uscire dalla rete si impicca nei timeout. Warp è un’altra strada — ha cucito un assistente IA nel terminale — ma è «IA che sta dentro il terminale», non «terminale guidato dall’IA dall’esterno»: il protagonista è ancora la persona davanti allo schermo, l’agent è al massimo il co-pilota, e il discorso proxy e reti cinesi non lo tocca. iTerm e Windows Terminal li uso tutti i giorni anch’io, sono buoni terminali — ma il metro di «buono» è ancora «comodo per una persona»: colori, font, scorciatoie, split — nessuno ha progettato «chi digita è un agent» come cittadino di prima classe.
Entrambe le strade sono valide, solo che nessuna delle due risponde alla mia domanda: quando il protagonista passa dall’essere umano all’essere un agent, come deve essere fatto il terminale? Il proxy, il cancello di sicurezza, il log riavvolgibile, l’orchestrazione in gruppo, le finestre con nome — per me non sono funzioni separate: sono facce dello stesso problema.
Per concludere
Di terminali ce ne sono ovunque, e farne uno in più è una cosa che sento di dover spiegare anche a me stesso.
Il motivo è uno solo: non volevo fare un terminale migliore — volevo fare un terminale il cui utente predefinito non è umano. Niente di quello che sta sopra viene da una roadmap — viene tutto dai problemi che in quel periodo mi stavano facendo venire i nervi davvero.
C’è anche un punto abbastanza concreto: Unterm stesso l’ho descritto all’IA in parole semplici, dal terminale — il codice di produzione non l’ho scritto io. Ho spiegato «deve poter essere guidato da un agent, deve sapersi cambiare il proxy da solo, deve bloccare rm -rf, deve poter essere riavvolto tutto intero», e l’IA l’ha costruito. Detto chiaro, lo costruisce — è così che lavoro da sempre.
Se il mondo avesse bisogno di un altro terminale, non lo so. Di sicuro ne avevo bisogno io.
Per approfondire
- Articolo precedente: Da esecutore a orchestratore: il tuo nuovo lavoro è dirigere una flotta di agent
- Sito ufficiale / repository open source di Unterm: unterm.app · GitHub
zhitongblog/unterm
Discussione