Agentic QAUPEX Galaxy · harnesses
Release · agosto 2026

Una fuente de verdad, tres harnesses que la leen

El repositorio corre igual en Claude Code, OpenCode y Codex (CLI y Desktop). Existe una sola copia de cada instrucción y de cada skill. Donde los harnesses difieren de verdad —formato de MCP, API de hook— cada uno conserva un adaptador fino, versionado y verificado. Nada más está duplicado.

1
cuerpo de instrucciones
3
harnesses soportados
19
skills en un solo store
20
wrappers generados
6
MCPs con paridad
11 B
pesa CLAUDE.md
Instrucciones

Ningún nombre de archivo lo descubren los tres

Claude Code carga CLAUDE.md. OpenCode y Codex cargan AGENTS.md. Mantener dos documentos completos y compararlos en CI no elimina el drift: lo detecta tarde, después de que alguien ya trabajó con la copia vieja.

Por eso la relación se invirtió. AGENTS.md es el único cuerpo de instrucciones y CLAUDE.md quedó en once bytes. Ese @ es la sintaxis de import documentada de Claude Code: trae el archivo al contexto de la sesión. Se eligió por encima de un symlink justamente porque un checkout de Windows lo trata igual que uno de macOS o Linux.

CLAUDE CODE busca CLAUDE.md OPENCODE busca AGENTS.md CODEX CLI + DESKTOP busca AGENTS.md carga nativa CLAUDE.md 11 bytes · shim generado import @AGENTS.md carga nativa carga nativa AGENTS.md único cuerpo de instrucciones · versionado
Claude Code OpenCode Codex artefacto generado
Dos de los tres llegan directo. El tercero llega por un salto de once bytes que nadie escribe a mano. Ese salto es toda la diferencia entre los harnesses en la superficie de instrucciones.
# CLAUDE.md — el archivo entero, sin recortar
@AGENTS.md

Escribir prosa operativa dentro de CLAUDE.md es drift estructural. La skill sync-ai-context se detiene y lo reporta en vez de propagarlo, y bun run agents:compat:check falla si el archivo deja de ser exactamente el shim.

Las cinco superficies

Qué consume cada harness, superficie por superficie

Cinco superficies por tres harnesses. Lo marcado como nativo lo descubre el harness por su cuenta; lo marcado como generado es salida de un script y no se edita a mano.

