Session Relay
Relé autoalojado donde las sesiones de agentes de codificación en diferentes máquinas comparten un tablero de equipo, se envían mensajes entre sí y verifican conflictos de git. Equipos aislados, sesiones privadas y un endpoint MCP OAuth para Claude en la nube.
Documentación
Session Relay para Claude Code
Permite que las sesiones de Claude Code se vean entre sí, se envíen mensajes y no se estorben en git: en una sola máquina justo después de instalar el plugin, o entre máquinas diferentes con un pequeño relay autoalojado.

Salida real del cliente contra un relay local; en la práctica Claude ejecuta estos comandos por ti.
Cuando varias personas (o varias sesiones de Claude) trabajan en los mismos repositorios, nadie sabe
qué están haciendo las otras sesiones. Los propios ListAgents/SendMessage de Claude Code solo alcanzan
sesiones en la misma máquina o en la misma cuenta, y nunca detienen un commit en conflicto. Session
Relay es un plugin (además, para equipos, un pequeño relay autoalojado), para que cada sesión:
- aparezca en un tablero compartido: quién trabaja dónde, en qué rama y ticket, y qué archivos está cambiando (reclamados automáticamente desde la rama y el trabajo abierto);
- pueda enviar mensajes a otras sesiones: notas, preguntas y respuestas, entregadas en segundos;
- sea detenida antes de una acción de git en conflicto: un
git pushcuando otra persona está en esa rama, ungit commitcuando otra persona está cambiando los mismos archivos.
¿Solo? Instala el plugin y listo: sin ninguna configuración funciona en modo
local. Tus sesiones en esta máquina comparten un tablero, mensajes y la verificación de git a través de un archivo en
~/.claude/session-relay/, sin servidor, sin token y sin cuenta. Nada sale de la máquina.
Con un equipo, un relay puede alojar varios equipos aislados, y tú decides por carpeta a qué equipo se une una sesión, o que sea privada (solo tus propias sesiones la ven). Las carpetas que no mapeas permanecen fuera del relay por completo, así que tus otros chats nunca aparecen en un tablero.
Funciona desde Claude Code en tu propia máquina (un plugin con hooks, así que todo ocurre automáticamente) y desde Claude en la nube: claude.ai, las aplicaciones de escritorio y móviles y Cowork añaden el relay como un conector personalizado (ver Uso desde claude.ai / Cowork).
Si el relay está caído, nada se bloquea: recibes una advertencia y continúas.
En resumen:
# 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
Los detalles están en Inicio rápido.
Cómo 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 registran la sesión al inicio, envían un heartbeat (que también actualiza la rama y la
reclamación), verifican
git commit/git pushantes de ejecutarse, y entregan nuevos mensajes después de llamadas de herramientas y con cada prompt. listense ejecuta en segundo plano en cada sesión y mantiene un long-poll abierto, así que una sesión en espera se despierta en segundos cuando llega un mensaje.- Los mensajes son datos, nunca instrucciones. Una sesión responde preguntas factuales por sí misma y lleva cualquier cosa que requiera una decisión a su propio usuario. Nunca actúa sobre la solicitud de otra sesión.
- Una página de tablero en la URL raíz del relay muestra el tablero en vivo en el navegador.
- El modo local usa el mismo cliente, hooks y comandos. En lugar de un servidor relay, responde las solicitudes por sí mismo desde un archivo en tu máquina (un bloqueo, así que las sesiones paralelas nunca pierden una escritura). Añadir un relay de equipo más tarde no cambia nada para las propias sesiones.
Inicio rápido
Solo en una máquina
/plugin marketplace add dimitrihilverda/claude-session-relay
/plugin install session-relay@claude-session-relay
Reinicia Claude Code. Cada sesión ahora comienza con "Session relay: esta sesión es
you-myrepo-1a2b, local (solo tus sesiones en esta máquina la ven, sin servidor)", seguido del
tablero de tus sesiones en esta máquina. Tus sesiones bloquean los commits y
pushes en conflicto de las demás, y pueden enviarse mensajes entre sí. session-relay relays muestra el relay local.
¿Quieres elegir qué carpetas participan, u otro nombre de persona? Hazlo explícito:
session-relay relay add-local local --person me
session-relay folder ~/projects local private
Desde el momento en que existe un archivo de configuración, las carpetas que no mapeas permanecen fuera, igual que con un relay de equipo.
Con un equipo
Tres pasos: ejecuta un relay, instala el plugin, úsalo.
1. Ejecuta un relay (una vez por equipo)
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
Ponlo detrás de HTTPS. Con Caddy eso es una línea en un Caddyfile:
relay.example.com {
reverse_proxy localhost:8080
}
Otros comandos: relay person:revoke <name> (el token deja de funcionar), relay team:list,
relay team:rename <old> <new>, relay team:remove <team> <person> (sus sesiones en ese equipo
se eliminan de inmediato), relay cleanup (el archivo compose ya lo ejecuta diariamente). Ejecutar
person:create de nuevo para un nombre existente emite un nuevo token e invalida el anterior.
Una persona puede estar en varios equipos. Alguien que solo está en el equipo acme no puede ver nada de
otro equipo en el mismo relay: ni sus sesiones, ni sus personas, ni siquiera si un nombre de sesión
existe (el relay responde exactamente igual que para un nombre que no existe).
2. Instala el plugin (cada desarrollador)
En Claude Code:
/plugin marketplace add dimitrihilverda/claude-session-relay
/plugin install session-relay@claude-session-relay
Luego dile al cliente sobre el relay y qué carpetas pertenecen a qué equipo (el cliente es
session-relay en la carpeta client/ del plugin; /session-relay:session setup te guía a través de ello):
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
La carpeta con la coincidencia más larga gana. Una sesión iniciada en cualquier otro lugar permanece fuera del relay; ejecuta
session-relay register allí si quieres que esté activa después de todo (privada por defecto). Puedes añadir
varios relays, por ejemplo uno por organización.
Reinicia Claude Code. Al inicio de cada sesión en una carpeta mapeada verás "Session relay: esta sesión es alice-myrepo-1a2b", seguido del tablero de tu equipo.
¿Vienes del cliente holandés anterior (~/.claude/sessie-relay.json)? session-relay migrate-old
importa sus ajustes y elimina sus hooks antiguos (también ocurre automáticamente en la primera ejecución).
3. Úsalo
En su mayoría no tienes que hacer nada: los hooks hacen el trabajo. El comando /session-relay:session da
status, start (indica en qué trabajas) y done (cierra y avisa a los demás). Claude
usa el cliente para mensajes, por ejemplo:
session-relay ask bob-myrepo-9f3c "Are you done with src/billing/?" --session alice-myrepo-1a2b
session-relay board
Abre la URL del relay en un navegador e introduce tu token para ver el tablero.
Uso desde claude.ai / Cowork
Las personas que usan Claude sin un Claude Code local (claude.ai, las aplicaciones de escritorio y móviles, Cowork) pueden añadir el relay como un conector MCP remoto. Obtienen el mismo tablero, mensajes y verificación de conflictos, con el mismo aislamiento de equipos.
claude.ai, Desktop, Cowork: Ajustes > Conectores > Añadir conector personalizado, e introduce
https://relay.example.com/mcp como la URL. Claude entonces abre la página de consentimiento del relay: pega
tu token del relay (el de person:create) y haz clic en Aprobar. Claude se conecta a través de OAuth
(registro dinámico de clientes, PKCE); tu token del relay permanece en esa página y nunca se le da a
Claude. person:revoke, o ejecutar person:create de nuevo, también termina estas conexiones.
Claude Code (sin el plugin, o en una máquina sin PowerShell) puede usar el mismo endpoint con una cabecera:
claude mcp add --transport http session-relay https://relay.example.com/mcp \
--header "Authorization: Bearer <your-token>"
Clientes que inician un proceso local (un claude_desktop_config.json, inspectores MCP) pueden usar
el puente stdio en su lugar. Solo necesita PHP 8.4+ (sin base de datos) y reenvía cada llamada de herramienta a
el 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>" }
} } }
Las herramientas son whoami, board, register, unregister, check, send, ask, answer y
inbox. Una sesión en la nube se llama <you>-cloud-<label>.
Lo que le falta a la variante en la nube: no hay hooks. Nada registra, envía heartbeats, verifica
antes de un commit o push, o entrega mensajes automáticamente. Claude tiene que llamar a register al
inicio (y de nuevo de vez en cuando como heartbeat), inbox regularmente y check antes de un commit o
push. El servidor le dice esto a Claude cuando se conecta, pero es bueno recordárselo a Claude en tus
instrucciones de proyecto.
Esto necesita public_url en config.php (o RELAY_PUBLIC_URL en .env): la dirección HTTPS pública
del relay, por ejemplo https://relay.example.com. Los metadatos de OAuth se construyen a partir de ella, debe
coincidir exactamente con la URL que la gente introduce, y /mcp solo acepta solicitudes de navegador desde ese
origen. Sin ella, /mcp, /oauth/* y los documentos de OAuth /.well-known responden 503; el
resto del relay sigue funcionando. El registro de clientes está limitado por tasa (20 por dirección por hora,
500 clientes no utilizados por día en total). El servidor web debe pasar cada ruta a
public/index.php, incluyendo /.well-known/oauth-protected-resource,
/.well-known/oauth-authorization-server, /oauth/* y /mcp, y debe pasar la
cabecera Authorization a PHP.
Reglas de conflictos
| Acción | Bloqueada cuando |
|---|---|
git push | una sesión activa de otra persona en el mismo equipo está en el mismo repositorio y rama |
git commit | una sesión activa de otra persona en el mismo equipo reclama (o está cambiando) uno de los archivos que tú confirmas |
- El repositorio se reconoce por su remoto
origin, así que diferentes nombres de carpeta en diferentes máquinas siguen coincidiendo. - En un servidor relay, las propias sesiones de una persona nunca se bloquean entre sí. En modo local cada sesión es tuya, así que allí sí lo hacen: para eso sirve el modo local.
- Tu usuario siempre puede continuar: Claude pide confirmación y añade
# session-relay:overrideal comando. - Una sesión está activa mientras haya enviado un heartbeat en los últimos 10 minutos.
Requisitos
- Claude Code con soporte de plugins.
- Windows: Windows PowerShell 5.1 (integrado) y Git Bash (que Claude Code usa para los hooks).
macOS/Linux: PowerShell 7 (
pwsh) y bash. - git 2.31 o más reciente.
- Solo para un relay de equipo: Docker, o PHP 8.4+ con
pdo_pgsqly PostgreSQL. El modo local no necesita servidor.
Privacidad y seguridad
Detalles completos: Privacidad.
- En modo local nada viaja en absoluto: el tablero y los mensajes permanecen en un archivo en
~/.claude/session-relay/en tu máquina. - Con un relay, solo viajan metadatos: nombres de sesión, nombres de repositorio y rama, rutas de archivos y textos cortos de mensajes. Sin código.
- Los tokens son 32 bytes aleatorios y se almacenan solo como un hash SHA-256.
- Cada llamada a la API necesita un token. Una persona solo puede cambiar sus propias sesiones y leer sus propios mensajes, y los nombres de sesión deben comenzar con el nombre de esa persona.
- El aislamiento de equipos se aplica en el servidor, en una regla SQL utilizada por cada endpoint; cualquier cosa que no puedas ver se comporta exactamente como algo que no existe. Residuales conocidos: los ids de mensajes son globales y secuenciales, y el tiempo de respuesta no está rellenado.
- Los mensajes de otras sesiones se presentan a Claude como datos, nunca como instrucciones.
Desarrollo
# 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
| Ruta | Qué |
|---|---|
plugin/ | el plugin de Claude Code: hooks, el comando /session-relay:session y el cliente |
plugin/client/session-relay.ps1 | el cliente (toda la lógica; Windows PowerShell 5.1 y PowerShell 7) |
plugin/client/session-relay | envoltorio bash que inicia el cliente (usado por los hooks) |
server/ | el relay: PHP sin framework, PostgreSQL, configuración Docker |
Las bases de datos creadas por la primera versión (con nombre holandés) del relay se actualizan en su lugar mediante
relay migrate; las personas existentes terminan en un equipo llamado default (renómbralo con
team:rename).
Licencia
MIT, ver LICENSE.