Comparativa · Intermedio · 10 min
Opus 5.5 vs Sonnet 5.5 vs Haiku 5.5 en Claude Code: cuál usar
Qué modelo y qué effort elegir en Claude Code 2.1.316, precios oficiales, opusplan y una prueba reproducible con tests ocultos (resultados pendientes).
Probado con Claude Code 2.1.316 · revisado
Ver los archivos en GitHub Gratis · licencia MIT
Resumen y veredicto
En seis semanas han llegado cuatro modelos nuevos a Claude Code (Fable 5.1, Opus 5.5, Sonnet 5.5 y Haiku 5.5) y, además, los modelos 5.5 arrancan ahora con effort medium. La pregunta «¿cuál uso?» es diaria y la respuesta habitual es una opinión. Aquí tienes dos cosas: una tabla de decisión basada en la documentación oficial y una prueba reproducible (misma tarea, mismo repositorio, pruebas ocultas, tres repeticiones) para medir tiempo, coste y calidad.
Estado de la prueba: metodología lista; resultados pendientes. La prueba cuesta dinero y todavía no se ha ejecutado, así que en esta página no hay ninguna cifra de resultados. Cuando se ejecute, la tabla de resultados se rellenará con fecha y versión. Mientras tanto, el veredicto se basa solo en la documentación oficial:
- Día a día con alcance claro: Sonnet 5.5 en
medium. Cuesta la mitad que Opus. - Bugs en código existente, diseño o cuando Sonnet se equivoca: Opus 5.5 en
medium(el valor por defecto) ohigh. - Tareas simples y de mucho volumen, subagentes de búsqueda: Haiku 5.5 en
lowomedium. - Trabajo más grande que una sesión, causa raíz o arquitectura: Fable 5.1, que puede cobrarse con créditos de uso.
- Planificar con Opus e implementar con Sonnet:
/model opusplan.
Todos los archivos de la prueba están en el repositorio gratuito ctrlia-opus-sonnet-haiku.
Los cuatro modelos que tienes hoy en Claude Code
En la API de Anthropic los alias apuntan a: opus → Opus 5.5 (desde la 2.1.280), sonnet → Sonnet 5.5 (2.1.284), haiku → Haiku 5.5 (2.1.293) y fable → Fable 5.1 (2.1.257). Los cuatro tienen ventana de 1 millón de tokens. En Bedrock, Agent Platform y Foundry los alias de Sonnet y Haiku siguen en versiones anteriores, así que allí hay que poner el ID completo.
Con el valor default, Pro, Max, Ultra, Team, Enterprise y la API arrancan en Opus 5.5. Fable nunca es el modelo por defecto y, según tu plan, puede cobrarse con créditos de uso (el selector lo indica con «Requires usage credits»). Para fijar una versión exacta usa el ID:
claude --model claude-opus-5-5
El effort: el ajuste que casi nadie toca
Los cuatro modelos aceptan low, medium, high, xhigh y max. Opus 5.5, Sonnet 5.5 y Haiku 5.5 arrancan en medium (Opus 5 arrancaba en high); según Anthropic, Opus 5.5 en medium iguala o supera a Opus 5 en high en sus evaluaciones de código. La guía oficial:
low: cambios pequeños que revisas tú (un renombrado).medium: trabajo diario con alcance claro.high: cuando importa verificar o hay casos límite (un bug en código existente).xhigh: razonar más a costa de tokens.max: problemas duros sin supervisión, con aviso de rendimientos decrecientes.
Se cambia con /effort (con s solo para esta sesión), con --effort al arrancar, por modelo en modelSettings o con CLAUDE_CODE_EFFORT_LEVEL, que manda sobre todo. Para un solo turno, escribe ultrathink en el prompt: desde la 2.1.311 sube ese turno a xhigh. Ojo: un effortLevel antiguo en tu ~/.claude/settings.json no se aplica a Opus 5.5.
Cómo lo probamos (metodología)
1. Una sola tarea realista y verificable
Un repositorio Python de 2 archivos donde el modelo tiene que: (1) arreglar un test que falla porque round() usa redondeo bancario y el negocio pide ROUND_HALF_UP, (2) añadir aplicar_cupon() con tres reglas y (3) escribir sus tests. El prompt es idéntico para todos los modelos (TAREA.md):
Estás en un proyecto Python pequeño (carpeta src/ y tests/).
1. Ejecuta `python3 -m pytest -q` y arregla el fallo de `tests/test_precios.py` sin tocar los tests.
2. Añade a `src/precios.py` la función `aplicar_cupon(total, codigo)` con estas reglas:
- "BIENVENIDA" resta un 10 %; "ENVIO" resta 4,99 si el total es de al menos 30; cualquier otro código lanza ValueError.
- El resultado nunca baja de 0 y se redondea a 2 decimales con ROUND_HALF_UP del módulo decimal (no con round()).
3. Escribe tests para `aplicar_cupon` en `tests/test_cupon.py`.
4. Termina cuando `python3 -m pytest -q` pase entero. No instales paquetes ni uses la red.
El código de partida tiene el bug a propósito. plantilla/src/precios.py:
from decimal import Decimal
def total_con_iva(neto, iva=0.21):
return round(neto * (1 + iva), 2)
Y el test visible que falla, plantilla/tests/test_precios.py:
from src.precios import total_con_iva
def test_iva_redondeo_hacia_arriba():
# 10.125 € netos al 0 % de IVA deben quedar en 10.13 (ROUND_HALF_UP), no en 10.12
assert total_con_iva(10.125, 0) == 10.13
def test_iva_normal():
assert total_con_iva(100, 0.21) == 121.0
2. La calidad la deciden pruebas ocultas, no nuestra opinión
Al terminar, el guion copia un archivo de pruebas que el modelo no ha visto (7 casos, incluidos bordes como 29,99 € o 0,045) y cuenta cuántas pasan. ocultas/test_ocultas.py:
import pytest
from src.precios import aplicar_cupon, total_con_iva
def test_bienvenida(): assert aplicar_cupon(50, "BIENVENIDA") == 45.0
def test_envio_minimo(): assert aplicar_cupon(30, "ENVIO") == 25.01
def test_envio_por_debajo(): assert aplicar_cupon(29.99, "ENVIO") == 29.99
def test_nunca_negativo(): assert aplicar_cupon(0, "BIENVENIDA") == 0
def test_redondeo_half_up(): assert aplicar_cupon(0.05, "BIENVENIDA") == 0.05 # 0.045 -> 0.05
def test_codigo_invalido():
with pytest.raises(ValueError): aplicar_cupon(10, "FALSO")
def test_iva_sigue_bien(): assert total_con_iva(2.675, 0) == 2.68
Antes de publicar comprobamos las pruebas en sí: una solución de referencia pasa los 9 tests (2 visibles + 7 ocultos) y el código de partida falla el test visible, como se pretende. Fíjate en total_con_iva(2.675, 0): el float 2.675 es en realidad 2.67499…, así que solo pasa quien convierte con Decimal(str(x)).
3. Qué medimos y en qué condiciones
De la salida JSON de claude -p sacamos total_cost_usd, duration_ms y num_turns, y con git contamos las líneas añadidas en src/. Matriz: 3 modelos × 2 efforts (medium, high) × 3 repeticiones = 18 ejecuciones; Fable 5.1 se añade solo si se aprueba aparte (6 más).
Cada ejecución arranca en una carpeta temporal nueva, con --bare para que no carguen hooks, skills ni CLAUDE.md del PC (resultados comparables), --permission-mode dontAsk con una lista cerrada de herramientas, sin red, y con topes --max-budget-usd 2 y --max-turns 40. Las versiones quedan fijadas: Claude Code 2.1.316 e IDs claude-opus-5-5, claude-sonnet-5-5 y claude-haiku-5-5.
4. Cuánto cuesta antes de ejecutarla
Supuesto por ejecución: unos 200 K tokens de entrada procesados en total (sumando turnos) y 8 K de salida.
| Modelo | Cota alta por ejecución (sin caché) | 6 ejecuciones |
|---|---|---|
| Opus 5.5 | ≈ 0,96 USD | 5,76 USD |
| Sonnet 5.5 | ≈ 0,48 USD | 2,88 USD |
| Haiku 5.5 | ≈ 0,02 USD | 0,14 USD |
| Fable 5.1 (opcional) | ≈ 2,40 USD | 14,40 USD |
Total de cota alta: 8,8 USD sin Fable y 23,2 USD con Fable. Estimación realista, con ~85 % de la entrada leída de caché a los precios de lectura oficiales: unos 3 USD sin Fable y 7,5 USD con Fable (no incluye el recargo de escritura en caché, que no hemos verificado). El tope --max-budget-usd 2 limita el peor caso a 36 USD (18 ejecuciones) o 48 USD (24).
El plan: fase 1 de humo con 3 ejecuciones (≈ 0,5-1,5 USD) para comprobar que el guion funciona; si sale bien, fase 2 completa sin Fable; Fable, decisión aparte. Con una suscripción en vez de clave de API, --bare no sirve (no lee el inicio de sesión), las cifras de coste son estimaciones y lo que se gasta es límite del plan.
5. Repítela tú
Requisitos: Claude Code 2.1.316, git, python3 con pytest, jq y una clave ANTHROPIC_API_KEY (necesaria para --bare y para un coste exacto). medir.sh hace una ejecución y añade una línea a resultados.jsonl:
#!/usr/bin/env bash
# medir.sh — una ejecución de la prueba: ./medir.sh <modelo> <effort> <repeticion>
# Requiere: claude 2.1.316, git, python3 con pytest, jq. Modo recomendado: --bare con ANTHROPIC_API_KEY.
# Cuesta dinero: cada ejecución tiene un tope de 2 USD (--max-budget-usd 2).
set -euo pipefail
[ $# -eq 3 ] || { echo "Uso: $0 <modelo> <effort> <repeticion>" >&2; exit 2; }
modelo="$1"; effort="$2"; rep="$3"
raiz="$(cd "$(dirname "$0")" && pwd)"
dir="$(mktemp -d /tmp/prueba-modelos.XXXXXX)"
cp -r "$raiz/plantilla/." "$dir/"
cd "$dir"
git init -q && git add -A && git -c user.name=prueba -c user.email=prueba@local commit -qm base
inicio=$(date +%s)
claude --bare -p "$(cat "$raiz/TAREA.md")" \
--model "$modelo" --effort "$effort" \
--permission-mode dontAsk \
--allowedTools "Read" "Edit" "Bash(python3 -m pytest *)" \
--max-budget-usd 2 --max-turns 40 \
--no-session-persistence \
--output-format json > resultado.json || true
fin=$(date +%s)
[ -s resultado.json ] || echo '{"is_error": true}' > resultado.json # si claude no escribió nada, la fila queda marcada como error
# Calidad: pruebas ocultas que el modelo no ha visto
cp "$raiz/ocultas/test_ocultas.py" tests/
if python3 -m pytest -q tests/test_ocultas.py > ocultas.txt 2>&1; then ocultas=ok; else ocultas=fallo; fi
pasan=$(grep -Eo '[0-9]+ passed' ocultas.txt | grep -Eo '[0-9]+' || echo 0)
lineas=$(git diff --shortstat HEAD -- src | grep -Eo '[0-9]+ insertion' | grep -Eo '[0-9]+' || echo 0)
jq -c --arg m "$modelo" --arg e "$effort" --arg r "$rep" --arg o "$ocultas" \
--arg p "$pasan" --arg l "$lineas" --arg s "$((fin-inicio))" \
'{modelo:$m, effort:$e, rep:($r|tonumber), coste_usd:.total_cost_usd,
ms:.duration_ms, ms_api:.duration_api_ms, turnos:.num_turns, error:.is_error,
ocultas:$o, ocultas_pasan:($p|tonumber), lineas_src:($l|tonumber), segundos_reloj:($s|tonumber),
por_modelo:.modelUsage}' resultado.json | tee -a "$raiz/resultados.jsonl"
echo "Carpeta de la ejecución: $dir"
lote.sh lanza la fase de humo o la matriz completa y saca el resumen:
#!/usr/bin/env bash
# lote.sh — fase 1 (humo, 3 ejecuciones, ~0,5-1,5 USD): ./lote.sh humo · fase 2 (18 ejecuciones): ./lote.sh completa
# Cuesta dinero. Revisa resultados.jsonl tras la fase de humo antes de lanzar la completa.
set -euo pipefail
cd "$(dirname "$0")"
modelos="claude-haiku-5-5 claude-sonnet-5-5 claude-opus-5-5" # Fable 5.1 solo si se aprueba aparte: añadir "fable"
case "${1:-humo}" in
humo) for m in $modelos; do ./medir.sh "$m" medium 1; done ;;
completa) for rep in 1 2 3; do for e in medium high; do for m in $modelos; do ./medir.sh "$m" "$e" "$rep"; done; done; done ;;
*) echo "Uso: $0 [humo|completa]" >&2; exit 2 ;;
esac
# Resumen por modelo y effort: media de coste y segundos, mediana de pruebas ocultas superadas (de 7)
jq -s 'group_by(.modelo+"/"+.effort) | map({clave:(.[0].modelo+"/"+.[0].effort),
n:length, coste_medio:(map(.coste_usd // 0)|add/length), seg_medios:(map(.ms // 0)|add/length/1000),
ocultas_mediana:(map(.ocultas_pasan)|sort|.[length/2|floor]),
ocultas_ok:(map(select(.ocultas=="ok"))|length), turnos_medios:(map(.turnos // 0)|add/length)})' resultados.jsonl
Los pasos:
git clone https://github.com/carlosp5751258-lgtm/ctrlia-opus-sonnet-haiku
cd ctrlia-opus-sonnet-haiku
export ANTHROPIC_API_KEY=... # la tuya; no la guardes en el repositorio
./lote.sh humo # 3 ejecuciones; revisa resultados.jsonl
./lote.sh completa # solo si la fase de humo salió bien
Tabla comparativa
Precios de lista por millón de tokens, según el CHANGELOG oficial:
| Modelo | Alias (API de Anthropic) | Desde | Entrada / salida (USD) | Lectura de caché (USD) | Effort por defecto |
|---|---|---|---|---|---|
| Fable 5.1 | fable | 2.1.257 | 10 / 50 | 0,25 | sin dato |
| Opus 5.5 | opus | 2.1.280 | 4 / 20 | 0,20 | medium |
| Sonnet 5.5 | sonnet | 2.1.284 | 2 / 10 | 0,10 (bajó de 0,20) | medium |
| Haiku 5.5 | haiku | 2.1.293 | 0,10 / 0,50 (0,50 / 2,50 si el prompt pasa de 100 K tokens) | sin dato | medium |
Resultados de la prueba: pendientes. Esta es la tabla que se publicará, una fila por modelo y effort:
| Modelo / effort | Coste medio por ejecución | Segundos medios | Turnos | Pruebas ocultas (de 7, mediana de 3) | Ejecuciones con todo en verde | Líneas añadidas en src/ |
|---|---|---|---|---|---|---|
| Haiku 5.5 / medium | pendiente | pendiente | pendiente | pendiente | pendiente | pendiente |
| Haiku 5.5 / high | pendiente | pendiente | pendiente | pendiente | pendiente | pendiente |
| Sonnet 5.5 / medium | pendiente | pendiente | pendiente | pendiente | pendiente | pendiente |
| Sonnet 5.5 / high | pendiente | pendiente | pendiente | pendiente | pendiente | pendiente |
| Opus 5.5 / medium | pendiente | pendiente | pendiente | pendiente | pendiente | pendiente |
| Opus 5.5 / high | pendiente | pendiente | pendiente | pendiente | pendiente | pendiente |
Reglas para leerla sin engañarse:
- Es una tarea pequeña: no extrapoles a refactors grandes, donde la documentación atribuye ventaja a Fable.
- Mostraremos la dispersión, no solo la media.
total_cost_usdes una estimación del cliente y puede diferir de la factura.- Fecha y versión en la cabecera; repetiremos la prueba con cada modelo nuevo.
Cuándo usar cada uno
Basado en la documentación oficial (se ajustará con los datos de la prueba):
| Tarea | Modelo | Effort |
|---|---|---|
| Renombrados, explicar un archivo, tareas de mucho volumen | Haiku 5.5 | low o medium |
| Subagentes de búsqueda o resumen | Haiku 5.5 (model: haiku en el frontmatter del subagente) | low |
| Día a día con alcance claro | Sonnet 5.5 | medium |
| Bugs en código existente, decisiones de diseño, cuando Sonnet se equivoca | Opus 5.5 | medium (por defecto) o high |
| Trabajo más grande que una sesión, causa raíz, arquitectura | Fable 5.1 (describe el resultado, no los pasos) | según la tarea |
| Planificar y luego implementar | opusplan (Opus en modo plan, Sonnet al ejecutar) | medium |
Tres consejos más:
opusplanes justo lo que buscas si piensas en «plan in Opus, implement in Sonnet».- Para que los subagentes no hereden un modelo caro, fija
modelen su definición (receta de subagentes) o usaCLAUDE_CODE_SUBAGENT_EFFORT(2.1.316). - Cambiar de modelo a mitad de sesión obliga a un turno sin caché, así que decide al principio.
Los comandos, verificados en la documentación:
claude --model sonnet --effort medium # solo esta sesión
/model haiku # dentro de la sesión (Enter = guardar como predeterminado; s = solo esta sesión)
/effort high # o /effort sin argumentos para el deslizador
/model opusplan # Opus en modo plan, Sonnet al ejecutar
export CLAUDE_CODE_EFFORT_LEVEL=low # manda sobre todo lo demás
export CLAUDE_CODE_SUBAGENT_EFFORT=low # effort de los subagentes que no fijan uno (2.1.316)
/status # ver modelo actual
Y un modelo por defecto con effort por modelo en ~/.claude/settings.json:
{
"model": "sonnet",
"modelSettings": {
"claude-opus-5-5": { "effortLevel": "high" }
}
}
Si quieres una skill que corra siempre en Haiku aunque tu sesión esté en Opus, mira /explica en el pack de 5 comandos. Para saber qué pagas con cada plan, la receta de precio de Claude Code. Fuentes: configuración de modelos, modo headless, referencia de la CLI, costes, seguimiento de costes, caché de prompts y el CHANGELOG.
Preguntas frecuentes
¿Qué modelo usa Claude Code por defecto?
Con el valor default, Opus 5.5 en Pro, Max, Ultra, Team, Enterprise y la API de Anthropic (desde la 2.1.280). En Microsoft Foundry, Sonnet 4.5. Fable nunca es el predeterminado. Compruébalo con /status.
¿Opus o Sonnet para programar?
La documentación describe Sonnet para el día a día y Opus para razonamiento complejo. Sonnet 5.5 cuesta la mitad (2/10 USD por millón frente a 4/20). Empieza con Sonnet en medium y sube a Opus cuando falle en bugs de código existente o en diseño; nuestra prueba dirá cuánto cambia en una tarea concreta.
¿Cómo planifico con Opus e implemento con Sonnet?
Con /model opusplan: usa Opus en modo plan (Shift+Tab o /plan) y cambia solo a Sonnet al ejecutar. Con /model opusplan[1m] pides 1M de contexto en las dos fases donde no venga por defecto.
¿Qué effort pongo?
Deja medium (el predeterminado de los modelos 5.5) para lo normal, high para bugs con casos límite y low para cambios pequeños que revisas. max solo para problemas duros: la documentación avisa de que puede pensar de más. Para un solo turno difícil escribe ultrathink.
¿Haiku 5.5 sirve para algo serio?
Para tareas simples y para subagentes de búsqueda o resumen es la opción barata (0,10/0,50 USD por millón, 1M de contexto). Ojo: si el prompt pasa de 100 K tokens el precio sube a 0,50/2,50.
¿Por qué no aparece Fable o me pide créditos?
Según tu plan, Fable puede cobrarse con créditos de uso en vez del límite incluido; el selector lo marca con «Requires usage credits». Requiere la 2.1.257 o posterior.
¿Cambiar de modelo a mitad de sesión gasta más?
Sí: la documentación de caché explica que cambiar de modelo provoca un turno sin caché. Decide el modelo al empezar o usa opusplan, que está pensado para ese cambio.
¿Cuándo publicaréis los resultados?
Cuando se ejecute la prueba, que cuesta dinero y requiere aprobación. Hasta entonces la página solo trae la metodología y el guion para que cualquiera la repita; nunca publicaremos cifras que no salgan de resultados.jsonl.