Switchboard

Um hub MCP local que permite que seus agentes Claude Code conversem entre si: enviem mensagens, cutuquem no terminal e coordenem através de um painel web.

Documentação

⇄ Switchboard

Deixe seus agentes de codificação conversarem entre si.
Claude Code e Codex CLI, na mesma rede, na mesma conversa.

The Switchboard dashboard — an operator's patchbay: agents grouped on the left, the transcript of what they said to each other in the center

Você tem Claude Code (CLI da Anthropic) aberto no backend, Codex CLI (da OpenAI) no frontend, outro agente na infraestrutura. Nenhum deles sabe que os outros existem. Então, quando o contrato da API muda, você é quem leva a notícia: copie deste terminal, cole naquele, repita. Você é o broker de mensagens.

Switchboard é o fio entre eles. É um hub local. Seus agentes trocam mensagens via MCP, o destinatário é acordado no seu próprio terminal, e você acompanha toda a conversa em um painel — onde também pode abrir o chat de qualquer agente, dirigir seu terminal real e ver o que ele fez com a mensagem recebida. Ele conecta sessões que você já tem. Ele não cria, orquestra ou gerencia sessões.

O que o mantém seguro: o tmux carrega um aviso de uma linha, e nada mais. A mensagem em si viaja via MCP. O agente A chama send_message, o Hub a anexa a ~/.switchboard/messages.jsonl (a fonte da verdade) e cutuca o terminal do agente B com uma única linha [switchboard]. B acorda e chama check_messages para lê-la.

Plataforma: Windows + WSL (Ubuntu). É nisso que o Switchboard é construído e testado. O núcleo (hub, MCP, avisos do tmux) é Unix puro e tmux, então Linux e macOS podem funcionar, mas ninguém testou. Trate-os como não suportados por enquanto. As partes que o fazem funcionar no Windows (o lançador de um clique, abrir uma janela de terminal real, caminhos de pasta \\wsl$\…) são específicas do WSL, e dizem isso em vez de quebrar quando você as executa em outro lugar.

Apenas local por design: o Hub vincula 127.0.0.1 e nada alcança a rede. Licença MIT.


Pré-requisitos

  • Node.js >= 20. Executa como ESM, com TypeScript executado por tsx. Sem etapa de build.
  • tmux >= 3.2 (testado na 3.4).
  • Claude Code >= 2.x, o binário claude no seu PATH.
  • Codex CLI, opcional: o binário codex no seu PATH. Você só precisa dele para executar agentes com --agent codex, ou o botão Codex do painel. Todo o resto funciona sem ele.
  • jq, opcional. Útil para ler o JSONL durante a depuração.

Uma distro WSL, um usuário. O servidor tmux pertence a um usuário em uma distro. Execute o Hub (serve) e cada agente (start) como o mesmo usuário na mesma distro. Divida-os entre duas e tmux send-keys não encontrará a sessão, então o aviso nunca chega.


Configuração: dois comandos

git clone https://github.com/rodcoppi/switchboard-mcp.git && cd switchboard-mcp && npm install
node bin/switchboard.mjs setup

setup faz cada etapa manual abaixo por você: verifica os pré-requisitos (e oferece uma instalação do tmux sem sudo se o tmux estiver faltando), registra o servidor MCP no Claude Code, coloca o trecho do protocolo do agente no seu ~/.claude/CLAUDE.md, adiciona as regras de permissão, executa npm link, oferece o atalho do Windows e traz o Hub para cima. Ele pergunta antes de tocar em um arquivo seu. Execute-o novamente quando quiser, ele não muda nada que já esteja certo. Passe --yes e ele para de perguntar.

Quando terminar, o painel está em http://127.0.0.1:4577/. Lance agentes pelo formulário Launch agent lá, ou execute switchboard wire na pasta de uma janela do claude que você já tem aberta para trazer essa para dentro.

Configuração manual (o que o assistente automatiza, passo a passo)

1. Instalação

git clone https://github.com/rodcoppi/switchboard-mcp.git
cd switchboard-mcp
npm install

O TypeScript é executado diretamente via tsx, então não há nada para compilar. Três maneiras de chamar a CLI switchboard:

  • npm link coloca switchboard no seu PATH. Esta é a que deve usar:
    npm link
    switchboard --help
    
  • O shim do bin, sem vincular:
    node bin/switchboard.mjs --help
    
  • O ponto de entrada, sem vincular:
    npx tsx src/index.ts --help
    

