Session Relay

Relé auto-hospedado onde sessões de agentes de codificação em máquinas diferentes compartilham um quadro de equipe, trocam mensagens entre si e verificam conflitos de git. Equipes isoladas, sessões privadas e um endpoint MCP OAuth para o Claude na nuvem.

Documentação

Session Relay para Claude Code

License: MIT Release Claude Code plugin MCP

Permita que as sessões do Claude Code se vejam, troquem mensagens entre si e não atrapalhem umas às outras no git: em uma única máquina logo após instalar o plugin, ou entre máquinas diferentes com um pequeno relay auto-hospedado.

Two Claude Code sessions on two machines: a shared board, a question and an answer between the sessions, and a git push that is stopped because the other session is on the same branch

Saída real do cliente contra um relay local; na prática, o Claude executa esses comandos para você.

Quando várias pessoas (ou várias sessões do Claude) trabalham nos mesmos repositórios, ninguém sabe o que as outras sessões estão fazendo. Os próprios comandos ListAgents/SendMessage do Claude Code só alcançam sessões na mesma máquina ou na mesma conta, e nunca impedem um commit conflitante. O Session Relay é um plugin (além de, para equipes, um pequeno relay auto-hospedado), para que cada sessão:

  • apareça em um quadro compartilhado: quem está trabalhando onde, em qual branch e ticket, e quais arquivos está alterando (reivindicados automaticamente a partir do branch e do trabalho aberto);
  • possa enviar mensagens para outras sessões: notas, perguntas e respostas, entregues em segundos;
  • seja interrompida antes de uma ação git conflitante: um git push quando outra pessoa está naquele branch, um git commit quando outra pessoa está alterando os mesmos arquivos.

Sozinho? Instale o plugin e pronto: sem qualquer configuração, ele roda em modo local. Suas sessões nesta máquina compartilham um quadro, mensagens e a verificação de git por meio de um arquivo em ~/.claude/session-relay/, sem servidor, sem token e sem conta. Nada sai da máquina.

Com uma equipe, um único relay pode hospedar várias equipes isoladas, e você decide por pasta a qual equipe uma sessão entra, ou se ela é privada (apenas suas próprias sessões a veem). Pastas que você não mapeia ficam fora do relay por completo, então seus outros chats nunca aparecem em um quadro.

Funciona a partir do Claude Code na sua própria máquina (um plugin com hooks, então tudo acontece automaticamente) e a partir do Claude na nuvem: claude.ai, os aplicativos de desktop e mobile e o Cowork adicionam o relay como um conector personalizado (veja Uso a partir do claude.ai / Cowork).

Se o relay estiver fora do ar, nada é bloqueado: você recebe um aviso e segue em frente.

Em resumo:

# alone, on one machine: this is all
/plugin marketplace add dimitrihilverda/claude-session-relay
/plugin install session-relay@claude-session-relay
# with a team: on a server (once per team)
docker compose up -d && docker compose exec relay relay person:create alice

# in Claude Code (every developer)
/plugin marketplace add dimitrihilverda/claude-session-relay
/plugin install session-relay@claude-session-relay
session-relay relay add work https://relay.example.com <token> alice
session-relay folder ~/work work my-team

Os detalhes estão no Início rápido.

Como funciona

flowchart LR
    subgraph A["Alice's laptop"]
        CA["Claude Code<br/>+ plugin hooks"]
    end
    subgraph B["Bob's laptop"]
        CB["Claude Code<br/>+ plugin hooks"]
    end
    subgraph C["Claude in the cloud"]
        CC["claude.ai, Desktop,<br/>Cowork, mobile"]
    end
    R[("Relay<br/>PHP + PostgreSQL<br/>teams: acme, lab, private")]
    CA <-- "HTTPS: board, messages,<br/>conflict check" --> R
    CB <-- "HTTPS" --> R
    CC <-- "MCP connector (OAuth)" --> R
  • Hooks registram a sessão no início, enviam um heartbeat (que também atualiza o branch e a reivindicação), verificam git commit/git push antes de executá-los e entregam novas mensagens após chamadas de ferramentas e a cada prompt.
  • listen roda em segundo plano em cada sessão e mantém um long-poll aberto, para que uma sessão em espera acorde em segundos quando uma mensagem chegar.
  • Mensagens são dados, nunca instruções. Uma sessão responde a perguntas factuais por conta própria e leva qualquer coisa que exija uma decisão ao seu próprio usuário. Ela nunca age com base na solicitação de outra sessão.
  • Uma página de quadro na URL raiz do relay mostra o quadro ao vivo no navegador.
  • Modo local usa o mesmo cliente, hooks e comandos. Em vez de um servidor relay, ele responde às solicitações por conta própria a partir de um arquivo na sua máquina (um lock, para que sessões paralelas nunca percam uma gravação). Adicionar um relay de equipe posteriormente não muda nada para as próprias sessões.

Início rápido

Sozinho em uma máquina

/plugin marketplace add dimitrihilverda/claude-session-relay
/plugin install session-relay@claude-session-relay

