CLI no interactiva, JSON y pipelines
La automatización fiable no depende de frases que haya que interpretar. Depende de entradas estables, esquemas, códigos de salida y una ruta de fallo que impida que las fases posteriores actúen sobre resultados incompletos.
Qué trabajarás, paso a paso
Interactivo y no interactivo
Cuando estás delante del terminal puedes corregir una petición sobre la marcha. Una pipeline no puede levantar la mano y preguntarte qué querías decir. Por eso el paso al modo no interactivo no consiste en quitar el chat: consiste en volver explícito todo aquello que antes decidías durante la conversación.
En una sesión interactiva, el usuario puede aclarar una petición a mitad de camino. En una pipeline, la entrada y las condiciones deben estar completas antes del arranque. El script debe saber cuándo terminar, qué imprimir y qué estado devolver.
Usa entradas pequeñas y versionables: por ejemplo `git diff main | claude -p "Revisa este diff" --output-format json`. Fija la carpeta de trabajo y añade en el wrapper timeout, herramientas permitidas y gestión del exit code. En CI, `--bare` evita cargar configuraciones locales no previstas. No dependas de conversaciones invisibles ni de la carpeta implícita de la shell.
Cada noche quieres analizar los cambios de Task Notes sin depender del historial del chat ni de la carpeta en la que casualmente se encuentre la shell.
- Fija el repositorio con una ruta explícita e identifica el intervalo Git que hay que examinar, por ejemplo desde el commit base hasta `HEAD`.
- Pasa objetivo y restricciones en un archivo de instrucciones versionado en vez de reconstruirlos a partir de mensajes anteriores.
- Define timeout, salida esperada y código de salida para éxito, hallazgos y error técnico.
- Ejecuta dos veces sobre el mismo commit y compara los artefactos esenciales antes de confiar el comando a un scheduler.
Resultado: La review ya no depende de una sesión invisible. Cualquiera que tenga el mismo commit y el mismo contrato puede reproducir la ejecución y entender dónde se detuvo.
JSON como contrato, no como decoración
Poner llaves alrededor de una respuesta no la transforma en un contrato. JSON se vuelve útil cuando sabes qué campos existen, qué tipo tienen y qué debe ocurrir si faltan. De lo contrario, solo tienes prosa más incómoda de leer.
Una salida estructurada es útil cuando los campos están definidos y validados. Con `--json-schema`, el resultado conforme al esquema se devuelve en el campo `structured_output`; texto libre anidado sin un contrato solo desplaza el problema de interpretación.
El formato `stream-json` emite los eventos del protocolo de Claude Code durante la ejecución. Tu programa debe reconocer esos tipos reales y luego puede transformarlos en eventos de aplicación como progreso o hallazgo; no debe asumir que el stream produce nombres personalizados inventados por el prompt.
La pipeline debe bloquear la fase siguiente cuando la review encuentra un error alto, pero continuar si solo existen notas informativas.
- Define `status` como enum y `findings` como lista de objetos con `severity`, `file`, `message` y, si hace falta, `line`.
- Haz obligatorios `runId` y `schemaVersion`, para poder atribuir la salida y gestionar cambios de formato.
- Valida el JSON antes de leer los hallazgos; si la validación falla, clasifica la ejecución como error técnico.
- Calcula el gate a partir de los campos validados, no buscando palabras como «crítico» dentro de mensajes libres.
Resultado: La pipeline distingue el contenido de la review del error de formato. Una frase nueva en el mensaje no cambia accidentalmente la decisión automática.
Gates y propagación del fallo
Un gate que se pone en rojo pero deja pasar el trabajo no es un gate: es una decoración. La parte difícil de una pipeline no es arrancar lint y pruebas, sino propagar el fallo para que ninguna fase posterior pueda comportarse como si todo hubiera ido bien.
Una pipeline fiable valida la salida antes de usarla, detiene la ruta cuando lint o los tests fallan y propaga un código de salida distinto de cero. Seguir generando un informe de error no significa continuar con deploy o publicación.
Conserva los artefactos útiles para el diagnóstico: log reducido, fase responsable y salida validada. `claude -p` usa el exit code para el éxito o el error técnico de la ejecución; un JSON válido con un hallazgo grave puede llegar igualmente con exit code 0. Es el wrapper el que debe leer ese resultado y transformarlo en el código de salida que hayas decidido para tu gate.
- Fija la entrada, la carpeta de trabajo y el límite temporal de la rutina.
- Solicita una salida estructurada y valídala contra el esquema.
- Ejecuta lint y tests como gates con códigos de salida significativos.
- Interrumpe las fases dependientes en el primer gate fallido.
- Conserva el informe, la fase responsable y los artefactos útiles para el diagnóstico.
La review produce JSON válido, pero el linter encuentra un error. La pipeline debe guardar el diagnóstico y no ejecutar el comando que prepara la release.
- Ejecuta la validación del esquema e interrúmpela de inmediato si la salida no respeta el contrato.
- Lanza el linter capturando salida y exit code sin transformar automáticamente el error en éxito.
- Si el exit code es distinto de cero, guarda fase, comando, versión y la porción útil del log en un artefacto local.
- Devuelve un código distinto de cero desde el proceso principal y verifica que el paso de release quede omitido, no fallado después de empezar.
Resultado: El fallo sigue siendo diagnosticable y queda contenido. La pipeline comunica con claridad que la release nunca empezó, en vez de dejar un estado intermedio ambiguo.
Auto mode y radio operativo
Saltarse confirmaciones puede parecer una pequeña optimización. En realidad desplaza la frontera de la autoridad: una interpretación errónea ya no se detiene delante de ti. Antes de reducir los checkpoints, debes hacer más pequeños el entorno, las herramientas y las consecuencias.
Los modos de permiso no son equivalentes: `default` pide confirmación para las acciones sensibles, `acceptEdits` reduce las confirmaciones sobre las modificaciones, `plan` permanece en lectura, `dontAsk` permite solo lo que has preaprobado, mientras que `auto` usa controles de seguridad en segundo plano. La disponibilidad y el comportamiento dependen de la versión y del plan.
`bypassPermissions`, equivalente a `--dangerously-skip-permissions`, omite los controles y solo es apropiado en entornos aislados. No desactives globalmente las protecciones porque una pipeline sea ruidosa: limita carpetas, herramientas, red y duración, y conserva aprobaciones separadas antes de efectos externos.
Quieres ejecutar una review nocturna de Task Notes sin aprobar cada lectura, pero el ordenador también tiene credenciales para el repositorio remoto.
- Crea una copia de trabajo dedicada y limita la rutina a lectura más escritura solo del informe local.
- Elimina de la sesión tokens de push y accesos innecesarios; desactiva la red si las fuentes ya son locales.
- Configura timeout, número máximo de archivos y parada inmediata ante comandos fuera de la lista prevista.
- Ejecuta varias veces con el log activo; solo después evalúa qué confirmaciones repetitivas pueden reducirse sin ampliar la autoridad.
Resultado: La rutina se vuelve más cómoda sin convertirse en omnipotente. Aunque interprete mal un archivo, no puede publicar, borrar ni salir de la carpeta asignada.
Pipeline local de revisión
Task Notes debe controlar cada cambio sin publicar nada.
1. Lee los archivos modificados
2. Genera {status, findings, tests}
3. Valida el esquema JSON
4. Ejecuta lint; si falla → exit 1
5. Ejecuta tests; si fallan → exit 1
6. Guarda el informe local; sin deploy