Skip to main content

Command Palette

Search for a command to run...

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

Updated
8 min readView as Markdown
A Spotify Engineer Routed Claude Code's I/O to a Small Model—and Cut Tokens 90%
E

Crafting seamless user experiences with a passion for headless CMS, Vercel deployments, and Cloudflare optimization. I'm a Full Stack Developer with expertise in building modern web applications that are blazing fast, secure, and scalable. Let's connect and discuss how I can help you elevate your next project!

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.

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.

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.

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:

/portal:setup

Check whether the public modes are already present:

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:

{
  "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.

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

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.