{"slug": "spotify-portal-shunt-cut-claude-code-tokens-90-via-bulk-reader-code-writer-aika", "title": "Spotify Portal shunt: cut Claude Code tokens 90% via bulk-reader + code-writer AiKA modes (extracted from tweet + Spotify Engineering)", "summary": "Spotify Engineering cut Claude Code token usage by roughly 90% on a Java monorepo by routing bulk file reading and boilerplate code generation to a cheap model such as Gemini 2.5 Flash while keeping reasoning on frontier models like Claude Opus and Sonnet. The setup, built on Spotify's Portal AiKA Modes, relies on a blocking PreToolUse hook that hard-blocks reads over 350 lines rather than relying on written routing instructions, which the team found were ignored. Spotify's takeaway: \"Written rules are a suggestion. A block is not.", "body_md": "Original: [Spotify's Claude Code setup (@undefinedKi tweet)](https://x.com/undefinedKi/status/2095942506433089832?s=20) + [Spotify Engineering, Sep 3 2026](https://engineering.atspotify.com/2026/9/portal-by-spotify-cut-my-claude-code-token-usage-by-90). Generalized below for GitHub Copilot, Kiro, and Codex (OpenAI Codex CLI).\n\n**Route grunt I/O to cheap model, keep reasoning on frontier, enforce with a hard block (>350 lines), not prompt instructions.**\n\nSpotify: `Claude Opus/Sonnet` + `Gemini 2.5 Flash` via Portal AiKA Modes → **~90% token savings** on Java monorepo. Same pattern works anywhere if you add 3 layers: **1) Blocking interceptor 2) Cheap-worker scripts/MCP 3) Redirect instructions.**\n\nUse *any* cheap/fast model: `gemini-2.5-flash` / `claude-haiku` / `gpt-4o-mini` / `gpt-4.1-nano` / `ollama/qwen2.5-coder`. Temp `0.2`.\n\n**1. `bulk-reader`** — reads N files, returns bullets. Frontier never sees full files.\n\n```\nYou are a precise code analyst. Read the provided files and answer the question concisely.\nOutput structured bullets only. No greetings, no prose. Lead every bullet with exact name/type/line.\nUse nested bullets for details. Skip anything not asked.\n```\n\n**2. `code-writer`** — generates boilerplate from spec + reference, writes to disk.\n\n```\nYou generate code files based on a spec and reference files. Match existing patterns, conventions, naming, style exactly.\nOutput only the code — no explanations, no markdown fences unless asked.\nIf ambiguous, choose what matches reference.\n```\n\nSpotify's Portal AiKA Modes implement these as `name: bulk-reader` / `code-writer` with `model: gemini-2.5-flash`. You can replace with a direct API call — see self-hosted script below.\n\n**Invocation contract (tool-agnostic):**\n\n```\nbulk-read --question \"What does this service do?\" --paths src/A.java src/B.java\ncode-write --spec \"Write tests for UserService\" --reference tests/OrderTest.java --target tests/UserTest.java\n# bulk-read wraps files in XML tags for boundaries; code-write strips fences and can write to --target\n```\n\n| Layer | Purpose | Claude Code (Spotify) | Generalized | \n|---|---|---|---|\n| **1. Hook / Enforcement** | Hard block, not suggestion | `PreToolUse` hooks:`check-file-size` (>`SHUNT_MIN_LINES=350` ) +`check-bash-read` (cat/head/tail) | See per-tool below | \n| **2. Scripts / MCP** | Call cheap model, handle XML/fences, report tokens | `bulk-read` /`code-write` bash wrappers over`portal` CLI | Same scripts, but call `curl` to cheap model OR Portal CLI OR MCP server | \n| **3. Skills / Instructions** | Tell agent when/how to redirect | `/bulk-reader` skill (md) + block message | `copilot-instructions.md` /`.kiro/steering/` /`AGENTS.md` — but**always paired with Layer 1** | \n\nLesson from Spotify: *\"Written rules are a suggestion. A block is not.\"* `CLAUDE.md` routing was ignored until they added blocking hooks.\n\n1. **Editing** — summaries lack reliable line numbers → keep targeted`read(offset,limit)` on frontier.\n2. **Reasoning/debugging/architecture/thread-safety** — cheap model missed subtle bug frontier caught in seconds.\n3. **Small files** — delegation overhead 10–30s + 30s cap; threshold exists for this reason.\n\nReplace Portal with 20 lines of bash. Works for *all* tools:\n\n``` bash\n#!/usr/bin/env bash\n# bulk-read — generic version, swap MODEL/endpoint as needed\nset -euo pipefail\nQUESTION=\"$1\"; shift\nFILES=(\"$@\")\n# Build XML payload\nPAYLOAD=\"\"\nfor f in \"${FILES[@]}\"; do\n  PAYLOAD+=\"<file path=\\\"$f\\\">$(cat \"$f\")</file>\\n\"\ndone\n# Call cheap model (example: OpenAI-compatible / Gemini / Anthropic)\ncurl -s https://api.openai.com/v1/chat/completions \\\n  -H \"Authorization: Bearer $CHEAP_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d @- <<EOF | jq -r '.choices[0].message.content'\n{\n  \"model\": \"gpt-4o-mini\",\n  \"temperature\": 0.2,\n  \"messages\": [\n    {\"role\":\"system\",\"content\":\"You are a precise code analyst. Output structured bullets only. No prose. Lead every bullet with exact name/type/line.\"},\n    {\"role\":\"user\",\"content\":\"Question: $QUESTION\\n\\nFiles:\\n$PAYLOAD\"}\n  ]\n}\nEOF\n```\n\nExpose same as MCP tool `bulk_read(question, paths)` and `code_write(spec, reference, target)` — then every agent can call it.\n\nCopilot has **no `PreToolUse` hooks**, so enforcement must be via MCP + custom tool descriptions.\n\n**Option A — MCP Router (recommended):**\n\n```\n// .vscode/mcp.json\n{\n  \"servers\": {\n    \"cheap-worker\": {\n      \"command\": \"node\",\n      \"args\": [\"./mcp-cheap-worker/index.js\"],\n      \"env\": { \"CHEAP_MODEL\": \"gpt-4o-mini\" }\n    }\n  }\n}\n```\n\n- MCP exposes `bulk_read` (reads files*server-side* , returns summary) and`code_write` (writes file, returns path only).\n- In `.github/copilot-instructions.md` :\n\n```\n## Routing (MANDATORY)\n- NEVER read files >350 lines directly. Call `bulk_read` instead.\n- For boilerplate/tests from a reference, call `code_write` — do not generate in context.\n- Targeted reads with offset/limit are allowed for edits.\n```\n\n- **Hard block:** MCP`bulk_read` is the*only* tool that has file access; revoke Copilot's`readFile` for large files via extension`copilot-tool-filter` or workspace`settings.json` :\n\n```\n{ \"github.copilot.chat.toolRestrictions\": { \"readFile\": { \"maxLines\": 350 } } }\n```\n\n(Copilot CLI `gh copilot` similarly: use `GH_COPILOT_TOOL_POLICY` to deny large reads)\n\n**Option B — Custom Chat Mode:**\nCreate `.github/chatmodes/research.mode.md` that *only* has `bulk_read` tool enabled, and `.github/chatmodes/build.mode.md` for code-write. Encourage `/research What does X do?` → auto-routes.\n\nKiro **has hooks** — closest 1:1 mapping to Claude.\n\n```\n// .kiro/hooks/bulk-reader.json\n{\n  \"preToolUse\": [\n    {\n      \"tool\": \"fs_read\",\n      \"check\": \"file.lines > 350 && !args.offset\",\n      \"block\": true,\n      \"message\": \"File >350 lines: use `bulk-read --question <q> --paths <files>` (cheap worker). For edits use offset/limit.\"\n    },\n    {\n      \"tool\": \"bash\",\n      \"match\": \"^(cat|head|tail|less|more)\\\\s+\",\n      \"blockIf\": \"targetFile.lines > 350\"\n    }\n  ]\n}\n```\n\n- Add steering: `.kiro/steering/routing.md` with same mandatory routing text + examples.\n- Scripts identical: Kiro executes `bulk-read` bash script which can call Portal CLI*or* direct API. Kiro's ephemeral runtime similar to AiKA.\n- Threshold configurable via `KIRO_SHUNT_MIN_LINES=500` env.\n\nCodex uses `AGENTS.md` + `config.toml` + MCP.\n\n```\n# ~/.codex/config.toml or .codex/config.toml\n[mcp_servers.cheap-worker]\ncommand = \"node\"\nargs = [\"./mcp-cheap-worker/index.js\"]\n\n[tools]\n# Deny direct large reads — force MCP\ndeny = [\"read_file({\\\"lines\\\" > 350})\"]\nphp\n<!-- AGENTS.md -->\n## Model Routing (ENFORCED)\n- Files >350 lines MUST use `bulk_read` MCP tool, not `read_file`.\n- Boilerplate/tests MUST use `code_write` with a reference file.\n- Direct generation without reference is forbidden.\n```\n\n- Codex respects tool `description` strongly — make`bulk_read` description:`MANDATORY for files >350 lines. Reads files server-side and returns concise bullets. Use instead of read_file.`\n- CLI wrapper fallback: `codex --mcp cheap-worker` + shell alias`read = bulk-read` for`cat` .\n\n| Scenario | Frontier | Cheap Worker | Method | \n|---|---|---|---|\n| Q&A across 5 files | sees summary (200 tokens) | reads full files | `bulk-read` | \n| Generate test copying 20 examples | never sees output | reads 1 reference + writes | `code-write --target` | \n| Edit/fix bug | targeted `read(offset,limit)` | not used | direct | \n| Debug/architecture/thread-safety | full context | not used | direct | \n\n- Start `350` lines (~10k tokens). Measure: if`p50 delegation latency > time saved` , raise to`500` . Spotify uses`SHUNT_MIN_LINES` env.\n- Temperature `0.2` for both workers;`0.0` for code-writer if you want deterministic scaffolding.\n- Always require `--reference` for code-write — without it, cheap model hallucinates patterns.\n\n```\n# Spotify (Portal) — original\nclaude plugin marketplace add spotify/portal-ai-plugins\nclaude plugin install portal@portal && claude plugin install shunt@portal\n/portal:setup\n\n# Generic (no Portal) — add MCP server once, works for all three\ngit clone https://github.com/your-org/mcp-cheap-worker\nnpm i && cheap-worker --setup  # sets CHEAP_API_KEY, model\n# then in Copilot/Kiro/Codex: call bulk_read / code_write — enforcement handles rest\n```\n\n- Tweet: [https://x.com/undefinedKi/status/2095942506433089832](https://x.com/undefinedKi/status/2095942506433089832)\n- Spotify article: [https://engineering.atspotify.com/2026/9/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)\n- Plugin: [https://github.com/sorantis/portal-ai-plugins/tree/add-shunt-claude/plugins/shunt](https://github.com/sorantis/portal-ai-plugins/tree/add-shunt-claude/plugins/shunt)\n- AiKA Modes: [https://backstage.spotify.com/docs/portal/core-features-and-plugins/aika/modes](https://backstage.spotify.com/docs/portal/core-features-and-plugins/aika/modes)\n\n*Generalized 2026-09-06 from Spotify's Claude-specific implementation. Principle is portable: cheap model + hard block + XML-wrapped delegation.*", "url": "https://wpnews.pro/news/spotify-portal-shunt-cut-claude-code-tokens-90-via-bulk-reader-code-writer-aika", "canonical_source": "https://gist.github.com/vtri950/84b2261efbadba243870bf161764aeb7", "published_at": "2026-09-06 16:26:53+00:00", "updated_at": "2026-09-19 02:53:59.896343+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-infrastructure", "mlops"], "entities": ["Spotify", "Claude Code", "Anthropic", "Gemini 2.5 Flash", "Google", "GitHub Copilot", "OpenAI Codex", "Kiro"], "alternates": {"html": "https://wpnews.pro/news/spotify-portal-shunt-cut-claude-code-tokens-90-via-bulk-reader-code-writer-aika", "markdown": "https://wpnews.pro/news/spotify-portal-shunt-cut-claude-code-tokens-90-via-bulk-reader-code-writer-aika.md", "text": "https://wpnews.pro/news/spotify-portal-shunt-cut-claude-code-tokens-90-via-bulk-reader-code-writer-aika.txt", "jsonld": "https://wpnews.pro/news/spotify-portal-shunt-cut-claude-code-tokens-90-via-bulk-reader-code-writer-aika.jsonld"}}