Que separador era esse? Grupos de separadores para o Claude Code no macOS
Cinco sessões do Claude Code, cinco separadores a dizer zsh. O Smart Terminal junta grupos, estado do Claude e alertas a um terminal tipo Terminal.app.
Ter cinco sessões do Claude Code abertas no Terminal.app significa cinco separadores que dizem todos zsh, e nenhuma forma de saber qual deles está à tua espera há vinte minutos. Construí o Smart Terminal, um terminal nativo para macOS que mantém tudo o que gosto no Terminal.app e acrescenta grupos de separadores ao estilo do Chrome, separadores que se nomeiam a partir da sessão do Claude que têm lá dentro, e uma notificação quando uma delas precisa de ti. Passou de uma pasta vazia a uma versão pública e notarizada em cerca de duas horas.
Era uma tarde normal: cinco sessões do Claude Code abertas ao mesmo tempo. Umas quantas com trabalho de clientes, outras com documentos, e uma num plugin de WordPress.
Todos os separadores diziam zsh.
Algures ali, uma sessão tinha terminado vinte minutos antes e estava parada à espera de uma resposta. Encontrei-a a clicar nos separadores, um a um.
Índice
- Só separadores não resolvem
- O que o Smart Terminal faz
- Separadores que sabem que o Claude está lá dentro
- O Claude Code já escreve tudo
- Trazer os separadores do Terminal.app
- Feito numa tarde, com o Claude Code
- O que correu mal
- Instalar
Só separadores não resolvem
O Terminal.app é um bom terminal. Uso-o há anos, com um perfil que afinei uma vez e nunca mais toquei. Mas os separadores são só uma fila de nomes de shell.
Os browsers resolveram isto há algum tempo. O Chrome deixa-te juntar separadores num grupo com nome e cor, e recolhê-lo quando não estás a olhar para ele. O Terminal.app tem uma coisa chamada grupos de janelas, mas são disposições guardadas, não grupos com que se trabalha.
Procurei um terminal nativo para macOS com grupos de separadores a sério e não encontrei nenhum. O mais próximo, o TabTerm, chega lá correndo os terminais dentro do Chrome para aproveitar os grupos do Chrome. É engenhoso, e confirmou-me que a lacuna era real.
Dar nomes também não chegava. O meu problema não era só "qual é o separador da API". Era "qual destas sessões do Claude está à minha espera".
O que o Smart Terminal faz

