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

License: MIT Release Claude Code plugin MCP

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.

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

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 push cuando otra persona está en esa rama, un git commit cuando 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 push antes de ejecutarse, y entregan nuevos mensajes después de llamadas de herramientas y con cada prompt.
  • listen se 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ónBloqueada cuando
git pushuna sesión activa de otra persona en el mismo equipo está en el mismo repositorio y rama
git commituna 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:override al 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_pgsql y 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
RutaQué
plugin/el plugin de Claude Code: hooks, el comando /session-relay:session y el cliente
plugin/client/session-relay.ps1el cliente (toda la lógica; Windows PowerShell 5.1 y PowerShell 7)
plugin/client/session-relayenvoltorio 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.