CommunityRedacción y edicióngithub.com

ssheleg/agent-sync

Varios agentes de código, un repositorio, sin colisiones: concesiones con TTL, reserva de ID libre de condiciones de carrera, un diario de ejecución y un panel generado sobre una nube de conocimiento conectable. Se envía en el paquete sshlg-skills.

¿Qué es agent-sync?

Agent-sync es una habilidad diseñada para permitir que múltiples agentes de IA (como Claude Code, Cursor o Codex) colaboren de forma segura en un único repositorio de código, evitando colisiones y conflictos. Proporciona un sistema de concesiones (leases) con tiempo de vida (TTL), reserva de IDs sin condiciones de carrera, un diario de ejecución por sesión y un panel de control generado sobre una 'nube de conocimiento' conectable (como Outline) o almacenamiento local. La habilidad se basa en un principio fundamental: Git es el plano de registro (hechos duraderos) y la nube es el plano de coordinación (quién hace qué ahora). Utiliza un conjunto de comandos CLI (init, acquire, release, reserve, guard, status, merge, etc.) y scripts para gestionar el ciclo de vida de las tareas, las concesiones de archivos y la integración de ramas. Es compatible con Claude Code de forma nativa (con ganchos) y con otros entornos mediante invocación manual del comando 'guard'. La habilidad enfatiza la importancia de no confundir el plano de registro con el de coordinación, y de no utilizar la nube para decidir concesiones, ya que carece de garantías de exclusión mutua atómica.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add ssheleg/agent-sync

Installed? Explore more Redacción y edición skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

agent-sync — un proyecto, muchos agentes, sin colisiones

Dos planos, y una regla entre ellos:

Git es el plano de registro. La nube es el plano de coordinación. Un hecho que debe perdurar se escribe primero en git y se referencia desde la nube. Un hecho sobre quién está haciendo qué ahora vive en la nube y expira.

Ningún objeto en la nube es nunca el único hogar de un hecho duradero. Todo lo que existe a continuación tiene como objetivo mantener eso cierto mientras varios agentes escriben al mismo tiempo.

Cuatro trampas — léelas antes que cualquier otra cosa

1. La base de conocimiento nunca decide una concesión. No puede: doce adiciones concurrentes a un documento de Outline devolvieron doce éxitos y dejaron tres líneas. La exclusión proviene de algo con una verdadera operación de comparar-e-intercambiar. El plano lleva el registro y nada más. Mediciones completas en references/lease-protocol.md.

2. Sepa qué concesión tiene, y dígalo. leaseBackend: "local" es una creación atómica de archivo — exclusiva entre procesos en un sistema de archivos, consultiva entre máquinas. leaseBackend: "git" envía una referencia, y el rechazo de no-avance-rápido del remoto es una comparar-e-intercambiar — exclusiva entre máquinas. acquire imprime cuál. Una concesión fingida es peor que ninguna concesión: el otro agente deja de comprobar.

acquire también escribe la reclamación en la hoja de ruta, y release restaura exactamente lo que había — una fila, una celda, se niega si hay ambigüedad, git diff vacío después de un ciclo completo. Lea references/roadmap.md antes de configurar claimTags o cerrar una tarea; cerrar es una declaración sobre el trabajo y sigue siendo suyo.

Trabaje en una rama; la rama de integración es una base estable de otro. acquire escribe la reclamación solo allí; en cualquier otra rama el titular permanece en el plano de coordinación, donde status lo muestra a todos los agentes sin que nadie tenga que recuperar su rama. Comprometida en una rama, una reclamación es invisible hasta la fusión y convierte la hoja de ruta compartida en un archivo que dos ramas editan ambas. Finalice el trabajo con merge: los conflictos calculados por git merge-tree antes de que se toque nada, nombrados y rechazados si los hay, la fusión registrada en docs/MERGES.md (días recientes completos, los más antiguos compactados al escribir), la concesión --key liberada. merges le dice al siguiente agente qué aterrizó mientras estaba fuera. Lea references/branching.md antes de fusionar.

3. Los ganchos existen solo en Claude Code. En otros entornos, nada bloquea una edición protegida: ejecute guard usted mismo y registre la ejecución como ungated. No describa un proyecto como protegido cuando no lo está.