- Podes dar nome a qualquer separador e juntar separadores em grupos com nome, nas nove cores do Chrome. Um clique no chip do grupo recolhe-o até ficar só uma contagem.
- O sítio onde largas um separador decide o grupo: entre dois separadores de um grupo, junta-se a ele. Arrasta um chip para mover o grupo inteiro, para outra janela ou para o ambiente de trabalho, onde se torna uma janela nova.
- Continua a parecer o Terminal.app. Lê o teu perfil predefinido do Terminal.app, incluindo tipo de letra, cores e transparência, e a barra de título mostra os mesmos detalhes em direto: pasta, título do programa, comando em execução e tamanho da janela.
- Um separador com o Claude Code assume o nome da sessão e mostra se o Claude está a trabalhar, parado ou à tua espera.
- Quando um Claude que não estás a ver termina ou chega a um pedido de permissão, recebes uma notificação do macOS, e o ícone na Dock conta quantos estão à espera.
- Os separadores lembram-se da sessão do Claude que estavam a correr e oferecem-se para a retomar depois de reiniciar, com as mesmas opções.
A disposição sobrevive a um reinício: janelas, grupos, cores, nomes e a pasta onde cada separador estava.
Separadores que sabem que o Claude está lá dentro
Um separador com o Claude Code dá a si próprio o nome da sessão. Usa o teu /rename se o definiste, senão o título curto que o Claude escreve para cada sessão, senão "Claude · pasta". "Add Stripe webhook retries" é bem mais útil do que zsh.
O estado também vive no separador. Enquanto o Claude trabalha, o separador mostra a mesma meia-lua que o Claude anima no título do próprio terminal, ◐ e ◑. Quando fica parado, aparece ✳. Quando está bloqueado num pedido de permissão, aparece um balão laranja.
Se mudares o nome do separador, o teu nome ganha, mas o estado em direto continua à frente dele.
A notificação só aparece para separadores que não estás a ver: a aplicação está em segundo plano, ou é outro separador. Clicas nela e vais parar a esse separador. Foi por causa desta notificação que comecei isto.
O Claude Code já escreve tudo
Tal como no wims, a maior parte do trabalho já estava feita pelo Claude Code. Só não estava à vista.
Cada processo do Claude em execução escreve um pequeno ficheiro em ~/.claude/sessions/, com o nome do seu process id:
{"pid":25965,"sessionId":"9b4e…","cwd":"/Users/me/code/api","status":"busy", …}
O estado é busy, idle ou waiting, e quando está à espera há um campo waitingFor que diz porquê, por exemplo permission prompt. O título que o Claude define no terminal não te diz isto, e é precisamente o estado que mais me interessa.
O process id é a parte útil. Um terminal já sabe qual é o grupo de processos em primeiro plano em cada separador, e num separador com o Claude, esse grupo é o processo do Claude. Por isso a deteção é exata, sem ler o ecrã nem mexer na configuração da tua shell.
Podes ver os teus agora mesmo:
cat ~/.claude/sessions/*.json
O nome vem da transcrição da sessão, onde o Claude acrescenta entradas ai-title, custom-title, last-prompt e pr-link. As transcrições ficam grandes, por isso o Smart Terminal lê de trás para a frente até encontrar um título, e depois só lê os bytes novos.
Encontrei mais uma coisa no código do Claude enquanto construía isto. O Claude Code consegue enviar as suas próprias notificações ao terminal, mas escolhe o método conforme o terminal que deteta. Para qualquer terminal que não reconheça, não envia nada. Ler o ficheiro da sessão contorna isso sem teres de mudar nenhuma definição.
Trazer os separadores do Terminal.app
Mudar de terminal custa quando tens uma dúzia de sessões abertas. Por isso existe Shell → Import Tabs from Terminal.app…
Mostra os separadores abertos no Terminal.app, agrupados por pasta de projeto, cada um com uma caixa de seleção:
- As sessões do Claude são passadas de mão. O Smart Terminal escreve
/exitna sessão no Terminal.app, espera que pare, e retoma-a comclaude --resumee as mesmas opções. Uma sessão nunca corre em dois sítios ao mesmo tempo. - As sessões de tmux são religadas aqui, e o cliente do Terminal.app é desligado. Nada dentro do tmux reinicia.
- As shells normais reabrem na mesma pasta.
As sessões ocupadas aparecem desmarcadas, porque passá-las de mão interrompe-as a meio. Esse cuidado conta mais do que parece: a própria sessão do Claude que estava a construir esta funcionalidade estava na lista.
Feito numa tarde, com o Claude Code
Comecei com uma pasta vazia às 14:21. A versão 0.5.0, notarizada, estava pública no GitHub às 16:20.
Pelo meio, numa única sessão do Claude Code: um modelo central testado para separadores e grupos, a aplicação em Swift sobre o SwiftTerm, tudo o que descrevi acima, e um processo de release que assina, notariza e empacota um DMG universal. O resultado são cerca de 4500 linhas de Swift e 52 testes, incluindo um aleatório que atira 8000 operações de separadores e grupos a duas janelas e confirma que nada se perde.
O meu papel foi o mesmo que no trabalho com WordPress sobre o qual já escrevi: decidir o que devia ser, testar com as minhas mãos, e dizer que não quando alguma coisa não parecia bem.
O truque mais útil foi dar olhos ao agente. Ele não conseguia tirar capturas de ecrã no meu Mac, por isso construiu um pequeno canal de debug nas versões de desenvolvimento. Esse canal abre separadores, escreve neles, muda-lhes o nome, agrupa-os e desenha a janela num PNG a partir de dentro da aplicação. A partir daí, verificava o próprio trabalho visualmente antes de me dizer que estava feito.
O que correu mal
Algumas coisas, e a maioria só apareceu a correr a aplicação.
Mover um separador para uma janela nova rebentava a aplicação. O código lia a disposição enquanto a estava a alterar, e as verificações de exclusividade do Swift paravam tudo. Os testes unitários nunca passavam por esse caminho. O canal de debug passou, logo à primeira.
tab quer dizer duas coisas em AppleScript. A leitura dos separadores para importar vinha vazia. Dentro de tell application "Terminal", a palavra tab refere-se ao objeto separador do Terminal, e não ao carácter de tabulação que eu usava para separar os campos.
Um bug que não era um bug. O primeiro turno terminado do Claude depois de abrir a aplicação nunca aparecia como a precisar de atenção. Os seguintes, sim. Depois de registar cada mudança, a resposta era banal: eu tinha clicado na notificação, que é suposto limpar esse estado.
O nome do processo é um número de versão. Os títulos dos separadores chegaram a mostrar my-project · 2.1.281, porque o binário do Claude vive numa pasta com a versão e é isso que o sistema reporta como nome. A deteção passa pelo ficheiro da sessão.
Instalar
Descarrega o DMG na página de releases, abre-o e arrasta o Smart Terminal para Aplicações. É uma versão universal, assinada e notarizada, e precisa do macOS 26 (Tahoe) ou mais recente.
Há limites. O Claude a correr dentro do tmux ainda não é detetado, porque o separador só vê o cliente do tmux. O macOS usa ⌃← e ⌃→ para mudar de Spaces por omissão, por isso mover um separador dentro do grupo tem uma alternativa com ⌃⌥. Ainda não há atualizações automáticas.
O Smart Terminal tem licença MIT e o código está no GitHub. Não faz pedidos à rede.
Se os teus separadores dizem todos zsh e um deles está à tua espera, agora já sabes qual é.
Links: Smart Terminal no GitHub · wims · Documentação do Claude Code · SwiftTerm
Tags: Claude Code, macOS, Terminal, ferramentas de developer