TL;DR Desde la v2.1.224, una sesión de Claude Code le puede escribir a otra sin que actives nada, y entre sesiones de la misma máquina el texto nunca sale de tu disco. Se lo pides en lenguaje normal ("cuéntale a la sesión del repo X que la migración ya está") y Claude localiza el destino y envía. Comprueba antes con
/list-agentsque la ve: si no sale en esa lista, no hay nada que enviar. Y si la sesión que recibe corre enbypassPermissionsy la que manda no, el mensaje se queda retenido esperando tu aprobación en la otra ventana.
Dos terminales abiertas sobre el mismo repositorio. En una acabas de renombrar una columna de la base de datos. En la otra, Claude lleva veinte minutos construyendo encima del nombre viejo y no tiene forma de saberlo. La manera de avisar siempre ha sido la misma: copias el resumen de una ventana, cambias de pestaña, lo pegas. Tú haciendo de cable entre dos Claudes.
Desde la versión 2.1.224 ese cable ya existe. Una sesión puede entregarle un texto a otra, y no hay nada que activar: si tu sesión cumple los requisitos, está encendido.
Primero, comprueba que se ven
/list-agents
En mi máquina, con una sesión de fondo trabajando en otro proyecto:
Other Claude sessions (1):
[idle] · wmedia · /Users/juan.nunez/Herd/wmedia · started 20h ago
Cada fila es una sesión que Claude puede alcanzar, y el nombre de la fila es la dirección a la que escribe. El comando tiene alias /peers. El directorio de trabajo aparece por un motivo práctico: dos sesiones pueden acabar con el mismo nombre, y esa columna es lo que las distingue. El nombre sale de /rename o del flag --name, y si no pones ninguno, Claude Code lo deriva de la carpeta (myapp-3f).
La lista incluye tus subagentes, tus otras sesiones locales (incluidas las de Agent View) y, si tienes Remote Control conectado, tus sesiones en otras máquinas y en la web, etiquetadas como Remote Control.
Si /list-agents no te lo reconoce, no es que falle el envío: es que la sesión no tiene la función. Repasa los requisitos del final antes de seguir.
Cómo se lo pides
No llamas tú a ninguna herramienta. Le dices a Claude qué quieres que sepa la otra sesión:
Pregúntale a la sesión de la otra terminal si ha terminado la migración
Explícale a la sesión que está con la API de pagos lo que acabamos de cambiar
El texto que viaja lo redacta Claude, no tú. Por debajo usa dos herramientas: ListAgents para descubrir a quién puede alcanzar y SendMessage para entregar el mensaje a uno de ellos por su nombre. Y no hace falta que se lo pidas: Claude puede mandar un mensaje por iniciativa propia cuando ve que un cambio suyo afecta a lo que otra sesión está construyendo.
Lo que llega al otro lado es texto plano y nada más:
Schema migration finished: the new column is tenant_id, and rebasing on main is safe now.
Ni tu historial, ni tus archivos, ni el contexto de la conversación. Si lo que quieres es mover la conversación entera a otro terminal, eso es /resume (o claude --resume desde otra terminal), no esto.
En la sesión que recibe, el mensaje aparece con el nombre de quien lo envía. Si Claude está a mitad de turno se encola y lo lee entre llamadas a herramientas, sin cortar nada; si estaba parada, arranca un turno nuevo con él. Una vez leído se colapsa a una línea Message from que Ctrl+O vuelve a desplegar. Y cuenta como consumo igual que un prompt que escribas tú.
Lo que un mensaje no puede hacer
Claude Code le dice a la sesión que recibe que eso viene de otra sesión, no de ti, y con eso se cae un montón de superficie de ataque:
| El mensaje pide… | Qué pasa |
|---|---|
| Aprobar un permiso pendiente | No cuenta como tu consentimiento. No lo aprueba |
Cambiar CLAUDE.md, permisos o cualquier config |
Tiene instrucción de no tocar configuración porque se lo pida otra sesión |
Ejecutar /compact o cualquier slash command |
Llega como texto plano. No se ejecuta |
| Algo que requiere un permiso que no tiene | Te salta el prompt de permisos de siempre |
Los permisos siguen siendo de cada sesión. Claude tiene instrucción de no pedirle a otra sesión algo que en la suya está denegado o bloqueado, y de devolvértelo a ti en su lugar. Si nunca has separado modos, reglas y permisos, los tres conceptos están aquí.
Cuándo el mensaje no llega
Esta es la parte que decide si esto te sirve o te frustra. Entre dos sesiones interactivas normales con la configuración por defecto, el mensaje se entrega. Fuera de ese caso hay tres finales posibles:
- Entregado: Claude lo lee.
- Retenido: Claude Code lo aparta sin entregarlo y te enseña un aviso. Solo llega si tú lo apruebas o si un cambio posterior de modo o de ajustes lo permite.
- Rechazado: se descarta sin entregar nada.
Cuando no has configurado nada, la decisión se toma comparando los modos de permisos de las dos sesiones. Claude Code agrupa por un lado las sesiones que se saltan los prompts de permisos y por otro todas las demás (auto, acceptEdits y dontAsk cuentan como que preguntan; plan mode cuenta como que se salta, en sesiones donde bypass está disponible):
| La sesión que recibe | Qué hace con el mensaje |
|---|---|
| Pregunta permisos | Lo entrega. Solo lo retiene si quien envía se identifica como que se salta los prompts |
| Se salta los prompts | Lo retiene para que tú lo apruebes. Solo lo entrega si quien envía también se los salta |
Traducido: la sesión más peligrosa, la que corre sin frenos, es precisamente la que se queda sin recibir. Si mandas algo desde una terminal normal a una que dejaste en bypassPermissions, el mensaje no llega hasta que vas a esa ventana y lo apruebas en un diálogo que caduca a los cinco minutos (dialogExpiry, configurable). Pasado el plazo, el mensaje se descarta.
Cuando quien envía está en la misma máquina, recibe aviso de lo que ha pasado: uno cuando el mensaje queda retenido y otro después con el desenlace (entregado, denegado o caducado). Un mensaje rechazado nada más llegar no genera ningún aviso al que envía.
Y el caso peor, el que aparece en cuanto automatizas algo: una sesión claude -p no puede enseñar ese diálogo. Un mensaje retenido ahí se queda retenido para siempre. Si quieres que un worker desatendido acepte mensajes, arráncalo con crossSessionInbound en accept dentro de su --settings.
Y su gemelo, por si alguna vez te falta una sesión en la lista: una sesión -p normal sí abre su socket y aparece en /list-agents, pero una arrancada en bare mode no lo abre, así que ni recibe ni sale listada.
{
"crossSessionInbound": "accept"
}
Los tres valores son accept (entrega), hold (avisa y no entrega) y refuse (descarta). Claude Code lee primero los managed settings, luego el flag --settings y luego tus settings de usuario, y aplica el primer valor que encuentre. Un valor en settings de proyecto o local solo se aplica si es más estricto en la escala accept < hold < refuse que lo que digan esas fuentes. Es decir: un archivo del repositorio puede endurecer la política, nunca aflojarla.
Dos límites más, por si algún día ves mensajes desaparecer: se retienen como mucho 100 y a partir de ahí caen los más antiguos, y en la cola de entrega caben 50 esperando a que Claude los lea. Los repetidos se limitan por emisor y los idénticos seguidos se descartan, que es lo que hace que un bucle de dos sesiones respondiéndose se apague solo.
Fuera de tu máquina, solo puedes responder
| Dónde corre la otra sesión | Por dónde viaja | Qué puede enviar Claude desde aquí |
|---|---|---|
| En esta máquina | Un socket por sesión, sin pasar por servidores de Anthropic | Mensajes nuevos y respuestas |
| En otra máquina tuya | Por servidores de Anthropic, hasta la conexión de Remote Control de esa máquina | Solo respuestas |
| En Claude Code en la web | Por servidores de Anthropic | Solo respuestas |
La entrega local funciona porque cada sesión se registra en archivos en disco y abre ahí su socket de entrada. De ahí sale una consecuencia práctica: dos sesiones solo se alcanzan si ven los mismos archivos. Un contenedor tiene su propio sistema de archivos, así que una sesión dentro y otra en el host no se ven. Dos sesiones dentro del mismo contenedor sí.
Si quieres que ningún mensaje salga de la máquina sin tu visto bueno:
{
"isolatePeerMachines": true
}
Con eso, hasta en bypassPermissions te pide aprobación antes de que una respuesta cruce fuera. Un true desde cualquier ámbito de settings manda, así que un archivo del repositorio puede encender la exigencia pero no apagarla.
Dónde encaja esto
| Si quieres… | Mira… |
|---|---|
| Que tus sesiones independientes se avisen entre ellas | Esto (/list-agents + pídeselo a Claude) |
| Un equipo de Claudes que él mismo lanza y supervisa | Agent Teams |
| Ver todas tus sesiones en una pantalla | Agent View |
| Seguir una conversación en otro terminal | /resume (y el resto de comandos entre sesiones) |
| Manejar una sesión tuya desde el móvil | Remote Control |
| Empujar eventos externos (CI, chat) hacia una sesión | Channels |
La confusión fácil es con Agent Teams, y la línea es limpia: un team son Claudes que Claude lanza y supervisa, con su propio protocolo de mensajes que no sale del equipo. Esto de aquí son sesiones que abres y diriges tú, que no se conocían entre sí, y lo único que se pasan es texto plano.
Apagarlo
Recibir y enviar son controles separados:
- Dejar de recibir:
crossSessionInboundenrefuse. - Dejar de enviar y de listar: reglas deny con
SendMessageyListAgents. Las dos van con el nombre pelado de la herramienta, sin especificador.
{
"permissions": {
"deny": ["SendMessage", "ListAgents"]
},
"crossSessionInbound": "refuse"
}
Ojo con el efecto colateral: denegar SendMessage también te quita los mensajes a subagentes y a compañeros de agent team, porque es la misma herramienta.
Referencia
| Aspecto | Detalle |
|---|---|
| Versión mínima | v2.1.224 |
| Sistemas | macOS y Linux, incluido WSL 2. En Windows nativo no existe |
| Proveedores | No está en Amazon Bedrock, Claude Platform on AWS, Google Cloud Agent Platform ni Microsoft Foundry |
| Comprobar | /list-agents (alias /peers). /status muestra tu dirección en la fila Peer address, con prefijo uds: |
| Herramientas | ListAgents para descubrir, SendMessage para enviar |
| Contenido | Solo texto plano. Ni historial, ni archivos, ni protocolo de agent teams |
| Ajustes | crossSessionInbound (accept / hold / refuse), isolatePeerMachines, dialogExpiry (default 5m) |
| Topes | 100 mensajes retenidos, 50 en cola de entrega, repetidos limitados por emisor |
| Lo apaga del todo | CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, DISABLE_TELEMETRY, DO_NOT_TRACK o DISABLE_GROWTHBOOK, porque tumban la evaluación de feature flags de la que depende |
Esa última fila es la que más cuesta diagnosticar. Si eres de los que apaga la telemetría por defecto, no vas a ver ningún error: /list-agents simplemente no existirá en tu sesión, y no hay nada en pantalla que conecte una cosa con la otra. Esas variables pueden venir de tu shell, del bloque env de un settings o de los managed settings de tu empresa.
Documentación oficial: Message your other Claude Code sessions