4. Analice con liberalidad, y nunca llame a un registro ilegible una carrera perdida. El almacén reescribe lo que escribió — Outline convierte un - (viñeta) en * . Emita - , acepte -/*/+, cuente todo lo que tenga forma de entrada que falle, y falle ruidosamente si supera el 2% de lo no analizable. Informar perdido cuando la verdad es ilegible nombra a un titular que no existe. Esté atento a un prefiltro silencioso: un continue antes de la expresión regular oculta las líneas defectuosas del contador diseñado para exponerlas.

Integrar esto en CUALQUIER proyecto — la cadena completa

scaffold  → crea la arquitectura de documentación, solo donde está ausente
adopt     → lee el repositorio, propone una configuración, no escribe nada
init      → escribe la configuración aprobada + el archivo env ignorado por git
            (el operador pega el token — nunca usted)
reconcile --set-baseline    → convierte el historial en un backlog contado, una vez
setup     → genera la instantánea que describe el cableado de este proyecto
check     → valida todo; distinto de cero si no es saludable

check es lo que hace que la habilidad sea autosuficiente. Se niega a llamar saludable a una configuración basada en una regla que no protege nada (un registro, un patrón de guardia, un patrón de reclamación, una puerta o fuente de espejo que apunta a algo que no existe), con credenciales faltantes, en un archivo env rastreado por git — el único error irrecuperable aquí — en una instantánea obsoleta o desvinculada, y en un registro sin una línea base. Nombra cada uno; cada uno falló de verdad durante la propia adopción de esta herramienta.

Ejecute check después de adoptar, después de cambiar la configuración y en CI.

scaffold nunca sobrescribe. Siembra un registro de decisiones con una línea de asignación y un AGENTS.md que apunta a la instantánea, y deja intacto cada archivo existente — una herramienta que reescribe las propias convenciones de un proyecto al adoptarlo es peor que una que no hace nada.

Proyecto existente: comience con adopt

Ejecute adopt antes de init. Lee el repositorio e imprime lo que encontró — registros de ID, archivos de registro, puertas — más las decisiones que se niega a tomar por usted — y luego propone una configuración.

python3 "$SKILL_DIR/scripts/agent_sync.py" adopt

Confirme los registros y los archivos protegidos con el operador primero: un registro apuntando al archivo incorrecto hace que cada verificación posterior sea incorrecta con confianza, y una lista protegida que omite un archivo compartido deja desprotegido el único lugar donde ocurren colisiones. En un submódulo no declara registros: las decisiones pertenecen al repositorio principal. Luego siga la cadena anterior desde init.

Primer comando en un proyecto: init

Nunca ejecute nada más contra un proyecto no inicializado. init es donde la pregunta de almacenamiento se hace y se responde, una vez, y se escribe.

Pregunte al operador estas dos cosas en el chat — no adivine, no elija un valor predeterminado:

  1. ¿Dónde debe vivir el estado de coordinación?

    • una nube de conocimiento (outline) — el registro compartido, la conciencia y el panel en todas las máquinas. No decide concesiones; nada en ella puede (trampa 1);
    • o archivos locales (fs) — sin credenciales y sin visibilidad para un agente en otra máquina: sin conciencia compartida, sin señales entre repositorios, sin panel compartido.

    La concesión se decide por separado mediante leaseBackend (trampa 2), y gated sigue esa elección, nunca el plano de registro. Informe la garantía que realmente tiene, no la más fuerte que sugiere el plano de registro.

  2. Si es nube: la URL de la instancia. La URL es configuración, no un secreto, por lo que puede escribirla. El token no lo es — nunca lo pida en el chat, nunca lo lea de vuelta y nunca lo coloque usted mismo.

Luego ejecútelo con sus respuestas:

python3 "$SKILL_DIR/scripts/agent_sync.py" init --backend outline --url https://<su-instancia>
python3 "$SKILL_DIR/scripts/agent_sync.py" init --backend fs

init escribe .claude/agent-sync.json (forma, comprometido), escribe .env.agent-sync con las claves y una línea de token vacía (identidad, modo 600), añade .env.agent-sync y .agent-sync/ a .gitignore, y luego imprime exactamente lo que el operador debe hacer por sí mismo — crear el token en su propia instancia y pegarlo en esa única línea. Nunca sobrescribe una configuración o archivo env existente sin --force.

Transmita esas instrucciones finales al operador textualmente. Obtener el token en el archivo es su paso, y el diseño depende de que siga siendo suyo.

Luego, antes de cada sesión

python3 "$SKILL_DIR/scripts/agent_sync.py" status

Idempotente. Inspecciona, repara, informa, nombra exactamente UNA siguiente acción — y lleva el veredicto de check, por lo que el comando que se ejecuta en cada sesión y el que valida la configuración no pueden dar dos respuestas sobre un proyecto.

Lea las dos secciones de conciencia que imprime — son el punto, no decoración.

  • Otras ejecuciones que trabajan en este proyecto ahora mismo. Quién tiene qué, en este minuto. No tome eso y no "solo mire" los archivos que cubren. Una concesión que no puede ver lo bloquea; una concesión que puede ver lo coordina.
  • Novedades desde la última vez que miró. Movimientos de dependencias entre repositorios que aterrizaron mientras estaba fuera. Una dependencia que se movió puede desbloquear lo que planeó — o invalidarlo. Esta lista tiene una marca de agua por ejecución, por lo que permanece en silencio hasta que algo realmente cambie; cuando habla, importa.

Un agente que se salta este bloque volverá a derivar el trabajo que alguien más está haciendo y actuará sobre un estado de dependencia que cambió hace una hora.

Qué más decide status: sin credenciales → modo degradado, informado, y continúa (un modo más pequeño, no un error); task-pipeline ausente → imprime la línea de instalación y se detiene. No improvise un flujo sustituto — sin esas etapas no hay nada a lo que vincularse.

npx sshlg-skills install

Los comandos

ComandoHace
initEjecutar primero. Preguntar dónde vive el estado, escribir la configuración + archivo env ignorado por git, imprimir el paso del operador
statusInspeccionar, reparar, informar, nombrar una siguiente acción
bootstrapCrear el contenedor en la nube e imprimir el ID para pegarlo en el archivo env
acquire <CLAVE>Tomar la concesión en un ID de tarea. Imprime ganó o perdió <titular>
renew <CLAVE>Extender la concesión. El gancho PostToolUse hace esto por usted
release <CLAVE>Devolver la concesión. Haga esto siempre, incluso en caso de fallo
reserve <REG>Reservar el próximo ID en un registro (DEC, OQ, DEP, ...). Imprime el ID
release-id <REG> <ID>Devolver un ID que no terminó escribiendo en git
journal <texto>Añadir una línea al diario de esta ejecución
record <texto>Añadir lo que realmente construyó — --decision DEC-..., --archivos a,b
reconcileIntención (git) vs. construido (nube). --set-baseline una vez por proyecto
signal <DEP-ID> <estado>Mover una dependencia entre repositorios: filed/accepted/delivered/closed/refused
guard <ruta>Responder si esta ejecución puede escribir esa ruta. Salida 0 = sí, 2 = no
boardRegenerar el panel compartido y la página de este repositorio. --mirror también renderiza los documentos git configurados en el plano
whoamiImprimir el ID de esta ejecución y sus concesiones retenidas
setupEscribir la instantánea generada de cómo este proyecto está cableado, para que los agentes la lean
adoptInspeccionar un proyecto existente y proponer una configuración — no escribe nada
mergeAterrizar esta rama: la rama objetivo local avanzada, los conflictos verificados antes de que se toque algo, el registro de fusión escrito, la concesión --key liberada. --summary, --dry-run, --push
mergesQué aterrizó mientras estaba en su rama. --all incluye la cola compactada
checkValidar toda la configuración de principio a fin. Distinto de cero cuando no es saludable
scaffold [--full]Crear solo lo que falta, nunca una línea sobre nada que exista. --full también siembra el registro de preguntas, el índice, el panel de dependencias, el modelo de datos con su registro de entidades y la puerta de documentos
finish [--gates]¿Está el trabajo terminado? — cada repositorio limpio, enviado y señalado, sin concesión retenida. check responde si el proyecto está cableado correctamente; esto responde si ha terminado

$SKILL_DIR es el propio directorio de esta habilidad: ${CLAUDE_PLUGIN_ROOT}/skills/agent-sync bajo el plugin de Claude Code, ~/.agents/skills/agent-sync en otros lugares. Resuélvalo una vez por sesión y reúselo — no adivine una ruta. Cada comando lee .claude/agent-sync.json desde la raíz del proyecto y no necesita argumentos más allá de los listados.

Una identidad por sesión, y cómo se decide

Una concesión es solo una concesión si dos agentes obtienen dos identidades. El orden importa aquí y ambos extremos han mordido: derivar el ID de CLAUDE_SESSION_ID solo le dio a una sesión dos identidades — adquirió como una y fue denegado por su propia guardia como la otra — y mantener un ID por checkout le dio a dos sesiones una identidad, lo cual es peor. La segunda es silenciosa: ambas sesiones adquieren, ambas están protegidas, y release toma una concesión que la persona que llama nunca tuvo.

El orden es: AGENT_SYNC_RUN_ID · CLAUDE_SESSION_ID · la sesión que inició este shell · compartido.

La tercera importa porque un comando de shell simple no tiene ID de sesión y un gancho sí. Entonces SessionStart sella .agent-sync/sessions/<PID de CLI> con la sesión que conoce, y un comando posterior se encuentra a sí mismo recorriendo su propia ascendencia de procesos hasta un PID sellado. Por qué eso y no analizar la línea de comandos: references/earned-rules.md.

Cuando ninguno de los cuatro puede establecerse, la ejecución lo dice — "esta identidad se comparte con cualquier otra sesión en este checkout" — en lugar de presentar una entrada compartida como separación.

Reclamación — la forma que importa

acquire → hacer el trabajo → release

Nunca omita release, incluso en caso de fallo: una concesión abandonada bloquea la tarea hasta que su TTL expire, y el siguiente agente no puede distinguir "en progreso" de "falló hace una hora".

La concesión no es la reclamación. La concesión dice quién la tiene ahora y expira; la reclamación duradera es la etiqueta en git, escrita por acquire y borrada por release. Un hecho, un hogar — no invente un tercer lugar que registre la propiedad.

Lea references/lease-protocol.md antes de cambiar la adquisición, caducidad, robo o asignación de ID.

Archivos protegidos

La configuración enumera los archivos de registro que varios agentes escriben. Antes de editar uno:

python3 "$SKILL_DIR/scripts/agent_sync.py" guard docs/DECISIONS.md

La salida 2 se trata de esta ejecución: no tiene concesión — no que otra persona tenga ese archivo. Una concesión cubre cada archivo protegido; tenga una o no escriba ninguno. Una denegación nombra la otra ejecución y su clave, porque "r-x tiene una concesión" junto a una ruta se repite como "r-x tiene este archivo". No edite de todos modos, y no "solo arregle una línea" — una decisión dañada se ve exactamente como una decisión.

El gancho PreToolUse de Claude Code ejecuta esto por usted. En otros entornos, nada lo hace.

Reservar un ID

Leer una línea "Próximo ID libre" no es reservarlo — dos agentes leen el mismo número y ambos lo usan.

python3 "$SKILL_DIR/scripts/agent_sync.py" reserve DEC   # → DEC-0216

La asignación es posicional sobre el registro fusionado — cada fragmento, nunca solo el de esta ejecución — por lo que cada agente calcula la misma respuesta. ¿Reservado y no escrito en git? release-id lo libera, o el número es un agujero que el panel informa como una fuga.

Nada en un registro se edita o elimina nunca

Los registros se reproducen en orden, por lo que una edición reescribe silenciosamente una conclusión sobre la que otros agentes ya actuaron. Corrija añadiendo: libere una concesión, release-id un ID no utilizado, sustituya una entrada incorrecta de "construido" con una posterior. Las páginas generadas son la única excepción, y una que perdió su marca agent-sync:generated

...

[truncado para traducción]

Skills relacionados