~/lab/relevo
relevo
Dos sesiones de Claude Code que se pasan el trabajo solas
claude plugin marketplace add melandres8/claude-modsconst PROMPTS: Record<RelevoRole, string> = {
planner: [
'# relevo: planner',
'Divides el objetivo en pasos pequeños y verificables. NO editas código.',
'Cuando el plan o el siguiente paso esté listo, termina tu respuesta con un bloque <handoff>…</handoff> para el constructor.',
'Cuando el objetivo esté cumplido, emite <done>resumen</done>.',
'Los mensajes que empiezan con "[relevo ronda N · de builder]" son el informe del constructor: revísalo y decide el siguiente paso.',
].join('\n'),
builder: [
'# relevo: builder',
'Ejecutas exactamente el paso recibido.',
'Al terminar, cierra con un <handoff> que traiga qué hiciste, qué archivos tocaste, el resultado de los tests y tus dudas.',
'Los mensajes que empiezan con "[relevo ronda N · de planner]" son el paso que te manda el planificador.',
].join('\n'),
}Por qué lo construí
Muchas veces trabajo con dos sesiones de Claude Code lado a lado: una planifica y la otra construye. Yo era el mensajero entre las dos. Copiaba cada plan en la constructora y después copiaba cada informe de vuelta en la planificadora.
relevo elimina ese paso. La planificadora escribe el siguiente paso dentro de un bloque <handoff>. Cuando termina su turno, relevo envía el bloque a la sesión constructora.
Cómo funciona el ciclo
Cada rol recibe un prompt corto, el del snippet. La planificadora divide el objetivo en pasos pequeños y verificables, y no edita código.
La constructora ejecuta exactamente el paso que recibe. Cierra con un informe en <handoff>: qué hizo, qué archivos tocó, el resultado de los tests y sus dudas.
relevo pone una cabecera en cada envío, que el modelo lee como [relevo ronda 3 · de planner]. Solo la planificadora sube la ronda. La constructora contesta con la misma ronda que recibió.
Una banda sobre el prompt resume el estado en una línea: el rol, la otra sesión, las rondas como ▰▰▰▱▱▱▱▱▱▱ 3/10 y quién tiene el turno.
Cómo funciona el enlace
Una sesión envía una petición de enlace, y la otra no toma ningún rol por su cuenta. Muestra el id de la primera sesión y el comando que acepta la petición, por ejemplo /relevo builder <id-de-A>. El botón Aceptar de su panel hace lo mismo.
La sesión que pide el enlace genera un nonce aleatorio. La aceptación lo devuelve, y cada cabecera de ronda lo lleva. Una ronda cuenta solo si trae el nonce del enlace y viene del otro rol.
relevo solo cuenta los mensajes que escribió el relevo de la otra sesión. Descarta un texto parecido, por ejemplo uno que un modelo envía con SendMessage, y muestra un toast. El modelo nunca ve ese texto, y tampoco ve el nonce.
Cómo se detiene
- La planificadora escribe
<done>…</done>cuando cumple el objetivo. - Las rondas llegan a
maxRounds, 10 por defecto, en cualquiera de las dos sesiones. relevo se pausa y guarda el<handoff>pendiente./relevo resumelo envía y concede otrasmaxRoundsrondas. - Nadie aceptó el enlace todavía. relevo no envía nada: guarda el
<handoff>y se pausa hasta/relevo resume. - Un envío falla o la otra sesión lo rechaza. relevo muestra el motivo en un toast y se pausa.
relevo también evita los ciclos de eco. Solo envía desde el final de un turno del modelo, nunca al recibir un mensaje. Tampoco reenvía un <handoff> igual al último que recibió o envió.
Cómo activarlo
Elige una sola forma de cargar el plugin. Si combinas la instalación desde el marketplace con --plugin-dir, los hooks se cargan dos veces y cada handoff sale duplicado.
claude plugin marketplace add melandres8/claude-mods
claude plugin install relevo@claude-mods
Las dos sesiones necesitan relevo 0.2.0, porque el protocolo de enlace cambió en esa versión. El código está en melandres8/claude-mods, con licencia MIT.
Abre dos sesiones en el mismo proyecto y escribe /relevo en la primera. El panel te pide el rol y la otra sesión, y Conectar envía la petición de enlace. Cuando la segunda sesión acepta, el panel te pide el objetivo.
Sin el panel:
/relevo planner <peer> # en la sesión A: pide el enlace
/relevo builder <id-de-A> # en la sesión B: lo acepta
/relevo goal Añadir paginación al endpoint /users con tests