# A Spotify Engineer Routed Claude Code's I/O to a Small Model—and Cut Tokens 90%

**The most expensive part of Claude Code may not be reasoning. Spotify engineer Dimitri Mazmanov found that a large share of tokens went to reading files, copying test patterns, and generating boilerplate. He combined AiKA Modes in Portal by Spotify with a Claude Code plugin named shunt, routing that I/O to Gemini 2.5 Flash. Across four Java monorepo scenarios, bulk reads used about 90% fewer frontier-model tokens on average.**

The result does not show that a small model can replace a frontier model. It shows that the frontier model should not personally move every byte. Hooks decide when to route, a cheaper worker compresses or generates predictable material, and Claude keeps the debugging, architecture, editing, and safety decisions.

![Official Spotify Portal product visual showing fast, no-code setup as an opening package.](https://s4.tenten.co/learning/content/images/2026/09/landing-page-1-9.png align="center")

#### Where the 90% came from

Spotify's public shunt README reports four scenarios from a 162,000-line Java monorepo. The first three cover bulk reading. The fourth covers boilerplate generation.

| Stage | Scenario | Lines | Without shunt | With shunt | Savings |
| --- | --- | --- | --- | --- | --- |
| Stage 1 | Single large file | 4,014 | 33,684 tokens | 5,737 tokens | 82% |
| Stage 2 | Source and test pair | 7,408 | 75,990 tokens | 4,148 tokens | 94% |
| Stage 3 | Multi-file cross-service | 1,281 | 16,221 tokens | 821 tokens | 94% |
| Stage 4 | Code-write | 3,667 | 40,614 tokens plus generation | 833 lines written to disk | Not directly comparable |

Mean savings across the three bulk-read cases were about 90%. This was one engineer, one codebase, and four scenarios. It is not a promise that every Claude Code workload will fall by nine-tenths. Tasks that require full context, repeated editing, or deep judgment will save less.

The source-and-test case is still striking. Passing 7,408 lines directly to Claude consumed 75,990 tokens. Passing the corpus through a worker first reduced the material Claude consumed to 4,148 tokens. The frontier model did not become more capable. The shape of its input changed.

#### Two modes separate transport from judgment

An AiKA Mode is a declarative agent in Portal. Its configuration selects instructions, a model, temperature, and MCP tools. Portal supplies an ephemeral runtime plus CLI and API access. Mazmanov created two modes, both using Gemini 2.5 Flash in the published examples.

`bulk-reader` accepts several large files and one question. It returns structured bullets only, leading each item with an exact name, type, or line number. Greetings, preambles, and unrelated observations are excluded. Claude gets compressed evidence instead of thousands of source lines.

`code-writer` handles tests, configuration scaffolding, and type stubs. It requires a reference file and must follow the repository's patterns, names, and style. A wrapper strips Markdown fences and can write the result directly to disk. Claude does not have to read the references and then spend expensive output tokens reproducing predictable code.

![Official Spotify Portal product visual showing different software assets organized inside one portal.](https://s4.tenten.co/learning/content/images/2026/09/landing-page-2-8.png align="center")

#### The three-layer router is the important part

Putting “send big files to a small model” in `CLAUDE.md` was the first attempt. It remained advisory, Claude could ignore it, and every repository needed a copy. Shunt turns routing into three distinct layers: hooks, scripts, and skills.

The first layer is a `PreToolUse` hook. `check-file-size` examines full `Read` calls. Files over 350 lines are blocked by default, with a redirect to `/bulk-reader`. Targeted reads that use `offset` or `limit` pass. `check-bash-read` catches broad reads through `cat`, `head`, `tail`, `less`, and `more`. Narrow pipelines such as `cat file | grep` pass.

The second layer is a pair of shell scripts. They build the payload, invoke the Portal CLI, unwrap errors, and report token usage. `bulk-read` uses XML tags to keep file boundaries clear. `code-write` accepts a specification, a reference file, and an optional target path.

The third layer is a pair of Markdown skills that tell Claude when to delegate and exactly how to call the scripts. The hook still enforces expensive read policy when Claude misses the skill. The skill makes the redirected path legible.

That separation matters more than the choice of Gemini. The hook owns policy, the script owns transport, and the Mode owns worker behavior. Teams can swap the worker without rewriting the enforcement layer.

#### Install and enable shunt

Shunt is available in Spotify's `portal-ai-plugins` marketplace under the Apache 2.0 license. It requires `jq` and a Portal instance with AiKA enabled.

Add the marketplace and install both plugins.

```bash
claude plugin marketplace add spotify/portal-ai-plugins
claude plugin install portal@portal
claude plugin install shunt@portal
```

Start a new Claude Code session, then configure and authenticate the Portal CLI:

```text
/portal:setup
```

Check whether the public modes are already present:

```bash
portal-cli actions aika:list-modes --json --input '{"search": "bulk-reader"}'
```

Many Portal instances already expose `bulk-reader` and `code-writer`. If yours does not, the official README includes creation payloads. Name resolution prefers a personal Mode, followed by a group Mode and then a public one. A customized personal `bulk-reader` can therefore shadow the default without changing the plugin.

#### Treat 350 lines as a starting point

The default threshold is configurable in `.claude/settings.json`:

```json
{
  "env": {
    "SHUNT_MIN_LINES": "500"
  }
}
```

The right value depends on latency, worker price, file structure, and summary quality. Every delegation adds a network round trip. The Spotify Engineering article observed 10 to 30 seconds for a typical response. The current README documents a default `SHUNT_TIMEOUT_SECONDS` of 180 seconds, correcting the social summary's claim that every call has a 30-second cap. Routing a small file can cost more time than it saves.

Payload size is another boundary. The README sets `SHUNT_MAX_PAYLOAD_BYTES` to 400,000 bytes by default on macOS and 120,000 on Linux because the request travels through argv. Shunt refuses oversized requests before they fail with `E2BIG`. Large corpora need batches.

#### Work that should stay with Claude

**Editing needs exact context.** Worker summaries do not guarantee reliable line numbers. Claude still needs targeted reads with `offset` or `limit` before making changes. Bulk reading saves the context used for broad understanding; it does not permanently hide the source.

**Debugging and architecture need judgment.** In Mazmanov's test, the worker found surface patterns but missed a subtle thread-safety bug. Claude caught it quickly once it received the right context. Shunt explicitly excludes debugging, architectural decisions, and safety-critical code.

**Code writing is not hook-enforced.** The README lists this as a known limitation. Only `bulk-reader` has hard enforcement. `code-writer` depends on Claude recognizing the skill and choosing it, so output-side savings also depend on routing compliance.

![Official Spotify Portal product visual showing plugins that can be added through the interface.](https://s4.tenten.co/learning/content/images/2026/09/landing-page-3-7.png align="center")

#### Measure decision quality before celebrating tokens

Optimizing the bill alone is dangerous. A cheap worker that drops a security condition can turn token savings into an expensive incident. Track at least four values: frontier input tokens, frontier output tokens, end-to-end latency, and human rework rate.

Start with read-only work. Pick a large file and prepare five questions whose answers you already know. Compare Claude reading the file directly with Claude answering from the bulk-reader summary. Token reduction counts only when answer quality holds.

Then test code writing on output that is predictable from an existing pattern. Let the worker create a new test or configuration file, with lint and the test suite serving as acceptance checks. If Claude has to repair much of the output, that class of work should not be delegated.

Spotify's useful contribution is larger than a 90% number. It publishes a testable boundary: cheap workers move and compress predictable material; frontier models own judgment and risk. Once context transport dominates agent cost, model choice stops being a global setting. It becomes a decision made before each tool call.

#### Frequently asked questions

##### Does this prove Gemini 2.5 Flash is better than Claude for coding?

No. The examples use Gemini 2.5 Flash for bulk summaries and predictable boilerplate. Debugging, architecture, safety-critical code, and precise editing remain with Claude.

##### Can I expect a 90% reduction in my repository?

No. The figure is the mean of three bulk-read scenarios in one 162,000-line Java monorepo. File sizes, task types, worker quality, and thresholds will change the result.

##### Why not use prompt caching instead?

Prompt caching discounts repeated use of the same context. Shunt keeps bulk source material out of the frontier context in the first place. They address different cost layers and can work together.

##### Can I put the routing rules in CLAUDE.md?

Yes, but they remain advisory. Shunt uses `PreToolUse` hooks to enforce broad-read policy consistently across repositories.

#### Sources

*   [Spotify Engineering — 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)
    
*   [GitHub — spotify/portal-ai-plugins shunt](https://github.com/spotify/portal-ai-plugins/tree/main/plugins/shunt)
    
*   [Spotify for Backstage — Portal](https://backstage.spotify.com/portal)
    
*   [Spotify for Backstage — AiKA Modes](https://backstage.spotify.com/docs/portal/core-features-and-plugins/aika/modes)
    

#### Author Insight

The portable idea is not Gemini 2.5 Flash or a 350-line threshold. It is the separation of responsibilities: hooks enforce cost policy, scripts encapsulate transport, and skills explain judgment. Models and thresholds can change without dissolving the boundary.

I would enable bulk reading first, collect shadow measurements for a week, and only then allow code writing directly to disk. Lower token use looks good on a dashboard. Less rework with no missed risk is what makes it cheaper.
