Lo esencial
En el modo normal, Claude Code es un cirujano con un asistente (tú): él propone y tú apruebas. En el modo headless (sin interfaz: trabaja en segundo plano, sin ventana; oficialmente se llama Agent SDK CLI) es un robot cirujano totalmente autónomo: recibe la tarea, la cumple, reporta y se apaga. Sin diálogo, sin "presiona Enter", sin pantalla. Así trabaja Claude en los pipelines de CI/CD (Continuous Integration/Delivery, integración y entrega continuas), en GitHub Actions (el sistema de automatización de GitHub) y en tareas cron (el programador de tareas por horario): sin una persona al lado, 24/7.
Términos de la lección: headless (sin interfaz, en segundo plano), CI/CD (integración y entrega continuas), GitHub Actions (el sistema de automatización de GitHub), cron (el programador de tareas por horario), API (interfaz de programación), token (una unidad de texto para la IA), permission (permiso: el derecho a ejecutar una acción), prompt (la solicitud a la IA), agent (agente: un ejecutor autónomo), workflow (flujo de trabajo).
Nota de la documentación de Anthropic: lo que antes se llamaba "headless mode" ahora se llama oficialmente Agent SDK CLI. La opción
-py todas las demás funcionan igual.
Conceptos clave
--print/-p: Claude responde una vez y termina (modo Agent SDK CLI)- Pipe (stdin): pasar datos con
cat file | claude -p "..."(límite de 10 MB) --bare: arranque rápido sin cargar hooks/skills/MCP/CLAUDE.md (recomendado para CI; requiereANTHROPIC_API_KEY, el acceso con suscripción no funciona en este modo)--output-format: formato de salida:text,json,stream-json--json-schema: JSON validado según el esquema que indiques--max-turns N: limitar las iteraciones para controlar el costo--max-budget-usd: un límite estricto de gasto en dólares--permission-mode: manejo de permisos:dontAsk,acceptEdits,auto,bypassPermissions--allowedTools: whitelist de herramientas que se aprueban automáticamente- GitHub Actions: la action oficial
anthropics/claude-code-action@v1 - Variables de entorno:
ANTHROPIC_API_KEY,CLAUDE_CODE_OAUTH_TOKEN,CLAUDE_CODE_USE_BEDROCK,CLAUDE_CODE_USE_VERTEX
Teoría
La opción --print: salir del modo interactivo
Por defecto, claude abre un REPL: una sesión interactiva donde platicas con Claude. La opción --print (o -p) cambia el comportamiento:
# Modo interactivo (espera tu entrada)
claude
# Headless: solicitud → respuesta → salida
claude --print "Explica qué hace esta función: def f(x): return x * 2"
# Forma corta
claude -p "Genera un UUID v4 en Python"Qué pasa: Claude recibe la solicitud, hace todas las acciones necesarias (lee archivos, corre código, escribe el resultado), imprime la respuesta en stdout y termina el proceso con código 0 (éxito) o un código distinto de cero (error).
--bare: arranque rápido para CI/CD
La opción --bare se salta la carga automática de hooks, skills, plugins, servidores MCP, la memoria automática y CLAUDE.md. Es el modo recomendado para scripts y CI/CD: el resultado es el mismo en cualquier máquina y no se carga nada "ajeno".
# Arranque rápido sin contexto de más
claude --bare -p "Summarize this file" --allowedTools "Read"En el modo bare, Claude tiene acceso a Bash y a leer y editar archivos. Todo lo demás se pasa explícitamente con opciones. Importante: sin --bare, claude -p carga los hooks y servidores MCP de .claude/settings.json y .mcp.json del proyecto sin preguntar por la confianza, así que con código ajeno en CI conviene correrlo justo con --bare:
| Qué necesitas cargar | Qué opción usar |
|---|---|
| Prompt de sistema | --append-system-prompt o --append-system-prompt-file |
| Configuración | --settings <file-or-json> |
| Servidores MCP | --mcp-config <file-or-json> |
| Tus propios subagentes | --agents <file-or-json> |
| Plugins | --plugin-dir <path> o --plugin-url <url> |
De la documentación de Anthropic:
--barese recomienda para scripts y será el modo por defecto de-pen versiones futuras. En modo bare, Claude Code no lee el acceso con suscripción (OAuth) ni el llavero del sistema, así que necesitas unaANTHROPIC_API_KEYde Claude Console (o las claves en la nube de Bedrock y similares).
Pipe: stdin como datos de entrada
El patrón estándar de Unix es pasar datos por un pipe. Claude Code soporta stdin por completo:
# Resumen de un log
cat server.log | claude -p "Encuentra todos los errores de nivel ERROR, agrúpalos por tipo, muestra los 5 principales"
# Code review de un archivo concreto
cat src/payment.py | claude -p "Encuentra posibles vulnerabilidades de seguridad en este código"
# Analizar el git diff antes del commit
git diff HEAD | claude -p "Escribe un mensaje de commit para estos cambios en formato Conventional Commits"
# Procesar un CSV
cat leads.csv | claude -p "De este CSV elige las filas donde la columna 'status' = 'qualified', devuelve un arreglo JSON"El pipe vuelve a Claude parte de los pipelines estándar de Unix: lo puedes meter en cualquier script de shell.
Limitación: stdin tiene un límite de 10 MB. Si lo rebasas, Claude Code termina con un error. Para archivos grandes, guarda los datos en un archivo e indica la ruta en el prompt en lugar del pipe.
--output-format json: salida legible por máquinas
Cuando Claude Code trabaja en una automatización, hay que leer su respuesta desde un programa. La opción --output-format json envuelve la salida en una estructura JSON:
claude -p "Revisa la sintaxis de este archivo de Python y devuelve una lista de errores" \
--output-format json \
< src/main.pySalida:
{
"type": "result",
"subtype": "success",
"total_cost_usd": 0.0023,
"duration_ms": 1840,
"result": "Se encontraron 2 errores:\n1. Line 14: SyntaxError — missing colon after if\n2. Line 31: IndentationError — unexpected indent"
}En el script lo lees con jq:
RESULT=$(cat src/main.py | claude -p "Encuentra errores de sintaxis" --output-format json)
ERRORS=$(echo "$RESULT" | jq -r '.result')
COST=$(echo "$RESULT" | jq -r '.total_cost_usd')
echo "Costo del análisis: $COST USD"
echo "Resultado: $ERRORS"Tres formatos de salida:
| Formato | Descripción | Cuándo usarlo |
|---|---|---|
text |
Texto normal (por defecto) | Lo lee una persona |
json |
JSON con result, session_id, total_cost_usd |
Leerlo desde scripts |
stream-json |
NDJSON: un objeto JSON por línea, en tiempo real | Streaming, monitoreo en vivo |
--json-schema: salida estructurada y validada
Cuando necesitas una respuesta con una estructura estrictamente definida, usa --json-schema. Claude devolverá un JSON validado según el JSON Schema que indiques. El resultado estará en el campo structured_output:
# Extraer los nombres de funciones en un formato estrictamente tipado
claude -p "Extrae los nombres de las funciones de auth.py" \
--output-format json \
--json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'Leer la salida estructurada:
# Obtener el arreglo de funciones
claude -p "Extrae las funciones de auth.py" \
--output-format json \
--json-schema '...' \
| jq '.structured_output'Streaming con stream-json
Para el monitoreo en vivo, usa stream-json con --verbose y --include-partial-messages:
# Streaming de tokens en tiempo real
claude -p "Escribe un poema" \
--output-format stream-json \
--verbose \
--include-partial-messages \
| jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'Control del costo y del modelo
# Indicar un modelo concreto (alias)
claude -p "Análisis de arquitectura complejo" --model opus
# Indicar el nombre completo del modelo (ejemplo de la documentación; los nombres vigentes están en la página Lo vigente)
claude -p "Análisis" --model claude-opus-5-5
# Modelo de respaldo si el principal está saturado (se puede dar una lista separada por comas)
claude -p "Solicitud" --fallback-model sonnet
# Limitar las iteraciones (para controlar el costo en tareas de agente)
claude -p "Corrige los bugs en src/" --max-turns 3
# Límite estricto de gasto en dólares
claude -p "Refactoriza el módulo de autenticación" --max-budget-usd 2.00--max-turns es especialmente importante en CI/CD: si Claude intenta corregir un bug sin fin, saldrá caro. Un límite de 3-5 iteraciones es razonable para tareas automáticas. Al llegar al límite, Claude termina con un error.
--max-budget-usd es un techo estricto de gasto. Si Claude gastó la cantidad indicada, se detiene. Solo funciona en print mode.
Modos de permisos para CI/CD
En CI/CD no hay una persona que presione "Yes". Enfoques para los permisos (los modos se describen en la lección Permisos y seguridad). Si no indicas un modo, -p toma el modo inicial por defecto, que puede resultar ser auto, así que fíjalo explícitamente:
# Enfoque 1: whitelist de herramientas concretas (recomendado)
# Claude solo puede leer y hacer operaciones de git
claude -p "Revisa el código" --allowedTools "Read" "Bash(git *)"
# Enfoque 2: dontAsk: solo lo aprobado de antemano, todo lo demás se rechaza
claude -p "Revisa el código" --permission-mode dontAsk
# Enfoque 3: acceptEdits: aprobar automáticamente la edición de archivos
claude -p "Corrige los errores de lint" --permission-mode acceptEdits
# Enfoque 4: auto: un modelo revisor decide en lugar de la persona
claude -p "Actualiza las dependencias y corre las pruebas" --permission-mode auto --permission-prompts none
# Enfoque 5: Bypass: ¡SOLO en contenedores aislados!
claude -p "Arregla todo" --dangerously-skip-permissionsLa regla para CI/CD: usa los permisos mínimos necesarios. --allowedTools con una whitelist de comandos concretos es mejor que --dangerously-skip-permissions.
Comodín en allowedTools: Bash(git diff *) permite cualquier comando que empiece con git diff. El espacio antes del * importa: sin él, Bash(git diff*) también permitiría git diff-index.
CI/CD: GitHub Actions
La GitHub Action oficial de Anthropic
Anthropic tiene una GitHub Action oficial: anthropics/claude-code-action@v1. Se puede instalar con un solo comando desde Claude Code:
# En una sesión interactiva de Claude Code
/install-github-appEl comando necesita GitHub CLI instalado y con sesión iniciada (gh auth login), permisos de administrador del repositorio y un repositorio en github.com. O se configura a mano: instalar la GitHub App (github.com/apps/claude) y agregar a los secrets del repositorio ANTHROPIC_API_KEY (una clave de Claude Console) o CLAUDE_CODE_OAUTH_TOKEN (un token de suscripción Pro, Max, Team o Enterprise, que se obtiene con el comando claude setup-token).
Workflow básico: reacciona a @claude en los comentarios de PR/issues:
# .github/workflows/claude.yml
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
claude:
if: contains(github.event.comment.body, '@claude')
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
# Reacciona automáticamente a @claude en los comentariosCode review automático en cada PR:
# .github/workflows/claude-review.yml
name: Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: "Analiza este PR en cuanto a calidad del código, bugs y seguridad. Deja las observaciones como review comments."
claude_args: "--max-turns 5 --model sonnet"
# Para publicar las observaciones directo en el PR, la action necesita la herramienta de comentarios inline
# (ver el ejemplo de review-workflow en la documentación). Para un review automático sin workflow propio
# también existe la función lista Code Review: code.claude.com/docs/en/code-reviewParámetros de claude-code-action@v1:
| Parámetro | Descripción | Obligatorio |
|---|---|---|
anthropic_api_key |
Clave de API de Anthropic | Sí (para la API directa), si no usas claude_code_oauth_token |
claude_code_oauth_token |
Token de suscripción (de claude setup-token) |
No |
prompt |
Instrucciones para Claude | No (sin él reacciona a @claude) |
claude_args |
Cualquier opción de CLI de Claude Code | No |
github_token |
Token de GitHub para la API | No (por defecto la action funciona como la Claude GitHub App) |
trigger_phrase |
Frase disparadora (por defecto @claude) |
No |
plugin_marketplaces, plugins |
Instalar plugins y correr sus skills | No |
use_bedrock |
Usar Amazon Bedrock | No |
use_vertex |
Usar Google Cloud Agent Platform (antes Vertex AI) | No |
use_foundry |
Usar Microsoft Foundry | No |
Enfoque manual: Claude CLI en GitHub Actions
Si necesitas control total, puedes usar claude -p directamente:
# .github/workflows/claude-review.yml
name: Claude Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
code-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Claude Code
# El método npm funciona (necesita Node.js 22+); la forma principal hoy: curl -fsSL https://claude.ai/install.sh | bash
run: npm install -g @anthropic-ai/claude-code
- name: Run Claude Code Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
# Obtenemos el diff solo de los archivos cambiados
git diff origin/main...HEAD -- '*.py' '*.ts' '*.js' > changes.diff
# Claude analiza los cambios (--bare para un CI limpio)
REVIEW=$(cat changes.diff | claude --bare -p "
Eres un code reviewer senior. Analiza este diff.
Encuentra: bugs, problemas de seguridad, violaciones de SOLID.
Si todo está bien, escribe 'LGTM'. Marca los problemas críticos con la palabra CRITICAL.
" --output-format json --max-turns 3 | jq -r '.result')
echo "## Claude Code Review" >> $GITHUB_STEP_SUMMARY
echo "$REVIEW" >> $GITHUB_STEP_SUMMARY
# La revisión va en el mismo paso: la variable REVIEW no pasa de un paso a otro
if echo "$REVIEW" | grep -q "CRITICAL"; then
echo "Critical issues found — blocking merge"
exit 1
fiHook pre-commit con Claude
Revisión automática del código antes de cada commit:
#!/bin/bash
# .git/hooks/pre-commit
# Obtenemos la lista de archivos de Python cambiados
CHANGED_PY=$(git diff --cached --name-only --diff-filter=ACM | grep '\.py$')
if [ -z "$CHANGED_PY" ]; then
exit 0 # No hay archivos de Python: lo dejamos pasar
fi
echo "Claude Code está revisando los cambios..."
for FILE in $CHANGED_PY; do
RESULT=$(cat "$FILE" | claude -p "
Revisa este archivo de Python en busca de:
1. Errores de sintaxis
2. Secretos escritos en el código (contraseñas, claves de API)
3. Inyecciones SQL
Si encuentras un problema, responde 'BLOCK: <descripción>'.
Si todo está limpio, responde 'OK'.
" --bare --max-turns 1 --output-format json | jq -r '.result')
if echo "$RESULT" | grep -q "^BLOCK:"; then
echo "Problema en $FILE:"
echo "$RESULT"
exit 1 # Bloqueamos el commit
fi
done
echo "Todas las revisiones pasaron."
exit 0Instalar el hook:
chmod +x .git/hooks/pre-commitGenerar el CHANGELOG automáticamente
#!/bin/bash
# scripts/generate-changelog.sh
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "HEAD~50")
COMMITS=$(git log ${LAST_TAG}..HEAD --oneline)
if [ -z "$COMMITS" ]; then
echo "No hay commits nuevos"
exit 0
fi
echo "Generando el CHANGELOG con Claude..."
CHANGELOG=$(echo "$COMMITS" | claude -p "
Esta es una lista de commits de git. Genera un CHANGELOG en formato Keep a Changelog.
Agrúpalo por categorías: Added, Changed, Fixed, Removed.
Usa descripciones cortas y claras en español.
Empieza directo con ## [Unreleased]: no agregues texto introductorio.
")
# Lo agregamos al principio de CHANGELOG.md
echo "$CHANGELOG" | cat - CHANGELOG.md > /tmp/changelog_new
mv /tmp/changelog_new CHANGELOG.md
echo "CHANGELOG.md actualizado"Autenticación y variables de entorno
Para trabajar sin interfaz, Claude necesita una clave de API. En CI/CD se usan variables de entorno:
| Variable | Descripción |
|---|---|
ANTHROPIC_API_KEY |
Clave de API de Anthropic (la forma principal) |
CLAUDE_CODE_USE_BEDROCK=1 |
Usar Amazon Bedrock en lugar de la API de Anthropic |
CLAUDE_CODE_USE_VERTEX=1 |
Usar Google Cloud (Vertex AI; en la documentación ahora se llama Google Cloud's Agent Platform) |
CLAUDE_CODE_OAUTH_TOKEN |
Token de suscripción para CI (se obtiene con el comando claude setup-token) |
ANTHROPIC_MODEL |
Modelo por defecto (--model lo sobrescribe) |
Generar un token de larga duración para CI:
# Crea un token OAuth y lo muestra en la terminal (no lo guarda)
# Requiere una suscripción de Claude
claude setup-tokenEl token se puede usar en lugar de ANTHROPIC_API_KEY en los pipelines de CI/CD (con CLAUDE_CODE_OAUTH_TOKEN o el parámetro claude_code_oauth_token de la action). La excepción: junto con --bare, el token de suscripción no funciona; ahí hace falta una clave de API. Para un secreto compartido de toda la organización, la documentación recomienda una clave de API y no un token: el token está ligado a la suscripción de la persona que lo creó.
Continuar sesiones en scripts
Puedes armar cadenas de llamadas que continúan el contexto anterior:
# Primera solicitud: análisis
claude -p "Analiza el rendimiento de este proyecto"
# Continuar la última conversación
claude -p "Ahora enfócate en las consultas SQL" --continue
# O con el session ID, para mayor confiabilidad
SESSION=$(claude -p "Empieza el review" --output-format json | jq -r '.session_id')
claude -p "Continúa el review" --resume "$SESSION"Patrones de costo/velocidad en headless
| Tarea | Modelo | max-turns | Orden de costo por ejecución |
|---|---|---|---|
| Revisión de sintaxis | haiku | 1 | mínimo |
| Code review de un diff | sonnet | 1 | bajo |
| Generar el changelog | sonnet | 1 | bajo |
| Corrección automática de bugs | sonnet | 5 | medio |
| Refactorización compleja | opus | 10 | por encima del medio |
El costo exacto de una ejecución lo ves en el campo total_cost_usd de la respuesta (es una estimación del lado del cliente y puede diferir de la factura real). Precios por token: precios y versiones vigentes: Lo vigente.
Reglas para controlar el costo en CI/CD:
--max-turns 1para análisis (solo lectura + salida)--max-turns 3-5para tareas que cambian archivos--max-budget-usd 5.00: techo estricto de gasto por ejecución--bare: no cargar contexto de más (ahorra tiempo y tokens)--model sonnetpara la rutina,--model opussolo para lo complejo
Práctica
Tarea: un hook pre-commit para buscar secretos
- Crea un repositorio git de prueba:
git init test-repo && cd test-repo - Crea el archivo
.git/hooks/pre-commitcon el contenido del ejemplo de arriba (una versión simplificada: solo la búsqueda de secretos) - Haz el hook ejecutable:
chmod +x .git/hooks/pre-commit - Crea el archivo
config.pycon este texto:python API_KEY = "sk-1234567890abcdef" # clave de prueba DATABASE_URL = "postgresql://user:password@localhost/db" - Intenta hacer el commit:
git add config.py && git commit -m "test"; el hook debe bloquearlo - Quita los secretos (usa variables de entorno) y repite el commit: debe pasar
- Extra: agrega al hook la generación del mensaje de commit con
git diff --cached | claude -p "Escribe un mensaje de commit"
Meta: entender cómo funciona Claude Code sin interfaz y cómo integrarlo en pipelines automáticos.
Herramientas y recursos
claude -p "...": solicitud headless (modo Agent SDK CLI)--bare: arranque rápido sin contexto (recomendado para CI)--output-format json: salida estructurada (result,total_cost_usd,session_id)--json-schema: salida estructurada validada según un JSON Schema--output-format stream-json: streaming NDJSON--max-turns N: límite de iteraciones--max-budget-usd N: límite estricto de gasto--allowedTools: whitelist de herramientas con soporte de comodines--permission-mode:dontAsk,acceptEdits,bypassPermissions--continue/--resume: continuar sesiones en scriptsclaude setup-token: generar un token OAuth de larga duración para CIanthropics/claude-code-action@v1: la GitHub Action oficial/install-github-app: configuración rápida de la GitHub App desde Claude Codejq:brew install jq, para leer JSON en scripts de bash- Documentación: https://code.claude.com/docs/en/headless
Conclusiones clave
claude --bare -p "solicitud"= el formato recomendado para CI/CD.--barepara un arranque limpio,-ppara headless. Nada interactivo, el mismo resultado en cualquier máquina.
El pipe (
cat file | claude -p "...") vuelve a Claude parte de un pipeline de Unix. El límite de stdin es de 10 MB. Para datos grandes, indica la ruta del archivo en el prompt.
Tres niveles de seguridad en CI:
--allowedTools(whitelist de comandos concretos) es mejor que--permission-mode dontAsk, que es mejor que--dangerously-skip-permissions. Usa los permisos mínimos necesarios.
La GitHub Action oficial (
anthropics/claude-code-action@v1) es más sencilla que la configuración manual. Reacciona a@claudeen los comentarios, soporta skills y todas las opciones de CLI medianteclaude_args.
Control del gasto:
--max-turns 3+--max-budget-usd 5.00+--model sonnet= límites razonables para tareas automáticas.
Qué sigue
La marca se guarda solo en este navegador y no se envía a ningún sitio. Mi progreso