<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Stephan Miller</title>
    <description>Kansas City Software Engineer and Writer</description>
    <link>https://www.stephanmiller.com/</link>
    <atom:link href="https://www.stephanmiller.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 05 Aug 2026 08:43:30 -0500</pubDate>
    <lastBuildDate>Wed, 05 Aug 2026 08:43:30 -0500</lastBuildDate>
    <generator>Jekyll v4.2.2</generator>
    
      <item>
        <title>The Expensive Model Only Plans Now: I Split My AI Coding Rig Across Two Tools</title>
        <description>&lt;p&gt;A couple of posts back I pulled a month of my own session logs to catch coding red-handed as the token hog, and &lt;a href=&quot;https://www.stephanmiller.com/planning-is-cheap-coding-is-not-and-my-own-logs-proved-me-wrong-about-why/&quot;&gt;the meter came back flat&lt;/a&gt;. Planning and building cost about the same to run. The expensive part is the thinking that has to happen &lt;em&gt;before&lt;/em&gt; the typing, and that thinking is mine.&lt;/p&gt;

&lt;p&gt;If the typing is the cheap, fast, mechanical part, why am I paying frontier-model prices for it? Why is Opus, the model I keep around because it can &lt;em&gt;think&lt;/em&gt;, the one grinding out a config file from a spec I already wrote?&lt;/p&gt;

&lt;p&gt;It shouldn’t be. I should keep the expensive model for the one thing it should, and hand all the work after that to &lt;a href=&quot;https://www.stephanmiller.com/the-cheapskates-guide-to-the-arena-leaderboard-why-i-stopped-paying-claude-opus-prices/&quot;&gt;the cheapest models that can write code&lt;/a&gt;. Which, it turns out, means splitting the work across two different tools. Claude Code plans, &lt;a href=&quot;https://opencode.ai&quot;&gt;Opencode&lt;/a&gt; builds.&lt;/p&gt;

&lt;p&gt;This is part four of a series about working with AI coding agents on an open-ended project through a single living &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLAN.md&lt;/code&gt; instead of vibe coding or spec-kit ceremony. &lt;a href=&quot;https://www.stephanmiller.com/the-third-attempt-how-a-living-plan-beat-both-vibe-coding-and-spec-kit/&quot;&gt;Post one&lt;/a&gt; is the thesis: the doc is the deliverable, the code is the byproduct. The &lt;a href=&quot;https://www.stephanmiller.com/the-living-plan-got-fat-compacting-a-doc-that-wont-stop-growing/&quot;&gt;last few&lt;/a&gt; were about keeping that doc lean and figuring out where the real cost lives. This one is about what happens when you stop paying the planner to type.&lt;/p&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#the-setup-one-expensive-model-doing-two-jobs&quot; id=&quot;markdown-toc-the-setup-one-expensive-model-doing-two-jobs&quot;&gt;The Setup: One Expensive Model Doing Two Jobs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#enter-opencode-and-a-roster-of-cheap-models&quot; id=&quot;markdown-toc-enter-opencode-and-a-roster-of-cheap-models&quot;&gt;Enter opencode (and a Roster of Cheap Models)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-rule-id-just-landed-on-and-why-i-inverted-it&quot; id=&quot;markdown-toc-the-rule-id-just-landed-on-and-why-i-inverted-it&quot;&gt;The Rule I’d Just Landed On, and Why I Inverted It&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#reviewers-that-dont-share-the-builders-blind-spots&quot; id=&quot;markdown-toc-reviewers-that-dont-share-the-builders-blind-spots&quot;&gt;Reviewers That Don’t Share the Builder’s Blind Spots&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-tell-the-diagrams-came-before-the-code&quot; id=&quot;markdown-toc-the-tell-the-diagrams-came-before-the-code&quot;&gt;The Tell: The Diagrams Came Before the Code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#three-docs-three-sets-of-write-permissions&quot; id=&quot;markdown-toc-three-docs-three-sets-of-write-permissions&quot;&gt;Three Docs, Three Sets of Write Permissions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-whole-truth&quot; id=&quot;markdown-toc-the-whole-truth&quot;&gt;The Whole Truth&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#whats-next&quot; id=&quot;markdown-toc-whats-next&quot;&gt;What’s Next&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-setup-one-expensive-model-doing-two-jobs&quot;&gt;The Setup: One Expensive Model Doing Two Jobs&lt;/h2&gt;

&lt;p&gt;For most of this series my setup has been one tool wearing two hats. I plan in Claude Code with Opus. Plain chat, back and forth, drilling down until the design is actually pinned. Then the &lt;em&gt;same&lt;/em&gt; Claude Code hands the build work to Sonnet sub-agents. Opus knows, Sonnet does. On the Pro plan I could talk to Opus for a long planning session and barely dent my usage, because in build mode the token-heavy churn (the greps, the file reads, the edits) happens in a sub-agent’s own context and comes back as a short summary. The orchestrator stays lean.&lt;/p&gt;

&lt;p&gt;That’s a fine setup. But it has Opus, or at least a Claude model, standing over &lt;em&gt;every&lt;/em&gt; build task, and I’d just proven to myself that the build tasks are the mechanical part. I was using an expensive model to assemble flat-pack furniture. The instructions were already written. Any model that can read can do the work.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/the-expensive-model-only-plans-now-i-split-my-ai-c-body-1.jpg&quot; alt=&quot;The Setup: One Expensive Model Doing Two Jobs&quot; srcset=&quot;            /assets/resized/480/the-expensive-model-only-plans-now-i-split-my-ai-c-body-1.jpg 480w,            /assets/resized/800/the-expensive-model-only-plans-now-i-split-my-ai-c-body-1.jpg 800w,            /assets/resized/1400/the-expensive-model-only-plans-now-i-split-my-ai-c-body-1.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here’s the framing that made me actually move, and it’s stolen from a thing I said to myself during a debugging session months ago: &lt;strong&gt;models are the Temu of things.&lt;/strong&gt; They’ll have knowledge of many things, but the most generalized version of it. A one-line prompt gets you the average of everything ever written on the subject. And if the build task is &lt;em&gt;fully specified&lt;/em&gt;, if I did the custom thinking already and wrote it down, then Temu is exactly what I want. Generalized competence at assembling a known thing is cheap and abundant. I just had to stop buying it at boutique prices.&lt;/p&gt;

&lt;h2 id=&quot;enter-opencode-and-a-roster-of-cheap-models&quot;&gt;Enter opencode (and a Roster of Cheap Models)&lt;/h2&gt;

&lt;p&gt;The tool that let me do this cleanly is &lt;a href=&quot;https://opencode.ai&quot;&gt;Opencode&lt;/a&gt;, a terminal coding agent that, crucially, lets you assign a &lt;em&gt;different model to every agent&lt;/em&gt; through a repo-local &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opencode.json&lt;/code&gt;, routed through OpenRouter. So the plan stays in Claude Code with Opus, and the entire build crew lives in opencode, each role on whatever model is cheapest for its job.&lt;/p&gt;

&lt;p&gt;Here’s the roster, trimmed from the real config:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://opencode.ai/config.json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;small_model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/z-ai/glm-4.7-flash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;default_agent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;orchestrate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;agent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;orchestrate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/z-ai/glm-5.2&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mode&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;subagent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/xiaomi/mimo-v2.5-pro&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ai-pipeline&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mode&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;subagent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/deepseek/deepseek-v4-pro&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;qa-fast&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mode&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;subagent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/deepseek/deepseek-v4-flash&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;qa-deep&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mode&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;subagent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/google/gemini-3.1-pro-preview&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;debug&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mode&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;subagent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/anthropic/claude-sonnet-5&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;docs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mode&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;subagent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/qwen/qwen3.7-plus&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;research&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mode&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;subagent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/deepseek/deepseek-v4-flash&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;architect&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/anthropic/claude-opus-5&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not a Claude model in the build path. GLM-5.2 orchestrates. A Xiaomi MiMo model writes the Go daemon and the CLI. DeepSeek handles the ML and retrieval code. Qwen writes the docs. The only Anthropic models in the whole file are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug&lt;/code&gt; (Sonnet, for when something’s genuinely stuck) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;architect&lt;/code&gt;. And to tell you the truth, most of the model choices are just a test of what will work in that slot or even if I need all these different agents.&lt;/p&gt;

&lt;p&gt;I’ve been coy about &lt;em&gt;what&lt;/em&gt; this crew is building, so: it’s &lt;a href=&quot;https://www.stephanmiller.com/i-got-tired-of-ai-memory-hype-so-i-built-a-context-lake/&quot;&gt;the Context Lake&lt;/a&gt;, the one-brain-outside-the-agents thing I wrote about a month back. A Go daemon that watches my session logs and my vault, a Python ML layer that indexes and retrieves, a CLI and a dashboard sitting on top. That matters here for exactly one reason: it is not a toy. It’s a real multi-language system with a knowledge graph, a vector store, and a daemon.&lt;/p&gt;

&lt;p&gt;MiMo wasn’t even my first pick for the build. I started with GLM-5.2 doing double duty, orchestrating &lt;em&gt;and&lt;/em&gt; building, and swapped the builder over to MiMo on day three (the commit message, optimistically, reads “for improved performance”). It’s cheaper on the output tokens a builder spends most of, though I’ll warn you the exact gap is a moving target: model pricing on OpenRouter whiplashes week to week, and as I write this GLM’s page is showing 76% off. The reason I &lt;em&gt;kept&lt;/em&gt; MiMo, though, wasn’t the couple of cents. It was that GLM tends to lose the thread across a long series of tasks, and MiMo just… doesn’t. Stack it deep and it grinds through the whole queue. For a builder whose entire job is to chew an unattended stack while I’m somewhere else, that turned out to matter more than the price.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/the-expensive-model-only-plans-now-i-split-my-ai-c-body-2.jpg&quot; alt=&quot;Enter opencode (and a Roster of Cheap Models)&quot; srcset=&quot;            /assets/resized/480/the-expensive-model-only-plans-now-i-split-my-ai-c-body-2.jpg 480w,            /assets/resized/800/the-expensive-model-only-plans-now-i-split-my-ai-c-body-2.jpg 800w,            /assets/resized/1400/the-expensive-model-only-plans-now-i-split-my-ai-c-body-2.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The division of labor is the same knower/doer split I’ve run all along, just stretched across a tool boundary:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Claude Code + Opus is the planner.&lt;/strong&gt; It’s where I think, discuss, and write the tasks. It never runs in opencode. The picks were made against live OpenRouter pricing using &lt;a href=&quot;https://www.stephanmiller.com/building-a-cost-saving-skill-that-accidentally-became-its-own-newsletter/&quot;&gt;my weekly model-buzz research&lt;/a&gt; as the value spine, so this isn’t “cheap for the sake of cheap.” It’s cheap where cheap is fine, and one expensive model where thinking has to happen.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Opencode is the whole build crew.&lt;/strong&gt; It reads the tasks I wrote, does the keystrokes, runs the checks, reports back.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;architect&lt;/code&gt;, the lone Opus-4.8 agent in opencode? It’s set to manual-only and &lt;strong&gt;never&lt;/strong&gt; auto-invoked. It’s my break-glass “call in a senior for a from-orbit sanity check” button for when a Claude Code session isn’t handy. A zero-invocation count on it is &lt;em&gt;expected&lt;/em&gt;. I wrote a note in the repo telling future-me not to delete it as dead config, because future-me absolutely would.&lt;/p&gt;

&lt;h2 id=&quot;the-rule-id-just-landed-on-and-why-i-inverted-it&quot;&gt;The Rule I’d Just Landed On, and Why I Inverted It&lt;/h2&gt;

&lt;p&gt;Here’s where it got uncomfortable, because I had to break something I’d just decided was right.&lt;/p&gt;

&lt;p&gt;In my single-tool setup, &lt;a href=&quot;https://www.stephanmiller.com/the-bottleneck-was-me-how-i-stopped-racing-my-ai-builder-and-started-pacing-it/&quot;&gt;the builder works a queue of numbered tasks&lt;/a&gt;, and the rule for a task it can’t finish was: &lt;strong&gt;skip it and keep going.&lt;/strong&gt; If piece 3 of 8 turns out underspecified, some fork I didn’t see, don’t halt the whole queue. Mark it blocked, move to piece 4, do everything that doesn’t depend on the broken one. An hour away should come back with six of eight done, not two. I was proud of that rule. It’s the thing that makes walking away safe.&lt;/p&gt;

&lt;p&gt;Then I moved the build to opencode and inverted it completely. The rule now: &lt;strong&gt;hit something underspecified, stop and report. Do not keep going. Do not invent the next task. Do not promote anything from the parking lot.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Same person, opposite rule, two weeks apart. What changed?&lt;/p&gt;

&lt;p&gt;The tool boundary changed. In the single-tool world, the thing that skips a blocked task and continues is &lt;em&gt;the same context that could re-plan it&lt;/em&gt;. It’s all one agent, warm on the whole conversation, and “keep going past the blocker” is safe because the planner is right there. In the cross-tool world, &lt;strong&gt;the planner is a different tool.&lt;/strong&gt; Opencode is a cheap executor that knows nothing about my planning thread and has no business deciding what to build next. Discovering work and scheduling work are different authorities, and I’d just handed them to different tools. If I let the cheap builder skip-and-continue, I’m letting the model I specifically chose &lt;em&gt;not&lt;/em&gt; to think make the scheduling calls.&lt;/p&gt;

&lt;p&gt;So the executor’s rule became rigid on purpose. From the actual contract in the repo:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/the-expensive-model-only-plans-now-i-split-my-ai-c-body-3.jpg&quot; alt=&quot;The Rule I&apos;d Just Landed On, and Why I Inverted It&quot; srcset=&quot;            /assets/resized/480/the-expensive-model-only-plans-now-i-split-my-ai-c-body-3.jpg 480w,            /assets/resized/800/the-expensive-model-only-plans-now-i-split-my-ai-c-body-3.jpg 800w,            /assets/resized/1400/the-expensive-model-only-plans-now-i-split-my-ai-c-body-3.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You may NOT execute items in § Next (underspecified by design — stop at the tier boundary and report), may NOT promote items out of § Parking lot, and may NOT invent new tasks. If § Now is drained, SAY SO AND STOP.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Take the planner out of the room and put it in another tool, and the safe move flips to “stop and wait.” A rule is only as good as the context it assumes, and the second you move the work across a boundary, re-check every assumption.&lt;/p&gt;

&lt;h2 id=&quot;reviewers-that-dont-share-the-builders-blind-spots&quot;&gt;Reviewers That Don’t Share the Builder’s Blind Spots&lt;/h2&gt;

&lt;p&gt;If cheap models are doing the building, the obvious worry is quality. My answer has two parts, and neither is “trust the cheap model.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part one: the reviewers run on a different bloodline than the builder.&lt;/strong&gt; The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build&lt;/code&gt; agent is MiMo; the deep reviewer, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qa-deep&lt;/code&gt;, is Gemini; the debugger is Sonnet. A reviewer that shares the implementer’s model lineage shares its blind spots. It’ll wave through the same class of mistake the builder was prone to make, because it thinks the same way. Point review and implementation at the same model and review quietly stops catching anything. Different lineage, different blind spots.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part two, and this is the one I got wrong first: the obligation to run the checks lives on the agent that can’t forget it.&lt;/strong&gt; Originally I had the planner enforce QA: “call the reviewer after every step.” It decayed. And I have the receipts, because this is the kind of thing I’d rather catch myself than have a commenter catch. I audited 58 opencode sessions on this project and found QA delegation went from &lt;strong&gt;5 calls in the first two weeks to 0 in the last two&lt;/strong&gt;, while the builder kept right on running. The deep reviewer, whose trigger was the soft phrase “at milestones,” had fired &lt;strong&gt;exactly zero times.&lt;/strong&gt; The invariants I care about were never actually being checked.&lt;/p&gt;

&lt;p&gt;Why did it decay? Because a planner’s context fills up over a long orchestration and it drops the soft, optional steps, the same way you stop doing the stretches your physical therapist gave you. The fix wasn’t a sterner reminder. It was structural: &lt;strong&gt;move the obligation onto the sub-agents, which get fresh context on every spawn.&lt;/strong&gt; The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ai-pipeline&lt;/code&gt; agents are now not-done until they’ve run the checks and pasted the output into their report, and the planner rejects any completion report that lacks it. An obligation on a long-lived context erodes. An obligation on a fresh-every-spawn context can’t. Don’t ask a model to remember. Make it structural.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/the-expensive-model-only-plans-now-i-split-my-ai-c-body-4.jpg&quot; alt=&quot;Reviewers That Don&apos;t Share the Builder&apos;s Blind Spots&quot; srcset=&quot;            /assets/resized/480/the-expensive-model-only-plans-now-i-split-my-ai-c-body-4.jpg 480w,            /assets/resized/800/the-expensive-model-only-plans-now-i-split-my-ai-c-body-4.jpg 800w,            /assets/resized/1400/the-expensive-model-only-plans-now-i-split-my-ai-c-body-4.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The deep reviewer got the same treatment. Instead of “at milestones,” it fires on a deterministic condition. When the current batch of work is drained, before the batch is reported done, it reviews the whole batch diff against a fixed list of the project’s load-bearing rules. A trigger you can’t measure is a trigger that never fires.&lt;/p&gt;

&lt;p&gt;I did have to fix the ordering the hard way first, because my initial config &lt;em&gt;looked&lt;/em&gt; right and wasn’t. Agents weren’t firing in sequence, QA was skippable, and a couple of agents never ran at all. So I rewrote it to force the line: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build&lt;/code&gt; writes the code and runs its own tests, and only after the checks pass does the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docs&lt;/code&gt; agent, which always reads the real code first, write anything. When I later asked Claude whether that fix actually held, the read was blunt: &lt;strong&gt;“Ordering is right. The QA-gate fix is genuinely first.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And then, a couple of weeks later, the whole thing handed me a lesson I didn’t order. At the batch drain the gate was green across the board: 43 Python tests passed, ruff and mypy clean, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go build&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go test&lt;/code&gt; fine. Then I ran the thing against real data. The dashboard crashed on an actual projection file, and the project-identity code reported &lt;strong&gt;6 projects where the vault holds 24&lt;/strong&gt;, four of the six being phantoms. Its last-resort rule for naming a project was “first tag containing a hyphen,” so it had been happily minting a project per topic tag. Both bugs sailed straight through a green gate. Making the checks structural fixed &lt;em&gt;whether they run&lt;/em&gt;. It did not turn them into a proxy for the software being correct, and I had started quietly treating it as one.&lt;/p&gt;

&lt;h2 id=&quot;the-tell-the-diagrams-came-before-the-code&quot;&gt;The Tell: The Diagrams Came Before the Code&lt;/h2&gt;

&lt;p&gt;Here’s the small, dumb detail that actually convinced me the split works.&lt;/p&gt;

&lt;p&gt;Back at the start, on June 26th, before a line of the Go daemon or the Python ML code existed, I had Claude draw the architecture as a set of mermaid diagrams. Not because the code was complex; there wasn’t any. Because the &lt;em&gt;plan&lt;/em&gt; was: “is there any way that we can create a rough mermaid diagram of what’s going on here? Cause it’s getting kind of complex now.” The diagrams were a picture of the intended system, committed a few hours before the first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;daemon/&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ml/&lt;/code&gt; directories landed that same evening.&lt;/p&gt;

&lt;p&gt;Then the roster of cheap models built the thing, over weeks, one specified task at a time.&lt;/p&gt;

&lt;p&gt;At some point I had Claude audit the built system, half-expecting the usual rot, docs that lie because nobody updated them. Instead: &lt;strong&gt;“OpenCode has kept the architecture honest.”&lt;/strong&gt; The diagrams hadn’t been quietly patched to match the code. The code had been built to match the diagrams. Weeks of cheap-model keystrokes, and the shape at the end was the shape I’d drawn on day one.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/the-expensive-model-only-plans-now-i-split-my-ai-c-body-5.jpg&quot; alt=&quot;The Tell: The Diagrams Came Before the Code&quot; srcset=&quot;            /assets/resized/480/the-expensive-model-only-plans-now-i-split-my-ai-c-body-5.jpg 480w,            /assets/resized/800/the-expensive-model-only-plans-now-i-split-my-ai-c-body-5.jpg 800w,            /assets/resized/1400/the-expensive-model-only-plans-now-i-split-my-ai-c-body-5.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That’s the real proof, and it’s humbler than “the cheap models are geniuses.” They’re not. But a plan they can’t skip, run in an order they can’t reorder, gets followed faithfully enough that the map you sketched before any code existed still describes the territory a month later. That’s the whole bet: the intelligence goes into the plan, and the plan is cheap to enforce.&lt;/p&gt;

&lt;h2 id=&quot;three-docs-three-sets-of-write-permissions&quot;&gt;Three Docs, Three Sets of Write Permissions&lt;/h2&gt;

&lt;p&gt;The last piece is the guardrail that keeps a cheap, eager builder from wandering off. When two tools share one repo, “who’s allowed to write what” stops being a style preference and becomes the fence that keeps them from fighting. Three docs, three permissions:&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;| Doc              | What it is                          | Who writes            |
|------------------|-------------------------------------|-----------------------|
| docs/vision.md   | The vision, architecture, invariants| Planner only          |
| TASKS.md         | The current batch of committed work | Executor (checkboxes) |
| docs/archive/    | Completed batches, frozen           | Planner, at replan    |
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The executor, opencode, can check off boxes in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TASKS.md&lt;/code&gt; § Now as work lands, keep the status line current, and &lt;strong&gt;append&lt;/strong&gt; discoveries to a parking lot. That’s it. It cannot edit the vision doc, cannot promote a parked item into the active work, cannot write the next batch. Those are planning authorities, and planning happens in the other tool, driven by me.&lt;/p&gt;

&lt;p&gt;This sounds like bureaucracy until you’ve watched a helpful agent decide, unprompted, that it knows what you want to build next. The most load-bearing sentence in the whole config is the one that tells the opencode orchestrator, in so many words, to &lt;strong&gt;never tell the human to “exit plan mode” or hand the work back&lt;/strong&gt;. Its job is to act by delegating to a sub-agent, not to bounce the plan back to me with a “ready when you are.” And the sibling rule, which longtime readers know I’ve promoted to a standing law: planning is a &lt;em&gt;discussion&lt;/em&gt;, not a multiple-choice quiz. The moment a tool tries to compress the design conversation into three options, you lose the part that was doing the work.&lt;/p&gt;

&lt;h2 id=&quot;the-whole-truth&quot;&gt;The Whole Truth&lt;/h2&gt;

&lt;p&gt;What I’m solid on: the &lt;em&gt;shape&lt;/em&gt; is right. Paying a thinker to type is a real waste, the cost data backs it up, and separating “who plans” from “who types” onto tools priced for each job is a clean way to stop doing it. The QA-decay finding is measured, not vibed: 58 sessions, 5 to 0, a reviewer that never fired. And putting the obligation on fresh context instead of a memory is a principle I’ll stand behind anywhere.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/the-expensive-model-only-plans-now-i-split-my-ai-c-body-6.jpg&quot; alt=&quot;The Honest Scope Note&quot; srcset=&quot;            /assets/resized/480/the-expensive-model-only-plans-now-i-split-my-ai-c-body-6.jpg 480w,            /assets/resized/800/the-expensive-model-only-plans-now-i-split-my-ai-c-body-6.jpg 800w,            /assets/resized/1400/the-expensive-model-only-plans-now-i-split-my-ai-c-body-6.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;What surprised me is how &lt;em&gt;smooth&lt;/em&gt; the unattended part has been. I can stack five tasks, walk away, and come back to a screen full of done. Actually unattended, actually finished, and I keep having Opus re-audit the whole thing because I half don’t believe it.&lt;/p&gt;

&lt;p&gt;What I was wrong about is the finish line. I wrote most of this post feeling like the project was nearly done. It isn’t. The batch I cut on July 18th sits at 11 of 15 remaining, it got &lt;em&gt;extended&lt;/em&gt; three days later after another dogfooding pass, and the scope has since grown a cross-repo orchestration layer and a skills catalog. The cheap crew is fast at the work I hand it. That was never the same thing as the work running out.&lt;/p&gt;

&lt;p&gt;What I’m still &lt;em&gt;not&lt;/em&gt; solid on: whether the cheap builders stay good enough, at scale, over time. The two bugs above are the first real data point, and they’re ambiguous on purpose. Neither is obviously a “a Claude builder would have caught this” failure, because both were spec gaps that a green test suite couldn’t see either. But they’re exactly the shape of thing I said I was watching for, they showed up inside a month, and one project going smoothly is still a sample size of one. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qa-deep&lt;/code&gt; reviewer is on a &lt;em&gt;preview-tier&lt;/em&gt; model, which means it can get rate-limited, change behavior, or vanish out from under me on a random Tuesday; I keep a same-obligation, different-lineage fallback noted for exactly that. And the roster itself drifts. Model pricing moves, slugs get deprecated, and the config is the truth while any table I write about it is already going stale. The table in my own docs has lied to me before.&lt;/p&gt;

&lt;p&gt;So: promising shape, real receipts on the &lt;em&gt;why&lt;/em&gt;, genuinely unproven on the “are cheap models good enough” question that the whole thing rides on. Frontier of the method, not a settled result.&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next&lt;/h2&gt;

&lt;p&gt;The plan lives in Claude Code with Opus, the build lives in Opencode with a crew of cheap models, the expensive model only thinks, and the whole thing is fenced by who’s allowed to write which file. It runs. Whether it &lt;em&gt;holds&lt;/em&gt; is the thing I actually have to live with now instead of theorize about. Can Temu models carry a real build over months without quietly costing me more in bugs than they saved me in tokens?&lt;/p&gt;