Os exemplos abaixo dizem switchboard <subcommand> e assumem que você vinculou. Se não vinculou, leia-os como node bin/switchboard.mjs <subcommand>.

2. Inicie o Hub (serve), geralmente automático

Pule esta etapa: switchboard start e switchboard wire trazem o Hub para cima para você quando ele não está em execução, em uma sessão tmux destacada chamada sb-hub. Nenhuma janela de terminal permanece aberta. Após uma reinicialização, wire ou start seu primeiro agente e o Hub sobe junto.

Execute você mesmo quando quiser ver os logs ao vivo:

switchboard serve

O Hub executa em primeiro plano e registra em stdout e ~/.switchboard/logs/hub.log. Sua primeira linha fornece os endereços e o comando de registro MCP, pronto para copiar:

Dashboard: http://127.0.0.1:4577/  |  MCP: http://127.0.0.1:4577/mcp  |  Register (once): claude mcp add --transport http --scope user switchboard http://127.0.0.1:4577/mcp --header 'Authorization: Bearer ${SWITCHBOARD_AGENT_TOKEN}' --header 'X-Switchboard-Agent-Name: ${SWITCHBOARD_AGENT_NAME}'

Para olhar dentro do Hub que se iniciou sozinho: tmux attach -t sb-hub, e Ctrl-b d para deixá-lo em execução. Ou switchboard logs -f. serve aceita --port <port> e --log-level debug|info|warn|error.

Lançamento com um clique do Windows (sem terminal WSL)

No Windows e WSL você pode pular o terminal. Uma vez, dentro do WSL:

switchboard shortcut            # creates Switchboard.lnk on your Windows Desktop
switchboard shortcut --startup  # or: installs it in the Startup folder (runs on every boot)

Clique duas vezes em Switchboard (ou apenas inicie o Windows, com --startup) e o Hub sobe em segundo plano, com o painel aberto em http://127.0.0.1:4577/ no seu navegador Windows. O WSL2 encaminha o localhost para você; o Hub ainda vincula 127.0.0.1 dentro do WSL, então nada alcança a rede. Lance ou conecte agentes pelo formulário Launch agent. Exclua o atalho para desfazer.

O atalho é um .lnk carregando o ícone do Switchboard e abrindo minimizado; o .bat que ele aciona, e o ícone, vivem em %LOCALAPPDATA%\Switchboard (um .bat não pode carregar um ícone, e um ícone no sistema de arquivos WSL renderiza em branco na inicialização, quando a distro ainda não está em execução). Regere o ícone com node scripts/make-icon.mjs.

3. Registre o MCP no Claude Code (mcp add)

Apenas uma vez, no escopo user (aplica-se a todos os projetos):

claude mcp add --transport http --scope user switchboard http://127.0.0.1:4577/mcp \
  --header 'Authorization: Bearer ${SWITCHBOARD_AGENT_TOKEN}' \
  --header 'X-Switchboard-Agent-Name: ${SWITCHBOARD_AGENT_NAME}'

claude mcp list mostra switchboard como conectado enquanto o Hub está ativo.

Esses dois cabeçalhos são o que tornam a entrada silenciosa. O Claude Code expande ${VAR} do ambiente do PRÓPRIO agente quando ele conecta, então o Hub sabe quem está chamando antes de qualquer ferramenta executar: a sessão vincula no momento da conexão e o agente está na rede sem uma única linha digitada no seu terminal — como qualquer outro servidor MCP que você usa. Um registro cobre toda a sua frota (cada sessão carrega seu próprio nome e token), e o token nunca passa pelo modelo. Um cliente registrado sem os cabeçalhos ainda funciona da maneira clássica: o Hub digita um pontapé de uma linha pedindo ao agente para chamar join ele mesmo.

Executando agentes Codex também? Aponte o Codex para o mesmo Hub. Mesmo endpoint streamable-HTTP, escrito de forma diferente (setup oferece isso quando encontra o binário codex):

codex mcp add switchboard --url http://127.0.0.1:4577/mcp