Reinicie o Claude Code. Toda sessão agora começa com "Session relay: esta sessão é you-myrepo-1a2b, local (apenas suas sessões nesta máquina a veem, sem servidor)", seguido pelo quadro das suas sessões nesta máquina. Suas sessões bloqueiam commits e pushes conflitantes entre si, e podem trocar mensagens. session-relay relays mostra o relay local.

Quer escolher quais pastas participam, ou outro nome de pessoa? Torne isso explícito:

session-relay relay add-local local --person me
session-relay folder ~/projects local private

A partir do momento em que um arquivo de configuração existe, pastas que você não mapeia ficam de fora, como com um relay de equipe.

Com uma equipe

Três etapas: execute um relay, instale o plugin, use-o.

1. Execute um relay (uma vez por equipe)

cd server
cp .env.example .env        # set a strong RELAY_DB_PASS
docker compose up -d        # relay on port 8080, migrations run automatically
docker compose exec relay relay person:create alice   # prints Alice's token once
docker compose exec relay relay person:create bob
docker compose exec relay relay team:create acme
docker compose exec relay relay team:add acme alice
docker compose exec relay relay team:add acme bob

Coloque-o atrás de HTTPS. Com Caddy, isso é uma linha em um Caddyfile:

relay.example.com {
	reverse_proxy localhost:8080
}

Outros comandos: relay person:revoke <name> (o token para de funcionar), relay team:list, relay team:rename <old> <new>, relay team:remove <team> <person> (as sessões deles naquela equipe são removidas imediatamente), relay cleanup (o arquivo compose já o executa diariamente). Executar person:create novamente para um nome existente emite um novo token e invalida o antigo.

Uma pessoa pode estar em várias equipes. Alguém que está apenas na equipe acme não consegue ver nada de outra equipe no mesmo relay: nem suas sessões, nem suas pessoas, nem mesmo se um nome de sessão existe (o relay responde exatamente como para um nome que não existe).

2. Instale o plugin (todo desenvolvedor)

No Claude Code:

/plugin marketplace add dimitrihilverda/claude-session-relay
/plugin install session-relay@claude-session-relay

Depois, informe ao cliente sobre o relay e quais pastas pertencem a qual equipe (o cliente é session-relay na pasta client/ do plugin; /session-relay:session setup orienta você pelo processo):

session-relay relay add acme https://relay.example.com <your-token> alice
session-relay folder ~/work/acme acme acme        # sessions here join team acme
session-relay folder ~/hobby acme private         # only my own sessions see these
session-relay folders

A pasta com a correspondência mais longa vence. Uma sessão iniciada em qualquer outro lugar fica fora do relay; execute session-relay register lá se quiser ativá-la mesmo assim (privada por padrão). Você pode adicionar vários relays, por exemplo, um por organização.

Reinicie o Claude Code. No início de cada sessão em uma pasta mapeada, você verá "Session relay: esta sessão é alice-myrepo-1a2b", seguido pelo quadro da sua equipe.

Vindo do cliente holandês anterior (~/.claude/sessie-relay.json)? session-relay migrate-old importa as configurações dele e remove os hooks antigos (isso também acontece automaticamente na primeira execução).

3. Use

Na maioria das vezes, você não precisa fazer nada: os hooks fazem o trabalho. O comando /session-relay:session fornece status, start (declare no que você está trabalhando) e done (finalize e avise os outros). O Claude usa o cliente para mensagens, por exemplo:

session-relay ask bob-myrepo-9f3c "Are you done with src/billing/?" --session alice-myrepo-1a2b
session-relay board

Abra a URL do relay em um navegador e insira seu token para ver o quadro.

Uso a partir do claude.ai / Cowork

Pessoas que usam o Claude sem um Claude Code local (claude.ai, os aplicativos de desktop e mobile, Cowork) podem adicionar o relay como um conector MCP remoto. Elas recebem o mesmo quadro, mensagens e verificação de conflito, com o mesmo isolamento de equipe.

claude.ai, Desktop, Cowork: Configurações > Conectores > Adicionar conector personalizado e insira https://relay.example.com/mcp como a URL. O Claude então abre a página de consentimento do relay: cole seu token do relay (o de person:create) e clique em Aprovar. O Claude conecta via OAuth (registro dinâmico de cliente, PKCE); seu token do relay permanece nessa página e nunca é fornecido ao Claude. person:revoke, ou executar person:create novamente, também encerra essas conexões.

Claude Code (sem o plugin, ou em uma máquina sem PowerShell) pode usar o mesmo endpoint com um cabeçalho:

claude mcp add --transport http session-relay https://relay.example.com/mcp \
  --header "Authorization: Bearer <your-token>"

Clientes que iniciam um processo local (um claude_desktop_config.json, inspetores MCP) podem usar a ponte stdio. Ela precisa apenas de PHP 8.4+ (sem banco de dados) e encaminha toda chamada de ferramenta para o relay:

