8 pontos por GN⁺ 2025-11-13 | 1 comentários | Compartilhar no WhatsApp
  • 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

 
GN⁺ 2025-11-13
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, eat etc.) ou mudar para um fluxo em estilo REPL (shell-mode, eshell etc.). Há suporte gráfico, embora não seja um contexto 2D completo
    Outro 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

    • O Emacs tem Org-mode e org-babel, então pode funcionar como um Jupyter notebook. Ele inclusive consegue se comunicar com kernels do Jupyter
      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
    • Quero saber mais sobre o Acme. Foi difícil pesquisar sobre ele.
      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
    • Acho que o ponto central do texto é abrir o modelo de dados do terminal. O importante é que isso permitiria implementar várias funcionalidades por cima
    • O aspecto único do Emacs é a independência da UI. Aplicativos escritos em Elisp funcionam do mesmo jeito tanto no terminal quanto na GUI. Eu já escrevia Elisp no terminal há 20 anos, e usuários de GUI nem percebiam a diferença. Não existe outra plataforma assim
  • 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

    • Na prática, o terminal não é centrado em texto, mas em fluxos bidirecionais de tokens. É essa simplicidade que permite a composição ao estilo Unix.
      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
    • Também concordo com as limitações de stdin/stdout da CLI. O fato de dados e apresentação serem a mesma coisa limita a composabilidade.
      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 PowerShell é interessante, mas tem a desvantagem de ir ficando cada vez mais próximo de uma linguagem de programação.
      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
    • Eu também gosto bastante do Nushell. É mais limpo que o PowerShell e não depende da Microsoft
      https://www.nushell.sh/
    • Alternativas de terminal não baseadas em texto já existem.
      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:

    • Arcan — propõe um novo protocolo para aplicações TUI
    • Shelter — um shell de sistema de arquivos com ramificações, como o Git
    • O Shelter exige snapshots do sistema de arquivos, mas é uma ideia realmente muito boa
    • Acho que qualquer texto que não mencione o Arcan fica incompleto. Ele já pode ser usado hoje
      • Nunca tinha ouvido falar, mas parece realmente muito interessante. Obrigado pelo link
  • 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

    • Eu também estava procurando um sistema assim. Parece ser mais adequado para LLMs ou para ambientes pessoais de trabalho
    • Colocar o conceito de notebook no Windows Terminal é realmente uma ideia muito boa. Espero ver mais tentativas desse tipo
  • 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 comando

    • Mas esse tipo de funcionalidade não é papel do terminal, e sim de programas separados (fbi, omxplayer etc.)
  • 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

    • JSON não é adequado para isso. Formatos binários como DER ou SDSER seriam mais eficientes
    • Uma abordagem moderna é enviar mensagens voltadas ao usuário para stderr e o JSON amigável para máquina para stdout
      Assim, pipelines e redirecionamentos continuam funcionando como antes, e a saída colorida também é preservada