---
title: "Medí si el shunt de Spotify recorta de verdad un 90% de tokens en Claude Code"
excerpt: "Shunt es el plugin de Spotify que intercepta las lecturas grandes de Claude Code y las delega a un modelo más barato. El 90% que anuncia es real, pero se aplica solo a lo interceptado. Medí 30 días de mis propias sesiones para ver cuánto es eso."
date: "2026-09-07T11:00:00.000Z"
category: "Inteligencia Artificial"
tech_article: true
author:
  name: "angel cruz"
  picture: "/images/me/angel-cruz.png"
ogImage:
  url: "/images/open-graph/claude-opengraph-image.jpg"
seo_title: "Shunt de Spotify en Claude Code: el 90% de ahorro, medido"
seo_description: "Qué es shunt, el plugin de Spotify para Claude Code, cómo funcionan sus hooks de 350 líneas y cómo medir en tus propios transcripts cuánto ahorrarías."
---

**Shunt es un plugin de Claude Code, publicado por Spotify, que intercepta las lecturas de archivos grandes antes de que entren al contexto y las delega a un modelo trabajador más barato.** Su README declara un ahorro de entre el 82% y el 94% en esas lecturas, con una media del 90%. La cifra es real y está medida. Lo que no dice el anuncio es la otra parte de la cuenta: qué porcentaje de tu contexto son lecturas grandes de archivos. El 90% se aplica solo a eso.

En mi caso, medido sobre 30 días de transcripts reales, la respuesta es 0,366%. El plugin me ahorraría un 0,33% del mes. Así llegué a ese número, y así puedes calcular el tuyo, que puede ser diez veces mayor.

## Qué es shunt y cómo funciona

