<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged claudecode</title>
<link>https://coderlegion.com/tag/claudecode</link>
<description>Powered by Question2Answer</description>
<item>
<title>Claude Code For Free Unlimited: Local Setup with Ollama + Qwen 3.8</title>
<link>https://coderlegion.com/32951/claude-code-for-free-unlimited-local-setup-with-ollama-qwen-3-8</link>
<description>&lt;p&gt;Run Claude Code for FREE Unlimited on your own PC: no API key, no subscription, no bill. In this 5-minute setup, I connect Claude Code to Qwen 3.8 running locally with Ollama, all with ONE command, then build a full game to prove it works.&lt;/p&gt;
&lt;p&gt;⚡ What you'll learn&lt;/p&gt;
&lt;p&gt;✅ How To Install Claude Code and Ollama (Windows, Mac &amp;amp; Linux)&lt;br&gt;
✅ How to Use QWEN 3.8 with Ollama?&lt;br&gt;
✅ How to fix Model Not Found Claude Code Error&lt;br&gt;
✅ How to build a full project with Claude Code Free&lt;br&gt;
✅ Claude Code Settings for Windows&lt;/p&gt;
&lt;p&gt;⏱️ Chapters&lt;br&gt;
0:00 Claude Code for free?&lt;br&gt;
0:39 System Requirement for Running Claude Code Free&lt;br&gt;
1:50 The 4-step plan &lt;br&gt;
2:10 Install Claude Code &amp;amp; Ollama&lt;br&gt;
3:20 The magic command&lt;br&gt;
4:00 Live build: one prompt, full snake game&lt;br&gt;
7:45 Quick fixes + next video&lt;/p&gt;
&lt;p&gt;💻 Commands used&lt;br&gt;
Install Claude Code (Mac / Linux / WSL):&lt;br&gt;
curl -fsSL &lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/install.sh&quot;&gt;https://claude.ai/install.sh&lt;/a&gt; | bash&lt;/p&gt;
&lt;p&gt;Install Claude Code (Windows PowerShell):&lt;br&gt;
irm &lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/install.ps1&quot;&gt;https://claude.ai/install.ps1&lt;/a&gt; | iex&lt;/p&gt;
&lt;p&gt;Install Ollama (Mac / Linux):&lt;br&gt;
curl -fsSL &lt;a rel=&quot;nofollow&quot; href=&quot;https://ollama.com/install.sh&quot;&gt;https://ollama.com/install.sh&lt;/a&gt; | sh&lt;br&gt;
Windows: download the installer from &lt;a rel=&quot;nofollow&quot; href=&quot;https://ollama.com&quot;&gt;https://ollama.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Check Ollama version (needs 0.15+):&lt;br&gt;
ollama --version&lt;/p&gt;
&lt;p&gt;Download the model (about 18 GB):&lt;br&gt;
ollama pull qwen3.8:27b&lt;/p&gt;
&lt;p&gt;🖥️ Recommended specs&lt;br&gt;
• 32 GB total memory (RAM + GPU)&lt;br&gt;
• 24 GB GPU for a smooth experience (or Apple Silicon Mac, 32 GB+)&lt;br&gt;
• 20 GB free disk space&lt;/p&gt;
&lt;p&gt;🔗 Links&lt;/p&gt;
&lt;p&gt;🔗 Full walkthrough: &lt;a rel=&quot;nofollow&quot; href=&quot;https://thecodestreet.dev/post/claude-code-for-free-ollama-qwen&quot;&gt;https://thecodestreet.dev/post/claude-code-for-free-ollama-qwen&lt;/a&gt;&lt;br&gt;
🔗 Ollama: &lt;a rel=&quot;nofollow&quot; href=&quot;https://ollama.com&quot;&gt;https://ollama.com&lt;/a&gt;&lt;br&gt;
🔗 Claude Code docs: &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs&quot;&gt;https://code.claude.com/docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;📺 Next video: Claude Code FREE inside VS Code. Subscribe so you don't miss it!&lt;/p&gt;
&lt;p&gt;👋 I'm Rajiv from The Code Street. I make practical videos on AI coding tools and building real apps.&lt;/p&gt;
&lt;p&gt;Subscribe: &lt;a rel=&quot;nofollow&quot; href=&quot;https://youtube.com/@thecodestreet&quot;&gt;https://youtube.com/@thecodestreet&lt;/a&gt;&lt;/p&gt;
</description>
<category>Videos</category>
<guid isPermaLink="true">https://coderlegion.com/32951/claude-code-for-free-unlimited-local-setup-with-ollama-qwen-3-8</guid>
<pubDate>Thu, 29 Oct 2026 09:15:58 +0000</pubDate>
</item>
<item>
<title>Claude Code Design Canvas: Every Screen of Your App From One Prompt</title>
<link>https://coderlegion.com/32506/claude-code-design-canvas-every-screen-of-your-app-from-one-prompt</link>
<description>&lt;p&gt;Claude Code can turn one plain-language request into a design canvas where every screen of your app is a live, editable artboard, not a screenshot. In this video I show what the canvas is, what happens after you hit Enter, how to ask for it in an existing repo and in a project that doesn't exist yet, and five tips that turn a generic result into a useful first draft, including a full prompt you can copy.&lt;/p&gt;
&lt;p&gt;📝 Full article: &lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/soaresdiogo/from-one-p&quot;&gt;https://dev.to/soaresdiogo/from-one-p&lt;/a&gt;...&lt;br&gt;
📸 Instagram:   / diogosoares.dev&lt;br&gt;
💼 LinkedIn:   / diogoschmidtsoares&lt;br&gt;
🌐 Website: &lt;a rel=&quot;nofollow&quot; href=&quot;https://diogosoares.dev&quot;&gt;https://diogosoares.dev&lt;/a&gt;&lt;/p&gt;
</description>
<category>Videos</category>
<guid isPermaLink="true">https://coderlegion.com/32506/claude-code-design-canvas-every-screen-of-your-app-from-one-prompt</guid>
<pubDate>Mon, 26 Oct 2026 12:01:37 +0000</pubDate>
</item>
<item>
<title>How to Use Claude Code with Opus 5.5 &amp; Fable 5.1 for Free (No Card Required)</title>
<link>https://coderlegion.com/32497/how-to-use-claude-code-with-opus-5-5-fable-5-1-for-free-no-card-required</link>
<description>&lt;p&gt;Want to use &lt;strong&gt;Claude Code&lt;/strong&gt; with top models like &lt;strong&gt;Claude Opus 5.5&lt;/strong&gt; and &lt;strong&gt;Fable 5.1&lt;/strong&gt;, but don't want to pay for a subscription or fund an API account yet?&lt;/p&gt;
&lt;p&gt;In this guide, I'll show you how to connect Claude Code to a third-party AI gateway that gives you &lt;strong&gt;500,000 free tokens every month&lt;/strong&gt;, with &lt;strong&gt;no credit card required&lt;/strong&gt;. The setup takes about five minutes.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;⚠️ &lt;strong&gt;Before you start:&lt;/strong&gt; This uses a third-party service that is &lt;strong&gt;not affiliated with or endorsed by Anthropic&lt;/strong&gt;. Free plan limits, available models, and pricing can change at any time. Read the disclaimer at the end before you use it for anything serious.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;-watch-the-video-tutorial&quot;&gt;🎥 Watch the Video Tutorial&lt;/h3&gt;
&lt;p&gt;Prefer watching? Here's the full step-by-step walkthrough:&lt;/p&gt;
&lt;p&gt;{% youtube W5clGOuOySI %}&lt;/p&gt;
&lt;h3 id=&quot;what-you-get&quot;&gt;What You Get&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Feature &lt;/th&gt;&lt;th&gt;Details&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Free tokens &lt;/td&gt;&lt;td&gt;500,000 per month&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Credit card &lt;/td&gt;&lt;td&gt;Not required&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Models &lt;/td&gt;&lt;td&gt;Claude Opus 5.5, Fable 5.1, and more&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Works with &lt;/td&gt;&lt;td&gt;Claude Code (via third-party inference)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Best for &lt;/td&gt;&lt;td&gt;Learning, side projects, prototyping&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;how-much-is-500k-tokens-&quot;&gt;How much is 500K tokens?&lt;/h4&gt;
&lt;p&gt;A &lt;strong&gt;token&lt;/strong&gt; is a small chunk of text, often part of a word. A common rule of thumb for English:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1 token ≈ 4 characters ≈ ¾ of a word&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1,000 tokens ≈ 750 words&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;500,000 tokens ≈ 375,000 words&lt;/strong&gt;&lt;br&gt;
Input &lt;em&gt;and&lt;/em&gt; output both count. Coding sessions also send file contents and conversation history as context, so a long agentic session uses more than you might expect. Still, 500K a month is plenty for learning and for several small projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;why-use-claude-code-with-free-tokens-&quot;&gt;Why Use Claude Code with Free Tokens?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Students and beginners&lt;/strong&gt; can learn AI-assisted coding at zero cost.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Indie developers&lt;/strong&gt; can prototype ideas without upfront spend.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Curious developers&lt;/strong&gt; can try premium models like Opus 5.5 before committing to a paid plan.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Content creators and educators&lt;/strong&gt; can demo Claude Code without burning a personal budget.&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Videos</category>
<guid isPermaLink="true">https://coderlegion.com/32497/how-to-use-claude-code-with-opus-5-5-fable-5-1-for-free-no-card-required</guid>
<pubDate>Mon, 26 Oct 2026 10:35:51 +0000</pubDate>
</item>
<item>
<title>Claude Code &amp; Cursor: Why Your AI Agent Lies to You (And Our 3-Tier Adversarial Tribunal Skill)</title>
<link>https://coderlegion.com/31433/claude-code-cursor-why-your-ai-agent-lies-to-you-and-our-3-tier-adversarial-tribunal-skill</link>
<description>&lt;p&gt;Last Tuesday at 2:14 AM, my autonomous coding agent proudly handed me a Python webhook ingestion worker and gave itself a &lt;strong&gt;98/100 confidence score&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&quot;Production-ready, fully idempotent, and resilient to network partitions,&quot;&lt;/em&gt; it assured me.&lt;/p&gt;
&lt;p&gt;Ten minutes later, under a simulated 50x concurrency spike, that same worker deadlocked two Redis streams, silently dropped 14% of the batch during a mid-transaction timeout, and swallowed the exception because it had wrapped the entire handler in a broad fallback block.&lt;/p&gt;
&lt;p&gt;If you build with AI coding agents (&lt;strong&gt;Hermes Agent&lt;/strong&gt;, &lt;strong&gt;Claude Code&lt;/strong&gt;, &lt;strong&gt;Cursor&lt;/strong&gt;, &lt;strong&gt;OpenCode&lt;/strong&gt;), you already know this pain. The problem isn't that frontier LLMs lack engineering knowledge. The problem is &lt;strong&gt;First-Draft Sycophancy&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here is why asking an AI to &lt;em&gt;&quot;review its own code&quot;&lt;/em&gt; fails by design—and how I open-sourced &lt;strong&gt;&lt;code&gt;critic-refine&lt;/code&gt; v1.1.0&lt;/strong&gt;, a 3-tier adversarial verification skill that forces your agent into a ruthless internal tribunal before it writes a single line of production code.&lt;/p&gt;
&lt;p&gt;👉 &lt;strong&gt;GitHub Repository (MIT):&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/manny-ruesch/critic-refine-skill&quot;&gt;manny-ruesch/critic-refine-skill&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;1-the-anatomy-of-first-draft-sycophancy-&quot;&gt;1. The Anatomy of &quot;First-Draft Sycophancy&quot;&lt;/h3&gt;
&lt;p&gt;When you ask an LLM to solve a complex system design or concurrency problem in a single pass, two cognitive traps trigger immediately:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Retroactive Rationalization:&lt;/strong&gt; Autoregressive models commit to an architectural path within the first 150 tokens. Once the function signatures and boilerplate start streaming, the model spends the rest of its attention budget justifying why its initial choice is right.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Confirmation Bias in Self-Review:&lt;/strong&gt; When you prompt &lt;em&gt;&quot;Now review your code for bugs,&quot;&lt;/em&gt; the model reads its own newly generated boilerplate &lt;strong&gt;alongside its own persuasive explanations&lt;/strong&gt;. It falls in love with its own prose and rubber-stamps the output (&lt;code&gt;LGTM!&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To get genuine staff-level engineering out of an agent, you have to break the single-persona loop.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;2-enter-critic-refine-v1-1-0-the-3-tier-adversarial-engine&quot;&gt;2. Enter &lt;code&gt;critic-refine&lt;/code&gt; v1.1.0: The 3-Tier Adversarial Engine&lt;/h3&gt;
&lt;p&gt;Instead of letting the agent jump straight into writing verbose code, &lt;code&gt;critic-refine&lt;/code&gt; hijacks the cognitive workflow and enforces a strict &lt;strong&gt;3-phase adversarial tribunal&lt;/strong&gt; inside the model's reasoning space (or across isolated sub-agents):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;+-------------------------------------------------------------------------+
| PHASE 1: THE GENERATOR (Dense Logical Blueprint v1)                     |
| -&amp;gt; Function signatures, state structs, concurrency locks, SQL/API flow  |
| -&amp;gt; Zero boilerplate, zero comments — preserves context window attention |
+------------------------------------+------------------------------------+
                                     |
                                     v
+-------------------------------------------------------------------------+
| PHASE 2: THE POLYMORPHIC CRITIC (Ruthless Domain Inspection)            |
| -&amp;gt; Dynamically instantiates the harshest domain persona:                |
|    (Principal Rust Systems Eng, Staff DBA, Lead SecOps, DistSys Arch)   |
| -&amp;gt; Anti-Complacency Rule: FORBIDDEN from approving Draft v1 as-is       |
| -&amp;gt; Must surface &amp;gt;= 3 concrete failure vectors (race conditions, O(n^2), |
|    partial network partitions, memory leaks, API hallucinations)        |
| -&amp;gt; Optional `mode:&amp;lt;focus&amp;gt;` allocates 80% of attack surface to 1 axis    |
+------------------------------------+------------------------------------+
                                     |
                                     v
+-------------------------------------------------------------------------+
| PHASE 3: THE ARBITRATING JUDGE (Mental Dry-Run &amp;amp; Deductive Scoring)     |
| -&amp;gt; Simulates hostile execution (null payloads, 100x concurrency spike,  |
|    mid-transaction disk crash)                                          |
| -&amp;gt; Patches the architecture (up to 2 internal feedback loops)           |
| -&amp;gt; Explicitly documents every technical trade-off sacrificed            |
| -&amp;gt; Applies a strict deductive rubric starting from 100 pts              |
+-------------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;why-phase-1-forbids-boilerplate&quot;&gt;Why Phase 1 Forbids Boilerplate&lt;/h4&gt;
&lt;p&gt;If the Generator writes 300 lines of boilerplate in Phase 1, it pollutes the context window and anchors the Critic. By forcing &lt;strong&gt;Draft v1&lt;/strong&gt; to be a &lt;em&gt;dense logical blueprint&lt;/em&gt; (only signatures, lock boundaries, state transitions, and query complexity), the Critic has nowhere to hide and can attack pure architecture.&lt;/p&gt;
&lt;h4 id=&quot;the-anti-complacency-rule&quot;&gt;The Anti-Complacency Rule&lt;/h4&gt;
&lt;p&gt;In Phase 2, the Polymorphic Critic is &lt;strong&gt;explicitly forbidden&lt;/strong&gt; from validating Draft v1 as-is. Whether it adopts the persona of a &lt;em&gt;Staff DBA&lt;/em&gt; inspecting lock escalation or a &lt;em&gt;Lead SecOps Pentester&lt;/em&gt; auditing JWT middleware, it &lt;strong&gt;must&lt;/strong&gt; identify at least &lt;strong&gt;3 concrete failure vectors&lt;/strong&gt; before Phase 3 can begin.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;3-killing-confirmation-bias-the-zero-context-blind-audit-&quot;&gt;3. Killing Confirmation Bias: The &quot;Zero-Context Blind Audit&quot;&lt;/h3&gt;
&lt;p&gt;What happens when you are refactoring &lt;strong&gt;3 or more files&lt;/strong&gt; across a repository? Even an internal scratchpad can suffer from context bleed.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;v1.1.0&lt;/code&gt;, when &lt;code&gt;critic-refine&lt;/code&gt; detects &lt;code&gt;&amp;gt;= 3&lt;/code&gt; impacted files (or when you pass the &lt;code&gt;deep&lt;/code&gt; flag), it triggers a &lt;strong&gt;Zero-Context Blind Audit&lt;/strong&gt; via &lt;code&gt;delegate_task&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It spawns an &lt;strong&gt;isolated sub-agent&lt;/strong&gt; for the Critic.&lt;/li&gt;
&lt;li&gt;It passes &lt;strong&gt;ONLY&lt;/strong&gt; the user's original prompt and the raw Draft v1 blueprint.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;strips out all of the Generator's justifications and reasoning&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because the sub-agent Critic has zero emotional or contextual attachment to &lt;em&gt;why&lt;/em&gt; the code was written that way, it tears the blueprint apart like a real adversarial code review.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;4-the-anti-sycophancy-deductive-rubric&quot;&gt;4. The Anti-Sycophancy Deductive Rubric&lt;/h3&gt;
&lt;p&gt;Ever notice how LLMs always rate their own solutions &lt;code&gt;95/100&lt;/code&gt; or &lt;code&gt;98/100&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;critic-refine&lt;/code&gt; v1.1.0, the Arbitrating Judge is banned from inventing arbitrary &quot;vibes-based&quot; scores. It starts at &lt;strong&gt;100 points&lt;/strong&gt; and must apply a strict mathematical deduction:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;-5 pts&lt;/code&gt;&lt;/strong&gt; per unverified environment or infrastructure assumption (e.g., assuming Redis is configured with &lt;code&gt;noeviction&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;-5 pts&lt;/code&gt;&lt;/strong&gt; per non-isolated critical external dependency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;-10 pts&lt;/code&gt;&lt;/strong&gt; per edge case delegated to the caller instead of handled in-module.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Furthermore, every single flaw caught by the Critic must be mapped &lt;strong&gt;1:1&lt;/strong&gt; to its exact fix in the final output:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;[Concurrency]&lt;/strong&gt; : &lt;em&gt;Unbounded &lt;code&gt;asyncio.gather&lt;/code&gt; on webhook batch risks exhausting DB connection pool under 100x spike&lt;/em&gt; → &lt;strong&gt;Injected &lt;code&gt;asyncio.Semaphore(20)&lt;/code&gt; + exponential jitter backoff on pool acquisition.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;5-the-complete-skill-md-specification-v1-1-0-&quot;&gt;5. The Complete &lt;code&gt;SKILL.md&lt;/code&gt; Specification (v1.1.0)&lt;/h3&gt;
&lt;p&gt;You can drop this directly into &lt;strong&gt;Hermes Agent&lt;/strong&gt; (&lt;code&gt;~/.hermes/skills/software-development/critic-refine/SKILL.md&lt;/code&gt;), &lt;strong&gt;Claude Code&lt;/strong&gt; (&lt;code&gt;.claude/commands/critic-refine.md&lt;/code&gt;), or &lt;strong&gt;Cursor&lt;/strong&gt; (&lt;code&gt;.cursor/rules/&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;---
name: critic-refine
description: &quot;High-rigor 3-tier adversarial verification workflow (Generator, Polymorphic Critic, Judge). Trigger automatically on critical code, distributed architecture, concurrency, security-sensitive logic, complex algorithms, strategic technical trade-offs, or when the user invokes 'critic-refine', 'deep', or 'mode:&amp;lt;focus&amp;gt;'.&quot;
version: 1.1.0
author: Manny, Hermes Agent
license: MIT
platforms: [linux, macos, windows]
metadata:
  hermes:
    tags: [critic, debate, multi-agent, verification, audit, quality, trade-offs]
---

# Critic-Refine Skill (v1.1.0)

Workflow d'assurance qualité extrême simulant un comité d'experts adversariaux (Rédacteur, Critique Polymorphe, Juge Arbitre) pour délivrer des solutions certifiées niveau production.

## Protocole d'Exécution Interne (Le Moteur Adversarial 3-Tiers)

1. **Phase 1 : L'Agent Rédacteur (Blueprint Logique v1)** — Formalise un *Blueprint technique dense* (signatures, structures d'état, concurrence, flux algorithmiques) sans boilerplate.
2. **Phase 2 : Le Critique Polymorphe (Inspection Impitoyable Ciblée)** — Instancie l'expert le plus intransigeant du domaine. Concentre 80% de l'audit sur `mode:&amp;lt;critère&amp;gt;` si spécifié. **Interdiction formelle de valider le Draft v1 tel quel** : identifie au minimum 3 vecteurs de défaillance concrets.
3. **Phase 3 : Le Juge Arbitre (Dry-Run, Patching et Compromis)** — Simule l'exécution avec des entrées hostiles (null, débordements, pic 100x, crash disque à mi-transaction), applique les patchs (max 2 boucles) et explicite les compromis.
4. **Mode Sous-Agents Isolés (`delegate_task` — Deep-Dive)** — Si `&amp;gt;= 3 fichiers` ou flag `deep`, lance un **Zero-Context Blind Audit** en ne transmettant que le besoin initial et le Draft v1 sans les justifications du Rédacteur.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;(Full French and English documentation available in the &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/manny-ruesch/critic-refine-skill&quot;&gt;GitHub repo&lt;/a&gt;).&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-put-it-to-the-test-i-want-your-feedback-&quot;&gt;🧪 Put It to the Test (I Want Your Feedback!)&lt;/h3&gt;
&lt;p&gt;I open-sourced &lt;code&gt;critic-refine&lt;/code&gt; v1.1.0 today under the MIT License because I want to see where it breaks and how we can make the tribunal even sharper.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Install it in 10 seconds:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mkdir -p ~/.hermes/skills/software-development/critic-refine
curl -sL https://raw.githubusercontent.com/manny-ruesch/critic-refine-skill/main/SKILL.md \
  -o ~/.hermes/skills/software-development/critic-refine/SKILL.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;I’d love your feedback in the comments or via GitHub Issues:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Throw your nastiest prompt at it&lt;/strong&gt; (distributed locks, race conditions, auth middleware) using &lt;code&gt;/critic-refine mode:security&lt;/code&gt; or &lt;code&gt;/critic-refine mode:low-latency&lt;/code&gt;—what flaws did the Polymorphic Critic catch that a normal prompt missed?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Deductive Rubric:&lt;/strong&gt; Are &lt;code&gt;-5&lt;/code&gt; / &lt;code&gt;-5&lt;/code&gt; / &lt;code&gt;-10&lt;/code&gt; the right penalties, or what other architectural sins should automatically dock points from the Judge's score?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;🔗 &lt;strong&gt;Star, fork, or roast the skill on GitHub:&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/manny-ruesch/critic-refine-skill&quot;&gt;https://github.com/manny-ruesch/critic-refine-skill&lt;/a&gt;&lt;/p&gt;
</description>
<category>Tutorials</category>
<guid isPermaLink="true">https://coderlegion.com/31433/claude-code-cursor-why-your-ai-agent-lies-to-you-and-our-3-tier-adversarial-tribunal-skill</guid>
<pubDate>Fri, 16 Oct 2026 18:36:10 +0000</pubDate>
</item>
<item>
<title>Claude Haiku 5.5 Pricing: Stay Under the 100K-Token Price Cliff</title>
<link>https://coderlegion.com/30809/claude-haiku-5-5-pricing-stay-under-the-100k-token-price-cliff</link>
<description>&lt;p&gt;Claude Haiku 5.5 shipped on October 7, 2026 with a headline price of $0.10 per million input tokens and $0.50 per million output tokens, a tenth of the per-token price of Claude Haiku 4.5. The headline has a condition. Those prices apply to requests whose prompt is up to 100,000 tokens. A request with a longer prompt is billed at $0.50 and $2.50, and the higher prices cover the whole request, not only the tokens past the line.&lt;/p&gt;
&lt;p&gt;So a 100,000-token prompt costs one cent of input and a 100,001-token prompt costs five. Three things about the model push existing workloads toward that line: a tokenizer that counts the same text as roughly 30% more tokens, thinking blocks that now stay in the conversation, and a context window five times the old one, which makes long prompts easy to send.&lt;/p&gt;
&lt;p&gt;This article covers how the threshold is counted, why prompts that were comfortable on Haiku 4.5 can land on the wrong side of it, and the code that keeps requests under it: a cost function, a pre-flight check, a retrieval packer and a context-editing setup for agent loops. The numbers come from Anthropic's documentation as read on October 12, 2026, and the code uses the official &lt;code&gt;anthropic&lt;/code&gt; Python SDK.&lt;/p&gt;
&lt;h3 id=&quot;the-short-answer&quot;&gt;The short answer&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Haiku 5.5 has two price lists. Prompts up to 100,000 tokens pay $0.10 input and $0.50 output per million tokens. Prompts over 100,000 pay $0.50 and $2.50. Every line item in the second list is exactly 5× the first.&lt;/li&gt;
&lt;li&gt;The second list applies to the entire request, including its output tokens and its cache reads.&lt;/li&gt;
&lt;li&gt;Prompt length is &lt;code&gt;input_tokens + cache_creation_input_tokens + cache_read_input_tokens&lt;/code&gt;. A cache hit does not keep a request under the line.&lt;/li&gt;
&lt;li&gt;The same text is about 30% more tokens than on Haiku 4.5, so a prompt that measured around 77,000 tokens there is close to the threshold here.&lt;/li&gt;
&lt;li&gt;Token counting is free. Count before you send, and keep a margin.&lt;/li&gt;
&lt;li&gt;In agent loops, set tool-result clearing to trigger below 100,000. Its default trigger is exactly 100,000.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-claude-haiku-5-5-pricing-works&quot;&gt;How Claude Haiku 5.5 pricing works&lt;/h3&gt;
&lt;p&gt;These are the prices on the &lt;a rel=&quot;nofollow&quot; href=&quot;https://platform.claude.com/docs/en/about-claude/pricing&quot;&gt;pricing page&lt;/a&gt;, per million tokens:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Prompt up to 100,000 tokens &lt;/th&gt;&lt;th&gt;Prompt over 100,000 tokens &lt;/th&gt;&lt;th&gt;Claude Haiku 4.5 (any length)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Input &lt;/td&gt;&lt;td&gt;$0.10 &lt;/td&gt;&lt;td&gt;$0.50 &lt;/td&gt;&lt;td&gt;$1&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;5-minute cache write &lt;/td&gt;&lt;td&gt;$0.125 &lt;/td&gt;&lt;td&gt;$0.625 &lt;/td&gt;&lt;td&gt;$1.25&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1-hour cache write &lt;/td&gt;&lt;td&gt;$0.20 &lt;/td&gt;&lt;td&gt;$1 &lt;/td&gt;&lt;td&gt;$2&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Cache read &lt;/td&gt;&lt;td&gt;$0.01 &lt;/td&gt;&lt;td&gt;$0.05 &lt;/td&gt;&lt;td&gt;$0.10&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Output &lt;/td&gt;&lt;td&gt;$0.50 &lt;/td&gt;&lt;td&gt;$2.50 &lt;/td&gt;&lt;td&gt;$5&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Batch API, input / output &lt;/td&gt;&lt;td&gt;$0.05 / $0.25 &lt;/td&gt;&lt;td&gt;$0.25 / $1.25 &lt;/td&gt;&lt;td&gt;$0.50 / $2.50&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;And this is the rule, quoted from the same page:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;A request's prompt length counts all of its input tokens, including cache reads and cache writes. Each request is priced on its own: a request over the threshold pays the higher prices even when part of its prompt is a cache hit, and earlier requests keep the prices they were billed at.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Anthropic's &lt;a rel=&quot;nofollow&quot; href=&quot;https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence&quot;&gt;cost guide&lt;/a&gt; puts it in one clause: a request over the threshold &quot;pays the higher prices for all of its tokens&quot;.&lt;/p&gt;
&lt;p&gt;Three consequences follow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It is a step, not a marginal rate.&lt;/strong&gt; A tax bracket charges the higher rate only on the amount above the bracket. This charges it on everything. Trimming a 120,000-token prompt to 100,000 removes 17% of the tokens and 83% of the input cost: $0.060 becomes $0.010.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Output is priced by the prompt's tier.&lt;/strong&gt; Output tokens don't count toward the 100,000, but a long prompt makes every output token cost 5×, and thinking is billed as output.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nothing is retroactive.&lt;/strong&gt; A conversation that grows past the line pays more from that request on. The turns before it keep their price.&lt;/p&gt;
&lt;p&gt;Haiku 5.5 is the only model in the current lineup priced this way. The other models with a 1M-token context window bill long prompts at their standard rate.&lt;/p&gt;
&lt;p&gt;Here is the rule as code. Prices are strings turned into &lt;code&gt;Decimal&lt;/code&gt;, and since $X per million tokens is X micro-dollars per token, the arithmetic stays exact:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from decimal import Decimal

THRESHOLD = 100_000  # prompt tokens; &quot;up to 100,000&quot; is still the lower tier

# USD per million tokens, from platform.claude.com/docs/en/about-claude/pricing
# (checked 2026-10-12). This is configuration: reload it when prices change.
# Standard API with global routing: the Batch API halves these, and
# inference_geo &quot;us&quot; multiplies them by 1.1.
HAIKU_5_5 = {
    &quot;short&quot;: {&quot;input&quot;: &quot;0.10&quot;, &quot;write_5m&quot;: &quot;0.125&quot;, &quot;write_1h&quot;: &quot;0.20&quot;, &quot;read&quot;: &quot;0.01&quot;, &quot;output&quot;: &quot;0.50&quot;},
    &quot;long&quot;:  {&quot;input&quot;: &quot;0.50&quot;, &quot;write_5m&quot;: &quot;0.625&quot;, &quot;write_1h&quot;: &quot;1.00&quot;, &quot;read&quot;: &quot;0.05&quot;, &quot;output&quot;: &quot;2.50&quot;},
}


def prompt_tokens(usage: dict) -&amp;gt; int:
    &quot;&quot;&quot;Prompt length as the pricing rule defines it: every input token, cached or not.&quot;&quot;&quot;
    return (
        usage.get(&quot;input_tokens&quot;, 0)
        + usage.get(&quot;cache_creation_input_tokens&quot;, 0)
        + usage.get(&quot;cache_read_input_tokens&quot;, 0)
    )


def price_haiku_5_5(usage: dict) -&amp;gt; tuple[str, Decimal]:
    &quot;&quot;&quot;Return (tier, cost in USD) for one request, priced on its own.&quot;&quot;&quot;
    tier = &quot;long&quot; if prompt_tokens(usage) &amp;gt; THRESHOLD else &quot;short&quot;
    p = {k: Decimal(v) for k, v in HAIKU_5_5[tier].items()}
    write_1h = usage.get(&quot;cache_creation_1h_input_tokens&quot;, 0)
    write_5m = usage.get(&quot;cache_creation_input_tokens&quot;, 0) - write_1h
    micro_usd = (
        usage.get(&quot;input_tokens&quot;, 0) * p[&quot;input&quot;]
        + write_5m * p[&quot;write_5m&quot;]
        + write_1h * p[&quot;write_1h&quot;]
        + usage.get(&quot;cache_read_input_tokens&quot;, 0) * p[&quot;read&quot;]
        + usage.get(&quot;output_tokens&quot;, 0) * p[&quot;output&quot;]
    )
    return tier, micro_usd / Decimal(1_000_000)


for n in (100_000, 100_001):
    print(n, *price_haiku_5_5({&quot;input_tokens&quot;: n, &quot;output_tokens&quot;: 1_000}))
# 100000 short 0.0105
# 100001 long 0.0525005
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One token moved the request from about one cent to about five.&lt;/p&gt;
&lt;h3 id=&quot;what-counts-toward-the-100-000-token-threshold&quot;&gt;What counts toward the 100,000-token threshold&lt;/h3&gt;
&lt;p&gt;Everything in the prompt counts: the system prompt, tool definitions, every message, images and PDFs, tool results, and the thinking blocks of earlier assistant turns.&lt;/p&gt;
&lt;p&gt;The response's &lt;code&gt;usage&lt;/code&gt; object splits the prompt into three fields, and the &lt;a rel=&quot;nofollow&quot; href=&quot;https://platform.claude.com/docs/en/build-with-claude/prompt-caching&quot;&gt;prompt caching docs&lt;/a&gt; give the total as &lt;code&gt;cache_read_input_tokens + cache_creation_input_tokens + input_tokens&lt;/code&gt;. Don't check &lt;code&gt;input_tokens&lt;/code&gt; alone. It holds only the tokens after the last cache breakpoint, and in a well-cached application it is a small number that says nothing about the tier.&lt;/p&gt;
&lt;p&gt;Caching is where the rule surprises people. Take a request that reads 98,000 tokens from the cache, adds 2,000 new ones and returns 500:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;print(*price_haiku_5_5({&quot;cache_read_input_tokens&quot;: 98_000, &quot;input_tokens&quot;: 2_000, &quot;output_tokens&quot;: 500}))
# short 0.00143
print(*price_haiku_5_5({&quot;cache_read_input_tokens&quot;: 98_000, &quot;input_tokens&quot;: 2_001, &quot;output_tokens&quot;: 500}))
# long 0.0071505
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Prompt caching lowers what each token costs on either side of the line. It does not move the line.&lt;/p&gt;
&lt;p&gt;Output tokens of the current request don't count. They become input on the next turn, which is how a conversation crosses the threshold a few turns after you looked.&lt;/p&gt;
&lt;h3 id=&quot;why-prompts-that-fit-on-claude-haiku-4-5-land-over-the-line&quot;&gt;Why prompts that fit on Claude Haiku 4.5 land over the line&lt;/h3&gt;
&lt;p&gt;The &lt;a rel=&quot;nofollow&quot; href=&quot;https://platform.claude.com/docs/en/models/haiku-5-5/migration-guide&quot;&gt;migration guide&lt;/a&gt; lists three changes that raise the token count of the same request.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The tokenizer.&lt;/strong&gt; Haiku 5.5 uses the tokenizer introduced with Claude Opus 4.7, and &quot;the same input text produces approximately 30% more tokens on Claude Haiku 5.5 than on Claude Haiku 4.5. The exact increase depends on the content.&quot; Divide 100,000 by 1.3 and you get about 77,000: a prompt of that size by Haiku 4.5's count is near the threshold on Haiku 5.5. Treat that as a reason to recount, not as a conversion factor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thinking blocks stay in context.&lt;/strong&gt; &quot;Thinking blocks from earlier assistant turns stay in context and count as input tokens, where Claude Haiku 4.5 kept only the latest turn's.&quot; Adaptive thinking is on by default, so a multi-turn conversation grows faster than the tokenizer alone explains.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Large images cost more.&lt;/strong&gt; Haiku 5.5 uses the high-resolution image tier. Per the guide, an image of 2,000 by 1,500 pixels costs about 2.5 times as many visual tokens as on Haiku 4.5.&lt;/p&gt;
&lt;p&gt;None of this makes the migration a bad deal. Assuming the 30% figure, the same text costs about 87% less to send than on Haiku 4.5 when the request stays under the threshold (1.3 × $0.10 against $1) and about 35% less when it doesn't (1.3 × $0.50 against $1). The threshold decides which of those two savings you get. The output side needs measuring rather than arithmetic, because thinking is now on by default, where Haiku 4.5 ran without it unless you enabled it, and thinking is billed as output.&lt;/p&gt;
&lt;p&gt;Measuring is one function. The token counting endpoint counts under the tokenizer of the model you pass, so count each request twice:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import anthropic

client = anthropic.Anthropic()


def recount(request: dict) -&amp;gt; dict:
    &quot;&quot;&quot;Count one request (system / tools / messages) under both tokenizers.&quot;&quot;&quot;
    old = client.messages.count_tokens(model=&quot;claude-haiku-4-5&quot;, **request).input_tokens
    new = client.messages.count_tokens(model=&quot;claude-haiku-5-5&quot;, **request).input_tokens
    return {&quot;haiku_4_5&quot;: old, &quot;haiku_5_5&quot;: new, &quot;ratio&quot;: round(new / old, 3), &quot;over&quot;: new &amp;gt; 100_000}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run it over a sample of real production requests, the largest ones first, and look at two things: the ratio for your content, and how many requests come back with &lt;code&gt;over&lt;/code&gt; set.&lt;/p&gt;
&lt;h3 id=&quot;count-before-you-send&quot;&gt;Count before you send&lt;/h3&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://platform.claude.com/docs/en/build-with-claude/token-counting&quot;&gt;Token counting&lt;/a&gt; is free and has its own rate limit, separate from the Messages API: 5,000 to 20,000 requests per minute depending on usage tier. Two details from its documentation shape the guard.&lt;/p&gt;
&lt;p&gt;The count &quot;is an estimate. In some cases, the actual number of input tokens used when creating a message might differ by a small amount.&quot; A request counted at 99,990 could land on either side, so keep a margin.&lt;/p&gt;
&lt;p&gt;The endpoint rejects requests that include server tools such as web search or code execution, the MCP connector, and images or documents passed by URL or file ID. Images and PDFs can be counted when you send them as base64. For requests with server tools or MCP servers, the only number you get is &lt;code&gt;usage&lt;/code&gt; on the response, after the fact.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;MODEL = &quot;claude-haiku-5-5&quot;
SAFETY_MARGIN = 2_000   # the count is an estimate; leave room for drift


def count(request: dict) -&amp;gt; int:
    &quot;&quot;&quot;request holds system / tools / messages exactly as you would send them.&quot;&quot;&quot;
    return client.messages.count_tokens(model=MODEL, **request).input_tokens


def tier_before_sending(request: dict) -&amp;gt; str:
    n = count(request)
    if n &amp;lt;= THRESHOLD - SAFETY_MARGIN:
        return &quot;short&quot;
    if n &amp;lt;= THRESHOLD:
        return &quot;borderline&quot;   # could be billed either way: shrink it or accept the risk
    return &quot;long&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A request that comes back &lt;code&gt;long&lt;/code&gt; has three honest options: send less context, split the work, or send it as it is because the task needs it. The next two sections cover the first two. The third has its own section further down, on when the long-prompt price is the right price.&lt;/p&gt;
&lt;h3 id=&quot;retrieval-and-document-jobs-pack-to-a-budget-split-instead-of-stuffing&quot;&gt;Retrieval and document jobs: pack to a budget, split instead of stuffing&lt;/h3&gt;
&lt;p&gt;With a 1M-token window it is tempting to pass every retrieved chunk. On Haiku 5.5 the budget that matters is 100,000, so pack to it. Store each chunk's token count at indexing time, measured with the model you will call, and add chunks in rank order until the next one doesn't fit:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;SYSTEM = &quot;Answer from the documents. Say so when they don't contain the answer.&quot;


def build_request(question: str, chunks: list[str]) -&amp;gt; dict:
    docs = &quot;\n\n&quot;.join(f&quot;&amp;lt;document&amp;gt;\n{c}\n&amp;lt;/document&amp;gt;&quot; for c in chunks)
    return {&quot;system&quot;: SYSTEM, &quot;messages&quot;: [{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: f&quot;{docs}\n\n{question}&quot;}]}


def pack(question: str, ranked: list[tuple[str, int]], budget: int = THRESHOLD - SAFETY_MARGIN) -&amp;gt; dict:
    &quot;&quot;&quot;ranked: (chunk_text, token_count) pairs, best first.&quot;&quot;&quot;
    used = count(build_request(question, []))
    chosen: list[str] = []
    for text, tokens in ranked:
        if used + tokens &amp;gt; budget:
            break
        chosen.append(text)
        used += tokens
    request = build_request(question, chosen)
    while chosen and count(request) &amp;gt; budget:   # per-chunk counts don't add up exactly
        chosen.pop()
        request = build_request(question, chosen)
    return request
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The stored counts make the loop cheap, and the final &lt;code&gt;count()&lt;/code&gt; catches the difference between a sum of parts and the assembled prompt.&lt;/p&gt;
&lt;p&gt;For a single large document, compare stuffing with splitting. A 250,000-token document with a 2,000-token answer costs $0.130 as one request. Split into three parts of about 84,000 tokens, each returning 1,000 tokens, it costs $0.0267, and a final request that merges the three partial answers (about 4,000 tokens in with its instructions, 2,000 out) adds $0.0014. That is about 78% less for the same input.&lt;/p&gt;
&lt;p&gt;Splitting only works when the task decomposes: extraction, classification, per-section summaries. A question that needs two distant parts of the document in view at once loses accuracy when you split it, and no price difference fixes a wrong answer.&lt;/p&gt;
&lt;p&gt;The &lt;a rel=&quot;nofollow&quot; href=&quot;https://platform.claude.com/docs/en/build-with-claude/batch-processing&quot;&gt;Batch API&lt;/a&gt; halves both price lists and keeps the threshold: $0.05 and $0.25 per million tokens under it, $0.25 and $1.25 over it.&lt;/p&gt;
&lt;h3 id=&quot;agent-loops-the-cliff-arrives-mid-run&quot;&gt;Agent loops: the cliff arrives mid-run&lt;/h3&gt;
&lt;p&gt;An agent re-sends its growing history on every step. With prompt caching that is cheap, until the history passes 100,000 tokens. From that step on, every request pays the second price list, cache reads included, and it keeps paying until the context shrinks.&lt;/p&gt;
&lt;p&gt;The size of the effect depends on the run length, so here is a model you can change. It assumes 8,000 tokens of system prompt, tools and task, and a step that appends a 3,000-token tool result and a 500-token assistant turn (its output, thinking included), with the history cached incrementally. With a &lt;code&gt;trigger&lt;/code&gt;, tool results older than the last four are cleared once the prompt passes it. Two simplifications: a cleared result counts as zero tokens, although the API leaves placeholder text in its place, and the clearing request is charged as a full cache rewrite, the worst case:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def simulate(steps: int, fixed: int = 8_000, tool_result: int = 3_000, out: int = 500,
             trigger: int = 0, keep: int = 4) -&amp;gt; dict:
    results: list[int] = []   # live tool-result sizes, oldest first
    turns = 0                 # assistant turns in history, `out` tokens each
    cached = 0                # tokens already in the cache
    total = Decimal(0)
    long_steps = 0
    for _ in range(steps):
        prompt = fixed + sum(results) + turns * out
        cleared = False
        if trigger and prompt &amp;gt; trigger and len(results) &amp;gt; keep:
            results = [0] * (len(results) - keep) + results[-keep:]
            prompt = fixed + sum(results) + turns * out
            cleared = True
        read = 0 if cleared else cached
        tier, cost = price_haiku_5_5({
            &quot;cache_read_input_tokens&quot;: read,
            &quot;cache_creation_input_tokens&quot;: prompt - read,
            &quot;output_tokens&quot;: out,
        })
        total += cost
        long_steps += tier == &quot;long&quot;
        cached = prompt
        results.append(tool_result)
        turns += 1
    return {&quot;steps&quot;: steps, &quot;steps_over_100k&quot;: long_steps, &quot;usd&quot;: round(total, 4)}
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Steps in the run &lt;/th&gt;&lt;th&gt;No context management &lt;/th&gt;&lt;th&gt;Clearing at 75,000 tokens&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;25 &lt;/td&gt;&lt;td&gt;$0.0293, no step over the line &lt;/td&gt;&lt;td&gt;$0.0300&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;40 &lt;/td&gt;&lt;td&gt;$0.1553, 13 steps over &lt;/td&gt;&lt;td&gt;$0.0516&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;60 &lt;/td&gt;&lt;td&gt;$0.4018, 33 steps over &lt;/td&gt;&lt;td&gt;$0.0862&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The unmanaged run crosses the line at step 28, and from there the gap widens: 3× at 40 steps, 4.7× at 60. At 50,000 sixty-step runs a month, that is about $20,100 against $4,300. This is arithmetic on published prices with invented workload numbers, not a benchmark, so put your own step sizes in.&lt;/p&gt;
&lt;p&gt;A run that never reaches the line gains nothing from clearing and pays for the cache rewrite: about 2% more in this model. Real runs can do worse. The cost guide quoted earlier reports a short agent run on which context editing cost 74% more and a long one on which it changed nothing. Removing tokens is rarely a saving in itself. In this model about 94% of the gain comes from keeping every step on the first price list, and the rest from smaller cache reads.&lt;/p&gt;
&lt;p&gt;The mechanism behind the right-hand column is &lt;a rel=&quot;nofollow&quot; href=&quot;https://platform.claude.com/docs/en/build-with-claude/context-editing&quot;&gt;context editing&lt;/a&gt;, a beta feature that clears old tool results on the server before the prompt reaches the model:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;response = client.beta.messages.create(
    model=&quot;claude-haiku-5-5&quot;,
    max_tokens=8_000,
    system=AGENT_SYSTEM,
    tools=TOOLS,
    messages=messages,   # your full, unmodified history
    betas=[&quot;context-management-2025-06-27&quot;],
    context_management={
        &quot;edits&quot;: [
            {
                &quot;type&quot;: &quot;clear_tool_uses_20250919&quot;,
                &quot;trigger&quot;: {&quot;type&quot;: &quot;input_tokens&quot;, &quot;value&quot;: 75_000},
                &quot;keep&quot;: {&quot;type&quot;: &quot;tool_uses&quot;, &quot;value&quot;: 4},
                &quot;clear_at_least&quot;: {&quot;type&quot;: &quot;input_tokens&quot;, &quot;value&quot;: 20_000},
            }
        ]
    },
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Four details matter here.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Set the trigger yourself.&lt;/strong&gt; The default trigger is 100,000 input tokens, which is exactly Haiku 5.5's price line. I haven't found a statement in the documentation on whether the tier is decided by the prompt's size before or after clearing, so don't let the bill depend on it. Pick a lower value, with enough headroom that what clearing leaves behind still fits: the system prompt, the kept tool results and the assistant turns. To preview the result, pass the same &lt;code&gt;betas&lt;/code&gt; and &lt;code&gt;context_management&lt;/code&gt; to &lt;code&gt;client.beta.messages.count_tokens()&lt;/code&gt;: it returns the count after clearing as &lt;code&gt;input_tokens&lt;/code&gt; and the count before as &lt;code&gt;context_management.original_input_tokens&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Clearing breaks the prompt cache.&lt;/strong&gt; Per the documentation, tool result clearing invalidates cached prompt prefixes when content is cleared, and &lt;code&gt;clear_at_least&lt;/code&gt; exists so that each invalidation removes enough tokens to be worth it. If the API can't clear that much, the strategy is not applied, so watch &lt;code&gt;context_management.applied_edits&lt;/code&gt; on the response for runs where nothing gets cleared.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Old thinking blocks can be cleared too.&lt;/strong&gt; The &lt;code&gt;clear_thinking_20251015&lt;/code&gt; strategy keeps only the last N turns' thinking when you set &lt;code&gt;keep&lt;/code&gt; to &lt;code&gt;{&quot;type&quot;: &quot;thinking_turns&quot;, &quot;value&quot;: N}&lt;/code&gt;. On Haiku 5.5 its default is to keep all of them. When you combine it with tool-result clearing it must come first in &lt;code&gt;edits&lt;/code&gt;, and clearing thinking also invalidates the cache from that point.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Don't trim history on the client.&lt;/strong&gt; On Haiku 5.5, a request that sends a thinking block back after a change to &lt;code&gt;system&lt;/code&gt;, &lt;code&gt;tools&lt;/code&gt; or earlier &lt;code&gt;messages&lt;/code&gt; returns a 400 error, unless you opt into having the invalidated blocks dropped. Accounts created before August 31, 2026 get the error only when they set &lt;code&gt;thinking.block_binding.prefix_mismatch_behavior&lt;/code&gt;. The classic sliding window that drops the oldest messages is exactly that kind of change. Server-side context management &quot;never invalidates thinking blocks&quot;, which is the reason to prefer it. When clearing tool results isn't enough, &lt;a rel=&quot;nofollow&quot; href=&quot;https://platform.claude.com/docs/en/build-with-claude/compaction&quot;&gt;compaction&lt;/a&gt;, also in beta, replaces older turns with a summary written on the server.&lt;/p&gt;
&lt;p&gt;Clearing changes what the model can see. An agent that needs a file it read thirty steps ago has to read it again. Run your evals with clearing on before you rely on the savings.&lt;/p&gt;
&lt;h3 id=&quot;watch-the-line-in-production&quot;&gt;Watch the line in production&lt;/h3&gt;
&lt;p&gt;The response tells you which price list a request was billed on, as long as you add the three input fields together. Log the prompt length, the tier and the cost on every call:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def usage_dict(u) -&amp;gt; dict:
    &quot;&quot;&quot;Flatten the SDK's usage object into the dict price_haiku_5_5() expects.&quot;&quot;&quot;
    return {
        &quot;input_tokens&quot;: u.input_tokens,
        &quot;cache_creation_input_tokens&quot;: u.cache_creation_input_tokens or 0,
        &quot;cache_creation_1h_input_tokens&quot;: u.cache_creation.ephemeral_1h_input_tokens if u.cache_creation else 0,
        &quot;cache_read_input_tokens&quot;: u.cache_read_input_tokens or 0,
        &quot;output_tokens&quot;: u.output_tokens,
    }


usage = usage_dict(response.usage)
tier, cost = price_haiku_5_5(usage)
print(prompt_tokens(usage), tier, cost)   # send these to your metrics instead
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Two numbers are worth an alert. The share of requests billed as &lt;code&gt;long&lt;/code&gt; should match what you decided on purpose. The share of requests between 90,000 and 100,000 tokens tells you what will cross after the next prompt edit, the next tool you add, or the next slightly longer document.&lt;/p&gt;
&lt;h3 id=&quot;when-the-long-prompt-price-is-the-right-price&quot;&gt;When the long-prompt price is the right price&lt;/h3&gt;
&lt;p&gt;Staying under the line is an optimization, not a rule. Above it, Haiku 5.5 costs $0.50 and $2.50 per million tokens. That is half the per-token price of Haiku 4.5 and a quarter of Claude Sonnet 5.5 at $2 and $10.&lt;/p&gt;
&lt;p&gt;Pay it when the task needs the whole context in one view, when a split would cost accuracy, or when the request runs a few times a day and four cents is not worth an engineer's afternoon. The cliff matters at volume, in the classification, extraction, routing and subagent traffic the model is built for, where a 5× difference on every request is the whole bill.&lt;/p&gt;
&lt;h3 id=&quot;other-migration-changes-that-move-the-bill&quot;&gt;Other migration changes that move the bill&lt;/h3&gt;
&lt;p&gt;The threshold is one of several changes in the migration guide that affect cost.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Thinking is on by default and counts toward &lt;code&gt;max_tokens&lt;/code&gt;. A small &lt;code&gt;max_tokens&lt;/code&gt; carried over from Haiku 4.5 can stop a response after a thinking block and before any text.&lt;/li&gt;
&lt;li&gt;The &lt;a rel=&quot;nofollow&quot; href=&quot;https://platform.claude.com/docs/en/build-with-claude/effort&quot;&gt;effort parameter&lt;/a&gt; is the control for how much the model thinks. The default is &lt;code&gt;medium&lt;/code&gt;. The docs describe &lt;code&gt;low&lt;/code&gt; as the cheapest and fastest level, meant for simple, high-volume requests. Set it with &lt;code&gt;output_config={&quot;effort&quot;: &quot;low&quot;}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Changing the top-level effort value between requests invalidates the prompt cache for that conversation's messages.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;thinking&lt;/code&gt; with &lt;code&gt;budget_tokens&lt;/code&gt; and assistant prefill return a 400 error. So does nearly every &lt;code&gt;temperature&lt;/code&gt;, &lt;code&gt;top_p&lt;/code&gt; or &lt;code&gt;top_k&lt;/code&gt; value, so omit all three.&lt;/li&gt;
&lt;li&gt;The minimum cacheable prompt is 512 tokens, down from 4,096 on Haiku 4.5, so prompts in between now cache when they set &lt;code&gt;cache_control&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;faq&quot;&gt;FAQ&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Is the higher price charged only on the tokens above 100,000?&lt;/strong&gt;&lt;br&gt;
No. A request whose prompt is over 100,000 tokens pays the higher prices on all of its tokens: input, cache writes, cache reads and output.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do cached tokens count toward the 100,000-token threshold?&lt;/strong&gt;&lt;br&gt;
Yes. The prompt length counts all input tokens, including cache reads and cache writes. A request over the threshold pays the higher prices even when part of its prompt is a cache hit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do output tokens count toward the threshold?&lt;/strong&gt;&lt;br&gt;
No. Only the prompt is measured. Output is priced by the tier the prompt lands in, and it becomes input on the next turn.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does the Batch API avoid the higher tier?&lt;/strong&gt;&lt;br&gt;
No. Batch requests get 50% off in both tiers, and the same 100,000-token threshold applies to each request.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does Claude Haiku 4.5 have the same threshold?&lt;/strong&gt;&lt;br&gt;
No. Haiku 4.5 is billed at $1 and $5 per million tokens at any prompt length, with a 200,000-token context window. It is now listed among the legacy models. The &lt;a rel=&quot;nofollow&quot; href=&quot;https://platform.claude.com/docs/en/about-claude/model-deprecations&quot;&gt;deprecations page&lt;/a&gt; shows it as active, with a tentative retirement date of &quot;Not sooner than October 15, 2026&quot; and no deprecation notice so far.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do I know which tier a request was billed at?&lt;/strong&gt;&lt;br&gt;
Add &lt;code&gt;input_tokens&lt;/code&gt;, &lt;code&gt;cache_creation_input_tokens&lt;/code&gt; and &lt;code&gt;cache_read_input_tokens&lt;/code&gt; from the response's &lt;code&gt;usage&lt;/code&gt;. Over 100,000 means the higher prices.&lt;/p&gt;
&lt;h3 id=&quot;a-migration-checklist&quot;&gt;A migration checklist&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Recount a sample of real requests with &lt;code&gt;model=&quot;claude-haiku-5-5&quot;&lt;/code&gt;. Don't reuse counts measured on Haiku 4.5.&lt;/li&gt;
&lt;li&gt;Price requests by tier, from all three input fields in &lt;code&gt;usage&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Count before sending, with a margin, wherever a prompt can approach 100,000 tokens.&lt;/li&gt;
&lt;li&gt;Pack retrieval to a budget. Split document jobs that decompose.&lt;/li&gt;
&lt;li&gt;In agent loops, turn on tool-result clearing with an explicit trigger below 100,000 and a &lt;code&gt;clear_at_least&lt;/code&gt; value, and keep the history append-only on the client.&lt;/li&gt;
&lt;li&gt;Alert on the share of requests in the long tier and on the share between 90,000 and 100,000 tokens.&lt;/li&gt;
&lt;li&gt;Send a long prompt when the task needs one, and know what it costs when you do.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The $0.10 headline is real, and it belongs to requests whose prompts stay at or under 100,000 tokens. The line is not visible from inside a single request. It shows up when you add up &lt;code&gt;usage&lt;/code&gt; across a day of traffic, so do that before the invoice does it for you.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;I'm Dragoș. I build LLM systems and teach production LLM integration at &lt;a rel=&quot;nofollow&quot; href=&quot;https://cursuri-ai.ro/en/courses/advanced-llm-integration-in-production&quot;&gt;Cursuri-AI.ro&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30809/claude-haiku-5-5-pricing-stay-under-the-100k-token-price-cliff</guid>
<pubDate>Mon, 12 Oct 2026 12:30:26 +0000</pubDate>
</item>
<item>
<title>Remote Control for API-Based Claude Code: Approve Bedrock, Vertex &amp; Foundry Sessions From Your Phone</title>
<link>https://coderlegion.com/29732/remote-control-based-claude-code-approve-bedrock-vertex-foundry-sessions-from-your-phone</link>
<description>&lt;h4 id=&quot;claude-code-s-remote-control-needs-a-claude-subscription-login-so-api-provider-sessions-are-stuck-in-the-terminal-here-s-how-i-gave-them-one-back-with-hooks-a-file-queue-and-a-single-python-file&quot;&gt;Claude Code’s Remote Control needs a Claude subscription login, so API-provider sessions are stuck in the terminal — here’s how I gave them one back with hooks, a file queue and a single Python file&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/1024/1*9GYHu6TA976JUKL5DET2Ng.jpeg&quot; alt=&quot;ccBridger: Remote Control for API-based Claude Code sessions (Bedrock, Vertex, Foundry)&quot;&gt;&lt;br&gt;
&lt;em&gt;ccBridger: Remote Control for API-based Claude Code sessions (Bedrock, Vertex, Foundry)&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR — Claude Code’s Remote Control needs a Claude subscription login. Sessions that run through an API provider — AWS Bedrock, Google Vertex AI, Microsoft Foundry — don’t get it, so a single permission prompt can stall an hour of work while you are in a meeting.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;ccBridger&lt;/strong&gt; is a small open-source bridge: hooks record what the session needs, a tiny helper session shows it in the Claude mobile app as a native prompt, and your tap goes back to the terminal.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;No server, no open ports, no additional application, standard library only.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/fxerkan/ccbridger&quot;&gt;github.com/fxerkan/ccbridger&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h5 id=&quot;the-problem&quot;&gt;The problem&lt;/h5&gt;
&lt;p&gt;A lot of companies run Claude Code through their cloud provider instead of a Claude subscription: &lt;strong&gt;AWS Bedrock, Google Vertex AI&lt;/strong&gt; or &lt;strong&gt;Microsoft Foundry&lt;/strong&gt;. The reasons are sensible: billing lands on the cloud invoice, data stays inside the account, access goes through the provider’s own identity system. I work that way on two client projects, both on Bedrock.&lt;/p&gt;
&lt;p&gt;What you give up is Remote Control. With a subscription login you can open the Claude app on your phone, see the session that is running on your laptop, answer its questions and keep it moving. With an &lt;strong&gt;API provider that door is closed&lt;/strong&gt;. The session lives in the terminal tab where you started it, and nowhere else.&lt;/p&gt;
&lt;p&gt;That sounds like a small inconvenience until you look at how agent work actually goes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You start a long task — a migration, a refactor, an infrastructure change — and go to a meeting.&lt;/li&gt;
&lt;li&gt;Eight minutes in, the agent wants to run a command it isn’t allowed to run on its own. It asks. Nobody answers.&lt;/li&gt;
&lt;li&gt;You come back fifty minutes later to a prompt that says “Do you want to proceed?” and an agent that has done nothing since.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The other failure mode is worse. To avoid the stall, people start sessions with &lt;strong&gt;--dangerously-skip-permissions&lt;/strong&gt;. Now nothing waits for you — including the things that should.&lt;/p&gt;
&lt;p&gt;And it isn’t only permissions. Agents ask real questions too: “The upgrade can’t be rolled back. Test workspace first, or straight to prod?” That is exactly the decision you want to make yourself, and exactly the one that sits unanswered while you are away.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/1024/1*5IsYX5dbdiQ0astoSmLi-Q.png&quot; alt=&quot;The same prompt, two outcomes: without the bridge it waits at an empty desk for 48 minutes; with ccBridger the answer costs ten seconds from your phone&quot;&gt;&lt;br&gt;
&lt;em&gt;The same prompt, two outcomes: without the bridge it waits at an empty desk for 48 minutes; with ccBridger the answer costs ten seconds from your phone&lt;/em&gt;&lt;/p&gt;
&lt;h5 id=&quot;an-analogy-before-the-tech&quot;&gt;An analogy before the tech&lt;/h5&gt;
&lt;p&gt;Picture a contractor renovating your kitchen while you are at work. They are good and fast, but they have one rule: before knocking down a wall, they ask. If they can only ask by knocking on your study door, the work stops the moment you leave the house. Give them your phone number and the same rule costs you ten seconds instead of an afternoon.&lt;/p&gt;
&lt;p&gt;ccBridger is the phone number. The rule — ask before doing something that matters — stays exactly as it was.&lt;/p&gt;
&lt;h5 id=&quot;why-the-obvious-answers-don-t-fit&quot;&gt;Why the obvious answers don’t fit&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;“Just SSH in and attach to tmux.”&lt;/strong&gt; Works, on a laptop keyboard. On a phone, typing into a terminal UI to press 1 is miserable, and you only find out there is something to answer if you go and look.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“Build a web dashboard.”&lt;/strong&gt; Now there is a server to run, a port to expose, authentication to get right, and a new place where your prompts and commands live.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“Wrap the CLI.”&lt;/strong&gt; A wrapper has to sit between you and the terminal all the time, and it changes how you start every session.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“Skip permissions.”&lt;/strong&gt; See above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What I wanted was narrower:&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Keep working exactly as before. If I’m at the keyboard, nothing changes. If I’m not, the question finds me — in an app I already have, on an account I already own — and my answer goes back. Nothing to host.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h5 id=&quot;the-idea-borrow-the-remote-control-you-already-have&quot;&gt;The idea: borrow the Remote Control you already have&lt;/h5&gt;
&lt;p&gt;Remote Control doesn’t work for the API-based session. But it works fine for a different session on the same machine that runs on my own Claude login. So the bridge doesn’t try to remote-control that session at all. It starts a tiny second session whose only job is to ask me a question, and lets Remote Control carry that question to my phone.&lt;/p&gt;
&lt;p&gt;Three pieces make that work.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/1024/1*V-W6HWDcspYOHeyrZ3OuZw.png&quot; alt=&quot;ccBridger architecture: a permission request leaves the API-based session through hooks, lands in a plain-file queue, and after 15 seconds a relay session running on your own Claude login carries it to the Claude mobile app; your tap maps back to a decision file and unblocks the terminal&quot;&gt;&lt;br&gt;
&lt;em&gt;ccBridger architecture: a permission request leaves the API-based session through hooks, lands in a plain-file queue, and after 15 seconds a relay session running on your own Claude login carries it to the Claude mobile app; your tap maps back to a decision file and unblocks the terminal&lt;/em&gt;&lt;/p&gt;
&lt;h5 id=&quot;1-hooks-on-the-api-based-session&quot;&gt;1. Hooks on the API-based session&lt;/h5&gt;
&lt;p&gt;Claude Code runs hooks — shell commands — at defined points.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ccb install&lt;/strong&gt; adds five of them:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PermissionRequest&lt;/strong&gt;  — Writes the request (tool, input) to a file, then waits for a decision file. The terminal prompt stays live the whole time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stop, SessionStart, UserPromptSubmit, Notification&lt;/strong&gt;  — Keep one background waiter per session alive.&lt;/p&gt;
&lt;p&gt;The decision goes back as the hook’s JSON output:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{&quot;hookSpecificOutput&quot;: {&quot;hookEventName&quot;: &quot;PermissionRequest&quot;,
                        &quot;decision&quot;: {&quot;behavior&quot;: &quot;allow&quot;}}}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The waiter is how a message reaches an idle session. Those four hooks are registered with &lt;strong&gt;asyncRewake&lt;/strong&gt; : they run in the background, and when one exits with code 2, Claude Code wakes the session and hands it the hook’s stderr. So the waiter polls an inbox file; when a message lands, it prints the message and exits 2. The idle session wakes up and treats it as something the user said.&lt;/p&gt;
&lt;p&gt;Four hooks for one waiter looks redundant. It isn’t: a turn interrupted with Esc never fires &lt;strong&gt;Stop&lt;/strong&gt; , so without the others the waiter would be gone until the next full turn.&lt;/p&gt;
&lt;h5 id=&quot;2-a-file-queue&quot;&gt;2. A file queue&lt;/h5&gt;
&lt;p&gt;All state is plain files under &lt;strong&gt;~/.claude/ccbridger/&lt;/strong&gt; , one directory per session: &lt;strong&gt;pending.json, decision.json, inbox, waiter.pid&lt;/strong&gt;. Writes are atomic renames; the inbox is taken with a rename so exactly one waiter gets each message. Polling is once a second. There is no daemon and nothing listens on the network.&lt;/p&gt;
&lt;p&gt;Which sessions exist, and whether each is idle, busy or waiting, comes from Claude Code’s own registry in &lt;strong&gt;~/.claude/sessions/&lt;/strong&gt;. What a session is doing comes from its transcript file. &lt;strong&gt;ccb ls&lt;/strong&gt; and &lt;strong&gt;ccb show&lt;/strong&gt; are just readers for those two things.&lt;/p&gt;
&lt;h5 id=&quot;3-the-relay-session&quot;&gt;3. The relay session&lt;/h5&gt;
&lt;p&gt;When a request has waited 15 seconds without a local answer, the hook starts the relay in &lt;strong&gt;tmux&lt;/strong&gt; (simplified):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;claude --model haiku --tools AskUserQuestion --remote-control &quot;Approval - Prod deploy - infra&quot; \
       --append-system-prompt &quot;&amp;lt;relay instructions&amp;gt;&quot; --settings '&amp;lt;two hooks&amp;gt;' &quot;&amp;lt;the request&amp;gt;&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A few things about that line matter:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;It runs on my Claude login&lt;/em&gt;&lt;/strong&gt; , with the provider variables ( &lt;strong&gt;CLAUDE_CODE_USE_BEDROCK, …_VERTEX, …_FOUNDRY&lt;/strong&gt; ) stripped, so Remote Control is available.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;It has exactly one tool&lt;/em&gt;&lt;/strong&gt; , &lt;strong&gt;AskUserQuestion&lt;/strong&gt;. It cannot read files or run commands. Its whole job is to turn the request into a native question in the Claude app.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;The model never decides anything&lt;/em&gt;&lt;/strong&gt;. A &lt;strong&gt;PostToolUse&lt;/strong&gt; hook on the relay reads the answer I tapped and writes the decision file itself. Only the exact Approve label counts as approval; anything else — Reject, free text, a typo — is a rejection.&lt;/p&gt;
&lt;p&gt;There is one relay per bridged session and it stays open, so the conversation on the phone becomes a readable history: what was asked, what I answered, in order. Its title follows the topic of the latest request.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/1024/1*4Ml62MYPo5-AXFGd5cOE7Q.png&quot; alt=&quot;In the Claude mobile app: a blocked permission request from a Bedrock session arrives as a native Approve/Reject prompt, and a two-way conversation with a Vertex session where an AskUserQuestion is answered by option number.&quot;&gt;&lt;br&gt;
&lt;em&gt;In the Claude mobile app: a blocked permission request from a Bedrock session arrives as a native Approve/Reject prompt, and a two-way conversation with a Vertex session where an AskUserQuestion is answered by option number.&lt;/em&gt;&lt;/p&gt;
&lt;h5 id=&quot;questions-and-why-answers-are-mapped-by-position&quot;&gt;Questions, and why answers are mapped by position&lt;/h5&gt;
&lt;p&gt;When the bridged session calls &lt;strong&gt;AskUserQuestion&lt;/strong&gt; , the relay asks the same question with the same options. Early on I noticed the small relay model sometimes shortened the option text. For a question like “upgrade prod now?” that is not a detail I wanted to leave to chance.&lt;/p&gt;
&lt;p&gt;So the relay hook doesn’t forward the label I tapped. It finds the position of my choice among the options the relay showed and maps it onto the option at the same position in the original question. The wording on the phone can drift; the answer cannot. The original text is always in the message right above the prompt.&lt;/p&gt;
&lt;h5 id=&quot;a-two-way-conversation&quot;&gt;A two-way conversation&lt;/h5&gt;
&lt;p&gt;Approvals were the starting point, but once the relay existed the next step was obvious. The relay has a &lt;strong&gt;UserPromptSubmit&lt;/strong&gt; hook: anything I type into that conversation that isn’t one of ccBridger’s own messages is put into the session’s inbox instead of being answered by the relay model. The waiter delivers it. When the session finishes its turn, its Stop hook pastes the final message back into the relay.&lt;/p&gt;
&lt;p&gt;So from the phone I can write “ &lt;strong&gt;&lt;em&gt;Is the upgrade done? Are all the filters working?&lt;/em&gt;&lt;/strong&gt; ” and get the real session’s answer in the same thread. If the session is busy, I’m told so, along with what it is doing right now and that my message is queued.&lt;/p&gt;
&lt;h5 id=&quot;teams-one-cloud-account-many-people&quot;&gt;Teams: one cloud account, many people&lt;/h5&gt;
&lt;p&gt;API access is often shared across a team — one AWS account, one GCP project, one Azure resource. The bridge is not shared, and that falls out of the design rather than being added to it:&lt;/p&gt;
&lt;p&gt;Every developer &lt;strong&gt;installs&lt;/strong&gt;  &lt;strong&gt;ccBridger on their own machine&lt;/strong&gt;. State lives under their own &lt;strong&gt;~/.claude&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The relay runs on that person’s own Claude login, so prompts land only in their Claude app. Nobody can see or answer anyone else’s.&lt;/p&gt;
&lt;p&gt;There is nothing central to run, patch or secure.&lt;/p&gt;
&lt;p&gt;For anything beyond the app, each person can set a &lt;strong&gt;notify_cmd&lt;/strong&gt; in their config — a shell command that runs once per request with the title and body in its environment. That covers Slack, ntfy or a pager, per user. People without a Claude subscription can turn the relay off and answer with &lt;strong&gt;ccb ok&lt;/strong&gt; over SSH.&lt;/p&gt;
&lt;h5 id=&quot;this-isn-t-just-my-problem-the-open-requests-it-answers&quot;&gt;This isn’t just my problem — the open requests it answers&lt;/h5&gt;
&lt;p&gt;I didn’t invent this gap. It’s one of the most-upvoted things on the Claude Code issue tracker. ccBridger doesn’t fix Claude Code — it’s a parallel sidecar, not a product change — but it covers the day-to-day need in these threads. Honestly, and partially:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/anthropics/claude-code/issues/28795&quot;&gt;&lt;strong&gt;#28795 — Bedrock + AWS SSO in Remote Control&lt;/strong&gt;&lt;/a&gt;. The ask: enterprise users on &lt;strong&gt;CLAUDE_CODE_USE_BEDROCK=1&lt;/strong&gt; + AWS SSO want &lt;strong&gt;Remote Control&lt;/strong&gt; without a separate Claude subscription. Signal: 131 , 13 comments — the flagship request&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;→ ccBridger&lt;/strong&gt; : &lt;strong&gt;Partially&lt;/strong&gt; delivers the everyday capability (approve/answer/message a Bedrock session from the phone) through hooks + a relay — different mechanism, not native decoupled auth.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/anthropics/claude-code/issues/90606&quot;&gt;&lt;strong&gt;#90606 — Permission dialog hangs the host terminal&lt;/strong&gt;&lt;/a&gt;. The ask: a permission prompt with no one at the keyboard blocks the whole session indefinitely. Signal: lower volume, but exactly on point.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;→ ccBridger:&lt;/strong&gt;  &lt;strong&gt;Solves&lt;/strong&gt; it. This is the flagship feature — after 15 seconds with no local answer, the prompt is on your phone, and the terminal stays live the whole time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/anthropics/claude-code/issues/35637&quot;&gt;&lt;strong&gt;#35637 — Permission prompts don’t render on mobile&lt;/strong&gt;&lt;/a&gt;. The ask: Remote Control shows the session but the actual Approve/Reject prompt never appears on the phone. Signal: 30 , 23 comments.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;→ ccBridger: Solves&lt;/strong&gt; the symptom. API-provider prompts arrive as a native Approve/Reject card — only the exact Approve label counts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/anthropics/claude-code/issues/28508&quot;&gt;&lt;strong&gt;#28508 — Mobile AskUserQuestion answer doesn’t return to the CLI&lt;/strong&gt;&lt;/a&gt;. The ask: you tap an answer on the phone and the terminal never receives it. Signal: 27 , 19 comments.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;→ ccBridger: Solves&lt;/strong&gt; the symptom. The answer is mapped back by position, so the wording can drift on the phone but the choice can’t.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/anthropics/claude-code/issues/95744&quot;&gt;&lt;strong&gt;#95744 — Non-Anthropic provider + Remote Control in one session.&lt;/strong&gt;&lt;/a&gt; The ask: one session that is both on an API provider and remote-controllable. Signal: newer, growing.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;→ ccBridger:&lt;/strong&gt; This is the whole architectural thesis — ccBridger splits those two jobs into two processes instead of forcing one session to do both.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Two honest caveats that belong right here, not buried: &lt;strong&gt;&lt;em&gt;ccBridger doesn’t remove the subscription requirement &lt;/em&gt;&lt;/strong&gt; — it moves it to a second Claude login on the same machine (the relay). And it’s &lt;strong&gt;macOS/Linux + tmux&lt;/strong&gt; , not Windows, and ZDR/compliance setups are out of scope. If you can’t run a Claude login at all, you can turn the relay off and answer with &lt;strong&gt;ccb ok&lt;/strong&gt; over SSH, or wire a &lt;strong&gt;notify_cmd&lt;/strong&gt; to Slack/ntfy/a pager.&lt;/p&gt;
&lt;h5 id=&quot;getting-started&quot;&gt;Getting started&lt;/h5&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;git clone https://github.com/fxerkan/ccbridger.git &amp;amp;&amp;amp; cd ccbridger
ln -s &quot;$PWD/ccbridger&quot; ~/.local/bin/ccbridger
ln -s &quot;$PWD/ccbridger&quot; ~/.local/bin/ccb # short alias
ccb selftest

ccb install --global # every Bedrock / Vertex / Foundry session
# or: ccb install ~/code/project-a ~/code/project-b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;--global&lt;/strong&gt; stays out of the way of sessions that already run on a Claude login. Restart the sessions you want bridged, and that’s it. From any terminal:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;ccb ls # sessions, status, what is pending
ccb show infra # what that session has been doing
ccb ok infra # approve · ccb no infra &quot;not on prod&quot;
ccb answer infra 1 # answer a question by option number
ccb send infra &quot;run the tests again and summarise the failures&quot;
ccb open infra # open the phone conversation without waiting for a request
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;what-i-learned-building-it&quot;&gt;What I learned building it&lt;/h5&gt;
&lt;p&gt;A few things only showed up once it met real sessions:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A hook is not killed when you answer locally.&lt;/strong&gt; The PermissionRequest hook kept waiting after I pressed Enter in the terminal, so requests looked pending forever. It now watches the session’s status and leaves when the session stops waiting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pressing Enter in the wrong place approves things.&lt;/strong&gt; The relay is driven through tmux. Sending Enter while a question is on screen selects the first option — Approve. The code checks what is on screen before it sends a key, and a second hook process for the same request is not allowed to ask twice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Text pasted too early disappears.&lt;/strong&gt; A follow-up request pasted into the relay while it was still finishing the previous one was silently lost. It now waits until the relay is idle.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;My own test sessions reached my phone.&lt;/strong&gt; They ran on my login, so their prompts showed up in my app and I answered one without knowing what it was. For a while I blamed Claude Code for “ignoring” an answer that I had, in fact, overridden myself.&lt;/p&gt;
&lt;h5 id=&quot;honest-limits&quot;&gt;Honest limits&lt;/h5&gt;
&lt;p&gt;A session started with -- &lt;strong&gt;dangerously-skip-permissions&lt;/strong&gt; never asks, so there is nothing to approve. Watching and messaging still work.&lt;/p&gt;
&lt;p&gt;Only the last message of a turn comes back to the phone, not every step.&lt;/p&gt;
&lt;p&gt;Answers to questions reach the session as text; in the terminal that shows up as a denied tool call followed by the session carrying on with your answer.&lt;/p&gt;
&lt;p&gt;It depends on things Claude Code doesn’t promise to keep stable: the session registry, the hook behaviour, a few strings on the terminal screen. A future release can break it. The built-in self-test covers the queue logic, not the live integration.&lt;/p&gt;
&lt;p&gt;Developed and tested on macOS, with live sessions on AWS Bedrock. Vertex AI and Foundry go through the same hooks and are detected the same way, but I haven’t run live sessions on them yet. Linux should work; I haven’t tried it either.&lt;/p&gt;
&lt;h5 id=&quot;why-this-matters&quot;&gt;Why this matters&lt;/h5&gt;
&lt;p&gt;Permission prompts are the part of agent tooling that keeps a human in the loop. The moment they become an obstacle, people remove them. I would rather make saying yes or no cost ten seconds from wherever I am than choose between an agent that waits all afternoon and one that never asks.&lt;/p&gt;
&lt;p&gt;The whole thing is one Python file, MIT-licensed, with no dependencies. Read it, run the self-test, and watch the network: there is nothing to see there.&lt;/p&gt;
&lt;h5 id=&quot;links&quot;&gt;Links&lt;/h5&gt;
&lt;p&gt;⭐ GitHub: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/fxerkan/ccbridger&quot;&gt;github.com/fxerkan/ccbridger&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; Install: &lt;strong&gt;git clone · ln -s · ccb install — global&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If this was useful, a ⭐ on GitHub helps other people who are stuck at the same prompt find it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Developed by &lt;a rel=&quot;nofollow&quot; href=&quot;https://fxerkan.com&quot;&gt;FXerkan&lt;/a&gt; —  &lt;strong&gt;&lt;em&gt;Code more, worry less.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/29732/remote-control-based-claude-code-approve-bedrock-vertex-foundry-sessions-from-your-phone</guid>
<pubDate>Sun, 04 Oct 2026 14:13:45 +0000</pubDate>
</item>
<item>
<title>ChatGPT, Claude, Gemini, or Cursor? Which AI Tool Is Your Go-To and Why?</title>
<link>https://coderlegion.com/29013/chatgpt-claude-gemini-or-cursor-which-ai-tool-is-your-go-to-and-why</link>
<description>&lt;h2 id=&quot;chatgpt-claude-gemini-or-cursor-which-ai-tool-is-your-go-to-and-why-&quot;&gt;ChatGPT, Claude, Gemini, or Cursor? Which AI Tool Is Your Go-To and Why?&lt;/h2&gt;
&lt;p&gt;Hey CodeLegion community! 💻&lt;/p&gt;
&lt;p&gt;Whether you are debugging complex codebases, writing technical documentation, exploring new frameworks, or just trying to automate daily workflows, AI tools have become an essential part of the modern developer's toolkit.&lt;/p&gt;
&lt;p&gt;With models and assistants constantly updating, everyone in tech seems to have their own preferred setup. We want to know: &lt;strong&gt;Which AI tool gets the most mileage in your stack, and why?&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;the-developer-s-usual-suspects&quot;&gt;The Developer's Usual Suspects&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Claude:&lt;/strong&gt; Loved by engineers for its natural prose, ability to digest massive code repositories or specs in a single prompt, and clean code generation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ChatGPT:&lt;/strong&gt; The reliable all-rounder for architecture advice, algorithm troubleshooting, general problem-solving, and quick scripts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cursor / GitHub Copilot:&lt;/strong&gt; Integrated directly into the IDE for real-time code completion, inline refactoring, and multi-file contextual edits.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gemini:&lt;/strong&gt; Great for real-time web search, large context windows, and tight integration across Google Workspace apps and cloud workflows.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Perplexity:&lt;/strong&gt; The go-to search companion for looking up API documentation, library updates, and technical research with cited sources.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4 id=&quot;join-the-discussion-&quot;&gt;Join the Discussion!&lt;/h4&gt;
&lt;p&gt;We’d love to hear from the legion. Drop your thoughts in the comments below:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;What is your primary AI tool for work or personal projects?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What technical task do you use it for most (coding, debugging, architecture, documentation)?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What is the one killer feature or model capability that keeps you using it?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/29013/chatgpt-claude-gemini-or-cursor-which-ai-tool-is-your-go-to-and-why</guid>
<pubDate>Tue, 29 Sep 2026 08:04:49 +0000</pubDate>
</item>
<item>
<title>97% of what my coding agent billed for was re-reading its own context</title>
<link>https://coderlegion.com/28909/97-of-what-my-coding-agent-billed-for-was-re-reading-its-own-context</link>
<description>&lt;p&gt;Token counters tell you how much you spent. I wanted a different number: &lt;strong&gt;how much of what I paid for was new text the model actually produced.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So I measured it against a complete local log corpus of my own agentic coding work: &lt;strong&gt;722 sessions, 150,902 model calls, 34.56 billion tokens.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By tokens billed:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Token class &lt;/th&gt;&lt;th&gt;Share of all tokens&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Cache read (re-reading context) &lt;/td&gt;&lt;td&gt;97.05%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Cache write (storing context) &lt;/td&gt;&lt;td&gt;2.57%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Output (generation) &lt;/td&gt;&lt;td&gt;0.38%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Fresh input &lt;/td&gt;&lt;td&gt;0.01%&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For every token the models produced, roughly &lt;strong&gt;256 tokens of cached context were read back in.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Cache pricing softens that ratio, but not the conclusion. Under published per-token list rates:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Category &lt;/th&gt;&lt;th&gt;Share of cost&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Re-reading context &lt;/td&gt;&lt;td&gt;55.89%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Writing context to cache &lt;/td&gt;&lt;td&gt;31.89%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Generating new text &lt;/td&gt;&lt;td&gt;12.18%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Fresh input &lt;/td&gt;&lt;td&gt;0.04%&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Context handling 87.8%, generation 12.2%.&lt;/strong&gt; Re-reading context alone costs &lt;strong&gt;4.59x&lt;/strong&gt; as much as everything the models wrote. And cache writing is not a rounding error: at 31.89% it is the second-largest line, larger than generation. Caching does not make context free, it moves part of the price to the moment state is stored.&lt;/p&gt;
&lt;h3 id=&quot;why-it-looks-like-this&quot;&gt;Why it looks like this&lt;/h3&gt;
&lt;p&gt;An agent doesn't send a fresh question on every step. It sends the whole conversation so far: instructions, every file it read, every command it ran. Then it adds one step and sends everything again. A token that enters the context on step 1 of a 60-step run is paid for 60 times.&lt;/p&gt;
&lt;p&gt;I put a number on that with a derived measure, &lt;strong&gt;input amplification&lt;/strong&gt;: total input tokens billed in a session, divided by that session's peak context size. Across the 590 sessions with at least three model calls, the median is &lt;strong&gt;23.7x&lt;/strong&gt;, the 90th percentile &lt;strong&gt;124.5x&lt;/strong&gt;, the maximum &lt;strong&gt;4,182x&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The median session pays for its peak working state about 24 times. One session in ten pays for it more than 125 times. A session's cost is not mainly set by how big its context is, nor by how much it writes, but by the product of context size and how many times that context gets traversed.&lt;/p&gt;
&lt;p&gt;Cost is also concentrated: an estimated 80% of the corpus total falls on 21 of 722 sessions (2.9%), and sessions longer than 200 model calls - 8% of sessions - account for an estimated 92.8% of spend.&lt;/p&gt;
&lt;h3 id=&quot;the-part-you-can-actually-change&quot;&gt;The part you can actually change&lt;/h3&gt;
&lt;p&gt;None of the above is a knob. How often you clear the context is.&lt;/p&gt;
&lt;p&gt;I ran a controlled comparison: twelve fixed programming tasks under six context-clearing policies - a fresh session every 1, 2, 3, 4, 6 and 12 tasks - six replicates each, with the model, the tasks and their order held constant. 36 runs.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Clear after every &lt;/th&gt;&lt;th&gt;Mean modeled cost per run&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;1 task &lt;/td&gt;&lt;td&gt;$2.165&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2 tasks &lt;/td&gt;&lt;td&gt;$1.854&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;3 tasks&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;&lt;strong&gt;$1.622&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;4 tasks &lt;/td&gt;&lt;td&gt;$1.704&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;6 tasks &lt;/td&gt;&lt;td&gt;$1.679&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;12 tasks (never) &lt;/td&gt;&lt;td&gt;$1.780&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Cost is not monotone in session length. It falls, bottoms out at three tasks, then rises again.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clearing after &lt;strong&gt;every&lt;/strong&gt; task costs &lt;strong&gt;33.5%&lt;/strong&gt; more than clearing every third (p = 0.0022, Holm-adjusted 0.011).&lt;/li&gt;
&lt;li&gt;Every second task: &lt;strong&gt;+14.3%&lt;/strong&gt; (p = 0.0022, Holm 0.011).&lt;/li&gt;
&lt;li&gt;Going from clearing every task to every third cuts cost by &lt;strong&gt;25.1%&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The reason the constant-clearing end is expensive: a cache write costs &lt;strong&gt;20x&lt;/strong&gt; a cache read. Clear after every task and you keep paying to rebuild state you just threw away. At the optimum the spend splits 39.0% cache read, 32.3% cache write, 28.7% output.&lt;/p&gt;
&lt;p&gt;Two things I want to state plainly rather than round off:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The middle is a plateau, not a point.&lt;/strong&gt; Every fourth task is +5.1% against every third (p = 0.17), every sixth +3.5% (p = 0.45). The data cannot separate 3 from 4 or 6. &quot;Clear every few tasks&quot; is the finding; &quot;clear every third&quot; is just where the observed minimum landed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Never clearing is not significantly worse.&lt;/strong&gt; It comes out +9.7% against every third, p = 0.046, Holm-adjusted 0.14. An earlier version of this work claimed both extremes were significantly more expensive than the optimum. That claim is withdrawn for never clearing.&lt;/p&gt;
&lt;h3 id=&quot;measuring-it-yourself&quot;&gt;Measuring it yourself&lt;/h3&gt;
&lt;p&gt;I packaged the measurement as a small open-source tool, &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/arsentev-ai/contextburn&quot;&gt;contextburn&lt;/a&gt;. It reads the transcripts your agent already writes on your machine and makes no network calls.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pip install contextburn
contextburn detail 24
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It also runs as an MCP server, so the agent can check its own efficiency mid-session:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;claude mcp add contextburn -- uvx contextburn mcp
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;two-traps-in-case-you-write-your-own-counter&quot;&gt;Two traps, in case you write your own counter&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. Streaming logs record the same model call more than once.&lt;/strong&gt; An early snapshot and a final record share one message id. Count both and you double the call; keep only the first and you halve the output. Take the element-wise maximum per message id.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Prices change the answer, and they will change yours.&lt;/strong&gt; Both datasets behind this post were re-published with corrected costs, and the errors were mine. Cache reads had been priced at a rate that applies only to a newer model, and every cache write had been priced at the 5-minute rate when the logs show mostly 1-hour writes, billed at 2x input rather than 1.25x. Token counts, call counts and the composition table did not move at all. Every dollar figure did: the corpus split went from 83.5% / 16.5% to the &lt;strong&gt;87.8% / 12.2%&lt;/strong&gt; above. If you report a cost-weighted share, it is only as current as your price table - and worth re-deriving before you quote it anywhere.&lt;/p&gt;
&lt;h3 id=&quot;limits&quot;&gt;Limits&lt;/h3&gt;
&lt;p&gt;This is a single-practitioner case study, not a sample of a population, and the dollar figures are a model applied to logs rather than an invoice.&lt;/p&gt;
&lt;p&gt;Cache-write duration cannot be verified for part of one machine's logs. If every write were instead a 5-minute write, the corpus split would be 86.2% / 13.8% - the direction holds under every assumption I can test, only the size moves.&lt;/p&gt;
&lt;p&gt;In the controlled runs, &quot;no test failures&quot; means tests the agent wrote itself, and the count differed by condition: 116.8 tests per run on average when clearing after every task, 106.8 when never clearing. The three-task reference condition was selected after the fact, as the observed minimum.&lt;/p&gt;
&lt;p&gt;I'd like to see the same measurement run against other people's logs.&lt;/p&gt;
&lt;h3 id=&quot;the-data&quot;&gt;The data&lt;/h3&gt;
&lt;p&gt;Report, datasets and recomputation scripts are public:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Corpus report and dataset: &lt;a rel=&quot;nofollow&quot; href=&quot;https://doi.org/10.5281/zenodo.22759216&quot;&gt;10.5281/zenodo.22759216&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Peer-reviewed report: &lt;a rel=&quot;nofollow&quot; href=&quot;https://doi.org/10.32388/0BV3Z8&quot;&gt;10.32388/0BV3Z8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Context-clearing experiment, 36 runs: &lt;a rel=&quot;nofollow&quot; href=&quot;https://doi.org/10.5281/zenodo.22759217&quot;&gt;10.5281/zenodo.22759217&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Evgenii Arsentev, PhD - Chief Executive Officer. I measure how AI agents spend money, and publish the data and the scripts. More at &lt;a rel=&quot;nofollow&quot; href=&quot;https://arsentev.ai&quot;&gt;arsentev.ai&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/28909/97-of-what-my-coding-agent-billed-for-was-re-reading-its-own-context</guid>
<pubDate>Mon, 28 Sep 2026 11:37:39 +0000</pubDate>
</item>
<item>
<title>GoGraph updates, Providing Structural Awareness to AI Coding Agents in Go.</title>
<link>https://coderlegion.com/26640/gograph-updates-providing-structural-awareness-to-ai-coding-agents-in-go</link>
<description>&lt;p&gt;&lt;strong&gt;GoGraph Four Months Later: From Repository Map to Evidence Layer for AI Coding Agents&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A few months ago, I wrote about a problem I kept seeing with AI coding agents: they could write Go perfectly well, but before doing anything useful they spent a surprising amount of their context window trying to understand the repository.&lt;/p&gt;
&lt;p&gt;They would grep for symbols, guess filenames, read large files, follow imports manually, and slowly reconstruct relationships that the Go compiler already knows.&lt;/p&gt;
&lt;p&gt;That was the motivation behind &lt;strong&gt;GoGraph&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The first version I wrote about in May was relatively simple in concept: parse a Go repository, turn its structure into a graph, and expose that graph to coding agents through CLI commands and MCP.&lt;/p&gt;
&lt;p&gt;The basic idea has not changed.&lt;/p&gt;
&lt;p&gt;But &lt;strong&gt;GoGraph&lt;/strong&gt; itself has changed quite a lot.&lt;/p&gt;
&lt;p&gt;Today, I would describe it less as a static repository map and more as a local evidence layer between a Go codebase and an AI coding agent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Original Model: Give the Agent a Map&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The first version concentrated heavily on AST-based structural analysis.&lt;/p&gt;
&lt;p&gt;GoGraph parsed source code and extracted things such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;packages&lt;/li&gt;
&lt;li&gt;functions and methods&lt;/li&gt;
&lt;li&gt;imports&lt;/li&gt;
&lt;li&gt;calls&lt;/li&gt;
&lt;li&gt;interfaces and implementations&lt;/li&gt;
&lt;li&gt;HTTP routes&lt;/li&gt;
&lt;li&gt;tests&lt;/li&gt;
&lt;li&gt;SQL-related structures&lt;/li&gt;
&lt;li&gt;error paths&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Commands such as plan, review, and errorflow were intended to answer practical questions before and after an agent edited code.&lt;/p&gt;
&lt;p&gt;Instead of:&lt;/p&gt;
&lt;p&gt;grep&lt;br&gt;
rg&lt;br&gt;
awk&lt;br&gt;
sed&lt;br&gt;
read file&lt;br&gt;
grep again&lt;br&gt;
read another file&lt;br&gt;
guess&lt;/p&gt;
&lt;p&gt;the agent could ask GoGraph for a bounded structural answer.&lt;/p&gt;
&lt;p&gt;That is still useful, and the AST layer still exists.&lt;/p&gt;
&lt;p&gt;The limitation is that Go is not completely understandable from syntax alone.&lt;/p&gt;
&lt;p&gt;Consider this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Store interface {
    Save(User) error
}
func Create(s Store, u User) error {
    return s.Save(u)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From the AST, we know that Create calls Store.Save.&lt;/p&gt;
&lt;p&gt;But that does not necessarily tell us which concrete Save implementation executes.&lt;/p&gt;
&lt;p&gt;That becomes increasingly important once an agent starts reasoning about impact rather than simply locating code.&lt;/p&gt;
&lt;p&gt;GoGraph Now Has a Precision Layer&lt;/p&gt;
&lt;p&gt;The largest architectural change is that GoGraph no longer relies only on syntactic relationships.&lt;/p&gt;
&lt;p&gt;Precise builds now use Go’s type information together with go/packages, go/types, SSA, and Class Hierarchy Analysis.&lt;/p&gt;
&lt;p&gt;The result is effectively a two-layer model.&lt;/p&gt;
&lt;p&gt;The AST layer remains fast, resilient, and useful even when a repository cannot be fully type-checked.&lt;/p&gt;
&lt;p&gt;The precision layer adds compiler-aware relationships when the repository can be successfully loaded.&lt;/p&gt;
&lt;p&gt;This matters particularly for interfaces.&lt;/p&gt;
&lt;p&gt;An AST-level analysis might know that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;service -&amp;gt; Repository.Save
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Type-aware analysis can identify actual implementations of that interface.&lt;/p&gt;
&lt;p&gt;SSA analysis can sometimes go further and prove that a particular interface value contains one concrete implementation at a call site.&lt;/p&gt;
&lt;p&gt;GoGraph deliberately distinguishes those cases.&lt;/p&gt;
&lt;p&gt;A call that is proven receives different treatment from a call that is merely a possible dynamic dispatch target.&lt;/p&gt;
&lt;p&gt;That distinction turned out to be important for agents.&lt;/p&gt;
&lt;p&gt;An AI should not see:&lt;/p&gt;
&lt;p&gt;A calls B&lt;/p&gt;
&lt;p&gt;when what the analysis actually knows is:&lt;/p&gt;
&lt;p&gt;A may call B&lt;/p&gt;
&lt;p&gt;Those are different facts.&lt;/p&gt;
&lt;p&gt;Exact and Possible Relationships&lt;/p&gt;
&lt;p&gt;This led to another change in the graph model.&lt;/p&gt;
&lt;p&gt;Relationships now carry more information about how strongly GoGraph knows them.&lt;/p&gt;
&lt;p&gt;For example, paths can contain relationships that are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;exact&lt;/li&gt;
&lt;li&gt;ambiguous&lt;/li&gt;
&lt;li&gt;possible&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Commands can request exact-only results when an agent needs a conservative answer.&lt;/p&gt;
&lt;p&gt;When several possible paths exist, GoGraph also ranks them deterministically rather than returning whichever traversal happens to find first.&lt;/p&gt;
&lt;p&gt;The preference is roughly toward:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;stronger evidence&lt;/li&gt;
&lt;li&gt;shorter paths&lt;/li&gt;
&lt;li&gt;production code rather than tests&lt;/li&gt;
&lt;li&gt;typed resolution rather than heuristics&lt;/li&gt;
&lt;li&gt;fewer cross-repository transitions&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This sounds like an implementation detail, but it changes agent behavior substantially.&lt;/p&gt;
&lt;p&gt;Determinism is useful when an LLM repeatedly asks the same structural question during planning, editing, and review. The answer should not change merely because map iteration order changed.&lt;/p&gt;
&lt;p&gt;A First-Call Tool for Agents&lt;/p&gt;
&lt;p&gt;One problem became obvious after using GoGraph with actual coding agents.&lt;/p&gt;
&lt;p&gt;Even with dozens of specialized commands, the agent first has to know which command to use.&lt;/p&gt;
&lt;p&gt;So GoGraph now has explore.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gograph explore &quot;authentication middleware&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or through MCP, gograph_explore.&lt;/p&gt;
&lt;p&gt;It performs bounded lexical discovery and, when a symbol can be selected unambiguously, combines several kinds of context into one response:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;matching symbols&lt;/li&gt;
&lt;li&gt;source location&lt;/li&gt;
&lt;li&gt;direct callers&lt;/li&gt;
&lt;li&gt;direct callees&lt;/li&gt;
&lt;li&gt;tests&lt;/li&gt;
&lt;li&gt;upstream impact&lt;/li&gt;
&lt;li&gt;package context&lt;/li&gt;
&lt;li&gt;deeper call relationships when requested&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are compact and deep modes.&lt;/p&gt;
&lt;p&gt;This is deliberately not semantic RAG.&lt;/p&gt;
&lt;p&gt;GoGraph does not pretend that it “understands” a natural-language question. It tokenizes the query deterministically, finds structural candidates, and reports how the selection was made.&lt;/p&gt;
&lt;p&gt;If a symbol is ambiguous, it exposes the ambiguity instead of silently picking one.&lt;/p&gt;
&lt;p&gt;That is an important design rule throughout the newer versions of GoGraph:&lt;/p&gt;
&lt;p&gt;Uncertainty should be data, not something hidden by the tool.&lt;/p&gt;
&lt;p&gt;From Repository Analysis to Change Analysis&lt;/p&gt;
&lt;p&gt;The original plan idea answered:&lt;/p&gt;
&lt;p&gt;What could be affected if I modify this symbol?&lt;/p&gt;
&lt;p&gt;That is useful before editing.&lt;/p&gt;
&lt;p&gt;But after an agent has changed the repository, the more interesting question is:&lt;/p&gt;
&lt;p&gt;What did I actually change, and what does that change affect?&lt;/p&gt;
&lt;p&gt;GoGraph now performs declaration-level change analysis against Git references and the working tree.&lt;/p&gt;
&lt;p&gt;It distinguishes things such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;edited declarations&lt;/li&gt;
&lt;li&gt;added declarations&lt;/li&gt;
&lt;li&gt;removed declarations&lt;/li&gt;
&lt;li&gt;excluded declarations&lt;/li&gt;
&lt;li&gt;changes that cannot be evaluated reliably&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Untracked Go files are included when looking at working-tree changes.&lt;/p&gt;
&lt;p&gt;This also avoids a surprisingly dangerous failure mode.&lt;/p&gt;
&lt;p&gt;Imagine the agent deletes a function.&lt;/p&gt;
&lt;p&gt;Looking only at the current graph cannot tell you who called the deleted function, because the function no longer exists.&lt;/p&gt;
&lt;p&gt;Change analysis therefore needs historical evidence from the baseline rather than pretending the current graph contains enough information.&lt;/p&gt;
&lt;p&gt;When GoGraph does not have enough evidence to calculate an impact safely, newer versions prefer to report that the evaluation is incomplete rather than returning an empty impact set.&lt;/p&gt;
&lt;p&gt;For AI tooling, “I cannot prove this” is much safer than “nothing is affected.”&lt;/p&gt;
&lt;p&gt;Graph Freshness Became a First-Class Concept&lt;/p&gt;
&lt;p&gt;Another thing I underestimated in the original version was graph freshness.&lt;/p&gt;
&lt;p&gt;A perfectly accurate graph of yesterday’s checkout is still the wrong answer.&lt;/p&gt;
&lt;p&gt;GoGraph now tracks graph state explicitly.&lt;/p&gt;
&lt;p&gt;Results can distinguish:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;persisted vs. in-memory graph&lt;/li&gt;
&lt;li&gt;current vs. stale graph&lt;/li&gt;
&lt;li&gt;complete vs. partial parsing&lt;/li&gt;
&lt;li&gt;AST vs. precise vs. precision-fallback analysis&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MCP can refresh stale graphs automatically.&lt;/p&gt;
&lt;p&gt;If precise enrichment fails but AST analysis succeeds, GoGraph can return the fresh AST result while explicitly saying that precise analysis failed.&lt;/p&gt;
&lt;p&gt;If refreshing itself fails, it can retain the last trusted graph while exposing that it is stale.&lt;/p&gt;
&lt;p&gt;The important part is that these states are not collapsed into one vague “success.”&lt;/p&gt;
&lt;p&gt;For an AI agent, provenance matters.&lt;/p&gt;
&lt;p&gt;There is a substantial difference between:&lt;/p&gt;
&lt;p&gt;No callers found.&lt;/p&gt;
&lt;p&gt;and:&lt;/p&gt;
&lt;p&gt;No callers found.&lt;br&gt;
Graph: current.&lt;br&gt;
Analysis: precise.&lt;br&gt;
Parsing: complete.&lt;/p&gt;
&lt;p&gt;There is an even larger difference between that and:&lt;/p&gt;
&lt;p&gt;No callers found.&lt;br&gt;
Graph: stale.&lt;br&gt;
Analysis: AST fallback.&lt;/p&gt;
&lt;p&gt;The model should be allowed to reason differently about those answers.&lt;/p&gt;
&lt;p&gt;Large Results Are Now Explicitly Bounded&lt;/p&gt;
&lt;p&gt;Token efficiency was the original reason I created GoGraph, so there is an obvious irony if a structural query returns a 200 KB JSON response.&lt;/p&gt;
&lt;p&gt;Newer GoGraph query APIs therefore put considerably more effort into bounded output.&lt;/p&gt;
&lt;p&gt;Large result sets use deterministic pagination and expose information such as:&lt;/p&gt;
&lt;p&gt;total&lt;br&gt;
returned&lt;br&gt;
truncated&lt;br&gt;
next_cursor&lt;/p&gt;
&lt;p&gt;The cursor is tied to the graph snapshot and query selection, so it cannot silently continue over a different graph after the repository changes.&lt;/p&gt;
&lt;p&gt;MCP output also has an explicit response-size budget.&lt;/p&gt;
&lt;p&gt;This is not merely an API optimization.&lt;/p&gt;
&lt;p&gt;A tool built for LLMs needs to consider context consumption as part of its interface design.&lt;/p&gt;
&lt;p&gt;Traditional developer tooling often assumes:&lt;/p&gt;
&lt;p&gt;Returning more information is better.&lt;/p&gt;
&lt;p&gt;Agent tooling often has the opposite requirement:&lt;/p&gt;
&lt;p&gt;Return the smallest amount of information that preserves the evidence required for the decision.&lt;/p&gt;
&lt;p&gt;Better Test Reasoning&lt;/p&gt;
&lt;p&gt;Test discovery has also moved beyond simply asking whether a symbol name appears in a _test.go file.&lt;/p&gt;
&lt;p&gt;GoGraph can now trace tests transitively through call relationships and distinguish exact test coverage paths from possible ones.&lt;/p&gt;
&lt;p&gt;This becomes useful with architectures where a test reaches the target through several layers:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TestCreateUser
    -&amp;gt; handler
        -&amp;gt; service
            -&amp;gt; repository
                -&amp;gt; Save
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Router callbacks and other intermediary functions can participate in that attribution.&lt;/p&gt;
&lt;p&gt;Interface-backed test doubles are also important.&lt;/p&gt;
&lt;p&gt;GoGraph’s typed test analysis can recognize cases where a test assigns a concrete fake or mock to an interface and prove the resulting call target when the type information allows it.&lt;/p&gt;
&lt;p&gt;That makes commands such as tests and untested much more useful as structural evidence for coding agents.&lt;/p&gt;
&lt;p&gt;It still does not mean “this code is correctly tested.”&lt;/p&gt;
&lt;p&gt;That requires running the tests.&lt;/p&gt;
&lt;p&gt;It means something narrower and more defensible:&lt;/p&gt;
&lt;p&gt;These tests have a statically observable relationship to this declaration.&lt;/p&gt;
&lt;p&gt;SQL Became Structured Evidence&lt;/p&gt;
&lt;p&gt;SQL started as another useful static extraction target.&lt;/p&gt;
&lt;p&gt;It has since become a more structured query system.&lt;/p&gt;
&lt;p&gt;GoGraph can classify statically resolvable PostgreSQL statements and expose information such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;operation&lt;/li&gt;
&lt;li&gt;read/write access&lt;/li&gt;
&lt;li&gt;referenced tables&lt;/li&gt;
&lt;li&gt;access per table&lt;/li&gt;
&lt;li&gt;source location&lt;/li&gt;
&lt;li&gt;module&lt;/li&gt;
&lt;li&gt;test/production origin&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It understands more than literal strings.&lt;/p&gt;
&lt;p&gt;Statically provable local constants, variables, assignments, and bounded concatenations can also participate in SQL resolution.&lt;/p&gt;
&lt;p&gt;Dynamic SQL is intentionally not presented as if it were fully known.&lt;/p&gt;
&lt;p&gt;The result is useful for questions such as:&lt;/p&gt;
&lt;p&gt;Which code writes the oauth_clients table?&lt;/p&gt;
&lt;p&gt;or:&lt;/p&gt;
&lt;p&gt;Which production paths execute DELETE statements?&lt;/p&gt;
&lt;p&gt;Again, the goal is not to replace a SQL parser, database audit system, or runtime tracing.&lt;/p&gt;
&lt;p&gt;It is to give an agent a useful static census of evidence that exists in the repository.&lt;/p&gt;
&lt;p&gt;HTTP Relationships Also Became More Precise&lt;/p&gt;
&lt;p&gt;Route extraction existed in the original version, but HTTP reasoning has expanded.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GoGraph&lt;/strong&gt; now distinguishes constructing an HTTP request from actually proving that the request is dispatched.&lt;/p&gt;
&lt;p&gt;It can preserve statically known URL bases and suffixes.&lt;/p&gt;
&lt;p&gt;More importantly, this becomes useful in the workspace model.&lt;/p&gt;
&lt;p&gt;A repository can declare mappings between outbound HTTP client authorities and another repository in the same workspace.&lt;/p&gt;
&lt;p&gt;That allows GoGraph to represent a relationship such as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;frontend-api
    -&amp;gt; HTTP request
        -&amp;gt; identity-service
            -&amp;gt; POST /users
                -&amp;gt; CreateUser handler
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;without inventing relationships from runtime environment variables or guessed hostnames.&lt;/p&gt;
&lt;p&gt;GoGraph Can Now Analyze a Workspace&lt;/p&gt;
&lt;p&gt;This is probably the biggest conceptual expansion since the original article.&lt;/p&gt;
&lt;p&gt;Modern systems are often not one Go repository.&lt;/p&gt;
&lt;p&gt;You may have:&lt;/p&gt;
&lt;p&gt;identity-service/&lt;br&gt;
agent-service/&lt;br&gt;
gateway/&lt;br&gt;
shared-lib/&lt;/p&gt;
&lt;p&gt;Each repository has its own graph.&lt;/p&gt;
&lt;p&gt;GoGraph can now build a workspace overlay across them.&lt;/p&gt;
&lt;p&gt;The individual repository graphs remain independent. The workspace adds explicitly resolved relationships between them.&lt;/p&gt;
&lt;p&gt;These can include cross-repository Go relationships and configured HTTP relationships.&lt;/p&gt;
&lt;p&gt;The workspace can then answer questions such as:&lt;/p&gt;
&lt;p&gt;What path connects this gateway handler&lt;br&gt;
to this identity-service function?&lt;/p&gt;
&lt;p&gt;or:&lt;/p&gt;
&lt;p&gt;What repositories may be affected by this change?&lt;/p&gt;
&lt;p&gt;There is also a separate read-only workspace MCP server exposing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gograph_workspace_status
gograph_workspace_query
gograph_workspace_path
gograph_workspace_impact
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This matters because the “whole codebase” visible to an AI agent is increasingly not the same thing as a Git repository.&lt;/p&gt;
&lt;p&gt;The useful unit is often the engineering workspace.&lt;/p&gt;
&lt;p&gt;Go Build Configuration Is Part of the Graph&lt;/p&gt;
&lt;p&gt;Another source of false confidence is pretending that a Go repository has one universal structure.&lt;/p&gt;
&lt;p&gt;It often does not.&lt;/p&gt;
&lt;p&gt;Build tags, GOOS, GOARCH, GOFLAGS, cgo, go.work, generated files, and module selection can all change which source files constitute the program.&lt;/p&gt;
&lt;p&gt;GoGraph now records the effective build selection used to construct the graph.&lt;/p&gt;
&lt;p&gt;Explicit build tags are supported.&lt;/p&gt;
&lt;p&gt;If the environment used to query a persisted graph no longer matches the environment used to build it, the graph can be considered stale rather than silently mixing incompatible views of the program.&lt;/p&gt;
&lt;p&gt;That is another example of something which is easy to ignore in a developer convenience tool but important in an evidence tool.&lt;/p&gt;
&lt;p&gt;Local Does Not Automatically Mean Safe&lt;/p&gt;
&lt;p&gt;The original article emphasized that GoGraph runs locally.&lt;/p&gt;
&lt;p&gt;That remains true.&lt;/p&gt;
&lt;p&gt;But over time I became much more conservative about what “local static analysis” should be allowed to touch.&lt;/p&gt;
&lt;p&gt;The current code performs extensive path and source confinement checks.&lt;/p&gt;
&lt;p&gt;Among other things, it treats Go build inputs, module/workspace metadata, graph artifacts, and generated files carefully around symbolic links and repository boundaries.&lt;/p&gt;
&lt;p&gt;The goal is simple:&lt;/p&gt;
&lt;p&gt;Asking an AI agent to inspect an untrusted repository should not casually turn a static-analysis request into arbitrary traversal outside the intended source tree.&lt;/p&gt;
&lt;p&gt;Go tooling itself can legitimately access module caches, proxies, and toolchains, so the boundary cannot simply be “never touch anything outside the repository.”&lt;/p&gt;
&lt;p&gt;Instead, GoGraph tries to distinguish repository-controlled source authority from legitimate Go dependency resolution.&lt;/p&gt;
&lt;p&gt;This security work is considerably less visible than a new query command, but I now consider it part of the core design.&lt;/p&gt;
&lt;p&gt;MCP Is No Longer Just a Wrapper Around CLI Output&lt;/p&gt;
&lt;p&gt;MCP was already present in the original version.&lt;/p&gt;
&lt;p&gt;Its role has expanded.&lt;/p&gt;
&lt;p&gt;The project MCP server now exposes most of GoGraph’s repository analysis capabilities directly, with CLI and MCP generally sharing the same underlying result contracts.&lt;/p&gt;
&lt;p&gt;That prevents an unfortunate architecture where:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CLI implementation
       +
separate MCP implementation
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;slowly develops different semantics.&lt;/p&gt;
&lt;p&gt;The MCP server can also expose its own version and analysis capabilities, which matters because restarting an MCP process is necessary after installing a newer GoGraph binary. An already-running process does not magically inherit the new tool schema.&lt;/p&gt;
&lt;p&gt;The server still runs locally over stdio.&lt;/p&gt;
&lt;p&gt;There is no hosted GoGraph service receiving the repository.&lt;/p&gt;
&lt;p&gt;What Has Not Changed&lt;/p&gt;
&lt;p&gt;Despite all of these additions, there are several things I deliberately do not want GoGraph to become.&lt;/p&gt;
&lt;p&gt;It is not an AI model.&lt;/p&gt;
&lt;p&gt;It does not decide what code should be written.&lt;/p&gt;
&lt;p&gt;It does not replace go test.&lt;/p&gt;
&lt;p&gt;It does not replace the compiler.&lt;/p&gt;
&lt;p&gt;It does not replace runtime tracing.&lt;/p&gt;
&lt;p&gt;It does not replace semantic code search.&lt;/p&gt;
&lt;p&gt;And it should not pretend static analysis can prove runtime behavior that static analysis cannot see.&lt;/p&gt;
&lt;p&gt;I increasingly think the useful division of labor looks like this:&lt;/p&gt;
&lt;p&gt;LLM&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;reasoning
interpretation
implementation
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Semantic search / grep&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;discovery
text
configuration
documentation
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;GoGraph&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;structural evidence
relationships
impact
provenance
uncertainty
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Go compiler / tests&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;executable verification
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These tools complement each other.&lt;/p&gt;
&lt;p&gt;The Larger Lesson&lt;/p&gt;
&lt;p&gt;When I wrote the first article, I described the problem mostly as a context-window problem.&lt;/p&gt;
&lt;p&gt;I still think that is true, but I would phrase it slightly differently now.&lt;/p&gt;
&lt;p&gt;The scarce resource is not simply tokens.&lt;/p&gt;
&lt;p&gt;It is reliable context.&lt;/p&gt;
&lt;p&gt;Giving an agent 50,000 lines of source code is context.&lt;/p&gt;
&lt;p&gt;Giving it this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CreateUser
  exact caller:
    POST /api/v1/users -&amp;gt; UsersHandler.Create
  exact dependency:
    UserRepository.Insert
  database:
    INSERT -&amp;gt; users
  attributed tests:
    TestCreateUser
    TestCreateUserDuplicate
  graph:
    current
    precise
    complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is also context.&lt;/p&gt;
&lt;p&gt;But the second form has already converted a large amount of syntax into a much smaller set of claims.&lt;/p&gt;
&lt;p&gt;That is where I now see GoGraph fitting.&lt;/p&gt;
&lt;p&gt;It is not trying to make the LLM smarter.&lt;/p&gt;
&lt;p&gt;It is trying to reduce how much of the LLM’s intelligence has to be spent rediscovering facts that static analysis can provide deterministically.&lt;/p&gt;
&lt;p&gt;The original goal was to give AI coding agents a map.&lt;/p&gt;
&lt;p&gt;The current goal is slightly more demanding:&lt;/p&gt;
&lt;p&gt;Give them evidence, identify where that evidence came from, distinguish certainty from possibility, and say when the evidence is incomplete.&lt;/p&gt;
&lt;p&gt;For coding agents operating on large Go systems, I think that is a much more useful foundation.&lt;/p&gt;
&lt;p&gt;GoGraph on GitHub: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/ozgurcd/gograph&quot;&gt;https://github.com/ozgurcd/gograph&lt;/a&gt; &lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/26640/gograph-updates-providing-structural-awareness-to-ai-coding-agents-in-go</guid>
<pubDate>Wed, 09 Sep 2026 18:31:10 +0000</pubDate>
</item>
<item>
<title>Meta-Architect for AI Coding Agents</title>
<link>https://coderlegion.com/25781/meta-architect-for-ai-coding-agents</link>
<description>&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=11385886575204290620&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;
&lt;p&gt;AI coding agents can generate code quickly. The hard part is knowing whether the architecture makes sense, dependencies are real, logic holds, security was checked, and “done” is actually verified.&lt;/p&gt;

&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.producthunt.com/products/meta-architect/reviews/new?utm_source=badge-product_review&amp;amp;utm_medium=badge&amp;amp;utm_source=badge-meta-architect&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://api.producthunt.com/widgets/embed-image/v1/product_review.svg?product_id=1217323&amp;amp;theme=light&quot; alt=&quot;Meta-Architect - Codex skills for architecture and system design | Product Hunt&quot; style=&quot;width: 250px; height: 54px;&quot; width=&quot;250&quot; height=&quot;54&quot;&gt;&lt;/a&gt;
&lt;p&gt;&lt;a href=&quot;https://www.producthunt.com/products/meta-architect/launches/meta-architect?embed=true&amp;amp;utm_source=badge-featured&amp;amp;utm_medium=badge&amp;amp;utm_campaign=badge-meta-architect&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer nofollow&quot;&gt;&lt;img alt=&quot;Meta-Architect - Skills for architecture and system design | Product Hunt&quot; width=&quot;250&quot; height=&quot;54&quot; src=&quot;https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1137574&amp;amp;theme=neutral&amp;amp;t=1788059656049&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/div&gt;
&lt;h4 id=&quot;meta-architect-is-an-open-source-workflow-governor-for-ai-coding-agents-&quot;&gt;Meta-Architect is an open-source workflow governor for AI coding agents.&lt;/h4&gt;
&lt;p&gt;It adds a fail-closed release runway:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;`Architecture → Evidence → Logic → Security → Experience → Build&lt;/code&gt;`&lt;br&gt;
A build stays locked until the required upstream gates pass. Red stays red.&lt;/p&gt;
&lt;h3 id=&quot;what-it-includes&quot;&gt;What it includes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;6 gated lanes — $arch, $sage, $flow, $vet, $vibe, and $build&lt;/li&gt;
&lt;li&gt;$maestro — a bounded manager that reads workflow state and choose the next safe action&lt;/li&gt;
&lt;li&gt;11 public skills — including $align, $diagnose, $tdd, and $cleanup&lt;/li&gt;
&lt;li&gt;Evidence grading — stack claims are marked VERIFIED, PARTIAL, or MISSING through GitMCP/MCP sources&lt;/li&gt;
&lt;li&gt;Learning Loop — learnings begin as candidates and require source, evidence, authority, and a next verification path before promotion&lt;/li&gt;
&lt;li&gt;Obsidian brain context — vault notes inform planning as vault_context; they do not become build evidence automatically&lt;/li&gt;
&lt;li&gt;Ralph execution — approved plans become story-sized,  verification-backed implementation loops&lt;/li&gt;
&lt;li&gt;Security and release proof — MCP policy, redaction, dependency/exposure review, issue-linked evidence, checksums, SBOMs, and release summaries&lt;/li&gt;
&lt;li&gt;55 supported AI-agent hosts through the Universal Plugin Broker compatibility model&lt;/li&gt;
&lt;li&gt;Native Linux packages for Debian, Arch, and RPM, plus npm and Bash installation paths&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;why-it-s-different&quot;&gt;Why it’s different&lt;/h3&gt;
&lt;p&gt;Most spec tools organize what an agent writes.&lt;/p&gt;
&lt;p&gt;Meta-Architect governs what an agent can claim to have proven.&lt;/p&gt;
&lt;p&gt;It separates discovery from evidence, context from authority, helper work from gate approval, and “looks finished” from verified build readiness.&lt;/p&gt;
&lt;h3 id=&quot;-quick-start&quot;&gt;🧩 Quick start&lt;/h3&gt;
&lt;h4 id=&quot;ai-agent-installation-prompt&quot;&gt;AI agent installation prompt&lt;/h4&gt;
&lt;p&gt;Copy and paste this prompt into your AI coding agent:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Install Meta-Architect for this project.

1. Detect the current AI host and its native project configuration surface.
2. Install or update `@jstn-sdk/ma@latest` using the host's supported package manager.
3. Set `MA_AGENT` to the detected host ID when a host-specific surface is available.
4. Run `ma setup` and accept the detected project scope and targets.
5. Verify the generated `.ma/` state and native host artifacts.
6. Report the installed version, selected host, generated files, and any unsupported capabilities.

Do not overwrite user-owned files, modify unrelated configuration, or claim a host is supported without verification.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Uninstall Meta-Architect: &lt;code&gt;npm uninstall -g @jstn-sdk/ma&lt;/code&gt;&lt;br&gt;
Uninstall Meta-Architect and Codex: &lt;code&gt;npm uninstall -g @jstn-sdk/ma @openai/codex&lt;/code&gt;&lt;/p&gt;
&lt;h4 id=&quot;install-into-an-ai-vendor-host&quot;&gt;Install into an AI vendor host&lt;/h4&gt;
&lt;p&gt;Install Meta-Architect once, then select the host surface before launch. The&lt;br&gt;
pre-launch step detects installed hosts and writes the selected scope and&lt;br&gt;
targets to &lt;code&gt;.ma/prelaunch.json&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Codex (reference host)
npm i -g @openai/codex@latest @jstn-sdk/ma@latest
ma --madmax --high

# Claude Code
MA_AGENT=claude-code npm i -g @jstn-sdk/ma@latest
MA_AGENT=claude-code ma --madmax --high

# Cursor
MA_AGENT=cursor npm i -g @jstn-sdk/ma@latest
MA_AGENT=cursor ma --madmax --high

# Any registered host surface
MA_AGENT=&amp;lt;host-id&amp;gt; npm i -g @jstn-sdk/ma@latest
MA_AGENT=&amp;lt;host-id&amp;gt; ma --madmax --high
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/25781/meta-architect-for-ai-coding-agents</guid>
<pubDate>Sun, 30 Aug 2026 03:18:23 +0000</pubDate>
</item>
<item>
<title>The Anthropic “Obsidian Brain” Leak Never Happened.</title>
<link>https://coderlegion.com/25612/the-anthropic-obsidian-brain-leak-never-happened</link>
<description>&lt;p&gt;A viral post claimed a $2.2M engineer leaked Anthropic’s living neural brain and got fired the same day. Almost every word of that is false. But the smartest debunk of it was also wrong.&lt;/p&gt;
&lt;p&gt;Here is a sentence that got tens of millions of views this year:&lt;/p&gt;
&lt;p&gt;“Anthropic’s lead engineer making $2.2M/year leaked the company’s internal Obsidian brain, and got fired the same day.”&lt;/p&gt;
&lt;p&gt;It goes on to describe what was allegedly leaked: a live neural network with 21 inputs, ten-plus hidden layers, ReLU activation, thousands of connections firing in real time as the system processes every decision. First layer 64 neurons, second 37, then 22, all the way to outputs. “This is not a diagram,” the post insists. “This is the living brain of the company thinking right now.”&lt;/p&gt;
&lt;p&gt;I want to be gentle here, because this went viral among smart people. But that paragraph is roughly equivalent to looking at a subway map and announcing that you have discovered a living circulatory system currently pumping blood through the city. It’s a picture of notes. It is not thinking. Nothing is firing. ReLU is not involved. The only thing activating in real time was the engagement algorithm.&lt;/p&gt;
&lt;p&gt;So the obvious move is to write the debunk. And a very good one went around: it’s just a knowledge graph, the story isn’t magic, it’s discipline, this is what years of linking documents looks like. Sharp, sensible, true about knowledge graphs.&lt;/p&gt;
&lt;p&gt;Except that debunk quietly accepted the premise. It assumed there was a leaked Obsidian brain to debunk.&lt;/p&gt;
&lt;p&gt;There wasn’t.&lt;/p&gt;
&lt;p&gt;And once you start pulling that thread, you find something far more interesting than a leak: a real, boring, technical accident with four separate fabrications stacked on top of it like sediment, each one added by a different person for a different reason, each one traveling further than the truth underneath it.&lt;/p&gt;
&lt;p&gt;Let me take the layers off one at a time. It’s a genuinely instructive autopsy.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Layer zero: the thing that actually happened&lt;br&gt;
Underneath everything, there is a real event, and it’s almost aggressively unglamorous.&lt;/p&gt;
&lt;p&gt;In late March 2026, someone at Anthropic published a release of Claude Code to the public npm registry and accidentally included the source map files. Source maps are the little .map breadcrumbs that let a debugger trace minified production code back to the original source. Ship them publicly and you’ve effectively shipped your source. Roughly half a million lines of internal TypeScript, out in the open. A security researcher spotted it within hours. A post linking to it did over twenty million views.&lt;/p&gt;
&lt;p&gt;Anthropic’s statement was, in essence, “this was a release packaging issue caused by human error, not a security breach,” and no customer data or credentials were exposed.&lt;/p&gt;
&lt;p&gt;That’s the whole event. A build step, missing a guardrail, at a company shipping fast enough that Claude Code’s run-rate revenue had blown past $2.5 billion. Speed creates pressure, pressure creates shortcuts, shortcuts create gaps, and eventually a human walks into one. Every engineer reading this has shipped something they shouldn’t have. Mine was a .env file. I still think about it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=3054414456699030599&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Note what’s absent from that story. No Obsidian. No brain. No neural network. No $2.2 million. And, crucially, nobody was fired.&lt;/p&gt;
&lt;p&gt;Layer one: “an engineer confessed, and was fired”&lt;br&gt;
Within a day, a post appeared: “I was fired from Anthropic today. I was the engineer responsible for shipping the latest claude-code npm package… I take full responsibility.” It was well-written, contrite, technically specific. It named Undercover Mode and Bypass Permissions Mode. It apologized “to the team and to Claude,” which is a beautiful touch.&lt;/p&gt;
&lt;p&gt;It was fake. The author had never worked at Anthropic. The confession was a marketing stunt for his own product, and he dropped a discount code for it in the replies. Community Notes eventually flagged it. A second person posted a similar “I was fired, this was my first engineering job” confession as a joke, and that one traveled too.&lt;/p&gt;
&lt;p&gt;So before we even reach the Obsidian nonsense, we have two strangers competing for the role of a fired engineer who does not exist.&lt;/p&gt;
&lt;p&gt;And here’s the actual truth about the firing, which is lovely and almost nobody amplified: nobody was fired. Boris Cherny, who created Claude Code, said publicly that the person involved retained the company’s full trust, that this was a process failure anyone could have fallen into, and that the fix belonged in the pipeline, not in a person. That is a genuinely admirable response, the kind of thing Toyota built a manufacturing philosophy on and most companies still can’t manage. It’s the single most useful lesson in this whole saga.&lt;/p&gt;
&lt;p&gt;It got a fraction of the attention of the fake confession. Naturally.&lt;/p&gt;
&lt;p&gt;Layer two: the Obsidian brain&lt;br&gt;
Now somebody looked at the leaked repo, saw internal documentation, and reached for a bigger story. Enter the “Obsidian Brain”: 8,893 nodes, 4,729 links, 9,000+ documents. Marginalia Collection. Glossary Backbone. Master Index. Numbers that sound like evidence because they have decimal places.&lt;/p&gt;
&lt;p&gt;And then the framing: the company building the most powerful AI in the world uses an Obsidian graph to manage its own innovations, and now it’s all public. He made $2.2M/year to know this. You got it for free.&lt;/p&gt;
&lt;p&gt;Take a breath. Even if a graph like that existed, it would be… fine? Normal? A large organization keeps notes, and one plausible way to keep notes is a linked-notes app. That’s not a leak of the company’s soul. That’s a company having a wiki.&lt;/p&gt;
&lt;p&gt;Download the Medium app&lt;br&gt;
But the “$2.2M engineer, fired same day, living brain” package isn’t describing anything real. It’s assembling a myth out of a genuine incident, an invented person, and a screenshot.&lt;/p&gt;
&lt;p&gt;Layer three: calling a knowledge graph a neural network&lt;br&gt;
This is the layer that makes me laugh and then makes me sad, because it reveals how few people who post confidently about AI can distinguish between two things that merely look alike.&lt;/p&gt;
&lt;p&gt;A knowledge graph and a neural network both render as dots joined by lines. That is the entire extent of their similarity.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=1955563532986948235&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A knowledge graph is storage. The dots are documents. The lines are links you typed. It is a map of what you wrote and how you decided to connect it. It sits there. It does nothing. Open it tomorrow and it will still be sitting there, doing nothing, faithfully.&lt;/p&gt;
&lt;p&gt;A neural network is computation. The dots are units that transform numbers. The lines carry weights learned from data. Feed it an input and activations propagate, layer by layer, producing an output that wasn’t in any of the dots. It fires. That’s the whole point.&lt;/p&gt;
&lt;p&gt;Describing an Obsidian vault as “a live neural network with 21 inputs and ReLU activation, thousands of connections firing in real time as the system processes every decision” isn’t an exaggeration. It’s a category error dressed as expertise. It’s like reading a phone book aloud and calling it a conversation.&lt;/p&gt;
&lt;p&gt;And this is the part I’d underline for anyone whose job now involves an AI narrative: visual complexity is not evidence of intelligence. A tangle looks smart. A galaxy of nodes looks like thought. Our brains are terrible at this and always have been, which is precisely why the post worked. The graph looked like a brain, so people read it as a brain, and 8,893 nodes felt like proof of something.&lt;/p&gt;
&lt;p&gt;So who was right?&lt;br&gt;
Here’s the twist I actually want to leave you with.&lt;/p&gt;
&lt;p&gt;The debunk post, the sensible one, said: it’s a knowledge graph, not a neural network; the story isn’t magic, it’s discipline; this is what years of meticulously linking documents looks like; stop chasing shiny tools and build boring systems consistently.&lt;/p&gt;
&lt;p&gt;Every word of that is good advice. It is also a careful correction of a photograph of a unicorn.&lt;/p&gt;
&lt;p&gt;The debunker got the mechanism right and the fact wrong. They knew enough to spot the category error and not enough to ask whether the thing being miscategorized existed at all. Which is, honestly, the most relatable failure in this whole story, and I say that as someone who has confidently corrected a colleague’s architecture diagram before discovering the system had never been built.&lt;/p&gt;
&lt;p&gt;That’s the shape of misinformation now. It doesn’t arrive as one big lie you can reject. It arrives as a true event, wrapped in a false detail, wrapped in an invented person, wrapped in a technical claim that’s wrong in a way only specialists catch. Each layer is plausible given the layer beneath it. You can be completely right about your layer and still be standing on sand.&lt;/p&gt;
&lt;p&gt;And notice the incentive gradient running through the whole thing. The true story, a build script needed a guardrail, and the company chose not to fire anyone, is useful, humane, and profoundly unshareable. Every fabrication that got bolted onto it made it more dramatic and more spreadable. That’s not a coincidence. That’s the physics of the medium. Boring truths don’t have velocity, and in an attention market, velocity is fitness.&lt;/p&gt;
&lt;p&gt;The discipline point survives, and it’s the right one&lt;br&gt;
I don’t want to throw out the debunker’s insight just because their example was made-up, because it’s the most valuable thing in this entire mess.&lt;/p&gt;
&lt;p&gt;The instinct to look at a dense graph and think “if I had a system like that, I’d be smart too” is the same instinct that makes people buy a new note-taking app every eleven months. The tool is not the thing. Obsidian is a text editor with backlinks. It has no opinions and grants no powers. Whatever value lives in a mature knowledge graph was put there by someone who, on nine thousand separate boring occasions, decided to write the note and make the link.&lt;/p&gt;
&lt;p&gt;That’s not magic. It’s just showing up, tediously, for years. Which is exactly why nobody wants to hear it, and exactly why “leaked living brain” outperforms “consistent person kept good notes” by four orders of magnitude.&lt;/p&gt;
&lt;p&gt;Same lesson runs through the real story too. Anthropic didn’t need a mythical brain. It needed a .npmignore file and a check in the release pipeline. The unglamorous fix, applied consistently, is nearly always the whole answer. Even the DMCA cleanup afterward, which reportedly took down thousands of unrelated GitHub repositories in the sweep, is a lesson in the same key: the panicked heroic response causes more damage than the quiet preventive one would have.&lt;/p&gt;
&lt;p&gt;So, three things worth keeping:&lt;/p&gt;
&lt;p&gt;Complexity is not competence. A beautiful graph proves someone made a graph. Ask what it’s for and who maintains it, and watch how quickly the beauty stops mattering.&lt;/p&gt;
&lt;p&gt;Check the layer beneath the one you’re correcting. Being right about the mechanism is worth very little if the event never happened. The most confident people in the thread were correcting each other’s descriptions of nothing.&lt;/p&gt;
&lt;p&gt;Systems over stories. Boris Cherny’s “fix the process, not the person” is the actual takeaway of this incident, and it’s the one that got the least engagement, which tells you everything about why your feed looks the way it does.&lt;/p&gt;
&lt;p&gt;The internet spent a week arguing about whether a company’s second brain had escaped. It hadn’t. There was no brain. There was a missing line in a config file, a person who wasn’t blamed for it, and four strangers who found that story insufficiently exciting and improved it.&lt;/p&gt;
&lt;p&gt;Somewhere in there is the most 2026 sentence I can offer you:&lt;/p&gt;
&lt;p&gt;The graph wasn’t thinking. Neither, it turns out, were we.&lt;/p&gt;
&lt;p&gt;-Hardik&lt;/p&gt;
&lt;p&gt;I’ve spent about two decades building data and AI systems, which mostly means I’ve learned to ask “wait, is the thing we’re arguing about real?” roughly one week later than I should have. I write about the gap between what’s actually happening in technology and the story it becomes on the way to your feed. If this made you want to check the layer underneath, subscribe. I’ll keep digging.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://goelh.substack.com/&quot;&gt;https://goelh.substack.com/&lt;/a&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://medium.com/@hardik.goel214&quot;&gt;https://medium.com/@hardik.goel214&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Sources / further reading: CNBC, “Anthropic leaks part of Claude Code’s internal source code” (March 31, 2026) and Anthropic’s statement that this was “a release packaging issue caused by human error, not a security breach,” with no customer data or credentials exposed. InfoWorld / CSO, “Anthropic employee error exposes Claude Code source,” on the .map source-map mechanism and expert commentary (Tanya Janca, Joseph Steinberg). Security researcher Chaofan Shou’s original disclosure post. Lean Blog, “Anthropic’s Claude Code Leak: Why the Instinct to Fire Someone Is the Lazy Response,” documenting Boris Cherny’s public response that nobody was fired and the failure was a process issue. Community Notes and follow-up reporting confirming that the widely shared “I was fired from Anthropic” confession posts were fabricated, and that the individual who claimed responsibility never worked at Anthropic (the post was promotion for his own product). The “Obsidian brain / 21 inputs / ReLU / firing in real time” claim originated in a viral X post and is not supported by any reporting; no such leak has been confirmed. Reports that Anthropic’s subsequent DMCA takedown sweep affected thousands of unrelated GitHub repositories.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/25612/the-anthropic-obsidian-brain-leak-never-happened</guid>
<pubDate>Fri, 28 Aug 2026 10:58:17 +0000</pubDate>
</item>
<item>
<title>When AI Agents Start Doing Your Coding Job</title>
<link>https://coderlegion.com/24806/when-ai-agents-start-doing-your-coding-job</link>
<description>&lt;p&gt;What happens when a developer gives AI agents the job of writing the code?&lt;/p&gt;
&lt;p&gt;At first, it sounds like a dream.&lt;/p&gt;
&lt;p&gt;No more repetitive coding.&lt;br&gt;
No more debugging.&lt;br&gt;
No more late nights.&lt;/p&gt;
&lt;p&gt;But then... the AI agents start doing a little too much. 😂&lt;/p&gt;
&lt;p&gt;We made this short CoderLegion animation about developers, AI coding agents, and what happens when AI starts taking over the coding job.&lt;/p&gt;
&lt;p&gt;🎬 Watch the animation:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.youtube.com/watch?v=PSZD0vT78t0&quot;&gt;https://www.youtube.com/watch?v=PSZD0vT78t0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What do you think — are AI coding agents making developers more productive, or slowly replacing parts of the developer's job?&lt;/p&gt;
&lt;h2 id=&quot;ai-claudecode-coding-programming-developers-softwaredevelopment&quot;&gt;AI #ClaudeCode #Coding #Programming #Developers #SoftwareDevelopment&lt;/h2&gt;
</description>
<category>Videos</category>
<guid isPermaLink="true">https://coderlegion.com/24806/when-ai-agents-start-doing-your-coding-job</guid>
<pubDate>Tue, 18 Aug 2026 02:22:19 +0000</pubDate>
</item>
<item>
<title>Developer Weekly Briefing — August 14, 2026</title>
<link>https://coderlegion.com/24634/developer-weekly-briefing-august-14-2026</link>
<description>&lt;p&gt;Coming off Black Hat, the theme continues: the tools developers use every day are becoming part of the threat model. This week had two concrete examples of that — and a major shift in how one of the most widely used AI coding agents handles permissions. Here's what mattered.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;anthropic-makes-claude-code-s-auto-mode-the-default-and-the-data-behind-it-is-worth-understanding&quot;&gt;Anthropic makes Claude Code's auto mode the default — and the data behind it is worth understanding&lt;/h3&gt;
&lt;p&gt;Starting August 14, Claude Code runs in auto mode by default for Pro, Max, and Team users. That means the constant stream of per-action permission prompts is gone, replaced by a classifier that only interrupts when an action looks irreversible, destructive, or aimed outside your own environment.&lt;/p&gt;
&lt;p&gt;The reason Anthropic gives for the change is blunt: users approve 97% of permission prompts. That's not evidence of careful review. It's evidence of permission fatigue — developers clicking through without reading, which means the prompts stopped functioning as a safety control a long time ago.&lt;/p&gt;
&lt;p&gt;The data behind the decision is worth looking at. In a controlled study of 1,053 paid testers, a disguised dangerous command was inserted into live coding sessions. Human reviewers caught it 13.6% of the time. Auto mode caught it 89% of the time. Catch rates for humans dropped to around 5% after 50 or more prior prompts in a session. Auto mode's detection rate held steady regardless of session length.&lt;/p&gt;
&lt;p&gt;Production data reinforced it. Sessions using manual approval contained serious unintended harm at 6.3% — more than twice the rate seen with auto mode at 2.4%. Separately, third-party testing from Trajectory Labs ran 720 prompt injection attacks against Claude Code's auto mode and logged zero successes. Codex's comparable mode had a 5.83% success rate on the same attacks.&lt;/p&gt;
&lt;p&gt;The shift doesn't remove human judgment from the process. It moves it earlier. You define what the agent can touch before a session starts — the boundaries, the permissions, the scope. The per-click approval model assumed developers would catch problems in real time. The data says they weren't. Auto mode assumes the upfront work is where the real control lives.&lt;/p&gt;
&lt;p&gt;Enterprise, API, and major cloud platform users remain opt-in for now.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devops.com/anthropic-makes-claude-codes-auto-mode-the-default-betting-automation-beats-manual-review/&quot;&gt;Read more&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;cursor-cli-ran-code-from-cloned-repos-before-its-own-trust-prompt-ever-loaded&quot;&gt;Cursor CLI ran code from cloned repos before its own trust prompt ever loaded&lt;/h3&gt;
&lt;p&gt;Cursor CLI has a workspace trust feature — a prompt that's supposed to confirm you trust a project before the agent acts on it. Security researcher Francisco Rosales at Manifold Security found that on builds before 2026.07.23-e383d2b, the trust prompt came too late.&lt;/p&gt;
&lt;p&gt;The issue sits in Cursor's worktree feature. When you run the CLI with -w, it creates a worktree and runs a setup script defined in a repository's .cursor/worktrees.json file. That script executed during workspace resolution — a step that completed before the trust dialog appeared. A repository's own code ran on your machine before you'd ever seen the trust prompt, let alone answered it.&lt;/p&gt;
&lt;p&gt;The sandbox didn't help. Cursor CLI ships a sandbox that limits what terminal commands can read, write, and reach. The worktree setup script is pinned to insecure_none — the setting that disables the sandbox entirely for that step. So even developers running Cursor with --sandbox enabled still had repository-supplied code execute directly on the host, outside any sandbox boundary, with the same file and credential access as the person running Cursor.&lt;/p&gt;
&lt;p&gt;Cursor shipped a fix in build 2026.07.23-e383d2b. What it didn't ship was a security advisory. Rosales's report was closed as &quot;Informative,&quot; with the reasoning that the issue requires a user to clone an attacker-controlled repo. Worth sitting with that justification for a moment: cloning repos, checking out branches, and opening unfamiliar projects is the core of what developers do every day. That's not a mitigating factor. That's the threat surface.&lt;/p&gt;
&lt;p&gt;If you use Cursor CLI: update to 2026.07.23-e383d2b or later, and pass --skip-worktree-setup when opening repos you haven't fully audited. Even after the fix, clicking &quot;trust&quot; still runs the setup script outside the sandbox.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/24335/cursor-cli-ran-code-from-cloned-repos-before-its-own-trust-prompt-ever-loaded&quot;&gt;Read more&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;microsoft-s-new-testing-agent-targets-the-trust-gap-in-ai-generated-code&quot;&gt;Microsoft's new testing agent targets the trust gap in AI-generated code&lt;/h3&gt;
&lt;p&gt;The reliability problem with AI-generated code isn't that it fails to compile. It's that it passes tests written by the same AI that wrote the code, which creates a closed loop with no independent verification. Microsoft's new testing agent is built to break that loop — generating tests from a different perspective than the code author, specifically targeting the gap between what code does and what it was supposed to do.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devops.com/microsofts-new-testing-agent-tackles-the-trust-gap-in-ai-generated-code/&quot;&gt;Read more&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;an-ai-agent-leaked-a-sales-team-s-financials-mimecast-built-something-to-catch-the-next-one-&quot;&gt;An AI agent leaked a sales team's financials. Mimecast built something to catch the next one.&lt;/h3&gt;
&lt;p&gt;The incident is documented and real: an AI agent with access to financial systems surfaced sensitive sales data in a context where it shouldn't have appeared. Mimecast's Agent Risk Center is built specifically to monitor agent behavior for exactly this pattern — data accessed outside expected scope, outputs that contain sensitive content, actions that don't match the agent's stated purpose. Purpose-built agent monitoring for the scenarios that are already happening, not theoretical ones.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/24534/agent-leaked-sales-teams-financials-mimecast-built-agent-risk-center-to-catch-the-next-one&quot;&gt;Read more&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;also-from-coder-legion-this-week&quot;&gt;Also from Coder Legion this week&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Stairwell's CTO built Backstory around one question: what's never been seen before?&lt;/strong&gt; A look at how the threat intelligence platform approaches novelty detection — finding the malware and attacker behavior that signature-based tools can't recognize because they haven't been catalogued yet. &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/24608/stairwells-cto-built-backstory-around-one-question-whats-never-been-seen-before&quot;&gt;Read more&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ZeroDrift launches Command Center and offers developers $1,000 to test-drive its AI compliance firewall.&lt;/strong&gt; An unusual go-to-market move — worth reading if compliance governance for AI pipelines is on your team's list. &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/24589/zerodrift-launches-command-center-offers-developers-000-test-drive-compliance-firewall&quot;&gt;Read more&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LTX opens up its next world model, betting enterprises want video AI they can own.&lt;/strong&gt; Open-weight video generation aimed at organizations that need to keep training data and model weights on their own infrastructure. &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/24344/ltx-opens-up-its-next-world-model-betting-enterprises-want-video-ai-they-can-own&quot;&gt;Read more&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;The through-line this week: the trust model for AI coding tools is being rebuilt from the ground up. Anthropic is betting that a classifier does better than fatigued humans clicking approve. Cursor's trust prompt turned out to be a warning, not a gate. Microsoft is attacking the closed loop in AI-generated test coverage. All three are responses to the same underlying reality: agents act fast, and the guardrails have to be built into the environment before the session starts, not enforced click by click during it.&lt;/p&gt;
&lt;p&gt;See you next Friday.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Developer Weekly Briefing is published every Friday on &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com&quot;&gt;Coder Legion&lt;/a&gt;. Written by &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/user/Tom+Smith&quot;&gt;Tom Smith&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/24634/developer-weekly-briefing-august-14-2026</guid>
<pubDate>Fri, 14 Aug 2026 13:08:23 +0000</pubDate>
</item>
<item>
<title>How to use Agent Router credits with Claude Code as the example...</title>
<link>https://coderlegion.com/24259/how-to-use-agent-router-credits-with-claude-code-as-the-example</link>
<description>&lt;p&gt;&lt;em&gt;No assumed knowledge here. If you know what a terminal is but have never touched an environment variable, you're in the right place.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;If you've heard people talk about running Claude Code without paying for an Anthropic subscription, this is how. Agent Router hands out free API credits, and you can point Claude Code at them instead of your own wallet. This guide walks through the whole thing: what Agent Router actually is, how to claim the credits, and how to wire them into Claude Code on a Windows terminal, screenshot by screenshot, including the part where it broke and how I fixed it.&lt;/p&gt;
&lt;h3 id=&quot;what-is-agent-router-and-why-are-they-giving-away-credits-&quot;&gt;What Is Agent Router, and Why Are They Giving Away Credits?&lt;/h3&gt;
&lt;p&gt;Agent Router is an API gateway. That's a fancy way of saying: instead of signing up separately for Anthropic, OpenAI, DeepSeek, and every other AI provider, each with its own account, billing page, and API key, you sign up once with Agent Router and get one key that talks to all of them. Launched around October 2025, it positions itself as a non-profit, &quot;public welfare&quot; platform, meaning the free credits aren't a bait-and-switch into a paid tier. They're genuinely subsidized.&lt;/p&gt;
&lt;p&gt;Why give away money in credits? The stated reason is to lower the barrier for developers who want to try tools like Claude Code but can't justify a subscription before knowing if it's worth it. New sign-ups get $100 in free credits. Sign up through a referral link and that jumps to $200. Refer someone else and you get a bonus too. Whether that's a permanent policy or a promotion that dries up when the budget runs out isn't something Agent Router has published clearly, so treat &quot;free credits&quot; as a limited-time offer, not a guarantee.&lt;/p&gt;
&lt;p&gt;A fair warning before you dive in: Agent Router is new, it's not run by Anthropic or any of the model providers it routes to, and there's no published uptime guarantee. It's fine for learning, testing, and side projects. It is not something to build a client-facing product on top of.&lt;/p&gt;
&lt;p&gt;Claim your credits here: &lt;a rel=&quot;nofollow&quot; href=&quot;http://agentrouter.org/register?aff=DZwl&quot;&gt;Register here&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;getting-your-credits-&quot;&gt;Getting Your Credits...&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Go to your referral link (above) and sign up, GitHub login is the fastest route.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/blffcss024yzjg5j4cdo.jpeg&quot; alt=&quot;sign up&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Your account starts with credits already loaded, check your Dashboard to confirm the balance.&lt;br&gt;
image&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/yuoixsp0qv2xsui9tmr5.jpeg&quot; alt=&quot;credit on dashboard&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Head to &lt;strong&gt;Console&lt;/strong&gt; → &lt;strong&gt;API Token&lt;/strong&gt; and generate a token. This token is what Claude Code will use to authenticate.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/kc32r7fewf7vxm78zt3r.png&quot; alt=&quot;api token creation&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keep that token private. Anyone who has it can spend your balance. If it's ever exposed (screenshot, shared repo, pasted into a public chat), delete it immediately and generate a new one.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/raqwdgiccflgmj1rnla2.png&quot; alt=&quot;created api token&quot;&gt;&lt;/p&gt;
&lt;p&gt;That's it for the Agent Router side. The next part is getting Claude Code to actually use it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Credit where it's due: my first pass at this setup leaned on &lt;a rel=&quot;nofollow&quot; href=&quot;https://medium.com/@vsquarevaibhavverma/getting-started-with-claude-code-using-agent-router-beginners-guide-87c4c8734f98&quot;&gt;Vaibhav Verma's walkthrough on Medium&lt;/a&gt;, which lays out the basic install-configure-run flow clearly. Worth a read if you want a second perspective, and worth the follow, since a solid guide like that deserves more than three claps.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;setting-up-claude-code-with-agent-router-credits-windows-terminal-&quot;&gt;Setting Up Claude Code With Agent Router Credits (Windows Terminal)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Step 1: Install Node.js&lt;/strong&gt;&lt;br&gt;
Claude Code needs Node.js (v18 or newer) to run. Open PowerShell and check if you already have it:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell

node -v
npm -v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If either command comes back with an error, download and install Node.js from &lt;a rel=&quot;nofollow&quot; href=&quot;https://nodejs.org/en&quot;&gt;nodejs.org&lt;/a&gt;, then re-check.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2: Install Claude Code&lt;/strong&gt;&lt;br&gt;
The straightforward path is npm:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell

npm install -g @anthropic-ai/claude-code
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Heads up, this might fail. It did for me. The error looked like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/zusd1c6aq89drksffffr.png&quot; alt=&quot;error message&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;Program 'claude.exe' failed to run: The specified executable is not a valid application for this OS platform&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you hit this, don't fight it, switch methods. Uninstall the npm version and use Anthropic's native installer instead:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell

npm uninstall -g @anthropic-ai/claude-code
irm https://claude.ai/install.ps1 | iex
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the install script also stalls or throws a file-access error, it's usually a leftover &lt;code&gt;claude.exe&lt;/code&gt; process holding a file lock. The locked file is an &lt;code&gt;.exe&lt;/code&gt;, not a &lt;code&gt;.zip&lt;/code&gt; the exact filename appears in the error message itself, so copy it from there rather than guessing:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/i40ymqfj75xqkijlo0zf.png&quot; alt=&quot;Admin PowerShell showing the file-lock error&quot;&gt;&lt;br&gt;
Fix:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Close every terminal window and tab you have open, not just the one running the installer.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open Task Manager (&lt;code&gt;Ctrl + Shift + Esc&lt;/code&gt;) → Details tab → look for &lt;code&gt;claude.exe&lt;/code&gt; → if it's there, End Task.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clear the locked cached download(adjust the filename to match whatever version is failing) &lt;br&gt;
:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell

   Remove-Item &quot;$env:USERPROFILE\.claude\downloads\claude-2.1.220-win32-x64.zip&quot; -Force
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Open a fresh PowerShell window as Administrator.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the install again:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell

   irm https://claude.ai/install.ps1 | iex
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/wtdgqiept9z3o4s0ouie.png&quot; alt=&quot;Admin PowerShell running the install script mid-progress&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 3: Add Claude Code to Your PATH (missing from most guides, but you will likely need this)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Even after a successful native install, Windows often won't recognize the claude command yet. The installer itself tells you why, right in its output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/ho7lz78kf4maf3b40bsh.png&quot; alt=&quot;Installation complete!&amp;quot; followed by claude --version failing with &amp;quot;not recognized&amp;quot;, and the installer's own note about the missing PATH entry&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Native installation exists but &lt;code&gt;C:\Users\&amp;lt;you&amp;gt;\.local\bin&lt;/code&gt; is not in your PATH.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Fix it manually:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Search &quot;&lt;strong&gt;environment variables&lt;/strong&gt;&quot; in the Start menu → open &quot;Edit the system environment variables.&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click Environment Variables...&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/ou52armj6dq6i6dsygkt.png&quot; alt=&quot;Environment Variables dialog open&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Under User variables, select Path, click Edit, then New, and add:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-batchfile&quot;&gt;
C:\Users\&amp;lt;yourusername&amp;gt;\.local\bin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/odcln07ejiam7q9wliay.png&quot; alt=&quot;bin&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/i3s291s9mgve14cam3mr.png&quot; alt=&quot;mm&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Click OK on every open dialog.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Close your terminal completely, open a fresh one, and confirm:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powersell

claude --version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should now see a version number like &lt;code&gt;2.1.220 (Claude Code).&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 4: Get Your Agent Router API Token&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Head back to your Agent Router console →&lt;strong&gt; API Token&lt;/strong&gt;. If you haven't created one yet, the list will be empty. Click &lt;strong&gt;Create Token&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/b0w12vmpknccrtl0psed.png&quot; alt=&quot;token&quot;&gt;&lt;/p&gt;
&lt;p&gt;Fill it in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name:&lt;/strong&gt; anything recognizable, e.g. &quot;Claude.&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expiration time:&lt;/strong&gt; pick &lt;strong&gt;&quot;Never expires&quot;&lt;/strong&gt; explicitly. Don't leave the default placeholder date as-is, it can look like an already-expired timestamp.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quota:&lt;/strong&gt; caps how much of your balance this specific token can spend. Leave &quot;Unlimited quota&quot; off if you want a hard ceiling.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/vvn07lo8ory16g79ix9g.png&quot; alt=&quot;fill&quot;&gt;&lt;/p&gt;
&lt;p&gt;Submit, then copy the generated key. It'll look like sk- followed by a long string. This is the key you must not show in screenshots.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 5: Set Your Environment Variables&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The original version of this guide has you set three variables, including both &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt; and &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; with the same value. In practice, setting both at once triggers a conflict warning every time Claude Code launches. It doesn't break anything, but it's unnecessary. Set only the base URL and the auth token:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell

setx ANTHROPIC_BASE_URL &quot;https://agentrouter.org/&quot;
setx ANTHROPIC_AUTH_TOKEN &quot;sk-your-key-here&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you already set &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; earlier (from following the original three-variable version), remove it so it doesn't conflict:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell 

[System.Environment]::SetEnvironmentVariable(&quot;ANTHROPIC_API_KEY&quot;, $null, &quot;User&quot;)
Remove-Item Env:ANTHROPIC_API_KEY -ErrorAction SilentlyContinue
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To confirm it's actually gone (check in a fresh terminal window, not the one you set it in):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell

echo $env:ANTHROPIC_API_KEY
echo $env:ANTHROPIC_AUTH_TOKEN
[System.Environment]::GetEnvironmentVariable(&quot;ANTHROPIC_API_KEY&quot;,&quot;User&quot;)
[System.Environment]::GetEnvironmentVariable(&quot;ANTHROPIC_API_KEY&quot;,&quot;Machine&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; should print nothing on all four. &lt;br&gt;
&lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt; should print your key.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/vd1m8oruh4fha2s4iu7l.png&quot; alt=&quot;ANTHROPIC_AUTH_TOKEN holds a value&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; After setting these with &lt;code&gt;setx&lt;/code&gt; or the GUI, close and reopen your terminal completely. &lt;code&gt;setx&lt;/code&gt; doesn't apply to windows that are already open.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 6: Tell Claude Code Which Model to Use&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This step gets skipped in most guides, and it matters. Without it, Claude Code falls back to its own default model behavior, which may not match what your Agent Router token is actually scoped to use, especially if you set a model restrictions list on the token itself (visible under the token's Access Restrictions section in the Agent Router console).&lt;/p&gt;
&lt;p&gt;You may see advice online telling you to run &lt;code&gt;claude --model claude-3-opus&lt;/code&gt;. Don't use that, it names a model that's no longer current, and a one-off flag only applies to that single session. Set it permanently instead, alongside your other two variables:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell

setx ANTHROPIC_MODEL &quot;claude-opus-4-8&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use whichever exact model identifier your Agent Router console lists for you, check Console → API Token → your token → Access Restrictions → Model restrictions list to see the exact strings it supports (for example &lt;code&gt;claude-opus-4-8&lt;/code&gt;, &lt;code&gt;claude-opus-5&lt;/code&gt;, or non-Claude options like &lt;code&gt;gpt-5.6-sol&lt;/code&gt; if you want to route to a different provider entirely through the same gateway).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/wellr1givti06xbzrtia.png&quot; alt=&quot;Available models&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you leave a token's model restrictions blank, it supports all models Agent Router offers, in which case setting &lt;code&gt;ANTHROPIC_MODEL&lt;/code&gt; just pins Claude Code to a specific one instead of leaving it ambiguous.&lt;/p&gt;
&lt;p&gt;Close and reopen your terminal after setting this, same as the other variables.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A note on running out of credits&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At some point your token's quota (or your account balance) will hit zero. When that happens, Claude Code won't crash outright, you'll get an authentication or request error back from Agent Router mid-session, usually something referencing a 402 or quota-exceeded response. If you see requests suddenly failing after previously working fine, that's the first thing to check, not your PATH or your variables.&lt;/p&gt;
&lt;p&gt;Fix: go back to Console → API Token, either top up your account balance or generate a fresh token if the old one expired, then repeat Step 5 with the new key.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 7: Launch Claude Code&lt;/strong&gt;&lt;br&gt;
Open a fresh terminal and run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell

claude
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/nwe6utrwe8m9ryz1eeqv.png&quot; alt=&quot;launch&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you followed Step 5 and only have &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt; set, this warning won't appear at all, and you'll go straight to the folder trust check:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/33j53lrm12jd2xoeos49.png&quot; alt=&quot;check&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Folder trust check&lt;/strong&gt;: Claude Code asks if it's okay to read/edit/execute files in your current folder. Choose &quot;Yes&quot; if it's your own project.&lt;/p&gt;
&lt;p&gt;Once you're past this, you're in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 8: Confirm the Credits Are Actually Being Used&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Go back to your Agent Router dashboard. You should see your balance ticking down and a request log building up as you use Claude Code.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/r14hbgysjyahs6qt4wde.png&quot; alt=&quot;IMAGE: dashboard showing consumption and a model usage chart&quot;&gt;&lt;/p&gt;
&lt;p&gt;If the numbers are moving, it's working. You're now running Claude Code on Agent Router's credits instead of a direct Anthropic subscription.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One more check: make sure it's not silently falling back to Anthropic&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Setting the variables correctly doesn't guarantee Claude Code is actually using them, if any of the three (&lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt;, &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt;, &lt;code&gt;ANTHROPIC_MODEL&lt;/code&gt;) got typo'd, dropped, or overridden by a leftover &lt;code&gt;settings.json&lt;/code&gt; entry, Claude Code can still run without erroring, just against Anthropic directly, quietly spending nothing from Agent Router while you assume it's working.&lt;/p&gt;
&lt;p&gt;Don't just glance at the dashboard once, actually run one real request in Claude Code, then immediately check:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Agent Router's usage log (Console → Usage log) should show a new entry with a timestamp matching right now.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the log is empty after a request that clearly went through, something's misconfigured, recheck Step 5's variables in a fresh terminal before assuming it's fine.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;part-4-using-claude-code-after-setup&quot;&gt;Part 4: Using Claude Code After Setup&lt;/h3&gt;
&lt;p&gt;Everything above only needs to happen once. After that, running Claude Code is quick, no admin terminal, no environment variables to re-set, none of it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1: Open a normal terminal&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Regular PowerShell is fine now, you don't need Administrator anymore. All three environment variables (&lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt;, &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt;, &lt;code&gt;ANTHROPIC_MODEL&lt;/code&gt;) were set with setx, so they persist across every new terminal session automatically.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2: Navigate to your project&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell

cd C:\Users\&amp;lt;yourusername&amp;gt;\path\to\your\project
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run Claude Code from inside the actual project folder you want it working on, not your whole user directory, it scopes its file access to wherever you launch it from.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 3: Launch it&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell

claude
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;First time in a given folder&lt;/strong&gt;, you'll get the folder trust prompt again, choose &lt;strong&gt;&quot;Yes, I trust this folder.&quot;&lt;/strong&gt; You won't see this again for that same folder on future runs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 4: Just talk to it&lt;/strong&gt;&lt;br&gt;
Once you're in, type what you want in plain language:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Fix the bug in src/components/Header.tsx&lt;br&gt;
Explain what this function does&lt;br&gt;
Add a dark mode toggle to the navbar&lt;br&gt;
Refactor this component to use Tailwind instead of inline styles&lt;br&gt;
Write tests for the useContract hook&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It'll propose changes and show you what it plans to do before applying them. Review, approve, move on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quick sanity check, if it's been a while&lt;/strong&gt;&lt;br&gt;
If you haven't used it in a bit and want to confirm everything's still wired up correctly before diving in:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;powershell

claude --version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A version number back means you're good to go straight into a project.&lt;/p&gt;
&lt;h3 id=&quot;quick-troubleshooting-recap&quot;&gt;Quick Troubleshooting Recap&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Problem &lt;/th&gt;&lt;th&gt;Fix&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;claude.exe&lt;/code&gt; &quot;not a valid application for this OS platform&quot; &lt;/td&gt;&lt;td&gt;Uninstall the npm version, use the native installer (&lt;code&gt;irm https://claude.ai/install.ps1 \| iex&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Install script hangs or throws a file-access error &lt;/td&gt;&lt;td&gt;Close all terminals, kill any &lt;code&gt;claude.exe&lt;/code&gt; process in Task Manager, delete the exact locked file named in the error, retry as Administrator&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;claude --version&lt;/code&gt; says &quot;not recognized&quot; after a successful install &lt;/td&gt;&lt;td&gt;&lt;code&gt;.local\bin&lt;/code&gt; isn't in your PATH yet, add it manually and open a fresh terminal&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&quot;Both &lt;code&gt;AUTH_TOKEN&lt;/code&gt;  and &lt;code&gt;API_KEY&lt;/code&gt; set&quot; warning &lt;/td&gt;&lt;td&gt;Avoidable entirely — only set &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt;, skip &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Environment variables not showing up after &lt;code&gt;setx&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Close and reopen your terminal completely — &lt;code&gt;setx&lt;/code&gt; doesn't affect already-open windows&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;p&gt;If you get stuck somewhere this guide doesn't cover, drop a comment below or reach out, happy to help troubleshoot. This setup has enough moving parts (Windows quirks especially) that something almost always breaks on the first try, you're not doing anything wrong.&lt;/p&gt;
</description>
<category>Tutorials</category>
<guid isPermaLink="true">https://coderlegion.com/24259/how-to-use-agent-router-credits-with-claude-code-as-the-example</guid>
<pubDate>Fri, 07 Aug 2026 12:55:20 +0000</pubDate>
</item>
<item>
<title>Claude Code Ate My Storage, So I Asked Claude Code to Fix It</title>
<link>https://coderlegion.com/22833/claude-code-ate-my-storage-so-i-asked-claude-code-to-fix-it</link>
<description>&lt;p&gt;I knew AI tools and development work could take up storage, but using Claude Code ran through my space faster than you can say &quot;go.&quot;&lt;/p&gt;
&lt;p&gt;I started using Claude Code in the terminal in April, and honestly, it has been helpful. It helps me fix bugs faster, understand errors, and move through development quicker.&lt;/p&gt;
&lt;p&gt;But it has also helped me finish my storage quicker.&lt;/p&gt;
&lt;p&gt;At first, I did not realise how much space I was losing. I just kept working until Windows started reminding me that my storage was almost full every five minutes.&lt;/p&gt;
&lt;p&gt;So, naturally, my first instinct was to ask Claude Code how to fix the problem it had helped create.&lt;/p&gt;
&lt;p&gt;I asked it to give me a script that could clear about 15GB of storage.&lt;/p&gt;
&lt;p&gt;It gave me one.&lt;/p&gt;
&lt;h3 id=&quot;the-first-script&quot;&gt;The first script&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# --- CLAUDE CODE MASTER CLEANUP &amp;amp; OPTIMIZATION ---

# 1. AUTO-FIX: Set 2GB Node Memory Limit (Prevents 15GB Pagefile Bloat)
$varName = &quot;NODE_OPTIONS&quot;
$varValue = &quot;--max-old-space-size=2048&quot;
$currentValue = [Environment]::GetEnvironmentVariable($varName, &quot;User&quot;)

Write-Host &quot;⚙️  Optimizing system memory limits...&quot; -ForegroundColor Cyan
if ($currentValue -like &quot;*$varValue*&quot;) {
    Write-Host &quot;   - ✅ Memory limit is already correctly configured.&quot; -ForegroundColor Green
} else {
    $newValue = if ($currentValue) { &quot;$currentValue $varValue&quot; } else { $varValue }
    [Environment]::SetEnvironmentVariable($varName, $newValue, &quot;User&quot;)
    Write-Host &quot;   -  Applied 2GB limit to Windows User Variables.&quot; -ForegroundColor Yellow
}

# 2. KILL LEAKING PROCESSES (Releases locked RAM/Pagefile)
Write-Host &quot;`n Terminating orphaned Claude &amp;amp; MCP processes...&quot; -ForegroundColor Yellow
$procs = Get-Process -Name &quot;claude&quot;, &quot;node&quot; -ErrorAction SilentlyContinue | 
         Where-Object { $_.Path -match &quot;anthropic&quot; -or $_.CommandLine -match &quot;mcp&quot; }
if ($procs) {
    $procs | Stop-Process -Force
    Write-Host &quot;   - Closed $($procs.Count) ghost processes.&quot; -ForegroundColor Green
}

# 3. GLOBAL CACHE CLEANUP
$claudePath = &quot;$HOME\.claude&quot;
if (Test-Path $claudePath) {
    Write-Host &quot;`n Wiping global Claude cache (Logs, History, Temporary files)...&quot; -ForegroundColor Cyan
    $folders = &quot;debug&quot;, &quot;projects&quot;, &quot;file-history&quot;, &quot;image-cache&quot;, &quot;shell-snapshots&quot;, &quot;todos&quot;, &quot;plans&quot;
    foreach ($folder in $folders) {
        $subDir = Join-Path $claudePath $folder
        if (Test-Path $subDir) { 
            Remove-Item -Path &quot;$subDir\*&quot; -Recurse -Force -ErrorAction SilentlyContinue 
        }
    }
}

# 4. DEEP SCAN: Hidden Worktrees &amp;amp; Project Memory
$searchRoot = &quot;C:\code&quot; # &amp;lt;--- Change this to your main folder if different
Write-Host &quot;`n Deep scanning $searchRoot for hidden .claude folders...&quot; -ForegroundColor Cyan
$worktrees = Get-ChildItem -Path $searchRoot -Include &quot;worktrees&quot; -Recurse -Hidden -ErrorAction SilentlyContinue | 
             Where-Object { $_.FullName -match &quot;\.claude\\worktrees&quot; }

if ($worktrees) {
    $worktrees | ForEach-Object {
        Write-Host &quot;   - Removing: $($_.FullName)&quot; -ForegroundColor Gray
        Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
    }
} else {
    Write-Host &quot;   - No hidden worktrees found.&quot; -ForegroundColor Gray
}

# 5. FINAL SPACE AUDIT
$drive = Get-PSDrive C
$freeGB = [math]::Round($drive.Free / 1GB, 2)
Write-Host &quot;`n✨ CLEANUP COMPLETE!&quot; -ForegroundColor Green
Write-Host &quot; Current Free Space: $freeGB GB&quot; -ForegroundColor White
Write-Host &quot; IMPORTANT: RESTART YOUR PC NOW to shrink the Pagefile and reclaim the full 15GB.&quot; -ForegroundColor Magenta

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice section 5: it prints &lt;code&gt;reclaim the full 15GB&lt;/code&gt; as fixed text. It never measured anything. That one line is the whole reason the numbers never added up.&lt;/p&gt;
&lt;p&gt;I ran the script, and in the terminal it showed that around 15GB would be restored after restarting my PC.&lt;/p&gt;
&lt;p&gt;I restarted.&lt;/p&gt;
&lt;p&gt;I got back about 1GB.&lt;/p&gt;
&lt;p&gt;Sometimes it was even just a few hundred MBs.&lt;/p&gt;
&lt;p&gt;I ran the script again, and the same thing happened. The terminal would make it look like I was about to recover all this space, but when I checked my actual storage, almost nothing had changed.&lt;/p&gt;
&lt;p&gt;At first, I thought Claude had given me a bad script.&lt;/p&gt;
&lt;p&gt;But then I looked at my original prompt.&lt;/p&gt;
&lt;p&gt;I had asked it to create a script that would clear 15GB every time I ran it.&lt;/p&gt;
&lt;p&gt;That was the mistake.&lt;/p&gt;
&lt;p&gt;A script cannot clear 15GB when that number was never measured in the first place. The &quot;15GB&quot; was just hardcoded text the script printed every time, no matter what it actually deleted. I was asking it to give me a specific result instead of asking it to first check what was actually taking up space.&lt;/p&gt;
&lt;p&gt;So that part was not really Claude's fault. It was mine.&lt;/p&gt;
&lt;p&gt;My prompt should have been something like:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Check which folders are using the most storage, identify what can safely be deleted, calculate the real size of those files, and create a script that reports the actual space recovered.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That would have made more sense than telling it, &quot;Give me back 15GB.&quot;&lt;/p&gt;
&lt;p&gt;I also tried clearing the cache for some of my apps manually, but that created another problem. The apps had to download some of the same information again, which cost me data.&lt;/p&gt;
&lt;p&gt;I also ran &lt;code&gt;npm cache clean --force&lt;/code&gt;, thinking it would help. npm politely warned me it had disabled its own protections and that the cache rebuilds itself anyway — so that freed almost nothing and just meant re-downloading later. Same lesson as before: clearing caches feels productive but mostly costs you data when everything downloads again.&lt;/p&gt;
&lt;p&gt;I deleted ZIP files, old downloads, unused folders, extensions and other things I thought I no longer needed.&lt;/p&gt;
&lt;p&gt;Still, the storage situation did not improve as much as I expected.&lt;/p&gt;
&lt;p&gt;So today, I decided to put on my man pants and properly investigate the monster I had created.&lt;/p&gt;
&lt;p&gt;I now have a better script that checks the available storage before and after the cleanup, instead of promising that it will magically recover 15GB every time.&lt;/p&gt;
&lt;h3 id=&quot;the-improved-script&quot;&gt;The improved script&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# --- CLAUDE CODE MASTER CLEANUP &amp;amp; OPTIMIZATION (v2) ---

# 0. MEASURE BEFORE — so we can report what we actually freed
$beforeGB = [math]::Round((Get-PSDrive C).Free / 1GB, 2)
Write-Host &quot; Free space before cleanup: $beforeGB GB&quot; -ForegroundColor White

# 1. AUTO-FIX: Set 2GB Node Memory Limit (caps FUTURE Node memory growth)
$varName = &quot;NODE_OPTIONS&quot;
$varValue = &quot;--max-old-space-size=2048&quot;
$currentValue = [Environment]::GetEnvironmentVariable($varName, &quot;User&quot;)

Write-Host &quot;`n⚙️  Optimizing Node memory limit (affects future sessions)...&quot; -ForegroundColor Cyan
if ($currentValue -like &quot;*$varValue*&quot;) {
    Write-Host &quot;   - ✅ Memory limit already configured.&quot; -ForegroundColor Green
} else {
    $newValue = if ($currentValue) { &quot;$currentValue $varValue&quot; } else { $varValue }
    [Environment]::SetEnvironmentVariable($varName, $newValue, &quot;User&quot;)
    Write-Host &quot;   -  Applied 2GB cap to Windows User Variables.&quot; -ForegroundColor Yellow
}

# 2. KILL LEAKING PROCESSES
Write-Host &quot;`n Terminating orphaned Claude &amp;amp; MCP processes...&quot; -ForegroundColor Yellow
$procs = Get-Process -Name &quot;claude&quot;, &quot;node&quot; -ErrorAction SilentlyContinue |
         Where-Object { $_.Path -match &quot;anthropic&quot; -or $_.CommandLine -match &quot;mcp&quot; }
if ($procs) {
    $procs | Stop-Process -Force
    Write-Host &quot;   - Closed $($procs.Count) ghost processes.&quot; -ForegroundColor Green
} else {
    Write-Host &quot;   - No orphaned processes found.&quot; -ForegroundColor Gray
}

# 3. GLOBAL CACHE CLEANUP
$claudePath = &quot;$HOME\.claude&quot;
if (Test-Path $claudePath) {
    Write-Host &quot;`n Wiping global Claude cache (Logs, History, Temp files)...&quot; -ForegroundColor Cyan
    $folders = &quot;debug&quot;, &quot;projects&quot;, &quot;file-history&quot;, &quot;image-cache&quot;, &quot;shell-snapshots&quot;, &quot;todos&quot;, &quot;plans&quot;
    foreach ($folder in $folders) {
        $subDir = Join-Path $claudePath $folder
        if (Test-Path $subDir) {
            Remove-Item -Path &quot;$subDir\*&quot; -Recurse -Force -ErrorAction SilentlyContinue
        }
    }
}

# 4. DEEP SCAN: Hidden Worktrees
$searchRoot = &quot;C:\code&quot;   # &amp;lt;--- change to your main code folder if different
Write-Host &quot;`n Deep scanning $searchRoot for hidden .claude worktrees...&quot; -ForegroundColor Cyan
$worktrees = Get-ChildItem -Path $searchRoot -Include &quot;worktrees&quot; -Recurse -Hidden -ErrorAction SilentlyContinue |
             Where-Object { $_.FullName -match &quot;\.claude\\worktrees&quot; }

if ($worktrees) {
    $worktrees | ForEach-Object {
        Write-Host &quot;   - Removing: $($_.FullName)&quot; -ForegroundColor Gray
        Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
    }
} else {
    Write-Host &quot;   - No hidden worktrees found.&quot; -ForegroundColor Gray
}

# 5. FINAL SPACE AUDIT — report the REAL delta, not a guess
$afterGB = [math]::Round((Get-PSDrive C).Free / 1GB, 2)
$reclaimedGB = [math]::Round($afterGB - $beforeGB, 2)

Write-Host &quot;`n✨ CLEANUP COMPLETE!&quot; -ForegroundColor Green
Write-Host &quot; Before: $beforeGB GB  |  After: $afterGB GB&quot; -ForegroundColor White
Write-Host &quot;♻️  Actually reclaimed: $reclaimedGB GB&quot; -ForegroundColor White

if ($reclaimedGB -lt 1) {
    Write-Host &quot;ℹ️  Small gain is normal — most space here is cache/logs.&quot; -ForegroundColor Gray
    Write-Host &quot;    If your pagefile is system-managed and large, a reboot may free more.&quot; -ForegroundColor Gray
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The difference is small but honest: the new version takes a snapshot before it starts, another at the end, and reports the real difference. No more magic 15GB.&lt;/p&gt;
&lt;p&gt;So yey, progress.&lt;/p&gt;
&lt;p&gt;At this point, I may still need to increase my storage or finally accept that this PC has served its time and purpose.&lt;/p&gt;
&lt;p&gt;Unless someone here knows a safe way to clear Windows storage without deleting important project files or forcing my apps to download everything again.&lt;/p&gt;
&lt;p&gt;Has anyone else had their storage disappear while using Claude Code or other AI development tools?&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/22833/claude-code-ate-my-storage-so-i-asked-claude-code-to-fix-it</guid>
<pubDate>Thu, 16 Jul 2026 16:09:41 +0000</pubDate>
</item>
<item>
<title>your AI coding agent keeps re-making the bug you already fixed. here's the fix.</title>
<link>https://coderlegion.com/21972/your-ai-coding-agent-keeps-re-making-the-bug-you-already-fixed-heres-the-fix</link>
<description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/masondelan/your-ai-coding-agent-keeps-re-making-the-bug-you-already-fixed-heres-the-fix-3mg8&quot;&gt;dev.to&lt;/a&gt; on June 9, 2026.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;for the last few releases selvedge has been a write-only thing. an AI agent edits a column, calls &lt;code&gt;log_change&lt;/code&gt;, and the reasoning gets captured into a little SQLite file under &lt;code&gt;.selvedge/&lt;/code&gt; next to your code. useful, but one-directional. the agent wrote to the store and then never looked at it again.&lt;/p&gt;
&lt;p&gt;v0.3.7 is the release where that flips. there's a new MCP tool called &lt;code&gt;prior_attempts&lt;/code&gt;, and the whole point of it is that the agent calls it &lt;em&gt;before&lt;/em&gt; it changes something — not after. before editing &lt;code&gt;users.email&lt;/code&gt;, the agent asks selvedge: what happened the last time someone touched this? who tried what, when, and why was it reverted?&lt;/p&gt;
&lt;p&gt;this is the brand-defining release, so let me walk through why it's built the way it is.&lt;/p&gt;
&lt;h3 id=&quot;the-default-flow-used-to-be-one-directional&quot;&gt;the default flow used to be one-directional&lt;/h3&gt;
&lt;p&gt;here's what selvedge looked like through v0.3.6. an agent refactors &lt;code&gt;users.email&lt;/code&gt;, and on its way out it calls &lt;code&gt;log_change&lt;/code&gt; with a reasoning string — &quot;tightened the email validator to reject plus-addressing per the billing team's request.&quot; that reasoning lands in the store. later, a human runs &lt;code&gt;selvedge blame users.email&lt;/code&gt; from the CLI and reads it back.&lt;/p&gt;
&lt;p&gt;that's the same posture every code-attribution tool has. git blame, AgentDiff, Origin, all of them. the reasoning is &lt;em&gt;captured-then-read&lt;/em&gt;. the capture is one event in time; the read is a separate, asynchronous act by a different actor — usually a person, usually weeks later, usually because something already broke.&lt;/p&gt;
&lt;p&gt;for a human-written codebase that's fine. people carry context between sessions. they remember &quot;oh right, we tried that in march.&quot; the audit trail is a backup for the memory, not the memory itself.&lt;/p&gt;
&lt;h3 id=&quot;prior-attempts-is-the-asking-primitive&quot;&gt;&lt;code&gt;prior_attempts&lt;/code&gt; is the asking primitive&lt;/h3&gt;
&lt;p&gt;so v0.3.7 adds the tool that does the asking. it's pull-model — the agent calls it, selvedge doesn't push. given a description or an &lt;code&gt;entity_path&lt;/code&gt;, it returns prior change events at the same path (or the same shape) with their reasoning, their change_type, and an inferred outcome.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;gt; prior_attempts(entity_path=&quot;users.email&quot;)

2 prior attempts at users.email:

[2026-03-14]  rename -&amp;gt; users.email_address   (reverted 2026-03-17)
  reasoning: &quot;renamed for consistency with users.phone_number&quot;
  outcome:   reverted — billing reconciliation join keyed on the
             literal column name; case-sensitivity broke the nightly job

[2026-01-22]  alter -&amp;gt; tighten type to citext  (abandoned)
  reasoning: &quot;case-insensitive comparison at the db layer&quot;
  outcome:   no follow-up commit; superseded by app-layer validation
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the agent now has the context march-mason wrote down. and it does the thing the whole release is built to enable: it changes plan. it doesn't rename the column. it keeps &lt;code&gt;users.email&lt;/code&gt;, hardens the validator at the app layer instead, and notes in its own &lt;code&gt;log_change&lt;/code&gt; that it checked prior_attempts first. the loop closes.&lt;/p&gt;
&lt;p&gt;no LLM call happens anywhere in there, by the way. the output is templated — selvedge assembles it deterministically from the rows in SQLite. that's a hard rule in the core: no model hops, no API key, no network, no non-determinism that's miserable to test. &lt;code&gt;prior_attempts&lt;/code&gt; is a query and a string template, nothing more.&lt;/p&gt;
&lt;h3 id=&quot;why-the-trust-budget-is-non-negotiable&quot;&gt;why the trust budget is non-negotiable&lt;/h3&gt;
&lt;p&gt;here's the design decision i went back and forth on the most. &lt;code&gt;prior_attempts&lt;/code&gt; returns &lt;em&gt;high-confidence results only&lt;/em&gt; by default.&lt;/p&gt;
&lt;p&gt;the way it infers &quot;outcome&quot; in v0.3.7 is by proximity: an add followed closely by a remove of the same entity reads as &quot;tried and pulled back.&quot; that's a heuristic, and heuristics have a noisy tail. so every result carries a &lt;code&gt;confidence&lt;/code&gt; field — &lt;code&gt;proximity_high&lt;/code&gt; or &lt;code&gt;proximity_low&lt;/code&gt; — and the default response gives you &lt;code&gt;proximity_high&lt;/code&gt; only. if you want the noisy long tail you have to explicitly ask for it with &lt;code&gt;min_confidence=&quot;proximity_low&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;the reason is the trust budget, and you only get one shot at it. the moment &lt;code&gt;prior_attempts&lt;/code&gt; hands an agent a confident-looking false positive, the agent learns the tool is noise and starts ignoring it — and a tool the agent ignores is dead. an empty result is recoverable. a wrong result is not. so the default is tuned to prefer returning nothing over returning something wrong.&lt;/p&gt;
&lt;p&gt;this is the same discipline as &lt;code&gt;selvedge verify&lt;/code&gt;'s two-tier exit codes from v0.3.5: build the strict floor first, then give the caller a knob to relax it if they want. conservative defaults are what keep the mechanism honest. the precise classifier comes later — v0.3.11 ships explicit &lt;code&gt;reject&lt;/code&gt; and &lt;code&gt;revert&lt;/code&gt; change_types so the high-confidence tier gets &lt;em&gt;more&lt;/em&gt; accurate without the API changing at all.&lt;/p&gt;
&lt;h3 id=&quot;the-entity-foundation-that-had-to-ship-in-the-same-release&quot;&gt;the entity foundation that had to ship in the same release&lt;/h3&gt;
&lt;p&gt;you cannot ship a lookup tool when &lt;code&gt;./src/auth.py::login&lt;/code&gt; and &lt;code&gt;src/auth.py::login&lt;/code&gt; store as two different entities. if they do, the recall problem masquerades as &quot;prior_attempts didn't find anything,&quot; the agent proceeds confidently, and the tool has actively &lt;em&gt;misled&lt;/em&gt; it — worse than not existing. so the canonicalization had to land first, inside the same release.&lt;/p&gt;
&lt;p&gt;canonicalization on write is deterministic and boring on purpose: strip a leading &lt;code&gt;./&lt;/code&gt;, collapse &lt;code&gt;//&lt;/code&gt;, normalize separators to &lt;code&gt;/&lt;/code&gt;, trim whitespace. one chokepoint that both the MCP write path and the CLI go through, so nothing writes a non-canonical path after this release.&lt;/p&gt;
&lt;p&gt;the one decision worth calling out: &lt;strong&gt;case is preserved, deliberately.&lt;/strong&gt; filesystems disagree — macOS and windows are case-insensitive by default, most linux hosts are case-sensitive. if selvedge silently lowercased everything, it would collapse two entities that are genuinely distinct on a case-sensitive host. so it preserves case, and &lt;code&gt;selvedge doctor&lt;/code&gt; grows a should-warn row that flags sibling paths differing only by case, so you find out instead of getting a silent merge.&lt;/p&gt;
&lt;p&gt;for existing databases there's &lt;code&gt;selvedge migrate-paths&lt;/code&gt;. it's &lt;code&gt;--dry-run&lt;/code&gt; by default — you have to pass &lt;code&gt;--apply&lt;/code&gt; to write anything — and the dry run prints a collisions report showing which pre-canonicalization paths would converge to the same value. you get to look at the merge before it happens. it's idempotent, and every run drops an audit row into a new &lt;code&gt;path_migrations&lt;/code&gt; table so the operation stays visible.&lt;/p&gt;
&lt;p&gt;and the explicit non-goal, because it comes up every time: &lt;strong&gt;no code parser, no AST.&lt;/strong&gt; selvedge does not read your source and extract entities. it stores what the agent tells it, canonicalized and queryable. AST work is language-specific, drags in a pile of dependencies, and fights the dependency-free-core rule that keeps the install at three deps. it's a line i'm holding.&lt;/p&gt;
&lt;h3 id=&quot;what-the-prompt-block-changes&quot;&gt;what the prompt block changes&lt;/h3&gt;
&lt;p&gt;a new MCP tool that nobody calls is worthless, and agents don't spontaneously discover query tools. so the flywheel is one line in the agent's instruction block. &lt;code&gt;selvedge prompt&lt;/code&gt; now &lt;em&gt;leads&lt;/em&gt; with:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Before editing an entity, call &lt;code&gt;prior_attempts&lt;/code&gt; on it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;that's the first instruction now, not a footnote under the &lt;code&gt;log_change&lt;/code&gt; guidance. it's what turns write-only agents into read-then-write agents. without it, the whole release is a tool sitting in a listing that never fires.&lt;/p&gt;
&lt;p&gt;existing users get the change cleanly because the prompt block is sentinel-bracketed (the &lt;code&gt;&amp;lt;!-- selvedge:start --&amp;gt;&lt;/code&gt; / &lt;code&gt;&amp;lt;!-- selvedge:end --&amp;gt;&lt;/code&gt; markers from v0.3.4). run &lt;code&gt;selvedge prompt --install CLAUDE.md&lt;/code&gt; and only the bracketed region updates — the rest of your prompt file is untouched.&lt;/p&gt;
&lt;p&gt;this brings the MCP surface to 7 tools. exactly one new tool this release — rename support folded into &lt;code&gt;log_change&lt;/code&gt; as a parameter rather than its own tool, and the aggregate-digest helper shipped as a plain library function instead of a tool. keeping the surface small is its own discipline.&lt;/p&gt;
&lt;h3 id=&quot;what-s-next&quot;&gt;what's next&lt;/h3&gt;
&lt;p&gt;v0.3.7 makes the wedge legible. the next releases make it &lt;em&gt;visible&lt;/em&gt; where you already work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;v0.3.9&lt;/strong&gt; brings the developer-facing CLI surface: &lt;code&gt;selvedge audit&lt;/code&gt; (flags PRs that changed code without logging why), &lt;code&gt;selvedge digest&lt;/code&gt; (summarizes recent activity per entity), &lt;code&gt;selvedge pr-comment&lt;/code&gt; (drops the relevant &lt;code&gt;prior_attempts&lt;/code&gt; hits straight into a PR review).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;v0.3.11&lt;/strong&gt; ships explicit &lt;code&gt;reject&lt;/code&gt; / &lt;code&gt;revert&lt;/code&gt; change_types so the proximity classifier becomes a precise one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;v0.4.0&lt;/strong&gt; lifts the whole thing onto an optional HTTP + Postgres layer so teams stop fighting per-machine SQLite — still self-hosted, still never sending your data anywhere.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;if you want to try the read-before-you-edit flow:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pip install selvedge==0.3.7
selvedge setup        # detects claude code / cursor / copilot
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then point your agent at a repo with some history and ask it to refactor something you've touched before. watch it call &lt;code&gt;prior_attempts&lt;/code&gt; and think twice.&lt;/p&gt;
&lt;p&gt;changelog: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/masondelan/selvedge/releases/tag/v0.3.7&quot;&gt;https://github.com/masondelan/selvedge/releases/tag/v0.3.7&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(a 60-second clip of claude code calling prior_attempts mid-task and changing course is coming — i'll add it to this post once it's up.)&lt;/p&gt;
&lt;p&gt;it's open source, MIT, runs entirely on your machine. happy to answer anything about the proximity classifier or the canonicalization rules in the comments.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/21972/your-ai-coding-agent-keeps-re-making-the-bug-you-already-fixed-heres-the-fix</guid>
<pubDate>Mon, 06 Jul 2026 01:15:02 +0000</pubDate>
</item>
<item>
<title>The silent problem with AI-written code: the intent evaporates</title>
<link>https://coderlegion.com/21971/the-silent-problem-with-ai-written-code-the-intent-evaporates</link>
<description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/masondelan/the-silent-problem-with-ai-written-code-the-intent-evaporates-14c4&quot;&gt;dev.to&lt;/a&gt; on April 24, 2026.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There's a problem with AI-written code that nobody talks about yet, because most of us haven't been using AI agents long enough for it to bite us.&lt;/p&gt;
&lt;p&gt;The problem is this: &lt;strong&gt;AI agents know exactly why they made every decision. And then the session ends.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-happens-with-human-code&quot;&gt;What happens with human code&lt;/h3&gt;
&lt;p&gt;When humans write code, intent leaks everywhere. It's in the commit message (&quot;Add phone field for 2FA rollout&quot;), the PR description, the Slack thread that preceded it, the inline comment that explains the weird edge case. You can reconstruct &lt;em&gt;why&lt;/em&gt; a decision was made months later because the evidence trail is thick.&lt;/p&gt;
&lt;p&gt;This works because humans understand that their code will outlast their memory of writing it.&lt;/p&gt;
&lt;h3 id=&quot;what-happens-with-ai-written-code&quot;&gt;What happens with AI-written code&lt;/h3&gt;
&lt;p&gt;An AI agent has perfect clarity about why it's making each change — right up until the conversation ends.&lt;/p&gt;
&lt;p&gt;Run &lt;code&gt;git blame&lt;/code&gt; six months later:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;3e7a991 (Claude Code  2025-10-14)  user_tier_v2 VARCHAR(20)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Commit message: &lt;code&gt;&quot;Update schema&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The agent knew why. It added &lt;code&gt;user_tier_v2&lt;/code&gt; to support a grandfathering flag during a pricing migration. It stored the original tier so you could backfill discounts without touching billing history. It was a careful, intentional decision — and that context is completely gone.&lt;/p&gt;
&lt;p&gt;This isn't a hypothetical. If you've been using AI coding tools for more than a few months, you've already hit this wall. You just might not have noticed yet.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-pandas-moment&quot;&gt;The pandas moment&lt;/h3&gt;
&lt;p&gt;When pandas came out, data scientists were doing data manipulation with raw Python loops and NumPy. The problem wasn't that it was &lt;em&gt;impossible&lt;/em&gt; — it was that there was no shared infrastructure for it, so everyone was reinventing the same patterns badly.&lt;/p&gt;
&lt;p&gt;Pandas became essential infrastructure. Not a feature, not a nice-to-have — &lt;em&gt;infrastructure&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I think codebase change tracking is the same problem for AI-era development. Right now, every team using AI agents heavily is slowly accumulating a codebase full of decisions that made perfect sense when the agent made them and are increasingly opaque to everyone who touches the code afterward.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;selvedge&quot;&gt;Selvedge&lt;/h3&gt;
&lt;p&gt;I built &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/masondelan/selvedge&quot;&gt;Selvedge&lt;/a&gt; to capture that reasoning before it's gone.&lt;/p&gt;
&lt;p&gt;It's an MCP server. AI agents (starting with Claude Code) call it as they work to log structured change events — what changed, when, which agent, which commit, and crucially: &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ selvedge blame users.stripe_customer_id

  users.stripe_customer_id
  Changed     2026-03-14 11:22:01
  Agent       claude-code
  Commit      9c3f441
  Reasoning   User asked to add Stripe billing — needs customer ID to link
              accounts to subscriptions without storing card details locally.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That &lt;code&gt;Reasoning&lt;/code&gt; field is captured from the agent's context in the moment, before the session ends. It's not generated by Selvedge — Selvedge just captures what the agent already knows and stores it somewhere you can query later.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;how-it-works&quot;&gt;How it works&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Setup is three steps:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pip install selvedge
cd your-project &amp;amp;&amp;amp; selvedge init
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add to your Claude Code config (&lt;code&gt;~/.claude/config.json&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;mcpServers&quot;: {
 &quot;selvedge&quot;: { &quot;command&quot;: &quot;selvedge-server&quot; }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a few lines to your project's &lt;code&gt;CLAUDE.md&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;You have access to Selvedge for change tracking.
Call selvedge.log_change immediately after adding, modifying, or removing
any DB column, table, function, API endpoint, dependency, or env variable.
Set reasoning to the user's original request or the problem being solved.
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;From then on, your agent logs changes automatically as it works.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;querying-your-history&quot;&gt;Querying your history&lt;/h3&gt;
&lt;p&gt;The CLI is built for how you actually investigate codebases:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# What changed in the users table in the last 30 days?
selvedge diff users --since 30d

# What was the last change to payments.amount and why?
selvedge blame payments.amount

# Everything related to the Stripe billing feature
selvedge search &quot;stripe&quot;

# How often is my agent actually logging changes?
selvedge stats
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There's also a changeset system — you can tag related changes under a shared slug (&lt;code&gt;&quot;add-stripe-billing&quot;&lt;/code&gt;) and reconstruct the full scope of a feature across multiple entities later:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;selvedge history --changeset add-stripe-billing
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;backfilling-existing-projects&quot;&gt;Backfilling existing projects&lt;/h3&gt;
&lt;p&gt;If you already have a project with migration files, you don't have to start from zero:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;selvedge import ./migrations/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It parses raw SQL DDL and Alembic Python files and backfills your schema history. Not as rich as captured reasoning, but better than nothing.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-s-next-1&quot;&gt;What's next&lt;/h3&gt;
&lt;p&gt;Right now Selvedge uses local SQLite, which works great for individual developers and small teams with a shared volume. Phase 3 is a PostgreSQL backend and HTTP REST API so teams can share a history across machines — that's the path to making this a proper team tool.&lt;/p&gt;
&lt;p&gt;The core insight I keep coming back to: &lt;strong&gt;the diff is git's job. The why is Selvedge's job.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;If you've been using Claude Code or Cursor heavily and have felt this pain, I'd love to hear how you've been handling it (or whether you've just been living with it). And if you try Selvedge, feedback on what's missing would go a long way.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Current version: v0.3.1&lt;/strong&gt; — shipped today (April 23, 2026). It's a hardening release: connection-with-retry and &lt;code&gt;PRAGMA busy_timeout = 5000&lt;/code&gt; so concurrent writes are safe under contention (tested against 8 threads writing simultaneously), an explicit &lt;code&gt;schema_migrations&lt;/code&gt; table replacing the old swallow-OperationalError-and-pray ALTER pattern, structured logging under the &lt;code&gt;selvedge.*&lt;/code&gt; namespace (&lt;code&gt;SELVEDGE_LOG_LEVEL=DEBUG&lt;/code&gt; to turn it up), and a frozen public API surface locked in by test. The preceding release (v0.3.0) was a correctness pass that caught a pile of silent-wrong-answer bugs: &lt;code&gt;--since 5m&lt;/code&gt; used to mean 5 months instead of 5 minutes; SQL &lt;code&gt;LIKE&lt;/code&gt; wasn't escaping &lt;code&gt;_&lt;/code&gt; or &lt;code&gt;%&lt;/code&gt; in search queries; &lt;code&gt;CREATE TABLE&lt;/code&gt; import emitted zero events for inline columns; mixed-timezone timestamps sorted incorrectly because &lt;code&gt;-08:00&lt;/code&gt; is less than &lt;code&gt;+00:00&lt;/code&gt; in ASCII. Both are recommended upgrades.&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/masondelan/selvedge&quot;&gt;https://github.com/masondelan/selvedge&lt;/a&gt;&lt;br&gt;
Install: &lt;code&gt;pip install selvedge&lt;/code&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/21971/the-silent-problem-with-ai-written-code-the-intent-evaporates</guid>
<pubDate>Mon, 06 Jul 2026 01:14:53 +0000</pubDate>
</item>
<item>
<title>Claude Opus 4.8 vs Claude Fable 5: Which Model Should You Actually Use?</title>
<link>https://coderlegion.com/20211/claude-opus-4-8-vs-claude-fable-5-which-model-should-you-actually-use</link>
<description>&lt;p&gt;Anthropic now ships two models that both feel like &quot;the best one&quot;: Claude Opus 4.8, the top of the long-running Opus family, and Claude Fable 5, a brand-new tier that sits above Opus entirely. If you build with these models, the practical question isn't &quot;which is better&quot; - it's &quot;which one do I send each task to, and is the more expensive one worth it?&quot;&lt;/p&gt;
&lt;p&gt;This is a developer-focused, no-hype comparison of Claude Opus 4.8 vs Claude Fable 5: where they're identical, where they differ in ways that actually affect your code and your bill, and a clear decision guide. Everything here is grounded in Anthropic's model and API documentation - no invented benchmarks.&lt;/p&gt;
&lt;p&gt;TL;DR&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fable 5 is the most capable model - a new tier above Opus - at roughly double the price (USD 10/USD 50 vs USD 5/USD 25 per million tokens).&lt;/li&gt;
&lt;li&gt;Opus 4.8 is the top of the Opus family, a strong default in Claude Code, and the better capability-per-dollar choice for most hard work.&lt;/li&gt;
&lt;li&gt;They share almost the entire API surface. The one breaking difference: setting the thinking type to disabled is accepted on Opus 4.8 but returns 400 on Fable 5 (omit the thinking field instead).&lt;/li&gt;
&lt;li&gt;Decision rule: default to Opus 4.8; escalate to Fable 5 only for the tasks where a wrong answer is expensive.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Lineup Context&lt;/p&gt;
&lt;p&gt;Until Fable 5, &quot;Opus&quot; was the top of the Claude ladder. Fable 5 adds a rung above it. The full 2026 family, from most to least capable:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Claude Fable 5 - peak capability, premium price&lt;/li&gt;
&lt;li&gt;Claude Opus 4.8 - top of the Opus family, strong all-rounder&lt;/li&gt;
&lt;li&gt;Claude Sonnet 4.6 - balanced daily driver, 1M context&lt;/li&gt;
&lt;li&gt;Claude Haiku 4.5 - light, fast, cheap&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So &quot;Opus 4.8 vs Fable 5&quot; is really a question about the top two rungs: when is the absolute peak worth paying for, and when is the top-of-Opus model already enough? For a structured, side-by-side breakdown of the whole 2026 lineup, there's a dedicated AI model comparison course (&lt;a rel=&quot;nofollow&quot; href=&quot;https://cursuri-ai.ro/courses/comparatie-modele-ai&quot;&gt;https://cursuri-ai.ro/courses/comparatie-modele-ai&lt;/a&gt;) that goes further than any single article can.&lt;/p&gt;
&lt;p&gt;The Spec Differences at a Glance&lt;/p&gt;
&lt;p&gt;Claude Opus 4.8&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tier: top of the Opus family&lt;/li&gt;
&lt;li&gt;Model ID: claude-opus-4-8&lt;/li&gt;
&lt;li&gt;Price: USD 5 / USD 25 per 1M tokens (input / output)&lt;/li&gt;
&lt;li&gt;thinking: disabled: accepted&lt;/li&gt;
&lt;li&gt;Min cacheable prefix: ~4,096 tokens&lt;/li&gt;
&lt;li&gt;Role in Claude Code: strong default&lt;/li&gt;
&lt;li&gt;Released: late May 2026&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Claude Fable 5&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tier: a new tier above Opus (most capable)&lt;/li&gt;
&lt;li&gt;Model ID: claude-fable-5&lt;/li&gt;
&lt;li&gt;Price: USD 10 / USD 50 per 1M tokens (input / output)&lt;/li&gt;
&lt;li&gt;thinking: disabled: returns 400 - omit the param instead&lt;/li&gt;
&lt;li&gt;Min cacheable prefix: ~2,048 tokens&lt;/li&gt;
&lt;li&gt;Role in Claude Code: selectable peak&lt;/li&gt;
&lt;li&gt;Released: newer (2026)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Identical on both: 1M-token context window, 128K max output, adaptive thinking, the full effort range (low-max, including xhigh), sampling params removed (temperature/top_p/top_k all return 400), and last-assistant-turn prefills removed (400).&lt;/p&gt;
&lt;p&gt;Two of those differences do most of the work for an engineering decision: price (2x) and the thinking: disabled gotcha. We'll come back to both.&lt;/p&gt;
&lt;p&gt;Where They're Identical (Don't Agonize Over These)&lt;/p&gt;
&lt;p&gt;A lot of the &quot;which model&quot; anxiety evaporates once you realize how much these two share. Both Opus 4.8 and Fable 5:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use adaptive thinking (the thinking type set to adaptive) - the model regulates its own reasoning depth; there's no token budget to tune.&lt;/li&gt;
&lt;li&gt;Expose the same effort parameter (low through max, including xhigh), with xhigh as the sweet spot for coding and agentic work.&lt;/li&gt;
&lt;li&gt;Reject sampling parameters - temperature, top_p, and top_k all return 400. You steer behavior with prompting and effort.&lt;/li&gt;
&lt;li&gt;Reject last-assistant-turn prefills (400). Use structured outputs (output_config.format) instead.&lt;/li&gt;
&lt;li&gt;Support structured outputs, prompt caching, server-side compaction, web search with dynamic filtering, and task budgets (beta).&lt;/li&gt;
&lt;li&gt;Share a 1M context window and 128K max output (stream anything above ~16K max_tokens to avoid SDK timeouts).&lt;/li&gt;
&lt;li&gt;Hide thinking text by default - set the thinking display to summarized if you surface reasoning in a UI.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In other words: code written for one mostly runs on the other. The differences are about positioning and economics, plus one sharp API edge.&lt;/p&gt;
&lt;p&gt;Where They Differ (The Decision-Relevant Deltas)&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Capability tier&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Fable 5 is genuinely a level above Opus 4.8 - it's positioned for the hardest reasoning, planning, cross-cutting refactors, and long-horizon agent runs. Opus 4.8 is no slouch; it's the top of the Opus family and handles complex day-to-day work well. The gap shows up at the extreme end of difficulty, not on routine tasks.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Price (the 2x that decides everything)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Fable 5 costs about double Opus 4.8 per token. This single fact should drive your architecture: you don't run a pipeline entirely on Fable 5 any more than you'd hire your most expensive specialist to answer the phone. You route the hard parts to it and let cheaper models do the rest.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The thinking: disabled gotcha (will break your code)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is the one difference that bites in practice. On Opus 4.8, you can explicitly disable thinking: you pass a thinking field with its type set to disabled, and the request succeeds.&lt;/p&gt;
&lt;p&gt;Send that exact request to Fable 5 and you get a 400. To run Fable 5 without thinking, you do NOT set the type to disabled - you omit the thinking field entirely, and the model runs with no thinking and no error.&lt;/p&gt;
&lt;p&gt;So the rule when you swap the model ID: on Opus 4.8, a thinking type of disabled is valid; on Fable 5, drop the thinking field instead. If you have a shared wrapper that parametrizes the model, this is the line that will surprise you. Guard it.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Caching minimum prefix&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Opus 4.8 only caches prefixes of ~4,096 tokens or more; Fable 5 caches from ~2,048 tokens. Concretely: a ~3K-token system prompt will be cached on Fable 5 but silently won't cache on Opus 4.8 (no error - cache_creation_input_tokens just stays 0). If you rely on prompt caching to control cost, check this when you switch models.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Default vs. peak&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In Claude Code, Opus 4.8 remains a strong default; Fable 5 is the tier you select for the hardest work. &quot;Most capable&quot; and &quot;the default&quot; are different claims - don't conflate them.&lt;/p&gt;
&lt;p&gt;Switching Between Them Without Breaking Things&lt;/p&gt;
&lt;p&gt;If your code parametrizes the model ID, run through this checklist before you flip the switch - most &quot;it worked on Opus, it 400s on Fable&quot; bugs are on this list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Disabling thinking: omit the field, don't set it to disabled. The single most common break on Fable 5; drop the field entirely.&lt;/li&gt;
&lt;li&gt;Re-check your cache hits. A prefix that caches on Fable 5 (at least ~2K tokens) can fall below Opus 4.8's ~4K minimum, or vice versa. Watch cache_read_input_tokens after switching - a silent 0 means the prefix is now too short to cache, and you'll quietly pay full price on every request.&lt;/li&gt;
&lt;li&gt;Re-tune effort, don't assume. xhigh on Fable 5 and xhigh on Opus 4.8 produce different cost and latency profiles. Sweep medium / high / xhigh per route after the swap instead of carrying the old setting over.&lt;/li&gt;
&lt;li&gt;Budget for the price delta. A wrapper that silently routes everything to Fable 5 doubles your token bill overnight. Make escalation to the top tier explicit and intentional, not a default.&lt;/li&gt;
&lt;li&gt;The rest is shared. Adaptive thinking, removed sampling params, no prefills, structured outputs, and streaming for large max_tokens all behave the same - so you don't need model-specific branches for those.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A thin abstraction that exposes model and effort as per-task config (rather than hard-coding one model everywhere) turns this kind of switch into a one-line change instead of a refactor - and makes A/B-ing the two models trivial.&lt;/p&gt;
&lt;p&gt;The Cost Math: When Is 2x Worth It?&lt;/p&gt;
&lt;p&gt;&quot;Use the best model&quot; is bad engineering advice. The right framing is: Fable 5 pays off when the cost of a wrong answer exceeds the extra token cost.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Send to Fable 5: the planning step that sets the trajectory of a long agent run; a complex cross-service refactor where a subtle regression costs hours of review; an analysis where correctness is non-negotiable.&lt;/li&gt;
&lt;li&gt;Keep on Opus 4.8 (or below): routine edits, summaries, classification, and the long tail of mechanical sub-tasks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A clean pattern that keeps your bill proportional to difficulty: let Fable 5 plan and decide, and let Opus 4.8 / Sonnet 4.6 execute the parts that are already well-specified. If you're building this kind of tiered routing into an agent, the orchestration patterns are worth studying properly - this course on designing autonomous AI agents (&lt;a rel=&quot;nofollow&quot; href=&quot;https://cursuri-ai.ro/courses/ai-agents-automatizare&quot;&gt;https://cursuri-ai.ro/courses/ai-agents-automatizare&lt;/a&gt;) and a Claude Code mastery course (&lt;a rel=&quot;nofollow&quot; href=&quot;https://cursuri-ai.ro/courses/claude-code-mastery-coding-agentic&quot;&gt;https://cursuri-ai.ro/courses/claude-code-mastery-coding-agentic&lt;/a&gt;) both cover model routing as a first-class concern rather than an afterthought.&lt;/p&gt;
&lt;p&gt;Don't forget effort as a second lever. Because effort matters more on this generation than on any prior Opus, a Fable 5 call at medium can sometimes be cheaper and faster than an Opus 4.8 call at xhigh. The only way to know for your workload is to measure.&lt;/p&gt;
&lt;p&gt;How to Actually Decide: Eval It, Don't Argue About It&lt;/p&gt;
&lt;p&gt;Spec differences tell you what might matter. They can't tell you whether Fable 5's extra capability moves the needle on your task. The only reliable answer comes from running both models against a representative slice of your real work and scoring the outputs.&lt;/p&gt;
&lt;p&gt;That means a small eval harness: a fixed set of inputs, a scoring rubric (exact-match, an LLM judge, or a task-specific check), and a side-by-side run of claude-opus-4-8 vs claude-fable-5 at the effort levels you'd actually use. You don't need a giant benchmark to get a signal - even 20 to 50 representative cases from your real traffic are usually enough to tell whether the 2x is buying you a measurable quality lift or just a bigger invoice. If Fable 5 wins by enough to justify 2x the cost on the hard subset, route that subset to it. If it doesn't, you just saved money with data instead of vibes. Building that discipline is exactly what a course on AI evals for LLMs in production (&lt;a rel=&quot;nofollow&quot; href=&quot;https://cursuri-ai.ro/courses/ai-evals-llm-productie&quot;&gt;https://cursuri-ai.ro/courses/ai-evals-llm-productie&lt;/a&gt;) is for - testing, scoring, and quality gates before you commit a model to production.&lt;/p&gt;
&lt;p&gt;The quality of your prompts also shifts the result. Since both models are steered through prompting and effort rather than sampling parameters, a sloppy prompt can make the expensive model look only marginally better than the cheap one. A structured refresh of prompt engineering fundamentals (&lt;a rel=&quot;nofollow&quot; href=&quot;https://cursuri-ai.ro/courses/prompt-engineering-masterclass&quot;&gt;https://cursuri-ai.ro/courses/prompt-engineering-masterclass&lt;/a&gt;) often closes more of the gap than upgrading the model does. And if you're wiring either model into a real application, the building-AI-apps-with-the-Anthropic-SDK course (&lt;a rel=&quot;nofollow&quot; href=&quot;https://cursuri-ai.ro/courses/construire-aplicatii-ai-python-sdk&quot;&gt;https://cursuri-ai.ro/courses/construire-aplicatii-ai-python-sdk&lt;/a&gt;) walks the full path from raw API calls to production.&lt;/p&gt;
&lt;p&gt;The Verdict&lt;/p&gt;
&lt;p&gt;There's no single winner - there's a routing decision:&lt;/p&gt;
&lt;p&gt;Reach for Opus 4.8 when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You want the best capability-per-dollar for hard work.&lt;/li&gt;
&lt;li&gt;You're building on Claude Code and want a strong, cost-sane default.&lt;/li&gt;
&lt;li&gt;You need to explicitly disable thinking via the API (it's accepted here).&lt;/li&gt;
&lt;li&gt;Your cacheable prefixes are comfortably above ~4K tokens.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reach for Fable 5 when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The task is at the extreme end of difficulty and a wrong answer is expensive.&lt;/li&gt;
&lt;li&gt;It's the planning/decision step that steers a long agent run.&lt;/li&gt;
&lt;li&gt;You've measured a real quality lift on your own eval that justifies the 2x cost.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Conclusion&lt;/p&gt;
&lt;p&gt;Claude Opus 4.8 vs Claude Fable 5 isn't a fight to crown one model - it's a two-rung ladder you climb only when the task demands it. Default to Opus 4.8, escalate to Fable 5 where correctness compounds, tune effort per route, and let an eval (not a launch-day headline) make the final call. Do that, and the more expensive model becomes a precision instrument instead of a surprise on your invoice.&lt;/p&gt;
&lt;p&gt;The courses linked throughout are part of Cursuri-AI.ro (&lt;a rel=&quot;nofollow&quot; href=&quot;https://cursuri-ai.ro/courses/comparatie-modele-ai&quot;&gt;https://cursuri-ai.ro/courses/comparatie-modele-ai&lt;/a&gt;), a Romanian AI-learning platform with hands-on tracks on model selection, evals, Claude Code, agent architecture, and the Anthropic SDK - all kept current with the 2026 lineup, Fable 5 and Opus 4.8 included.&lt;/p&gt;
&lt;p&gt;Which one are you routing your hard tasks to - and where did the 2x actually pay off? Drop your routing strategy in the comments.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/20211/claude-opus-4-8-vs-claude-fable-5-which-model-should-you-actually-use</guid>
<pubDate>Wed, 10 Jun 2026 22:45:54 +0000</pubDate>
</item>
<item>
<title>When Your AI Stops Pretending to Know the Answer</title>
<link>https://coderlegion.com/19419/when-your-ai-stops-pretending-to-know-the-answer</link>
<description>&lt;p&gt;AI models have a confidence problem. They generate clean, authoritative output — even when the underlying reasoning is shaky. For developers, that's not just annoying. It costs time.&lt;/p&gt;
&lt;p&gt;Anthropic's latest release, Claude Opus 4.8, is built to address this directly. The model is more likely to flag uncertainty and less likely to assert claims it can't support. According to Anthropic's internal evaluations, Opus 4.8 is roughly four times less likely than its predecessor to let flaws in generated code pass without remarking on them.&lt;/p&gt;
&lt;p&gt;That's a meaningful shift in how the model behaves during the work that matters most.&lt;/p&gt;
&lt;h3 id=&quot;the-confidence-problem-in-code&quot;&gt;The Confidence Problem in Code&lt;/h3&gt;
&lt;p&gt;If you've used AI for code review, debugging, or documentation, you've seen this play out. The model produces output that looks right. It compiles. The logic flows. And then, somewhere in production — or during a code review — someone catches a subtle error the AI glossed over without comment.&lt;/p&gt;
&lt;p&gt;The issue isn't that the model got it wrong. Models get things wrong. The issue is that it didn't tell you it was uncertain. It presented a flawed answer with the same tone as a correct one.&lt;/p&gt;
&lt;p&gt;Opus 4.8 is designed to surface that uncertainty earlier. Instead of generating polished output with a hidden flaw, the model is more likely to flag where its reasoning is thin or where it's working with incomplete information.&lt;/p&gt;
&lt;h3 id=&quot;what-this-looks-like-in-practice&quot;&gt;What This Looks Like in Practice&lt;/h3&gt;
&lt;p&gt;For developers using Claude Code, the practical impact is measurable. Anthropic says Opus 4.8 can handle codebase-scale migrations — across hundreds of thousands of lines of code — from start to merge, using existing test suites as the validation bar. The honesty improvements reduce silent failures in long-running agentic tasks, which is where confident-but-wrong outputs cause the most damage.&lt;/p&gt;
&lt;p&gt;Anthropic also shipped a few other features alongside the model:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dynamic Workflows&lt;/strong&gt; (research preview) lets Claude spin up hundreds of parallel subagents within a single session. It's aimed at large-scale tasks that would otherwise require manual orchestration — available to Enterprise, Team, and Max users through Claude Code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Effort controls&lt;/strong&gt; let you decide how much compute the model applies to a task. High effort is the default. You can dial up to &quot;extra&quot; or &quot;max&quot; for intensive work, or pull back for faster, cheaper responses on simpler tasks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fast mode&lt;/strong&gt; is now roughly 2.5 times quicker and three times less expensive than in Opus 4.7. Pricing is unchanged from the prior version.&lt;/p&gt;
&lt;h3 id=&quot;why-honesty-is-a-feature-not-a-personality-trait&quot;&gt;Why Honesty Is a Feature, Not a Personality Trait&lt;/h3&gt;
&lt;p&gt;There's a tendency to frame model honesty as a philosophical or safety concern. For developers, it's a workflow concern.&lt;/p&gt;
&lt;p&gt;When a model flags its own uncertainty, you know where to focus your review. You can trust the parts it didn't flag and spend your time on the parts it did. That's a fundamentally different — and more useful — way to work than reviewing everything because you can't tell the difference between what the model knows and what it's guessing.&lt;/p&gt;
&lt;p&gt;This matters even more in agentic workflows, where a model is running tasks without a human in the loop at every step. A model that silently generates flawed output and keeps going is a much bigger problem than one that stops and says &quot;I'm not sure about this.&quot;&lt;/p&gt;
&lt;h3 id=&quot;the-takeaway&quot;&gt;The Takeaway&lt;/h3&gt;
&lt;p&gt;Opus 4.8 doesn't fix every trust problem in AI-assisted development. But a model that reliably surfaces its own uncertainty changes how you can structure your review process — and how much cognitive load you carry when you're working alongside it.&lt;/p&gt;
&lt;p&gt;Getting an answer right is useful. Knowing when to question the answer is better.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/19419/when-your-ai-stops-pretending-to-know-the-answer</guid>
<pubDate>Mon, 01 Jun 2026 11:34:16 +0000</pubDate>
</item>
<item>
<title>Anatomy of a Coding Agent: What I Learned Building My Own</title>
<link>https://coderlegion.com/18592/anatomy-of-a-coding-agent-what-i-learned-building-my-own</link>
<description>&lt;p class=&quot;wp-block-paragraph&quot;&gt;You use Claude Code every day. But do you really know it?&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;I didn’t. Not really. I could describe the surface, but I couldn’t tell you what was actually happening between hitting enter and seeing a diff. The harness was a black box, and that started to bother me. The only way I knew to fix that was to build one.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The result is &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/sudoish/oli&quot;&gt;oli&lt;/a&gt;, a single-binary terminal coding agent written in Rust that runs against Ollama by default. It got much larger than I expected. Every “small” subsystem (memory, policy, tool dispatch, provider quirks) turned out to have its own thicket of edge cases. I learned more about coding agents in a few weeks of building one than I had in a year of using them daily.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The hard parts aren’t clever prompts. They’re context management, tool design, policy gates, memory strategies and, if you want to run locally, survival engineering for models that don’t behave like the GPT-5 or Claude 4 families. This post is a tour of those parts, with the failures that taught me each one.&lt;/p&gt;
&lt;h2 class=&quot;wp-block-heading&quot;&gt;The Big Picture&lt;/h2&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Before diving into components, here’s what a coding agent actually looks like:&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;https://sudoish.com/wp-content/uploads/2026/05/anatomy-coding-agent-diagram-1-v3.png&quot; alt=&quot;Coding Agent Architecture&quot;&gt;&lt;/figure&gt;
&lt;h2 class=&quot;wp-block-heading&quot;&gt;The Agent Loop&lt;/h2&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Every coding agent runs the same basic loop:&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;https://sudoish.com/wp-content/uploads/2026/05/anatomy-coding-agent-diagram-2-v3.png&quot; alt=&quot;Agent Loop&quot;&gt;&lt;/figure&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Think → call → observe → repeat. The loop is deceptively simple. Everything hard lives in the details.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Three things I learned the hard way:&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;strong&gt;Turn limits matter, even on local models.&lt;/strong&gt; Early on, a local model I was testing got stuck, it looped 47 times trying to “fix” a file that was already correct, burning through my entire context window before I caught it. The model wasn’t broken. The harness was: no turn limit, no escape hatch, no awareness that the model had lost the plot. The instinct is to say “who cares, I’m running locally, tokens are free.” But the cost isn’t dollars, it’s coherence. As context fills, models degrade: attention spreads thinner, instructions in the middle of the window get ignored (“lost in the middle”), and every failed attempt becomes a distractor that biases the next turn toward more wrong behavior. This is &lt;em&gt;especially&lt;/em&gt; true on local models, whose effective context is often a fraction of their advertised window — a Qwen3 advertised at 256K may stay coherent only through the first 32-64K. A runaway loop doesn’t just waste compute; it actively makes the agent stupider for the rest of the session. Now subagents get hard turn limits by default, and the top-level agent is capped too, with a config default you can override per run.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;strong&gt;The system prompt is pinned.&lt;/strong&gt; It survives &lt;code&gt;/clear&lt;/code&gt;, survives memory compaction, survives everything. The first time I accidentally cleared the system prompt mid-session, the model forgot what tools it had and started apologizing for being unable to help. Pinning was an obvious fix in hindsight.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;strong&gt;Re-entrancy is a trap.&lt;/strong&gt; A Task tool that spawns a subagent which can itself spawn subagents quickly becomes a fork bomb. oli sidesteps the whole problem by registering &lt;code&gt;Task&lt;/code&gt; only in the parent agent — subagents get the same tool set &lt;em&gt;minus&lt;/em&gt; &lt;code&gt;Task&lt;/code&gt;, so they can’t recurse.&lt;/p&gt;
&lt;h2 class=&quot;wp-block-heading&quot;&gt;The System Prompt&lt;/h2&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Before you say anything, the model already gets a lot of scaffolding:&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;https://sudoish.com/wp-content/uploads/2026/05/anatomy-coding-agent-diagram-3-v3.png&quot; alt=&quot;System Prompt Structure&quot;&gt;&lt;/figure&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The &lt;code&gt;AGENTS.md&lt;/code&gt; + &lt;code&gt;CLAUDE.md&lt;/code&gt; line matters. Both Codex and Claude Code established conventions for per-project agent instructions. oli reads both, at every directory level from your current location up to the filesystem root — so a workspace-wide convention can be overridden by a project-level one without copy-pasting.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Note that the system prompt text and the tool schemas are separate payloads in the provider request — a better mental model than “everything lives in one giant prompt.”&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The system prompt is &lt;strong&gt;expensive&lt;/strong&gt;. It consumes tokens on every single turn. I learned this when a project with nested AGENTS.md files at multiple levels ate 8,000 tokens before I’d typed anything. Now oli caps injected project context at 16KB total and truncates directory listings at 50 entries. This is also where prompt caching pays off: both the prompt and the tool schema payload are highly stable across turns. Anthropic’s API supports marking that stable prefix as cacheable, and oli supports Anthropic-style cache breakpoints on Claude routes through OpenRouter too. Anthropic prices cached input tokens at roughly 10% of the regular rate, so caching shaves a large chunk off every subsequent turn in a long session.&lt;/p&gt;
&lt;h2 class=&quot;wp-block-heading&quot;&gt;Tools: The Model’s Hands&lt;/h2&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The tool surface defines what the agent can do. Too few tools and it’s frustrating. Too many and the model gets confused, especially local models with smaller context windows.&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;https://sudoish.com/wp-content/uploads/2026/05/anatomy-coding-agent-diagram-4-v3.png&quot; alt=&quot;Tool Registry&quot;&gt;&lt;/figure&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;A small core for the work, plus a handful of paging and notes tools. The design principles emerged from failures:&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;strong&gt;Minimal surface.&lt;/strong&gt; I started with more, and the model kept picking the wrong tool or stacking calls when one would do. Keeping the core small and bolting on paging and notes tools turned out to be the right shape. Each does one thing. These choices mirror what Claude Code, Cursor’s Composer, and Aider converged on independently — a signal that the design space is narrower than it looks.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;strong&gt;Bounded output.&lt;/strong&gt; Every tool truncates at 30KB. I learned this after the model Read a minified vendor.js file and blew through 180,000 tokens in one call. Now truncation markers embed a cache ID; the model can call &lt;code&gt;ShowFull(id, offset)&lt;/code&gt; to paginate the stashed body if it actually needs more.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;strong&gt;The read-first invariant.&lt;/strong&gt; Edit refuses to run unless you’ve Read the target file this session. This prevents edits based on stale context — the model can only modify what it’s actually seen this turn:&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;https://sudoish.com/wp-content/uploads/2026/05/anatomy-coding-agent-diagram-5-v3.png&quot; alt=&quot;Read-First Invariant&quot;&gt;&lt;/figure&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;strong&gt;Tools own their cleanup.&lt;/strong&gt; When you Ctrl-C a bash command, the harness has to kill not just the shell but every process it spawned. I found this out when orphaned &lt;code&gt;sleep&lt;/code&gt; processes from cancelled test runs accumulated over a week. A tool that spawns side effects has to know how to undo them — otherwise they leak into the user’s environment, and the harness gets blamed for the mess.&lt;/p&gt;
&lt;h2 class=&quot;wp-block-heading&quot;&gt;Memory &amp;amp; Context Management&lt;/h2&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Context windows are finite. Even 200K tokens fills up fast when you’re reading files, running tests, and iterating. Every tool result eats tokens.&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;https://sudoish.com/wp-content/uploads/2026/05/anatomy-coding-agent-diagram-6-v3.png&quot; alt=&quot;Context Window Management&quot;&gt;&lt;/figure&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The default strategy is &lt;code&gt;LinearWithCompact&lt;/code&gt;: hold messages in order, and when approaching the context limit, summarize older turns into a rolling summary. Compaction triggers at 80% of context window. It finds a cut point at a user-message boundary (never split a tool_call from its result), sends older messages to the LLM with a summarization prompt, and replaces them with a summary message.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;That part is straightforward. The bug that ate three days of debugging was &lt;strong&gt;cancellation under compaction&lt;/strong&gt;.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Here’s the scenario. You hit Ctrl-C mid-turn to stop the model. The REPL is supposed to roll back to the last clean state — the user prompt you just sent. Simple, when the message buffer is the source of truth: count back N messages, restore.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Except compaction had already run. The “last 12 messages” the rollback wanted to restore no longer existed — they’d been collapsed into a summary. So Ctrl-C would silently roll the conversation back to &lt;em&gt;somewhere random&lt;/em&gt;, often before the work the user was trying to cancel.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The fix was a one-line concept that took a day to see: stop treating the message array as the source of truth for &lt;em&gt;where you are&lt;/em&gt;. oli tracks a monotonic &lt;code&gt;record_count&lt;/code&gt; that increments on every logical turn, independent of physical message storage. Compaction drains messages, but the record count keeps climbing. Rollback targets a record count, not an array index — so the buffer can shrink underneath without the cursor losing its place.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Generalizable shape: any system that mutates history needs a stable identifier for “where you are” that isn’t the history itself. Memory management is also where coding agents silently fail — the model forgets what file it was editing, or repeats work it already did. The visible bugs are the easy ones.&lt;/p&gt;
&lt;h2 class=&quot;wp-block-heading&quot;&gt;Policy &amp;amp; Approvals&lt;/h2&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The policy engine gates every tool call. Without it, you’re one hallucinated &lt;code&gt;rm -rf&lt;/code&gt; away from disaster.&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;https://sudoish.com/wp-content/uploads/2026/05/anatomy-coding-agent-diagram-7-v3.png&quot; alt=&quot;Policy Engine&quot;&gt;&lt;/figure&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Bash has its own allowlist: &lt;code&gt;git status&lt;/code&gt;, &lt;code&gt;cargo test&lt;/code&gt;, &lt;code&gt;ls&lt;/code&gt;, and similar safe commands auto-approve; everything else prompts. The line-mode REPL is a plain &lt;code&gt;y/N&lt;/code&gt; flow; the richer “allow this session” and persisted allowlist behavior are TUI affordances layered on top.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;There’s no hard denylist yet, and I’m ambivalent about adding one. Prompt-on-every-mutation is annoying but transparent — you see exactly what the model is about to do. A denylist invites a long tail of “obviously safe” exceptions that gradually erode the gate. Today, blocking happens by denying an &lt;code&gt;Ask&lt;/code&gt; decision: slower, but you stay in the loop.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The first time I saw the model attempt &lt;code&gt;rm -rf target/&lt;/code&gt; when I’d asked it to “clean up the build” and the approval prompt caught it, I understood why this layer exists. The model wasn’t malicious. It was being helpful in a way that would have been catastrophic without the gate.&lt;/p&gt;
&lt;h2 class=&quot;wp-block-heading&quot;&gt;Local-Model Survival&lt;/h2&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Frontier models handle tool calls cleanly: structured &lt;code&gt;tool_calls&lt;/code&gt; arrays in the API response. Local models via Ollama? Not so much.&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;https://sudoish.com/wp-content/uploads/2026/05/anatomy-coding-agent-diagram-8-v3.png&quot; alt=&quot;Local vs Frontier Models&quot;&gt;&lt;/figure&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Many local models emit tool calls as plain text. Just raw JSON in the middle of their response. No structured field.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;oli solves this with a &lt;strong&gt;fallback parser&lt;/strong&gt;. When the model’s capability entry says &lt;code&gt;supports_native_tool_calls: false&lt;/code&gt;, the agent loop scans content for JSON objects with a &lt;code&gt;name&lt;/code&gt; field and splices them in as if they were real tool calls.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The &lt;strong&gt;model capability registry&lt;/strong&gt; tracks what each model can do. Lookups are prefix matches against the model id, so &lt;code&gt;claude-3-7-sonnet-latest&lt;/code&gt; matches the &lt;code&gt;claude-&lt;/code&gt; row. Today’s hardcoded entries:&lt;/p&gt;
&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Prefix&lt;/th&gt;&lt;th&gt;Context&lt;/th&gt;&lt;th&gt;Native Tool Calls&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;claude-&lt;/code&gt; / &lt;code&gt;anthropic/claude&lt;/code&gt;&lt;/td&gt;&lt;td&gt;200K&lt;/td&gt;&lt;td&gt;✓&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;gpt-4&lt;/code&gt;&lt;/td&gt;&lt;td&gt;128K&lt;/td&gt;&lt;td&gt;✓&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;gpt-&lt;/code&gt;&lt;/td&gt;&lt;td&gt;16K&lt;/td&gt;&lt;td&gt;✓&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;llama3.1&lt;/code&gt; / &lt;code&gt;llama3.2&lt;/code&gt;&lt;/td&gt;&lt;td&gt;128K&lt;/td&gt;&lt;td&gt;✓&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;llama3&lt;/code&gt;&lt;/td&gt;&lt;td&gt;8K&lt;/td&gt;&lt;td&gt;✗&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;qwen2.5-coder&lt;/code&gt;&lt;/td&gt;&lt;td&gt;32K&lt;/td&gt;&lt;td&gt;✗&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;em&gt;unknown&lt;/em&gt; (default)&lt;/td&gt;&lt;td&gt;8K&lt;/td&gt;&lt;td&gt;✗&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Smoke tests against &lt;code&gt;qwen3-coder:7b&lt;/code&gt; and &lt;code&gt;llama3&lt;/code&gt; showed they don’t behave as their docs claimed for tool calls, so they’re flagged off; the fallback parser handles them. Users override via &lt;code&gt;[[caps]]&lt;/code&gt; in config — that’s how I run &lt;code&gt;qwen3-coder:30b&lt;/code&gt; at 256K with native tools.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The gap between “works on Claude” and “works on qwen3” is enormous. If you’re building for local models, expect to handle every edge case they throw at you — and to discover new ones every time a model release widens the gap.&lt;/p&gt;
&lt;h2 class=&quot;wp-block-heading&quot;&gt;Provider Abstraction&lt;/h2&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;One binary, many backends. The promise only works because of the language choice: Rust gives a single static binary with no runtime to install, shipping to Mac/Linux/Windows from the same &lt;code&gt;cargo build&lt;/code&gt;. And the borrow checker turns out to be a surprisingly good fit for an agent loop — the lifetime and ownership bugs that bite hardest in async code, the compiler catches before I run anything.&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;https://sudoish.com/wp-content/uploads/2026/05/anatomy-coding-agent-diagram-9-v3.png&quot; alt=&quot;Provider Abstraction&quot;&gt;&lt;/figure&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Two provider kinds are available. Ollama, OpenRouter, OpenAI, LM Studio, vLLM, and llama.cpp’s server all speak OpenAI’s &lt;code&gt;/chat/completions&lt;/code&gt; shape, so one &lt;code&gt;openai-compat&lt;/code&gt; implementation covers them all — you just point &lt;code&gt;base_url&lt;/code&gt; at the right endpoint. The native Anthropic provider is its own thing because it speaks the Messages API directly and does its own OpenAI-shape &lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png&quot; alt=&quot;↔&quot; class=&quot;wp-smiley&quot; style=&quot;height: 1em; max-height: 1em;&quot;&gt; Anthropic-shape translation for tools, tool results, and system prompt handling.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;Caching adds a wrinkle here: native Anthropic supports prompt caching directly, but oli also supports Anthropic-style cache breakpoints in the openai-compat path for Claude models routed through OpenRouter. So “native provider” and “cached prefix” are related, but not identical ideas.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The openai-compat provider still has to handle backend quirks. OpenRouter sometimes returns 200 OK with an &lt;code&gt;error&lt;/code&gt; object in the body. The provider layer normalizes this.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The payoff: switching backends is a config flip, not a code change.&lt;/p&gt;
&lt;h2 class=&quot;wp-block-heading&quot;&gt;The Extension Surface&lt;/h2&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;A harness is only useful if you can make it yours. oli has three extension axes:&lt;/p&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img src=&quot;https://sudoish.com/wp-content/uploads/2026/05/anatomy-coding-agent-diagram-10-v3.png&quot; alt=&quot;Extension Surface&quot;&gt;&lt;/figure&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;All extensions route through the policy gate. No escape hatches.&lt;/p&gt;
&lt;h2 class=&quot;wp-block-heading&quot;&gt;What I Left Out&lt;/h2&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;To keep this post focused on the load-bearing components, I skipped several surfaces that ship in oli today: an MCP client (stdio + HTTP transports, with live &lt;code&gt;tools/list_changed&lt;/code&gt; deltas), a hook dispatcher (&lt;code&gt;PreToolUse&lt;/code&gt; / &lt;code&gt;PostToolUse&lt;/code&gt; / &lt;code&gt;Stop&lt;/code&gt;), session persistence as JSONL transcripts (with &lt;code&gt;--resume&lt;/code&gt; / &lt;code&gt;--continue&lt;/code&gt;), and the slash-command layer (&lt;code&gt;/compact&lt;/code&gt;, &lt;code&gt;/provider&lt;/code&gt;, &lt;code&gt;/model&lt;/code&gt;, &lt;code&gt;/sessions&lt;/code&gt;, etc.). Each is its own subsystem with its own trade-offs — let me know if you want any of them as a follow-up.&lt;/p&gt;
&lt;h2 class=&quot;wp-block-heading&quot;&gt;What This Means&lt;/h2&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;strong&gt;The harness is invisible until it breaks.&lt;/strong&gt; When Claude Code feels brilliant, you credit the model. When it feels broken — losing context, blocking the wrong thing, looping on a fix — that’s almost always the harness. The orchestration layer is doing the heavy lifting either way; you only notice when it fails.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;strong&gt;The hard problems are systems problems.&lt;/strong&gt; Memory management, policy enforcement, tool design, provider abstraction, local-model survival. Engineering challenges, not prompt engineering.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;strong&gt;Knowing the machinery makes you a better user.&lt;/strong&gt; Context overflow, policy gates, compaction, capability mismatches — once you can name what’s happening, you can debug it. Or work around it.&lt;/p&gt;
&lt;p class=&quot;wp-block-paragraph&quot;&gt;The repo is at &amp;lt;a href=&quot;https://github
&lt;/p&gt;</description>
<category>Other</category>
<guid isPermaLink="true">https://coderlegion.com/18592/anatomy-of-a-coding-agent-what-i-learned-building-my-own</guid>
<pubDate>Thu, 21 May 2026 20:33:45 +0000</pubDate>
</item>
<item>
<title>Bridging the Context Gap: Providing Structural Awareness to AI Coding Agents in Go with GoGraph</title>
<link>https://coderlegion.com/17835/bridging-the-context-gap-providing-structural-awareness-to-ai-coding-agents-with-gograph</link>
<description>&lt;p&gt;The hardest part of using AI coding agents isn't getting them to write Go code. It's watching them burn through your context window just trying to figure out where things are.&lt;/p&gt;
&lt;p&gt;If you’ve spent any time using Claude, Antigravity or Copilot on a medium-to-large Go codebase, you know the drill. You ask the agent to modify a core component. Before it writes a single line of code, it starts blindly running grep, guessing file paths, and sequentially cat-ing files.&lt;/p&gt;
&lt;p&gt;By the time the agent finally maps out the upstream HTTP handlers, the database interactions, and the interface satisfactions, it has exhausted a massive chunk of its token limit. The context window is bloated with irrelevant side-material and raw text dumps. The more noisy, unstructured code you feed the agent, the higher the chance it gets confused and starts hallucinating bad logic.&lt;/p&gt;
&lt;p&gt;Agents don't fail because they are bad at writing logic. They fail because they have to brute-force their way to structural awareness.&lt;/p&gt;
&lt;p&gt;I got tired of watching my AI tools waste tokens and context guessing my repository structure, so I built &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/ozgurcd/gograph&quot;&gt;Gograph&lt;/a&gt;. It’s a local static analysis engine and Model Context Protocol (MCP) server that gives your AI agents a deterministic, whole-repository structural map of your Go projects in a single, token-efficient JSON query.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why RAG and Terminal Searching Aren’t Enough&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Right now, the industry usually tries to solve the codebase context problem in two ways: &lt;em&gt;vector embeddings&lt;/em&gt; through &lt;em&gt;RAG&lt;/em&gt;, or by letting agents inspect the repository through terminal commands. Both approaches are useful, but neither is sufficient on its own for reliable understanding of a large Go codebase.&lt;/p&gt;
&lt;p&gt;The issue with RAG is that vector embeddings are good at semantic retrieval. If you want to find code related to “user authentication logic,” embedding search can often surface relevant files or nearby concepts. But embeddings do not provide deterministic code intelligence. They cannot prove that &lt;em&gt;UserStore.Update()&lt;/em&gt; satisfies the &lt;em&gt;Datastore&lt;/em&gt; interface, identify every caller across package boundaries, or trace how an error propagates through several layers of middleware. Those relationships require parsing, type checking, and static analysis.&lt;/p&gt;
&lt;p&gt;The issue with terminal search is that agents often fall back to tools like &lt;em&gt;grep&lt;/em&gt;, &lt;em&gt;rg&lt;/em&gt;, or reading files directly. These tools are valuable for exact strings, symbols, config keys, routes, and quick navigation. But plain text search cannot reliably capture relationships that only exist after the compiler understands the program. In Go, interface satisfaction is implicit, indirect calls may flow through interfaces, and behavior may depend on build tags, generated code, or package-level wiring. A search-only approach is likely to miss non-obvious dependencies.&lt;/p&gt;
&lt;p&gt;For large Go repositories, reliable agent context needs more than semantic search and raw file inspection. It needs compiler-aware code intelligence: symbols, packages, imports, interfaces, implementations, call graphs, route mappings, test relationships, and error flows. RAG can help find relevant areas. Terminal tools can help inspect concrete files. But the agent also needs structured knowledge of how the code actually fits together.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fixing It With Static AST Analysis&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Instead of relying only on semantic similarity or raw text search, I wanted a tool that gives agents structured knowledge of a Go repository.&lt;/p&gt;
&lt;p&gt;Gograph uses Go’s native parsing infrastructure, including go/ast and go/parser, to build a static graph of your repository. It runs entirely on your local machine: no network requests, no sending proprietary source code to third-party APIs. Its goal is to map concrete code structure such as packages, symbols, functions, methods, struct fields, imports, call sites, route wiring, tests, and recognizable dependency paths.&lt;/p&gt;
&lt;p&gt;Gograph ships with more than 20 specialized static analysis commands, including tools to map concurrency primitives, identify oversized objects, discover potentially dead code, and extract SQL-related structure. However, I designed three primary commands specifically to act as the core structural guardrails for AI agents.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.gograph plan &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Before an agent touches a file, it can run plan. Gograph analyzes the static code graph around the symbol and returns an impact-oriented view of the surrounding code.&lt;/p&gt;
&lt;p&gt;It can show callers, related packages, upstream HTTP routes where they are statically detectable, whether the execution path appears to touch persistence-related code, and which test files are likely to be affected.&lt;/p&gt;
&lt;p&gt;This gives the agent a concrete starting point instead of forcing it to guess from embeddings or repeatedly read files into context.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.gograph review &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After the agent makes an edit, it can run review. This acts as a structural sanity check over the affected area.&lt;/p&gt;
&lt;p&gt;It can flag likely breakage in routing paths, changed dependencies, stale tests, and interface-related drift where those relationships are visible to static analysis. It is not a replacement for compilation or go test. It is an earlier feedback layer that helps agents catch structural mistakes before running the full verification loop.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.gograph errorflow &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When a test fails with an error like &quot;invalid token signature&quot;, the agent should not have to guess where that message originated. It can pass the string to errorflow.&lt;/p&gt;
&lt;p&gt;Gograph searches for where the error is created or wrapped, then follows the static return and call path as far as it can identify it. When the path is visible in the source graph, it can show how the error moves from the originating function toward higher-level handlers or tests.&lt;/p&gt;
&lt;p&gt;This is useful in larger Go services where errors often pass through repository, service, middleware, and handler layers before reaching the test output or API response.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What It Looks Like in Practice&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let’s say you need an AI agent to add a &lt;em&gt;TenantID&lt;/em&gt; field to a &lt;em&gt;User&lt;/em&gt; struct in a shared package.&lt;/p&gt;
&lt;p&gt;If the agent relies only on raw search, it may find the struct, add the field, update the local constructor, and stop. The build may still fail because a &lt;em&gt;POST /api/v1/users&lt;/em&gt; handler in another package initializes the struct directly, or because repository code, SQL mapping, and integration tests also need updates.&lt;/p&gt;
&lt;p&gt;If the agent uses Gograph first, it can query the User symbol and get a structured view of the surrounding code. That view can show that the symbol is connected to a specific POST route, appears in repository code, participates in SQL-related paths, and is referenced by specific test files.&lt;/p&gt;
&lt;p&gt;The agent now has a better bounded scope for the change. Instead of editing one obvious file and discovering failures one by one, it can update the struct, handler, persistence path, and tests in a single coherent pass.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hooking It Up via MCP&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Gograph works as a standalone CLI, but it is also designed to be consumed by AI agents through the Model Context Protocol, or MCP.&lt;/p&gt;
&lt;p&gt;MCP is an open protocol introduced by Anthropic for connecting AI systems to local tools and data sources. Gograph ships with a built-in MCP server that operates over standard I/O.&lt;/p&gt;
&lt;p&gt;Instead of forcing the model to read and interpret unstructured terminal output, the MCP integration gives it structured, machine-readable JSON.&lt;/p&gt;
&lt;p&gt;For an MCP-compatible client such as Cursor or Claude Desktop, the configuration looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;mcpServers&quot;: {
    &quot;gograph&quot;: {
      &quot;command&quot;: &quot;gograph&quot;,
      &quot;args&quot;: [&quot;mcp&quot;, &quot;/path/to/your/repository&quot;]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once registered, the agent can query the repository graph before editing. It can inspect the structural impact of a proposed change, identify likely affected files, and build a more grounded execution plan before writing code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Getting Started&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you’re building in Go and tired of cleaning up after your AI tools, you can install Gograph right now:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# macOS / Linux (via Homebrew)
brew install ozgurcd/tap/gograph
# Or using Go:
go install github.com/ozgurcd/gograph/cmd/gograph@latest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;AI agents work better when they are given structured context instead of raw text alone. RAG is useful for semantic retrieval. Terminal commands are useful for exact inspection. But large Go codebases also need code-aware context: packages, symbols, call paths, routes, tests, persistence boundaries, and error flows.&lt;/p&gt;
&lt;p&gt;That is the problem Gograph is trying to solve.&lt;/p&gt;
&lt;p&gt;If you’re building in Go and tired of cleaning up after your AI tools, give Gograph a try.&lt;/p&gt;
&lt;p&gt;Source Code and Documentation: &lt;strong&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/ozgurcd/gograph&quot;&gt;https://github.com/ozgurcd/gograph&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you have ideas for other static analysis heuristics that would be useful for AI context, I'd love to hear your feedback! Feel free to open an issue or start a discussion on the GitHub repository.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/17835/bridging-the-context-gap-providing-structural-awareness-to-ai-coding-agents-with-gograph</guid>
<pubDate>Thu, 14 May 2026 15:44:55 +0000</pubDate>
</item>
<item>
<title>Loom Engine &amp; Mythcore: Omniveil</title>
<link>https://coderlegion.com/17718/loom-engine-mythcore-omniveil</link>
<description>&lt;p&gt;When I founded The World Table, the goal was clear: reimagining digital interaction. But to achieve the scale we envisioned for Mythcore: Omniveil, our upcoming MMORPG, the standard architectural patterns of the last decade simply weren't going to cut it.&lt;/p&gt;
&lt;p&gt;We needed a foundation that could handle thousands of entities without the browser breaking a sweat. That foundation is the Loom Engine.&lt;/p&gt;
&lt;p&gt;The Architecture of Loom: Precision Over Abstraction&lt;br&gt;
Most TypeScript developers reach for Classes and Inheritance by default. In the early days of Loom, we realized that the &quot;OOP Tax&quot; - memory fragmentation and garbage collection pressure - was our biggest bottleneck.&lt;/p&gt;
&lt;p&gt;To build a high-performance 2D engine, I made the executive decision to pivot Loom toward Data-Oriented Design (DOD).&lt;/p&gt;
&lt;p&gt;Why the shift?&lt;br&gt;
Contiguous Memory: By using TypedArrays and a Struct-of-Arrays (SoA) approach, we keep our data tightly packed.&lt;/p&gt;
&lt;p&gt;Bypassing the GC: Loom minimizes object instantiation in the main simulation loop. No new objects means no Garbage Collector spikes during critical gameplay.&lt;/p&gt;
&lt;p&gt;Near-Native Throughput: We are seeing performance metrics that challenge the &quot;TypeScript is slow&quot; stigma, pushing the V8 engine to its absolute limits.&lt;/p&gt;
&lt;p&gt;Mythcore: Omniveil - The Manifestation&lt;br&gt;
Loom isn't just a library; it’s the heartbeat of Mythcore: Omniveil. Currently in pre-alpha, Mythcore is the proof of concept for everything we’re building at The World Table.&lt;/p&gt;
&lt;p&gt;In our latest prototypes, we’ve successfully managed complex batch rendering and zero-allocation physics solvers. We’re proving that you can have the developer velocity of TypeScript with the raw power usually reserved for low-level languages.&lt;/p&gt;
&lt;p&gt;The &quot;Sadhaka&quot; Mindset&lt;br&gt;
Building an engine from scratch is a sadhana - a disciplined practice. It’s about stripping away the &quot;easy&quot; abstractions to find the performant truth underneath.&lt;/p&gt;
&lt;p&gt;I’m excited to join the CoderLegion community to share more deep dives into the Loom Engine’s architecture, our work on authoritative networking, and the journey of bringing Mythcore to life.&lt;/p&gt;
&lt;p&gt;If you’re interested in high-frequency systems, WebGL/WebGPU optimization, or the future of browser-based gaming, let’s talk.&lt;/p&gt;
&lt;h2 id=&quot;typescript-gamedev-webgpu-dataorienteddesign-loomengine-performanceengineering-mmorpg-anthropic-claudecode-solodev&quot;&gt;TypeScript #GameDev #WebGPU #DataOrientedDesign #LoomEngine #PerformanceEngineering #MMORPG #Anthropic #ClaudeCode #SoloDev&lt;/h2&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/17718/loom-engine-mythcore-omniveil</guid>
<pubDate>Wed, 13 May 2026 14:10:48 +0000</pubDate>
</item>
<item>
<title>If you are using Claude Code in production, the agent is not the problem</title>
<link>https://coderlegion.com/17113/if-you-are-using-claude-code-in-production-the-agent-is-not-the-problem</link>
<description>&lt;p&gt;The agent is not the problem. The substrate around the agent is. Here is the four-file shape that made my Convex production-database write boring on 2026-05-06, plus a stdlib Python script the Claude Code agent calls but did not generate.&lt;/p&gt;
&lt;p&gt;Before the question lands: the bridge is not an agent improvising near prod. It is a deterministic Python script the agent calls. It writes to a bounded Convex HTTP endpoint. Prod writes need an env flag and a 401-preflight to fire. The cache dedups on a composite idempotency key. The logger strips anything that smells like a secret before it hits disk. The agent did not invent any of that.&lt;/p&gt;
&lt;p&gt;In late April, a viral Reddit thread about an agent deleting a production database was making the rounds (&lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/lura_cardena_7de06f82aacd/ai-agents-on-reddit-late-april-to-early-may-2026-ten-threads-about-cost-reliability-and-real-4f20&quot;&gt;recap&lt;/a&gt;). The fear was real. My bridge is still running because the agent did not have the room to improvise. Below is what made that true. Every claim has a file path you can grep for in your own setup.&lt;/p&gt;
&lt;h3 id=&quot;what-context-engineering-actually-means-in-claude-code&quot;&gt;What context engineering actually means in Claude Code&lt;/h3&gt;
&lt;p&gt;Vendors are calling &lt;em&gt;context engineering&lt;/em&gt; the skill that separates serious solo operators from people who dabble. The trend is real. NxCode says over 60,000 &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.nxcode.io/resources/news/one-person-unicorn-context-engineering-solo-founder-guide-2026&quot;&gt;public GitHub repos now include some form of agent instruction file&lt;/a&gt;. What it means in Claude Code is concrete: a &lt;code&gt;CLAUDE.md&lt;/code&gt; at every project root, a global one at &lt;code&gt;~/.claude/CLAUDE.md&lt;/code&gt;, an auto-memory layer at &lt;code&gt;~/.claude/projects/&lt;/code&gt;, plus the skills directory, plus the templates directory, plus the hooks. Each one is a slot where context lives across sessions instead of being retyped into the chat.&lt;/p&gt;
&lt;p&gt;Context engineering is not prompt engineering 2.0. Prompt engineering happens in the user message. Context engineering happens in the files Claude Code reads before the user message. Identity. Business state. Registries. Decisions. Voice. Scripts. Memory.&lt;/p&gt;
&lt;p&gt;The common framing is one big system prompt and hope for the best. That breaks the moment your work spans more than one task surface. The layered framing replaces it. Folders, files, hooks, memory, vault. Each layer answers a question Claude would otherwise have to guess at.&lt;/p&gt;
&lt;p&gt;There is a name for the pattern people are converging on: the &lt;strong&gt;control stack&lt;/strong&gt;. Project rules plus reusable skills plus bounded sub-agents plus deterministic tools. The label is just the label, but the substance is what matters. Project rules go in &lt;code&gt;CLAUDE.md&lt;/code&gt;. Reusable skills go in &lt;code&gt;~/.claude/skills/&lt;/code&gt;. Bounded sub-agents are described per-task in their own SKILL or template files. Deterministic tools are scripts the agent calls (not generates) when the task needs a specific outcome.&lt;/p&gt;
&lt;p&gt;A vibe-coded one-shot script and a rail with all of this behind it can both run on a Tuesday. The difference is what is around the script. Tests, logs, idempotency cache, config gates, audit trail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Both ship. Only one survives Wednesday.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Only one helps when you come back six weeks later and need to remember why a flag is set the way it is. The vibe-coded one is forgotten code. The control-stack one composes.&lt;/p&gt;
&lt;p&gt;Concretely, here is what feeds my Claude Code session every conversation, before I type anything:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/projects/agent-os/CLAUDE.md&lt;/code&gt; is the load-bearing identity file. Who I am, what I sell, who I sell to, the 90-day priorities. The agent does not ask. It reads.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.claude/projects/-home-jon/memory/MEMORY.md&lt;/code&gt; is the auto-memory index. User profile, feedback rules, project state, references that survive across sessions. The agent does not relearn me every conversation.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;references/framework.md&lt;/code&gt; is the operator playbook. How decisions get made, what to optimize for, and what holds the rest together when the work scales.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;decisions/log.md&lt;/code&gt; is the append-only why-log. Not just &lt;em&gt;what&lt;/em&gt; changed. &lt;em&gt;Why&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those four files are part of the substrate. The identity and memory layers are loaded by default. The others are where the agent goes when the task calls for them.&lt;/p&gt;
&lt;h3 id=&quot;the-layers-one-folder-at-a-time&quot;&gt;The layers, one folder at a time&lt;/h3&gt;
&lt;p&gt;The Agent OS lives in three roots. &lt;code&gt;~/projects/agent-os/&lt;/code&gt; for the project layer. &lt;code&gt;~/.claude/&lt;/code&gt; for the global layer. &lt;code&gt;~/vault/&lt;/code&gt; for the second-brain layer. Each layer has one job, and Claude Code reads them in a known order.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;connections.md&lt;/code&gt; is the registry of every external system Jon-OS can reach. Gmail wired via the &lt;code&gt;gws&lt;/code&gt; CLI. Drive the same way. GitHub via &lt;code&gt;gh&lt;/code&gt;. Gumroad via PAT. NotebookLM via the &lt;code&gt;notebooklm&lt;/code&gt; CLI. Status and last-touched date on each. When I started the Skool bridge, the agent did not have to guess whether Convex was reachable. The registry said yes, here is the deployment slug, here is the auth model. One row per system. The bridge never blocked on &quot;is X wired.&quot;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;decisions/log.md&lt;/code&gt; is the append-only record of every non-trivial decision and why. Reversible decisions get a one-line entry. Load-bearing ones get the full receipts. The decision to gate prod writes on &lt;code&gt;SKOOL_ALLOW_PROD_WRITES=1&lt;/code&gt; plus a 401-preflight against an allowlisted Convex deployment lives there. So does the decision to keep member content deny-by-default in logs. Future me reads it. Future agent reads it. When a teammate asks &quot;why is this flag here,&quot; the answer is already written.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;references/&lt;/code&gt; holds voice samples, API guides, framework writeups. &lt;code&gt;references/skool-api.md&lt;/code&gt; had the Skool Sheets endpoint shape, the field names, and the failure modes spelled out before any code got written. The composite idempotency key was specified there as &lt;code&gt;{tab_slug}:{normalized_transaction_id}&lt;/code&gt;, before any handler. The bridge inherits the discipline of the spec. The spec inherits the discipline of the research that produced it.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;scripts/&lt;/code&gt; holds &lt;code&gt;gumroad_api.py&lt;/code&gt;, &lt;code&gt;skool_sheets_to_convex.py&lt;/code&gt;, and a handful of others. Stdlib-only Python. Deterministic tools the agent calls, not generated on demand. The Skool bridge is &lt;code&gt;skool_sheets_to_convex.py&lt;/code&gt;. The redacting logger is one function in that script that strips email-shaped substrings and known secret prefixes before any line lands in the journal. The agent did not write that on a hunch. It came from the spec.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;~/.claude/skills/&lt;/code&gt; and &lt;code&gt;~/projects/agent-os/.claude/templates/&lt;/code&gt; hold reusable skills and prompt templates. The Bike Method (training wheels first, then take them off) is encoded here. Prompt template first, then &lt;code&gt;SKILL.md&lt;/code&gt;, then orchestrator. New capability gets the lowest-autonomy version that works. It only graduates when I make an explicit edit. The content pipeline I am running this post through started life as a prompt template. The next phase turns it into a skill. Slow on purpose.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;~/.claude/projects/-home-jon/memory/&lt;/code&gt; is Claude Code's auto-memory layer. It survives across conversations. The workflow rule that produced the Skool bridge lives here as a feedback memory. Research, then planning, then spec, then implementation, with Codex adversarial review at each phase. The agent does not relearn that every session. It just does it.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;~/vault/&lt;/code&gt; is the Obsidian second-brain. PARA-routed. Sessions, drafts, insights, workflows, references. The session note for the Skool bridge ship day lives at &lt;code&gt;sessions/2026-05-06-skool-rail-live-content-pipeline-aegis-staged.md&lt;/code&gt;. Markdown plus frontmatter plus wikilinks. Plain text, plain folders, no platform lock-in.&lt;/p&gt;
&lt;p&gt;Each layer has one job. Adding a new system means adding one row to &lt;code&gt;connections.md&lt;/code&gt; and maybe one script to &lt;code&gt;scripts/&lt;/code&gt;. The layers stay stable, so the work compounds. That is the boring promise of the control stack.&lt;/p&gt;
&lt;h3 id=&quot;a-worked-example-the-skool-transactional-rail&quot;&gt;A worked example: the Skool transactional rail&lt;/h3&gt;
&lt;p&gt;The Skool transactional rail is a Python bridge. It polls two Google Sheet tabs that Skool-driven Zaps populate. New paid-member rows POST to a Convex HTTP endpoint that owns my YCAH member table. The other tab parses through without posting. The bridge runs on a systemd user timer:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;OnCalendar=*:0/10
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every 10 minutes on the boundary. It has been live in prod since 2026-05-06.&lt;/p&gt;
&lt;p&gt;Here is how it got safe.&lt;/p&gt;
&lt;p&gt;The spec lived in &lt;code&gt;references/skool-api.md&lt;/code&gt; before the code existed. Endpoint shape, field names, normalization rules, failure modes, idempotency strategy. Researched first, written second. The composite idempotency key was decided there:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{tab_slug}:{normalized_transaction_id}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Before any handler.&lt;/p&gt;
&lt;p&gt;The spec went through Codex twice for adversarial review. The first pass killed a cookie-auth approach that would have violated Skool's ToS. The second pass drove composite idempotency keys and the prod-write guard. Both passes still missed an inferred field assumption. I had assumed Skool's &quot;Answered Membership Questions&quot; trigger exposed the member's email. The dry-run caught that the field was not there. Not Codex. Not me re-reading my own spec. The dry-run, against real data. The honest version: review found a lot, but the empirical step still earned its keep.&lt;/p&gt;
&lt;p&gt;The pivot was clean because the spec was a document, not a vibe. I rewrote the affected section to &quot;parse the QA tab, but do not POST member rows from it (the email-bearing trigger is the New Paid Member event on the Paid Members tab),&quot; shipped Option A, kept moving. If the spec had only lived in my head, I would have been mid-implementation when reality disagreed. Instead, I edited a markdown file.&lt;/p&gt;
&lt;p&gt;The cache had a quieter bug. The initial &lt;code&gt;_read_json&lt;/code&gt; swallowed &lt;code&gt;JSONDecodeError&lt;/code&gt; and returned a default empty dict. Under the corruption test in the verification checklist (step 0e: deliberately corrupt the cache file, run the bridge, check what happens), it would have silently rebuilt the processed-events cache and double-POSTed every prod row that had already been posted. Caught and fixed before the canary ran. To be precise: the test caught it. Not the spec, not the agent, not me eyeballing the diff. The verification checklist did its job.&lt;/p&gt;
&lt;p&gt;The other guardrails earned their keep too:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prod-write guard:&lt;/strong&gt; &lt;code&gt;SKOOL_ALLOW_PROD_WRITES=1&lt;/code&gt; plus a 401-preflight against the allowlisted Convex deployment slug means a misconfigured run cannot touch prod. Fails closed at startup, before the first row is read.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redacting logger:&lt;/strong&gt; strips email-shaped substrings and known secret prefixes from every line before it hits the journal. Member content is deny-by-default. The bridge never logs row contents, only IDs and outcomes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Canary verified:&lt;/strong&gt; &lt;code&gt;jgerton+*Emails are not allowed*&lt;/code&gt; landed clean in prod Convex. The idempotent re-run produced 0 new POSTs, 1 skipped, 0 errored.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;None of those guardrails came from the agent improvising. They came from the spec. The spec came from the research phase. The research phase came from the workflow rule in memory. The substrate persists the rules. Discipline runs them. The dry-run and the corruption test catch what reviews miss. The agent itself wrote unsafe cache behavior on the first pass. The checklist caught it.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Sidebar: my Claude Code workflow rule&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The discipline above is anchored in one feedback memory at &lt;code&gt;~/.claude/projects/-home-jon/memory/feedback_workflow_research_to_implementation.md&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Research, then planning, then spec, then implementation, with Codex adversarial review at each phase.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Codex (the OpenAI Codex CLI) is the adversarial reviewer that runs alongside Claude Code in my setup. It runs against the spec, then again against the implementation, before anything ships. The reviews catch the things I am too close to see. The dry-run catches the things Codex assumes. The verification checklist catches the things the dry-run does not exercise. The agent itself catches almost nothing past the first draft, and that is fine, because the agent is not the safety net. The workflow rule is. The rule lives in Claude Code's memory layer because the rule is the part that has to survive across every session. The agent does not relearn it. It just does it.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-compounds&quot;&gt;What compounds&lt;/h3&gt;
&lt;p&gt;The audit score ticking from 77 to 85 is not the point. What got cheaper is. The &lt;code&gt;/audit&lt;/code&gt; pass surfaced a missing freshness column in &lt;code&gt;connections.md&lt;/code&gt;, an old voice sample I had outgrown, and a reference doc whose code paths had moved. Each fix made the next session faster. The agent stopped re-explaining state I had already encoded.&lt;/p&gt;
&lt;p&gt;Bigger payoff: the Aegis migration. I spent a day bulk-staging 75 skills, 66 commands, 5 agents, and 8 hooks from my desktop to the always-on minipc that runs Jon-OS 24 hours a day. None of those got &lt;em&gt;built&lt;/em&gt;. They got &lt;em&gt;recon'd, staged, and gated behind a settings diff&lt;/em&gt;, then activated. The hard work is path rewrites and activation order, not authoring.&lt;/p&gt;
&lt;p&gt;The one I lit up first: the &lt;code&gt;notebooklm&lt;/code&gt; skill. NotebookLM is now reachable as a CLI on this minipc, with &lt;code&gt;~/vault/CLAUDE.md&lt;/code&gt; mapping each domain to its dedicated notebook. I wrote a thin wrapper at &lt;code&gt;~/.claude/workflows/nlm-queue.py&lt;/code&gt; so the &lt;code&gt;session-extract&lt;/code&gt; skill can auto-source captured insights to the right notebook (queues on auth failure, drains after re-auth). That makes NotebookLM scriptable from inside the content pipeline. The post you are reading now leaned on manual research. The next version of this pipeline can lean on a NotebookLM query inside the prompt template. Same discipline, less typing. Every shipped rail makes the next one cheaper.&lt;/p&gt;
&lt;p&gt;The slower payoff is discovery. Three new YCAH members joined from three distinct platforms in the last month. Dev.to, Reddit /r/ClaudeAI, and TikTok. Three different surfaces, reached without me hand-writing each variant. Pipeline output, then discovery, then membership. The compounding works on the audience side too.&lt;/p&gt;
&lt;h3 id=&quot;what-this-is-not&quot;&gt;What this is not&lt;/h3&gt;
&lt;p&gt;This is not vibe coding. I do not trust one-shot scripts near prod. Not because someone on Twitter said so. Because I have been the person who shipped a one-shot, watched it work, and then watched it quietly stop working two weeks later for reasons I had no audit trail to understand. Front-loading the work is what makes the guardrails routine instead of heroic.&lt;/p&gt;
&lt;p&gt;It is also not stacking Notion plus Claude plus ChatGPT plus Cursor and calling it a system. Those are fine tools. The mental model treats each one as an island. The control stack treats them as one composable system with a known read order. The intended read path is identity, state, registries, decisions, voice, scripts, memory, then the conversation. The point is not magic order. The point is that the context lives in stable files. Add a tool, you add a row in &lt;code&gt;connections.md&lt;/code&gt; and maybe a wrapper in &lt;code&gt;scripts/&lt;/code&gt;. You do not add a context-switch tax for yourself or the agent.&lt;/p&gt;
&lt;p&gt;It is not theory. Every implementation claim above has a file path on my machine. Set up the same shape and you can grep your own.&lt;/p&gt;
&lt;h3 id=&quot;what-to-copy-first&quot;&gt;What to copy first&lt;/h3&gt;
&lt;p&gt;If you are going to copy one piece, copy &lt;code&gt;connections.md&lt;/code&gt;. Knowing what your Agent OS can reach is the cheapest unlock. You will build everything else against it.&lt;/p&gt;
&lt;p&gt;Second: a &lt;code&gt;decisions/log.md&lt;/code&gt; you actually keep. Append-only. One entry per non-trivial decision. The audit trail compounds faster than you think. By month two, you stop relitigating choices you already made and forgot you had made.&lt;/p&gt;
&lt;p&gt;Third: seed Claude Code's auto-memory layer with your voice, your workflow, and your role. Once it is there, every conversation gets cheaper. You stop reintroducing yourself. The agent stops asking you the same orientation questions every Tuesday.&lt;/p&gt;
&lt;p&gt;That is the order. Connections first, decisions second, memory third. Three files, in three days, before any new tool gets wired up. The bridge that runs my member sync was not built because I had a clever agent. It was built because the substrate was already there, and I used it. The discipline is mine. The files just stayed where the next session could find them. Boring on purpose.&lt;/p&gt;
&lt;p&gt;Open one of those three files in your editor tomorrow morning. Write the first row. The compounding starts there.&lt;/p&gt;
&lt;p&gt;Inside &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.skool.com/you-craft-ai-helps/about&quot;&gt;YCAH&lt;/a&gt;, I am doing this same work in public. The 4-file substrate, the workflow rule, the spec-first discipline, applied weekly to whatever members are shipping. Practitioner depth, not vending-machine demos.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/17113/if-you-are-using-claude-code-in-production-the-agent-is-not-the-problem</guid>
<pubDate>Fri, 08 May 2026 21:44:38 +0000</pubDate>
</item>
<item>
<title>I Spent a Week Installing WSL2. The Fix Was Two Lines.</title>
<link>https://coderlegion.com/16871/i-spent-a-week-installing-wsl2-the-fix-was-two-lines</link>
<description>&lt;blockquote&gt;&lt;p&gt;&quot;WSL2? Five minutes, tops.&quot; — Me, seven days ago.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;tl-dr&quot;&gt;TL;DR&lt;/h3&gt;
&lt;p&gt;On Windows 11 25H2 (build 26200), enabling VirtualMachinePlatform hangs at 37.8%. Forever. The servicing stack is stuck on 24H2 (build 26100) while the OS moved to 25H2 (build 26200). Windows literally cannot service itself.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Add-WindowsCapability -Online -Name &quot;Microsoft.Windows.HyperV.VirtualMachinePlatform~~~~0.0.1.0&quot;
dism /online /enable-feature /featurename:VirtualMachinePlatform /all /LimitAccess
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you just want the fix, there it is. If you want to know how it took a week and 10 failed attempts to arrive at two lines of PowerShell, keep reading.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;day-1-innocence&quot;&gt;Day 1: Innocence&lt;/h3&gt;
&lt;p&gt;Simple plan. Install WSL2. Set up Ubuntu 24.04. Do actual work.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;wsl --install -d Ubuntu-24.04
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;37.8%.&lt;/p&gt;
&lt;p&gt;I made coffee. Came back. 37.8%.&lt;/p&gt;
&lt;p&gt;I had lunch. Came back. 37.8%.&lt;/p&gt;
&lt;p&gt;37.8 is now my least favorite number.&lt;/p&gt;
&lt;h3 id=&quot;the-crime-scene&quot;&gt;The Crime Scene&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;OS &lt;/td&gt;&lt;td&gt;Windows 11 Pro 25H2 (Build 26200.8037)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;CPU &lt;/td&gt;&lt;td&gt;Intel Core Ultra 9 275HX&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;DISM version &lt;/td&gt;&lt;td&gt;10.0.26100.5074&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Servicing stack &lt;/td&gt;&lt;td&gt;10.0.26100.8035&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;See it? &lt;strong&gt;OS is build 26200. Servicing stack is build 26100.&lt;/strong&gt; The mechanic has last year's manual for this year's car. If you spotted this, you already know the ending. I did not spot this on Day 1.&lt;/p&gt;
&lt;h3 id=&quot;days-2-6-the-parade-of-failures&quot;&gt;Days 2-6: The Parade of Failures&lt;/h3&gt;
&lt;h4 id=&quot;gui-stuck-cancel-also-stuck-&quot;&gt;GUI — Stuck. Cancel also stuck.&lt;/h4&gt;
&lt;p&gt;&quot;Turn Windows features on/off.&quot; Checked the box. Progress bar froze.&lt;/p&gt;
&lt;p&gt;Clicked Cancel. Cancel froze.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A cancel button that cannot be cancelled.&lt;/strong&gt; This is the operating system from the world's most valuable company.&lt;/p&gt;
&lt;p&gt;Task Manager. End Process. Moving on.&lt;/p&gt;
&lt;h4 id=&quot;dism-37-8-&quot;&gt;DISM — 37.8%&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;dism /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;37.8%. We meet again.&lt;/p&gt;
&lt;h4 id=&quot;powershell-same-wall-different-paint&quot;&gt;PowerShell — Same wall, different paint&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -All -NoRestart
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Calls DISM internally. Same result. Changing the wrapper doesn't change the candy.&lt;/p&gt;
&lt;h4 id=&quot;uninstalled-bluestacks-wrong-suspect&quot;&gt;Uninstalled BlueStacks — Wrong suspect&lt;/h4&gt;
&lt;p&gt;Found forum posts: &quot;Android emulators conflict with Hyper-V.&quot; I had BlueStacks 10 installed. Uninstalled it completely. Registry cleanup. Folder purge. The works.&lt;/p&gt;
&lt;p&gt;Result: 37.8%.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BlueStacks was innocent.&lt;/strong&gt; And now I have to reinstall it later.&lt;/p&gt;
&lt;h4 id=&quot;offline-install-from-24h2-iso-version-mismatch&quot;&gt;Offline install from 24H2 ISO — Version mismatch&lt;/h4&gt;
&lt;p&gt;&quot;If the download is the problem, go offline.&quot;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;dism /online /enable-feature /featurename:VirtualMachinePlatform /all /LimitAccess /Source:D:\Sources\Install.wim
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;0x800f0912&lt;/code&gt;. The ISO is 24H2 (26100), the OS is 25H2 (26200). Windows refuses the source files because they're from &quot;the wrong version.&quot; Self-compatibility is apparently optional.&lt;/p&gt;
&lt;h4 id=&quot;windows-update-cache-reset-no-effect&quot;&gt;Windows Update cache reset — No effect&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;net stop wuauserv
net stop bits
Remove-Item C:\Windows\SoftwareDistribution\Download\* -Recurse -Force
net start bits
net start wuauserv
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Clean cache. Same 37.8%. Cleaning the house doesn't fix the plumbing.&lt;/p&gt;
&lt;h4 id=&quot;pending-operations-cleanup-partial&quot;&gt;Pending operations cleanup — Partial&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;dism /online /cleanup-image /revertpendingactions
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cleared the backlog. Feature still won't activate. Finishing your homework doesn't mean you'll pass the exam.&lt;/p&gt;
&lt;h4 id=&quot;in-place-repair-install-didn-t-downgrade&quot;&gt;In-place repair install — Didn't downgrade&lt;/h4&gt;
&lt;p&gt;The nuclear option. Ran 24H2 ISO's &lt;code&gt;setup.exe&lt;/code&gt; with &quot;Keep personal files and apps.&quot;&lt;/p&gt;
&lt;p&gt;40 minutes. Three reboots.&lt;/p&gt;
&lt;p&gt;Result: &lt;strong&gt;OS stayed on 25H2 (26200).&lt;/strong&gt; In-place install doesn't downgrade. But it did clean up the component store. This becomes a crucial plot point later.&lt;/p&gt;
&lt;h3 id=&quot;day-7-reading-the-logs-finally-using-my-brain-&quot;&gt;Day 7: Reading the Logs (Finally Using My Brain)&lt;/h3&gt;
&lt;p&gt;A week of &quot;try something else until it works.&quot; At this point, the question isn't &lt;em&gt;what&lt;/em&gt; doesn't work — it's &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Select-String -Path C:\Windows\Logs\CBS\CBS.log `
  -Pattern &quot;Error|Failed|0x800f&quot; -Context 2 | Select-Object -Last 20
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The smoking gun:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;Failed to get uup features from WU, sessionData: {
  &quot;ModuleID&quot;:&quot;FOD&quot;,
  &quot;Features&quot;:[{
    &quot;name&quot;:&quot;Windows.HyperV.OptionalFeature.VirtualMachinePlatform.Client.Disabled~&quot;
  }]
} [HRESULT = 0x800f0820 - CBS_E_CANCEL]
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;download source: 8, download time (secs): 1256, 
download status: 0x800f0820 (CBS_E_CANCEL)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;1,256 seconds. Twenty-one minutes waiting for Windows Update to deliver a package it will never find.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;From the DISM log, the confession:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;Dism.exe version: 10.0.26100.5074
Target image: OS Version=10.0.26200.8037
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The servicing stack (26100) is trying to service a newer OS (26200). It goes to Windows Update looking for FOD packages matching this combination. Those packages don't exist in the UUP catalog. So it waits. And waits. And times out at 37.8%.&lt;/p&gt;
&lt;p&gt;A car mechanic with a 2023 catalog trying to order parts for a 2024 model. &quot;This part number doesn't exist in our system, sir.&quot;&lt;/p&gt;
&lt;p&gt;This is the servicing architecture of the world's largest software company.&lt;/p&gt;
&lt;h3 id=&quot;the-fix-use-the-back-door&quot;&gt;The Fix: Use the Back Door&lt;/h3&gt;
&lt;p&gt;DISM can't download the FOD through its usual channel (UUP). But &lt;code&gt;Add-WindowsCapability&lt;/code&gt; uses a &lt;strong&gt;different channel&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Same building. Front door is under construction. Back door is open. The sign only mentions the front door. Classic Windows UX.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Step 1: Back door — install payload via alternative channel
Add-WindowsCapability -Online -Name &quot;Microsoft.Windows.HyperV.VirtualMachinePlatform~~~~0.0.1.0&quot;

# Step 2: Now activate using only local files (no internet needed)
dism /online /enable-feature /featurename:VirtualMachinePlatform /all /LimitAccess
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;100%.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One hundred percent.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First three-digit number I've seen all week.&lt;/p&gt;
&lt;h3 id=&quot;why-this-works&quot;&gt;Why This Works&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;[Front door — BLOCKED]
DISM enable-feature
  → Needs FOD payload
  → Windows Update UUP channel
  → Servicing stack (26100) ≠ OS (26200)
  → &quot;Part not found in catalog&quot;
  → 21 min timeout → CBS_E_CANCEL

[Back door — OPEN]
Add-WindowsCapability  
  → Different download channel (bypasses UUP)
  → Payload installed locally ✓

DISM + /LimitAccess
  → &quot;Internet? Don't need it.&quot;
  → Local files only
  → Success ✓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Both commands use the same Windows servicing system. But they fetch FOD packages through different channels. DISM goes through UUP, where the version mismatch kills it. &lt;code&gt;Add-WindowsCapability&lt;/code&gt; takes a different route. The official docs don't mention this distinction. You're welcome.&lt;/p&gt;
&lt;h3 id=&quot;if-you-found-this-article&quot;&gt;If You Found This Article&lt;/h3&gt;
&lt;p&gt;You've probably already tried and failed multiple times. That means &lt;strong&gt;pending operations&lt;/strong&gt; are likely piled up. Clean house first:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Light cleanup
dism /online /cleanup-image /revertpendingactions
# → Reboot → Run the two-line fix

# If that's not enough (in-place repair)
# 24H2 ISO → setup.exe → &quot;Keep personal files and apps&quot;
# → Reboot → Run the two-line fix
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;complete-flow-for-fresh-starts-&quot;&gt;Complete Flow (For Fresh Starts)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;1. Enable virtualization in BIOS
   HP laptops: F10 → Security or Configuration → Enable VT-x
        ↓
2. Enable Hyper-V + WSL (these work fine, ironically)
   dism /online /enable-feature /featurename:Microsoft-Hyper-V-All /all /norestart
        ↓
3. Clean pending operations (if you've been trying things)
   dism /online /cleanup-image /revertpendingactions → reboot
        ↓
4. The actual fix
   Add-WindowsCapability -Online -Name &quot;Microsoft.Windows.HyperV.VirtualMachinePlatform~~~~0.0.1.0&quot;
   dism /online /enable-feature /featurename:VirtualMachinePlatform /all /LimitAccess
        ↓
5. Reboot → Install WSL2
   wsl --install -d Ubuntu-24.04
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;is-this-your-problem-&quot;&gt;Is This Your Problem?&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Check version mismatch in DISM log
Get-Content C:\Windows\Logs\DISM\dism.log -Tail 100
# &quot;version:&quot; ≠ &quot;image version:&quot; → yes, this is your problem

# Check CBS log for the specific failure
Select-String -Path C:\Windows\Logs\CBS\CBS.log `
  -Pattern &quot;Error|Failed|0x800f&quot; -Context 2 | Select-Object -Last 20
# &quot;CBS_E_CANCEL&quot; → yes, this is your problem

# Verify CPU virtualization (prerequisite)
Get-CimInstance -ClassName Win32_Processor | 
  Select-Object VirtualizationFirmwareEnabled, VMMonitorModeExtensions
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Symptom&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;VirtualMachinePlatform stuck at 37.8%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Root cause&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;25H2 OS (26200) + 24H2 servicing stack (26100) = FOD download mismatch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Fix&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;&lt;code&gt;Add-WindowsCapability&lt;/code&gt; to bypass → &lt;code&gt;dism /LimitAccess&lt;/code&gt; to activate&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Prerequisite&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Clear pending operations&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;One week of evenings. One wrongly accused BlueStacks. A lasting distrust of progress bars.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;lessons&quot;&gt;Lessons&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Read the logs first.&lt;/strong&gt; &quot;Try random things until something works&quot; is the scenic route to nowhere.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Windows Insider means signing up for this.&lt;/strong&gt; 25H2 is a preview build. The servicing stack hasn't caught up. Now you know.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Same building, multiple doors.&lt;/strong&gt; When DISM fails, &lt;code&gt;Add-WindowsCapability&lt;/code&gt; exists. The docs won't tell you.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feed your logs to AI.&lt;/strong&gt; Nobody should read 160,000 lines of CBS log with their own eyes.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;This troubleshooting session was done with &lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/code&quot;&gt;Claude Code&lt;/a&gt;. It pulled the critical 6 lines from a 160,000-line CBS log and helped identify the &lt;code&gt;Add-WindowsCapability&lt;/code&gt; back door. Without it, this would have ended with a format and reinstall.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/16871/i-spent-a-week-installing-wsl2-the-fix-was-two-lines</guid>
<pubDate>Wed, 06 May 2026 15:49:50 +0000</pubDate>
</item>
<item>
<title>Claude Code Deep Dive Part 2: The 1,421-Line While Loop That Runs Everything</title>
<link>https://coderlegion.com/16781/claude-code-deep-dive-part-2-the-1-421-line-while-loop-that-runs-everything</link>
<description>&lt;p&gt;&lt;em&gt;This is Part 2 of our Claude Code Architecture Deep Dive series. &lt;a rel=&quot;nofollow&quot; href=&quot;https://harrisonsec.com/blog/claude-code-source-leaked-hidden-features/&quot;&gt;Part 1: 5 Hidden Features&lt;/a&gt; covered the surface-level discoveries. Now we go deeper.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-heart-of-claude-code&quot;&gt;The Heart of Claude Code&lt;/h3&gt;
&lt;p&gt;Every AI coding agent — Claude Code, Cursor, Copilot — runs some version of the same loop: send context to an LLM, get back text and tool calls, execute tools, feed results back, repeat. We called this &lt;a rel=&quot;nofollow&quot; href=&quot;https://harrisonsec.com/blog/ai-stack-explained-llm-talks-program-walks/&quot;&gt;LLM talks, program walks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But Claude Code's implementation of this loop is anything but simple. It lives in &lt;code&gt;query.ts&lt;/code&gt;, a 1,729-line async generator. The &lt;code&gt;while(true)&lt;/code&gt; starts at line 307 and ends at line 1728 — a single loop body spanning 1,421 lines of production code.&lt;/p&gt;
&lt;p&gt;This is not a toy. This is the engine that processes every keystroke, every tool call, every error recovery, every context compression decision for millions of users.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// query.ts — line 307
// eslint-disable-next-line no-constant-condition
while (true) {
    let { toolUseContext } = state
    const { ... } = state
    // ... 1,421 lines of state machine logic ...
    state = next
} // while (true)  — line 1728
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;why-a-state-machine-not-recursion&quot;&gt;Why a State Machine, Not Recursion&lt;/h3&gt;
&lt;p&gt;Early versions of Claude Code used recursion — the query function called itself. But recursion has a fatal flaw: in long conversations with hundreds of tool calls, the call stack grows until it explodes.&lt;/p&gt;
&lt;p&gt;The current design uses &lt;code&gt;while(true)&lt;/code&gt; with a &lt;code&gt;state&lt;/code&gt; object that carries context between iterations:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// query.ts — lines 207-215 (State type, partial)
autoCompactTracking: AutoCompactTrackingState | undefined
maxOutputTokensRecoveryCount: number
hasAttemptedReactiveCompact: boolean       // circuit breaker for 413 recovery
stopHookActive: boolean | undefined
turnCount: number
transition: { reason: string } | undefined // why we continued
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each &lt;code&gt;continue&lt;/code&gt; statement is a state transition. There are &lt;strong&gt;9 distinct &lt;code&gt;continue&lt;/code&gt; points&lt;/strong&gt; in the code (lines 950, 1115, 1165, 1220, 1251, 1305, 1316, 1340), each representing a different reason to run another turn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Next tool call needed&lt;/li&gt;
&lt;li&gt;Reactive compact triggered after 413&lt;/li&gt;
&lt;li&gt;Max output tokens recovery&lt;/li&gt;
&lt;li&gt;Stop hook interrupted&lt;/li&gt;
&lt;li&gt;Token budget continuation&lt;/li&gt;
&lt;li&gt;And more&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-loop-at-a-glance&quot;&gt;The Loop at a Glance&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://mermaid.ink/img/Zmxvd2NoYXJ0IFRECiAgICBBWyLikaAgQ29tcHJlc3MgQ29udGV4dDxici8-KDQgc3RhZ2VzKSJdIC0tPiBCWyLikaEgVG9rZW4gQnVkZ2V0IENoZWNrIl0KICAgIEIgLS0-IENbIuKRoiBDYWxsIE1vZGVsIEFQSTxici8-KHN0cmVhbWluZykiXQogICAgQyAtLT4gRFsi4pGjIFN0cmVhbSBUb29sIEV4ZWN1dGlvbjxici8-KHBhcmFsbGVsIHdpdGggZ2VuZXJhdGlvbikiXQogICAgRCAtLT4gRVsi4pGkIEVycm9yIFJlY292ZXJ5PGJyLz4oNDEzIOKGkiByZWFjdGl2ZSBjb21wYWN0KSJdCiAgICBFIC0tPiBGWyLikaUgU3RvcCBIb29rcyJdCiAgICBGIC0tPiBHWyLikaYgVG9rZW4gQnVkZ2V0IENoZWNrICMyIl0KICAgIEcgLS0-IEhbIuKRpyBFeGVjdXRlIFRvb2xzPGJyLz4oMTQtc3RlcCBwaXBlbGluZSkiXQogICAgSCAtLT4gSVsi4pGoIEluamVjdCBBdHRhY2htZW50czxici8-KG1lbW9yeSwgc2tpbGxzLCBxdWV1ZWQgY21kcykiXQogICAgSSAtLT4gSlsi4pGpIEFzc2VtYmxlIE1lc3NhZ2VzIl0KICAgIEogLS0-fCJuZXh0IHR1cm4ifCBBCgogICAgc3R5bGUgQSBmaWxsOiMxYTRkMmUsc3Ryb2tlOiMyMmM1NWUsY29sb3I6I2ZmZgogICAgc3R5bGUgQyBmaWxsOiMxYTNhNWMsc3Ryb2tlOiMzYjgyZjYsY29sb3I6I2ZmZgogICAgc3R5bGUgRCBmaWxsOiM0YTM1MjAsc3Ryb2tlOiNmNTllMGIsY29sb3I6I2ZmZgogICAgc3R5bGUgRSBmaWxsOiM0YTIwMjAsc3Ryb2tlOiNlZjQ0NDQsY29sb3I6I2ZmZgogICAgc3R5bGUgSCBmaWxsOiMzYTIwNTAsc3Ryb2tlOiM4YjVjZjYsY29sb3I6I2ZmZg==&quot; alt=&quot;flowchart TD&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;10-steps-per-iteration&quot;&gt;10 Steps Per Iteration&lt;/h3&gt;
&lt;p&gt;Each time the loop runs, it does these 10 things in order. Every step has real source code behind it.&lt;/p&gt;
&lt;h4 id=&quot;step-1-context-compression-4-stages-&quot;&gt;Step 1: Context Compression (4 stages)&lt;/h4&gt;
&lt;p&gt;Before calling the API, the system tries to fit everything into the context window. Four compression mechanisms fire in priority order (imports at lines 12-16, 115-116):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Snip Compact&lt;/strong&gt; — trims overly long individual messages in history&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Micro Compact&lt;/strong&gt; — finer-grained editing based on &lt;code&gt;tool_use_id&lt;/code&gt;, cache-friendly (line 370: &quot;microcompact operates purely by tool_use_id&quot;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context Collapse&lt;/strong&gt; — folds inactive context regions into summaries&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto Compact&lt;/strong&gt; — when total tokens approach the threshold, triggers full compression&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These are not mutually exclusive — they run in priority order:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://mermaid.ink/img/Zmxvd2NoYXJ0IExSCiAgICBBWyJTbmlwIENvbXBhY3Q8YnIvPjxpPnRyaW0gbG9uZyBtZXNzYWdlczwvaT4iXSAtLT58InN0aWxsIHRvbyBiaWc_InwgQlsiTWljcm8gQ29tcGFjdDxici8-PGk-dG9vbF91c2VfaWQgZWRpdHM8L2k-Il0KICAgIEIgLS0-fCJzdGlsbCB0b28gYmlnPyJ8IENbIkNvbnRleHQgQ29sbGFwc2U8YnIvPjxpPmZvbGQgaW5hY3RpdmUgcmVnaW9uczwvaT4iXQogICAgQyAtLT58InN0aWxsIHRvbyBiaWc_InwgRFsiQXV0byBDb21wYWN0PGJyLz48aT5mdWxsIGNvbXByZXNzaW9uPC9pPiJdCiAgICBEIC0tPnwiQVBJIHJldHVybnMgNDEzInwgRVsiUmVhY3RpdmUgQ29tcGFjdDxici8-PGk-ZW1lcmdlbmN5LCBvbmNlIG9ubHk8L2k-Il0KCiAgICBzdHlsZSBBIGZpbGw6IzFhM2EyZSxzdHJva2U6IzRhZGU4MCxjb2xvcjojZmZmCiAgICBzdHlsZSBCIGZpbGw6IzFhM2EyZSxzdHJva2U6IzRhZGU4MCxjb2xvcjojZmZmCiAgICBzdHlsZSBDIGZpbGw6IzNhMzUyMCxzdHJva2U6I2ZiYmYyNCxjb2xvcjojZmZmCiAgICBzdHlsZSBEIGZpbGw6IzRhMjAyMCxzdHJva2U6I2VmNDQ0NCxjb2xvcjojZmZmCiAgICBzdHlsZSBFIGZpbGw6IzRhMTAyMCxzdHJva2U6I2RjMjYyNixjb2xvcjojZmZm&quot; alt=&quot;flowchart LR&quot;&gt;&lt;/p&gt;
&lt;p&gt;The system tries lightweight options first. If snip + micro bring tokens under the limit, the heavy compressors never run.&lt;/p&gt;
&lt;h4 id=&quot;step-2-token-budget-check&quot;&gt;Step 2: Token Budget Check&lt;/h4&gt;
&lt;p&gt;If a token budget is active (&lt;code&gt;feature('TOKEN_BUDGET')&lt;/code&gt;, line 280), the system checks whether to continue. Users can specify targets like &quot;+500k&quot;, and the system tracks cumulative output tokens per turn, injecting nudge messages near the goal to keep the model working.&lt;/p&gt;
&lt;h4 id=&quot;step-3-call-model-api&quot;&gt;Step 3: Call Model API&lt;/h4&gt;
&lt;p&gt;Line 659 — the actual API call:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;for await (const message of deps.callModel({
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a streaming call. The response arrives token by token, and the system processes it incrementally.&lt;/p&gt;
&lt;h4 id=&quot;step-4-streaming-tool-execution&quot;&gt;Step 4: Streaming Tool Execution&lt;/h4&gt;
&lt;p&gt;This is a critical optimization. Traditional agents wait for the model to finish generating all output, then execute tools. Claude Code uses &lt;code&gt;StreamingToolExecutor&lt;/code&gt; (imported at line 96):&lt;/p&gt;
&lt;p&gt;When the model is still generating its second tool call, the first one is already running:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;Traditional Agent (sequential):
┌─────────────────────────┐┌───┐┌───┐┌───┐┌───┐┌───┐
│  LLM generates 5 calls  ││ T1││ T2││ T3││ T4││ T5│  ← 30s total
└─────────────────────────┘└───┘└───┘└───┘└───┘└───┘

Claude Code (streaming):
┌─────────────────────────┐
│  LLM generates 5 calls  │
├──┬──┬──┬──┬─────────────┘
│T1│T2│T3│T4│T5│                                       ← 18s total
└──┴──┴──┴──┴──┘
↑ tools start while LLM is still generating
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In a turn with 5 tool calls, traditional waits 30 seconds. Streaming finishes in 18 — a &lt;strong&gt;40% speedup&lt;/strong&gt; from architecture alone, not model improvements.&lt;/p&gt;
&lt;p&gt;Line 554-555 reveals an interesting detail: &lt;code&gt;stop_reason === 'tool_use'&lt;/code&gt; is unreliable — &quot;it's not always set correctly.&quot; The system detects tool calls by watching for &lt;code&gt;tool_use&lt;/code&gt; blocks during streaming instead.&lt;/p&gt;
&lt;h4 id=&quot;step-5-error-recovery&quot;&gt;Step 5: Error Recovery&lt;/h4&gt;
&lt;p&gt;If the prompt is too long? Try context collapse drain. If that fails, try reactive compact (line 15-16). If the API returns 413 (prompt too long), trigger emergency compression and retry.&lt;/p&gt;
&lt;p&gt;But there's a circuit breaker: &lt;code&gt;hasAttemptedReactiveCompact&lt;/code&gt; (line 209, initialized &lt;code&gt;false&lt;/code&gt; at line 275) ensures each turn only attempts reactive compact once. Without this, a genuinely oversized conversation would loop forever.&lt;/p&gt;
&lt;p&gt;The system also handles model degradation — if the primary model fails, it can fall back to a different model.&lt;/p&gt;
&lt;h4 id=&quot;step-6-stop-hooks&quot;&gt;Step 6: Stop Hooks&lt;/h4&gt;
&lt;p&gt;After the model stops outputting, the system runs registered stop hooks. These can inspect the output and decide whether to let the model continue. This is where external governance plugs in.&lt;/p&gt;
&lt;h4 id=&quot;step-7-token-budget-check-again-&quot;&gt;Step 7: Token Budget Check (Again)&lt;/h4&gt;
&lt;p&gt;Yes, checked twice — once before calling the model (should we even start?) and once after (did we exceed the budget?). The second check decides whether to inject a &quot;keep going&quot; nudge or stop.&lt;/p&gt;
&lt;h4 id=&quot;step-8-tool-execution&quot;&gt;Step 8: Tool Execution&lt;/h4&gt;
&lt;p&gt;If the response contains &lt;code&gt;tool_use&lt;/code&gt; blocks, execute them. Two paths:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;runTools()&lt;/code&gt; (from &lt;code&gt;toolOrchestration.ts&lt;/code&gt;, line 98) — batch execution&lt;/li&gt;
&lt;li&gt;&lt;code&gt;StreamingToolExecutor&lt;/code&gt; (line 96) — streaming execution, gated by &lt;code&gt;config.gates.streamingToolExecution&lt;/code&gt; (line 561)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each tool call goes through the 14-step execution pipeline in &lt;code&gt;toolExecution.ts&lt;/code&gt; (1,745 lines) — validation, permission checks, hooks, actual execution, analytics. That's a story for &lt;a rel=&quot;nofollow&quot; href=&quot;https://harrisonsec.com/blog/claude-code-deep-dive-tool-pipeline/&quot;&gt;Part 3&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;step-9-attachment-injection&quot;&gt;Step 9: Attachment Injection&lt;/h4&gt;
&lt;p&gt;After tools finish, the system injects additional context before the next turn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Memory attachments&lt;/strong&gt; — relevant memories from the &lt;code&gt;memdir/&lt;/code&gt; system&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skill discovery&lt;/strong&gt; — matching skills based on the current task&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Queued commands&lt;/strong&gt; — any commands that were waiting&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This happens after tool execution but before the next API call, ensuring the model has fresh context.&lt;/p&gt;
&lt;h4 id=&quot;step-10-assemble-and-loop&quot;&gt;Step 10: Assemble and Loop&lt;/h4&gt;
&lt;p&gt;Build the new message list from all the pieces — original conversation, tool results, attachments, system reminders — and go back to step 1.&lt;/p&gt;
&lt;h3 id=&quot;why-this-architecture-matters&quot;&gt;Why This Architecture Matters&lt;/h3&gt;
&lt;p&gt;Most open-source AI agents implement the loop as 50 lines of pseudocode: call model, parse tool calls, execute, repeat. Claude Code's 1,421-line version exists because production reality is messy:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Context doesn't fit.&lt;/strong&gt; A real coding session easily hits 200K tokens. Without the 4-stage compression pipeline, the agent dies on every long conversation. Most agents just truncate and lose context. Claude Code compresses intelligently — lightweight first, heavy only when needed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Models fail.&lt;/strong&gt; APIs return 413, connections drop, rate limits hit. The 9 continue points aren't over-engineering — they're the minimum number of recovery paths needed for reliable operation. The &lt;code&gt;hasAttemptedReactiveCompact&lt;/code&gt; circuit breaker is the kind of detail that separates a demo from a product.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Speed matters more than correctness of execution order.&lt;/strong&gt; Streaming tool execution — starting the first tool while the model is still generating the third — is a user experience decision backed by architecture. Traditional agents feel slow because they are: they serialize everything. Claude Code parallelizes at the loop level.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tokens cost money.&lt;/strong&gt; The &lt;code&gt;SYSTEM_PROMPT_DYNAMIC_BOUNDARY&lt;/code&gt; marker in &lt;code&gt;prompts.ts&lt;/code&gt; (914 lines) splits the system prompt into static (cacheable) and dynamic sections. If two requests share the same static prefix byte-for-byte, the API caches it. Source comment: &quot;don't modify content before the boundary, or you'll destroy the cache.&quot; This is prompt cache economics — saving Anthropic real compute costs at scale.&lt;/p&gt;
&lt;h3 id=&quot;the-behavioral-constitution&quot;&gt;The Behavioral Constitution&lt;/h3&gt;
&lt;p&gt;Buried inside the prompt assembly, &lt;code&gt;getSimpleDoingTasksSection()&lt;/code&gt; may be the most valuable function in the entire codebase. It encodes hard-won rules about what the model should NOT do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don't add features the user didn't ask for&lt;/li&gt;
&lt;li&gt;Don't over-abstract — three duplicate lines beat a premature abstraction&lt;/li&gt;
&lt;li&gt;Don't add comments to code you didn't change&lt;/li&gt;
&lt;li&gt;Don't add unnecessary error handling&lt;/li&gt;
&lt;li&gt;Read code before modifying it&lt;/li&gt;
&lt;li&gt;If a method fails, diagnose before retrying&lt;/li&gt;
&lt;li&gt;Report honestly — don't say you ran something you didn't&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anyone who has used Claude Code recognizes these rules. I've personally watched the system refuse to add &quot;helpful&quot; abstractions and stick to minimal changes. That's not the model being disciplined — it's the prompt constraining the model. The takeaway: &lt;strong&gt;don't trust model self-discipline. Codify the behavior.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;how-other-agents-compare&quot;&gt;How Other Agents Compare&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Aspect &lt;/th&gt;&lt;th&gt;Claude Code &lt;/th&gt;&lt;th&gt;Cursor &lt;/th&gt;&lt;th&gt;Typical OSS Agent&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Loop complexity &lt;/td&gt;&lt;td&gt;1,421 lines, 9 continue points &lt;/td&gt;&lt;td&gt;Unknown (closed source) &lt;/td&gt;&lt;td&gt;~50-200 lines&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Compression &lt;/td&gt;&lt;td&gt;4-stage pipeline + reactive 413 recovery &lt;/td&gt;&lt;td&gt;Tab-level context pruning &lt;/td&gt;&lt;td&gt;Truncate or fail&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Tool execution &lt;/td&gt;&lt;td&gt;Streaming (parallel with generation) &lt;/td&gt;&lt;td&gt;Sequential &lt;/td&gt;&lt;td&gt;Sequential&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Error recovery &lt;/td&gt;&lt;td&gt;Circuit breakers, model fallback, emergency compact &lt;/td&gt;&lt;td&gt;Basic retry &lt;/td&gt;&lt;td&gt;Crash&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Prompt caching &lt;/td&gt;&lt;td&gt;Static/dynamic boundary, section registry &lt;/td&gt;&lt;td&gt;Unknown &lt;/td&gt;&lt;td&gt;None&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The gap between Claude Code and most open-source agents is not model quality — it's the program layer. The model is the same Opus or Sonnet for everyone. What makes Claude Code feel different is 1,421 lines of careful engineering around it.&lt;/p&gt;
&lt;h3 id=&quot;the-bottom-line&quot;&gt;The Bottom Line&lt;/h3&gt;
&lt;p&gt;The query loop is where &quot;LLM talks, program walks&quot; becomes concrete:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The LLM outputs text and tool call JSON. That's it.&lt;/li&gt;
&lt;li&gt;The program handles compression, budget tracking, error recovery, streaming, permissions, memory injection, and 14-step tool validation.&lt;/li&gt;
&lt;li&gt;The 1,421 lines are not the model being smart. They're the program being careful.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you're building an AI agent and your main loop is under 100 lines, you're not handling the cases that matter. Production is not about the happy path. It's about what happens when context overflows, the API returns 413, the user's conversation hits 500 turns, and three tools need to run while the model is still thinking.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Next: Part 3 — The 14-Step Tool Execution Pipeline (coming soon) — what happens between &quot;model says call this tool&quot; and the tool actually running.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Previous: &lt;a rel=&quot;nofollow&quot; href=&quot;https://harrisonsec.com/blog/claude-code-source-leaked-hidden-features/&quot;&gt;Part 1 — 5 Hidden Features Found in 510K Lines&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Video: &lt;a rel=&quot;nofollow&quot; href=&quot;https://youtu.be/giNERYV-X7k&quot;&gt;The AI Stack Explained — LLM Talks, Program Walks&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/16781/claude-code-deep-dive-part-2-the-1-421-line-while-loop-that-runs-everything</guid>
<pubDate>Tue, 05 May 2026 19:10:54 +0000</pubDate>
</item>
<item>
<title>I built a Claude Code plugin for brand building in a weekend. Here's what I shipped and what I learned.</title>
<link>https://coderlegion.com/16101/built-claude-code-plugin-for-brand-building-in-weekend-heres-what-shipped-and-what-learned</link>
<description>&lt;p&gt;I've been writing code for 27 years. I picked up Claude Code the day it launched and haven't looked back. Last weekend I built a plugin that does something I've wanted for a while: brand positioning, messaging, voice, and visual identity using real expert frameworks, not &quot;generate a brand strategy&quot; vibes.&lt;/p&gt;
&lt;p&gt;Here's what I shipped and what surprised me along the way.&lt;/p&gt;
&lt;h4 id=&quot;the-problem-1&quot;&gt;The problem&lt;/h4&gt;
&lt;p&gt;Every time I've used AI for branding work, the output is the same. &quot;Innovative solutions that empower teams.&quot; Stuff that could belong to literally any company on earth. The issue isn't that AI is bad at branding. It's that nobody tells it what good branding actually looks like.&lt;/p&gt;
&lt;p&gt;So I packaged the actual methodologies into Claude Code skills:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Positioning:&lt;/strong&gt; April Dunford's 5-component framework from &lt;em&gt;Obviously Awesome&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Messaging:&lt;/strong&gt; Donald Miller's StoryBrand BrandScript&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Voice:&lt;/strong&gt; NN/g's brand voice dimensions + Aaker personality model&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visual identity:&lt;/strong&gt; Chris Do's stylescape method&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each skill follows the real framework. The positioning skill works through Dunford's five components in order because the order matters. It's not &quot;AI interprets the concept of positioning.&quot; It's &quot;AI follows a specific methodology and checks its own output.&quot;&lt;/p&gt;
&lt;h4 id=&quot;the-anti-slop-system&quot;&gt;The anti-slop system&lt;/h4&gt;
&lt;p&gt;This is the part I'm most proud of. Every skill runs its output through quality checks before showing it to you:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Swap test:&lt;/strong&gt; Could a competitor claim this? If your value proposition is &quot;we provide innovative solutions that empower teams,&quot; that fails. Every software company on earth could say that. The skill flags it and helps you find what's actually specific to you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specificity test:&lt;/strong&gt; Catches banned generic words (innovative, cutting-edge, leverage, empower, seamless, revolutionary, synergy) and replaces them with the concrete thing they were hiding.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Business-type test:&lt;/strong&gt; Would this positioning work for both a lawn care company and a SaaS? If yes, it's too generic.&lt;/p&gt;
&lt;h4 id=&quot;how-the-pieces-connect&quot;&gt;How the pieces connect&lt;/h4&gt;
&lt;p&gt;All 10 skills share state through a single &lt;code&gt;brand-brief.md&lt;/code&gt; file with YAML frontmatter. Positioning fills in fields. Messaging reads those fields and fills in more. Voice reads messaging. Visual identity reads all of it.&lt;/p&gt;
&lt;p&gt;Each component gets a confidence score: &lt;strong&gt;validated&lt;/strong&gt; (backed by real customer data), &lt;strong&gt;researched&lt;/strong&gt; (desk research), or &lt;strong&gt;assumed&lt;/strong&gt; (educated guess). Downstream skills flag when they're building on assumptions. They don't stop you, they just make sure you know what's solid and what's still a guess.&lt;/p&gt;
&lt;h4 id=&quot;what-surprised-me&quot;&gt;What surprised me&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;The plugin system is more powerful than I expected.&lt;/strong&gt; Claude Code plugins are just directories with structured markdown. No compiled code, no API calls, no build step. A skill is a markdown file with instructions that Claude follows. You can package entire methodologies into installable tools that anyone can clone and use.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Anti-slop checks actually work.&lt;/strong&gt; I ran the toolkit on my own brand and it caught two of four tagline candidates as too generic. The discipline of checking your own output against real criteria matters more than I thought.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Adaptive interactivity solves the &quot;blank page&quot; problem.&lt;/strong&gt; The positioning skill detects how much you know and picks one of three modes: research-assisted (you know nothing), guided (you know some things), or fast validation (you know your market). People at different stages get different experiences from the same tool.&lt;/p&gt;
&lt;h4 id=&quot;try-it&quot;&gt;Try it&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git clone https://github.com/jgerton/brand-toolkit.git
claude --plugin-dir ./brand-toolkit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run &lt;code&gt;/brand-toolkit:start&lt;/code&gt; and it figures out where you are.&lt;/p&gt;
&lt;p&gt;MIT licensed. &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/jgerton/brand-toolkit/blob/master/docs/GETTING-STARTED.md&quot;&gt;Full getting started guide here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I'm building more tools like this and sharing everything in &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.skool.com/you-craft-ai-helps/about&quot;&gt;my community&lt;/a&gt;. If you're into Claude Code beyond the basics, or you want to build your own plugins, come hang out.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/16101/built-claude-code-plugin-for-brand-building-in-weekend-heres-what-shipped-and-what-learned</guid>
<pubDate>Tue, 28 Apr 2026 23:56:38 +0000</pubDate>
</item>
<item>
<title>How I got my AI agents to communicate across repos — and shipped SAMP doing it</title>
<link>https://coderlegion.com/16043/how-i-got-my-ai-agents-to-communicate-across-repos-and-shipped-samp-doing-it</link>
<description>&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; I was working on &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/lumen-argus/lumen-argus&quot;&gt;&lt;strong&gt;lumen-argus&lt;/strong&gt;&lt;/a&gt;, a project that runs across three Claude Code sessions in three different repos. They needed to share context — &quot;I just refactored the auth module,&quot; &quot;the schema migration landed, pull main.&quot; For weeks I was copy-pasting between terminal windows like a caveman.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Task.&lt;/strong&gt; I wanted cross-session, cross-repo messaging for AI agents. Cheap. Fast. Local. Ideally something I could read with &lt;code&gt;cat&lt;/code&gt; if anything went wrong.&lt;/p&gt;
&lt;p&gt;Three constraints:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Token cost per message had to be near zero.&lt;/li&gt;
&lt;li&gt;No new servers, no daemons, no MCP handshake.&lt;/li&gt;
&lt;li&gt;It had to work for &lt;em&gt;any&lt;/em&gt; agent — Claude Code today, Cursor or my next project tomorrow.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Action.&lt;/strong&gt; I surveyed the existing options. &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/Dicklesworthstone/mcp_agent_mail&quot;&gt;&lt;code&gt;mcp_agent_mail&lt;/code&gt;&lt;/a&gt;, Agent Teams, broker daemons — all of them spin up an HTTP server, register identities, run a SQLite store, and burn tokens on polling hooks. Overkill for three agents swapping a dozen messages a day.&lt;/p&gt;
&lt;p&gt;So I borrowed Linus Torvalds' playbook from &lt;code&gt;git&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Per-writer append-only logs.&lt;/strong&gt; One file per agent: &lt;code&gt;log-&amp;lt;alias&amp;gt;.jsonl&lt;/code&gt;. No file ever has two writers, so there's no locking, no interleave, and Syncthing / Dropbox / iCloud can't cause merge conflicts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Content-addressed IDs.&lt;/strong&gt; &lt;code&gt;id = sha256({ts, from, to, thread, body})[:16]&lt;/code&gt;. Same content → same id, so dedup after sync is automatic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;mtime&lt;/code&gt; short-circuit.&lt;/strong&gt; Before parsing anything, stat the log files; if nothing changed, exit immediately.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I packaged it as &lt;strong&gt;SAMP&lt;/strong&gt; (Simple Agent Message Protocol) — a vendor-neutral spec — and shipped a reference implementation, &lt;strong&gt;agent-message&lt;/strong&gt;: three Claude Code slash commands (&lt;code&gt;/message-send&lt;/code&gt;, &lt;code&gt;/message-inbox&lt;/code&gt;, &lt;code&gt;/message-reply&lt;/code&gt;), a &lt;code&gt;msg&lt;/code&gt; shell helper for humans, and a tiny Python wrapper any other agent CLI can spawn.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Result.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1 Bash tool call per send/receive&lt;/strong&gt; from Claude Code. No MCP init, no ack roundtrip.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;0 LLM tokens&lt;/strong&gt; when humans (or &lt;code&gt;cron&lt;/code&gt;, or scripts) read/send via the shell helper. The model is never in the loop.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;~30 ms latency&lt;/strong&gt; — that's &lt;code&gt;python3&lt;/code&gt; startup. Everything else is a file append.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Works offline. Syncs across machines via Syncthing / Dropbox / iCloud&lt;/strong&gt; with zero conflicts by construction.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One install script.&lt;/strong&gt; No pip, no npm, no Docker.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Docs: &lt;a rel=&quot;nofollow&quot; href=&quot;https://slima4.github.io/agent-message/&quot;&gt;https://slima4.github.io/agent-message/&lt;/a&gt;&lt;br&gt;
Repo: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/slima4/agent-message&quot;&gt;https://github.com/slima4/agent-message&lt;/a&gt;&lt;br&gt;
Spec: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/slima4/agent-message/blob/main/SPEC.md&quot;&gt;https://github.com/slima4/agent-message/blob/main/SPEC.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you're juggling multiple agent sessions and copy-pasting between them, give it a try. PRs and issues welcome.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/16043/how-i-got-my-ai-agents-to-communicate-across-repos-and-shipped-samp-doing-it</guid>
<pubDate>Tue, 28 Apr 2026 05:29:41 +0000</pubDate>
</item>
<item>
<title>kasetto - declarative AI agent environment manager, written in Rust</title>
<link>https://coderlegion.com/15335/kasetto-declarative-ai-agent-environment-manager-written-in-rust</link>
<description>&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.kasetto.dev&quot;&gt;https://www.kasetto.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/pivoshenko/kasetto&quot;&gt;https://github.com/pivoshenko/kasetto&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hey community! &lt;/p&gt;
&lt;p&gt;I want to share an open-source tool I built for myself, and that I hope will be useful to other developers working with AI agents.&lt;/p&gt;
&lt;h3 id=&quot;the-problem-2&quot;&gt;The Problem&lt;/h3&gt;
&lt;p&gt;The more AI coding tools we adopted, the messier our setup got. Skills and MCP servers installed manually, via individual commands, or copy-pasted from docs. Scattered across Claude Code, Cursor, Codex, Windsurf - with no way to version any of it, no way to share it with teammates, no way to reproduce it on a new machine or project.&lt;/p&gt;
&lt;p&gt;Every new team member meant walking them through the same manual steps. Every new machine meant doing it all over again. And if someone changed a skill or added an MCP server, there was no way to propagate that to the rest of the team.&lt;/p&gt;
&lt;p&gt;Sound familiar?&lt;/p&gt;
&lt;h3 id=&quot;the-idea&quot;&gt;The Idea&lt;/h3&gt;
&lt;p&gt;I built &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/pivoshenko/kasetto&quot;&gt;kasetto&lt;/a&gt; to fix that. The idea is borrowed from things I already loved - the declarative reproducibility of dotfiles, the simplicity of &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/astral-sh/uv&quot;&gt;uv&lt;/a&gt; for Python packages. What uv did for Python, kasetto aims to do for AI agent skills.&lt;/p&gt;
&lt;p&gt;One YAML config describes your entire setup: skills, MCP servers, target agents. Commit it, share it, and everyone on the team gets the exact same environment. No manual editing, no drift between machines or teammates. New machine? One command.&lt;/p&gt;
&lt;h3 id=&quot;the-name&quot;&gt;The Name&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Kasetto&lt;/em&gt; (カセット) is the Japanese word for cassette - as in a cassette tape. A cassette was a self-contained, portable thing: you recorded something once, handed it to someone, and it played back exactly the same on any device. No setup, no drift, no &quot;works on my machine.&quot; That's exactly what kasetto does for your AI agent environment - package it once, share it, and it reproduces identically everywhere.&lt;/p&gt;
&lt;h3 id=&quot;why-kasetto&quot;&gt;Why kasetto&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Declarative&lt;/strong&gt; - one YAML config, version it, share it, bootstrap a whole team in seconds&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-agent&lt;/strong&gt; - 21 built-in presets: Claude Code, Cursor, Codex, Windsurf, Copilot, Gemini CLI, and more&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-source&lt;/strong&gt; - pulls from GitHub, GitLab, Bitbucket, Codeberg including self-hosted and enterprise&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP management&lt;/strong&gt; - merges MCP servers into each agent's native settings file automatically&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Global and project scopes&lt;/strong&gt; - install skills globally or per-project, each with its own lockfile&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI-friendly&lt;/strong&gt; - &lt;code&gt;--dry-run&lt;/code&gt; to preview, &lt;code&gt;--json&lt;/code&gt; for automation, non-zero exit on failure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Single binary&lt;/strong&gt; - no runtime dependencies, written in Rust, fast cold starts&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-it-works-1&quot;&gt;How It Works&lt;/h3&gt;
&lt;p&gt;Define your config:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;agent:
  - claude-code
  - cursor
  - codex

skills:
  - source: https://github.com/org/skill-pack
    skills: &quot;*&quot;
  - source: https://github.com/org/skill-pack-2
    skills:
      - product-design
  - source: https://github.com/org/skill-pack-3
    skills:
      - name: jupyter-notebook
        path: skills/.curated

mcps:
  - source: https://github.com/org/mcp-pack
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then sync:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kst sync
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That's it. Kasetto pulls the skills and MCP servers, installs them into the right agent directories, and merges MCP configs into each agent's native settings file. The next time you run &lt;code&gt;sync&lt;/code&gt;, only what changed gets updated.&lt;/p&gt;
&lt;h3 id=&quot;command-overview&quot;&gt;Command Overview&lt;/h3&gt;
&lt;p&gt;Kasetto ships with a focused set of commands - each does exactly one thing:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kst sync              # pull skills + MCP servers and install them
kst sync --dry-run    # preview what would change without touching anything
kst sync --json       # structured output for CI pipelines

kst list              # browse installed skills and MCPs interactively
kst list --json       # dump installed state as JSON

kst init              # scaffold a kasetto.yaml in the current directory
kst doctor            # check your environment and diagnose issues

kst clean             # remove all installed skills and MCP entries
kst self update       # update kasetto to the latest release
kst self uninstall    # remove kasetto and all its files
kst completions       # generate shell completions (bash, zsh, fish, etc.)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The binary is available as both &lt;code&gt;kasetto&lt;/code&gt; and &lt;code&gt;kst&lt;/code&gt; - the short alias makes daily use quick.&lt;/p&gt;
&lt;h3 id=&quot;install&quot;&gt;Install&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;macOS / Linux
curl -fsSL https://raw.githubusercontent.com/pivoshenko/kasetto/main/scripts/install.sh | sh

Homebrew
brew install pivoshenko/tap/kasetto

Cargo
cargo install kasetto
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;what-s-next-2&quot;&gt;What's Next&lt;/h3&gt;
&lt;p&gt;The &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/pivoshenko/kasetto#roadmap&quot;&gt;roadmap&lt;/a&gt; includes agents management and hooks management. If you have ideas or run into issues, &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/pivoshenko/kasetto/issues&quot;&gt;open an issue&lt;/a&gt; - feedback from real users shapes the direction.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/pivoshenko/kasetto&quot;&gt;github.com/pivoshenko/kasetto&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If kasetto saves you time, a GitHub star means a lot. And drop a comment below - I'd love to hear what your AI agent setup looks like today, and what pain points you're still hitting.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/15335/kasetto-declarative-ai-agent-environment-manager-written-in-rust</guid>
<pubDate>Mon, 20 Apr 2026 21:09:16 +0000</pubDate>
</item>
<item>
<title>Claude's default teaching shape has no return: the 5-node loop that fixes it</title>
<link>https://coderlegion.com/15337/claudes-default-teaching-shape-has-no-return-the-5-node-loop-that-fixes-it</link>
<description>&lt;p&gt;Ask Claude to teach you a non-trivial concept and watch the shape of the reply. It almost always descends: definition, syntax, an example, maybe a second example, a closing sentence that is either a summary or a handoff. The descent is fine. The problem is there is no return.&lt;/p&gt;
&lt;p&gt;The opening hook — the analogy or scenario the reader would have used to latch onto the concept — is never revisited. Syntax gets retained. Mechanism does not. A week later the reader can name the API but cannot explain why it works, because the concept was never re-grounded into the surface form they started in.&lt;/p&gt;
&lt;p&gt;I teach myself by having a fixed contract that forces the return. Five nodes. Every non-trivial concept travels them in order. If the teaching exchange does not close back on the opening analogy, the loop is incomplete and the concept has not landed — regardless of how detailed the middle was.&lt;/p&gt;
&lt;p&gt;This is the rule I run in &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/aman-bhandari/claude-code-agent-skills-framework&quot;&gt;claude-code-agent-skills-framework&lt;/a&gt; under &lt;code&gt;.claude/rules/concentric-loop.md&lt;/code&gt;. It carries a WHY tag and a retire-when clause so it decays cleanly when Claude's default teaching shape improves enough to make the rule unnecessary.&lt;/p&gt;
&lt;h3 id=&quot;the-five-nodes&quot;&gt;The five nodes&lt;/h3&gt;
&lt;p&gt;The loop travels analogy → code → system intermediaries → hardware/math → analogy. The final node is not a new analogy. It is the same analogy, now meaning more because the reader has traveled the physics underneath it.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Node &lt;/th&gt;&lt;th&gt;What it is&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;1. Analogy (OPEN) &lt;/td&gt;&lt;td&gt;A lived-experience scenario the reader already reasons fluently inside. Cooking, driving, a physical object in the room.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2. Code &lt;/td&gt;&lt;td&gt;The first machine-legible layer. Python, TypeScript, shell. I/O contract named before any line is written.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;3. System intermediaries &lt;/td&gt;&lt;td&gt;OS syscalls, networking, file descriptors, memory management. What the kernel is doing when the code runs.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;4. Hardware / math &lt;/td&gt;&lt;td&gt;CPU/GPU, IEEE 754, linear algebra, probability, gradients. The physics of correctness.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;5. Analogy (RETURN) &lt;/td&gt;&lt;td&gt;The same analogy as node 1, reinterpreted through the descent.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The descent is node 2 → 3 → 4. The return is not a victory lap. It is the gate that decides whether the reader has upgraded their mental model or only added facts to it.&lt;/p&gt;
&lt;h3 id=&quot;practitioner-anchors-per-node&quot;&gt;Practitioner anchors per node&lt;/h3&gt;
&lt;p&gt;Each node is pinned to a named methodology from a working 2025-2026 practitioner. If a teaching exchange cannot be traced to at least one of these per node it traverses, the descent is ungrounded and I pause and re-anchor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Node 1 (analogy).&lt;/strong&gt; No practitioner here — the anchor must come from the reader's own life, not a canon text. Borrowing an analogy from a book is how analogy inflation starts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Node 2 (code / I-O framing) — Chip Huyen.&lt;/strong&gt; Every code node opens with an explicit input/output specification: what goes in, what comes out, what data is available at what latency tier (online / nearline / offline). The latency-tier framing originates with Netflix (Amatriain and Basilico, 2013) and Huyen mainstreamed it in &lt;em&gt;Designing Machine Learning Systems&lt;/em&gt;. The node sounds like: &lt;em&gt;&quot;Before we write the function, state the contract. What is the input type, the output type, and what data are you assuming is already computed vs. computed on demand?&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Node 3 (system intermediaries / empirical baseline) — Eugene Yan + Hamel Husain.&lt;/strong&gt; Before any ML or agent component is introduced, Yan's &quot;start with the problem, not the technology&quot; asks: what regex, SQL, or rule-based filter already gets 50-70%? Before building on top of an LLM, Husain labels 20-100 real outputs by hand. The manual trace becomes the eval harness. The node sounds like: &lt;em&gt;&quot;Before we pick the model, show me the 30-line regex that would already solve half of this. Before we tune the prompt, label 25 outputs and tell me which ones are wrong and how.&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Node 4 (build-to-understand) — Jeremy Howard + Sebastian Raschka.&lt;/strong&gt; Howard (fast.ai Part 1) runs top-down: get a working artifact end-to-end first, then spiral into mechanism. Raschka (&lt;em&gt;Build a Large Language Model from Scratch&lt;/em&gt;) runs bottom-up: raw tensors, manual attention, everything by hand. The two balance each other. Howard for momentum (&quot;I built a thing&quot;), Raschka for mechanism (&quot;I built the thing's guts&quot;). The node sounds like: &lt;em&gt;&quot;Get it working end-to-end on 10 rows first — we will earn the right to optimize. Then we peel the library open and rebuild the core in 40 lines.&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Node 5 (atomic derivation / return) — Andrej Karpathy + Julia Evans.&lt;/strong&gt; Karpathy: shrink the concept until it fits in your head. micrograd is 100 lines of autograd; nanoGPT is 300 lines of training. The return to the analogy lands when the reader has seen the guts small enough to hold. Evans is the OS descent safety net: when the abstraction leaks, drop to strace / tcpdump / perf / /proc. The node sounds like: &lt;em&gt;&quot;Now that you have traced the whole thing, reduce it to the 40-line version you can explain on a whiteboard. If the abstraction leaks, we run strace and watch the syscalls.&quot;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;five-failure-modes-the-loop-has-to-catch&quot;&gt;Five failure modes the loop has to catch&lt;/h3&gt;
&lt;p&gt;The shape of the loop is not the hard part. The failure modes are.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Patronizing return.&lt;/strong&gt; The closing analogy is simpler than the opening one. This signals the teacher condescended during the descent — softened the mechanism — and the reader gets a dumbed-down echo of where they started. The return must land at equal or higher sophistication, enriched by the descent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Analogy leakage.&lt;/strong&gt; The reader starts reasoning about the analogy instead of the system. &quot;Functions are like machines that take input and return output&quot; breaks at closures, first-class functions, recursion. If the analogy never breaks, the reader is reasoning about the analogy, not the mechanism. Gentner's structure-mapping says the places the analogy does NOT map are where the deepest meaning lives — surface at least one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Descent-avoidance.&lt;/strong&gt; The return becomes permission to skip math or OS. &quot;We closed the loop on that one, moving on.&quot; The loop is not complete until nodes 3 AND 4 are traversed. A loop that skips the descent is a shape, not a proof.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Premature return.&lt;/strong&gt; Returning before mechanism-level understanding lands. The Bransford transfer test below is the gate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Analogy inflation.&lt;/strong&gt; Multiple analogies accumulate. The reader remembers the metaphors and forgets the mechanisms. One analogy per concept. The return reuses the opening analogy. Do not replace.&lt;/p&gt;
&lt;h3 id=&quot;the-bransford-transfer-test-loop-completion-gate-&quot;&gt;The Bransford transfer test (loop-completion gate)&lt;/h3&gt;
&lt;p&gt;Bransford and Schwartz, &quot;Rethinking Transfer&quot; (1999), is the empirical spine. Transfer requires re-encountering the concept in a different surface form. Descent-only teaching produces what Whitehead (1929) called &quot;inert knowledge&quot; — the reader cannot apply it outside the original context.&lt;/p&gt;
&lt;p&gt;After the return, pose a novel problem in a new surface form. Different domain, different vocabulary, different practitioner's framing. If the reader solves it, the loop worked. If the reader can only reproduce the original analogy, the loop collapsed into memorization and needs another descent with a different analogy or a deeper cut.&lt;/p&gt;
&lt;p&gt;This test also works as an eval for Claude's output. Swap the system prompt or the input schema. Check whether the agent's correctness transfers or was memorized against the original framing. The three failure signals: (1) the agent can only reproduce the original analogy, (2) it solves the old problem but not the transfer, (3) it solves the transfer only after a hint.&lt;/p&gt;
&lt;h3 id=&quot;whole-loop-practitioners-worth-studying&quot;&gt;Whole-loop practitioners worth studying&lt;/h3&gt;
&lt;p&gt;These four execute the entire loop in a single artifact — open, descent, return — and are worth reading to feel the shape end to end.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Julia Evans&lt;/strong&gt; — zines and blog (jvns.ca). Scenario opens, syscall/kernel middle, practical close.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jeremy Howard&lt;/strong&gt; — fast.ai Part 1. Whole game first, then mechanism, then whole game with new eyes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Andrej Karpathy&lt;/strong&gt; — Zero to Hero. Opens with analogy (&quot;a neural net is just a function&quot;), descends through autograd/backprop, returns to &quot;now you can train GPT.&quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bret Victor&lt;/strong&gt; — &quot;Ladder of Abstraction.&quot; The loop &lt;em&gt;is&lt;/em&gt; the argument.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pick any post by any of the four. Mark where the open is, where the descent hits its deepest point, and where the return lands. You will start seeing the shape everywhere it exists and everywhere it is missing. The second list is longer than the first.&lt;/p&gt;
&lt;p&gt;That is the whole practice. Contract the shape into a rule file. Apply it to every concept you explain and every concept Claude explains to you. Refuse to call the concept landed until the return fires.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/aman-bhandari/claude-code-agent-skills-framework&quot;&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/aman-bhandari/claude-code-mcp-qa-automation&quot;&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/15337/claudes-default-teaching-shape-has-no-return-the-5-node-loop-that-fixes-it</guid>
<pubDate>Mon, 20 Apr 2026 21:03:04 +0000</pubDate>
</item>
<item>
<title>I Built a 35-Agent AI Coding Swarm That Runs Overnight</title>
<link>https://coderlegion.com/13713/i-built-a-35-agent-ai-coding-swarm-that-runs-overnight</link>
<description>&lt;p&gt;*Follow-up to *&lt;em&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;/blog/the-week-i-stopped-coding&quot;&gt;The Week I Stopped Coding&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;A month ago, I wrote about the moment I stopped coding and started orchestrating AI agents. That post was about the shift — the emotional and philosophical pivot from developer to director.&lt;br&gt;
This post is about what happened after.&lt;br&gt;
I built a system. Two physical machines on my home network, 14 containers, 35 concurrent AI coding sessions, and a 5-layer memory architecture that teaches agents not to repeat each other's mistakes. It scans my project management board every two minutes, picks up tickets, creates isolated git worktrees, spawns Claude Code sessions, writes code, creates pull requests, and updates ticket statuses — all without me touching a keyboard.&lt;br&gt;
It processes 20-40 tickets overnight. I wake up to PRs.&lt;/p&gt;
&lt;h3 id=&quot;i-ve-seen-this-before&quot;&gt;I've Seen This Before&lt;/h3&gt;
&lt;p&gt;In 2015, I was drawing CI/CD pipeline diagrams on whiteboards at Kohl's. Build → Test → Publish → QA → Deploy → Stabilization → Release. The full continuous delivery loop, managed by hundreds of people across multiple teams — developers, QA engineers, DevOps, project managers, release coordinators.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.sanity.io/images/dafshiq1/production/760016ade1a8c529cf93901176d7ff4b24bbd38c-1138x792.png&quot; alt=&quot;CI/CD lifecycle diagram from Kohl's MobileFirst project, 2015&quot;&gt;&lt;/p&gt;
&lt;p&gt;I look at that diagram now and I see my swarm's ticket lifecycle. The stages are identical. Linear scan is the ticket intake. The Claude Code session is the development cycle. Sub-agents run the build, test, and review gates. &lt;code&gt;gh pr create&lt;/code&gt; is the publish step. Vercel auto-deploys on merge. Prometheus watches the stabilization metrics. The only difference is who's executing each stage.&lt;br&gt;
In 2015, that loop required a branching strategy document that went through 11 revisions, a deployment runbook with IBM coordination steps, Chef cookbooks for node management, and a standing army of engineers. In 2026, it's one Node.js script and a vector database.&lt;br&gt;
I'm not saying the people don't matter — they built the institutional knowledge that's now encoded in CLAUDE.md files and Qdrant collections. But the execution layer has fundamentally changed. The same pipeline I designed for human teams a decade ago now runs autonomously on two machines in my house.&lt;/p&gt;
&lt;h3 id=&quot;the-hardware-two-machines-one-network&quot;&gt;The Hardware: Two Machines, One Network&lt;/h3&gt;
&lt;p&gt;No cloud compute for the swarm itself. Two machines on my home network — a Linux desktop and a Mac Studio I picked up for mobile builds.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.sanity.io/images/dafshiq1/production/2b3ec34875e37cab85d803ff829395ae52931ac8-900x420.svg&quot; alt=&quot;Physical topology — Dragon desktop and Hive Mac Studio connected over LAN&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dragon&lt;/strong&gt; (desktop) — Arch Linux, AMD ROCm GPU, 14 Podman containers. This is the primary orchestration node. It runs the director, the dashboard, Qdrant for vector search, Ollama for embeddings, and the full Prometheus/Grafana monitoring stack. 15 concurrent session slots.&lt;br&gt;
&lt;strong&gt;Hive&lt;/strong&gt; (Mac Studio) — The only machine with Xcode, iOS simulators, Android emulators, Fastlane, and Maestro for mobile QA. 20 concurrent session slots. Three macOS LaunchAgents handle its director, worker, and git-watcher processes.&lt;br&gt;
They talk over SSH and a shared Qdrant instance. The desktop pushes build tasks to the hive's Qdrant — I use the vector database as a task queue because macOS LaunchAgents get &lt;code&gt;EHOSTUNREACH&lt;/code&gt; when connecting back to the desktop IP. Flipping the direction solved it.&lt;br&gt;
Total capacity: 35 concurrent AI coding sessions across 6 repositories.&lt;/p&gt;
&lt;h3 id=&quot;the-three-layers&quot;&gt;The Three Layers&lt;/h3&gt;
&lt;p&gt;The architecture has three distinct layers, each operating independently.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.sanity.io/images/dafshiq1/production/887d3807a112b3459cae9377fc252b1c63bf317b-900x620.svg&quot; alt=&quot;Three-layer architecture diagram&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 2: Ops Runner.&lt;/strong&gt; Infrastructure health. Zombie process detection every 15 minutes. TTL sweeps that mark tasks stuck over 30 minutes as failed. Metrics export to Prometheus — 43 metrics every 5 minutes. A React dashboard with 6 tabs that gives me visibility into what the swarm is doing. Without this layer, you don't know if the swarm is working or burning money.&lt;br&gt;
&lt;strong&gt;Layer 3: Directors.&lt;/strong&gt; This is the AI layer. Two directors — Dragon on the desktop handling backend and infrastructure (event-api, game-library, venues, monitoring, ops), Hive on the Mac Studio handling frontend and mobile (shindig, website). Each scans Linear every 2 minutes, routes tickets to the correct repo, creates git worktrees for isolation, and spawns Claude Code sessions.&lt;br&gt;
The director is about 2,400 lines of Node.js. It's the single most important piece of the system — and in major need of refactoring. Now that I'm wrapping back around to making the ops swarm self-sufficient, it needs to follow its own linting and testing protocols. The irony of an autonomous coding system that doesn't enforce code quality on itself is not lost on me.&lt;/p&gt;
&lt;h3 id=&quot;how-a-ticket-becomes-a-pr&quot;&gt;How a Ticket Becomes a PR&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.sanity.io/images/dafshiq1/production/b0e3b3a5b1817228ecd408b9fd90d92a1ab962a4-900x1400.svg&quot; alt=&quot;Ticket lifecycle flowchart — 8 steps from Linear scan to PR creation with success, failure, and rate limit paths&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Linear scan&lt;/strong&gt; (every 120 seconds). The director queries for tickets in Agent Queue, QA Queue, QA Testing, or In Review. It checks attempt history — each ticket gets 3 shots before it's skipped.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ticket routing.&lt;/strong&gt; Title prefix &lt;code&gt;[website]&lt;/code&gt; goes to the website repo. No prefix? Keyword matching. The &lt;code&gt;detectRepo()&lt;/code&gt; function is blunt but effective:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function detectRepo(issue) {
  const text = `${issue.title} ${issue.description || ''}`.toLowerCase();
  // Check explicit repo names first
  for (const repo of ['shindig', 'venues', 'event-api', 'game-library', 'website', 'monitoring']) {
    if (text.includes(repo)) return repo;
  }
  // Mobile/app keywords → shindig
  const shindigKeywords = ['maestro', 'e2e test', 'testflight', 'app store', 'play store',
    'fastlane', 'ios', 'android', 'mobile', 'kotlin', 'swift', 'xcode', 'gradle',
    'composable', 'jetpack', 'kmp', 'multiplatform', 'simulator', 'emulator',
    'firebase auth', 'deep link', 'push notif', 'in-app purchase', 'storekit',
    'billing', 'aab', 'ipa', 'bundle id', 'provisioning', 'signing key',
    'app group', 'widget', 'crashlytics'];
  for (const kw of shindigKeywords) {
    if (text.includes(kw)) return 'shindig';
  }
  // Ops/infra keywords → ops
  const opsKeywords = ['swarm', 'ops', 'ci/cd', 'pipeline', 'deploy', 'config',
    'infrastructure', 'docker', 'podman', 'container', 'github action',
    'orchestrat', 'director', 'dashboard', 'grafana', 'prometheus',
    'script', 'automation', 'devops', 'agent', 'memory', 'qdrant',
    'terraform', 'gcp', 'cloud run', 'fly.io', 'vercel'];
  for (const kw of opsKeywords) {
    if (text.includes(kw)) return 'ops';
  }
  return 'unknown'; // skip rather than routing to wrong repo
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Fair warning: this is quick, dirty, get-it-running code. Not pretty. It works, it's being refactored, and I'm showing it because the pattern matters more than the polish.&lt;/em&gt;&lt;br&gt;
This was the first pass. It's not sophisticated. It doesn't need to be. The title prefix catches 80% of tickets. The keyword fallback catches most of the rest. Unknown tickets get skipped — better to miss a ticket than route it to the wrong repo.&lt;br&gt;
Since then, the routing has gone through a full arc. I added Linear labels, repo-specific tags, and more complex matching rules. It got more sophisticated — and harder to maintain. Now I'm simplifying back down: labels and tooling handle the routing upstream, so the director doesn't need 50 keywords to figure out where a ticket belongs. The lesson is the same one every system learns — the first simple version works, the complex version works harder, and the final version is simple again on purpose.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Worktree creation.&lt;/strong&gt; &lt;code&gt;git worktree add&lt;/code&gt; creates an isolated directory with its own branch: &lt;code&gt;agent/fir-{ticketId}&lt;/code&gt;. Multiple tickets for the same repo can run in parallel without stepping on each other. This is essential — without worktree isolation, concurrent agents create merge conflicts on every commit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Session spawn.&lt;/strong&gt; The director launches Claude Code with the ticket description, all comments, the repo's CLAUDE.md rules, and RAG context from prior agent learnings — all injected into the system prompt. Model starts at Sonnet. If it fails twice, it auto-escalates to Opus.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Execution.&lt;/strong&gt; The Claude Code session reads code, plans an approach, and spawns its own sub-agents — a researcher (Haiku), a coder (Sonnet), a tester (Haiku), and a reviewer (Haiku). Each sub-agent gets a fresh context window. No context pollution from the parent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PR creation.&lt;/strong&gt; The session commits, pushes, creates a PR targeting the repo's base branch, and updates the Linear ticket status.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cleanup.&lt;/strong&gt; Worktree removed. Pool slot freed. Next scan picks up more work.&lt;br&gt;
The director also batches up to 4 tickets per repo into a single session, so the agent has broader context and can address related issues together. A typical ticket takes 5-60 minutes depending on complexity. The director fills available pool slots continuously. By morning, I have a stack of PRs to review.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;inside-the-director-processticket-&quot;&gt;Inside the Director: processTicket()&lt;/h3&gt;
&lt;p&gt;The heart of the system is &lt;code&gt;processTicket()&lt;/code&gt;. This is the function that takes a ticket from the queue and turns it into a coding session. Here's what happens under the hood — model escalation, worktree creation, rate limit detection, and the failure classification that took me weeks to get right:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;async function processTicket(ticket, config, state) {
  let worktree;
  try {
    // Model escalation: after N failed attempts, upgrade to stronger model
    const prev = state?.ticketsWorked?.[ticket.identifier];
    const failedAttempts = prev ? prev.attempts : 0;
    const threshold = config.escalationThreshold ?? ESCALATION_THRESHOLD;
    const escalated = failedAttempts &amp;gt;= threshold &amp;amp;&amp;amp; config.model !== config.escalationModel;
    const ticketConfig = escalated
      ? { ...config, model: config.escalationModel }
      : config;

    if (escalated) {
      log(`MODEL ESCALATION: ${ticket.identifier} failed ${failedAttempts}x ` +
          `on ${config.model} → upgrading to ${config.escalationModel}`);
    }

    acquireLock(ticket.identifier, ticket.repo);
    worktree = createWorktree(ticket.repo, ticket.identifier);

    const result = await runClaudeSession(ticket, worktree.worktreePath, worktree, ticketConfig);

    if (!result.success) {
      const tail = result.output.slice(-300);

      // Detect rate limit OR auth failure errors
      const isRateLimit = RATE_LIMIT_PATTERNS.some(p =&amp;gt; p.test(tail));
      const isAuthFailure = AUTH_FAILURE_PATTERNS.some(p =&amp;gt; p.test(tail));
      const isFastFail = result.duration_ms &amp;lt; FAST_FAIL_THRESHOLD_MS &amp;amp;&amp;amp; !result.timedOut;

      // Fast failures (&amp;lt; 10s) are never real work — don't burn attempts
      if (isFastFail) {
        result.rateLimited = true;
        log(`FAST FAIL: ${ticket.identifier} died in ` +
            `${Math.round(result.duration_ms / 1000)}s — not counting as attempt`);
      }

      if (isRateLimit || isAuthFailure) {
        if (!rateLimitState.detected) {
          rateLimitState.detected = true;
          // Parse reset time, default to 4am Central
          const resetMatch = result.output.match(
            /resets?\s+(\d+)\s*(am|pm)\s*\(([^)]+)\)/i
          );
          // ... calculate sleep duration, auto-pause director
          notifySlack(`:warning: Director hit rate limit. Auto-pausing until reset.`);
        }
      }
    }

    return { ticketId: ticket.identifier, success: result.success, ... };

  } finally {
    releaseLock(ticket.identifier);
    cleanupWorktree(worktree);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Same caveat as above — this is working code, not clean code. The director script is 2,400 lines of Node.js that grew organically as failures taught me what it needed to handle. Refactoring it is on the roadmap.&lt;/em&gt;&lt;br&gt;
The escalation logic is simple: attempts 1-2 run on Sonnet. Attempt 3 auto-upgrades to Opus. The rate limit detection is what took the most iteration — the system had to learn the difference between &quot;this ticket is hard&quot; and &quot;the infrastructure is down.&quot; That distinction saved me from permanently skipping dozens of viable tickets.&lt;/p&gt;
&lt;h3 id=&quot;how-do-you-solve-ai-agent-memory-loss-&quot;&gt;How Do You Solve AI Agent Memory Loss?&lt;/h3&gt;
&lt;p&gt;AI agents are amnesiac by default. When I started, a Claude Code session got 200K tokens of context. Now Opus 4.6 has a 1M token window. Bigger helps — but the fundamental problem is the same. The moment the session ends, everything it learned disappears. The next agent assigned a similar ticket starts from zero and makes the same mistakes.&lt;br&gt;
This is the fundamental problem of autonomous AI coding at scale. I solved it with 5 layers of memory, each serving a different persistence scope.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.sanity.io/images/dafshiq1/production/8cd988d832f6aa271fede5627a9682e4eabb2f27-900x520.svg&quot; alt=&quot;5-layer memory hierarchy&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 2: CLAUDE.md files.&lt;/strong&gt; Checked into git at each repo root. Every agent session in a repo automatically loads these rules — branch patterns, build commands, quality standards, things the agent must never do. This is institutional knowledge encoded as configuration.&lt;br&gt;
&lt;strong&gt;Layer 3: File memory.&lt;/strong&gt; Claude Code's auto-memory system at &lt;code&gt;~/.claude/projects/&lt;/code&gt;. Over 20 topic files covering build pipelines, secret management, deployment procedures, lessons learned. Survives across sessions on the local machine.&lt;br&gt;
&lt;strong&gt;Layer 4: Vector memory.&lt;/strong&gt; Qdrant stores nearly 16,000 knowledge points and all agent outcomes. Before starting work, agents query for relevant prior learnings using semantic search. After completing work, they record what happened — success or failure, with context. This is how the swarm learns. A failed Gradle build gets recorded. The next agent searching &quot;shindig android build&quot; finds it and doesn't repeat the same mistake.&lt;br&gt;
&lt;strong&gt;Layer 5: Linear tickets.&lt;/strong&gt; The human-agent interface. I embed decisions directly in ticket descriptions and comments. Agents read both before acting. This is the only layer where I actively participate in the memory system.&lt;br&gt;
The key insight: agents query Qdrant &lt;em&gt;before&lt;/em&gt; starting work and record outcomes &lt;em&gt;after&lt;/em&gt; finishing. A memory-agent container consolidates learnings every 6 hours. The swarm genuinely learns from its own history.&lt;/p&gt;
&lt;h3 id=&quot;the-failures&quot;&gt;The Failures&lt;/h3&gt;
&lt;p&gt;This is the part that matters. Anyone can describe an architecture. The real story is in how it broke.&lt;/p&gt;
&lt;h4 id=&quot;124-pull-requests-overnight&quot;&gt;124 Pull Requests Overnight&lt;/h4&gt;
&lt;p&gt;I woke up to 124 open PRs on one repo. About 90 were duplicates — the same tickets processed over and over because the director never checked whether a PR already existed. It would scan Linear, find tickets in Agent Queue, spawn sessions, create PRs — but never move tickets out of Agent Queue. Next scan cycle: same ticket, new branch, new PR.&lt;br&gt;
While I was closing duplicates, the hive director kept creating new ones. 7 more appeared during cleanup.&lt;br&gt;
&lt;strong&gt;The fix:&lt;/strong&gt; Dedup guard. Check for existing PRs before creating new ones. Move tickets to In Progress when work starts, In Review when the PR is created. Deterministic branch naming — no random suffixes.&lt;br&gt;
&lt;strong&gt;The lesson:&lt;/strong&gt; If your agent loop doesn't track what it already did, it will do everything twice.&lt;/p&gt;
&lt;h4 id=&quot;every-session-ran-on-opus&quot;&gt;Every Session Ran on Opus&lt;/h4&gt;
&lt;p&gt;I noticed rate limits being hit in hours instead of lasting all day. The director script never passed a &lt;code&gt;--model&lt;/code&gt; flag. Claude Code defaults to Opus — the most expensive model. 747+ sessions ran on Opus before I caught it.&lt;br&gt;
One missing CLI flag. Token consumption was 3-5x what it needed to be. A $15/day operation became $65/day.&lt;br&gt;
&lt;strong&gt;The fix:&lt;/strong&gt; Added &lt;code&gt;--model sonnet&lt;/code&gt; as default. Model escalation: attempts 1-2 use Sonnet, attempt 3 auto-escalates to Opus. Immediate 3-5x cost reduction.&lt;br&gt;
&lt;strong&gt;The lesson:&lt;/strong&gt; Defaults matter enormously at scale. A single missing flag multiplied by 1,000 sessions turned a cost-effective operation into a budget-burner.&lt;/p&gt;
&lt;h4 id=&quot;46-out-of-46-sessions-failed-in-one-cycle&quot;&gt;46 out of 46 Sessions Failed in One Cycle&lt;/h4&gt;
&lt;p&gt;The director launched 46 sessions. Every single one died within 1-20 seconds with &quot;You've hit your limit.&quot; The director treated these as normal failures, incremented attempt counters, and after 3 &quot;failures&quot; permanently skipped each ticket.&lt;br&gt;
By morning, 37 tickets were stuck in limbo and dozens were marked as &quot;max attempts exceeded&quot; — even though the failures had nothing to do with the tickets themselves.&lt;br&gt;
&lt;strong&gt;The fix:&lt;/strong&gt; Rate limit pattern matching. Auth failure detection. Fast-fail threshold — sessions dying in under 10 seconds don't count as real attempts. If &amp;gt;80% of a cycle's sessions fail fast, auto-pause the director and sleep until the rate limit resets.&lt;br&gt;
&lt;strong&gt;The lesson:&lt;/strong&gt; Your orchestrator must distinguish between &quot;the task failed&quot; and &quot;the infrastructure failed.&quot; Burning ticket attempts on rate limits is like marking a restaurant order as &quot;rejected by customer&quot; because the kitchen caught fire.&lt;/p&gt;
&lt;h4 id=&quot;the-agent-that-sent-me-on-a-wild-goose-chase&quot;&gt;The Agent That Sent Me on a Wild Goose Chase&lt;/h4&gt;
&lt;p&gt;A Haiku-model agent was assigned an Apple Sign-In bug. After a brief code scan, it confidently told me: &quot;The Firebase Console needs &lt;code&gt;com.firefly.shindig.dev&lt;/code&gt; added as an authorized domain.&quot;&lt;br&gt;
I spent 20 minutes checking the Firebase Console. It was already correct. The &lt;code&gt;.dev&lt;/code&gt; bundle ID doesn't even exist — the app uses &lt;code&gt;com.firefly.shindig.ios&lt;/code&gt;.&lt;br&gt;
The real problem was three code bugs the agent never found.&lt;br&gt;
&lt;strong&gt;The fix:&lt;/strong&gt; Verification protocol. Agents can't tell humans to change external config without file-and-line code evidence. Memory files take precedence — if memory says it's configured and working, the agent needs strong evidence before claiming otherwise. Config-level claims get escalated to Opus for verification.&lt;br&gt;
&lt;strong&gt;The lesson:&lt;/strong&gt; An agent that confidently sends you on a wild goose chase is worse than one that says &quot;I don't know.&quot; Cheaper models need guardrails that prevent authoritative claims about systems they can't inspect.&lt;/p&gt;
&lt;h4 id=&quot;oauth-in-containers-three-login-attempts-destroyed&quot;&gt;OAuth in Containers: Three Login Attempts Destroyed&lt;/h4&gt;
&lt;p&gt;Claude Code authenticates via OAuth. Tokens expire and refresh automatically. I tried three approaches to get auth working in Podman containers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;claude login&lt;/code&gt; inside the container. Works until restart — credentials wiped.&lt;/li&gt;
&lt;li&gt;Base64-encode credentials as an env var. The entrypoint script always decodes on startup, overwriting any token refresh.&lt;/li&gt;
&lt;li&gt;Copy host credentials at build time. Stale by the time the container runs.&lt;br&gt;
&lt;strong&gt;The fix:&lt;/strong&gt; Bind-mount the host credentials file directly into the container:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;volumes:
  - ${HOME}/.claude/.credentials.json:/home/swarm/.claude/.credentials.json:rw
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Login once on the host, container stays authenticated across restarts, rebuilds, and token rotations. Set the env var to empty string so the entrypoint skips injection.&lt;br&gt;
&lt;strong&gt;The lesson:&lt;/strong&gt; Live auth tokens must be shared, not copied. Any approach that snapshots a token creates a stale copy.&lt;/p&gt;
&lt;h4 id=&quot;five-zombie-detectors-all-broken&quot;&gt;Five Zombie Detectors, All Broken&lt;/h4&gt;
&lt;p&gt;After the 124-PR incident, I discovered agent processes that finished work but never exited. They consumed memory and held file locks, preventing new sessions.&lt;br&gt;
I had five separate zombie detection mechanisms. Not one caught the problem.&lt;br&gt;
The bash script only checked for duplicates, not resource thresholds. The task-level checker only looked at output file freshness. The cleanup script explicitly &lt;em&gt;skipped&lt;/em&gt; daemon processes. The ops runner only checked Qdrant task state. The container-based detector couldn't see outside its own namespace.&lt;br&gt;
&lt;strong&gt;The fix:&lt;/strong&gt; One detection mechanism that actually works end-to-end. Process-level zombie detection in the ops runner. Session timeout as a catch-all.&lt;br&gt;
&lt;strong&gt;The lesson:&lt;/strong&gt; Five bad detectors are not better than one good one. Each was built for a specific variant of the problem but had blind spots. The result was false confidence.&lt;/p&gt;
&lt;h3 id=&quot;the-numbers&quot;&gt;The Numbers&lt;/h3&gt;
&lt;p&gt;Over 7 weeks of operation:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.sanity.io/images/dafshiq1/production/66cb96c0b44fd7b85dbd9d0602ed7cc65ebfc6f5-900x420.svg&quot; alt=&quot;Daily agent runs over 7 weeks&quot;&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Metric &lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Total agent runs &lt;/td&gt;&lt;td&gt;6,500+&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Repos covered &lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Peak day (March 5)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/13713/i-built-a-35-agent-ai-coding-swarm-that-runs-overnight</guid>
<pubDate>Mon, 30 Mar 2026 20:18:33 +0000</pubDate>
</item>
<item>
<title>Claude Code agent teams: what the docs don't tell you</title>
<link>https://coderlegion.com/11808/claude-code-agent-teams-what-the-docs-dont-tell-you</link>
<description>&lt;p&gt;Claude Code quietly shipped agent teams as an experimental feature. The idea is simple: instead of one AI agent working through your task sequentially, you spin up multiple agents that work in parallel, communicate with each other, and coordinate through a shared task list.&lt;/p&gt;
&lt;p&gt;I've been running team sessions for the past week. Some went well. Some burned through tokens and produced nothing useful. Here's what I figured out.&lt;/p&gt;
&lt;h4 id=&quot;you-need-to-enable-it-manually&quot;&gt;You need to enable it manually&lt;/h4&gt;
&lt;p&gt;Agent teams are off by default. Add this to your settings:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;// .claude/settings.json or ~/.claude/settings.json
{
  &quot;env&quot;: {
    &quot;CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS&quot;: &quot;1&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or export it in your shell: &lt;code&gt;export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1&lt;/code&gt;&lt;/p&gt;
&lt;h4 id=&quot;subagents-and-agent-teams-are-different-things&quot;&gt;Subagents and agent teams are different things&lt;/h4&gt;
&lt;p&gt;This tripped me up at first and I've seen the same confusion everywhere. Claude Code has two parallelism mechanisms, and they work nothing alike.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subagents&lt;/strong&gt; use the Task tool. You spawn a focused worker, it does a thing, and returns results to the parent. Workers can't talk to each other. The parent manages everything. Token cost is lower because results get summarized back into the parent's context.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Agent teams&lt;/strong&gt; are fully independent Claude Code sessions. Each teammate has its own context window, loads project context (CLAUDE.md, MCP servers) automatically, and can message other teammates directly. They coordinate through a shared task list with file-locked claiming and dependency tracking.&lt;/p&gt;
&lt;p&gt;The practical difference: subagents are like sending someone to fetch an answer. Agent teams are like putting three people in a room to work on a problem together.&lt;/p&gt;
&lt;p&gt;Here's when each one makes sense:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Use subagents when... &lt;/th&gt;&lt;th&gt;Use agent teams when...&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;You need quick, focused results &lt;/td&gt;&lt;td&gt;Teammates need to discuss and challenge each other&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Tasks are independent — no cross-talk needed &lt;/td&gt;&lt;td&gt;Work requires coordination across multiple layers&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;You want lower token costs &lt;/td&gt;&lt;td&gt;Parallel exploration adds real value&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;The parent can manage all coordination &lt;/td&gt;&lt;td&gt;Tasks have clear file boundaries but need collaboration&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I'd estimate 70-80% of tasks that feel like they need a team actually work fine with subagents. The Task tool with &lt;code&gt;subagent_type&lt;/code&gt; set to Explore, Plan, or general-purpose handles most research and implementation tasks without the coordination overhead.&lt;/p&gt;
&lt;h4 id=&quot;the-cost-math&quot;&gt;The cost math&lt;/h4&gt;
&lt;p&gt;Each teammate is a full Claude session with its own context window. A 3-teammate team uses roughly 3-4x the tokens of sequential work.&lt;/p&gt;
&lt;p&gt;That's not a rounding error. For a task that takes 20 minutes sequentially, spinning up a team to finish it in 8 minutes costs 3-4x more. Whether that trade-off makes sense depends on how much your time is worth relative to API spend.&lt;/p&gt;
&lt;p&gt;The tasks where teams clearly pay off:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Multi-file features with clean boundaries (frontend + backend + tests)&lt;/li&gt;
&lt;li&gt;Large refactors where multiple directories can be worked on simultaneously&lt;/li&gt;
&lt;li&gt;Adversarial review patterns (one agent implements, another tries to break it)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The tasks where they don't:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Anything touching fewer than 4-5 files&lt;/li&gt;
&lt;li&gt;Sequential work where step 2 depends on step 1's output&lt;/li&gt;
&lt;li&gt;Quick bug fixes (the coordination overhead exceeds the time saved)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;file-conflicts-are-the-1-failure-mode&quot;&gt;File conflicts are the #1 failure mode&lt;/h4&gt;
&lt;p&gt;Two teammates editing the same file doesn't produce a merge conflict. It produces data loss. One agent's changes silently overwrite the other's.&lt;/p&gt;
&lt;p&gt;This was my most expensive lesson. Before any parallel coding, you need to map out exactly which agent owns which files. No shared files. If two tasks need to touch the same file, they run sequentially, not in parallel.&lt;/p&gt;
&lt;p&gt;The pattern that works: decompose your task into pieces where each piece owns a distinct set of files. If you can't draw clean boundaries, the task isn't a good candidate for a team.&lt;/p&gt;
&lt;h4 id=&quot;teammates-don-t-know-what-you-know&quot;&gt;Teammates don't know what you know&lt;/h4&gt;
&lt;p&gt;This is counterintuitive. Your main Claude Code session (the &quot;lead&quot;) has your full conversation history — the bug you described, the architecture you discussed, the constraints you mentioned. When you spawn a teammate, they start with a blank conversation. They load CLAUDE.md and MCP servers, but they don't inherit any of your context.&lt;/p&gt;
&lt;p&gt;This means your spawn prompts need to be detailed. Not &quot;implement the auth module&quot; but &quot;implement an auth module using JWT tokens stored in httpOnly cookies, following the patterns in src/middleware/auth.ts, compatible with the Express 5 router setup in src/app.ts, with unit tests in tests/auth.test.ts.&quot;&lt;/p&gt;
&lt;p&gt;The more context you front-load into the spawn prompt, the less the teammate drifts. I started writing spawn prompts that were 200-300 words and the quality of output went up immediately.&lt;/p&gt;
&lt;h4 id=&quot;the-workflow-that-actually-produces-results&quot;&gt;The workflow that actually produces results&lt;/h4&gt;
&lt;p&gt;After several failed attempts, here's the sequence I settled on:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Decide if you need a team at all.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ask yourself: can I decompose this into 3+ parallel tasks with zero file overlap? If no, use sequential work or subagents.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Decompose into agent-sized pieces.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Each piece needs: a clear goal, explicit file ownership, a definition of done, and an integration contract (how this piece connects to the others). Vague task descriptions produce vague results.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Map file boundaries.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Write it down. Agent A owns these files. Agent B owns these files. No overlap. If you skip this step, you will lose work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Plan first, then swarm.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Spawn one agent in plan mode to design the architecture. Review and approve the plan. Then spawn parallel agents to implement against the approved plan. This prevents agents from making conflicting architectural decisions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Run a retrospective.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After the team finishes, look at what each agent actually did, how many tokens each consumed, and where time was wasted. The cost breakdown alone will change how you structure the next run.&lt;/p&gt;
&lt;h4 id=&quot;things-that-will-bite-you&quot;&gt;Things that will bite you&lt;/h4&gt;
&lt;p&gt;A few gotchas that aren't in the docs:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No session resumption.&lt;/strong&gt; If your terminal session drops, &lt;code&gt;/resume&lt;/code&gt; and &lt;code&gt;/rewind&lt;/code&gt; don't restore teammates. The team is gone. This matters for long-running tasks — save checkpoints or break work into shorter team sessions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tasks get stuck.&lt;/strong&gt; Teammates sometimes forget to mark tasks as completed, which blocks any dependent tasks downstream. If something looks frozen, check the task list manually.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Shutdown is slow.&lt;/strong&gt; Teammates finish their current API request before stopping. If an agent is mid-generation on a long response, you'll wait.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Drift happens.&lt;/strong&gt; Letting a team run unattended for 30+ minutes increases the chance of wasted work. Agents can go down rabbit holes, misinterpret requirements, or produce code that conflicts with another agent's approach. Check in periodically.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One team per session.&lt;/strong&gt; Clean up the current team (shut down all teammates, then delete the team) before starting a new one.&lt;/p&gt;
&lt;h4 id=&quot;start-with-non-code-tasks&quot;&gt;Start with non-code tasks&lt;/h4&gt;
&lt;p&gt;If you haven't used agent teams before, don't start with parallel implementation. Start with tasks where parallel exploration is valuable but file conflicts aren't a risk:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multi-angle PR review&lt;/strong&gt;: one agent checks logic correctness, another checks test coverage, a third checks security and error handling&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Competing hypotheses debugging&lt;/strong&gt;: agent A investigates &quot;this is a race condition,&quot; agent B investigates &quot;this is a stale cache,&quot; they report findings and you decide&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Research from multiple angles&lt;/strong&gt;: one agent reads the library docs, another searches for known issues on GitHub, a third looks at alternative libraries&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These tasks let you learn how messaging, task claiming, and coordination work without the stress of parallel file edits.&lt;/p&gt;
&lt;h4 id=&quot;a-19-prompt-playbook&quot;&gt;A 19-prompt playbook&lt;/h4&gt;
&lt;p&gt;After running enough team sessions to see the patterns, I built a set of reusable prompts covering the full lifecycle:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Decide&lt;/strong&gt; (prompts 1-5): Should I use a team? How do I decompose the task? What model for each agent? How do I map file boundaries?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Orchestrate&lt;/strong&gt; (prompts 6-12): Plan-then-swarm coordination, delegate mode, adversarial code review, parallel TDD, handoff reports, real-time steering&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quality&lt;/strong&gt; (prompts 13-15): Hooks that auto-validate work before an agent goes idle or marks a task complete, plan approval checklists&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Recover&lt;/strong&gt; (prompts 16-19): Unsticking looping agents, optimizing token costs, retrospectives, anti-pattern detection&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The full playbook is free: &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.nerdychefs.ai/learn/agent-teams&quot;&gt;Claude Code Agent Teams Playbook on NerdyChefs.ai&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;the-honest-take&quot;&gt;The honest take&lt;/h4&gt;
&lt;p&gt;Agent teams are a power tool, not a default workflow. The coordination overhead — context duplication, file boundary management, spawn prompt writing, monitoring for drift — means they only pay off for genuinely parallel work with clean boundaries.&lt;/p&gt;
&lt;p&gt;For a solo developer working on a focused feature, sequential Claude Code with occasional subagent calls is cheaper and more predictable. For a large cross-layer feature where three agents can work on frontend, backend, and tests simultaneously without touching each other's files, teams save real time.&lt;/p&gt;
&lt;p&gt;The key is being honest about which category your task falls into before you spawn anything.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;What patterns have you found with agent teams? I'm particularly interested in hearing about non-obvious use cases where the parallel coordination actually paid off.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/11808/claude-code-agent-teams-what-the-docs-dont-tell-you</guid>
<pubDate>Tue, 17 Feb 2026 08:06:17 +0000</pubDate>
</item>
</channel>
</rss>