Superficie Claude Code OpenCode Codex CLI + Desktop
Instrucciones generado
CLAUDE.md un import: @AGENTS.md
nativo
AGENTS.md
nativo
AGENTS.md
Skills generado
.claude/skills symlink en POSIX, junction en Windows
nativo
.agents/skills/
nativo
.agents/skills/
Comandos generado
.claude/commands/*.md 10 wrappers de 7 líneas
generado
.opencode/commands/*.md 10 wrappers de 7 líneas
ninguno invoca la skill directamente
Hook .claude/settings.json UserPromptSubmit .opencode/plugins/ plugin de proyecto .codex/hooks.json UserPromptSubmit + commandWindows
MCP .mcp.jsonJSON opencode.jsoncJSONC .codex/config.tomlTOML

Codex Desktop no agrega convención

CLI y Desktop consumen exactamente la misma configuración del repositorio. Desktop agrega interfaz, no un segundo contrato ni un directorio extra.

Los adaptadores son delgados a propósito

Solo dos superficies tienen adaptador real: el hook y el MCP. Ahí los harnesses difieren en la API, no en la intención. Las otras tres son la misma fuente vista desde tres lugares.

Skills · regla dura

Lo generado nunca se edita a mano ni se commitea

Hay un solo store de skills, .agents/skills/, versionado, con las 19 skills adentro. Todo lo demás que un harness necesita ver son punteros hacia ahí. Si un puntero se rompe, se regenera; nunca se parchea.

FUENTE · VERSIONADA GENERADOR SALIDA · GITIGNORADA .agents/ skills/ 19 skills · el store canónico compatibility/ command-aliases.json · 10 entradas hooks/ personality-reinject.mjs se edita acá, siempre bun run agents:compat .claude/skills symlink POSIX · junction Windows .claude/commands/ 10 wrappers de 7 líneas .opencode/commands/ 10 wrappers de 7 líneas compara byte a byte bun run agents:compat:check corre en repo:check · en pre-push · condicionalmente en pre-commit
La fuente sale una vez del lado izquierdo y vuelve a entrar por abajo como verificación. Un wrapper editado a mano no sobrevive a ese ciclo: la comparación es contra el manifiesto, no contra la última versión que alguien guardó.
Artefacto generado Su fuente Se repara con
.claude/skills .agents/skills/symlink o junction bun run agents:compat
10 wrappers Claude + 10 OpenCode .agents/compatibility/command-aliases.json bun run agents:compat
CLAUDE.md AGENTS.mdun import de 11 bytes bun run agents:compat

La reparación del alias tiene una salvaguarda: si .claude/skills es un directorio real con contenido propio, se niega a borrarlo y nombra el conflicto. La única excepción es la forma que escribe la CLI de skills —un directorio cuyas entradas son todas punteros hacia .agents/skills— porque ahí no hay nada que perder.

Comandos

Los slash commands son transporte, no workflow

Antes cada comando llevaba el workflow entero escrito adentro. adapt-framework solo tenía 590 líneas. Eso era instrucción duplicada que ningún harness fuera de Claude podía descubrir, y que se desincronizaba de su skill en cuanto alguien editaba una de las dos copias.

Workflow duplicado dentro de los diez comandos 2 531 líneas
Wrappers que los reemplazan 41 líneas

Los diez nombres sobreviven como alias. El wrapper solo selecciona skill y modo, y reenvía $ARGUMENTS sin tocarlo. Este es un archivo completo, no un fragmento:

# .claude/commands/business-data-map.md — las 7 líneas, enteras
---
description: Generate or refresh the business data and flow map.
argument-hint: [project-path]
---

Invoke skill `project-context` in mode `data`.
Forward `$ARGUMENTS` unchanged.
Alias Skill destino Modo
/adapt-framework adapt-framework adapt
/break-down-tests test-automation explainsellado, solo lectura
/business-data-map project-context data
/business-feature-map project-context features
/business-api-map project-context api
/master-test-plan project-context test-plan
/fix-traceability test-documentation repair-traceability conserva el gate de aprobación
/jira-components jira-administration components
/jira-instance-migration jira-administration instance-migration
/sync-ai-memory sync-ai-context sync

Codex no usa wrappers

No hay una tercera copia de los diez archivos. Codex invoca la skill directamente, que es exactamente lo que el wrapper hace por vos en los otros dos.

La verificación no es cosmética

agents:compat:check rechaza un alias cuya skill destino no exista o cuyo modo no esté declarado. Y a un wrapper al que le crece un cuerpo lo falla con el mensaje contains workflow prose.

Hook

Un emisor, tres adaptadores

El contrato de personalidad que se reinyecta en cada prompt vive una sola vez, en .agents/hooks/personality-reinject.mjs. El archivo exporta la constante y además la escribe a stdout cuando se lo ejecuta como script. Esas dos formas de consumirlo son las que necesitan los tres harnesses.

personality-reinject.mjs en .agents/hooks/ · el contrato, una vez exporta la constante · la imprime a stdout ejecuta ejecuta importa .claude/settings.json UserPromptSubmit · stdout → developer context .codex/hooks.json UserPromptSubmit · stdout → developer context .opencode/plugins/ muta output.system en el lugar
Los verbos de las flechas son la diferencia real: dos harnesses ejecutan el archivo y leen su salida, uno lo importa como módulo. El texto del contrato es idéntico en los tres porque nunca se copió.

El validador de contrato rechaza, con nombre y línea:

  • Rutas absolutas personales dentro de cualquier comando de hook, que romperían en la máquina de cualquier otra persona.
  • Un emisor compartido que trate CLAUDE.md como el archivo canónico, que es exactamente la inversión que este release deshizo.
  • Un plugin de OpenCode que reemplace output.system en vez de mutarlo, lo que descartaría el system prompt del harness.
  • La reaparición de los archivos de hook duplicados que se eliminaron.

El adaptador de Codex además carga commandWindows para PowerShell y resuelve la raíz del repositorio con git rev-parse --show-toplevel, en vez de asumir el directorio de trabajo.

MCP

Seis servidores, tres formatos, paridad semántica

Los seis servidores canónicos existen en las tres configuraciones. La comparación no puede ser textual: los archivos ni siquiera comparten lenguaje.

context7 tavily playwright dbhub openapi postman
.mcp.json JSON · Claude Code opencode.jsonc JSONC · OpenCode .codex/config.toml TOML · Codex normalización transporte · comando · args url · env vars · estado una forma común, sin sintaxis compara 6 servidores × 3 hosts agregarlo a uno solo es un fallo, no un aviso
Sin el paso del medio, la comparación solo podría decir que los tres archivos son distintos. Con él, dice si describen los mismos seis servidores.
Migración

Si venís de la versión anterior

Un proyecto creado cuando las instrucciones vivían en CLAUDE.md y las skills en .claude/skills/ recibe una migración preflight la primera vez que corre bun run up — antes de que se sincronice un solo componente, porque sincronizar primero sobre una estructura vieja es exactamente cómo se pierde trabajo.

bun run up en un proyecto de la era Claude migración preflight antes de sincronizar ningún componente ¿todo resoluble sin adivinar? se evalúa el árbol entero, no archivo por archivo no se niega entera no toca nada · nada a medias nombra el archivo que la bloqueó migra, en este orden memoria → AGENTS.md, shim de 11 bytes skills → .agents/skills/, propias incluidas colisión de nombre → se archiva la legacy .template/pre-agents-migration/ recién ahora se sincronizan los componentes
La rama izquierda es la que importa: una migración que no puede resolver un elemento sin adivinar aborta completa en vez de dejar el proyecto mitad viejo y mitad nuevo.

Nada se borra

Todo se mueve o se respalda. Lo que no se puede mover a su lugar canónico queda en .template/pre-agents-migration/, con su contenido intacto.

Es idempotente

Correrla dos veces no hace nada la segunda vez. Un proyecto ya migrado pasa de largo sin escribir.

Límites conocidos

Lo que todavía no está cerrado

Cuatro cosas que conviene saber antes de apoyarse en esto, dichas como límites y no como notas al pie.

  • El adaptador de OpenCode usa experimental.chat.system.transform. Es una API oficial, pero marcada como experimental por el proyecto. Claude y Codex están sobre APIs de hook estables. Hay que re-verificar al actualizar OpenCode.
  • El junction de Windows está cubierto por tests unitarios de construcción de ruta y de comando. La verificación en una máquina Windows real sigue pendiente.
  • Codex necesita que el repositorio esté marcado como confiable. La configuración de proyecto bajo .codex/ y sus hooks no cargan si no lo está. bun run setup:doctor reporta esa confianza por separado de la corrección de los archivos, porque es estado de runtime que no se puede verificar leyendo el disco.
  • Lanzá siempre con bun run claude, bun run opencode o bun run codex. Cada uno pasa por dotenv -o, que fuerza que .env gane sobre una variable heredada del proceso padre. Ejecutar el binario pelado se saltea eso y puede dejar un valor viejo tapando el del archivo.