Shunt vive en el repositorio [spotify/portal-ai-plugins](https://github.com/spotify/portal-ai-plugins), con licencia Apache 2.0, escrito en TypeScript y creado el 23 de julio de 2026. Al consultar la API de GitHub el 7 de septiembre de 2026 tenía 203 estrellas y 11 forks. Es el segundo plugin del marketplace, junto al plugin `portal` del que depende.

La arquitectura son tres capas, en palabras de su propio README: los hooks bloquean, los scripts invocan al modelo trabajador y las skills le explican a Claude cuándo llamarlos. Toda la lógica de intercepción son dos scripts de bash de menos de cuarenta líneas cada uno, así que se puede auditar entera.

El primero se registra como `PreToolUse` sobre la tool `Read`:

```bash
MIN_LINES="${SHUNT_MIN_LINES:-350}"

# Allow targeted reads (offset or limit set) — Claude already knows what it needs
if [ -n "$offset" ] || [ -n "$limit" ]; then
  echo '{"decision": "allow"}'
  exit 0
fi

lines=$(wc -l < "$file_path" 2>/dev/null | tr -d ' ' || echo "0")
if [ "$lines" -le "$MIN_LINES" ]; then
  echo '{"decision": "allow"}'
  exit 0
fi
```

Si el archivo pasa de 350 líneas y la lectura no está acotada con `offset` o `limit`, el hook devuelve `block` con un motivo que redirige a la skill `bulk-reader`. El umbral se cambia con la variable de entorno `SHUNT_MIN_LINES`.

El segundo hook cubre la vía de escape obvia, que es leer el archivo con la tool `Bash`:

```bash
# Skip piped commands (cat file | grep) — those are targeted reads
echo "$command" | grep -qE '\|' && { echo '{"decision": "allow"}'; exit 0; }

# Skip redirections (cat file > out) — not a read-into-context operation
echo "$command" | grep -qE '>' && { echo '{"decision": "allow"}'; exit 0; }

if echo "$command" | grep -qE '^(cat|head|tail|less|more) '; then
```

Ese último `grep` define la superficie entera del plugin: **solo se intercepta un comando que empiece por `cat`, `head`, `tail`, `less` o `more`, y que no contenga ni una tubería ni una redirección.** Un `sed -n '1,400p' archivo`, un `grep -A20`, un `awk` o un script de Python que imprime medio archivo pasan sin que el hook los mire. Tiene sentido, porque esos comandos casi siempre son lecturas acotadas, pero cambia el cálculo de tu ahorro.

Cuando el hook bloquea, el trabajo se va a un modo de AiKA a través del registro de acciones del Portal CLI, con una llamada `aika:invoke-chat` por delegación. Hay dos modos: `bulk-reader`, que lee varios archivos y responde una pregunta en viñetas, y `code-writer`, que genera boilerplate contra un archivo de referencia. En el anuncio del blog de ingeniería de Spotify, firmado por Dimitri Mazmanov el 3 de septiembre de 2026, el modelo trabajador de los dos modos de ejemplo es Gemini 2.5 Flash, aunque el modo se resuelve del lado del servidor y el modelo depende de tu instancia de Portal.

Antes del ahorro hay un filtro más duro: shunt necesita una instancia de Spotify Portal con AiKA habilitado. Los prerequisitos del README son `jq`, el plugin `portal` y un `/portal:setup` autenticado contra tu instancia. Si no trabajas en una organización que ya tiene Portal desplegado, el plugin no se instala y el debate sobre el 90% es teórico.

## Los benchmarks de Spotify

El README publica los cuatro escenarios que midieron, contra un monorepo Java de 162.000 líneas:

| Escenario | Líneas | Sin shunt | Con shunt | Ahorro |
|---|---|---|---|---|
| Archivo grande único | 4.014 | 33.684 tokens | 5.737 tokens | 82% |
| Par fuente y test | 7.408 | 75.990 tokens | 4.148 tokens | 94% |
| Multiarchivo entre servicios | 1.281 | 16.221 tokens | 821 tokens | 94% |
| Code-write | 3.667 | 40.614 tokens más generación | 833 líneas a disco | sin dato |

La media de ahorro en `bulk-read` que declaran es del 90%. Los números son creíbles y la metodología está en el repositorio: `bash evals/run.sh --benchmark` los vuelve a medir contra los modos reales.

La columna "Líneas" es la que importa. El escenario más favorable son 7.408 líneas en dos archivos, justo la lectura que shunt existe para evitar y justo la que un monorepo Java de 162.000 líneas produce todo el tiempo. Si tu trabajo no se parece a eso, el ahorro tampoco.

## Cómo medir tu propio perfil

Claude Code guarda cada sesión como JSONL en `~/.claude/projects/`. Cada bloque `tool_use` de un mensaje del asistente tiene su `tool_result` correspondiente en el mensaje de usuario siguiente, emparejados por `tool_use_id`. Sumando caracteres por nombre de herramienta sale el reparto real de tu contexto.

La forma más rápida de sacar ese reparto es pedírselo a Claude Code, que ya tiene permiso de lectura sobre tus propios transcripts. Este es el prompt que usé, tomado del análisis de ai.rundatarun.io que cito más abajo:

```bash
claude "Measure where my Claude Code context actually goes.
Walk every transcript under ~/.claude/projects/*/*.jsonl modified in the last 30 days.
Pair each tool_use block in assistant messages with its tool_result in the following user message by tool_use_id.
Sum result characters by tool name and report each tool as a share of all message content.
For Read results, record line count and character count, then report what fraction of calls and what
fraction of bytes come from results of 350 lines or more. Do the same for Bash results whose command
starts with cat, head, tail, less or more, and separately for all Bash results.
Print one table: tool, calls, chars, share of context, and a second: thresholds of 50, 100 and 350 lines
against calls and bytes for Read and for Bash. Estimate tokens at 4 characters per token and label it an estimate."
```

> Va en inglés a propósito: es el original, y las instrucciones técnicas con nombres de campo literales como `tool_use_id` sobreviven mejor sin traducir. No sale nada de tu máquina, porque el propio Claude lee los archivos locales y hace las cuentas ahí.

Los tokens salen a cuatro caracteres por token. Es una estimación, no tu factura: el tokenizador real agrupa distinto, y el código y el JSON tienden a gastar más tokens por carácter que la prosa. Para comparar herramientas entre sí sirve, porque el sesgo se aplica parecido a todas.

Dos decisiones de conteo cambian bastante el resultado, así que las digo: cuento el resultado completo de cada herramienta, incluidas las imágenes en base64 que devuelven las tools del navegador, y mido la parte de contexto sobre todo el contenido de mensajes, no solo sobre los resultados de herramientas. Si tu medición cuenta solo texto, o solo `tool_result`, los porcentajes te van a salir más altos que los míos.

## Mis 30 días

Sobre 77 transcripts y 131.964.208 caracteres de contenido de mensajes, unos 33 millones de tokens estimados, el reparto sale así:

| Herramienta | Llamadas | Caracteres | Porcentaje del contexto |
|---|---:|---:|---:|
| `claude-in-chrome__computer` | 548 | 41.268.505 | 31,27% |
| `claude-in-chrome__browser_batch` | 170 | 27.147.578 | 20,57% |
| `Bash` | 15.419 | 19.564.983 | 14,83% |
| `Read` | 345 | 3.844.410 | 2,91% |
| `WebFetch` | 317 | 766.126 | 0,58% |
| `WebSearch` | 100 | 285.261 | 0,22% |
| `Edit` | 1.136 | 208.867 | 0,16% |

Los resultados de herramientas son el 72,2% de todo el contenido de mensajes. Y el 52% de mi contexto son capturas de pantalla del navegador: la tool `computer` y el `browser_batch` de la extensión de Chrome devuelven imágenes en base64 dentro del resultado, a razón de unos 95.000 caracteres por llamada. Ahí no hay nada que interceptar con un umbral de líneas.

`Read` es el 2,91%. Y dentro de ese 2,91%, las lecturas de 350 líneas o más son el 2,9% de las llamadas y el 6,0% de los bytes. Los umbrales completos:

| Corpus | Mediana | ≥50 líneas | ≥100 líneas | ≥350 líneas |
|---|---|---|---|---|
| `Read` (345 calls, 3,84M chars) | 45 líneas | 47,0% calls / 30,2% bytes | 25,2% / 23,4% | 2,9% / 6,0% |
| `Bash` todo (15.419 calls, 19,56M) | 10 líneas | 14,3% / 54,3% | 5,1% / 31,5% | 0,3% / 4,4% |
| `Bash` cat y familia (784 calls, 1,91M) | 14 líneas | 28,7% / 81,2% | 17,5% / 65,6% | 1,7% / 13,3% |

La cuenta final, aplicando exactamente los dos hooks del plugin: las lecturas interceptables son el 0,174% de mi mes por la vía de `Read` y el 0,193% por la vía de `cat` y compañía. **Total interceptable: 0,366%. Ahorro al 90%: 0,330%.** Antes de restar las llamadas al modelo trabajador y la latencia, que el anuncio de Spotify sitúa entre 10 y 30 segundos por respuesta.

Incluso si el plugin interceptara cualquier resultado de `Bash` de 350 líneas o más, no solo los cinco comandos de lectura, la superficie total subiría al 0,83% del mes y el ahorro al 0,75%.

Otro perfil da un número muy distinto. En un análisis con la misma metodología publicado en [ai.rundatarun.io](https://ai.rundatarun.io/ai-development-agents/i-checked-the-90-percent-token-cut-on-my-own-30-days), sobre 574 sesiones y 174,1 millones de caracteres, `Bash` sale al 28,5% y `Read` al 14,3%, con una superficie interceptable del 3,48% y un ahorro estimado del 3,1%. Diez veces mi cifra, con la misma herramienta y el mismo umbral. La diferencia no está en el plugin: está en el perfil de uso.

## Por qué mi Read es tan pequeño

En mis sesiones, `Bash` supera a `Read` por 45 a 1 en número de llamadas. Eso no es normal en una instalación por defecto y tiene una causa concreta: trabajo con instrucciones que empujan a resolver la lectura de archivos con `sed -n`, `grep` y `head` acotados en vez de con la tool `Read`. Cada llamada devuelve una mediana de 506 caracteres, unas 10 líneas.

El efecto secundario es que las lecturas grandes que shunt intercepta, en mi caso ya no existen: se convirtieron en cientos de lecturas pequeñas y dirigidas. Y las que sobreviven pasan por comandos que el hook no mira, porque llevan tubería o no empiezan por `cat`.

Hay dos formas de no gastar tokens en lecturas grandes. Una es delegarlas a un modelo barato. La otra es no hacerlas. La segunda es gratis y no añade 30 segundos de latencia, aunque cuesta más disciplina en el prompt.

## Dónde está mi gasto real

El corte útil en mi perfil no está en 350 líneas, está en 50. El 14,3% de las llamadas a `Bash` que devuelven 50 líneas o más aportan el 54,3% de todos los bytes de `Bash`. En la familia `cat`, ese 28,7% de llamadas aporta el 81,2% de los bytes. Ahí sí se nota pasar la salida por `head -50`, contar con `wc -l` antes de imprimir, o filtrar con `grep` en lugar de volcar el archivo.

Y por encima de todo eso, las capturas de pantalla. Cada llamada a la tool `computer` cuesta el equivalente a diez lecturas largas de archivo. Sustituir capturas por `get_page_text`, `find` o `read_console_messages`, que en mi mes juntas no llegan al 0,1% del contexto, recortaría más que cualquier plugin de intercepción de lecturas. Si te interesa el resto del inventario, lo tengo desglosado en [cómo ahorrar tokens en Claude Code](/post/optimizar-claude-code-reducir-tokens).

## Cuándo sí instalar shunt

El plugin está bien construido: 51 evals en el repositorio, los hooks fallan hacia `allow` en todos los casos dudosos, hay un tope de payload configurable porque la entrada viaja por `argv` y el README declara explícitamente qué no se delega. El problema no es la calidad, es que la superficie donde aplica es muy estrecha.

Instálalo si se cumplen las tres condiciones:

1. **Tienes acceso a una instancia de Spotify Portal con AiKA.** Sin eso no hay nada que instalar.
2. **`Read` es una fracción grande de tu contexto**, del orden del 40%, con medianas en cientos de líneas. Un monorepo Java, un proyecto Android, cualquier base de código con archivos de miles de líneas.
3. **Tu trabajo dominante es análisis y resumen, no edición ni depuración.** El propio anuncio de Spotify cuenta que el modelo trabajador encontró los patrones superficiales pero se le pasó un bug sutil de concurrencia. Para editar, Claude necesita el contenido exacto en contexto.

Si `Read` te sale por debajo del 10%, como a mí, corre el prompt antes de instalar nada. La cifra del 90% es cierta y sigue siendo irrelevante para tu factura.

## Preguntas frecuentes

### ¿Qué es el plugin shunt de Spotify?

Un plugin de Claude Code, distribuido en el marketplace `spotify/portal-ai-plugins` bajo Apache 2.0, que usa hooks `PreToolUse` para bloquear las lecturas de archivos de más de 350 líneas y redirigirlas a un modelo trabajador más barato a través del Portal CLI de Spotify.

### ¿De verdad ahorra un 90% de tokens?

Sí, en las lecturas que intercepta. El README publica un rango del 82% al 94% sobre cuatro escenarios contra un monorepo Java de 162.000 líneas. Lo que no dice, porque depende de ti, es qué parte de tu contexto son esas lecturas. En mis 30 días fue el 0,366%.

### ¿Se puede usar shunt sin Spotify Portal?

No. La delegación va por el registro de acciones del Portal CLI con una llamada `aika:invoke-chat`, y los prerequisitos incluyen un `/portal:setup` autenticado contra una instancia con AiKA habilitado.

### ¿Cómo sé cuánto contexto consume cada herramienta en Claude Code?

Parseando los JSONL de `~/.claude/projects/`: emparejas cada `tool_use` con su `tool_result` por `tool_use_id` y sumas caracteres por nombre de herramienta. El prompt de este artículo se lo pide a Claude directamente. Para la sesión en curso, `/context` y `/usage` dan la foto rápida.

### ¿Qué modelo usa el trabajador?

En los dos modos de ejemplo del anuncio de Spotify, Gemini 2.5 Flash. Los modos se resuelven del lado del servidor, así que el modelo real lo decide la instancia de Portal contra la que invoques.

### ¿Cómo cambio el umbral de 350 líneas?

Con la variable de entorno `SHUNT_MIN_LINES` en el bloque `env` de tu `.claude/settings.json`. Bajarlo mete más lecturas en la delegación, a costa de pagar los 10 a 30 segundos de latencia en lecturas cada vez más pequeñas, que es justo el punto donde el propio README dice que la delegación deja de compensar.

## Fuentes

- [spotify/portal-ai-plugins](https://github.com/spotify/portal-ai-plugins), repositorio del marketplace. Licencia, lenguaje y fecha de creación consultados en la API de GitHub el 7 de septiembre de 2026.
- [README de shunt](https://github.com/spotify/portal-ai-plugins/blob/main/plugins/shunt/README.md), de donde salen los benchmarks, las variables de configuración y las limitaciones declaradas.
- Código de los hooks: [`check-file-size`](https://github.com/spotify/portal-ai-plugins/blob/main/plugins/shunt/hooks/check-file-size) y [`check-bash-read`](https://github.com/spotify/portal-ai-plugins/blob/main/plugins/shunt/hooks/check-bash-read).
- [Portal by Spotify cut my Claude Code token usage by 90%](https://engineering.atspotify.com/2026/9/portal-by-spotify-cut-my-claude-code-token-usage-by-90), Dimitri Mazmanov, Spotify Engineering, 3 de septiembre de 2026. Las traducciones de las citas son mías.
- [I checked the 90 percent token cut on my own 30 days](https://ai.rundatarun.io/ai-development-agents/i-checked-the-90-percent-token-cut-on-my-own-30-days), de donde tomo el prompt de medición y las cifras del perfil de uso comparado.

---

## Sitemap

Índice completo del sitio: [/sitemap.md](https://www.angelcruz.dev/sitemap.md)

Canónico HTML: [https://www.angelcruz.dev/post/medir-contexto-claude-code-shunt-spotify](https://www.angelcruz.dev/post/medir-contexto-claude-code-shunt-spotify)