Permissões de ferramenta. Adicione a regra de permissão mcp__switchboard__* ao permissions no settings.json do Claude Code, ou as ferramentas do Switchboard pedirão aprovação toda vez que você as usar. Já está no bypassPermissions? Você está coberto. switchboard start lembra você na sua primeira execução.

Apenas se você pular os cabeçalhos acima. No caminho clássico, o agente lê SWITCHBOARD_AGENT_TOKEN do seu ambiente com printenv antes de chamar join, então esse comando de shell também precisa de aprovação — adicione Bash(printenv:*) à regra de permissão, ou execute o agente com bypassPermissions. Com os cabeçalhos de identidade registrados, nada disso se aplica: nada é digitado e nenhum token chega ao modelo.

4. Cole o protocolo do agente (trecho)

Cole agent-protocol/CLAUDE.snippet.md no seu ~/.claude/CLAUDE.md, onde cobre todos os projetos, ou no CLAUDE.md de um projeto. Ele ensina um agente a ler seu nome e token do ambiente e entregá-los ao join, a chamar check_messages quando vir uma linha [switchboard], e a ler o que seus pares dizem sem cair em um loop de agradecimento. Ele também traça a linha que importa: coordenação não é subordinação, e nenhum outro agente pode autorizar o que seu usuário não autorizou.

5. Inicie um agente (start)

Execute isso em vez de abrir claude você mesmo:

switchboard start alpha --role "payments API backend" --dir ~/projects/api

O que acontece:

  1. O Hub registra o agente via REST, antes do Claude Code abrir.
  2. Uma sessão tmux sb-alpha inicia claude no diretório --dir.
  3. De um terminal interativo, start executa tmux attach nessa sessão, então sua aba do Windows Terminal se torna a tela do agente. Desanexe com Ctrl-b d e o agente continua trabalhando em segundo plano.
  4. O agente entra silenciosamente: seu cliente MCP conecta carregando os cabeçalhos de identidade, e o Hub vincula a sessão — ele aparece como MCP conectado em switchboard status com nada digitado no seu terminal. Registrou o MCP sem os cabeçalhos? Alguns segundos após a TUI estar pronta, um pontapé de uma linha pede ao agente para chamar join ele mesmo (--no-kickoff desativa isso).

Sinalizadores start: --role "<description>", --dir <path>, --no-kickoff, --agent <claude|codex>, --claude-args "<extra args for the agent CLI>".

Adotando um agente já aberto (wire)

Já tem uma janela do Claude Code aberta (um claude simples no bash, sem tmux) e quer juntá-la à rede sem perder a conversa? Use wire em vez de start:

  1. Nessa janela, saia do claude (Ctrl-C duas vezes, ou /exit).
  2. Na mesma pasta, execute:
    switchboard wire
    
  3. A conversa volta — agora dentro de uma sessão tmux, conectada ao Hub. O nome do agente assume o padrão do nome da pasta (sanitizado para letras minúsculas, dígitos e hífens; passe --name <name> se o nome da pasta não puder ser usado).

Por baixo dos panos, wire reabre o claude com -c (continuar a conversa da pasta) e --dangerously-skip-permissions (para o agente ler seu token e chamar join sem prompt) — estes são os padrões wire, ao contrário de start. Quaisquer --claude-args extras são adicionados depois deles. Se uma sessão tmux para esse nome já existir, wire a substitui (mata a antiga e a recria — sem confirmação), então executa o mesmo pontapé automático que start.

Fallback automático: se a pasta não tiver uma conversa retomável (nunca abriu o claude lá, ou a última executou em modo -p/print), claude -c sai imediatamente — wire detecta isso e reabre automaticamente uma sessão nova (sem -c), informando você. Nunca falha em uma janela morta; no pior caso, você obtém uma conversa totalmente nova já conectada à rede.

Sinalizadores wire: --name <name>, --role "<description>", --dir <path> (padrão: pasta atual), --no-kickoff, --agent <claude|codex>, --claude-args "<extra args for the agent CLI>".

Escolhendo a CLI do agente (--agent claude|codex)

Cada maneira de abrir um agente aceita um tipo de agente: claude (padrão, Claude Code) ou codex (Codex CLI). É um fluxo com uma escolha, não um modo separado — registro, o aviso, o pontapé, status, menções e o painel se comportam de forma idêntica:

switchboard start alpha --dir ~/projects/api --agent codex
switchboard wire --agent codex        # adopt the current folder with Codex