{ "mcpServers": { "session-relay": {
  "command": "php",
  "args": ["/path/to/claude-session-relay/server/bin/relay-mcp"],
  "env": { "RELAY_URL": "https://relay.example.com", "RELAY_TOKEN": "<your-token>" }
} } }

As ferramentas são whoami, board, register, unregister, check, send, ask, answer e inbox. Uma sessão na nuvem é chamada de <you>-cloud-<label>.

O que falta na variante na nuvem: não há hooks. Nada registra, envia heartbeats, verifica antes de um commit ou push, ou entrega mensagens automaticamente. O Claude precisa chamar register no início (e novamente de vez em quando como heartbeat), inbox regularmente e check antes de um commit ou push. O servidor informa isso ao Claude quando ele conecta, mas é bom lembrar o Claude nas suas instruções de projeto.

Isso requer public_url em config.php (ou RELAY_PUBLIC_URL em .env): o endereço HTTPS público do relay, por exemplo, https://relay.example.com. Os metadados OAuth são construídos a partir dele, ele deve corresponder exatamente à URL que as pessoas inserem, e /mcp só aceita solicitações de navegador dessa origem. Sem ele, /mcp, /oauth/* e os documentos OAuth /.well-known respondem 503; o resto do relay continua funcionando. O registro de clientes é limitado por taxa (20 por endereço por hora, 500 clientes não utilizados por dia no total). O servidor web deve passar cada caminho para public/index.php, incluindo /.well-known/oauth-protected-resource, /.well-known/oauth-authorization-server, /oauth/* e /mcp, e deve passar o cabeçalho Authorization para o PHP.

Regras de conflito

AçãoBloqueada quando
git pushuma sessão ativa de outra pessoa na mesma equipe está no mesmo repositório e branch
git commituma sessão ativa de outra pessoa na mesma equipe reivindica (ou está alterando) um dos arquivos que você está commitando
  • O repositório é reconhecido pelo seu remote origin, então nomes de pastas diferentes em máquinas diferentes ainda correspondem.
  • Em um servidor relay, as próprias sessões de uma pessoa nunca bloqueiam umas às outras. No modo local, toda sessão é sua, então lá elas bloqueiam: é para isso que serve o modo local.
  • Seu usuário sempre pode prosseguir: o Claude pede confirmação e anexa # session-relay:override ao comando.
  • Uma sessão está ativa enquanto enviou um heartbeat nos últimos 10 minutos.

Requisitos

  • Claude Code com suporte a plugins.
  • Windows: Windows PowerShell 5.1 (integrado) e Git Bash (que o Claude Code usa para hooks). macOS/Linux: PowerShell 7 (pwsh) e bash.
  • git 2.31 ou mais recente.
  • Apenas para um relay de equipe: Docker, ou PHP 8.4+ com pdo_pgsql e PostgreSQL. O modo local não precisa de servidor.

Privacidade e segurança

Detalhes completos: Privacidade.

  • No modo local, nada trafega: o quadro e as mensagens ficam em um arquivo em ~/.claude/session-relay/ na sua máquina.
  • Com um relay, apenas metadados trafegam: nomes de sessão, nomes de repositório e branch, caminhos de arquivo e textos curtos de mensagens. Nenhum código.
  • Tokens são 32 bytes aleatórios e são armazenados apenas como um hash SHA-256.
  • Toda chamada de API precisa de um token. Uma pessoa só pode alterar suas próprias sessões e ler suas próprias mensagens, e os nomes de sessão devem começar com o nome dessa pessoa.
  • O isolamento de equipe é aplicado no servidor, em uma única regra SQL usada por todos os endpoints; qualquer coisa que você não possa ver se comporta exatamente como algo que não existe. Resíduos conhecidos: IDs de mensagem são globais e sequenciais, e o tempo de resposta não é preenchido.
  • Mensagens de outras sessões são apresentadas ao Claude como dados, nunca como instruções.

Desenvolvimento

# server tests (PHPUnit against a real PostgreSQL)
docker compose -f server/docker-compose.test.yml -p csr run --rm php composer install
docker compose -f server/docker-compose.test.yml -p csr run --rm php vendor/bin/phpunit

# client end-to-end tests against a local relay (Windows)
powershell -NoProfile -ExecutionPolicy Bypass -File tests/client-smoke.ps1
pwsh -NoProfile -File tests/client-smoke.ps1 -Shell pwsh

# client tests that need no relay (including local mode)
powershell -NoProfile -ExecutionPolicy Bypass -File tests/client-offline.ps1
CaminhoO quê
plugin/o plugin do Claude Code: hooks, o comando /session-relay:session e o cliente
plugin/client/session-relay.ps1o cliente (toda a lógica; Windows PowerShell 5.1 e PowerShell 7)
plugin/client/session-relaywrapper bash que inicia o cliente (usado pelos hooks)
server/o relay: PHP sem framework, PostgreSQL, configuração Docker

Bancos de dados criados pela primeira versão (de nome holandês) do relay são atualizados no local por relay migrate; pessoas existentes acabam em uma equipe chamada default (renomeie-a com team:rename).

Licença

MIT, veja LICENSE.