&lt;p&gt;There’s a bigger post hiding under this one, the thesis version: that planning is the only thing in the whole stack worth a boutique model, and everything downstream is keystrokes you can buy in bulk. I’ve now watched that hold across three projects, which is finally enough proof points to write it honestly instead of as a hot take. That’s the one I want to write eventually.&lt;/p&gt;
</description>
        <pubDate>Wed, 05 Aug 2026 07:00:00 -0500</pubDate>
        <link>https://www.stephanmiller.com/the-expensive-model-only-plans-now-i-split-my-ai-coding-rig-across-two-tools/</link>
        <guid isPermaLink="true">https://www.stephanmiller.com/the-expensive-model-only-plans-now-i-split-my-ai-coding-rig-across-two-tools/</guid>
        
        <category>Claude Opus</category>
        
        <category>opencode AI</category>
        
        <category>LLM cost optimization</category>
        
        <category>AI coding agents</category>
        
        <category>multi-model AI setup</category>
        
        <category>AI workflow optimization</category>
        
        
        <category>agentic-development</category>
        
      </item>
    
      <item>
        <title>Qwen3.8-Max Dropped. I&apos;m Still Running the $0.87 Model.</title>
        <description>&lt;p&gt;This week Alibaba dropped Qwen3.8-Max, a 2.4-trillion-parameter monster, and the stock jumped 7% in Hong Kong. Everybody lost their minds. And the smartest thing a cheapskate can do with that news is nod politely and keep running a Chinese model from April that costs 57 times less than the thing everyone’s actually cheering for.&lt;/p&gt;

&lt;p&gt;Let me explain how I got there.&lt;/p&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#china-dropped-a-24-trillion-parameter-flagship-and-i-mostly-yawned&quot; id=&quot;markdown-toc-china-dropped-a-24-trillion-parameter-flagship-and-i-mostly-yawned&quot;&gt;China Dropped a 2.4-Trillion-Parameter Flagship and I Mostly Yawned&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-smartest-model-in-the-world-had-an-awkward-debut&quot; id=&quot;markdown-toc-the-smartest-model-in-the-world-had-an-awkward-debut&quot;&gt;The “Smartest Model in the World” Had an Awkward Debut&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-boring-answer-that-keeps-winning&quot; id=&quot;markdown-toc-the-boring-answer-that-keeps-winning&quot;&gt;The Boring Answer That Keeps Winning&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cheapskate-picks-where-the-actual-money-is&quot; id=&quot;markdown-toc-cheapskate-picks-where-the-actual-money-is&quot;&gt;Cheapskate Picks: Where the Actual Money Is&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#horror-stories-from-the-wild&quot; id=&quot;markdown-toc-horror-stories-from-the-wild&quot;&gt;Horror Stories From the Wild&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#coming-soon-or-soon-anyway&quot; id=&quot;markdown-toc-coming-soon-or-soon-anyway&quot;&gt;Coming Soon (Or “Soon,” Anyway)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#what-i-actually-took-away-this-week&quot; id=&quot;markdown-toc-what-i-actually-took-away-this-week&quot;&gt;What I Actually Took Away This Week&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;china-dropped-a-24-trillion-parameter-flagship-and-i-mostly-yawned&quot;&gt;China Dropped a 2.4-Trillion-Parameter Flagship and I Mostly Yawned&lt;/h2&gt;

&lt;p&gt;Here’s the thing about Qwen3.8-Max. It’s genuinely impressive on paper. 2.4 trillion total parameters, 95 billion active through a sparse mixture-of-experts setup, a 1-million-token context window, and API access that went worldwide on day one. It landed at #5 on the Arena text leaderboard and #2 on the vision board about a day after launch, which makes it the highest-ranked Chinese text model anyone’s ever put up. Alibaba priced it at roughly 24% to 40% of Claude Opus 5. Open weights are supposedly landing next week.&lt;/p&gt;

&lt;p&gt;But look at the votes. It’s sitting at #5 on 3,327 Arena votes. Opus 4.6-thinking above it has 67,000. When a model debuts high on a thin vote count, that’s not a verdict, that’s a first impression with good lighting. Arena rewards new-and-polished before the crowd has actually lived with the thing.&lt;/p&gt;

&lt;p&gt;And then there’s the benchmark table. Alibaba says Qwen3.8-Max scores 86.1 on OSWorld-Verified, ahead of GPT-5.6 Sol Max at 83.2 and Fable 5 at 85.0. It claims 86.6 on Terminal-Bench 2.1 and 93.0 on PaperBench. Great numbers. Here’s my problem: &lt;a href=&quot;https://venturebeat.com/technology/qwen3-8-max-arrives-with-a-bold-claim-it-outperforms-gpt-5-6-sol-max-and-fable-5-on-agentic-computer-use&quot;&gt;that table includes self-reported scores for the competitors too&lt;/a&gt;, and as of the day before I wrote this, &lt;a href=&quot;https://evolink.ai/blog/qwen3-8-benchmark&quot;&gt;no independent evaluation of the model existed at all&lt;/a&gt;. A vendor grading its own homework and its rivals’ homework in the same table isn’t a lie. It’s just not evidence yet. The correct posture is interested skepticism, and I’ll happily eat my words next week when somebody who doesn’t work at Alibaba runs the thing.&lt;/p&gt;

&lt;h2 id=&quot;the-smartest-model-in-the-world-had-an-awkward-debut&quot;&gt;The “Smartest Model in the World” Had an Awkward Debut&lt;/h2&gt;

&lt;p&gt;Claude Opus 5 shipped July 24, and by this week it finally had enough Arena votes to show up properly. Anthropic and Artificial Analysis both told you it’s the most intelligent model on Earth right now. On AA’s &lt;a href=&quot;https://artificialanalysis.ai/articles/opus-5&quot;&gt;Intelligence Index it scores 61&lt;/a&gt;, narrowly the top of the board, effectively tied with Fable 5 at 60 and ahead of GPT-5.6 Sol at 59 and Kimi K3 at 57.&lt;/p&gt;

&lt;p&gt;So where does it land on Arena Overall, now that humans have actually voted on it blind?&lt;/p&gt;

&lt;p&gt;Number 7. Behind Opus 4.6-thinking at #2 and Opus 4.7-thinking at #3. It got beaten by its own grandparents.&lt;/p&gt;

&lt;p&gt;I want to be fair here, because this is the interesting part, not a dunk. Opus 5 is #1 on the hard-benchmark axis and it takes the Arena Math crown outright (on thin preliminary votes, but still). The &lt;a href=&quot;https://artificialanalysis.ai/articles/opus-5&quot;&gt;cost-per-task number is the real headline&lt;/a&gt;: $2.03 per Intelligence Index task versus Fable 5’s $2.75, about 26% cheaper, at the same $5/$25 sticker as Opus 4.8. That’s a real bargain if you’re doing hard agentic work.&lt;/p&gt;

&lt;p&gt;But if you upgraded to Opus 5 on the strength of the word “smartest” alone, blind human raters are quietly telling you that you bought a lateral move on everyday chat. “Best on the benchmarks” and “the answer people prefer when they don’t know which model they’re looking at” are two different axes, and this week they pointed in two different directions at the same lab.&lt;/p&gt;

&lt;h2 id=&quot;the-boring-answer-that-keeps-winning&quot;&gt;The Boring Answer That Keeps Winning&lt;/h2&gt;

&lt;p&gt;Now the part I actually care about. If I strip away the launch confetti, what’s the model that gives me the most quality per dollar right now?&lt;/p&gt;

&lt;p&gt;Same answer as last cycle. MiMo v2.5 Pro. Xiaomi’s model from April, MIT-licensed, $0.43/$0.87 per million tokens on Arena’s list price and &lt;a href=&quot;https://openrouter.ai/xiaomi/mimo-v2.5-pro&quot;&gt;routing even cheaper on OpenRouter&lt;/a&gt; at roughly $0.35/$0.70. Listed, purchasable, no geo-lock, multiple providers. Boring. Available. Cheap as dirt.&lt;/p&gt;

&lt;p&gt;What makes this week different is that two completely unrelated methodologies pointed at the same model. Arena’s price sort puts MiMo as the cheapest thing inside the competitive band of four separate categories. And Artificial Analysis, which measures hard-benchmark capability instead of crowd preference, &lt;a href=&quot;https://artificialanalysis.ai/models/mimo-v2-5-pro&quot;&gt;puts MiMo on its Intelligence-vs-Cost Pareto frontier&lt;/a&gt;. Its “most attractive quadrant.” When the popularity metric and the capability metric independently name the same cheap model, that’s about as strong a buy signal as this newsletter ever gets.&lt;/p&gt;

&lt;p&gt;The honest caveat: MiMo scores 42 on AA’s Intelligence Index while the frontier sits at 57 to 61, and it’s slow at around 47 tokens per second. So it’s the crowd favorite and cost-efficient for what it is. But it’s not frontier-grade on hard reasoning, and it won’t win a latency race. For everyday work and agentic loops where you care about the bill, that’s a trade I’ll take every time. For a gnarly proof or a nasty debugging session, spend the money.&lt;/p&gt;

&lt;p&gt;That’s the whole hype-versus-value story this week in one line. Qwen3.8-Max is new, loud, and unproven. MiMo is old, quiet, and double-confirmed.&lt;/p&gt;

&lt;h2 id=&quot;cheapskate-picks-where-the-actual-money-is&quot;&gt;Cheapskate Picks: Where the Actual Money Is&lt;/h2&gt;

&lt;p&gt;This is the section I write the newsletter for. The method is simple and I’ll say it once so the table makes sense. For each Arena category, take the leader’s rating, draw a line 50 points below it, and that’s the competitive band. Everything inside that band is, statistically, a rounding error away from the “best” model. Then I sort the band by output price and pick the cheapest thing in it. The trick, and the thing I screwed up in a past issue, is that the band is defined by points, not by rank. It runs way deeper than the visible top 20. The Coding band this week is 53 models deep. The cheap open-weight models live down in the 20s, 30s, and 40s, sitting a couple of points below premium brands while costing an order of magnitude less. Truncate at rank 20 and you delete the entire reason this section exists.&lt;/p&gt;

