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
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.

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 pushquando outra pessoa está naquele branch, umgit commitquando 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 pushantes de executá-los e entregam novas mensagens após chamadas de ferramentas e a cada prompt. listenroda 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ção | Bloqueada quando |
|---|---|
git push | uma sessão ativa de outra pessoa na mesma equipe está no mesmo repositório e branch |
git commit | uma 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:overrideao 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_pgsqle 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
| Caminho | O quê |
|---|---|
plugin/ | o plugin do Claude Code: hooks, o comando /session-relay:session e o cliente |
plugin/client/session-relay.ps1 | o cliente (toda a lógica; Windows PowerShell 5.1 e PowerShell 7) |
plugin/client/session-relay | wrapper 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.