- Aponta a complexidade e os limites da arquitetura tradicional de terminais e propõe um conceito de terminal de próxima geração que reintegra entrada, saída e controle de processos
- Toma o Jupyter Notebook como modelo para explorar a viabilidade de uma interface interativa, com renderização de imagens, reexecução de comandos, saída editável e editor embutido
- Usa os casos de Warp e iTerm2 para explicar de forma concreta a integração profunda entre shell e terminal (shell integration), o gerenciamento de processos de longa duração e os recursos de separação e recuperação de sessão
- Com base em dataflow tracking e persistência, imagina recursos estendidos como undo/redo de comandos, reexecução automática e terminais colaborativos
- Apresenta uma estratégia de construção incremental que evolui de CLI transacional → sessões persistentes → RPC estruturado → frontend no estilo Jupyter
Estrutura básica do terminal
- Um terminal é composto por quatro elementos: emulador de terminal, terminal virtual (PTY), shell e grupo de processos
- O emulador de terminal é o programa que renderiza uma estrutura em grade na tela
- O PTY é um estado interno do kernel, responsável por encaminhar a entrada ao grupo de processos e converter sinais (signals)
- O shell funciona como um loop de eventos que lê e faz o parsing da entrada e cria processos
- Os processos interagem com os componentes acima por meio de entrada e saída
- A entrada não é apenas texto simples, mas inclui sinais (signals); a saída é composta por sequências de escape ANSI, que expressam formatação
A visão de um terminal melhor
- Os terminais atuais têm muitas limitações funcionais e carecem de extensibilidade e interatividade
- O Jupyter Notebook oferece recursos impossíveis em um emulador VT100 tradicional
- Renderização de imagens em alta resolução
- Um botão de "executar novamente do zero" que substitui saídas anteriores sem apenas anexar novas saídas
- "Views" que permitem reescrever no próprio lugar o código-fonte e a saída (por exemplo, mostrar Markdown como fonte ou como HTML renderizado)
- Um editor embutido com realce de sintaxe, abas, painéis e suporte a mouse
- Porém, a ideia de um notebook Jupyter usando o shell como kernel enfrenta vários problemas
- O shell recebe os comandos de uma vez só, então completar com Tab, realce de sintaxe e sugestões automáticas não funcionam
- Problemas com processos de longa duração: o Jupyter, por padrão, executa até a célula terminar; é possível cancelar, mas não é possível pausar, retomar, interagir nem ver processos em execução
- O botão de "reexecutar célula" pode causar problemas no estado do computador (especialmente se incluir comandos como
rm -rf)
- Undo/redo não funciona
Como isso funcionaria?
-
Integração com o shell (Shell Integration)
- O terminal Warp constrói uma integração nativa entre terminal e shell
- O terminal entende o início e o fim de cada comando, sua saída e a entrada do usuário
- Isso é implementado usando recursos padrão (DCS customizado)
- O iTerm2 também permite uma abordagem semelhante com os códigos de escape OSC 133
- Navegação entre comandos com uma única tecla de atalho
- Notificações quando um comando termina
- Exibição do comando atual como um "overlay" quando a saída sai da área visível da tela
-
Gerenciamento de processos de longa duração
- Interação (interacting):
- Para interagir com processos longos, é necessária comunicação bidirecional
- Exemplos de TUI:
top, gdb, vim
- O Jupyter tem pontos fortes no desenho de saída interativa que pode ser alterada e atualizada
- Recurso esperado do terminal: sempre oferecer uma "célula de entrada livre"
- O processo interativo roda na parte superior da janela e a célula de entrada fica na parte inferior
- Suspensão (suspending):
- "Pausar" um processo é chamado de controle de jobs (job control)
- Espera-se que terminais modernos mostrem uma indicação visual persistente de processos pausados e em segundo plano
- Similar à forma como o IntelliJ mostra "indexando..." na barra inferior
- Desconexão (disconnecting): há três abordagens para separação e recuperação de sessão
- Tmux / Zellij / Screen: inserem um emulador de terminal adicional entre o emulador real e o programa. O servidor possui o PTY e renderiza a saída, enquanto o cliente exibe a saída no emulador real. Permitem desconectar o cliente, reconectar e conectar múltiplos clientes ao mesmo tempo. O iTerm atua como seu próprio cliente, contornando o cliente tmux e se comunicando diretamente com o servidor
- Mosh: substituto do SSH. Permite reconectar à sessão do terminal após interrupções de rede. Executa uma máquina de estados no servidor e reproduz no cliente as diferenças incrementais do viewport. Presume que multiplexação e scrollback serão tratados pelo emulador de terminal. Como o cliente realmente roda no lado da rede, a edição local de linha é imediata
- alden/shpool/dtach/abduco/diss: lidam apenas com separar/retomar sessões via cliente/servidor, sem incluir rede, scrollback ou um emulador de terminal próprio. Têm um nível de separação mais alto que tmux e mosh
-
Reexecução e reversão
- A solução é o rastreamento de fluxo de dados
- O pluto.jl já faz isso hoje ao se conectar ao compilador Julia
- Atualiza em tempo real células que dependem de células anteriores
- Não atualiza células se as dependências não mudarem
- É como um Jupyter semelhante a uma planilha, reexecutando código apenas quando necessário
- Generalização por meio de persistência ortogonal (orthogonal persistence)
- Isolar processos em sandbox e rastrear todo o I/O, evitando coisas "estranhas demais" desde que não se comuniquem com outros processos fora da sandbox
- Passa a ser possível tratar um processo como uma função pura de suas entradas, sendo as entradas "todo o sistema de arquivos, todas as variáveis de ambiente e todas as propriedades do processo"
Recursos derivados
- Exigem um frontend Jupyter:
- Runbooks (na prática, já podem ser construídos apenas com Jupyter e primitivas de PTY)
- Customização do terminal com CSS comum, sem linguagens estranhas personalizadas nem códigos de cor ANSI
- Busca de comandos por saída/timestamps: hoje é possível buscar em toda a saída da sessão atual ou em todo o histórico de entrada de comandos, mas sem filtros inteligentes e sem persistência de saída entre sessões
- Exigem integração com o shell:
- Timestamps e tempo de execução de cada comando
- Edição local de linha mesmo atravessando fronteiras de rede
- IntelliSense para comandos de shell sem precisar pressionar Tab, com renderização integrada ao terminal
- Exigem rastreamento de sandbox:
- Todos os recursos do rastreamento de sandbox: terminal colaborativo, consulta de arquivos modificados por um comando, asciinema editável em tempo de execução, rastreamento de sistemas de build
- Extensão da busca inteligente para também pesquisar o estado do disco no momento em que o comando foi executado
- Expansão de undo/redo para um modelo de ramificações semelhante ao git (o emacs undo-tree já oferece isso), com diferentes "views" da árvore de processos
- Com o modelo de undo-tree e sandboxing, torna-se possível dar a LLMs acesso ao projeto e executar várias em paralelo ao mesmo tempo, sem que sobrescrevam o estado umas das outras, permitindo inspecionar, editar e salvar o trabalho como runbooks para uso posterior
- Um terminal que apenas inspeciona o estado existente em produção, sem afetar o estado da máquina
Estratégia de construção por etapas
-
Etapa 1: semântica transacional (transactional semantics)
- Ao redesenhar o terminal, começar pelo emulador de terminal é a abordagem errada
- Usuários se apegam ao emulador, às configurações, ao visual e aos atalhos de teclado
- O custo de trocar de emulador é alto
- O caminho certo é começar pela camada de CLI
- Programas de CLI são fáceis de instalar e executar, e o custo de troca é muito baixo
- Dá para usá-los pontualmente sem mudar o fluxo de trabalho inteiro
- Escrever uma CLI que implemente semântica transacional para o terminal
- Uma interface como
transaction [start|rollback|commit]
- Tudo o que for executado após
start pode ser desfeito
- Só isso já seria suficiente para construir todo um negócio
-
Etapa 2: sessões persistentes (Persistent Sessions)
- Após garantir a semântica transacional, separar a persistência de tmux e mosh
- Para obter persistência de PTY, é preciso adotar um modelo cliente/servidor
- O kernel presume que ambos os lados do PTY estarão sempre conectados
- É possível implementar isso de forma simples, sem afetar o emulador de terminal nem os programas em execução dentro da sessão PTY, usando comandos como alden ou bibliotecas semelhantes
- Para obter scrollback, o servidor armazena indefinidamente a entrada e a saída e as reproduz quando o cliente se reconecta
- O emulador de terminal oferece scrollback nativo tratado como qualquer outra saída
- É possível reproduzir e retomar a partir de um ponto arbitrário
- É necessário fazer parsing de códigos de escape ANSI, mas isso é viável com trabalho suficiente
- Para retomada de rede ao estilo mosh, usar Eternal TCP (podendo ser construído sobre QUIC para maior eficiência)
- Separar a persistência do PTY da persistência da conexão de rede
- Eternal TCP é pura otimização: pode ser construído por cima de um script bash que execute
ssh host eternal-pty attach em loop
- Nesse ponto, como no tmux, vários clientes podem se conectar à mesma sessão de terminal, enquanto o gerenciamento de janelas continua sendo responsabilidade do emulador
- Se quiser gerenciamento de janelas integrado, o emulador pode usar um protocolo como o tmux -CC, à maneira do iTerm
- Todas as partes desta etapa podem ser feitas em paralelo e independentemente da semântica transacional, mas ainda não bastam para construir o negócio
-
Etapa 3: RPC estruturado
- Depende do modelo cliente/servidor
- Quando um servidor fica entre o emulador e o cliente, torna-se possível implementar recursos como marcação de I/O com metadados
- É possível adicionar timestamps a todos os dados
- É possível distinguir entrada de saída
- O xterm.js funciona de maneira semelhante
- Em combinação com a integração com o shell, isso permite distinguir no nível de dados o prompt do shell da saída dos programas
- Obtém-se um log estruturado da sessão do terminal
- Reproduzir o log como uma gravação, como no asciinema
- Transformar prompts do shell sem reexecutar todos os comandos
- Importar para o Jupyter Notebook ou para o Atuin Desktop
- Salvar comandos e reexecutá-los depois como scripts
- O terminal vira dado
-
Etapa 4: frontend semelhante ao Jupyter
- É a primeira etapa que mexe no emulador de terminal e, de propósito, a última
- Porque tem o maior custo de troca
- Usar todos os recursos construídos para oferecer uma boa UI
- A CLI
transaction deixa de ser necessária, a menos que se queira transações aninhadas
- Toda a sessão de terminal passa a começar como uma transação por padrão
- Como todas as peças foram combinadas, torna-se possível oferecer todos os recursos derivados mencionados acima
Conclusão
- Essa arquitetura é ousada, ambiciosa e deve levar cerca de 10 anos para ser construída por completo
- É preciso avançar com paciência, passo a passo
- Espera-se que este texto inspire alguém a começar a construí-la por conta própria
1 comentários
Comentários do Hacker News
Depois de ler o texto inteiro, a primeira impressão foi que parecia apenas uma lista de desejos no estilo NIH
Já existem várias alternativas capazes de substituir o terminal, mas o texto não menciona nenhuma delas
Por exemplo, o Emacs é uma VM baseada em Lisp, na qual é fácil redefinir funções, e os comandos são funções documentadas com comentários. A saída é gerenciada por buffers, e várias janelas e frames podem ser organizados em mosaico. Também é possível usar a CLI como está (
vterm,eatetc.) ou mudar para um fluxo em estilo REPL (shell-mode,eshelletc.). Há suporte gráfico, embora não seja um contexto 2D completoOutro exemplo é o Acme, parecido com o Emacs, mas que é um ambiente de texto interativo em que todo texto pode se tornar um comando. O Smalltalk segue uma filosofia semelhante, mas é mais próximo de uma IDE
Eu uso o GPTel no Emacs para recortar automaticamente um PDF antigo de material didático em latim, aplicar OCR e converter para o formato org-mode. Como resultado, ao selecionar uma palavra, posso consultar imediatamente o dicionário, e ao selecionar uma frase, um LLM faz a análise gramatical. Um editor de texto dos anos 1970 acabou virando uma plataforma de aprendizado futurista
Plataformas como Emacs, Jupyter e VSCode são poderosas, mas, em vez de aplicações prontas, parecem mais plataformas baseadas em customização.
Se a ideia for realmente inovadora, ela precisa ser distribuída de uma forma facilmente reproduzível, como contêineres Docker ou executáveis, em vez de depender de configurações complexas
Tenho dúvidas se o sucessor do terminal precisa mesmo ser baseado em texto
O terminal do futuro pode ser uma API, com chamadas remotas via autenticação OAuth. A entrada e a saída talvez já não precisem mais ser texto de CLI.
Em vez disso, poderíamos migrar para entrada/saída baseada em objetos, tornando comandos e estruturas de dados exploráveis via API.
O terminal é um legado dos anos 1970, e hoje já é perfeitamente possível ter alternativas melhores
Se você adicionar saída em JSON, pode montar pipelines com ferramentas como
jq.A simplicidade é justamente a força da filosofia de “worse is better”, que permitiu sua evolução ao longo de décadas
Se fosse possível trocar objetos autodescritivos, como no PowerShell, a composição seria muito mais poderosa
Reuni exemplos relacionados neste post do meu blog
O fluxo intuitivo baseado em comandos vai se perdendo, e você passa a precisar decorar a estrutura das APIs.
Se houvesse autocompletar com IA e recursos para explorar a estrutura dos objetos, isso poderia compensar essa fraqueza
https://www.nushell.sh/
Mesmo assim, um terminal evoluído baseado em texto continua interessante quando vem acompanhado de propostas concretas e imagináveis
O terminal sobreviveu até hoje por causa da compatibilidade e da possibilidade de automação
É mais fácil de transformar em script do que uma GUI, e tudo é reproduzível e pesquisável
Antigamente eu me incomodava com a troca para a alt-screen no Neovim, mas esses detalhes finos de UX também importam
Eu me apaixonei duas vezes: quando conheci computadores pela primeira vez, e quando aprendi a usar o terminal
Alguns projetos relacionados:
Fiz uma experiência parecida no Windows Terminal há 18 meses
Está registrada neste comentário no GitHub
Mas depois de usar Polyglot Notebooks, mudei porque aquilo pareceu muito mais natural
Trocar o backend imperativo por um kernel do Jupyter e usar isso como um documento interativo em estilo notebook é muito mais eficiente
No passado eu criei um projeto chamado TopShell, um shell+terminal baseado em programação funcional
https://github.com/topshell-language/topshell#readme
Há potencial, mas ainda falta muito trabalho para virar uma alternativa completa
Eu estava procurando um terminal capaz de exibir imagens ou vídeos
Seria bom ter um terminal que simplesmente funcionasse como um navegador.
Por exemplo, algo como
browser google.com/maps, abrindo diretamente de forma interativa por comandofbi,omxplayeretc.)A proposta é expandir o pseudo-terminal (PTY) e adicionar um canal out-of-band baseado em JSON-RPC
As escape sequences atuais têm muitas limitações.
Desse jeito, seria possível fazer uma transição gradual e retrocompatível.
Assim como em LSP ou MCP, seria possível negociar funcionalidades, e o kernel só precisaria fornecer o canal
stderre o JSON amigável para máquina parastdoutAssim, pipelines e redirecionamentos continuam funcionando como antes, e a saída colorida também é preservada