&lt;p&gt;So I pulled the full tables and computed the bands in code. Here’s where the money is:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Category&lt;/th&gt;
      &lt;th&gt;Leader&lt;/th&gt;
      &lt;th&gt;$ leader&lt;/th&gt;
      &lt;th&gt;Cheapskate pick&lt;/th&gt;
      &lt;th&gt;$ pick&lt;/th&gt;
      &lt;th&gt;Δ rating&lt;/th&gt;
      &lt;th&gt;Price ratio&lt;/th&gt;
      &lt;th&gt;AA Pareto&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Overall&lt;/td&gt;
      &lt;td&gt;claude-fable-5&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;MiMo v2.5 Pro (#40)&lt;/td&gt;
      &lt;td&gt;$0.87&lt;/td&gt;
      &lt;td&gt;−43&lt;/td&gt;
      &lt;td&gt;~57×&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Coding&lt;/td&gt;
      &lt;td&gt;claude-fable-5&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;MiMo v2.5 Pro (#29)&lt;/td&gt;
      &lt;td&gt;$0.87&lt;/td&gt;
      &lt;td&gt;−35&lt;/td&gt;
      &lt;td&gt;~57×&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Creative Writing&lt;/td&gt;
      &lt;td&gt;claude-fable-5&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;Gemini 3 Flash (#23)&lt;/td&gt;
      &lt;td&gt;$3&lt;/td&gt;
      &lt;td&gt;−49&lt;/td&gt;
      &lt;td&gt;~16.7×&lt;/td&gt;
      &lt;td&gt;nearby&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Instruction Following&lt;/td&gt;
      &lt;td&gt;claude-fable-5&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;MiMo v2.5 Pro (#25)&lt;/td&gt;
      &lt;td&gt;$0.87&lt;/td&gt;
      &lt;td&gt;−46&lt;/td&gt;
      &lt;td&gt;~57×&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Hard Prompts&lt;/td&gt;
      &lt;td&gt;claude-fable-5&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;MiMo v2.5 Pro (#27)&lt;/td&gt;
      &lt;td&gt;$0.87&lt;/td&gt;
      &lt;td&gt;−40&lt;/td&gt;
      &lt;td&gt;~57×&lt;/td&gt;
      &lt;td&gt;✓&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Math&lt;/td&gt;
      &lt;td&gt;claude-opus-5-max*&lt;/td&gt;
      &lt;td&gt;$25&lt;/td&gt;
      &lt;td&gt;Gemini 3.6 Flash (#4)&lt;/td&gt;
      &lt;td&gt;$7.50&lt;/td&gt;
      &lt;td&gt;−32&lt;/td&gt;
      &lt;td&gt;~3.3×&lt;/td&gt;
      &lt;td&gt;nearby&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;* The Math leader is preliminary, sitting on only 231 votes. Treat that whole board as a rumor this week.&lt;/p&gt;

&lt;p&gt;A few things worth saying out loud about that table.&lt;/p&gt;

&lt;p&gt;MiMo sweeps four of six categories, all at $0.87 output, all roughly 57 times cheaper than the Fable 5 leader. Its ranks look scary (#40 in Overall) until you check the vote counts. That Overall rating is backed by 45,910 votes. It’s a far more settled number than most of the shiny preliminary top-10 entries with a few hundred votes each. Deep rank measures preference, not reliability. Don’t let it spook you.&lt;/p&gt;

&lt;p&gt;Creative Writing is the one place MiMo can’t reach, because that category rewards polish and the cheap crowd falls just below the cutoff. The pick there is Gemini 3 Flash at $3 output, and it’s clinging to the very edge of the band at 49 points back. Still 16 times cheaper than the leader.&lt;/p&gt;

&lt;p&gt;Math is a mess this week and I’m flagging it hard. The leader is Opus 5 on 231 votes, the band is only 8 models deep, and the cheapest thing in it is Gemini 3.6 Flash at $7.50. There’s no sub-$7 play here. Math is a “you’re paying for quality” category right now, so if you need it, budget for it and check back when the votes settle.&lt;/p&gt;

&lt;p&gt;And the throughline underneath all of it: Fable 5 still sweeps 5 of 6 Arena categories as the outright leader. The ceiling hasn’t moved in weeks. What keeps changing is the floor, and the floor keeps getting cheaper.&lt;/p&gt;

&lt;h2 id=&quot;horror-stories-from-the-wild&quot;&gt;Horror Stories From the Wild&lt;/h2&gt;

&lt;p&gt;Two this week. One is a real fire, the other is a smoke alarm.&lt;/p&gt;

&lt;p&gt;The fire: the DeepSeek V4 API migration deadline hit on July 24 at 15:59 UTC, and it hit hard. DeepSeek retired the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-chat&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-reasoner&lt;/code&gt; model aliases with no grace period and no fallback. Call the old names now and you get an error, full stop. &lt;a href=&quot;https://www.developersdigest.tech/blog/deepseek-chat-to-v4-migration-guide&quot;&gt;One developer went digging through production logs and found 14,000 calls still hitting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-chat&lt;/code&gt;&lt;/a&gt;, every single one returning a 404. The fix is a one-line model-name swap, which sounds trivial until you hit the two gotchas: thinking mode moved from the model name into a request parameter, so a naive swap either silently drops your reasoning entirely or quietly turns the cheapest endpoint into a reasoning-token furnace that torches your bill. If you run anything scheduled or agentic against DeepSeek, go read your logs right now. I’ll wait.&lt;/p&gt;

&lt;p&gt;The smoke alarm: I already said it above, but it belongs here too. Qwen3.8-Max launched with a benchmark table that scores its competitors for them and zero independent verification behind any of it. That’s not a crash. It’s a “don’t rewire your whole pipeline around a press release” warning. Wait for someone outside Alibaba to run it.&lt;/p&gt;

&lt;h2 id=&quot;coming-soon-or-soon-anyway&quot;&gt;Coming Soon (Or “Soon,” Anyway)&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Qwen3.8-Max open weights.&lt;/strong&gt; Announced for roughly the week of August 10, right behind the API launch. If they’re real, the &lt;a href=&quot;https://www.scmp.com/tech/article/3362738/alibabas-ai-model-qwen38-max-made-widely-accessible-ahead-open-weights-release&quot;&gt;independent evals that follow will be the actual story&lt;/a&gt;, not the launch table.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Gemini 3.5 Pro.&lt;/strong&gt; Still vapor. It missed its July 17 target, which is somewhere around the third or fourth slip now, and &lt;a href=&quot;https://techcrunch.com/2026/07/21/google-releases-three-new-gemini-models-but-no-3-5-pro/&quot;&gt;Google shipped three other Gemini models instead of it&lt;/a&gt; while reportedly scrapping and rebuilding the base model over hallucination and reliability problems. At this point I’ll believe it when I can call the API.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Kimi K3 community quants.&lt;/strong&gt; The weights &lt;a href=&quot;https://www.interconnects.ai/p/kimi-k3-the-open-weights-escalation&quot;&gt;went public July 26 under a modified MIT license&lt;/a&gt;, so quantized community builds are showing up. Just remember the model is 2.8 trillion parameters and needs something like 1.4TB of fast memory even at four-bit. “Open weights” and “you can run it” aren’t the same sentence when you’d need 4 to 8 H100s to load the thing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-i-actually-took-away-this-week&quot;&gt;What I Actually Took Away This Week&lt;/h2&gt;

&lt;p&gt;The frontier is stuck and the bargain bin is on fire. That’s the real state of things.&lt;/p&gt;

&lt;p&gt;Anthropic still owns the top of every leaderboard that matters, and it has for a month. Meanwhile Alibaba, Xiaomi, DeepSeek, and Moonshot are locked in a race to give away nearly-as-good models for pennies, and Chinese labs now make up something like 45% of all the tokens flowing through OpenRouter. The story isn’t “who’s the smartest.” It’s been settled for weeks. The story is that the price of “good enough for almost everything” fell off a cliff and keeps falling.&lt;/p&gt;

&lt;p&gt;So here’s my honest advice, which is the same advice as last week and probably next week. Ignore the launch you read about in the news. Open the leaderboards, find the cheapest model inside the band, check that two different metrics agree it’s actually good, and run that. This week that’s MiMo v2.5 Pro at 57 times less than the model everyone’s cheering for.&lt;/p&gt;

&lt;p&gt;And go read your DeepSeek logs. Seriously. Right now.&lt;/p&gt;

&lt;p&gt;Next Tuesday I’ll be back with the coffee and the two tabs, and I fully expect a different Chinese lab to have dropped a trillion-parameter something-or-other by then. That’s the price you pay for paying attention.&lt;/p&gt;
</description>
        <pubDate>Tue, 04 Aug 2026 08:00:00 -0500</pubDate>
        <link>https://www.stephanmiller.com/model-buzz-roundup-week-of-0729/</link>
        <guid isPermaLink="true">https://www.stephanmiller.com/model-buzz-roundup-week-of-0729/</guid>
        
        <category>llm</category>
        
        <category>openrouter</category>
        
        <category>model-roundup</category>
        
        
        <category>large-language-models</category>
        
      </item>
    
      <item>
        <title>Obsidian Git Sync in 2026: What Actually Works on Mobile</title>
        <description>&lt;p&gt;I use git every day. So when I started taking Obsidian seriously, the obvious move was to drop the vault into a repo and call it solved. Commit, push, pull, done.&lt;/p&gt;

&lt;p&gt;That works perfectly. On laptops. The second you add a phone, git stops being the easy answer and starts being the thing you fight with, which is why it is the one method I do not use for mobile in &lt;a href=&quot;https://www.stephanmiller.com/sync-obsidian-vault-across-devices/&quot;&gt;my guide to syncing Obsidian for free on every device&lt;/a&gt;. I run the Git plugin on desktop for version history and sync my iPad with something else entirely.&lt;/p&gt;

&lt;p&gt;Almost nobody searching for this is asking how to set up git. They already know git. They are asking one question: &lt;strong&gt;will this work on my phone?&lt;/strong&gt; So let’s answer that directly.&lt;/p&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#desktop-git-is-solved-so-lets-not-waste-your-time&quot; id=&quot;markdown-toc-desktop-git-is-solved-so-lets-not-waste-your-time&quot;&gt;Desktop Git Is Solved, So Let’s Not Waste Your Time&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#why-mobile-is-a-completely-different-animal&quot; id=&quot;markdown-toc-why-mobile-is-a-completely-different-animal&quot;&gt;Why Mobile Is a Completely Different Animal&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#what-actually-breaks-and-when&quot; id=&quot;markdown-toc-what-actually-breaks-and-when&quot;&gt;What Actually Breaks, and When&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#no-it-is-not-real-time-sync&quot; id=&quot;markdown-toc-no-it-is-not-real-time-sync&quot;&gt;No, It Is Not Real-Time Sync&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-stable-path-let-a-real-git-client-do-the-mobile-leg&quot; id=&quot;markdown-toc-the-stable-path-let-a-real-git-client-do-the-mobile-leg&quot;&gt;The Stable Path: Let a Real Git Client Do the Mobile Leg&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#gitsync-which-is-what-i-would-use-now&quot; id=&quot;markdown-toc-gitsync-which-is-what-i-would-use-now&quot;&gt;GitSync, which is what I would use now&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#working-copy-on-ios&quot; id=&quot;markdown-toc-working-copy-on-ios&quot;&gt;Working Copy on iOS&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#about-mgit-on-android&quot; id=&quot;markdown-toc-about-mgit-on-android&quot;&gt;About mgit on Android&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#git-vs-remotely-save-vs-livesync&quot; id=&quot;markdown-toc-git-vs-remotely-save-vs-livesync&quot;&gt;Git vs Remotely Save vs LiveSync&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#who-git-is-actually-right-for&quot; id=&quot;markdown-toc-who-git-is-actually-right-for&quot;&gt;Who Git Is Actually Right For&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#faq&quot; id=&quot;markdown-toc-faq&quot;&gt;FAQ&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-short-version&quot; id=&quot;markdown-toc-the-short-version&quot;&gt;The Short Version&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;desktop-git-is-solved-so-lets-not-waste-your-time&quot;&gt;Desktop Git Is Solved, So Let’s Not Waste Your Time&lt;/h2&gt;

&lt;p&gt;If you only use Obsidian on computers, there is no article here. Put the vault in a repo, add a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt;, commit, push. That is it. You do not need a plugin at all.&lt;/p&gt;

&lt;p&gt;If you want the commits to happen without you thinking about it, install the &lt;a href=&quot;https://github.com/Vinzent03/obsidian-git&quot;&gt;Obsidian Git plugin&lt;/a&gt; from the community plugins tab like &lt;a href=&quot;/how-to-install-obsidian-plugins/&quot;&gt;any other plugin&lt;/a&gt;, and it will do automatic commit-and-sync (commit, pull, and push) on a schedule, plus auto-pull when Obsidian starts. On desktop the plugin shells out to the actual git binary on your machine, so it behaves exactly the way git behaves. I walked through my own setup of this in the first post, including the part where it refused to give me any branch options and I had to go back to the command line like a caveman.&lt;/p&gt;

&lt;p&gt;The mobile story is not the same.&lt;/p&gt;

&lt;h2 id=&quot;why-mobile-is-a-completely-different-animal&quot;&gt;Why Mobile Is a Completely Different Animal&lt;/h2&gt;

&lt;p&gt;Neither iOS nor Android will let an app run the real git binary. So the plugin does the only thing it can do: it swaps in &lt;a href=&quot;https://isomorphic-git.org/&quot;&gt;isomorphic-git&lt;/a&gt;, a reimplementation of git written in JavaScript, and runs that inside Obsidian.&lt;/p&gt;

&lt;p&gt;That is a different program wearing git’s clothes, and the gaps are specific:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;No SSH authentication.&lt;/strong&gt; isomorphic-git does not support it. Your SSH keys and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git@github.com:&lt;/code&gt; remotes are useless here. You are on HTTPS with a personal access token, and you get to store that token on your phone.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No rebase merge strategy.&lt;/strong&gt; If your workflow assumes rebase, mobile does not have it.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No submodules.&lt;/strong&gt; Some people build vaults out of submodules. Not on a phone.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No git-lfs.&lt;/strong&gt; If your repo uses Large File Storage, mobile is out.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Repo size is capped by memory.&lt;/strong&gt; All of this happens inside the app’s RAM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last one is the one that actually kills people, and it deserves its own section.&lt;/p&gt;

&lt;h2 id=&quot;what-actually-breaks-and-when&quot;&gt;What Actually Breaks, and When&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/obsidian-git-sync-in-2026-what-actually-works-on-m-body-1.jpg&quot; alt=&quot;What Actually Breaks, and When&quot; srcset=&quot;            /assets/resized/480/obsidian-git-sync-in-2026-what-actually-works-on-m-body-1.jpg 480w,            /assets/resized/800/obsidian-git-sync-in-2026-what-actually-works-on-m-body-1.jpg 800w,            /assets/resized/1400/obsidian-git-sync-in-2026-what-actually-works-on-m-body-1.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The plugin’s documentation does not hedge. It says the git implementation on mobile is &lt;strong&gt;very unstable&lt;/strong&gt;, that it would not recommend using this plugin on mobile, and that you should try other syncing services instead.&lt;/p&gt;

&lt;p&gt;That is the developer of the plugin telling you not to use his plugin. I have never seen a clearer signal in an Obsidian community plugin.&lt;/p&gt;

&lt;p&gt;The docs get specific about the failure mode too. Depending on your device and how much free RAM it has, Obsidian may crash on clone or pull, throw buffer overflow errors, or just run forever without finishing.&lt;/p&gt;

&lt;p&gt;Notice what all three have in common. They are memory failures, not sync failures. So the variable that decides whether this works for you is not “is my vault big” in some absolute sense. It is &lt;strong&gt;your vault plus its entire history versus whatever RAM your phone has free right now.&lt;/strong&gt; Which means it can work fine for weeks and then fail because you had a bunch of tabs open.&lt;/p&gt;

&lt;p&gt;I am not going to give you a magic megabyte number, because there isn’t one. What I can tell you is the shape of it:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;strong&gt;initial clone is the worst moment&lt;/strong&gt;, by a wide margin. Biggest memory spike you will ever ask it to perform, and where most people give up before they reach daily use.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Attachments are the accelerant.&lt;/strong&gt; A pure-markdown vault is tiny. Start pasting screenshots and PDFs into it and the repo gets heavy fast, and unlike your notes, images do not compress or diff. Every version of that screenshot is in your history forever.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;History accumulates even if the vault doesn’t.&lt;/strong&gt; A three year old vault with automatic commits every ten minutes has a lot of objects in it, and the clone deals with all of them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also worth knowing: an older separate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obsidian-git-mobile&lt;/code&gt; repo exists and shows up in search results. Do not install it. It was archived back in September 2022 and its functionality was folded into the main plugin.&lt;/p&gt;

&lt;h2 id=&quot;no-it-is-not-real-time-sync&quot;&gt;No, It Is Not Real-Time Sync&lt;/h2&gt;

&lt;p&gt;“Obsidian git plugin real-time sync” is one of the most searched versions of this question, and I think people are hoping the answer has changed. It has not.&lt;/p&gt;

&lt;p&gt;Git is not a sync engine. It is a version control system you are using as a sync engine, and the difference shows up exactly here. The plugin’s automatic commit-and-sync runs &lt;strong&gt;on a timer measured in minutes&lt;/strong&gt;. There is no file watcher pushing your keystrokes to a server.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/obsidian-git-sync-in-2026-what-actually-works-on-m-body-2.jpg&quot; alt=&quot;No, It Is Not Real-Time Sync&quot; srcset=&quot;            /assets/resized/480/obsidian-git-sync-in-2026-what-actually-works-on-m-body-2.jpg 480w,            /assets/resized/800/obsidian-git-sync-in-2026-what-actually-works-on-m-body-2.jpg 800w,            /assets/resized/1400/obsidian-git-sync-in-2026-what-actually-works-on-m-body-2.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So the real behavior is: you type a note on your laptop, and some number of minutes later it gets committed and pushed. Then your phone pulls whenever it pulls. Best case, a gap of a few minutes. Worst case, you opened the app before it finished pulling and you are now editing a stale copy of a note, which is how you manufacture a merge conflict on a device with no good way to resolve one.&lt;/p&gt;

&lt;p&gt;If you want changes to appear on the other device almost immediately, git is the wrong tool and Self-hosted LiveSync is the one built for that.&lt;/p&gt;

&lt;h2 id=&quot;the-stable-path-let-a-real-git-client-do-the-mobile-leg&quot;&gt;The Stable Path: Let a Real Git Client Do the Mobile Leg&lt;/h2&gt;

&lt;p&gt;Here is the setup that actually holds up, and it is the same principle for both platforms. &lt;strong&gt;Do not make Obsidian do the git.&lt;/strong&gt; Install a dedicated git client on the phone, let it clone and push the repo into a real folder, and then point Obsidian at that folder as a vault. Obsidian just edits markdown files. The git app handles git. Neither one has to be clever.&lt;/p&gt;

&lt;h3 id=&quot;gitsync-which-is-what-i-would-use-now&quot;&gt;GitSync, which is what I would use now&lt;/h3&gt;

&lt;p&gt;The plugin’s own docs point at &lt;a href=&quot;https://github.com/ViscousPot/GitSync&quot;&gt;GitSync&lt;/a&gt; as the alternative, and having looked at it, that recommendation is correct and it is the biggest thing that has changed in this space.&lt;/p&gt;

&lt;p&gt;GitSync is a mobile git client built specifically for syncing a folder between a git remote and a local directory, which is precisely the job. It runs on Android 5+ and iOS 13+, it is open source under GPL-3.0, and it is on Google Play, the App Store, F-Droid, and IzzyOnDroid. It won a 2024 Gem of the Year award in the Obsidian tools category, so the vault use case is not an accident, it is the point.&lt;/p&gt;

&lt;p&gt;The part that matters most: it does &lt;strong&gt;not&lt;/strong&gt; use isomorphic-git. It uses a native Rust core built on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git2-rs&lt;/code&gt;. So it supports SSH, along with HTTPS and OAuth (GitHub, GitLab, and Gitea), and it does not inherit the memory ceiling that makes the plugin fall over. It also does background sync, which the plugin cannot do because the plugin only runs while Obsidian is open.&lt;/p&gt;

&lt;p&gt;It is free to download. Premium is a &lt;strong&gt;$24.99 one-time unlock&lt;/strong&gt; that adds additional repositories, Git LFS, git-crypt, and priority issue tagging, and you can also get it by becoming a GitHub Sponsor. There is a separate GitSync AI subscription at $6.99, which has nothing to do with syncing and which you can ignore. Note that Git LFS thing: it is a capability the Obsidian plugin does not have on mobile at any price.&lt;/p&gt;

&lt;h3 id=&quot;working-copy-on-ios&quot;&gt;Working Copy on iOS&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/working-copy-git-client/id896694807&quot;&gt;Working Copy&lt;/a&gt; is the old reliable iOS git client and it is genuinely excellent. The catch that nobody mentions in sync articles: &lt;strong&gt;the free version cannot push.&lt;/strong&gt; The App Store description says it straight, that you need to unlock pro features “such as the ability to push commits and manage more than 5 repositories.” Pro Unlock is $35.99. There is a 10 day trial, and it is free for students through the GitHub Student Developer Pack.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/obsidian-git-sync-in-2026-what-actually-works-on-m-body-3.jpg&quot; alt=&quot;Working Copy on iOS&quot; srcset=&quot;            /assets/resized/480/obsidian-git-sync-in-2026-what-actually-works-on-m-body-3.jpg 480w,            /assets/resized/800/obsidian-git-sync-in-2026-what-actually-works-on-m-body-3.jpg 800w,            /assets/resized/1400/obsidian-git-sync-in-2026-what-actually-works-on-m-body-3.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;One wrinkle on “one-time”: you get permanent access to every pro feature that exists at purchase plus anything added over the next year. Features added after that need a Pro Upgrade ($17.99 for the recent ones). You never lose what you bought, but “buy once, get everything forever” is not quite the deal.&lt;/p&gt;

&lt;p&gt;For a sync workflow, “cannot push” means “cannot sync,” so budget for it. What you get is a mature app other iOS apps can read from, which is what makes the handoff to Obsidian clean.&lt;/p&gt;

&lt;h3 id=&quot;about-mgit-on-android&quot;&gt;About mgit on Android&lt;/h3&gt;

&lt;p&gt;I have recommended &lt;a href=&quot;https://manichord.com/projects/mgit.html&quot;&gt;mgit&lt;/a&gt; before and I am walking that back. The advice used to be to skip the Google Play build (users report it broken) and grab it from &lt;a href=&quot;https://f-droid.org/packages/com.manichord.mgit/&quot;&gt;F-Droid&lt;/a&gt; instead. That is still true, but the F-Droid listing’s latest release is version 1.7.0, from &lt;strong&gt;January 4, 2023.&lt;/strong&gt; That is over three years of nothing. It may well still work for you, but I am not going to tell somebody to trust their notes to an abandoned app when GitSync exists, is maintained, and is better.&lt;/p&gt;

&lt;h2 id=&quot;git-vs-remotely-save-vs-livesync&quot;&gt;Git vs Remotely Save vs LiveSync&lt;/h2&gt;

&lt;p&gt;People search for this comparison literally, so here it is without hedging.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;Git&lt;/th&gt;
      &lt;th&gt;Remotely Save&lt;/th&gt;
      &lt;th&gt;Self-hosted LiveSync&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;What it really is&lt;/td&gt;
      &lt;td&gt;Version control used as sync&lt;/td&gt;
      &lt;td&gt;File sync to cloud storage&lt;/td&gt;
      &lt;td&gt;Live replication over CouchDB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Mobile story&lt;/td&gt;
      &lt;td&gt;Bad via plugin, fine via GitSync&lt;/td&gt;
      &lt;td&gt;Good, it is the whole point&lt;/td&gt;
      &lt;td&gt;Good, but you run a server&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Speed&lt;/td&gt;
      &lt;td&gt;Minutes, on a timer&lt;/td&gt;
      &lt;td&gt;Minutes, on a timer&lt;/td&gt;
      &lt;td&gt;Near instant&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Version history&lt;/td&gt;
      &lt;td&gt;Excellent, it is the entire feature&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Setup burden&lt;/td&gt;
      &lt;td&gt;Low if you know git&lt;/td&gt;
      &lt;td&gt;Lowest&lt;/td&gt;
      &lt;td&gt;Highest by a mile&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Conflict handling&lt;/td&gt;
      &lt;td&gt;Real merges, and real merge conflicts&lt;/td&gt;
      &lt;td&gt;Duplicate files&lt;/td&gt;
      &lt;td&gt;Handled at the database level&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Pick Remotely Save&lt;/strong&gt; if you want your notes on your phone with the least friction. This is what I actually run. &lt;strong&gt;Pick LiveSync&lt;/strong&gt; if you want changes to land before you can switch apps, and you are the kind of person who is fine maintaining a CouchDB instance. &lt;strong&gt;Pick git&lt;/strong&gt; if you want history.&lt;/p&gt;

&lt;h2 id=&quot;who-git-is-actually-right-for&quot;&gt;Who Git Is Actually Right For&lt;/h2&gt;

&lt;p&gt;Git is right for you if you already live in git and what you want out of sync is a &lt;strong&gt;time machine&lt;/strong&gt;, not a file transfer. Being able to see that you deleted three paragraphs on March 12th and get them back is a genuinely different capability from having your notes on two devices, and no cloud sync method matches it. Add the &lt;a href=&quot;https://github.com/kometenstaub/obsidian-version-history-diff&quot;&gt;Version History Diff plugin&lt;/a&gt; and you can read those diffs inside Obsidian.&lt;/p&gt;

&lt;p&gt;Git is wrong for you if what you want is your notes on your phone. That is a sync problem, and you should solve it with a sync tool.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/obsidian-git-sync-in-2026-what-actually-works-on-m-body-4.jpg&quot; alt=&quot;Who Git Is Actually Right For&quot; srcset=&quot;            /assets/resized/480/obsidian-git-sync-in-2026-what-actually-works-on-m-body-4.jpg 480w,            /assets/resized/800/obsidian-git-sync-in-2026-what-actually-works-on-m-body-4.jpg 800w,            /assets/resized/1400/obsidian-git-sync-in-2026-what-actually-works-on-m-body-4.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Which leads to the setup I think most git people should actually run, and it is a hybrid: &lt;strong&gt;Git plugin on desktop only, for history and backup. Something else for the mobile leg.&lt;/strong&gt; My iPad talks to Dropbox through &lt;a href=&quot;https://www.stephanmiller.com/sync-obsidian-iphone-ipad-free/&quot;&gt;Remotely Save, which is the route I walk through in the iPhone and iPad guide&lt;/a&gt;, my laptops keep a git history, and the two never touch each other.&lt;/p&gt;

&lt;p&gt;That last part is a hard rule, and it is the same one that &lt;a href=&quot;https://www.stephanmiller.com/obsidian-icloud-sync-windows/&quot;&gt;wrecks iCloud vaults on Windows&lt;/a&gt;: never point two sync systems at the same vault folder at once. Git and a cloud sync client fighting over the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; directory is a genuinely creative way to destroy a repo.&lt;/p&gt;

&lt;h2 id=&quot;faq&quot;&gt;FAQ&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does the Obsidian Git plugin work on mobile?&lt;/strong&gt;
Technically yes, on both iOS and Android, using isomorphic-git instead of real git. Practically, the plugin’s own documentation says the mobile implementation is very unstable and recommends using a different syncing service instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is the Obsidian Git plugin stable on iOS and Android?&lt;/strong&gt;
No. The documented failure modes are Obsidian crashing during clone or pull, buffer overflow errors, or the operation running indefinitely, all depending on your device’s available RAM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the Obsidian Git plugin do real-time sync?&lt;/strong&gt;
No. Automatic commit-and-sync runs on a schedule measured in minutes. If you need near instant propagation, Self-hosted LiveSync is the method built for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use SSH with the Obsidian Git plugin on mobile?&lt;/strong&gt;
No. isomorphic-git does not support SSH authentication, so mobile requires HTTPS with a personal access token. GitSync does support SSH, because it uses a native git implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the best Android support option for Obsidian and git?&lt;/strong&gt;
GitSync. It is maintained, it is on Play, F-Droid, and IzzyOnDroid, and it uses native git rather than a JavaScript reimplementation. mgit’s last F-Droid release was January 2023.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use the Git plugin with Nextcloud for multi-user sync?&lt;/strong&gt;
You can host the remote anywhere, Nextcloud included. But git is not a live collaboration layer. Two people editing the same note between pushes produces a merge conflict, not a merged note. For shared vaults, look at LiveSync or Obsidian Sync’s shared vaults.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I uninstalled the Git plugin. Where did my vault go?&lt;/strong&gt;
Nowhere. The plugin does not own your vault, and removing it leaves your files and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; folder untouched. The confusion is almost always a mobile vault location problem: if you cloned through the plugin on iOS, the vault lives inside Obsidian’s own app storage, which is not somewhere you can casually browse to. Clone with a real git client into a folder you picked, and you always know where your notes are.&lt;/p&gt;

&lt;h2 id=&quot;the-short-version&quot;&gt;The Short Version&lt;/h2&gt;

&lt;p&gt;Git on Obsidian desktop is great and you should probably be doing it for the history alone. Git on Obsidian mobile through the plugin is a thing the plugin’s own author asked you not to do, and nobody seems to want to say that plainly.&lt;/p&gt;

&lt;p&gt;If you want git on your phone anyway, and that is a reasonable thing to want, use GitSync and let a native git implementation do the work. If you just want your notes to show up on your phone, stop trying to make git do it and go use an &lt;a href=&quot;https://www.stephanmiller.com/sync-obsidian-vault-across-devices/&quot;&gt;actual sync method&lt;/a&gt;. I use git for the time machine and Dropbox for the phone, and I have not lost a note yet.&lt;/p&gt;
</description>
        <pubDate>Mon, 03 Aug 2026 08:00:00 -0500</pubDate>
        <link>https://www.stephanmiller.com/obsidian-git-sync-mobile/</link>
        <guid isPermaLink="true">https://www.stephanmiller.com/obsidian-git-sync-mobile/</guid>
        
        <category>obsidian</category>
        
        <category>git</category>
        
        <category>sync</category>
        
        <category>ios</category>
        
        <category>android</category>
        
        
        <category>obsidian</category>
        
      </item>
    
      <item>
        <title>How to Sync Obsidian on iPhone and iPad for Free in 2026</title>
        <description>&lt;p&gt;My iPad is the device that made me actually think about Obsidian sync instead of just having opinions about it. Laptops are easy. Two MacBook Pros and a Windows desktop will happily share a folder in any cloud service you point them at. Then you add an iPad and the thing that worked everywhere else does not work at all, because iOS doesn’t let apps do the stuff sync tools need to do.&lt;/p&gt;

&lt;p&gt;I run Dropbox with Remotely Save for my iPad, and I pay nothing for it, which is the whole point of &lt;a href=&quot;https://www.stephanmiller.com/sync-obsidian-vault-across-devices/&quot;&gt;my guide to syncing Obsidian for free on every device&lt;/a&gt;. This post is the iOS-only version of that. Four options that work, what each one costs, and why the answer depends on what your desktop computer is rather than anything about your phone.&lt;/p&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#why-ios-is-the-hard-case&quot; id=&quot;markdown-toc-why-ios-is-the-hard-case&quot;&gt;Why iOS Is the Hard Case&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-four-routes-that-actually-work&quot; id=&quot;markdown-toc-the-four-routes-that-actually-work&quot;&gt;The Four Routes That Actually Work&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#route-1-icloud-if-your-desktop-is-a-mac&quot; id=&quot;markdown-toc-route-1-icloud-if-your-desktop-is-a-mac&quot;&gt;Route 1: iCloud, If Your Desktop Is a Mac&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#route-2-remotely-save-the-one-i-actually-run&quot; id=&quot;markdown-toc-route-2-remotely-save-the-one-i-actually-run&quot;&gt;Route 2: Remotely Save, the One I Actually Run&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#route-3-syncthing-on-ios-the-route-everyone-asks-about&quot; id=&quot;markdown-toc-route-3-syncthing-on-ios-the-route-everyone-asks-about&quot;&gt;Route 3: Syncthing on iOS, the Route Everyone Asks About&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#möbius-sync&quot; id=&quot;markdown-toc-möbius-sync&quot;&gt;Möbius Sync&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#synctrain&quot; id=&quot;markdown-toc-synctrain&quot;&gt;SyncTrain&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#the-reality-of-both&quot; id=&quot;markdown-toc-the-reality-of-both&quot;&gt;The Reality of Both&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#route-4-obsidian-sync-when-you-are-done-fighting&quot; id=&quot;markdown-toc-route-4-obsidian-sync-when-you-are-done-fighting&quot;&gt;Route 4: Obsidian Sync, When You Are Done Fighting&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#onedrive-on-ios-is-its-own-problem&quot; id=&quot;markdown-toc-onedrive-on-ios-is-its-own-problem&quot;&gt;OneDrive on iOS Is Its Own Problem&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-files-app-trap&quot; id=&quot;markdown-toc-the-files-app-trap&quot;&gt;The Files App Trap&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#frequently-asked-questions&quot; id=&quot;markdown-toc-frequently-asked-questions&quot;&gt;Frequently Asked Questions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-verdict&quot; id=&quot;markdown-toc-the-verdict&quot;&gt;The Verdict&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;why-ios-is-the-hard-case&quot;&gt;Why iOS Is the Hard Case&lt;/h2&gt;

&lt;p&gt;Every other platform gives you a folder. iOS gives you a sandbox.&lt;/p&gt;

&lt;p&gt;On a Mac or a Windows box, a sync tool runs as a background service, watches a directory, and pushes changes when they happen. None of that is available to an iOS app. There are no background daemons. An app that is not on screen is mostly not running, and iOS decides when to wake it, not you. Apps also cannot freely read each other’s files, so “just point Obsidian at the Dropbox folder” is not a thing that exists here the way it does on desktop.&lt;/p&gt;

&lt;p&gt;That is also why there is no native Syncthing for iOS. Syncthing is a daemon. iOS does not do daemons. Everything you will find on the App Store is a third-party app that embeds the Syncthing engine and works within Apple’s rules, which is a different and more limited thing.&lt;/p&gt;

&lt;p&gt;So the question is not “which sync tool is best.”, but “which compromise do I want.”&lt;/p&gt;

&lt;h2 id=&quot;the-four-routes-that-actually-work&quot;&gt;The Four Routes That Actually Work&lt;/h2&gt;

&lt;p&gt;Pick by what your desktop is.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Your desktop&lt;/th&gt;
      &lt;th&gt;Best free route&lt;/th&gt;
      &lt;th&gt;Why&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Mac only&lt;/td&gt;
      &lt;td&gt;iCloud&lt;/td&gt;
      &lt;td&gt;Built into Obsidian’s iOS vault creation, near zero setup&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Windows&lt;/td&gt;
      &lt;td&gt;Remotely Save with Dropbox or S3&lt;/td&gt;
      &lt;td&gt;Works identically on both ends, no Apple dependency&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Linux&lt;/td&gt;
      &lt;td&gt;Remotely Save, or Syncthing via SyncTrain&lt;/td&gt;
      &lt;td&gt;Linux has no iCloud and no official OneDrive client&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Mixed, or you want no cloud at all&lt;/td&gt;
      &lt;td&gt;Syncthing via SyncTrain or Möbius Sync&lt;/td&gt;
      &lt;td&gt;Peer to peer, nothing stored on anyone’s server&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;You want it to just work&lt;/td&gt;
      &lt;td&gt;Obsidian Sync, $4/mo annual&lt;/td&gt;
      &lt;td&gt;Not free, but it is the one that never needs troubleshooting&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Now the details.&lt;/p&gt;

&lt;h2 id=&quot;route-1-icloud-if-your-desktop-is-a-mac&quot;&gt;Route 1: iCloud, If Your Desktop Is a Mac&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/how-to-sync-obsidian-on-iphone-and-ipad-for-free-i-body-1.jpg&quot; alt=&quot;Route 1: iCloud, If Your Desktop Is a Mac&quot; srcset=&quot;            /assets/resized/480/how-to-sync-obsidian-on-iphone-and-ipad-for-free-i-body-1.jpg 480w,            /assets/resized/800/how-to-sync-obsidian-on-iphone-and-ipad-for-free-i-body-1.jpg 800w,            /assets/resized/1400/how-to-sync-obsidian-on-iphone-and-ipad-for-free-i-body-1.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you are all Apple, stop here. Create the vault on your iPhone or iPad, toggle on &lt;strong&gt;Store in iCloud&lt;/strong&gt; during creation, and you are done. It is the only route with first-class support inside Obsidian’s own iOS app.&lt;/p&gt;

&lt;p&gt;I am not going to repeat the setup steps, because I wrote the long version already. See &lt;a href=&quot;https://www.stephanmiller.com/obsidian-icloud-sync-windows/&quot;&gt;the full iCloud walkthrough&lt;/a&gt; for creating versus migrating a vault, the “Optimize Mac Storage” setting that removes your notes, and the part where it falls apart if Windows is involved.&lt;/p&gt;

&lt;p&gt;The short version: works perfectly on Apple hardware, unreliably the moment it is not.&lt;/p&gt;

&lt;h2 id=&quot;route-2-remotely-save-the-one-i-actually-run&quot;&gt;Route 2: Remotely Save, the One I Actually Run&lt;/h2&gt;

&lt;p&gt;This is my setup. &lt;a href=&quot;https://github.com/remotely-save/remotely-save&quot;&gt;Remotely Save&lt;/a&gt; is a community plugin that syncs your vault to a storage backend you already have. The free tier covers S3 and anything S3-compatible like Cloudflare R2 or Backblaze B2, plus Dropbox, WebDAV including Nextcloud and Synology, and OneDrive personal with a caveat I get to below.&lt;/p&gt;

&lt;p&gt;The reason it wins on iOS is that it sidesteps the sandbox problem. Remotely Save runs &lt;em&gt;inside&lt;/em&gt; Obsidian. It does not need to watch a folder or run in the background, because it syncs when Obsidian is open and you tell it to, or on the schedule you set. iOS does not have to cooperate for it to work.&lt;/p&gt;

&lt;p&gt;The setup is the same on every platform, which is the other reason I use it. Install the plugin from Community Plugins, pick your service, authenticate, set a sync interval, and run a manual sync once to seed the vault. Do the desktop side first and let it finish before you touch the iPad, same as any sync method.&lt;/p&gt;

&lt;p&gt;The tradeoff is honest: sync happens when Obsidian is open. Open the app, wait a couple of seconds, then start typing. That is the deal, and after a couple of years of it I have stopped noticing.&lt;/p&gt;

&lt;h2 id=&quot;route-3-syncthing-on-ios-the-route-everyone-asks-about&quot;&gt;Route 3: Syncthing on iOS, the Route Everyone Asks About&lt;/h2&gt;

&lt;p&gt;This is the biggest cluster of searches on this topic and the one the forum threads are full of, so here is the current state of it in 2026.&lt;/p&gt;

&lt;p&gt;You cannot run &lt;a href=&quot;https://syncthing.net/&quot;&gt;Syncthing&lt;/a&gt; on iOS directly. You run one of two apps that wrap it.&lt;/p&gt;

&lt;h3 id=&quot;möbius-sync&quot;&gt;Möbius Sync&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://mobiussync.com/&quot;&gt;Free to download&lt;/a&gt;. The catch is the one people keep asking about in forum threads: usage within the Möbius Sync sandbox is free up to 20MB. Past that you need the in-app purchase, &lt;strong&gt;Unlimited file sync, $4.99&lt;/strong&gt;, which is a one-time purchase and not a subscription.&lt;/p&gt;

&lt;p&gt;For an Obsidian vault, 20MB is the deciding number. A text-only vault of a few thousand notes fits under it well. A vault with images, PDFs, or scanned documents blows through it immediately. But five dollars once is a fair price for a sync solution.&lt;/p&gt;

&lt;h3 id=&quot;synctrain&quot;&gt;SyncTrain&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/how-to-sync-obsidian-on-iphone-and-ipad-for-free-i-body-2.jpg&quot; alt=&quot;SyncTrain&quot; srcset=&quot;            /assets/resized/480/how-to-sync-obsidian-on-iphone-and-ipad-for-free-i-body-2.jpg 480w,            /assets/resized/800/how-to-sync-obsidian-on-iphone-and-ipad-for-free-i-body-2.jpg 800w,            /assets/resized/1400/how-to-sync-obsidian-on-iphone-and-ipad-for-free-i-body-2.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/synctrain/id6553985316&quot;&gt;The other option&lt;/a&gt;, and worth knowing about because it is truly free. No in-app purchases, open source, iOS 17 or later, actively maintained. It has deeper Shortcuts integration, which is the closest thing iOS offers to background syncing, since you can trigger a sync from an automation rather than remembering to open the app.&lt;/p&gt;

&lt;p&gt;I appreciate that its own App Store description tells you this: “Do not use Synctrain for back-up purposes, and always keep a back-up of your data.” An app that volunteers its own limitations is an app I trust more than one that does not.&lt;/p&gt;

&lt;h3 id=&quot;the-reality-of-both&quot;&gt;The Reality of Both&lt;/h3&gt;

&lt;p&gt;Syncthing on iOS is peer to peer, which means your notes never sit on anyone else’s server. That is the real reason to pick it.&lt;/p&gt;

&lt;p&gt;But it also means both devices have to be awake and reachable at the same time for anything to happen. Your Mac asleep in a bag syncs nothing. This is why people describe iOS Syncthing as flaky when it is actually working exactly as designed. There is no server holding your changes until the other device shows up. If you want that, you want one of the other three routes.&lt;/p&gt;

&lt;h2 id=&quot;route-4-obsidian-sync-when-you-are-done-fighting&quot;&gt;Route 4: Obsidian Sync, When You Are Done Fighting&lt;/h2&gt;

&lt;p&gt;Not free, so it does not really belong in a free guide, except that it belongs in every honest one. &lt;a href=&quot;https://obsidian.md/sync&quot;&gt;Sync Standard&lt;/a&gt; is $5 a month billed monthly or $4 billed annually, it is end-to-end encrypted by default, and it is the only option on this page where iOS is a first-class platform rather than a workaround.&lt;/p&gt;

&lt;p&gt;If you have read this far and the phrase “sandbox limitations” has stopped being interesting, that is the answer. Four dollars a month is roughly one coffee.&lt;/p&gt;

&lt;h2 id=&quot;onedrive-on-ios-is-its-own-problem&quot;&gt;OneDrive on iOS Is Its Own Problem&lt;/h2&gt;

&lt;p&gt;OneDrive keeps showing up in the search data for this topic, so it deserves a direct answer: it is the most awkward of the cloud options on iOS.&lt;/p&gt;

&lt;p&gt;Remotely Save does support OneDrive on the free tier, but with a restriction worth understanding before you start. The free version can only connect to the App Folder, meaning &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Apps/remotely-save&lt;/code&gt; inside your OneDrive. The PRO version is what connects to the root folder.&lt;/p&gt;

&lt;p&gt;That means you can’t point free Remotely Save at a vault that already lives somewhere else in your OneDrive. The vault has to live in the app’s own folder. If you were planning to sync a vault that sits alongside your work documents, that is the plan that breaks, and it breaks after you have already set everything up.&lt;/p&gt;

&lt;p&gt;If you are on OneDrive because your job is on Microsoft 365, this is workable as long as you keep the vault in the app folder. If you are on OneDrive out of habit, Dropbox or an S3 bucket will give you a smoother ride for free.&lt;/p&gt;

&lt;h2 id=&quot;the-files-app-trap&quot;&gt;The Files App Trap&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/how-to-sync-obsidian-on-iphone-and-ipad-for-free-i-body-3.jpg&quot; alt=&quot;The Files App Trap&quot; srcset=&quot;            /assets/resized/480/how-to-sync-obsidian-on-iphone-and-ipad-for-free-i-body-3.jpg 480w,            /assets/resized/800/how-to-sync-obsidian-on-iphone-and-ipad-for-free-i-body-3.jpg 800w,            /assets/resized/1400/how-to-sync-obsidian-on-iphone-and-ipad-for-free-i-body-3.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here is the mistake that generates the most confused forum posts.&lt;/p&gt;

&lt;p&gt;Your Obsidian vault on iOS is not just a folder in the Files app that you can put anywhere. Obsidian stores its iOS vaults in its own app container, which surfaces in Files as &lt;strong&gt;iCloud Drive &amp;gt; Obsidian&lt;/strong&gt;. That location is not decoration. Obsidian’s docs are explicit that vaults should live inside the Obsidian folder in iCloud Drive.&lt;/p&gt;

&lt;p&gt;Drop a vault in some other Files location and you get the confusing outcome: it looks fine in Files, it may even sync between your Macs, and the iOS app will not list it. People then conclude sync is broken when the vault was never somewhere Obsidian could see.&lt;/p&gt;

&lt;p&gt;The other half of this trap is that “it’s in Files” does not mean “it’s on the device.” A file showing a cloud icon is a placeholder. Obsidian searching a vault full of placeholders returns incomplete results and nothing tells you why.&lt;/p&gt;

&lt;h2 id=&quot;frequently-asked-questions&quot;&gt;Frequently Asked Questions&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can I sync Obsidian on iPhone for free?&lt;/strong&gt;
Yes. iCloud if your desktop is a Mac, Remotely Save with Dropbox or S3 for everything else, or SyncTrain if you want peer to peer with no cloud involved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Syncthing work on iOS?&lt;/strong&gt;
Not directly, because iOS does not allow background daemons. You use a wrapper app, either Möbius Sync or SyncTrain, and both devices must be awake at the same time to sync.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is Möbius Sync free?&lt;/strong&gt;
Free to download and free within its sandbox up to 20MB. Beyond that the Unlimited file sync in-app purchase is $4.99, one time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I sync Obsidian between my PC and iPhone?&lt;/strong&gt;
Remotely Save with Dropbox or an S3 bucket. iCloud is the wrong tool when a Windows machine is involved, for reasons covered in the iCloud walkthrough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What about syncing with Git on iOS?&lt;/strong&gt;
It works, but not through the Obsidian Git plugin, whose own documentation recommends against mobile use. You need a real git client doing the mobile leg. I covered the whole situation in &lt;a href=&quot;https://www.stephanmiller.com/obsidian-git-sync-mobile/&quot;&gt;Obsidian git sync and what actually works on mobile&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why are my notes out of date when I open Obsidian on my phone?&lt;/strong&gt;
Because no iOS sync method runs continuously in the background. Open the app and give it a few seconds before you start editing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where does Obsidian store vaults on iPhone and iPad?&lt;/strong&gt;
In its own container, visible in the Files app as iCloud Drive &amp;gt; Obsidian. Vaults kept elsewhere may not appear in the app’s vault list.&lt;/p&gt;

&lt;h2 id=&quot;the-verdict&quot;&gt;The Verdict&lt;/h2&gt;

&lt;p&gt;The iOS question answers itself once you stop asking it about iOS. Mac desktop, use iCloud. Windows or Linux desktop, use Remotely Save. Want nothing on anyone’s server, use SyncTrain and accept that both devices have to be on. Want to stop thinking about it, pay the four dollars.&lt;/p&gt;

&lt;p&gt;What none of them do is sync silently in the background the way you are used to on a laptop, and no blog post is going to fix that, because it is Apple’s design and not a gap in the tooling. Once you build the two-second pause into opening the app, iOS sync stops being a problem and goes back to being a folder.&lt;/p&gt;

&lt;p&gt;Mine has been a folder for four years now. I only think about it when I write about it.&lt;/p&gt;
</description>
        <pubDate>Thu, 30 Jul 2026 08:00:00 -0500</pubDate>
        <link>https://www.stephanmiller.com/sync-obsidian-iphone-ipad-free/</link>
        <guid isPermaLink="true">https://www.stephanmiller.com/sync-obsidian-iphone-ipad-free/</guid>
        
        <category>obsidian</category>
        
        <category>ios</category>
        
        <category>iphone</category>
        
        <category>ipad</category>
        
        <category>sync</category>
        
        
        <category>obsidian</category>
        
      </item>
    
      <item>
        <title>Apple Books Hides Your PDF Highlights. My Obsidian Plugin Now Digs Them Out.</title>
        <description>&lt;p&gt;Of all &lt;a href=&quot;https://www.stephanmiller.com/the-obsidian-plugin-collection-i-built-one-free-kiro-credit-at-a-time/&quot;&gt;the little plugins I’ve vibe coded into existence&lt;/a&gt;, the &lt;a href=&quot;https://github.com/eristoddle/apple-books-annotation-import&quot;&gt;Apple Books Annotation Import&lt;/a&gt; plugin is the one I actually use. Not “use” in the way you use a project once, screenshot it for a blog post, and never open again. I mean I run it every week. It’s my favorite thing I’ve built, and it’s been humming along for &lt;a href=&quot;https://www.stephanmiller.com/using-jules-to-update-my-obsidian-plugin/&quot;&gt;over a year without me touching it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then a few weeks ago I went looking for a highlight I knew I’d made in a PDF. It wasn’t there. None of my PDF highlights were there. A year of trusting this thing, and it turns out it had quietly been ignoring an entire category of my books the whole time.&lt;/p&gt;

&lt;p&gt;So I went digging. And it turns out Apple Books handles PDFs in a completely different way. This is the story of getting those highlights out, and the 1.1.0 release that finally does it.&lt;/p&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#a-quick-refresher-on-what-this-thing-does&quot; id=&quot;markdown-toc-a-quick-refresher-on-what-this-thing-does&quot;&gt;A Quick Refresher On What This Thing Does&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#where-apple-actually-hides-pdf-highlights&quot; id=&quot;markdown-toc-where-apple-actually-hides-pdf-highlights&quot;&gt;Where Apple Actually Hides PDF Highlights&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#reading-highlights-out-of-a-raw-pdf&quot; id=&quot;markdown-toc-reading-highlights-out-of-a-raw-pdf&quot;&gt;Reading Highlights Out Of A Raw PDF&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#hooking-it-into-the-machine-that-already-worked&quot; id=&quot;markdown-toc-hooking-it-into-the-machine-that-already-worked&quot;&gt;Hooking It Into The Machine That Already Worked&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-tradeoff-its-slower-but-its-everything-now&quot; id=&quot;markdown-toc-the-tradeoff-its-slower-but-its-everything-now&quot;&gt;The Tradeoff: It’s Slower, But It’s Everything Now&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-to-install-it-its-not-in-community-plugins-yet&quot; id=&quot;markdown-toc-how-to-install-it-its-not-in-community-plugins-yet&quot;&gt;How To Install It (It’s Not In Community Plugins Yet)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-takeaway&quot; id=&quot;markdown-toc-the-takeaway&quot;&gt;The Takeaway&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;a-quick-refresher-on-what-this-thing-does&quot;&gt;A Quick Refresher On What This Thing Does&lt;/h2&gt;

&lt;p&gt;If you’ve &lt;a href=&quot;https://www.stephanmiller.com/creating-an-obsidian-plugin-with-claude/&quot;&gt;never seen the plugin before&lt;/a&gt;, here’s the pitch. It’s macOS desktop only, and I’m fine with that, because being desktop only is the entire reason it can do what it does. I read in an iPad and I pay for the cheapest rung of iCloud specificallly because of this plugin to get the books where the plugin runs.&lt;/p&gt;

&lt;p&gt;When you highlight something in Apple Books, that highlight has to live somewhere on disk. On a Mac it does. On an iPhone it’s locked in a sandbox you can’t reach. So the plugin sits on the desktop where all the good data is and pulls from every source it can find:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;The Books SQLite databases.&lt;/strong&gt; This is where your EPUB highlights and notes actually live, buried in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Library/Containers/com.apple.iBooksX&lt;/code&gt;. The plugin &lt;a href=&quot;https://www.stephanmiller.com/import-osx-book-notes-into-obsidian/&quot;&gt;reads them straight out of SQLite&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The EPUB files themselves.&lt;/strong&gt; The database doesn’t have everything. So the plugin also cracks open the EPUB to grab the real metadata: ISBN, publisher, language, subjects, and the cover image.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;And now, as of 1.1.0, the PDFs themselves.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Out of all that it builds a clean markdown note per book: your highlights as blockquotes, color-coded to match the highlighter you used, optional notes, dates, citations, cover image, and an author page with a Dataview query that lists every book by that author. It has a smart overwrite mode that hashes the note so re-importing only rewrites files that actually changed. Pick “Import all books” or cherry-pick from a list.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2025/obsidian-annotation-import-settings.png&quot; alt=&quot;Apple Books Annotation Import settings&quot; srcset=&quot;            /assets/resized/480/obsidian-annotation-import-settings.png 480w,            /assets/resized/800/obsidian-annotation-import-settings.png 800w,            /assets/resized/1400/obsidian-annotation-import-settings.png 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The whole point is completeness. I’m not scraping one source, I’m triangulating across three. Which is why the missing PDF highlights bugged me so much. There was a hole in the completeness.&lt;/p&gt;

&lt;h2 id=&quot;where-apple-actually-hides-pdf-highlights&quot;&gt;Where Apple Actually Hides PDF Highlights&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/apple-books-hides-your-pdf-highlights-my-obsidian-body-1.jpg&quot; alt=&quot;A Quick Refresher On What This Thing Does&quot; srcset=&quot;            /assets/resized/480/apple-books-hides-your-pdf-highlights-my-obsidian-body-1.jpg 480w,            /assets/resized/800/apple-books-hides-your-pdf-highlights-my-obsidian-body-1.jpg 800w,            /assets/resized/1400/apple-books-hides-your-pdf-highlights-my-obsidian-body-1.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here’s the part that took real detective work, and where my first assumption was flat wrong.&lt;/p&gt;

&lt;p&gt;My mental model was simple: highlights go in the SQLite database, PDFs are books, therefore PDF highlights go in the database. So I looked. And there they were. Sort of.&lt;/p&gt;

&lt;p&gt;The database had a row for every PDF I’d ever opened. But every single one looked like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ZANNOTATIONSELECTEDTEXT = (empty)
ZANNOTATIONSTYLE        = 0
ZANNOTATIONTYPE         = 3
ZPLUSERDATA             = &amp;lt;binary plist: BKPageLocation, pageOffset 21&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;No text. No color. No note. Just a page number wrapped in a binary property list. That’s not a highlight. That’s a bookmark. Apple Books drops one of these in the database for every PDF so it can remember what page you were on, and my plugin had been correctly throwing them away for a year because they have no selected text.&lt;/p&gt;

&lt;p&gt;So the highlights weren’t in the database at all. That meant they had to be in the PDF files, which on a Mac live in your iCloud Books folder:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~/Library/Mobile Documents/iCloud~com~apple~iBooks/Documents/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I grepped one of my highlighted PDFs for the PDF highlight marker, and there it was:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;58 occurrences of /Subtype /Highlight
71 QuadPoints arrays
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s the answer. Apple Books writes PDF highlights back into the PDF file as standard PDF annotations. Not into its own database like it does for EPUBs. Into the file. Which is actually the more portable choice, it’s just the opposite of everywhere else the app stores things.&lt;/p&gt;

&lt;h2 id=&quot;reading-highlights-out-of-a-raw-pdf&quot;&gt;Reading Highlights Out Of A Raw PDF&lt;/h2&gt;

&lt;p&gt;A PDF highlight annotation doesn’t store the text you highlighted. That would be too easy. It stores &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QuadPoints&lt;/code&gt;, which are the rectangles the yellow marker was painted over, in PDF coordinate space. To get the actual words you have to line those rectangles up against the text on the page and read out whatever sits underneath.&lt;/p&gt;

&lt;p&gt;That’s a job for &lt;a href=&quot;https://github.com/mozilla/pdf.js&quot;&gt;pdf.js&lt;/a&gt;, Mozilla’s PDF engine. It gives me the annotations on each page and, separately, every run of text with its position. For each highlight I:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Turn its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QuadPoints&lt;/code&gt; into one box per highlighted line.&lt;/li&gt;
  &lt;li&gt;Find the text on the page whose baseline falls inside each box.&lt;/li&gt;
  &lt;li&gt;Clip the first and last lines, because a highlight usually starts and ends mid-sentence, snapping the cut to the nearest word boundary so I don’t slice a word in half.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/apple-books-hides-your-pdf-highlights-my-obsidian-body-2.jpg&quot; alt=&quot;Reading Highlights Out Of A Raw PDF&quot; srcset=&quot;            /assets/resized/480/apple-books-hides-your-pdf-highlights-my-obsidian-body-2.jpg 480w,            /assets/resized/800/apple-books-hides-your-pdf-highlights-my-obsidian-body-2.jpg 800w,            /assets/resized/1400/apple-books-hides-your-pdf-highlights-my-obsidian-body-2.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I tested it against a highlight I knew the exact wording of, and it came back verbatim, starting and ending in exactly the right place. Colors came out too. pdf.js hands them back as plain RGB values from 0 to 255, and Apple’s highlighter yellow is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(250, 205, 90)&lt;/code&gt;, so I map that to the same little yellow square the EPUB highlights already use.&lt;/p&gt;

&lt;h2 id=&quot;hooking-it-into-the-machine-that-already-worked&quot;&gt;Hooking It Into The Machine That Already Worked&lt;/h2&gt;

&lt;p&gt;This is the part I’m actually happy about, and it’s the part that keeps this from being a bolt-on mess.&lt;/p&gt;

&lt;p&gt;The plugin already had a whole pipeline for EPUBs: an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Annotation&lt;/code&gt; object shape, a markdown renderer, the smart-overwrite dedup, author page creation, file naming. All of it keyed off two internal types. So instead of writing a parallel universe for PDFs, I made the PDF extractor produce those exact same types. A PDF highlight becomes an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Annotation&lt;/code&gt;. A PDF file becomes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BookDetail&lt;/code&gt;, with its title and author pulled from the Books library database so the note gets a real title instead of a mangled filename.&lt;/p&gt;

&lt;p&gt;Once the shapes matched, the entire existing machine just ran. The renderer, the dedup, the author pages, the color emoji, none of it knew or cared that these highlights came out of a PDF instead of a database. PDF import is just a second phase inside the same “Import all books” command, plus one new toggle in settings so you can turn it off (because it is now the slow part of the plugin).&lt;/p&gt;

&lt;p&gt;The genuinely annoying part was bundling pdf.js into a single-file Obsidian plugin. pdf.js wants to run its parser in a Web Worker loaded from a separate file, and an Obsidian plugin ships as one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.js&lt;/code&gt;. The trick is to run the worker on the main thread by handing pdf.js its own worker module through a global:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pdfjsWorker&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;pdfjs-dist/legacy/build/pdf.worker.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;globalThis&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pdfjsWorker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pdfjsWorker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That, plus telling the bundler to leave the optional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canvas&lt;/code&gt; dependency alone, and it works. It also took &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.js&lt;/code&gt; from about 250KB to 4.3MB, because I’m now shipping an entire PDF engine inside a note-taking plugin. Such is life.&lt;/p&gt;

&lt;h2 id=&quot;the-tradeoff-its-slower-but-its-everything-now&quot;&gt;The Tradeoff: It’s Slower, But It’s Everything Now&lt;/h2&gt;

&lt;p&gt;I’m not going to pretend this is free. The database approach for EPUBs is instant. The PDF approach is not.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/apple-books-hides-your-pdf-highlights-my-obsidian-body-3.jpg&quot; alt=&quot;The Tradeoff: It&apos;s Slower, But It&apos;s Everything Now&quot; srcset=&quot;            /assets/resized/480/apple-books-hides-your-pdf-highlights-my-obsidian-body-3.jpg 480w,            /assets/resized/800/apple-books-hides-your-pdf-highlights-my-obsidian-body-3.jpg 800w,            /assets/resized/1400/apple-books-hides-your-pdf-highlights-my-obsidian-body-3.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Apple doesn’t track which PDFs you’ve highlighted anywhere I can query, so the plugin has to go look. It scans your entire iCloud Books folder, does a cheap byte-level check for the highlight marker to skip the hundreds of PDFs you never marked up, and then parses the survivors with pdf.js on the main thread. In my library that’s 748 PDFs to glance at. So yes, “Import all books” takes noticeably longer than it used to, and a book with a lot of highlights can make the app pause for a second while it works.&lt;/p&gt;

&lt;p&gt;I decided I’ll take that trade every time. A slightly slower import that gets me everything beats an instant import with a hole in it.&lt;/p&gt;

&lt;p&gt;And I do mean everything. Between the SQLite databases, the EPUB files, and now the PDFs, I’m fairly confident there’s nothing left in Apple Books that I can’t pull out. EPUB highlights, PDF highlights, notes, metadata, covers. If Apple is storing it on my Mac, this plugin can reach it. I went looking for one more hidden source after the PDFs and came up empty, which for once is the good outcome.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2025/obsidian-book-note-example.png&quot; alt=&quot;A PDF book note with imported highlights&quot; srcset=&quot;            /assets/resized/480/obsidian-book-note-example.png 480w,            /assets/resized/800/obsidian-book-note-example.png 800w,            /assets/resized/1400/obsidian-book-note-example.png 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-to-install-it-its-not-in-community-plugins-yet&quot;&gt;How To Install It (It’s Not In Community Plugins Yet)&lt;/h2&gt;

&lt;p&gt;Fair warning: this plugin is not in the Obsidian community plugin browser. It’s mine, it’s niche, and it reads files out of your macOS system libraries, so it lives on GitHub for now. That means two ways in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The easy way, with BRAT.&lt;/strong&gt; BRAT is the Beta Reviewers Auto-update Tool, and it exists exactly for plugins like this one. Install BRAT from the community plugins, then add this repo as a beta plugin:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;eristoddle/apple-books-annotation-import
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;BRAT installs it and keeps it updated whenever I push a new release. I wrote a whole walkthrough of this if you’ve never done it: &lt;a href=&quot;https://www.stephanmiller.com/how-to-install-obsidian-plugins/#:~:text=How%20to%20Install%20Beta%20Obsidian%20Plugins%20with%20BRAT&quot;&gt;How to Install Obsidian Plugins&lt;/a&gt;, including the BRAT section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The manual way.&lt;/strong&gt; Grab &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.js&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;manifest.json&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;styles.css&lt;/code&gt; from the &lt;a href=&quot;https://github.com/eristoddle/apple-books-annotation-import/releases&quot;&gt;latest release&lt;/a&gt;, drop them in a folder under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.obsidian/plugins/apple-books-annotation-import/&lt;/code&gt; in your vault, and enable it in settings. No auto-updates, but it works.&lt;/p&gt;

&lt;p&gt;Either way, once it’s on, flip on “Import PDF highlights” in the settings, hit “Import all books,” and give it a minute to chew through your library.&lt;/p&gt;

&lt;h2 id=&quot;the-takeaway&quot;&gt;The Takeaway&lt;/h2&gt;

&lt;p&gt;The lesson here isn’t really about PDFs. It’s that “it works” and “it’s complete” are two different claims, and I’d been quietly making the first one while believing the second for over a year. The plugin worked. It just wasn’t done. It took actually going looking for a specific missing highlight to find the gap.&lt;/p&gt;

&lt;p&gt;If you build tools for yourself, this is the failure mode to watch for. The thing runs, you trust it, and you stop checking whether it’s still telling you the whole truth. Apple gave me a good excuse by hiding PDF highlights in a completely different place than everything else, but the hole was mine to notice.&lt;/p&gt;

&lt;p&gt;Anyway. It’s fixed. Every highlight I’ve got, in every format Apple Books supports, now lands in Obsidian. Which means I’m out of excuses and back to actually reading the books.&lt;/p&gt;
</description>
        <pubDate>Wed, 29 Jul 2026 07:00:00 -0500</pubDate>
        <link>https://www.stephanmiller.com/apple-books-hides-your-pdf-highlights-my-obsidian-plugin-now-digs-them-out/</link>
        <guid isPermaLink="true">https://www.stephanmiller.com/apple-books-hides-your-pdf-highlights-my-obsidian-plugin-now-digs-them-out/</guid>
        
        <category>obsidian</category>
        
        <category>apple-books</category>
        
        <category>plugin</category>
        
        <category>pdf</category>
        
        <category>vibe-coding</category>
        
        
        <category>obsidian</category>
        
      </item>
    
      <item>
        <title>Claude Opus 5: The Flagship Got Cheaper (There&apos;s a Catch)</title>
        <description>&lt;p&gt;For about a year now, every model launch has followed the same script. A lab drops a new flagship, it’s a little smarter than the last one, and it costs more. You brace for it. New tier, new price, same shrug. So when Anthropic put out Claude Opus 5 on July 24, I opened the pricing page already wincing.&lt;/p&gt;

&lt;p&gt;Then I read it twice, because it was half the price.&lt;/p&gt;

&lt;p&gt;Not half the price of some bloated competitor. Half the price of Anthropic’s own current king, Fable 5. And on the Artificial Analysis Intelligence Index, Opus 5 edged out Fable 5 for the number one spot. Smarter and cheaper, in the same launch. That’s not how any of this has gone for a year.&lt;/p&gt;

&lt;p&gt;And then, three days later, the biggest open-weights model in human history dropped on Hugging Face, and I sat there doing the math on whether I could run it. Spoiler: I cannot. Nobody with fewer than eight datacenter GPUs can. Welcome to the week.&lt;/p&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#the-flagship-got-cheaper-wait-what&quot; id=&quot;markdown-toc-the-flagship-got-cheaper-wait-what&quot;&gt;The Flagship Got Cheaper (Wait, What?)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-28-trillion-parameter-paperweight&quot; id=&quot;markdown-toc-the-28-trillion-parameter-paperweight&quot;&gt;The 2.8 Trillion Parameter Paperweight&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-actually-useful-release-nobody-tweeted-about&quot; id=&quot;markdown-toc-the-actually-useful-release-nobody-tweeted-about&quot;&gt;The Actually Useful Release Nobody Tweeted About&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cheapskate-picks-what-id-actually-pay-for&quot; id=&quot;markdown-toc-cheapskate-picks-what-id-actually-pay-for&quot;&gt;Cheapskate Picks: What I’d Actually Pay For&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-horror-show&quot; id=&quot;markdown-toc-the-horror-show&quot;&gt;The Horror Show&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-still-waiting-room&quot; id=&quot;markdown-toc-the-still-waiting-room&quot;&gt;The Still-Waiting Room&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-takeaway&quot; id=&quot;markdown-toc-the-takeaway&quot;&gt;The Takeaway&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-flagship-got-cheaper-wait-what&quot;&gt;The Flagship Got Cheaper (Wait, What?)&lt;/h2&gt;

&lt;p&gt;Here’s the part I keep re-reading. Claude Opus 5 costs $5 per million input tokens and $25 per million output. That’s the exact same price as Opus 4.8, the model it replaces. Meanwhile Fable 5, Anthropic’s big expensive brain, sits at $10 in and $50 out. So Opus 5 is literally half the sticker of the model it just beat on the intelligence leaderboard.&lt;/p&gt;

&lt;p&gt;On the Artificial Analysis Intelligence Index, Opus 5 (max) scores 61. Fable 5 lands at 60. GPT-5.6 Sol comes in at 59, and Moonshot’s Kimi K3 at 57. It’s a photo finish at the top, but the point is that the cheaper Anthropic model is the one holding the trophy this week.&lt;/p&gt;

&lt;p&gt;The number that actually matters, though, isn’t the Index rank. It’s cost per task. Sticker price per token lies to you, because different models burn different amounts of tokens to finish the same job. Artificial Analysis measured it: running their full Intelligence Index costs about $2.03 per task on Opus 5 versus $2.75 on Fable 5. That’s roughly 26 percent cheaper to do the same work, on top of the lower per-token rate. For anyone running agent loops where the bill compounds, that’s the real headline.&lt;/p&gt;

&lt;p&gt;The benchmarks back up the “it’s genuinely good” claim, not just the “it’s cheap” one. On Frontier-Bench v0.1 it hit 43.3 percent, against Fable 5’s 33.7 and GPT-5.6 Sol’s 34.4. On ARC-AGI-3 it scored 30.2 percent while Opus 4.8 managed a sad 1.5. It’s the new default on Claude Max and the strongest model available on Claude Pro.&lt;/p&gt;

&lt;p&gt;So what’s the catch, because there’s always a catch. The catch is buried in the launch chart. On the Frontier-Bench numbers, Anthropic notes that Opus 4.8 “stood in as a fallback” whenever a safety classifier refused an Opus 5 request. Fine. Except they never said how often that happened. So the flagship benchmark quietly folds in a weaker model’s answers by an amount nobody will tell you. If you remember the refuse-and-reroute mess that followed Fable 5 around, this is the same species of problem wearing a nicer suit.&lt;/p&gt;

&lt;h2 id=&quot;the-28-trillion-parameter-paperweight&quot;&gt;The 2.8 Trillion Parameter Paperweight&lt;/h2&gt;

&lt;p&gt;While Anthropic was cutting prices, Moonshot was flexing. On July 27 they released the open weights for Kimi K3, and this thing is a monster: 2.8 trillion parameters, the largest open-weight model ever shipped. On the Artificial Analysis Index it scores 57, which makes it the highest-scoring open model on the board, ahead of everything else you can actually download.&lt;/p&gt;

&lt;p&gt;Here’s where the dream meets the parking lot. The download is about 1.4 terabytes of weights even at MXFP4 quantization. The architecture is a mixture of experts, 896 experts total with 16 active per token, so roughly 50 billion parameters are actually doing work on any given pass. To load it you need something like four to eight H100 80GB GPUs. Your 4090 can’t touch it. Your maxed-out Mac Studio can’t touch it. “Own your weights” is a beautiful slogan right up until you price the hardware to hold them.&lt;/p&gt;

&lt;p&gt;So in practice, for almost everyone, Kimi K3 is still just an API you rent at $3 per million in and $15 per million out. The weights being open is great for labs, cloud providers, and the three guys on Reddit with a GPU rack in the garage. For the rest of us it’s a philosophical victory, not a practical one.&lt;/p&gt;

&lt;p&gt;And it’s not a clean win even on quality. Accuracy went up about 13 points over the K2.6 generation, which sounds great, but the hallucination rate also climbed about 12 points. Moonshot frames that as the model being “more willing to answer.” Cute. For regulated, legal, medical, or financial work, “more willing to answer” is a polite way of saying “more confidently wrong more often,” and there’s no dial to trade it back.&lt;/p&gt;

&lt;h2 id=&quot;the-actually-useful-release-nobody-tweeted-about&quot;&gt;The Actually Useful Release Nobody Tweeted About&lt;/h2&gt;

&lt;p&gt;Buried under the Opus 5 launch and the Kimi K3 spectacle, Google shipped the model I’d actually reach for on a Tuesday. Gemini 3.6 Flash landed July 21 at $1.50 in and $7.50 out. That output price is down from the $9 that Gemini 3.5 Flash charged, and Google says it uses about 17 percent fewer output tokens on top of that. Cheaper rate, fewer tokens, same 1 million token context, knowledge cutoff pushed to March 2026.&lt;/p&gt;

&lt;p&gt;The funny part: Artificial Analysis gives 3.6 Flash the same Intelligence Index score as 3.5 Flash, a 50. So the tech press mostly shrugged. No leap, no headline. But it gained on the benchmarks that matter for real work, SWE-Bench Pro up to 58.7 percent from 55.1, OSWorld computer use up to 83 from 78.4. And it sits inside the competitive band of five of the six Arena categories I track. Cheaper than the thing it replaces, and it beats the mid-tier of the pricier labs. That’s the whole pitch, and it’s a good one.&lt;/p&gt;

&lt;h2 id=&quot;cheapskate-picks-what-id-actually-pay-for&quot;&gt;Cheapskate Picks: What I’d Actually Pay For&lt;/h2&gt;

&lt;p&gt;Here’s the trick I run every week, because I’m cheap and I have to be. The Arena leaderboards cluster tight at the top. The entire Overall top 20 this week fits inside 32 rating points, from Fable 5 at 1508 down to a pack at 1476. When the whole visible field is that compressed, paying the leader’s price buys you almost nothing over something a fraction of the cost. So the game is: find the cheapest model still inside spitting distance of the category leader.&lt;/p&gt;

&lt;p&gt;Here’s where that landed this week:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Category&lt;/th&gt;
      &lt;th&gt;Leader&lt;/th&gt;
      &lt;th&gt;$ out&lt;/th&gt;
      &lt;th&gt;Cheapskate pick&lt;/th&gt;
      &lt;th&gt;$ out&lt;/th&gt;
      &lt;th&gt;Δ rating&lt;/th&gt;
      &lt;th&gt;Cheaper by&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Overall&lt;/td&gt;
      &lt;td&gt;Fable 5 (1508)&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;MiMo v2.5 Pro (1465, #37)&lt;/td&gt;
      &lt;td&gt;$0.87&lt;/td&gt;
      &lt;td&gt;−43&lt;/td&gt;
      &lt;td&gt;~57x&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Coding&lt;/td&gt;
      &lt;td&gt;Opus 4.7-thinking (1553)&lt;/td&gt;
      &lt;td&gt;~$25&lt;/td&gt;
      &lt;td&gt;MiMo v2.5 Pro (1519, #25)&lt;/td&gt;
      &lt;td&gt;$0.87&lt;/td&gt;
      &lt;td&gt;−34&lt;/td&gt;
      &lt;td&gt;~29x&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Creative Writing&lt;/td&gt;
      &lt;td&gt;Fable 5 (1507)&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;Gemini 3-Flash (1458, #21)&lt;/td&gt;
      &lt;td&gt;$3&lt;/td&gt;
      &lt;td&gt;−49&lt;/td&gt;
      &lt;td&gt;~16.7x&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Instruction Following&lt;/td&gt;
      &lt;td&gt;Fable 5 (1515)&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;MiMo v2.5 Pro (1469, #23)&lt;/td&gt;
      &lt;td&gt;$0.87&lt;/td&gt;
      &lt;td&gt;−46&lt;/td&gt;
      &lt;td&gt;~57x&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Hard Prompts&lt;/td&gt;
      &lt;td&gt;Fable 5 (1535)&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;MiMo v2.5 Pro (1494, #25)&lt;/td&gt;
      &lt;td&gt;$0.87&lt;/td&gt;
      &lt;td&gt;−41&lt;/td&gt;
      &lt;td&gt;~57x&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Math&lt;/td&gt;
      &lt;td&gt;Fable 5 (1539)&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;Qwen3.7 Max (1490, #14)&lt;/td&gt;
      &lt;td&gt;$4.42&lt;/td&gt;
      &lt;td&gt;−49&lt;/td&gt;
      &lt;td&gt;~11.3x&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;MiMo v2.5 Pro, Xiaomi’s open-weights model, is the actual story this week, not Gemini 3.6 Flash. It sweeps four of six categories, Overall, Coding, Instruction Following, and Hard Prompts, all at the same $0.87 output price, and it does it by sitting at rank 23 to 37 in every one of those boards. A top-20 read misses it every single time, which is exactly the mistake I made drafting this section the first time around: I caught it on Coding, went back and checked the rest, and found the same miss in three more categories. Nobody’s talking about it. It’s just sitting there, MIT-licensed, being the actual answer.&lt;/p&gt;

&lt;p&gt;Gemini 3.6 Flash, the model with a whole section above this one, doesn’t win a single category outright once you look past the top 20. It’s still inside the band in five of six categories, so it’s a perfectly good pick if you want something you don’t have to go hunting for or self-host, but the honest cheapest option in four of six categories is a phone company’s open-weights model most readers have never heard of.&lt;/p&gt;

&lt;p&gt;Creative Writing breaks the pattern in both directions. MiMo doesn’t even show up in this category’s band, because Arena’s Creative Writing top end closes off faster (around rank 22 here) than the other categories do. And the actual cheapest thing inside that narrower band isn’t Gemini 3.6 Flash either, it’s the older, cheaper Gemini 3-Flash at $3, forty-nine points back and sitting right at the edge of the cutoff.&lt;/p&gt;

&lt;p&gt;Math is the one category where nothing changed. Qwen3.7 Max is still the cheapest model in the band, and it’s still clinging to the very edge at 49 points back. Grok 4.5 and Gemini 3.6 Flash both sit closer to the leader for a bit more money if you’d rather not ride the edge.&lt;/p&gt;

&lt;p&gt;One caveat on Overall and Hard Prompts: I pulled 40 rows deep for each category and the band technically hadn’t closed yet at row 40 in those two (the cutoff-adjacent rows were still inside the window). MiMo’s $0.87 is close to the price floor this cycle, so it’s very unlikely anything cheaper is sitting a few rows further down, but “very unlikely” isn’t the same as “confirmed,” so treat those two picks as high-confidence rather than fully closed.&lt;/p&gt;

&lt;p&gt;If you’re keeping score: MiMo v2.5 Pro is the boring, correct answer this week, not Gemini 3.6 Flash. Four out of six categories, one price tag, and it took reading past rank 20 in every single one of them to find that out.&lt;/p&gt;

&lt;h2 id=&quot;the-horror-show&quot;&gt;The Horror Show&lt;/h2&gt;

&lt;p&gt;Every roundup needs a section where I tell you what broke. This week was generous.&lt;/p&gt;

&lt;p&gt;The big one was DeepSeek’s migration cliff. DeepSeek is the single most-used vendor on OpenRouter right now, about 17.6 percent of all routed tokens. On July 24 at 15:59 UTC they hard-retired the old model names &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-chat&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-reasoner&lt;/code&gt;. Not deprecated with a grace period. Retired. Calls to those names now return errors with no fallback, so any service that didn’t repoint to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-v4-flash&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-v4-pro&lt;/code&gt; started throwing user-facing failures the moment the clock hit. Worse, reasoning moved from being a model name to being a request parameter, so lazy integrations silently lost their thinking mode before the hard cutoff even arrived. If your app went weird last Friday afternoon, there’s your answer.&lt;/p&gt;

&lt;p&gt;Then there’s the Opus 5 fallback I already whined about. A benchmark that quietly swaps in a different model when the safety filter trips, by an amount nobody discloses, is exactly the kind of asterisk that gets left out of the headline.&lt;/p&gt;

&lt;p&gt;And Kimi K3 has a confidence problem. The hallucination rate climbing 12 points while the marketing calls it “more willing to answer” is going to bite somebody who wired it into a pipeline that trusts its output. Retrieval checks and citation verification are not optional with this one.&lt;/p&gt;

&lt;h2 id=&quot;the-still-waiting-room&quot;&gt;The Still-Waiting Room&lt;/h2&gt;

&lt;p&gt;The upcoming section is short and it’s mostly one name. Gemini 3.5 Pro missed its target again, and I’ve lost count, but this is at least the fourth slip. It’s still stuck in Vertex AI enterprise preview. Instead of the Pro model everyone actually wanted, Google shipped a fistful of Flash variants on July 21, which is how we got 3.6 Flash. TechCrunch’s headline said it plainly: three new Gemini models, but no 3.5 Pro. Reporting says the model keeps failing to hit Google’s own internal performance bar. At some point “delayed” starts to read as “in trouble.”&lt;/p&gt;

&lt;p&gt;On the open side, expect the Kimi K3 community quants and finetunes to start rolling now that the weights are public, assuming you have the hardware to do anything with them.&lt;/p&gt;

&lt;h2 id=&quot;the-takeaway&quot;&gt;The Takeaway&lt;/h2&gt;

&lt;p&gt;For most of the past year, the story in these roundups was rent versus own. Big closed models you pay for by the token, versus open Chinese weights you could theoretically host yourself. This week broke that frame in both directions at once. Anthropic made the closed flagship cheaper than its predecessor, and Moonshot made the open flagship so enormous that owning it is meaningless unless you run a datacenter.&lt;/p&gt;

&lt;p&gt;So the real question quietly changed. It’s not rent versus own anymore. It’s how much intelligence can you actually afford to run. Opus 5 answers it one way, by dropping the price of the top shelf. Gemini 3.6 Flash answers it another, by being 85 percent cheaper and good enough. Kimi K3 answers it by being technically free and practically out of reach.&lt;/p&gt;

&lt;p&gt;For the record, the market keeps drifting east while all this happens. Chinese models hit a record 58 percent of tokens processed by US firms on OpenRouter this month, peaking around 63 percent earlier in July. DeepSeek alone is that 17.6 percent, Qwen another 13.9, and Anthropic is the last US lab standing in the top 10. Make of that what you will.&lt;/p&gt;

&lt;p&gt;Me, I’m going to keep running Gemini 3.6 Flash for the boring stuff and paying up for Opus 5 when the task actually needs a brain. And I’m going to keep not running Kimi K3, because I do not, in fact, own a rack of H100s. Maybe next week.&lt;/p&gt;
</description>
        <pubDate>Tue, 28 Jul 2026 08:00:00 -0500</pubDate>
        <link>https://www.stephanmiller.com/model-buzz-roundup-week-of-0722/</link>
        <guid isPermaLink="true">https://www.stephanmiller.com/model-buzz-roundup-week-of-0722/</guid>
        
        <category>llm</category>
        
        <category>openrouter</category>
        
        <category>model-roundup</category>
        
        
        <category>large-language-models</category>
        
      </item>
    
      <item>
        <title>Obsidian iCloud Sync in 2026, Including the Windows Problem</title>
        <description>&lt;p&gt;I sync Obsidian to two MacBook Pros, a Windows desktop, an iPad, and an Android phone, and I pay nothing for it. iCloud is not how I do it. I wrote up every method I know of in &lt;a href=&quot;https://www.stephanmiller.com/sync-obsidian-vault-across-devices/&quot;&gt;my full guide to syncing an Obsidian vault across devices&lt;/a&gt;, and iCloud got a short section in that post with a warning attached, because the moment an Android phone enters the picture iCloud is done.&lt;/p&gt;

&lt;p&gt;But that pillar post never had room to explain the part people actually get burned by. So this is the long version. How to set iCloud sync up properly, what the Apple-only happy path looks like, and the specific ways iCloud Drive on Windows starts leaving random markdown files around your vault.&lt;/p&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#who-obsidian-icloud-sync-is-actually-for&quot; id=&quot;markdown-toc-who-obsidian-icloud-sync-is-actually-for&quot;&gt;Who Obsidian iCloud Sync Is Actually For&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-to-create-a-new-obsidian-vault-in-icloud&quot; id=&quot;markdown-toc-how-to-create-a-new-obsidian-vault-in-icloud&quot;&gt;How to Create a New Obsidian Vault in iCloud&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-to-move-an-existing-obsidian-vault-to-icloud&quot; id=&quot;markdown-toc-how-to-move-an-existing-obsidian-vault-to-icloud&quot;&gt;How to Move an Existing Obsidian Vault to iCloud&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-mac-iphone-and-ipad-happy-path&quot; id=&quot;markdown-toc-the-mac-iphone-and-ipad-happy-path&quot;&gt;The Mac, iPhone, and iPad Happy Path&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-setting-that-quietly-destroys-your-vault&quot; id=&quot;markdown-toc-the-setting-that-quietly-destroys-your-vault&quot;&gt;The Setting That Quietly Destroys Your Vault&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-windows-problem&quot; id=&quot;markdown-toc-the-windows-problem&quot;&gt;The Windows Problem&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#the-workaround-that-actually-respects-the-problem&quot; id=&quot;markdown-toc-the-workaround-that-actually-respects-the-problem&quot;&gt;The Workaround That Actually Respects the Problem&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#when-to-just-not-do-it&quot; id=&quot;markdown-toc-when-to-just-not-do-it&quot;&gt;When To Just Not Do It&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#obsidian-sync-vs-icloud&quot; id=&quot;markdown-toc-obsidian-sync-vs-icloud&quot;&gt;Obsidian Sync vs iCloud&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#is-obsidian-icloud-sync-encrypted&quot; id=&quot;markdown-toc-is-obsidian-icloud-sync-encrypted&quot;&gt;Is Obsidian iCloud Sync Encrypted?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cleaning-up-the-duplicates-you-already-have&quot; id=&quot;markdown-toc-cleaning-up-the-duplicates-you-already-have&quot;&gt;Cleaning Up the Duplicates You Already Have&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#frequently-asked-questions&quot; id=&quot;markdown-toc-frequently-asked-questions&quot;&gt;Frequently Asked Questions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-verdict&quot; id=&quot;markdown-toc-the-verdict&quot;&gt;The Verdict&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;who-obsidian-icloud-sync-is-actually-for&quot;&gt;Who Obsidian iCloud Sync Is Actually For&lt;/h2&gt;

&lt;p&gt;iCloud is the best free option in exactly one situation: every device you touch has an Apple logo on it.&lt;/p&gt;

&lt;p&gt;Mac plus iPhone plus iPad is close to zero configuration. Obsidian on iOS has a first-class iCloud option built into the vault creation screen, which is more than you can say for Dropbox or Google Drive on that platform.  You tap a toggle. If your desktop is not a Mac, the other iOS options are worth comparing before you commit, and I ranked all four in &lt;a href=&quot;https://www.stephanmiller.com/sync-obsidian-iphone-ipad-free/&quot;&gt;the guide to syncing Obsidian on iPhone and iPad for free&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Everywhere else it gets worse. Windows is possible but unreliable, covered in detail below. Linux has no official iCloud Drive client at all. And Android is not possible in any way I would recommend to a human being, because there is no iCloud Drive client for Android that syncs a folder to local storage, and Obsidian on Android needs a real local folder. That is why my own vault lives in Dropbox with &lt;a href=&quot;https://github.com/remotely-save/remotely-save&quot;&gt;Remotely Save&lt;/a&gt; handling Android. My phone is the constraint that decided the whole architecture.&lt;/p&gt;

&lt;p&gt;If your phone is an iPhone and your desktop is a Mac, stop reading comparison posts and just use iCloud. It is free, it is already on, and it works.&lt;/p&gt;

&lt;h2 id=&quot;how-to-create-a-new-obsidian-vault-in-icloud&quot;&gt;How to Create a New Obsidian Vault in iCloud&lt;/h2&gt;

&lt;p&gt;Two completely different procedures get searched for here, and people mix them up constantly. Creating a fresh vault in iCloud is the easy one. Do this first if you are starting clean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On iPhone or iPad:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open Obsidian and tap &lt;strong&gt;Create new vault&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Give it a name. Make it something you will recognize in Files.&lt;/li&gt;
  &lt;li&gt;Turn on &lt;strong&gt;Store in iCloud&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Tap &lt;strong&gt;Create&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;On Mac:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open Obsidian and choose &lt;strong&gt;Create new vault&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;For the location, browse to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iCloud Drive&lt;/code&gt; and pick or make a folder there.&lt;/li&gt;
  &lt;li&gt;Create the vault.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/obsidian-icloud-sync-in-2026-including-the-windows-body-1.jpg&quot; alt=&quot;How to Create a New Obsidian Vault in iCloud&quot; srcset=&quot;            /assets/resized/480/obsidian-icloud-sync-in-2026-including-the-windows-body-1.jpg 480w,            /assets/resized/800/obsidian-icloud-sync-in-2026-including-the-windows-body-1.jpg 800w,            /assets/resized/1400/obsidian-icloud-sync-in-2026-including-the-windows-body-1.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;On disk, the Mac path is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Library/Mobile Documents/iCloud~md~obsidian/Documents/&lt;/code&gt;, which shows up in the Files app as &lt;strong&gt;iCloud Drive &amp;gt; Obsidian&lt;/strong&gt;. That is where the iOS app puts vaults, and it is worth knowing because it is the folder you will be pointing other tools at later. Obsidian’s own docs are direct about this: vaults should live inside the Obsidian folder in iCloud Drive. A vault you drop somewhere else in iCloud Drive will sync between Macs fine and then fail to show up in the iOS app’s vault list, which is a confusing hour of your life you can skip.&lt;/p&gt;

&lt;h2 id=&quot;how-to-move-an-existing-obsidian-vault-to-icloud&quot;&gt;How to Move an Existing Obsidian Vault to iCloud&lt;/h2&gt;

&lt;p&gt;This is the one that goes wrong. The instinct is to drag your vault folder into iCloud Drive and open it. Do not start there.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Back the vault up first.&lt;/strong&gt; Copy the entire folder somewhere outside any sync service. A zip on your desktop is fine, and it is the only thing standing between you and a bad afternoon.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Close Obsidian on every device.&lt;/strong&gt; Not backgrounded on your phone. Closed. Two clients writing into a folder during an initial upload is how you generate conflicts on day one.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Create a new empty vault in iCloud&lt;/strong&gt; using the steps above, with the same name as your existing vault.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Move the contents&lt;/strong&gt; of your old vault into that new iCloud folder. Include the hidden &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.obsidian&lt;/code&gt; folder if you want your settings, themes, hotkeys, and plugins to come along. On Mac, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd + Shift + .&lt;/code&gt; toggles hidden files in Finder.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Wait for the upload to finish completely&lt;/strong&gt; before opening Obsidian anywhere. Watch the iCloud status in Finder’s sidebar. Rushing this is the whole problem.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Open it on your Mac first&lt;/strong&gt;, let plugins load, then open it on iOS.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On a big vault, leave the attachments out of the first pass. Sync the markdown, confirm it works, then move the images. Markdown files are tiny. Attachments are what blow up the initial sync window and give conflicts room to happen.&lt;/p&gt;

&lt;h2 id=&quot;the-mac-iphone-and-ipad-happy-path&quot;&gt;The Mac, iPhone, and iPad Happy Path&lt;/h2&gt;

&lt;p&gt;Once the vault is in place, the Apple-only setup genuinely is the low-maintenance option. Edits show up on the other device in a few seconds when both are awake and online. Obsidian’s own settings sync along with the vault because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.obsidian&lt;/code&gt; is just another folder, so if you have gone deep on &lt;a href=&quot;https://www.stephanmiller.com/how-to-install-obsidian-plugins/&quot;&gt;installing Obsidian plugins&lt;/a&gt; you do not have to set them up again per device.&lt;/p&gt;

&lt;p&gt;Two habits keep it that way. Let one device finish syncing before you start editing on another, because sync services do not have opinions about which version of a paragraph you meant. And never run a second sync system on the same vault. Not Obsidian Sync on top of iCloud, not Dropbox pointed at the same folder, not &lt;a href=&quot;https://www.stephanmiller.com/obsidian-git-sync-mobile/&quot;&gt;a Git plugin committing every two minutes&lt;/a&gt;. Two sync engines fighting over one folder is the most reliable way to lose notes, and it is self-inflicted every time.&lt;/p&gt;

&lt;h2 id=&quot;the-setting-that-quietly-destroys-your-vault&quot;&gt;The Setting That Quietly Destroys Your Vault&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/obsidian-icloud-sync-in-2026-including-the-windows-body-2.jpg&quot; alt=&quot;The Setting That Quietly Eats Your Vault&quot; srcset=&quot;            /assets/resized/480/obsidian-icloud-sync-in-2026-including-the-windows-body-2.jpg 480w,            /assets/resized/800/obsidian-icloud-sync-in-2026-including-the-windows-body-2.jpg 800w,            /assets/resized/1400/obsidian-icloud-sync-in-2026-including-the-windows-body-2.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Turn off &lt;strong&gt;Optimize Mac Storage&lt;/strong&gt; for iCloud Drive, or at least understand what it does before you leave it on.&lt;/p&gt;

&lt;p&gt;When macOS decides you are low on space, it evicts the local copies of files it thinks you are not using and leaves a placeholder with a little cloud icon. For photos, fine. For an Obsidian vault, not fine. Search, graph view, and backlinks all depend on files actually being present on disk. An evicted note is not a note. Searches come back short, links look broken, and nothing warns you that half your vault is currently a stub.&lt;/p&gt;

&lt;p&gt;The setting is in &lt;strong&gt;System Settings &amp;gt; [your name] &amp;gt; iCloud &amp;gt; iCloud Drive&lt;/strong&gt;. If you need it on for storage reasons, open iCloud Drive in Finder, control-click the vault folder, and choose &lt;strong&gt;Keep Downloaded&lt;/strong&gt; to exempt it. Windows has the same concept with a different name, and it is worse there, which is a good segue.&lt;/p&gt;

&lt;h2 id=&quot;the-windows-problem&quot;&gt;The Windows Problem&lt;/h2&gt;

&lt;p&gt;Obsidian’s own documentation says flatly that iCloud Drive on Windows may lead to file duplication or corruption. When the people who make the app warn you off a sync method, that is worth more than any blog post, including this one.&lt;/p&gt;

&lt;p&gt;iCloud for Windows exists. You install it from the Microsoft Store, sign in, and get an iCloud Drive folder in File Explorer. You can point Obsidian at a vault inside it. It will appear to work. Then, over days and weeks, these things start happening.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Placeholder files instead of real files.&lt;/strong&gt; iCloud for Windows does on-demand downloads the same way OneDrive does. A file with a cloud icon next to it is not on your disk. Obsidian tries to read it, and depending on timing you get an empty note, a failed read, or a plugin that throws. Vault-wide operations like search and Dataview queries are the worst hit because they touch everything at once. You can fight this by right-clicking the vault folder and choosing &lt;strong&gt;Always keep on this device&lt;/strong&gt;, which pins it locally. Do that before anything else if you are going to attempt this at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Duplicate files with numbers appended.&lt;/strong&gt; This is the classic symptom and the reason people search for this problem. You end up with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Meeting Notes.md&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Meeting Notes 2.md&lt;/code&gt;, sometimes several generations deep. It happens when the Windows client and another device both write a file before either has seen the other’s version. iCloud does not merge and it does not prompt. It keeps both and renames one.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/obsidian-icloud-sync-in-2026-including-the-windows-body-3.jpg&quot; alt=&quot;The Windows Problem&quot; srcset=&quot;            /assets/resized/480/obsidian-icloud-sync-in-2026-including-the-windows-body-3.jpg 480w,            /assets/resized/800/obsidian-icloud-sync-in-2026-including-the-windows-body-3.jpg 800w,            /assets/resized/1400/obsidian-icloud-sync-in-2026-including-the-windows-body-3.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.obsidian&lt;/code&gt; folder taking damage.&lt;/strong&gt; Your config folder is a pile of small JSON files that get rewritten constantly as you use the app. That write pattern is exactly what a lazy sync client handles worst. Corrupted &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;workspace.json&lt;/code&gt;, plugin settings reverting, hotkeys resetting, community plugins disabling themselves. If your Windows machine keeps forgetting your setup, this is why.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sync that just stops.&lt;/strong&gt; The client parks in a pending state and stays there. No error, no notification, just a folder that stopped updating while you kept typing into it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timing that encourages all of the above.&lt;/strong&gt; iCloud on Windows is slower to propagate changes than it is between Apple devices. A longer window between “I saved” and “the other machine knows” is a bigger window for conflicts.&lt;/p&gt;

&lt;h3 id=&quot;the-workaround-that-actually-respects-the-problem&quot;&gt;The Workaround That Actually Respects the Problem&lt;/h3&gt;

&lt;p&gt;The fix that works is to stop letting Obsidian and iCloud touch the same folder.&lt;/p&gt;

&lt;p&gt;Keep your working vault in a plain local folder on the Windows machine, somewhere iCloud cannot see. Then run a separate process that syncs that local folder to the iCloud copy, with real conflict handling. Obsidian only ever talks to fast local disk, and the sync layer deals with iCloud’s nonsense on its own schedule.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/gursimar/obsidian-icloud-windows-sync&quot;&gt;gursimar/obsidian-icloud-windows-sync&lt;/a&gt; does exactly this. It is a Python three-way sync engine that tracks the local vault, the iCloud copy, and a history snapshot so it can tell the difference between “this file changed here” and “this file changed on the other side.” When both changed, it keeps the newer one by modification time and saves the loser as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_CONFLICT_&amp;lt;timestamp&amp;gt;&lt;/code&gt; file rather than silently picking a winner. It uses atomic writes and a stabilization delay so it is not reacting to Obsidian’s autosave mid-keystroke. The README is explicit that it must run natively on Windows and not under WSL, because iCloud placeholder files behave incorrectly when accessed through WSL.&lt;/p&gt;

&lt;p&gt;That is a real answer, but be honest with yourself about what it is. It is a Python script you have to configure with a YAML file, keep running, and troubleshoot when it stops. If that sounds like a project rather than a solution, it probably is one for you.&lt;/p&gt;

&lt;h3 id=&quot;when-to-just-not-do-it&quot;&gt;When To Just Not Do It&lt;/h3&gt;

&lt;p&gt;If your setup is Windows plus iPhone, iCloud is the wrong tool. You are picking the option that is worst on your primary computer for the sake of convenience on your phone.&lt;/p&gt;

&lt;p&gt;Dropbox with Remotely Save covers Windows and iOS without any of this. So does Syncthing if you want nothing in the cloud at all. Obsidian Sync costs money and handles it. Any of those is a better use of your evening than fighting a sync client that is not designed for the write pattern of a notes app.&lt;/p&gt;

&lt;p&gt;I keep a Windows desktop in my rotation. I have never once been tempted to put my vault in iCloud on it.&lt;/p&gt;

&lt;h2 id=&quot;obsidian-sync-vs-icloud&quot;&gt;Obsidian Sync vs iCloud&lt;/h2&gt;

&lt;p&gt;The honest comparison, since “obsidian sync vs icloud” is what a lot of people are really asking.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/obsidian-icloud-sync-in-2026-including-the-windows-body-4.jpg&quot; alt=&quot;Obsidian Sync vs iCloud&quot; srcset=&quot;            /assets/resized/480/obsidian-icloud-sync-in-2026-including-the-windows-body-4.jpg 480w,            /assets/resized/800/obsidian-icloud-sync-in-2026-including-the-windows-body-4.jpg 800w,            /assets/resized/1400/obsidian-icloud-sync-in-2026-including-the-windows-body-4.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;iCloud&lt;/th&gt;
      &lt;th&gt;Obsidian Sync&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Price&lt;/td&gt;
      &lt;td&gt;Free with your existing iCloud storage&lt;/td&gt;
      &lt;td&gt;Standard $5/mo, or $4/mo billed annually. Plus $10/mo, or $8/mo annually&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Storage&lt;/td&gt;
      &lt;td&gt;Shares your iCloud quota&lt;/td&gt;
      &lt;td&gt;Standard 1 GB. Plus 10 GB, upgradable to 100 GB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;File size cap&lt;/td&gt;
      &lt;td&gt;iCloud Drive limits&lt;/td&gt;
      &lt;td&gt;Standard 5 MB. Plus 200 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Version history&lt;/td&gt;
      &lt;td&gt;Whatever iCloud keeps, not note-aware&lt;/td&gt;
      &lt;td&gt;Standard 1 month. Plus 12 months&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Windows&lt;/td&gt;
      &lt;td&gt;Unreliable, see above&lt;/td&gt;
      &lt;td&gt;Works&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Android&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
      &lt;td&gt;Works&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Linux&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
      &lt;td&gt;Works&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Encryption&lt;/td&gt;
      &lt;td&gt;In transit and at rest, Apple holds the keys unless Advanced Data Protection is on&lt;/td&gt;
      &lt;td&gt;End-to-end by default&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Conflict handling&lt;/td&gt;
      &lt;td&gt;Duplicate files&lt;/td&gt;
      &lt;td&gt;Merges, with per-file history to recover from&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Four dollars a month is the price of not reading this article. If you use Obsidian daily and your devices are not all Apple, that is a rounding error against the time any free method will cost you. I do not pay it, but I also enjoy this kind of problem, which is not a normal thing to enjoy.&lt;/p&gt;

&lt;p&gt;The version history row is the one people undervalue. iCloud can restore some files some of the time. Obsidian Sync keeps per-note history that understands what a vault is. The first time you need it, that gap is enormous.&lt;/p&gt;

&lt;h2 id=&quot;is-obsidian-icloud-sync-encrypted&quot;&gt;Is Obsidian iCloud Sync Encrypted?&lt;/h2&gt;

&lt;p&gt;Yes, but probably not in the way you are assuming.&lt;/p&gt;

&lt;p&gt;iCloud Drive is encrypted in transit and encrypted on Apple’s servers by default, and Apple holds the keys. That means Apple can access the contents and can be compelled to hand them over. Standard data protection is the default on every account.&lt;/p&gt;

&lt;p&gt;Turning on &lt;strong&gt;Advanced Data Protection&lt;/strong&gt; moves iCloud Drive to end-to-end encryption, so only your devices hold the keys. It is in &lt;strong&gt;System Settings &amp;gt; [your name] &amp;gt; iCloud &amp;gt; Advanced Data Protection&lt;/strong&gt; on a Mac, and the same path under Settings on iOS. The tradeoff is real. Apple makes you set up at least one alternative recovery method first, either a recovery contact or a recovery key, because once it is on Apple does not have the keys to help you. Lose your recovery methods and the data is gone. That is the entire point of it.&lt;/p&gt;

&lt;p&gt;Obsidian Sync is end-to-end encrypted by default with no configuration. If your vault holds anything you would call sensitive, that difference matters more than the price difference does.&lt;/p&gt;

&lt;h2 id=&quot;cleaning-up-the-duplicates-you-already-have&quot;&gt;Cleaning Up the Duplicates You Already Have&lt;/h2&gt;

&lt;p&gt;If you got here after the fact, the vault is already littered with numbered copies. Work in this order.&lt;/p&gt;

&lt;p&gt;Close Obsidian everywhere, let iCloud finish syncing, and copy the whole vault out to somewhere iCloud does not control. Then find the offenders. On Mac, from the vault root:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;* 2.md&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;* 3.md&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*conflicted copy*&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/obsidian-icloud-sync-in-2026-including-the-windows-body-5.jpg&quot; alt=&quot;Cleaning Up the Duplicates You Already Have&quot; srcset=&quot;            /assets/resized/480/obsidian-icloud-sync-in-2026-including-the-windows-body-5.jpg 480w,            /assets/resized/800/obsidian-icloud-sync-in-2026-including-the-windows-body-5.jpg 800w,            /assets/resized/1400/obsidian-icloud-sync-in-2026-including-the-windows-body-5.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;On Windows, in PowerShell:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Get-ChildItem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Recurse&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Filter&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;* 2.md&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Diff before you delete. Most numbered copies are identical to the original and safe to remove. Some contain the only copy of a paragraph you wrote:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;diff &lt;span class=&quot;s2&quot;&gt;&quot;Meeting Notes.md&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Meeting Notes 2.md&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Merge what matters, delete the rest, fix any internal links that pointed at the duplicate, then fix the cause or you will do this again next month. Fixing the cause means taking the Windows machine out of the iCloud path, or moving the vault to a method that handles conflicts properly.&lt;/p&gt;

&lt;p&gt;You can also automate the finding part. Obsidian Cleaner, one of &lt;a href=&quot;https://www.stephanmiller.com/the-obsidian-plugin-collection-i-built-one-free-kiro-credit-at-a-time/&quot;&gt;the plugins I had Kiro build for me on free monthly credits&lt;/a&gt;, surfaces conflicted copies, numbered duplicates, and zero-byte markdown files as a checklist you can review before deleting. I built it because I kept hitting this, which tells you how common the problem is across every sync method, not just iCloud.&lt;/p&gt;

&lt;h2 id=&quot;frequently-asked-questions&quot;&gt;Frequently Asked Questions&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How do I sync Obsidian with iCloud?&lt;/strong&gt;
On iOS, enable &lt;strong&gt;Store in iCloud&lt;/strong&gt; when you create the vault. On Mac, put the vault in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Library/Mobile Documents/iCloud~md~obsidian/Documents/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I connect Obsidian to iCloud on a vault I already have?&lt;/strong&gt;
Close Obsidian everywhere, create an empty iCloud vault with the same name, and move your files plus the hidden &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.obsidian&lt;/code&gt; folder into it. The order matters more than the steps do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I move my Obsidian vault to iCloud without losing anything?&lt;/strong&gt;
Back up first, and wait for the initial upload to finish before you open the vault on a second device. On a large vault, sync the markdown first and the attachments second.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Obsidian iCloud sync work on Windows?&lt;/strong&gt;
It runs, but it is unreliable. If you must do it, keep the working vault in a plain local folder and mirror it to iCloud with a tool like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gursimar/obsidian-icloud-windows-sync&lt;/code&gt; rather than letting Obsidian edit inside the iCloud folder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is Obsidian iCloud sync encrypted?&lt;/strong&gt;
Encrypted in transit and at rest, but Apple holds the keys unless Advanced Data Protection is on. Obsidian Sync is end-to-end encrypted by default.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I sync Obsidian to Android with iCloud?&lt;/strong&gt;
No. Use Dropbox with Remotely Save, Syncthing, or Obsidian Sync instead.&lt;/p&gt;

&lt;h2 id=&quot;the-verdict&quot;&gt;The Verdict&lt;/h2&gt;

&lt;p&gt;iCloud sync for Obsidian is genuinely good and genuinely free, right up to the edge of Apple’s ecosystem, where it falls off a cliff with no railing.&lt;/p&gt;

&lt;p&gt;All Apple, all the time: use it, it is the right answer and you can stop researching. Windows in the mix: it is a maintenance project, and you should either run a real sync layer on top of it or pick a different method entirely. Android anywhere in your life: it is not a choice you have.&lt;/p&gt;

&lt;p&gt;I landed on Dropbox and Remotely Save because of an Android phone, and I have no regrets about it, though I did spend a weekend getting there. The methods are not ranked by quality. They are ranked by which devices you happen to own, and the honest advice is to pick based on your worst device rather than your best one.&lt;/p&gt;
</description>
        <pubDate>Mon, 27 Jul 2026 08:00:00 -0500</pubDate>
        <link>https://www.stephanmiller.com/obsidian-icloud-sync-windows/</link>
        <guid isPermaLink="true">https://www.stephanmiller.com/obsidian-icloud-sync-windows/</guid>
        
        <category>obsidian</category>
        
        <category>icloud</category>
        
        <category>sync</category>
        
        <category>windows</category>
        
        
        <category>obsidian</category>
        
      </item>
    
      <item>
        <title>The Bottleneck Was Me: How I Stopped Racing My AI Builder and Started Pacing It</title>
        <description>&lt;p&gt;The last post ended on a clean little problem. I’d gotten my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLAN.md&lt;/code&gt; lean: the decisions up top, the history filed away, a skill that keeps it that way so I don’t have to. The plan was finally generating work faster than I could build it. And that exposed a new bottleneck on the build side: my setup hands one task at a time to a background Sonnet agent and waits. The builder finishes, then sits there idle while I plan the next one. So I asked the next question: how do you keep the builder &lt;em&gt;always busy?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The goal turned out to be a decent description of the symptom and a terrible description of what I actually wanted. This is the post where I figured out the difference, by doing it backwards first.&lt;/p&gt;

&lt;p&gt;This is part three of a series about working with AI coding agents using a single living &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLAN.md&lt;/code&gt; instead of vibe coding or spec-kit ceremony. &lt;a href=&quot;https://www.stephanmiller.com/the-third-attempt-how-a-living-plan-beat-both-vibe-coding-and-spec-kit/&quot;&gt;Post one&lt;/a&gt; is the thesis. The doc is the deliverable, the code is the byproduct. &lt;a href=&quot;https://www.stephanmiller.com/the-living-plan-got-fat-compacting-a-doc-that-wont-stop-growing/&quot;&gt;The last post&lt;/a&gt; was about keeping that doc from turning into a 28,000-word novella.&lt;/p&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#the-batch-that-hooked-me&quot; id=&quot;markdown-toc-the-batch-that-hooked-me&quot;&gt;The Batch That Hooked Me&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-experiment-a-pre-specified-queue&quot; id=&quot;markdown-toc-the-experiment-a-pre-specified-queue&quot;&gt;The Experiment: A Pre-Specified Queue&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#i-optimized-the-wrong-thing&quot; id=&quot;markdown-toc-i-optimized-the-wrong-thing&quot;&gt;I Optimized the Wrong Thing&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-gap-was-the-point&quot; id=&quot;markdown-toc-the-gap-was-the-point&quot;&gt;The Gap Was the Point&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-model-a-serial-queue&quot; id=&quot;markdown-toc-the-model-a-serial-queue&quot;&gt;The Model: A Serial Queue&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#two-ways-to-stack&quot; id=&quot;markdown-toc-two-ways-to-stack&quot;&gt;Two Ways to Stack&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-real-bottleneck-was-never-the-task-slot&quot; id=&quot;markdown-toc-the-real-bottleneck-was-never-the-task-slot&quot;&gt;The Real Bottleneck Was Never the Task Slot&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-name&quot; id=&quot;markdown-toc-the-name&quot;&gt;The Name&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-honest-scope-note&quot; id=&quot;markdown-toc-the-honest-scope-note&quot;&gt;The Honest Scope Note&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#whats-next&quot; id=&quot;markdown-toc-whats-next&quot;&gt;What’s Next&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-batch-that-hooked-me&quot;&gt;The Batch That Hooked Me&lt;/h2&gt;

&lt;p&gt;The seed of this whole idea was a session a few weeks back where I did something different. Instead of speccing one hardening task, launching it, and waiting, I lined up a &lt;em&gt;batch&lt;/em&gt; of small mechanical jobs and drove them back-to-back as one verified sequence. Each one: Sonnet builds it, I re-read the diff and the tests, then I launch the next. The test count climbed 140 → 234 across the run.&lt;/p&gt;

&lt;p&gt;Driving them as a batch freed up enough of my attention that I was &lt;em&gt;working a second project at the same time&lt;/em&gt;, jumping back and forth between this content pipeline and my other repo. The fact that the builder grinding away in the background bought me time to go be useful somewhere else.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-1.jpg&quot; alt=&quot;The Batch That Hooked Me&quot; srcset=&quot;            /assets/resized/480/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-1.jpg 480w,            /assets/resized/800/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-1.jpg 800w,            /assets/resized/1400/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-1.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I filed that away as a direction and went back to feeding the plan. But it nagged at me, because I’d named it wrong in my own head. I called it “keeping the builder busy,” and I built the next experiment around that name.&lt;/p&gt;

&lt;h2 id=&quot;the-experiment-a-pre-specified-queue&quot;&gt;The Experiment: A Pre-Specified Queue&lt;/h2&gt;

&lt;p&gt;Here’s how I decided to actually test it. I had a real feature coming up: making the content pipeline able to &lt;em&gt;require&lt;/em&gt; embedded artifacts in an article. A brief could say “this post needs at least two of: a code block, a comparison table, a diagram,” and the pipeline would produce them, preserve them through the humanizer, and verify they’re actually there at the end. Four moving parts, real dependencies between them.&lt;/p&gt;

&lt;p&gt;So instead of speccing it one task at a time the way I always had, I pre-specified the &lt;em&gt;entire arc&lt;/em&gt; up front as an ordered queue. Four tasks. Task A, the schema that declares the requirement, had to land first, because the other three all depend on it. Then B (the writer produces the artifacts), C (the humanizer preserves them), and D (the checker verifies them) could each go independently. I wrote all four specs, mapped the dependency, and flagged the genuine design forks, the questions only I could answer, to settle before anything ran.&lt;/p&gt;

&lt;p&gt;The point of pre-specifying the whole thing wasn’t speed. It was to find out &lt;em&gt;where pre-specifying breaks down.&lt;/em&gt; Which specs would look airtight on paper and fall apart the moment a builder touched real code.&lt;/p&gt;

&lt;p&gt;Then I ran it. And immediately optimized the wrong variable.&lt;/p&gt;

&lt;h2 id=&quot;i-optimized-the-wrong-thing&quot;&gt;I Optimized the Wrong Thing&lt;/h2&gt;

&lt;p&gt;Task A landed first. It had to; everything blocked on it. But B, C, and D were independent. So Claude decided to run them concurrently.&lt;/p&gt;

&lt;p&gt;Three Sonnet agents, in parallel, each on its own task, each on a disjoint set of files. And it &lt;strong&gt;worked&lt;/strong&gt;. All three landed clean. The test suite went from 234 to 328. If you’d asked me to measure throughput, I’d just tripled it. By every number I’d have put on a dashboard, this was the win.&lt;/p&gt;

&lt;p&gt;It felt awful.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-2.jpg&quot; alt=&quot;I Optimized the Wrong Thing&quot; srcset=&quot;            /assets/resized/480/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-2.jpg 480w,            /assets/resized/800/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-2.jpg 800w,            /assets/resized/1400/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-2.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Because the second those three agents came back, they came back &lt;em&gt;together&lt;/em&gt;. The background hum that let me work on the other project and do slow human thinking. Gone. I’d taken a process whose entire value was &lt;em&gt;spreading work out over time&lt;/em&gt; and I’d compressed it back into a single spike of “everything needs you, now.”&lt;/p&gt;

&lt;p&gt;I’d been accidentally optimizing for &lt;strong&gt;throughput&lt;/strong&gt;: get the most build done per unit time. But throughput was never what bought me the second project. What bought me the second project was the &lt;em&gt;gap.&lt;/em&gt; Parallelism doesn’t widen that gap. It removes it.&lt;/p&gt;

&lt;h2 id=&quot;the-gap-was-the-point&quot;&gt;The Gap Was the Point&lt;/h2&gt;

&lt;p&gt;The builder’s grind is not a cost to be minimized. &lt;strong&gt;It’s a resource.&lt;/strong&gt; A long-enough synchronous build is a &lt;em&gt;gap&lt;/em&gt; I spend doing the slow human work: investigating, answering my own open questions, and making the design calls that only I can make. Often on a completely different project. The ideal loop isn’t “builder always busy.” It’s two slow things overlapping in time: the machine grinding through mechanical work while I grind through judgment work. Pacing, not racing.&lt;/p&gt;

&lt;p&gt;Once I saw it that way, the design fell out immediately:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Synchronous, one-task-at-a-time, is the default&lt;/strong&gt;, because that’s what manufactures the gap. One builder, working a queue in order, then stopping to report. The stop is a feature. It’s the handoff point where I come back, review, and re-aim.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Parallel is a rare opt-in burst,&lt;/strong&gt; for the specific case where I’m actively babysitting &lt;em&gt;this&lt;/em&gt; project and want raw speed more than I want freed attention. But it’s not a default. The session that taught me this lesson proved parallel works. It just also proved it’s the wrong thing to reach for ninety percent of the time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-3.jpg&quot; alt=&quot;The Gap Was the Point&quot; srcset=&quot;            /assets/resized/480/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-3.jpg 480w,            /assets/resized/800/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-3.jpg 800w,            /assets/resized/1400/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-3.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-model-a-serial-queue&quot;&gt;The Model: A Serial Queue&lt;/h2&gt;

&lt;p&gt;So the task handoff file got reshaped. It used to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TASK.md&lt;/code&gt;: singular, one task, overwrite it for the next one. Now it’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TASKS.md&lt;/code&gt;, and the active task is a &lt;strong&gt;serial queue of numbered pieces.&lt;/strong&gt; The builder works them top to bottom, in one pass, then stops and reports. Finished work doesn’t get overwritten and lost. It collapses into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;✅ Done&lt;/code&gt; archive with a stable tag, so the file carries its own history.&lt;/p&gt;

&lt;h2 id=&quot;two-ways-to-stack&quot;&gt;Two Ways to Stack&lt;/h2&gt;

&lt;p&gt;Because once the active task is a queue you can stack as deep as you want, two genuinely different working modes fall out of the exact same mechanism:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pacing.&lt;/strong&gt; Stack a couple of pieces. The builder grinds them while I plan the next batch a step ahead. By the time it stops, I’ve got the next chunk ready to go. This is the everyday rhythm, the overlap of machine-grind and human-thinking I’ve been describing the whole post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unattended.&lt;/strong&gt; Stack a &lt;em&gt;lot&lt;/em&gt; of pieces (an hour’s worth) and walk away entirely. Go do something else, something not-this-project, and come back to a pile of finished, tested work and one report. Same serial builder, same queue. The only difference is how deep I stack it and whether I’m in the room.&lt;/p&gt;

&lt;p&gt;They’re mechanically identical, but the unattended mode forced two rules that the pacing mode never exposed, because pacing rarely runs more than a piece or two before I’m back:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A blocked piece must not halt the queue.&lt;/strong&gt; If the builder hits piece 3 of 8 and it turns out underspecified (some fork I didn’t see), the old rule was “stop and report.” Fine when I’m sitting right there. Catastrophic when I’m gone for an hour, because pieces 4 through 8 never run even if they don’t depend on the broken one. So the rule is now: mark the blocked piece, &lt;em&gt;skip it,&lt;/em&gt; and keep going with anything that doesn’t depend on it. Halt only when nothing left can proceed. An hour away should come back with six of eight done, not two.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-4.jpg&quot; alt=&quot;Two Ways to Stack&quot; srcset=&quot;            /assets/resized/480/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-4.jpg 480w,            /assets/resized/800/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-4.jpg 800w,            /assets/resized/1400/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-4.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State gets logged on every stop.&lt;/strong&gt; This is the one that matters most for walking away. Whenever the builder stops, finished or blocked, it writes its state directly into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TASKS.md&lt;/code&gt;: which pieces are done, which are blocked and why, what’s left, where to resume. It flips a status box on each piece as it goes.&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gu&quot;&gt;## Design — pieces&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; [x] 1. Schema: declare required_artifacts on the brief
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; [x] 2. Writer produces the artifacts
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; [!] 3. Humanizer preserves them — BLOCKED: heading-protection
       order is ambiguous, needs a call
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; [x] 4. Checker verifies presence  (depends on #1)

&lt;span class=&quot;gu&quot;&gt;### ▶ Run state&lt;/span&gt;
3 of 4 done. #3 blocked on a design fork (see above). Resume there.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Why in the task file and not somewhere clever? Because that file is already what the builder is working in, it survives the session getting killed, and if I come back tomorrow having completely forgotten where I left off, the file tells me. No memory required, mine or the agent’s. The thing that makes unattended runs safe to walk away from is that every piece keeps the test suite green, so “done” actually means done, and the state log means “interrupted” never means “lost.”&lt;/p&gt;

&lt;h2 id=&quot;the-real-bottleneck-was-never-the-task-slot&quot;&gt;The Real Bottleneck Was Never the Task Slot&lt;/h2&gt;

&lt;p&gt;I’d assumed the constraint on keeping a builder fed was the single-task slot: one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TASK.md&lt;/code&gt;, one job at a time, obviously that’s the chokepoint. It isn’t. &lt;strong&gt;The real bottleneck is spec throughput.&lt;/strong&gt; The builder only stays fed if there’s a backlog of &lt;em&gt;fully-specified, mechanical&lt;/em&gt; tasks waiting for it. The moment a task hits a real design fork, a genuine “should it do A or B” that only I can answer, the queue stalls, no matter how clever the queue is.&lt;/p&gt;

&lt;p&gt;And pre-specifying that whole embedded-artifacts arc up front is what made this visible, because it told me exactly &lt;em&gt;where&lt;/em&gt; my specs leak. The verdict: pre-specifying nails &lt;strong&gt;structure&lt;/strong&gt; and leaks on &lt;strong&gt;judgment.&lt;/strong&gt; The file decomposition was right. The dependency order (A blocks the rest, B/C/D are independent) was right. What broke was subtler:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-5.jpg&quot; alt=&quot;The Real Bottleneck Was Never the Task Slot&quot; srcset=&quot;            /assets/resized/480/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-5.jpg 480w,            /assets/resized/800/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-5.jpg 800w,            /assets/resized/1400/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-5.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;One task rested on a &lt;strong&gt;wrong premise.&lt;/strong&gt; I’d specified the “diagram” artifact as something the pipeline could satisfy with an ASCII drawing. But my actual diagram practice is to render real images, with ASCII only as a fallback. That’s not a fork the builder could catch or resolve. It’s a wrong assumption baked into the spec, and only I could see it, because it lived in my head and not in the code.&lt;/li&gt;
  &lt;li&gt;A &lt;strong&gt;judgment call hid inside a “mechanical” task.&lt;/strong&gt; The artifact checker had to count distinct artifacts, and my supposedly airtight spec quietly let one image get counted twice toward the requirement. The builder implemented exactly what I wrote. What I wrote had a bug. I only caught it because I read the diff.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which is the callback to post one’s whole “trust but verify” spine, and it’s &lt;em&gt;more&lt;/em&gt; load-bearing in a pipeline, not less. The batch doesn’t skip verification. It removes the &lt;em&gt;round-trip with me between tasks,&lt;/em&gt; not the rigor. I still read every diff the builder actually wrote. Both of those bugs, the double-count and a separate one where a config value silently broke its file format, got caught at my review, not by the agents. The lesson for the queue is precise: a task is only “ready” when its &lt;em&gt;premises&lt;/em&gt; and its &lt;em&gt;judgment semantics&lt;/em&gt; are pinned, not just its files. Pinning the files is the easy 80%. The leak is always in the other 20%, and the other 20% is mine.&lt;/p&gt;

&lt;h2 id=&quot;the-name&quot;&gt;The Name&lt;/h2&gt;

&lt;p&gt;The seed of this post had a whole brainstorm in it about &lt;em&gt;finally&lt;/em&gt; renaming the skill. Its name describes one of the three things it does and I can never remember it. I had candidates: &lt;em&gt;planwright,&lt;/em&gt; for the one who authors plans, and &lt;em&gt;foreman,&lt;/em&gt; for the one who keeps the line moving and the builder fed. And given that this entire post is about keeping the line moving, &lt;em&gt;foreman&lt;/em&gt; was right there, practically gift-wrapped.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-6.jpg&quot; alt=&quot;The Name&quot; srcset=&quot;            /assets/resized/480/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-6.jpg 480w,            /assets/resized/800/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-6.jpg 800w,            /assets/resized/1400/the-bottleneck-was-me-how-i-stopped-racing-my-ai-b-body-6.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I did not rename it. I codified the whole convention, ported it into the skill, patched both projects, and left the dumb name exactly where it was. The rename is real work. It’s wired into three repos now, and I wasn’t going to fake-land it just to give this post a tidy bow. So the name is still wrong, &lt;em&gt;foreman&lt;/em&gt; is still leading, and it’ll get fixed when it gets fixed. Consider this the third post in a row where I’ve promised to rename the thing.&lt;/p&gt;

&lt;h2 id=&quot;the-honest-scope-note&quot;&gt;The Honest Scope Note&lt;/h2&gt;

&lt;p&gt;Every post gets one. Here’s this one’s: &lt;strong&gt;this is the frontier of the method, not a settled result.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The pacing-over-throughput call is fresh. I made it by running the throughput version, hating it, and reasoning backward, which is a strong signal but a sample size of basically one. The unattended mode, with its skip-and-continue and its state logging, is &lt;em&gt;built&lt;/em&gt; but barely road-tested; I haven’t actually walked away for a real hour and come back to judge what I found, and I’d bet the skip-and-continue logic has edge cases I haven’t hit. The “promote a recurring judgment into an automatic rule” idea from the last post is still unproven. And the deepest claim here, that spec throughput, not the task slot, is the true bottleneck, is a hypothesis I’ve confirmed exactly once.&lt;/p&gt;

&lt;p&gt;What I’m confident about is the shape of the mistake, because I made it cleanly: optimizing throughput when I wanted pacing is a real and seductive wrong turn, and “keep the builder busy” is exactly the kind of goal that leads you into it. The metric that’s easy to put on a dashboard, work per unit time, is not always the one you actually care about. Sometimes the gap is the product.&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next&lt;/h2&gt;

&lt;p&gt;I don’t know yet, and I’m not going to force a cliffhanger. The plan stays lean, the builder runs on a paced queue, and I can stack it shallow to work alongside it or deep to walk away from it. The pieces are in place. What I don’t have is a real verdict on the unattended mode under fire, or a clue whether the “spec throughput is the bottleneck” insight holds up across more than one feature arc. Those are the next things to actually live with rather than theorize about.&lt;/p&gt;

&lt;p&gt;There may be a post four. There may not. The method’s still moving, and I’d rather tell you what actually happened than what would make a clean ending. So far that’s served the series fine. We’ll see what the gap fills with.&lt;/p&gt;
</description>
        <pubDate>Wed, 22 Jul 2026 07:00:00 -0500</pubDate>
        <link>https://www.stephanmiller.com/the-bottleneck-was-me-how-i-stopped-racing-my-ai-builder-and-started-pacing-it/</link>
        <guid isPermaLink="true">https://www.stephanmiller.com/the-bottleneck-was-me-how-i-stopped-racing-my-ai-builder-and-started-pacing-it/</guid>
        
        <category>AI coding agents</category>
        
        <category>Sonnet agent</category>
        
        <category>PLAN.md methodology</category>
        
        <category>AI development workflow</category>
        
        <category>Agentic workflow optimization</category>
        
        
        <category>agentic-development</category>
        
      </item>
    
      <item>
        <title>Kimi K3 and Inkling: The Week the Open Models Won</title>
        <description>&lt;p&gt;Last week I signed off by saying I’d see you when Gemini 3.5 Pro and DeepSeek V4 had presumably set something on fire. Well. Gemini 3.5 Pro missed its launch date again, for the third time. DeepSeek V4 is quietly shipping with a deadline attached that’s going to ruin somebody’s Friday. And while the three biggest AI labs on the planet were busy being late, two models you can just download showed up out of nowhere. One of them is now the fourth-smartest model on Earth, ahead of Claude Opus 4.8, and it came from Moonshot, a lab most people couldn’t have picked out of a lineup a year ago.&lt;/p&gt;

&lt;p&gt;That’s the whole week. The frontier moved, and it didn’t move at OpenAI, Google, or Anthropic. It moved open.&lt;/p&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#the-open-frontier-crashed-the-party&quot; id=&quot;markdown-toc-the-open-frontier-crashed-the-party&quot;&gt;The Open Frontier Crashed the Party&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#kimi-k3-is-genuinely-smart-and-it-never-stops-thinking&quot; id=&quot;markdown-toc-kimi-k3-is-genuinely-smart-and-it-never-stops-thinking&quot;&gt;Kimi K3 Is Genuinely Smart and It Never Stops Thinking&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#inkling-mira-murati-gives-it-away&quot; id=&quot;markdown-toc-inkling-mira-murati-gives-it-away&quot;&gt;Inkling: Mira Murati Gives It Away&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#meanwhile-the-west-was-late-again&quot; id=&quot;markdown-toc-meanwhile-the-west-was-late-again&quot;&gt;Meanwhile, the West Was Late Again&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-cheapskate-picks&quot; id=&quot;markdown-toc-the-cheapskate-picks&quot;&gt;The Cheapskate Picks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#horror-stories-from-the-wild&quot; id=&quot;markdown-toc-horror-stories-from-the-wild&quot;&gt;Horror Stories From the Wild&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#whats-coming&quot; id=&quot;markdown-toc-whats-coming&quot;&gt;What’s Coming&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-takeaway&quot; id=&quot;markdown-toc-the-takeaway&quot;&gt;The Takeaway&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-open-frontier-crashed-the-party&quot;&gt;The Open Frontier Crashed the Party&lt;/h2&gt;

&lt;p&gt;Here’s the setup you need. For most of this year, the “open weights are catching up” story has been a Chinese story. DeepSeek, Qwen, GLM, MiMo. Good models you could download, consistently a few points behind the closed Western flagships, consistently way cheaper. The pattern was reliable enough to be boring.&lt;/p&gt;

&lt;p&gt;This week two things happened in a 48-hour window that broke the pattern.&lt;/p&gt;

&lt;p&gt;On July 15th, Thinking Machines Lab shipped Inkling, a 975-billion-parameter open-weights model, under an Apache 2.0 license, on Hugging Face, right now, today. On July 16th, Moonshot AI shipped Kimi K3, a 2.8-trillion-parameter monster that lands at number four on the Artificial Analysis Intelligence Index. Two frontier-class open (or opening) models from two labs that are not the big three, dropped back to back.&lt;/p&gt;

&lt;p&gt;On the Intelligence Index, Kimi K3 lands at 57.1, behind only Claude Fable 5 at 59.9 and GPT-5.6 Sol at 58.9, and ahead of Claude Opus 4.8 at 55.7. Read that again. An open-weight model from a Chinese lab is beating Anthropic’s own Opus 4.8 on raw intelligence. That is not “catching up.” That’s arrived.&lt;/p&gt;

&lt;h2 id=&quot;kimi-k3-is-genuinely-smart-and-it-never-stops-thinking&quot;&gt;Kimi K3 Is Genuinely Smart and It Never Stops Thinking&lt;/h2&gt;

&lt;p&gt;Let me tell you what makes Kimi K3 the headline and then tell you the part that’ll cost you money.&lt;/p&gt;

&lt;p&gt;The good part first. K3 is a 2.8-trillion-parameter mixture-of-experts model, which is the largest open-weight model anybody has announced. It only activates 16 of its 896 experts per token, so it’s big but not insane to run. It’s got a 1-million-token context window and it’s multimodal. The full weights are coming to Hugging Face by July 27th under a modified MIT license that lets you use it commercially.&lt;/p&gt;

&lt;p&gt;But the number that matters is Arena. Normally when a model launches, the Arena leaderboard takes a week or two to catch up, because Arena is vote-based and nobody’s voted on the new thing yet. New models are supposed to be invisible on Arena for a bit. Kimi K3 did not get that memo. Three days after launch it’s already in the top 10 of every category I track: Overall #8, Coding #9, Creative Writing #9, Instruction Following #10, Hard Prompts #10. On Arena data dated July 19th. Three days. That doesn’t happen unless a lot of people tried it and a lot of people liked what they saw.&lt;/p&gt;

&lt;p&gt;On cost-per-task, Artificial Analysis clocked it at about $0.94 to run one Intelligence Index task. That’s roughly half of Opus 4.8’s $1.80 for a model that scores higher on intelligence. On paper, that’s a steal.&lt;/p&gt;

&lt;p&gt;Now the part that’ll cost you money.&lt;/p&gt;

&lt;p&gt;K3 always thinks. There is no non-thinking variant. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reasoning_effort&lt;/code&gt; is locked to maximum, and every one of those reasoning tokens bills as output at $15 per million. Simon Willison ran his usual “generate an SVG of a pelican on a bicycle” test on launch day and the model burned 13,241 reasoning tokens before it produced a 3,417-token answer. His verdict on the pricing was blunt: “This is expensive. The pelican cost 25 cents.” One pelican. A quarter.&lt;/p&gt;

&lt;p&gt;So the cost-per-task number is real, but it’s an average, and the tail on that average is fat. The visible answer you get back is a fraction of what you actually pay for, because you’re renting the model’s internal monologue at output rates whether you want it or not. If you were burned by the whole cost-per-task lesson last week (Grok 4.5 winning on tokens-per-job while sitting fourth on intelligence), K3 is the same lesson wearing different clothes. The sticker says $3/$15. Your invoice will say something with more zeroes.&lt;/p&gt;

&lt;h2 id=&quot;inkling-mira-murati-gives-it-away&quot;&gt;Inkling: Mira Murati Gives It Away&lt;/h2&gt;

&lt;p&gt;The other open drop is the one that made me sit up, and not because of the benchmarks.&lt;/p&gt;

&lt;p&gt;Inkling comes from Thinking Machines Lab, which is Mira Murati’s outfit. If the name doesn’t ring a bell, she was OpenAI’s CTO. So this is a former top executive of the most closed, most commercial AI lab in the world shipping a 975-billion-parameter model on Hugging Face under Apache 2.0, framed explicitly around low cost and, in their words, “resistance to censorship.” You can legally fine-tune it, ship it in a product, and never pay Thinking Machines a cent.&lt;/p&gt;

&lt;p&gt;The specs are interesting. 975B total parameters, only 41B active per token, multimodal across text, images, and audio. It’s got a thinking-effort dial you can turn from 0.2 to 0.99, which is exactly the knob Kimi K3 refuses to give you. Want cheap and fast? Turn it down. Want it to grind? Turn it up. That’s the right design, and Moonshot should take notes.&lt;/p&gt;

&lt;p&gt;On the composite Intelligence Index, Inkling only scores 41, which is well down the board, so don’t expect it to beat Fable 5 in a general chat. But dig into the specific benchmarks and it’s a different story: 77.6% on SWE-bench Verified, 97.1% on AIME 2026 math, 87.2% on GPQA Diamond, and 74.1% on MCP Atlas for agentic workflows. Sebastian Raschka called it the best open multimodal generalist out there right now, and the category-level scores back that up. It’s not a great chatbot. It might be a great tool.&lt;/p&gt;

&lt;p&gt;Here’s why these two drops matter together. The “own your weights” argument used to be a China thing, and if you had opinions about running Chinese models in production, you could opt out of the whole conversation. You can’t anymore. When Mira Murati is handing out Apache-2.0 weights and Moonshot is shipping the biggest open model ever built, the choice in front of you isn’t “American closed model or Chinese open model.” It’s “rent from three labs, or own from everybody else.” That’s a genuinely different question than it was a month ago.&lt;/p&gt;

&lt;h2 id=&quot;meanwhile-the-west-was-late-again&quot;&gt;Meanwhile, the West Was Late Again&lt;/h2&gt;

&lt;p&gt;While all that was happening, the closed Western frontier did its now-familiar thing: it announced a date and then missed it.&lt;/p&gt;

&lt;p&gt;Gemini 3.5 Pro was targeting July 17th. That was already a slip from June, which was itself a slip from Google I/O in May. Google reportedly scrapped the base model entirely and rebuilt it after engineers found structural failures in recursive tool-calling and SVG generation. Ambitious. Also, the 17th came and went and it’s still limited to a handful of enterprise preview customers. No public API, no confirmed pricing, no confirmed 2-million-token context window, none of the rumored Deep Think reasoning layer you can actually touch. Third promised date, third miss. At this point I’m not writing another word about Gemini 3.5 Pro until there’s an endpoint I can hit with a real API key. It’s vapor until it isn’t.&lt;/p&gt;

&lt;p&gt;DeepSeek V4, on the other hand, is very real, and it comes with homework. The V4 family is graduating from preview to stable, and if you use DeepSeek’s hosted API, you have a hard deadline: July 24th at 15:59 UTC. After that, the old model names &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-chat&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-reasoner&lt;/code&gt; stop working. They start returning HTTP 404 and 400 errors. More on that in the horror section, because it’s nastier than it looks.&lt;/p&gt;

&lt;h2 id=&quot;the-cheapskate-picks&quot;&gt;The Cheapskate Picks&lt;/h2&gt;

&lt;p&gt;Okay. The part you can actually use.&lt;/p&gt;

&lt;p&gt;Same method as always. For each Arena category, I take the leader’s rating and find the cheapest model within 50 rating points of it. Arena’s top is compressed, so “cheapest in the band” is a real choice between models that are genuinely close, not settling for junk.&lt;/p&gt;

&lt;p&gt;And this week I have to own something, because I got it wrong the first time I ran these numbers. “Within 50 points” is a band defined by &lt;em&gt;points&lt;/em&gt;, not by rank, and I’d been reading down the first screen of the leaderboard and calling that the band. It is not the band. In Coding, the leader is Opus 4.7-thinking at 1553, which puts the cutoff at 1503 — and the leaderboard doesn’t drop below 1503 until &lt;strong&gt;rank 46&lt;/strong&gt;. Forty-six models are inside that window. I was sorting the first twenty and declaring a winner, which is exactly the mistake this section exists to stop &lt;em&gt;you&lt;/em&gt; from making. The bands run 44 deep in Overall, 39 in Hard Prompts, 27 in Instruction Following. Only Creative (14) and Math (6) actually fit on one screen.&lt;/p&gt;

&lt;p&gt;Fix the band, and the answer changes in four of six categories. Arena data below is dated July 19th. Fable 5 leaders run about $50 per million output tokens; Opus-thinking leaders about $25.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Category&lt;/th&gt;
      &lt;th&gt;Leader&lt;/th&gt;
      &lt;th&gt;$ out&lt;/th&gt;
      &lt;th&gt;Cheapskate pick&lt;/th&gt;
      &lt;th&gt;$ out&lt;/th&gt;
      &lt;th&gt;Δ rating&lt;/th&gt;
      &lt;th&gt;Cheaper by&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Overall&lt;/td&gt;
      &lt;td&gt;Fable 5 (1507)&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;MiMo v2.5 Pro (1466, #33)&lt;/td&gt;
      &lt;td&gt;$0.87&lt;/td&gt;
      &lt;td&gt;−41&lt;/td&gt;
      &lt;td&gt;~57x&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Coding&lt;/td&gt;
      &lt;td&gt;Opus 4.7-thinking (1553)&lt;/td&gt;
      &lt;td&gt;~$25&lt;/td&gt;
      &lt;td&gt;MiMo v2.5 Pro (1519, #23)&lt;/td&gt;
      &lt;td&gt;$0.87&lt;/td&gt;
      &lt;td&gt;−34&lt;/td&gt;
      &lt;td&gt;~29x&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Creative&lt;/td&gt;
      &lt;td&gt;Fable 5 (1513)&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;Gemini 3.5 Flash (1467, #11)&lt;/td&gt;
      &lt;td&gt;$9&lt;/td&gt;
      &lt;td&gt;−46&lt;/td&gt;
      &lt;td&gt;~5.6x&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Instruction Following&lt;/td&gt;
      &lt;td&gt;Fable 5 (1513)&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;MiMo v2.5 Pro (1470, #19)&lt;/td&gt;
      &lt;td&gt;$0.87&lt;/td&gt;
      &lt;td&gt;−43&lt;/td&gt;
      &lt;td&gt;~57x&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Hard Prompts&lt;/td&gt;
      &lt;td&gt;Fable 5 (1533)&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;MiMo v2.5 Pro (1494, #22)&lt;/td&gt;
      &lt;td&gt;$0.87&lt;/td&gt;
      &lt;td&gt;−39&lt;/td&gt;
      &lt;td&gt;~57x&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Math&lt;/td&gt;
      &lt;td&gt;Fable 5 (1550)&lt;/td&gt;
      &lt;td&gt;$50&lt;/td&gt;
      &lt;td&gt;Grok 4.5 (1504, #5)&lt;/td&gt;
      &lt;td&gt;$6&lt;/td&gt;
      &lt;td&gt;−46&lt;/td&gt;
      &lt;td&gt;~8.3x&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;So the value story of the week is Xiaomi’s MiMo v2.5 Pro at $0.43 in / $0.87 out, sweeping four of six categories. Not narrowly, either. On Coding it sits 34 points off the best coding model in the world at &lt;strong&gt;a twenty-ninth of the output price&lt;/strong&gt;, and it’s been sitting there with 11,355 votes behind that rating — this is not a preliminary number on a model that dropped Tuesday. It shipped in April. It’s MIT-licensed open weights. In a week whose headline is “the open models won,” the cheapest competitive model on four separate leaderboards turning out to be a phone company’s MIT-licensed side project isn’t a coincidence. It’s the same story from a different angle.&lt;/p&gt;

&lt;p&gt;Two honest caveats, because a 57x price gap deserves scrutiny.&lt;/p&gt;

&lt;p&gt;First, Artificial Analysis does &lt;em&gt;not&lt;/em&gt; rank MiMo v2.5 Pro near the top — it scores 42 on the Intelligence Index, against Kimi K3’s 57.1. That’s the classic Arena-loves-it/AA-doesn’t split, and it means what it usually means: people &lt;em&gt;prefer&lt;/em&gt; MiMo’s answers head-to-head, but it isn’t doing frontier-grade reasoning on the hard stuff. For everyday coding, instruction-following, and general work, preference is the metric that matches how you’ll actually use it. For genuinely hard problems, pay up.&lt;/p&gt;

&lt;p&gt;Second, it’s slow. 58.2 output tokens per second, below median for its class. If you’re running an agent loop where latency compounds across hundreds of calls, that 57x price advantage buys you a wall-clock penalty you should measure before you commit.&lt;/p&gt;

&lt;p&gt;Two runners-up worth knowing. If your workload is input-heavy or long-context, Qwen3.7 Plus is cheaper on the input side at $0.32 in / $1.28 out and sits inside the Coding band at #36. And last week’s champion, Meta’s Muse Spark 1.1 at $1.25 / $4.25, is still competitive on rating — but it’s now about 5x more expensive than MiMo &lt;em&gt;and&lt;/em&gt; it’s geo-locked to US developers on OpenRouter, so it falls out of the recommendation twice over. More on that below.&lt;/p&gt;

&lt;p&gt;Kimi K3 is right there in the Coding band too at #9, but at $15 output with that always-on thinking tax, it is not the cheapskate answer. It’s the “I want the best open model and I’ll pay for it” answer.&lt;/p&gt;

&lt;p&gt;Math is the fun one this week, and it’s the one category where the band really is tiny — six models, top to bottom. The pure cheapskate pick is Grok 4.5 at $6 output, sitting at #5, cheapest thing in the band. But look one row up: Gemini 3.5 Flash is at #3 on Math, 1518, only 32 points behind Fable 5, for $9. For the third or fourth week running, Gemini 3.5 Flash is quietly the smart-money answer for math and creative work. If you’re paying Fable 5’s $50 to do math and Flash is sitting 32 points back at a fifth of the price, you’re not buying quality, you’re buying a rating difference smaller than the noise in the measurement.&lt;/p&gt;

&lt;p&gt;Also worth flagging: several of these Fable 5 category-leader ratings are sitting on thin vote counts (Math #1 has under 500 votes). Don’t over-trust a fresh #1 with that little data behind it.&lt;/p&gt;

&lt;h2 id=&quot;horror-stories-from-the-wild&quot;&gt;Horror Stories From the Wild&lt;/h2&gt;

&lt;p&gt;Every roundup needs the part where I tell you what’s going to ruin your day. This week there are three, and one of them has a countdown clock.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The DeepSeek migration cliff.&lt;/strong&gt; July 24th, 15:59 UTC. If you’ve got &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-chat&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-reasoner&lt;/code&gt; hard-coded anywhere in your codebase, those names get retired and start returning 404 and 400 errors. Here’s the sneaky part: both of those names &lt;em&gt;already&lt;/em&gt; route to DeepSeek-V4-Flash under the hood, and have since April. So nothing looks broken today. Your code works fine right up until next Friday afternoon, when it doesn’t. And the fix isn’t a clean find-and-replace, because thinking mode moved from being its own model name to being a request parameter. If you naively swap &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-reasoner&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deepseek-v4-flash&lt;/code&gt; and call it done, you’ll silently drop reasoning on all that traffic and wonder why your outputs got dumber. Go patch this now, not on the 24th.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kimi K3’s metered brain.&lt;/strong&gt; I already covered this up top, but it belongs in the horror section on principle. There is no way to turn K3’s thinking off. Every request pays for a full reasoning trace at $15 per million output tokens, whether the question needed it or not. Simon Willison’s pelican cost 25 cents. Scale that across an agent loop making thousands of calls and the “half the cost of Opus” headline evaporates fast. Contrast it with Inkling shipping a thinking-effort dial the same week, and K3’s design choice looks less like a feature and more like a billing strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The value pick you’re locked out of.&lt;/strong&gt; Meta shipped the cheapest competitive brand-name model of the week and then restricted it to US developers on OpenRouter. Muse Spark 1.1 was last week’s cheapskate champion in three categories, and for most of the planet it’s just a leaderboard entry you get to look at. Cool. Very open. Very connected world we live in. It got dethroned on price this week anyway, which is its own kind of answer: the model you &lt;em&gt;can&lt;/em&gt; buy from anywhere is 5x cheaper and ships its weights.&lt;/p&gt;

&lt;h2 id=&quot;whats-coming&quot;&gt;What’s Coming&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Kimi K3 open weights&lt;/strong&gt; land on Hugging Face by July 27th, modified MIT license. This is the one to actually wait for if you want to own it instead of renting the API.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Gemini 3.5 Pro&lt;/strong&gt;, allegedly, eventually. Missed July 17th. I’ll believe it when I can curl it.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DeepSeek V4&lt;/strong&gt; graduates preview to stable, with that mandatory API migration deadline on July 24th. Set a reminder.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Inkling derivatives.&lt;/strong&gt; Apache 2.0 weights are already out, so expect fine-tunes and specialized variants to start showing up fast. That’s the whole point of shipping it open.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the background hum, unchanged and getting louder: Chinese-origin models are now about 46% of all OpenRouter tokens, and as of July 20th they hit a record 58% share among US firms specifically. US labs have fallen from roughly 70% of token volume to 30% year over year. Anthropic’s Claude slid from 29% to 13%. DeepSeek alone is 17.6%, the single largest vendor on the platform, with Qwen right behind. Two more open flagships this week did not slow that trend. They poured gas on it.&lt;/p&gt;

&lt;h2 id=&quot;the-takeaway&quot;&gt;The Takeaway&lt;/h2&gt;

&lt;p&gt;The intelligence race at the very top is still basically a tie: Fable 5, GPT-5.6 Sol, Kimi K3, Opus 4.8, all inside four points. But the interesting thing this week wasn’t who’s smartest. It was who’s &lt;em&gt;ownable&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For the first time, the answer to “I want a near-frontier model I can actually hold in my hands” isn’t a compromise. Kimi K3 is fourth on the whole intelligence board and its weights ship in a week. Inkling is out right now under a license that lets you do whatever you want with it. The former CTO of OpenAI is handing out model weights. Meanwhile the three labs whose whole pitch is “trust us, it’s on our servers” spent the week being late, geo-locking their cheap model, and metering your reasoning tokens.&lt;/p&gt;

&lt;p&gt;So here’s what I’m actually doing. I’m patching my DeepSeek model names before Friday, because I’m not getting caught by a 404 on a Friday. I’m keeping Gemini 3.5 Flash on math and creative, because paying 5x more for a rating rounding error is still stupid this week. I’m moving my bulk coding and instruction-following traffic to MiMo v2.5 Pro and eating the latency, because 29x is not a margin you argue with. I’m waiting the seven days for Kimi K3’s weights before I decide whether it’s worth the thinking tax, because owning it changes the math. And I’m downloading Inkling this weekend just to see what a 975-billion-parameter model does on my own hardware, because I can, and a month ago I couldn’t.&lt;/p&gt;

&lt;p&gt;Rent everything, own nothing was the mood in June. In July the challengers handed out the keys. Read your bills, and maybe download a frontier model while it’s free. See you next week, when Gemini 3.5 Pro has presumably missed a fourth date.&lt;/p&gt;
</description>
        <pubDate>Tue, 21 Jul 2026 08:00:00 -0500</pubDate>
        <link>https://www.stephanmiller.com/model-buzz-roundup-week-of-0715/</link>
        <guid isPermaLink="true">https://www.stephanmiller.com/model-buzz-roundup-week-of-0715/</guid>
        
        <category>llm</category>
        
        <category>openrouter</category>
        
        <category>model-roundup</category>
        
        
        <category>large-language-models</category>
        
      </item>
    
      <item>
        <title>Planning Is Cheaper Than Coding, and My Own Logs Proved Me Wrong About Why</title>
        <description>&lt;p&gt;I went into this post sure of one thing: coding with an agent burns tokens like a house fire, and planning is the cheap part where you just talk. I’ve &lt;em&gt;felt&lt;/em&gt; it. You watch the agent grep twenty files, read half of them, figure out what it already built, then start writing, and the usage bar just keeps moving forward. Planning, by comparison, is me and Opus talking for three hours and barely denting the budget. Obvious, right?&lt;/p&gt;

&lt;p&gt;So I did the thing I should always do before I put a claim in writing. I looked at a month of my own Claude Code session logs across two projects.&lt;/p&gt;

&lt;p&gt;The meter came back flat. Coding and planning cost about the same to run. I was wrong about &lt;em&gt;why&lt;/em&gt; coding is expensive.&lt;/p&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#the-slogan-and-the-hole-in-it&quot; id=&quot;markdown-toc-the-slogan-and-the-hole-in-it&quot;&gt;The Slogan, and the Hole in It&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#what-the-meter-actually-says&quot; id=&quot;markdown-toc-what-the-meter-actually-says&quot;&gt;What the Meter Actually Says&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-expensive-kind-of-cheap&quot; id=&quot;markdown-toc-the-expensive-kind-of-cheap&quot;&gt;The Expensive Kind of Cheap&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#and-planning-is-dense&quot; id=&quot;markdown-toc-and-planning-is-dense&quot;&gt;And Planning Is Dense&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#even-the-prototype-gets-a-plan&quot; id=&quot;markdown-toc-even-the-prototype-gets-a-plan&quot;&gt;Even the Prototype Gets a Plan&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#my-freeform-rhythm&quot; id=&quot;markdown-toc-my-freeform-rhythm&quot;&gt;My Freeform Rhythm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#planning-is-also-how-i-learn-the-thing&quot; id=&quot;markdown-toc-planning-is-also-how-i-learn-the-thing&quot;&gt;Planning Is Also How I Learn the Thing&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#so-cheap-compared-to-what&quot; id=&quot;markdown-toc-so-cheap-compared-to-what&quot;&gt;So, Cheap Compared to What&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-slogan-and-the-hole-in-it&quot;&gt;The Slogan, and the Hole in It&lt;/h2&gt;

&lt;p&gt;The line I started with is “planning is cheap, coding is not.” I still believe it. But there’s a hole in it and I’d rather stab it myself than let a commenter do it.&lt;/p&gt;

&lt;p&gt;Here’s the hole: &lt;strong&gt;agents made code fast.&lt;/strong&gt; The whole selling point is that you describe a thing and the machine types it out in a minute. If typing is free now, in what sense is coding “not cheap”? A skeptic reads the title and closes the tab, because on its face the tool that generates 2,000 lines while you get coffee is the &lt;em&gt;cheapest&lt;/em&gt; thing in the whole stack.&lt;/p&gt;

&lt;p&gt;I couldn’t answer that cleanly, which usually means I don’t understand my own point yet. So instead of arguing from vibes, I went and measured.&lt;/p&gt;

&lt;h2 id=&quot;what-the-meter-actually-says&quot;&gt;What the Meter Actually Says&lt;/h2&gt;

&lt;p&gt;Two projects. Both ones I had genuinely &lt;em&gt;no idea how to build&lt;/em&gt; when I started. Which is the whole reason they’re useful here. One is a &lt;a href=&quot;https://www.stephanmiller.com/the-living-plan-got-fat-compacting-a-doc-that-wont-stop-growing/&quot;&gt;content pipeline&lt;/a&gt;. The other is a knowledge-graph site I’ve written about &lt;a href=&quot;https://www.stephanmiller.com/the-third-attempt-how-a-living-plan-beat-both-vibe-coding-and-spec-kit/&quot;&gt;before&lt;/a&gt;. Different domains, different stacks, both explored more or less blind.&lt;/p&gt;

&lt;p&gt;I parsed every session’s log and split each of the agent’s turns into two buckets: &lt;strong&gt;conversation turns&lt;/strong&gt; (the agent replied with text and touched nothing) and &lt;strong&gt;tool-action turns&lt;/strong&gt; (it ran a command, read, edited, or wrote a file). It’s not a clean planning-vs-coding line (the agent talks during a build and reads files during planning), but across a month it’s a fair read on where the time and tokens go.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/planning-is-cheap-coding-is-not-and-my-own-logs-pr-body-1.jpg&quot; alt=&quot;What the Meter Actually Says&quot; srcset=&quot;            /assets/resized/480/planning-is-cheap-coding-is-not-and-my-own-logs-pr-body-1.jpg 480w,            /assets/resized/800/planning-is-cheap-coding-is-not-and-my-own-logs-pr-body-1.jpg 800w,            /assets/resized/1400/planning-is-cheap-coding-is-not-and-my-own-logs-pr-body-1.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;Content pipeline&lt;/th&gt;
      &lt;th&gt;Knowledge-graph site&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Sessions (about one month)&lt;/td&gt;
      &lt;td&gt;22&lt;/td&gt;
      &lt;td&gt;14&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Conversation vs tool-action turns&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;59% / 41%&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;59% / 41%&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Output tokens (talk vs build)&lt;/td&gt;
      &lt;td&gt;65% / 35%&lt;/td&gt;
      &lt;td&gt;61% / 39%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tokens &lt;em&gt;per turn&lt;/em&gt; (talk vs build)&lt;/td&gt;
      &lt;td&gt;~100K vs ~98K&lt;/td&gt;
      &lt;td&gt;~119K vs ~122K&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Two things fell out of this, and one of them is the whole post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First: both projects landed on the exact same split.&lt;/strong&gt; Fifty-nine percent conversation, forty-one percent building. Two unrelated codebases, two different domains, both started from “I don’t know what the fuck I’m doing,” and I independently spent about sixty percent of my turns just &lt;em&gt;deciding&lt;/em&gt;. I didn’t plan that symmetry. It’s just what working in unknown territory costs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second, and this is where I lied to myself: the per-turn token cost is basically flat.&lt;/strong&gt; On the content pipeline, a conversation turn and a tool-action turn cost within about three percent of each other. Same story on the other project. Coding doesn’t burn more tokens than talking. It just &lt;em&gt;feels&lt;/em&gt; like it does, because you sit there watching it work.&lt;/p&gt;

&lt;p&gt;The reason is boring and it’s caching. I plan on a million-token context window, and every single turn, whether the agent is writing a paragraph of reasoning or grepping the repo, re-reads roughly the same enormous cached context. The dominant cost per turn is &lt;em&gt;the size of the context&lt;/em&gt;, not the activity inside the turn. Reading a cached window is cheap per token, but there’s a mountain of it, and it gets re-read on every message. Planning quietly pays that toll on every back-and-forth and hides it, because nothing visible is happening. Coding pays the same toll and shows you a progress bar, so you blame the progress bar.&lt;/p&gt;

&lt;p&gt;So “coding burns more tokens” is just false, at least for how I work. Good. Now I have to figure out what I actually meant.&lt;/p&gt;

&lt;h2 id=&quot;the-expensive-kind-of-cheap&quot;&gt;The Expensive Kind of Cheap&lt;/h2&gt;

&lt;p&gt;Here’s what I meant, once the data forced me to say it properly:&lt;/p&gt;

&lt;p&gt;Planning and coding cost about the same to &lt;em&gt;run&lt;/em&gt;. What’s wildly different is the cost of being &lt;strong&gt;wrong&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A wrong decision while planning costs one edited sentence. I write “we’ll use X,” I talk it through, I realize X is dumb, I change the sentence to “we’ll use Y.” Done. The blast radius is a paragraph.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;same&lt;/em&gt; wrong decision, once it’s code, costs a refactor. Or a dead end. Or a start-over. Because the agent didn’t just write the line that encodes the decision. It wrote the four modules downstream that assume it, the tests that lock it in, the data shapes that depend on it. Agents didn’t make coding cheap. They made &lt;em&gt;typing&lt;/em&gt; cheap, which is a different thing, and worse in a specific way: they make your wrong assumptions reality faster and in greater volume than you ever could by hand. By the time you notice the assumption was wrong, it’s load-bearing in a thousand lines.&lt;/p&gt;

&lt;p&gt;That’s the real asymmetry. Not tokens. &lt;strong&gt;Reversibility.&lt;/strong&gt; Prose is cheap to be wrong in because it’s cheap to change. Code is expensive to be wrong in because everything else is stacked on top of it. Planning is cheap because you can throw it away for free. Coding is expensive because you mostly can’t.&lt;/p&gt;

&lt;p&gt;And I have the scar tissue to prove it. Of the &lt;a href=&quot;https://www.stephanmiller.com/the-great-vibe-coding-experiment/&quot;&gt;first fifteen-or-so projects I built with AI&lt;/a&gt;, something like half either got completely refactored or thrown out and restarted from scratch. I &lt;a href=&quot;https://www.stephanmiller.com/i-burned-out-on-vibe-coding-came-back-and-rewrote-everything/&quot;&gt;burned out on the whole approach once&lt;/a&gt; and the lesson that came out the other side was, essentially: I had to plan more. Every one of those rewrites was a wrong decision I’d committed to code instead of catching in a sentence.&lt;/p&gt;

&lt;p&gt;The cleanest example is a choice I &lt;em&gt;didn’t&lt;/em&gt; pay full price for. On the content pipeline, this was my first real jump into agentic development: building workflows, not just pointing a coding agent at a repo. I’d done my own reading for a while and my instinct was the LangGraph / LangChain family. It’s what everyone reaches for. But before I committed, I spent planning sessions researching it with the agent and testing a couple of open-source projects built on it. In my testing the tokens just &lt;em&gt;evaporated&lt;/em&gt;. Gone, nothing to show. Pair that with a pile of horror stories from people running those frameworks in anger, and I bailed. Landed on &lt;a href=&quot;https://pydantic.dev/docs/ai/graph/graph/&quot;&gt;Pydantic Graph&lt;/a&gt; instead and it’s working well. And I can look at the code and know how it works.&lt;/p&gt;

&lt;p&gt;Notice where that decision happened. In research and planning. Cost: a few conversations and a couple of throwaway test runs. If I’d made that call the vibe way (pick LangChain because it’s the default, build three weeks on it, &lt;em&gt;then&lt;/em&gt; discover the token hole), that’s not a conversation. That’s a rewrite. Same wrong turn, two completely different bills, and the only variable was whether I found out in prose or in code.&lt;/p&gt;

&lt;h2 id=&quot;and-planning-is-dense&quot;&gt;And Planning Is Dense&lt;/h2&gt;

&lt;p&gt;There’s a second thing the meter doesn’t catch, and it cuts the same direction. My split, 59% talking and 41% building, counts &lt;em&gt;effort&lt;/em&gt;. It says nothing about &lt;em&gt;yield&lt;/em&gt;, and the yield is lopsided as hell.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/planning-is-cheap-coding-is-not-and-my-own-logs-pr-body-3.jpg&quot; alt=&quot;And Planning Is Dense&quot; srcset=&quot;            /assets/resized/480/planning-is-cheap-coding-is-not-and-my-own-logs-pr-body-3.jpg 480w,            /assets/resized/800/planning-is-cheap-coding-is-not-and-my-own-logs-pr-body-3.jpg 800w,            /assets/resized/1400/planning-is-cheap-coding-is-not-and-my-own-logs-pr-body-3.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Fifteen minutes of planning doesn’t buy fifteen minutes of building. It can buy an &lt;em&gt;hour&lt;/em&gt;. A clear decision, a couple of constraints, a handoff to the agent, and it goes and runs with all of it while I do something else. Planning is dense. A little of it aims a lot of building.&lt;/p&gt;

&lt;p&gt;Which is the reversibility point again, from the other end. That same dense fifteen minutes, if the decision underneath it is wrong, doesn’t cost you fifteen minutes back. It fans out into the whole hour that got stacked on top of it. Leverage runs both ways. A good plan multiplies what you build; a bad one multiplies what you rewrite. The denser the planning, the more each decision is worth getting right while it’s still just a sentence.&lt;/p&gt;

&lt;h2 id=&quot;even-the-prototype-gets-a-plan&quot;&gt;Even the Prototype Gets a Plan&lt;/h2&gt;

&lt;p&gt;The obvious objection: “Fine, but prototypes are &lt;em&gt;throwaway&lt;/em&gt;. The whole point is to build junk fast and learn from it. Planning a prototype is like drawing blueprints for a sandcastle.”&lt;/p&gt;

&lt;p&gt;I used to believe that. I don’t anymore, and it’s the same reversibility argument.&lt;/p&gt;

&lt;p&gt;A prototype with no plan doesn’t actually test anything. It just generates code that &lt;em&gt;looks&lt;/em&gt; like it works, which is the single most expensive output there is, because it lies to you convincingly. If you can’t say what question the prototype is supposed to answer, you haven’t built an experiment. You’ve built a thing that runs.&lt;/p&gt;

&lt;p&gt;Planning a prototype doesn’t mean a spec. It means one honest sentence: &lt;em&gt;what am I actually trying to find out here?&lt;/em&gt; Does this framework survive my token budget? Does this data shape hold up when the input gets weird? Can this feature even do the thing before I build the other five around it? That’s the plan. It’s cheap (cheaper than the prototype), and it’s the difference between a prototype that de-risks the project and one that just adds a codebase you’ll abandon.&lt;/p&gt;

&lt;p&gt;The stakes go &lt;em&gt;up&lt;/em&gt; in unknown territory, not down. When you already know the domain, you can afford to skip ahead, because your gut is a decent planner. When you don’t know the domain (which is where I live now, on purpose), the plan is the only thing standing between you and confidently building the wrong thing very fast.&lt;/p&gt;

&lt;h2 id=&quot;my-freeform-rhythm&quot;&gt;My Freeform Rhythm&lt;/h2&gt;

&lt;p&gt;None of this means I plan the whole thing up front and then march. I never have. My process, long before AI, was tracer bullets with the safety off.&lt;/p&gt;

&lt;p&gt;Back when I built scrapers (and I built a &lt;em&gt;lot&lt;/em&gt; of scrapers), I’d start with a command-line app that did the one core thing. Does it actually pull the data? Yes? Okay. Then maybe a little Electron UI to wrap it. I had a vague idea of the architecture I wanted, but I’d build it up, change it, and refactor mid-stream constantly, because I wanted to &lt;em&gt;see the result&lt;/em&gt;. That’s the honest core of it: I’m a creator and a builder more than a technologist. Code, AI, tools: those are how I make things, not the thing I love. I jump toward the result.&lt;/p&gt;

&lt;p&gt;The AI version of this is the same shape. I get one feature working &lt;em&gt;really&lt;/em&gt; well (not “it runs,” but “it does what I actually want as the end user”), and then I jump. Right now the article-writing pipeline is about 75% of the features I want, and I’ve hit the part I’ll admit out loud is boring. Nothing new is going to surprise me in the last 25%. There’s no “whoa, that’s cool” left in it, just grind. And I can grind, but there’s a timer on how long before I need something interesting again.&lt;/p&gt;

&lt;p&gt;So I’m jumping to the novel-writing feature, because &lt;em&gt;that’s&lt;/em&gt; going to be interesting for a while. The rest of the article pipeline goes on the back burner until I’m in grind mode again. One rule I don’t break, though: I’d rather leave a feature &lt;strong&gt;incomplete&lt;/strong&gt; than ship one that isn’t what I want. I test each one as the actual end user (not “does it run,” but “would I be annoyed using this”) because I’ve learned the hard way that assuming a feature is right and backtracking later is exactly the expensive-code problem that is the point of this post. Incomplete is free. Wrong is a refactor.&lt;/p&gt;

&lt;p&gt;Yeah, this probably means a pileup at the end, where everything I put off comes due at once and it’s grind mode for days. I’m aware. But that’s for the Stephan of tomorrow. He is much more patient than the Stephan of today…I tell myself.&lt;/p&gt;

&lt;h2 id=&quot;planning-is-also-how-i-learn-the-thing&quot;&gt;Planning Is Also How I Learn the Thing&lt;/h2&gt;

&lt;p&gt;There’s one more reason planning earns its 59%, and it’s not on any token report.&lt;/p&gt;

&lt;p&gt;I’m learning these domains &lt;em&gt;while&lt;/em&gt; I plan them. I don’t know Pydantic Graph cold. I’m learning it as I go. I’m learning how graphify’s guts work slowly, session by session, on the other project. A big chunk of what looks like “planning” is really the agent teaching me the terrain before I commit to a route through it. Every back-and-forth where it explains why a graph approach beats a chunked one, or what a framework’s failure mode is, is a decision I now get to make with my eyes open instead of discovering the map by driving off the cliff.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2026/planning-is-cheap-coding-is-not-and-my-own-logs-pr-body-5.jpg&quot; alt=&quot;Planning Is Also How I Learn the Thing&quot; srcset=&quot;            /assets/resized/480/planning-is-cheap-coding-is-not-and-my-own-logs-pr-body-5.jpg 480w,            /assets/resized/800/planning-is-cheap-coding-is-not-and-my-own-logs-pr-body-5.jpg 800w,            /assets/resized/1400/planning-is-cheap-coding-is-not-and-my-own-logs-pr-body-5.jpg 1400w,    &quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And that learning compounds into things I couldn’t have specced on day one. Enough sessions poking at graphify taught me its node-and-edge model. Well enough that when I wanted my whole Obsidian vault in a graph, the agent didn’t just charge ahead and it didn’t flat refuse either. It made a reasoned call: pointing graphify at all ~2,400 notes in one shot wasn’t worth the grind, here’s why. So on a different project I had it &lt;a href=&quot;https://www.stephanmiller.com/i-got-tired-of-ai-memory-hype-so-i-built-a-context-lake/&quot;&gt;build a custom connector&lt;/a&gt; instead, one that pulls every note’s folder, tags, and wikilinks out as structured facts, the exact raw material a graph turns into edges. I couldn’t have asked for that connector, or understood why the agent was right to talk me out of the brute-force version, before graphify taught me what a graph actually wants. The planning didn’t just produce decisions; it produced a version of me who knew enough to ask for the right thing.&lt;/p&gt;

&lt;p&gt;Which is exactly why I never use plan mode. The official one, the structured feature: I don’t touch it, not for anything open-ended. It collapses the conversation into multiple choice. Pick A, B, or C. And when a decision is still half-formed, the options are never quite the thing in my head. I end up arguing with the menu instead of thinking. I want the back-and-forth: ask a question, get an answer, push on it, change my mind three exchanges in, &lt;em&gt;then&lt;/em&gt; decide. That messy conversation is what has to happen. It’s where the learning lives, and it’s where the cheap decisions get made before they turn into expensive code. I wrote up the actual machinery I use instead (one living plan doc, numbered decisions, the whole system) in the &lt;a href=&quot;https://www.stephanmiller.com/the-third-attempt-how-a-living-plan-beat-both-vibe-coding-and-spec-kit/&quot;&gt;living-plan post&lt;/a&gt;, so I won’t rerun it here.&lt;/p&gt;

&lt;h2 id=&quot;so-cheap-compared-to-what&quot;&gt;So, Cheap Compared to What&lt;/h2&gt;

&lt;p&gt;I’m not here to tell you you’re doing it wrong. I genuinely don’t care if the vibe-coder down the street thinks planning is for cowards. Live and let live. Or live and mortgage your house to cover your coding bill, your call. Some of the best things I’ve built started as pure “just build it and see.” Prototyping to figure out how something even works is real and I do it constantly.&lt;/p&gt;

&lt;p&gt;But I pulled my own numbers hoping to prove coding was the expensive part, and the meter told me the truth instead: it costs about the same as talking. The expense was never in the tokens. It’s in the concrete. A wrong sentence is free to fix. A wrong foundation is a rewrite, and the agent will happily pour you a bigger one, faster, than you could ever pour yourself.&lt;/p&gt;

&lt;p&gt;So plan the thing. Plan the prototype, even. Especially the prototype. Not because planning is virtuous. Because it’s the only place left where being wrong is still cheap. Unless you’re a millionaire, of course, but for us working stiffs, coding still costs real money.&lt;/p&gt;
</description>
        <pubDate>Wed, 15 Jul 2026 07:00:00 -0500</pubDate>
        <link>https://www.stephanmiller.com/planning-is-cheap-coding-is-not-and-my-own-logs-proved-me-wrong-about-why/</link>
        <guid isPermaLink="true">https://www.stephanmiller.com/planning-is-cheap-coding-is-not-and-my-own-logs-proved-me-wrong-about-why/</guid>
        
        <category>LLM cost analysis</category>
        
        <category>Claude Code usage</category>
        
        <category>Agent token costs</category>
        
        <category>Planning vs coding costs</category>
        
        <category>AI agent efficiency</category>
        
        <category>Token usage data</category>
        
        
        <category>agentic-development</category>
        
      </item>
    
  </channel>
</rss>