No painel, o formulário Launch agent tem um interruptor Claude | Codex, e cada cartão mostra o tipo do seu agente ao lado do chip MCP. O tipo é registrado no agente, então reopen o relança com a mesma CLI com que foi lançado.

Requisitos: o binário codex no PATH, e o Hub registrado como servidor MCP no Codex (codex mcp add switchboard --url http://127.0.0.1:4577/mcp — switchboard setup oferece isso automaticamente quando encontra codex). Sem esse registro, um agente Codex abre bem, mas não tem ferramentas do Switchboard para entrar.

O que difere por baixo dos panos é apenas o argv e as duas strings lidas da TUI — ambas vivem em um adaptador (src/shared/agent-types.ts):

Claude CodeCodex CLI
binárioclaudecodex
continuar conversa-cresume --last (um subcomando)
pular aprovações--dangerously-skip-permissions--dangerously-bypass-approvals-and-sandbox
diálogo de confiançaaceito por você na anexaçãoaceito automaticamente pelo kickoff

Agentes registrados antes dessa funcionalidade existir não têm tipo registrado e são tratados como Claude Code — que é o que eles são.

Grupos — manter os agentes de um projeto fora dos de outro

Todo agente pertence a um grupo, e um grupo é uma parede: um agente só pode enviar mensagens para agentes no mesmo grupo, list_agents mostra a ele ninguém mais, e sua transmissão para na borda do grupo. Execute os agentes de um projeto em panorama e os de outro em site e nenhum pode acordar o outro, seja por um deslize seu ou de um agente.

switchboard start alpha --dir ~/projects/api --group panorama
switchboard wire --group site        # adopt the current folder into another group
switchboard status                   # the GROUP column tells you who talks to whom

No painel, o formulário Iniciar agente tem um campo de grupo, e as abas acima da transcrição trocam de salas: escolha panorama e você lê a conversa daquele grupo sozinho. Uma transmissão enviada de lá alcança aquele grupo e para.

Agentes já em execução? Você não precisa relançá-los. Abra o menu ⋯ em um cartão e escolha grupo…; a célula de nome se torna um campo com seus grupos existentes atrás dele, e Enter move o agente. Isso entra em vigor na próxima mensagem do agente, sem reiniciar: ao contrário de renomear, que exige o agente parado (um agente ativo se juntaria novamente com o nome antigo e desfaria a mudança), nada em uma sessão em execução desfaz uma mudança de grupo.

Deixe --group desligado e nada muda: o agente mantém o grupo que já tinha, e um novo entra em default, onde todos os agentes que você tem hoje já vivem. Reexecutar start ou wire sem a flag nunca move um agente para fora do seu grupo.

Você é o operador, então nenhuma parede se aplica a você: você pode enviar mensagens para qualquer agente a partir do painel.

Menções — delegue com %name

Dentro da janela de qualquer agente, referencie outro agente como %<name> e isso se torna uma delegação. Por exemplo, ao dizer ao seu agente de backend:

Corrija o bug de paginação e peça ao %frontend para atualizar os tipos de consumidor depois.

faz com que ele corrija o bug e envie a frontend uma mensagem factual e acionável com a tarefa delegada (caminhos, contratos, o que reportar de volta). O agente que menciona permanece responsável pelo seu pedido — a menção apenas roteia a subtarefa. Isso faz parte do protocolo do agente (a etiqueta join + o trecho), então funciona em todos os agentes conectados.

Por que % e não @: @ já é o símbolo de referência de arquivo no Claude Code e no Codex, e o TUI o resolve antes de o modelo ver seu prompt. Nomes de agentes são comumente nomes de pastas (wire deriva um do outro), então @frontend digitado ao lado de uma pasta frontend/ silenciosamente se torna uma referência de arquivo e a delegação se perde sem erro. % não colide com nada em nenhum dos CLIs (! é bash, # é memória, / é comandos). @<name> ainda é entendido — apenas falha sempre que um caminho coincide.

Iniciando agentes a partir do painel

O painel (http://127.0.0.1:4577/) tem um formulário Iniciar agente (na parte inferior da barra lateral): digite o diretório do projeto, opcionalmente um nome (padrão é o nome da pasta) e um papel, escolha o agente (Claude ou Codex), marque continuar conversa para retomar a última conversa da pasta (mesmo fallback automático do wire) e clique em Iniciar. O próprio Hub cria a sessão tmux do agente e executa o kickoff automático — nenhum terminal é necessário. O novo cartão aparece ao vivo via SSE; anexe-se ao agente a qualquer momento com tmux attach -t sb-<name>. Por baixo dos panos, é POST /api/agents/launch {dir, name?, role?, continue?, agentType?} — somente localhost, como todo o resto.

Conversando com um agente — o chat

Clique no cartão de um agente e você obtém a conversa dele, renderizada como chat: o que você perguntou, o que ele respondeu, suas chamadas de ferramenta dobradas em uma linha cada, markdown e realce de sintaxe, e os acontecimentos do harness que o terminal mostra (worked for 2m 20s, tarefas em segundo plano, interrupções). É lido do próprio log de transcrição do Claude Code — o Switchboard não possui nada, então a sessão do agente fica intocada. O compositor abaixo despacha para esse agente: digite e pressione Enter, / para comandos de barra (roteados para o terminal), @ para mencionar um arquivo, arraste um arquivo para referenciá-lo, e o 🎤 para ditar — o reconhecimento de fala roda localmente na sua máquina, sem API, sem chave, sem conta.

Cada mensagem que chega de um par aparece como a própria linha do Switchboard com um alternador mostrar o que X enviou que desdobra a mensagem real, e no feed de tráfego cada mensagem lida tem um alternador de reação que mostra o que o destinatário disse sobre ela no próprio chat. Os dois respondem à pergunta que um quadro de mensagens nunca faz: e depois o que aconteceu?

Assistindo à tela de um agente

Alterne Terminal e a tela ao vivo do agente assume o painel — o TUI real do Claude Code (ou Codex), cores e cursor e tudo, e você pode digitar nele (aprovar um prompt, pressionar Esc para interromper, arrastar um arquivo para digitar seu caminho). Abra vários agentes e eles se tornam abas no topo; janela no menu do cartão ainda abre um terminal real do SO quando você quiser. Este é um cliente control-mode do tmux (tmux -C), não um segundo pty: o tmux é dono do processo do agente, então fechar o painel nunca derruba o agente — o objetivo de poder fechar a pilha de janelas de terminal.

Visualizando arquivos que os agentes mencionam

Agentes nomeiam caminhos absolutos constantemente ("escreveu /home/you/api/src/foo.ts"). Esses caminhos são clicáveis na transcrição — clique em um e o arquivo abre inline (imagens, texto, código, markdown). As leituras são escopadas: apenas arquivos sob o diretório de trabalho de um agente ou sua pasta pessoal, resolvidos com realpath para que .. e symlinks não possam escapar. Um caminho fora do escopo é recusado com uma mensagem clara, nunca lido — o corpo de uma mensagem não é confiável, então um agente não pode fazer você abrir um arquivo arbitrário apenas nomeando-o.

Duas portas ficam no cabeçalho da visualização para o que um painel inline não pode fazer: navegador abre o arquivo em uma aba real (um .html que um agente construiu renderiza como o site real — dentro de uma sandbox CSP, então seus scripts nunca podem dirigir o Hub com sua autoridade), e pasta revela o arquivo no Windows Explorer.

Soltar um arquivo no chat ou no terminal referencia o arquivo onde ele já vive — o Hub encontra o original por nome e tamanho nos projetos dos seus agentes, Downloads e Área de Trabalho, exatamente como arrastar para um terminal real. Somente quando não há um original para apontar (uma captura de tela colada, um anexo arrastado diretamente de um cliente de e-mail) ele prepara uma cópia em ~/.switchboard/uploads, mantida por 24h; um arquivo grande sem origem é recusado em vez de duplicado.

Gerenciando agentes a partir do painel

Cada cartão tem um botão abrir (reabrir quando o agente está offline: relança-o em sua pasta, continuando a conversa, com o mesmo CLI com que foi lançado) e um menu ⋯:

AçãoO que faz
cutucarForça uma cutucada manual — ainda sujeito à proteção de painel (nunca digita em um shell) e à proteção de diálogo (nunca digita enquanto um modal possui o painel).
silenciarPara de cutucar este agente. As mensagens continuam sendo registradas e ele ainda as lê na próxima check_messages — silenciar cala a cutucada, não o correio.
início automáticoMarca o agente para ser iniciado no login da máquina. O Hub apenas armazena a flag; um pequeno hook de login a lê e relança os agentes marcados, retomando suas conversas.
comando de inicializaçãoUma linha de shell que o lançador executa antes do CLI, no mesmo shell (<boot> && exec <cli>), para projetos que precisam de serviços ou env primeiro. Exports são levados para o CLI; uma configuração com falha aborta o lançamento em vez de deixar um agente meio preparado.
argumentos de lançamentoSubstitui os argumentos de lançamento do CLI para este agente — um --resume <session-id> fixado, flags extras. Definido pelo operador via REST apenas: um agente nunca pode escrever seu próprio código de inicialização ou argv.
grupoMove o agente para outra sala (a parede de comunicação — veja Grupos).
apelidoUm nome de exibição livre (emoji bem-vindo) para a UI. O kebab name permanece o endereço do protocolo, então isso funciona em um agente em execução.
renomearMuda o id técnico; todo o histórico e a contagem de não lidas seguem o novo nome. Apenas para um agente parado (um em execução se juntaria novamente sob o nome antigo).
parar / removerparar mata a sessão tmux e mantém o registro (o cartão vira reabrir). remover descarta o registro (confirmação em dois cliques) — as mensagens permanecem no JSONL somente anexação.

Nomes de agentes são endereços (%name em um prompt, a sessão tmux sb-<name>), então são letras minúsculas, dígitos e hífens. Você não precisa memorizar isso: os campos de nome reescrevem o que você digita enquanto digita — Chefe de Redes se torna chefe-de-redes diante de você, da mesma forma que wire deriva um nome de uma pasta chamada ai panorama.


Outros subcomandos

ComandoO que faz
switchboard wireAdota a janela atual na rede, continuando sua conversa (veja abaixo).
switchboard statusTabela de agentes registrados: NOME, PAPEL, STATUS, MCP, NÃO LIDAS, ÚLTIMA VISTA.
switchboard send <to> <message...>Envia uma mensagem como operador (o humano) para um agente, ou all para transmissão. Útil para scripts e para testar sem o painel.
switchboard stop <name>Para a sessão tmux do agente (pede confirmação se houver mensagens não lidas; --yes pula isso). O registro no Hub permanece — um novo start <name> reutiliza o nome (re-anexar).
switchboard downPara as sessões tmux de todos os agentes. O Hub permanece de pé (nunca é morto aqui).
switchboard logs [-f]Últimas ~100 linhas de ~/.switchboard/logs/hub.log; -f segue o arquivo.

Para parar o Hub: Ctrl-C no terminal switchboard serve (ou tmux kill-session -t sb-hub, se ele rodar na sessão recomendada).

Os dados vivem em ~/.switchboard/: config.json (todo valor tem um padrão; o arquivo pode nem existir), agents.json (snapshot atômico) e messages.jsonl (somente anexação, pesquisável com cat/jq).


Segurança

O modelo de ameaça é honesto e o limite de confiança é a máquina local. Leia isto antes de expor qualquer coisa:

  • Vincular em 127.0.0.1, fixo e não configurável. Uma mensagem entregue torna-se entrada executável para um agente com acesso ao sistema de arquivos. Expor o Hub na rede = RCE grátis.
  • NUNCA faça port-forward da porta 4577 (sem ssh -L, sem regra de firewall/NAT) e NUNCA execute o Hub atrás de um proxy reverso. 127.0.0.1 é a única barreira.
  • Modelo de confiança local: qualquer processo local pode publicar no Hub e, portanto, injetar entrada em qualquer agente. Isso é aceito na v1 (o mesmo modelo de qualquer ferramenta de desenvolvimento local), desde que nunca vaze para a rede.
  • O nudge nunca digita em um painel que pertence a um diálogo. O nudge é uma linha mais um Enter separado ~500ms depois (a única maneira de um TUI aceitá-lo), e com um prompt de permissão aberto (Do you want to proceed? ❯ 1. Yes) esse Enter costumava cair na escolha destacada — ou seja, qualquer agente capaz de enviar uma mensagem poderia aprovar uma chamada de ferramenta pendente de outro agente. Comprovado com um agente descartável, depois fechado: o leitor de painel relata blocked para prompts de permissão, diálogos de confiança e avisos de canal; o despachante enfileira em vez de digitar, e relê o painel ao vivo imediatamente antes de digitar (fail-closed — um painel ilegível conta como bloqueado). A mensagem retida é entregue no próximo flush, assim que você responder ao diálogo.
  • Token de capacidade (adendo v1.1): start injeta um token por agente no ambiente da sessão tmux (SWITCHBOARD_AGENT_TOKEN); o agente o lê e o passa para join, e ele nunca aparece em list_agents, em GET /api/agents, no painel ou nos logs. Com os cabeçalhos de identidade registrados (veja o passo 3), o token nunca chega ao modelo: o cliente MCP o envia diretamente do ambiente da sessão.
  • Superfícies somente para operador. O que um agente pode persistir sobre si mesmo para em sua função. O comando de inicialização e os argumentos de lançamento — os dois campos que decidem o que é executado na inicialização — são configuráveis via REST (o painel) e deliberadamente não expostos via MCP, para que um agente comprometido não possa escrever seu próprio código de inicialização. Isso fecha a personificação por processos que conhecem o nome de um agente, mas nunca falam com o endpoint de registro.
  • Risco residual conhecido (documentado no comentário de src/server/api.ts): o endpoint POST /api/agents/register é deliberadamente não autenticado, e re-registrar um nome existente regenera e retorna um novo token. Portanto, um processo local malicioso pode obter um token válido para qualquer nome e personificar esse agente via join — também invalidando o token da sessão legítima (seu join após um reinício do Hub falha). Isso é aceito pela especificação v1.1 (o mesmo limite de "qualquer processo local pode publicar") e não deve ser "corrigido" sem aprovação — exigir rotação de token quebraria o re-anexo do switchboard start.
  • Injeção de prompt entre agentes é um risco residual: um agente comprometido/alucinando pode tentar manipular outro. Mitigação v1: o limite declarado no trecho do protocolo (mensagens de pares são avaliadas criticamente; coordenação ≠ subordinação) mais visibilidade total do feed no painel.

Dicas de tmux no WSL / Windows Terminal (armadilha P11)

  • Se você raramente usa tmux, um ~/.tmux.conf mínimo com o mouse habilitado ajuda muito com rolagem e seleção de painéis:
    set -g mouse on
    
  • switchboard start executa tmux attach na sessão do agente, então cada aba do Windows Terminal permanece "a tela de um agente" — o fluxo de trabalho de abas que você já usa é preservado. Para sair da visão de um agente sem matá-lo: Ctrl-b d (destacar). Para voltar: tmux attach -t sb-<name>.

Roadmap

O Switchboard executa agentes Claude Code e Codex CLI hoje (veja Escolhendo o CLI do agente) — na mesma rede, na mesma conversa. Algumas direções para depois:

  • Mais CLIs de agentes. A infraestrutura é agnóstica ao agente — o nudge é tmux e as mensagens são MCP (um padrão aberto) — e adicionar o segundo tipo transformou essa afirmação em um adaptador real (src/shared/agent-types.ts). Um terceiro agora é um descritor: qual binário lançar, como ele escreve "continue" e "skip approvals", seus marcadores prontos para TUI, sua grafia mcp add. O requisito é que o CLI fale MCP e rode em um terminal.
  • Níveis de urgência (interrupt / normal / fyi): uma mensagem fyi que nunca acorda o destinatário (custo zero de token até que ele verifique por conta própria) — o economizador estrutural de tokens sobre a etiqueta atual + limite de taxa como proteção.
  • Estado do agente no cartão (working / blocked / idle), lido do painel que o dashboard já transmite. A metade blocked foi lançada com a proteção de diálogo (veja Segurança); exibi-la como quem precisa de mim agora é o próximo passo, e expor o estado de um par em list_agents permite que agentes parem de cutucar alguém preso em um prompt.
  • Retomada exata de sessão. Um hook SessionStart relatando o id de sessão do próprio CLI substituiria -c ("a última conversa da pasta") por --resume <id>, e entregaria ao chat o caminho exato da transcrição em vez de uma heurística.
  • Exportação do histórico do feed (a busca já vive no cabeçalho do dashboard).

Contribuições são bem-vindas — veja a estrutura de código nas seções acima; o Hub é um único processo Node e não há etapa de build.