<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stephan Miller</title>
    <description>The latest articles on DEV Community by Stephan Miller (@eristoddle).</description>
    <link>https://dev.to/eristoddle</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F18795%2F5f6c41b8-6033-4887-937a-2ebdfe623d2e.jpeg</url>
      <title>DEV Community: Stephan Miller</title>
      <link>https://dev.to/eristoddle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eristoddle"/>
    <language>en</language>
    <item>
      <title>Remotely Save for Obsidian: S3 and WebDAV Sync That Costs $0 on R2</title>
      <dc:creator>Stephan Miller</dc:creator>
      <pubDate>Wed, 21 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/eristoddle/remotely-save-for-obsidian-s3-and-webdav-sync-that-costs-0-on-r2-1gfh</link>
      <guid>https://dev.to/eristoddle/remotely-save-for-obsidian-s3-and-webdav-sync-that-costs-0-on-r2-1gfh</guid>
      <description>&lt;p&gt;I’ve used Remotely Save to sync Obsidian to my phone and iPad since the first week I started using Obsidian. I told it to use Dropbox, it worked, and I didn’t think about it. That’s the greatest praise you can give a sync plugin.&lt;/p&gt;

&lt;p&gt;Then I started to write this post and checked the changelog. The latest release is 0.5.25, from October 20, 2024. The last commit to the repo is from November 2024. It has 2.3 million downloads and over 200 open issues. So before we start with buckets and endpoints, just know that you’re putting a two year frozen plugin on your system. I covered the plugin briefly in my &lt;a href="https://dev.to/eristoddle/how-to-sync-obsidian-across-all-your-devices-including-free-methods-1mi5"&gt;guide to syncing an Obsidian vault across devices&lt;/a&gt;. This is the long version of the part that guide skipped: pointing it at storage you own.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is Remotely Save Dead?&lt;/li&gt;
&lt;li&gt;Why Bring Your Own Bucket&lt;/li&gt;
&lt;li&gt;
What It Actually Costs

&lt;ul&gt;
&lt;li&gt;The AWS bill is mostly requests, not storage&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Setting Up Cloudflare R2&lt;/li&gt;
&lt;li&gt;Setting Up AWS S3 Without Handing Over Your Account&lt;/li&gt;
&lt;li&gt;The CORS Step You Can Skip&lt;/li&gt;
&lt;li&gt;WebDAV: Nextcloud, InfiniCLOUD, and Your NAS&lt;/li&gt;
&lt;li&gt;Encryption: RClone Crypt or OpenSSL&lt;/li&gt;
&lt;li&gt;Free vs. PRO, If You’re Picking a Backend Anyway&lt;/li&gt;
&lt;li&gt;Settings That Bite&lt;/li&gt;
&lt;li&gt;Should You Use It?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Is Remotely Save Dead?
&lt;/h2&gt;

&lt;p&gt;I don’t know, and neither does anybody else outside the developer’s head. This much is true as of this writing.&lt;/p&gt;

&lt;p&gt;The repo is not archived. No “this is dead now” posts. It installs from the community directory, and it still syncs my vault daily. Obsidian’s plugin API is not the type to break stuff often. So a 2024 plugin works… well… Mostly.&lt;/p&gt;

&lt;p&gt;What worries me more is not the code. It’s &lt;a href="https://remotelysave.com/" rel="noopener noreferrer"&gt;remotelysave.com&lt;/a&gt; that handles PRO tier. “FREE during beta until Jan 1, 2027”. “The price will be set later.” That’s 10 weeks from when this posts.&lt;/p&gt;

&lt;p&gt;Unreleased for 2 years plugin, service with a deadline, but no price. Not exactly confidence-inspiring.&lt;/p&gt;

&lt;p&gt;I wrote it anyway because &lt;strong&gt;it all runs on free tier below&lt;/strong&gt;. S3, Cloudflare R2, Backblaze B2, MinIO, WebDAV. No account needed at remotelysave.com.&lt;/p&gt;

&lt;p&gt;If PRO service disappeared tomorrow, you’re still good. The plugin communicates directly to your bucket. There is no intermediary server in the mix. If you’re going to use a zombie plugin, this is how you should do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Bring Your Own Bucket
&lt;/h2&gt;

&lt;p&gt;Obsidian Sync is the easy answer and it’s good. But the Standard plan gives you 1GB of storage.&lt;/p&gt;

&lt;p&gt;I measured the part of my writing vault that Remotely Save syncs: 9,371 files, 1.62GB. Only 80MB of that is markdown. The rest is images, PDFs, and the junk from years of web clipping. So Standard is already too small for me, and I’d be on Plus.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fthqagpfsvskzdj070fnv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fthqagpfsvskzdj070fnv.jpg" alt="Why Bring Your Own Bucket" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The BYO storage pitch is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The storage is yours.&lt;/strong&gt; Your notes live in a bucket you own, in a format you can read without Obsidian.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It’s cheap or free.&lt;/strong&gt; For a normal vault, the bill rounds to zero. I’ll show numbers in a bit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It works everywhere Obsidian does,&lt;/strong&gt; including iOS, where folder sync is a nightmare. I covered why in the &lt;a href="https://dev.to/eristoddle/how-to-sync-obsidian-on-iphone-and-ipad-for-free-in-2026-427p"&gt;iPhone and iPad sync guide&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Trade off is someone else’s problem becomes your problem. Obsidian Sync has a support team. You have your R2 bucket.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Actually Costs
&lt;/h2&gt;

&lt;p&gt;I went through my own vault: 1.62GB, synced from 3 devices.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Backend&lt;/th&gt;
&lt;th&gt;Free allowance&lt;/th&gt;
&lt;th&gt;After that&lt;/th&gt;
&lt;th&gt;My 1.62GB vault&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloudflare R2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10GB storage, 1M Class A ops, 10M Class B ops per month&lt;/td&gt;
&lt;td&gt;$0.015/GB-month, zero egress&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backblaze B2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;First 10GB free, egress free up to 3x what you store&lt;/td&gt;
&lt;td&gt;$6.95/TB-month&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS S3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;New-account credits only&lt;/td&gt;
&lt;td&gt;about $0.023/GB-month, plus requests&lt;/td&gt;
&lt;td&gt;well under $1 a month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MinIO, self-hosted&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Whatever disk you have&lt;/td&gt;
&lt;td&gt;Your electricity and your weekend&lt;/td&gt;
&lt;td&gt;$0 and a weekend&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;R2 is the sleeper pick. No egress fees from Cloudflare. All those devices that download your full vault for the first time, that’s egress. 10 free gigabytes is a lot of markdown.&lt;/p&gt;

&lt;h3&gt;
  
  
  The AWS bill is mostly requests, not storage
&lt;/h3&gt;

&lt;p&gt;AAWS is the weird numbers one. Storing 1.62GB in S3 Standard costs about four cents a month. No big deal.&lt;/p&gt;

&lt;p&gt;What costs money is asking the bucket what’s in it. A sync starts by listing the remote files, and S3 bills LIST requests at the same rate as PUT, $0.005 per thousand. A listing returns at most 1,000 objects, so my vault takes about 10 requests just to look. Run auto-sync every five minutes on three devices for eight hours a day and you’re at around 86,000 list requests a month. That’s roughly 43 cents. More than ten times the storage bill, for checking whether anything changed.&lt;/p&gt;

&lt;p&gt;Forty-three cents is still nothing. But it’s why people get surprised by S3 bills, and it’s one more reason R2’s flat free tier is the better deal for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Cloudflare R2
&lt;/h2&gt;

&lt;p&gt;This is the setup I’d pick if I were starting today. Remotely Save’s own &lt;a href="https://github.com/remotely-save/remotely-save/blob/master/docs/remote_services/s3_cloudflare_r2/README.md" rel="noopener noreferrer"&gt;R2 tutorial&lt;/a&gt; is short, and so is this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcrdmj84hbd23pne9cyb0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcrdmj84hbd23pne9cyb0.jpg" alt="Setting Up Cloudflare R2" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Make a Cloudflare account and enable R2.&lt;/strong&gt; It will probably want a credit card even though you’ll stay in the free tier. Annoying, but normal for cloud storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a bucket.&lt;/strong&gt; Name it something like &lt;code&gt;obsidian-vault&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create an API token&lt;/strong&gt; with &lt;strong&gt;Object Read &amp;amp; Write&lt;/strong&gt; permission, scoped to just that bucket. Don’t give it access to everything on your account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save what it shows you:&lt;/strong&gt; the access key, the secret key, and the endpoint URL. Cloudflare only shows the secret once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In Obsidian&lt;/strong&gt; , install Remotely Save (the &lt;a href="https://dev.to/eristoddle/how-to-install-activate-and-update-obsidian-plugins-4d2p"&gt;plugin install walkthrough&lt;/a&gt; covers that), open its settings, and pick &lt;strong&gt;S3 or compatible&lt;/strong&gt; as the remote service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fill in&lt;/strong&gt; the endpoint, region &lt;code&gt;us-east-1&lt;/code&gt;, access key, secret key, and bucket name. R2 doesn’t really use regions, and &lt;code&gt;us-east-1&lt;/code&gt; is what the tutorial says to put there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn on Bypass CORS.&lt;/strong&gt; The tutorial calls this “usually what you want,” and it is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click Check Connectivity&lt;/strong&gt; , then run your first sync.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Back up the vault before that first sync. Copy the folder somewhere Remotely Save doesn’t know about. Every sync tool I’ve covered in this series gets the same advice, because the first sync is when you find out you configured something backwards.&lt;/p&gt;

&lt;p&gt;The one R2 issue: older versions of the plugin failed the connectivity check even when the settings were right, because Cloudflare doesn’t allow that kind of key to run &lt;code&gt;HeadBucket&lt;/code&gt;. Version 0.3.29 switched to &lt;code&gt;ListObjects&lt;/code&gt; and fixed it. Since the current version is 0.5.25, this only bites you if you’re running something ancient. If the check fails, look at your keys before you blame Cloudflare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up AWS S3 Without Handing Over Your Account
&lt;/h2&gt;

&lt;p&gt;R2 asks for a scoped token and you’re done. AWS makes you build the scope yourself, and this is where it’s easy to get stuck. The easy move is to use your root account’s keys because they’re right there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don’t.&lt;/strong&gt; Those keys can do anything to your entire AWS account, and now they live in a plugin settings file on your phone.&lt;/p&gt;

&lt;p&gt;Instead, create an IAM policy that can touch one bucket and nothing else. This is the policy from the plugin’s &lt;a href="https://github.com/remotely-save/remotely-save/blob/master/docs/remote_services/s3_general/s3_user_policy.md" rel="noopener noreferrer"&gt;S3 user policy doc&lt;/a&gt;, with &lt;code&gt;my-bucket&lt;/code&gt; swapped for your bucket name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ObsidianObjects"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:HeadObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:ListBucket"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:PutObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:CopyObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:UploadPart"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:UploadPartCopy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:ListMultipartUploads"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:AbortMultipartUpload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:CompleteMultipartUpload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:ListObjects"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:ListObjectsV2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:ListParts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObjectAttributes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:DeleteObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:DeleteObjects"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::my-bucket"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::my-bucket/*"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In IAM, create a new user and choose &lt;strong&gt;Attach policies directly&lt;/strong&gt;. Attach the policy above.&lt;/li&gt;
&lt;li&gt;Open that user, go to &lt;strong&gt;Security credentials&lt;/strong&gt; , and create an access key. If it asks for a use case, pick &lt;strong&gt;Other&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Put that access key, the secret, your bucket name, and the bucket’s region into Remotely Save.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The doc says that the bucket itself doesn’t need a policy, only the user. It also says “not fully tested,” which is good of them to admit, and a reason to test a sync with a throwaway note first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CORS Step You Can Skip
&lt;/h2&gt;

&lt;p&gt;If you’ve read an older Remotely Save guide, you’ve seen a big block of CORS JSON with origins like &lt;code&gt;app://obsidian.md&lt;/code&gt; and &lt;code&gt;capacitor://localhost&lt;/code&gt;. It used to be the step that broke everybody’s setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvj32v8v6kib8cbr017ex.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvj32v8v6kib8cbr017ex.jpg" alt="The CORS Step You Can Skip" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You probably don’t need it anymore. The plugin’s &lt;a href="https://github.com/remotely-save/remotely-save/blob/master/docs/remote_services/s3_general/s3_cors_configure.md" rel="noopener noreferrer"&gt;CORS doc&lt;/a&gt; says it’s only required on Obsidian desktop below 0.13.25 or mobile below 1.1.1. Newer Obsidian lets the plugin make requests that don’t go through the browser’s CORS rules, which is what the Bypass CORS toggle is about. Those version numbers are years old. If you are running Obsidian that old, CORS is not your biggest problem.&lt;/p&gt;

&lt;p&gt;So if a tutorial sends you into your bucket’s CORS settings, skip it, turn on Bypass CORS, and only come back to it if the connectivity check fails. WebDAV has its own CORS doc with the same desktop and iOS cutoffs, plus one exception: it says Android needs CORS on the WebDAV server at any version, and Nextcloud and ownCloud don’t turn it on by default. If you sync from an Android phone over WebDAV, read that doc before you skip anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebDAV: Nextcloud, InfiniCLOUD, and Your NAS
&lt;/h2&gt;

&lt;p&gt;WebDAV is the other free-tier backend, and it’s the one for people who already run a server or own a NAS. Remotely Save has setup docs for a dozen of them. Here’s the 3 most people will care about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nextcloud.&lt;/strong&gt; If you already self-host it, this is the obvious pick. Your notes land next to everything else you run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Synology NAS.&lt;/strong&gt; Turn on the WebDAV Server package and point the plugin at it. It’s great at home. Away from home you’ll need a way to reach the NAS, and exposing it to the internet so your phone can sync is something to do only if you understand what you’re letting in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;InfiniCLOUD&lt;/strong&gt; (it used to be called TeraCLOUD). A hosted WebDAV service with a free plan that recent listings put at 20GB. The catch is that free accounts can be deleted after two years without a login. A sync plugin that’s working perfectly never makes you log into the website, so put a reminder in your calendar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Setup is the same every time: pick &lt;strong&gt;Webdav&lt;/strong&gt; in the plugin, enter the server address, username, and password, and check connectivity. The plugin puts your vault in a subfolder named after it, so one WebDAV account can hold several vaults without them stepping on each other.&lt;/p&gt;

&lt;p&gt;I’ve never run my vault through WebDAV. I’ve used Dropbox the whole time. So for this section I’m going on the plugin’s docs, not my scars. If you hit something weird with a specific server, the per-server tutorials in the repo’s &lt;code&gt;docs/remote_services/&lt;/code&gt; folder are where to start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encryption: RClone Crypt or OpenSSL
&lt;/h2&gt;

&lt;p&gt;If you set a password, Remotely Save encrypts your files on your device before they go up. Leave it blank and your notes sit in the bucket as plain markdown. With your own S3 bucket, plain is defensible. With a third-party WebDAV host, set a password.&lt;/p&gt;

&lt;p&gt;You get two formats, and the plugin recommends RClone Crypt. Its own &lt;a href="https://github.com/remotely-save/remotely-save/blob/master/docs/encryption/comparation.md" rel="noopener noreferrer"&gt;comparison page&lt;/a&gt; lays out the difference:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0a8c6xjnx05bdzxgwm4g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0a8c6xjnx05bdzxgwm4g.jpg" alt="Encryption: RClone Crypt or OpenSSL" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;RClone Crypt (recommended)&lt;/th&gt;
&lt;th&gt;OpenSSL enc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Content&lt;/td&gt;
&lt;td&gt;XSalsa20Poly1305, in chunks&lt;/td&gt;
&lt;td&gt;AES-256-CBC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Filenames&lt;/td&gt;
&lt;td&gt;Each path segment encrypted separately&lt;/td&gt;
&lt;td&gt;The whole path encrypted as one&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reading it without Obsidian&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;rclone&lt;/code&gt; can mount the bucket decrypted&lt;/td&gt;
&lt;td&gt;Write your own script&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The filename row is the real tradeoff. RClone Crypt encrypts each folder name and filename on its own, so your folder structure survives. Someone with access to the bucket can’t read your note titles, but they can see that you have a folder with 400 things in it, nested three deep. OpenSSL hides the structure too, at the cost of not being able to open your vault with a standard tool.&lt;/p&gt;

&lt;p&gt;I’d still take RClone Crypt. Being able to run &lt;code&gt;rclone mount&lt;/code&gt; and read my notes without Obsidian is the point of owning the bucket.&lt;/p&gt;

&lt;p&gt;Two warnings from that page. First, if you ever switch formats, you have to delete the remote files “manually and fully” so the plugin can re-upload everything. Second, the page says the author “doesn’t have sufficient knowledge to ‘judge’ which one is the better format.” Credit for saying so, and a reminder that this is a hobby project’s encryption, not an audited product. Use a long password. Also, for Dropbox, OneDrive, and WebDAV, the vault’s name itself isn’t encrypted. Don’t name your vault after something you’re hiding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free vs. PRO, If You’re Picking a Backend Anyway
&lt;/h2&gt;

&lt;p&gt;The split as of 0.5.x:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free, no account:&lt;/strong&gt; S3 and anything S3-compatible (R2, B2, MinIO), Dropbox, WebDAV, OneDrive’s App Folder, and Webdis, which the README calls “mostly experimental.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PRO, needs a remotelysave.com account:&lt;/strong&gt; Google Drive, Box, pCloud, Yandex Disk, Koofr, Azure Blob Storage, full OneDrive access, and Smart Conflict.&lt;/p&gt;

&lt;p&gt;Smart Conflict is the PRO feature I’d actually miss. On the free tier, the plugin detects a conflict and you pick a rule: keep the newer file or keep the larger one. Whichever loses is gone. Smart Conflict tries to merge two versions of a small markdown file instead, and for anything it can’t merge, it keeps both.&lt;/p&gt;

&lt;p&gt;The free list is exactly the backends this post is about. If you choose R2, B2, S3, or WebDAV, the PRO price that gets announced after January 1 doesn’t touch you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Settings That Bite
&lt;/h2&gt;

&lt;p&gt;Most of these come from the README, which I read properly for the first time while writing this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffpitp62rr6ph7j5ysy6b.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffpitp62rr6ph7j5ysy6b.jpg" alt="The Settings That Bite" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Files starting with &lt;code&gt;.&lt;/code&gt; or &lt;code&gt;_&lt;/code&gt; don’t sync by default.&lt;/strong&gt; If you have an &lt;code&gt;_attachments&lt;/code&gt; folder, it isn’t going anywhere. Your &lt;code&gt;.obsidian&lt;/code&gt; config folder can sync, but that option is marked experimental.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-sync only runs while Obsidian is open.&lt;/strong&gt; It’s an interval timer inside the app. Close the app and nothing syncs. Open it on your phone and nothing is current until the next run, so hit sync by hand before you start writing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Errors “fail silently.”&lt;/strong&gt; That’s the README’s phrase. A broken auto-sync looks exactly like a working one with nothing to sync. Check the last sync time once in a while.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Big files are slow on mobile.&lt;/strong&gt; The README flags trouble at 50MB and up. There’s a Skip Large Files setting and a regex filter for paths. Use them before your phone tries to pull down a 300MB PDF over cell data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;data.json&lt;/code&gt; holds your keys.&lt;/strong&gt; It’s in &lt;code&gt;.obsidian/plugins/remotely-save/&lt;/code&gt;, and it has your secret key or tokens in it. The plugin drops a &lt;code&gt;.gitignore&lt;/code&gt; into its own folder that excludes it. And one I did to myself. My laptops sync the vault through the Dropbox app, and my mobile devices sync it through Remotely Save. That plugin folder sits inside the vault, so Dropbox syncs each laptop’s copy of the plugin’s settings file. When I went looking just now, I found this in it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(Stephan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Miller's&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;conflicted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;copy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2025-12-14&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(Stephan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Miller's&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;conflicted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;copy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2025-12-14&lt;/span&gt;&lt;span class="err"&gt;).json&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A conflicted copy of a conflicted copy. That’s my own rule from the pillar, “don’t run two sync systems on one vault,” broken by me in my own vault, and it’s been there since December. It’s harmless here, since the plugin ignores those files. But it’s the kind of mess you get when two tools both think they’re in charge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should You Use It?
&lt;/h2&gt;

&lt;p&gt;If you want Obsidian on every device without a subscription, and you’re fine owning a bucket, yes. With a caveat I didn’t have to write a year ago.&lt;/p&gt;

&lt;p&gt;Remotely Save has done its job for my phone and iPad for years and it’s still doing it today. R2 makes it free for most vaults. AWS makes it cost pocket change, mostly for listing files. WebDAV is free if you already run the server. Encryption is there, with the author’s own disclaimer attached.&lt;/p&gt;

&lt;p&gt;But it hasn’t had a release since October 2024, and nobody is telling us whether that’s a pause or the end. So set it up the way that survives the plugin going away: a free-tier backend, RClone Crypt if you encrypt, and a backup that isn’t the sync target. If the plugin stops working someday, your notes are still in a bucket you own, readable with &lt;code&gt;rclone&lt;/code&gt;. That’s a better exit than most sync tools give you.&lt;/p&gt;

&lt;p&gt;If you’d rather someone else worry about all this, &lt;a href="https://dev.to/eristoddle/obsidian-dropbox-sync-a-setup-guide-2ajl"&gt;Dropbox&lt;/a&gt; is the simplest Remotely Save backend, and &lt;a href="https://dev.to/eristoddle/syncthing-for-obsidian-free-private-and-genuinely-annoying-3dbm"&gt;Syncthing&lt;/a&gt; skips the cloud entirely. Me, I’m keeping my setup. I should probably delete that conflicted copy, too.&lt;/p&gt;

</description>
      <category>obsidian</category>
    </item>
    <item>
      <title>Gemini 4 Argon Is for Sale Now. The Price Doubles December 1.</title>
      <dc:creator>Stephan Miller</dc:creator>
      <pubDate>Tue, 20 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/eristoddle/gemini-4-argon-is-for-sale-now-the-price-doubles-december-1-4a4c</link>
      <guid>https://dev.to/eristoddle/gemini-4-argon-is-for-sale-now-the-price-doubles-december-1-4a4c</guid>
      <description>&lt;p&gt;For two issues in a row I printed a second cheapskate table, because the model at the top of the first one wasn’t for sale. Gemini 4 Argon sat at number one in every Arena category, and you couldn’t buy it unless Google had vetted you as a cyber defender for its Fairwind program.&lt;/p&gt;

&lt;p&gt;You can buy it now. Google made it generally available on October 13, and OpenRouter listed it the same day. So I deleted the second table. Then I went to see what the first wave of paying customers had to say, and the top thread on r/GeminiAI is titled “Out of Gemini 4 Argon usage after 10 messages.” You know how that goes.&lt;/p&gt;

&lt;p&gt;Argon wasn’t the only thing going on. DeepSeek pushed a “minor update” to its Flash model on Friday, and by Sunday it was the busiest model on OpenRouter. Meta, which went closed back in April, put out open weights again. Reflection shipped a 501B open model with a benchmark claim that the independent numbers don’t back up. StepFun’s weights showed up after all. And somebody broke into OpenCode Console and spent people’s API credits for them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Gemini 4 Argon went on sale, and the first complaint was the limits

&lt;ul&gt;
&lt;li&gt;What the paying customers said&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
DeepSeek shipped a “minor update” and took the daily top spot

&lt;ul&gt;
&lt;li&gt;The price depends on what time it is&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Open weights week

&lt;ul&gt;
&lt;li&gt;Meta went back to open, sort of&lt;/li&gt;
&lt;li&gt;Reflection Beam 1.0: big claim, small index&lt;/li&gt;
&lt;li&gt;Step 5’s weights showed up, and the free traffic left&lt;/li&gt;
&lt;li&gt;Space Bunny got a name&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
The cheapskate table: one table again

&lt;ul&gt;
&lt;li&gt;GLM-5.3-Flash missed Overall by six hundredths of a point&lt;/li&gt;
&lt;li&gt;The rest of the table&lt;/li&gt;
&lt;li&gt;Speed is still the catch&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Local sweet spot&lt;/li&gt;
&lt;li&gt;
Horror stories

&lt;ul&gt;
&lt;li&gt;OpenCode Console leaked people’s API keys&lt;/li&gt;
&lt;li&gt;The Argon usage wall&lt;/li&gt;
&lt;li&gt;The peak-hour batch job&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;What’s coming&lt;/li&gt;
&lt;li&gt;Finally&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Gemini 4 Argon went on sale, and the first complaint was the limits
&lt;/h2&gt;

&lt;p&gt;As of October 13, Argon is &lt;a href="https://pasqualepillitteri.it/en/news/23457/gemini-4-argon-disponibile-dove-usarlo-prezzo-en" rel="noopener noreferrer"&gt;generally available&lt;/a&gt; in the Gemini API on the paid plan (the model string is &lt;code&gt;gemini-4-argon&lt;/code&gt;), in the Gemini app for AI Pro and Ultra subscribers, and in AI Studio and Antigravity for Ultra. The Fairwind-only restriction is gone for paying customers. On &lt;a href="https://openrouter.ai/google/gemini-4-argon" rel="noopener noreferrer"&gt;OpenRouter&lt;/a&gt; it’s $2 in and $10 out, with a flex tier at $1/$5 if you can wait.&lt;/p&gt;

&lt;p&gt;That $2/$10 is still the intro price. It has an end date now: &lt;a href="https://andrew.ooo/answers/gemini-4-argon-generally-available-price-access-limits-october-2026/" rel="noopener noreferrer"&gt;$4/$20 from December 1&lt;/a&gt;. So if you build a budget on Argon this month, build it on the December number.&lt;/p&gt;

&lt;p&gt;So is it worth $10 a million? Arena still has it number one Overall (1524, now on 4,904 votes), plus Coding, Instruction Following, Hard Prompts, and Math. But it lost one. Claude Opus 5.5 took Creative Writing, 1519 to 1516. That’s three and a half points, which is nothing statistically, but it’s the first category Argon hasn’t swept since it showed up. And the Math lead is sitting on 273 votes, so I wouldn’t tattoo that one anywhere.&lt;/p&gt;

&lt;p&gt;Artificial Analysis likes it less. Argon scores 53 on the &lt;a href="https://artificialanalysis.ai/leaderboards/models" rel="noopener noreferrer"&gt;Intelligence Index&lt;/a&gt;, tied with GPT-6 Astra and behind Opus 5.5 (58), Sonnet 5.5 (56), and Meta’s Muse Wonder Full (56). That’s the same split I’ve been writing about for weeks: Arena voters love it, the hard benchmarks say it’s frontier but not the top of the frontier.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the paying customers said
&lt;/h3&gt;

&lt;p&gt;Reddit was reachable this week, so I got real threads instead of aggregator summaries. The loudest ones are about the consumer apps, not the API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://www.reddit.com/r/GeminiAI/comments/1x5nyfu/out_of_gemini_4_argon_usage_after_10_messages/" rel="noopener noreferrer"&gt;r/GeminiAI usage thread&lt;/a&gt; I mentioned up top has 733 points and 141 comments. The top comment’s theory is that Argon is just very expensive for Google to run, and the limits are how Google pays for it.&lt;/li&gt;
&lt;li&gt;On r/AntigravityGoogle: “&lt;a href="https://www.reddit.com/r/AntigravityGoogle/comments/1x79jlx/to_all_the_pro_users_thinking_of_upgrading_to/" rel="noopener noreferrer"&gt;To all the Pro users thinking of upgrading to Ultra for Gemini 4 Argon: Don’t do it. The limits are a joke.&lt;/a&gt;” (430 points). Another thread there, “&lt;a href="https://www.reddit.com/r/AntigravityGoogle/comments/1x54fqo/gemini_4_argon_did_way_more_damage_than_good/" rel="noopener noreferrer"&gt;Gemini 4 Argon did way more damage than good&lt;/a&gt;” (794 points), has at least one person saying the botched release made them cancel.&lt;/li&gt;
&lt;li&gt;The positive one is from launch week. An r/singularity thread called “&lt;a href="https://www.reddit.com/r/singularity/comments/1wuj72j/gemini_4_argon_solved_hallucinations/" rel="noopener noreferrer"&gt;Gemini 4 Argon solved hallucinations&lt;/a&gt;” got 1,608 points, and the top reply sums it up: “‘solved’ 15% But yeah, it’s a very nice improvement if not benchmaxxed.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want Argon, I’d use the API and pay per token, where you know what you’re getting. Paying for an Ultra subscription to get Argon in the app is the move people are warning each other off of.&lt;/p&gt;

&lt;h2&gt;
  
  
  DeepSeek shipped a “minor update” and took the daily top spot
&lt;/h2&gt;

&lt;p&gt;On October 17, DeepSeek put out &lt;a href="https://openrouter.ai/deepseek/deepseek-v4.1-flash-1017" rel="noopener noreferrer"&gt;DeepSeek V4.1 Flash 1017&lt;/a&gt;, a new snapshot of the model that was already number one on OpenRouter. It now sits behind DeepSeek’s &lt;code&gt;deepseek-flash&lt;/code&gt; API name, and the &lt;a href="https://huggingface.co/deepseek-ai/DeepSeek-V4.1-Flash-1017" rel="noopener noreferrer"&gt;weights went up on Hugging Face&lt;/a&gt; under MIT the same day.&lt;/p&gt;

&lt;p&gt;Two days later it had the top spot on &lt;a href="https://openrouter.ai/rankings" rel="noopener noreferrer"&gt;OpenRouter’s&lt;/a&gt; daily board. The board through October 19 has it at 3.61 trillion tokens for the day, first place, with the original V4.1 Flash second at 2.8 trillion. For the week it’s sixth at 7.34 trillion on about two days of traffic, and first on New &amp;amp; Trending. The original V4.1 Flash is still number one for the week (29.6 trillion), but it’s down 27 percent, so you can watch the traffic move from one to the other. DeepSeek is now 24.4 percent of every request on OpenRouter.&lt;/p&gt;

&lt;p&gt;Artificial Analysis gives the 1017 snapshot a &lt;a href="https://artificialanalysis.ai/models/deepseek-v4-1-flash-1017" rel="noopener noreferrer"&gt;45&lt;/a&gt;, second among the 121 open-weights models it tracks (MiMo-V2.6-Pro is first at 46). AA clocks it at 211 tokens a second, with the first token arriving in about a second. The catch is the same one I keep finding with the smart cheap models. It took 210 million output tokens to get through AA’s index, against a median of 140 million, and AA doesn’t put it on the intelligence-versus-cost frontier.&lt;/p&gt;

&lt;p&gt;r/LocalLLaMA’s &lt;a href="https://www.reddit.com/r/LocalLLaMA/comments/1x84po4/deepseekaideepseekv41flash1017_hugging_face/" rel="noopener noreferrer"&gt;release thread&lt;/a&gt; has 1,117 points and 314 comments. The top comment (605 upvotes): “‘minor update’ Proceeds to obliterate GLM5.3, Kimi K3 and GPT5.6 Sol.” Another one notes that “Flash is now 700B,” which is about right going by the size of the safetensors on Hugging Face. And a 519-upvote reply warns that one of the charts going around comes from a knockoff benchmark site dressed up to look like Artificial Analysis. Check where a chart comes from before you share it.&lt;/p&gt;

&lt;p&gt;Over on r/DeepSeek, someone ran &lt;a href="https://www.reddit.com/r/DeepSeek/comments/1x8kwp7/deepseek_v41_flash_1017_vs_claude_opus_55_same/" rel="noopener noreferrer"&gt;1017 against Claude Opus 5.5&lt;/a&gt; on the same task. The top reply had the most sensible take of the week: priced like Haiku, performs closer to Sonnet than Opus. And r/opencode noticed &lt;a href="https://www.reddit.com/r/opencode/comments/1x6fj9m/deepseek_v41_flash_is_free_in_opencode/" rel="noopener noreferrer"&gt;it’s free in OpenCode&lt;/a&gt; (1,666 points), where the replies went straight to “you are the product” and complaints about the 200K context cap.&lt;/p&gt;

&lt;h3&gt;
  
  
  The price depends on what time it is
&lt;/h3&gt;

&lt;p&gt;DeepSeek’s own endpoint charges $0.15 in and $0.60 out off-peak. During peak hours it’s &lt;a href="https://www.eesel.ai/blog/deepseek-v4-1-flash-pricing" rel="noopener noreferrer"&gt;exactly double&lt;/a&gt;, $0.30/$1.20. Peak is 01:00 to 04:00 and 06:00 to 10:00 UTC, Monday through Friday. That’s Beijing’s working day. In US Central time, while daylight saving lasts, that’s 8 to 11pm and 1 to 5am.&lt;/p&gt;

&lt;p&gt;DeepSeek didn’t invent this for 1017. It’s been charging by the clock since V4.1 launched in September. But now that millions of requests a day are moving onto it, the gap costs real money. “60 cents” is the number everybody quotes and $1.20 is the number you pay if your overnight batch job runs at the wrong damn time. In my cheapskate math I use the $1.20, since that’s the rate you can’t schedule your way out of.&lt;/p&gt;

&lt;p&gt;It’s not on Arena yet, so it doesn’t get a row in the table this week. The older V4.1 Flash is in the Overall band at 38th place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open weights week
&lt;/h2&gt;

&lt;p&gt;Three labs put out big open-weight models in the same week, and a fourth confirmed a stealth model’s identity. None of them change the cheapskate table yet. One of them is Meta reversing itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Meta went back to open, sort of
&lt;/h3&gt;

&lt;p&gt;Back in April, one of my first roundups led with Meta abandoning open source for Muse Spark. On October 15 Meta released &lt;a href="https://pasqualepillitteri.it/en/news/24330/meta-muse-spark-open-816b-open-weights" rel="noopener noreferrer"&gt;Muse Spark Open&lt;/a&gt;, with weights on Hugging Face, SageMaker, Vertex Model Garden, and Microsoft Foundry. It’s 816 billion parameters with 42 billion active, a 1M context window, native image and video input, and it’s built for coding and agent work.&lt;/p&gt;

&lt;p&gt;The license is the first problem. It ships under the Muse Model License, which has &lt;a href="https://www.trendingtopics.eu/muse-spark-open-meta-open-weight-license/" rel="noopener noreferrer"&gt;commercial limits&lt;/a&gt;, so you can download the weights and still not be allowed to do whatever you want with them. If you’re building a product on it, have somebody read that license before you write any code.&lt;/p&gt;

&lt;p&gt;And you aren’t running this at home. The &lt;a href="https://www.yottalabs.ai/post/muse-spark-open-hardware-requirements-gpu-memory" rel="noopener noreferrer"&gt;hardware floor&lt;/a&gt; is about 700GB of VRAM at NVFP4 (four Blackwell Ultras or eight H200s) and about 2TB at BF16. On Artificial Analysis it scores 39, behind Kimi K3 and GLM 5.3 according to &lt;a href="https://www.developersdigest.tech/blog/muse-spark-open-weights-816b-run-it-2026" rel="noopener noreferrer"&gt;Developers Digest&lt;/a&gt;. Meta hosts it on OpenRouter at $1.25/$4.25. Why pay $4.25 out for a 39 when DeepSeek’s snapshot scores 45 and tops out at $1.20?&lt;/p&gt;

&lt;p&gt;I’ll still take it. Six months ago the story was Meta closing the door, and this week I could pull Muse weights off Hugging Face (if I had a rack of H200s to put them on).&lt;/p&gt;

&lt;h3&gt;
  
  
  Reflection Beam 1.0: big claim, small index
&lt;/h3&gt;

&lt;p&gt;Reflection AI, the NVIDIA-backed startup from former DeepMind researchers, released &lt;a href="https://www.vktr.com/ai-platforms/reflection-ai-unveils-beam-a-501b-open-weight-model/" rel="noopener noreferrer"&gt;Beam 1.0&lt;/a&gt; on October 16. It’s 501B total and 23B active, under &lt;a href="https://techjacksolutions.com/ai-brief/reflection-ai-beam-501b-weights-live-apache-download/" rel="noopener noreferrer"&gt;Apache 2.0&lt;/a&gt;, which is a real open license this time. OpenRouter has it at $0.30/$1.00.&lt;/p&gt;

&lt;p&gt;Reflection says it scores 80.9 percent on SWE-bench Verified and is three to four times more efficient than GLM 5.2. Artificial Analysis, which averages a much broader set of hard evals, gives it a 30. It’s fast (AA clocks about 350 tokens a second), but a 30 sits a long way below what that SWE-bench number implies. This is the same vendor-table problem I flagged with Meta’s Muse Wonder last week. The lab’s chart says one thing, the independent average says another, and when they’re this far apart I go with the independent one until someone explains the gap.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5’s weights showed up, and the free traffic left
&lt;/h3&gt;

&lt;p&gt;Last week I said I wouldn’t count StepFun’s promised October 15 weights as shipped until there was something on Hugging Face. There is. &lt;a href="https://huggingface.co/stepfun-ai/Step-5-Preview" rel="noopener noreferrer"&gt;stepfun-ai/Step-5-Preview&lt;/a&gt; went up on the 15th, with BF16 and NVFP4 variants, though early that morning &lt;a href="https://www.orcarouter.ai/fr/blog/step-5-preview-open-weights" rel="noopener noreferrer"&gt;people were reporting a 404&lt;/a&gt;. The license field says “other,” so read it before you use it.&lt;/p&gt;

&lt;p&gt;I also said to watch what happened to Step 5’s traffic once the free week ended on October 16. It fell 32 percent to 8.22 trillion tokens, and it’s still fourth on OpenRouter for the week. I figured the freeloaders would bail harder than that. About a third of the traffic left, and I’d guess most of the rest is paying $2.70 out now. Arena still has it 84th Overall. In Coding it’s 63rd, missing the 50-point band by 1.3 points.&lt;/p&gt;

&lt;h3&gt;
  
  
  Space Bunny got a name
&lt;/h3&gt;

&lt;p&gt;The free stealth model that was number one on OpenRouter three weeks ago has an identity. According to &lt;a href="https://www.eesel.ai/blog/minimax-m3-1-flash" rel="noopener noreferrer"&gt;eesel&lt;/a&gt;, Space Bunny Alpha was MiniMax M3.1, which is what everybody guessed. MiniMax M3.1 Flash showed up on OpenRouter as a free model on October 19 and did 1.05 trillion tokens on its first day, seventh place. AA gives it 43 at about 105 tokens a second.&lt;/p&gt;

&lt;p&gt;There are no Hugging Face weights yet, and no model card or technical report either. You can’t turn thinking off, only turn it down, and it defaults to max effort. And outside the free OpenRouter endpoint, eesel says MiniMax currently sells it through subscription plans at $20, $50, or $120 a month rather than a published per-token price. Free endpoints on OpenRouter have a habit of turning into paid ones with about a week’s notice, so I’ll check on this one next issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cheapskate table: one table again
&lt;/h2&gt;

&lt;p&gt;If you’re new here: for each Arena category I take the leader’s rating, subtract 50, and look for the cheapest model still above that line. The band gets computed in code from every row on the board, and I write down the first model below the line so I know nothing got cut off. The board comes from &lt;a href="https://huggingface.co/datasets/lmarena-ai/leaderboard-dataset" rel="noopener noreferrer"&gt;LMArena’s leaderboard dataset&lt;/a&gt; on Hugging Face (arena.ai’s site still blocks me), published October 15. Prices are each maker’s own endpoint on OpenRouter.&lt;/p&gt;

&lt;p&gt;Since Argon is for sale now, there’s only one table. Argon is priced at its $10 intro rate.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&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;gemini-4-argon-high (1524)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;MiMo-V2.6-Pro (1479, #27)&lt;/td&gt;
&lt;td&gt;$0.87&lt;/td&gt;
&lt;td&gt;−45&lt;/td&gt;
&lt;td&gt;11.5×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coding&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1559)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;MiMo-V2.6-Flash* (1513, #51)&lt;/td&gt;
&lt;td&gt;$0.28&lt;/td&gt;
&lt;td&gt;−46&lt;/td&gt;
&lt;td&gt;36×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creative Writing&lt;/td&gt;
&lt;td&gt;claude-opus-5.5-high (1519)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;gemini-3.7-flash-high (1491, #5)&lt;/td&gt;
&lt;td&gt;$3.75&lt;/td&gt;
&lt;td&gt;−28&lt;/td&gt;
&lt;td&gt;5.3×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instruction Following&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1527)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;gemini-3.8-flash-high (1490, #14)&lt;/td&gt;
&lt;td&gt;$3.75&lt;/td&gt;
&lt;td&gt;−37&lt;/td&gt;
&lt;td&gt;2.7×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard Prompts&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1549)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1500, #34)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;−49&lt;/td&gt;
&lt;td&gt;20×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Math&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1529)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1506, #8)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;−23&lt;/td&gt;
&lt;td&gt;20×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;*2,625 votes, 3.6 points above the cutoff. GLM-5.3-Flash sits at 1525 with 8,457 votes for 50 cents and is still the safer bet.&lt;/p&gt;

&lt;p&gt;Band depths: Overall 40, Coding 59, Creative 17, Instruction Following 23, Hard Prompts 35, Math 38.&lt;/p&gt;

&lt;h3&gt;
  
  
  GLM-5.3-Flash missed Overall by six hundredths of a point
&lt;/h3&gt;

&lt;p&gt;The Overall cutoff is 1473.90. The first model below it is GLM-5.3-Flash at 1473.84. That’s 0.06 points, out of a scale that runs to 1524. If it had made it, it would be the Overall pick at 50 cents and a 20x ratio. Instead the pick is MiMo-V2.6-Pro at 87 cents, for the third issue running.&lt;/p&gt;

&lt;p&gt;And GLM pushed 11.9 trillion tokens through OpenRouter this week, second only to DeepSeek. Plenty of people clearly think it’s good enough for general work, and my table leaves it out of Overall over a gap that disappears when you round to whole numbers. I don’t round, though. 1473.84 is under 1473.90, so GLM sits this one out.&lt;/p&gt;

&lt;p&gt;It went the other way in Hard Prompts. Last week GLM missed that band by 0.3. This week it’s in by 1.0, on 20,935 votes, and it’s the pick at 20x. It also holds Math for the third issue in a row, 8th place on that board.&lt;/p&gt;

&lt;h3&gt;
  
  
  The rest of the table
&lt;/h3&gt;

&lt;p&gt;Opus 5.5 beat Argon in Creative Writing, so that ratio now runs against Opus’s $20 instead of Argon’s $10, and Gemini 3.7 Flash stays the pick at 5.3x. Not one open model made that 17-model band. Instruction Following looks the same: the cheapest thing in its band is Gemini 3.8 Flash at $3.75. If you write fiction or need strict instruction following, you’re still paying for quality.&lt;/p&gt;

&lt;p&gt;MiMo-V2.6-Flash holds Coding for the third week, and it went up this time, 1,989 votes to 2,625. It’s still only 3.6 points over the line. My rule was that if it held the spot on a few thousand votes I’d call it the Coding pick for real. It’s getting there. I’d still run GLM-5.3-Flash for anything I cared about.&lt;/p&gt;

&lt;p&gt;Mark December 1 on the calendar, because every ratio with Argon as the leader doubles that day. Overall goes from 11.5x to 23x, and Hard Prompts and Math go from 20x to 40x, without a single pick changing. Google raises its price and the cheap models start looking twice as good.&lt;/p&gt;

&lt;h3&gt;
  
  
  Speed is still the catch
&lt;/h3&gt;

&lt;p&gt;The cheap end of the table is still slow. MiMo-V2.6-Pro, the best open model on AA at 46, runs at about &lt;a href="https://artificialanalysis.ai/models/mimo-v2-6-pro" rel="noopener noreferrer"&gt;50 tokens a second&lt;/a&gt;. MiMo-V2.6-Flash is around 54 and GLM-5.3-Flash about 78 this week (it moves around every week, so I re-pull it). Say your agent runs 20 steps and writes 1,000 tokens at each one. At 50 tokens a second that’s almost seven minutes of waiting. At the 211 that DeepSeek’s 1017 snapshot manages, it’s about a minute and a half, which is why I want to see where it lands once Arena rates it.&lt;/p&gt;

&lt;p&gt;The distillation accusation Anthropic made against Xiaomi in September still hangs over the MiMo family. Anthropic made that claim as a competitor, and nobody has ruled on it. If your contracts care where a model’s training data came from, factor it in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local sweet spot
&lt;/h2&gt;

&lt;p&gt;This section picks the biggest model that fits your machine with room left for context and still runs at 15 or more tokens a second. Nothing changed this week. I added Gemma 4 26B-A4B to the candidates and it didn’t beat Qwen3.8 27B on any tier. Every big open release this week (Muse Spark Open, Beam, the DeepSeek snapshot) is far too big for a 64GB machine.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your machine&lt;/th&gt;
&lt;th&gt;Pick&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;Arena&lt;/th&gt;
&lt;th&gt;AA&lt;/th&gt;
&lt;th&gt;Measured tok/s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mac 16GB&lt;/td&gt;
&lt;td&gt;qwen3.5-9b Q4_K_M&lt;/td&gt;
&lt;td&gt;5.7 GB&lt;/td&gt;
&lt;td&gt;unlisted&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;27 (n=4, 6-82)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mac 32GB&lt;/td&gt;
&lt;td&gt;qwen3.8-27b MLX 4bit&lt;/td&gt;
&lt;td&gt;16.1 GB&lt;/td&gt;
&lt;td&gt;1438 (#100)&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;not measured&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mac 64GB+&lt;/td&gt;
&lt;td&gt;qwen3.8-27b MLX 8bit&lt;/td&gt;
&lt;td&gt;29.5 GB&lt;/td&gt;
&lt;td&gt;1438 (#100)&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;19 (n=1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NVIDIA 12GB&lt;/td&gt;
&lt;td&gt;qwen3.5-9b Q4_K_M&lt;/td&gt;
&lt;td&gt;5.7 GB&lt;/td&gt;
&lt;td&gt;unlisted&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;50 (n=1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NVIDIA 24GB&lt;/td&gt;
&lt;td&gt;qwen3.8-27b Q4_K_M&lt;/td&gt;
&lt;td&gt;16.5 GB&lt;/td&gt;
&lt;td&gt;1438 (#100)&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;41 (n=2, 40-42)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The 9B rows have no Arena rating, so they’re picked by what fits, not by a leaderboard. The Mac 32GB speed is still unmeasured. I’m not going to fill it in from a calculator site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Horror stories
&lt;/h2&gt;

&lt;h3&gt;
  
  
  OpenCode Console leaked people’s API keys
&lt;/h3&gt;

&lt;p&gt;Overnight on October 18, attackers got into OpenCode Console, an older part of OpenCode’s online platform where some users store the API keys they use with OpenAI, Anthropic, and Google. &lt;a href="https://techcrunch.com/2026/10/19/hackers-hit-ai-coding-tool-opencode-running-up-charges-on-users-ai-accounts/" rel="noopener noreferrer"&gt;TechCrunch reports&lt;/a&gt; that 1.4 percent of Console users got breach notices, and people reported unauthorized charges from a few hundred dollars to more than $1,000. One user: “I saw my Open AI, Anthropic, and Google AI spend alerts all fire off before going to bed.” Some had their Google Cloud projects suspended on top of that, so they lost the money and the projects in the same night.&lt;/p&gt;

&lt;p&gt;Anthropic and Google blocked the exposed keys. OpenAI worked with OpenCode on refunds, and OpenCode says it’s refunding the charges too. Co-founder Dax Raad drew the line clearly: “Note this is the OpenCode Console, not OpenCode itself, those keys never come to us.” So the CLI didn’t leak anything. The web console did. OpenCode blamed a “large-scale distillation attack,” and &lt;a href="https://www.bleepingcomputer.com/news/security/opencode-hack-exposes-api-keys-amid-ai-distillation-attacks/" rel="noopener noreferrer"&gt;some security people&lt;/a&gt; said that hasn’t been proven.&lt;/p&gt;

&lt;p&gt;If you ever pasted a provider key into OpenCode Console, rotate it at the provider today. And set spend alerts on every provider account you have. Those alerts are the only reason the guy above found out before morning.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Argon usage wall
&lt;/h3&gt;

&lt;p&gt;I covered this above, but it’s the most common way people got burned this week. You pay for AI Ultra because you want Argon. You get through a handful of messages and hit the limit. The r/AntigravityGoogle advice is blunt: don’t upgrade for it. The API charges per token at a published price. The app charges a subscription and then cuts you off at a number nobody printed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The peak-hour batch job
&lt;/h3&gt;

&lt;p&gt;You move a nightly summarization job to DeepSeek V4.1 Flash because it’s 60 cents out. You schedule it at 9pm Central because that’s when your other jobs finish. That’s inside DeepSeek’s peak window, so every token costs double, and you’re paying $1.20 for a model you budgeted at $0.60. In a Hacker News thread about V4.1 Flash, one commenter said they &lt;a href="https://news.ycombinator.com/item?id=50012463" rel="noopener noreferrer"&gt;burned through $50 in a few days&lt;/a&gt; on the cheapest provider on OpenRouter, a quarter of what their Codex subscription costs. Cheap per token isn’t the same as cheap per job. Check what time your jobs actually run.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s coming
&lt;/h2&gt;

&lt;p&gt;Argon’s API price doubles to $4/$20 on December 1, and that’s the only item in this section with a firm date.&lt;/p&gt;

&lt;p&gt;Mistral Large 4’s open weights are still scheduled for October 31. Kimi K3.1 has a rumored October 29 date, and Grok 4.8 was supposed to land around today, according to the &lt;a href="https://waifuai.github.io/llm-countdowns/" rel="noopener noreferrer"&gt;LLM countdown tracker&lt;/a&gt;. I’ve learned to treat xAI dates as tweets. Claude Fable 5.5 is at about 93 percent on &lt;a href="https://manifold.markets/prismatic/october-2026-ai-model-releases" rel="noopener noreferrer"&gt;Manifold&lt;/a&gt; for October, and Anthropic hasn’t said a word. Haiku 5.5 still doesn’t have an Arena rating, two weeks after launch. MiniMax hasn’t posted M3.1 Flash weights or a model card. DeepSeek V5 is still speculation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally
&lt;/h2&gt;

&lt;p&gt;Every headline this week came with a condition attached. Argon is buyable, until December 1 changes the price. DeepSeek is 60 cents, unless the clock says otherwise. Meta’s weights are open, under a license you have to read first. If you only skim the launch posts, you’ll budget off the wrong number.&lt;/p&gt;

&lt;p&gt;So what actually changed for somebody picking a model today? Less than the headlines suggest. The top of the board got a price tag. The bottom of my table held for a third week: MiMo-V2.6-Pro, MiMo-V2.6-Flash, and GLM-5.3-Flash, all under a dollar out, and I’d still start any cost-sensitive project with GLM-5.3-Flash and see whether it falls short before paying 20 times more.&lt;/p&gt;

&lt;p&gt;Next week I’ll see whether DeepSeek’s 1017 snapshot gets an Arena rating, and whether it lands in the band at $1.20. And I’ll keep checking whether Haiku 5.5 ever gets rated.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>openrouter</category>
    </item>
    <item>
      <title>Firecrawl Universal Scrape Can Read Podcasts. The Terms Say You Can't Keep Them.</title>
      <dc:creator>Stephan Miller</dc:creator>
      <pubDate>Thu, 15 Oct 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/eristoddle/firecrawl-universal-scrape-can-read-podcasts-the-terms-say-you-cant-keep-them-3eda</link>
      <guid>https://dev.to/eristoddle/firecrawl-universal-scrape-can-read-podcasts-the-terms-say-you-cant-keep-them-3eda</guid>
      <description>&lt;p&gt;On October 8, &lt;a href="https://firecrawl.link/stephan-miller" rel="noopener noreferrer"&gt;Firecrawl&lt;/a&gt; launched &lt;a href="https://www.firecrawl.dev/blog/universal-scrape" rel="noopener noreferrer"&gt;Universal Scrape&lt;/a&gt;. The scrape endpoint I have been feeding URLs to for this whole series now answers questions about podcasts, people profiles, company financials and website traffic too. Ask it about podcasts and it gets you transcripts.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dev.to/eristoddle/track-new-ai-models-on-the-arena-leaderboard-with-a-70-line-scraper-3f3m"&gt;70-line harness from the Arena post&lt;/a&gt; already does the hard part: run on a schedule, save every result to SQLite, compare this week to last week, speak up when something changes. Point it at podcast mentions instead of a leaderboard and you have a brand monitor. Which podcasts talked about your product this week? Is that number going up? Who mentioned it for the first time?&lt;/p&gt;

&lt;p&gt;Then I read the terms and had to accept them to use the feature. And the terms forbid storing the data, reusing it for a later query, keeping it past the session, and showing it to anyone who isn’t one of your own users. That rules out the harness, the comparison, my AI agents, and other things I haven’t thought of yet.&lt;/p&gt;

&lt;p&gt;So this post is not what I originally planned. It’s about the fine print for every paid provider behind Universal Scrape, plus the version of the podcast tracker that survives it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Universal Scrape Adds&lt;/li&gt;
&lt;li&gt;The Recipe I Was Going to Write&lt;/li&gt;
&lt;li&gt;What Particle’s Terms Actually Say&lt;/li&gt;
&lt;li&gt;I Read the Terms for Every Paid Provider&lt;/li&gt;
&lt;li&gt;
The Tracker That Survives the Terms

&lt;ul&gt;
&lt;li&gt;The second gotcha: don’t pass a domain&lt;/li&gt;
&lt;li&gt;The script&lt;/li&gt;
&lt;li&gt;What I can show you&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Read the Schedule Before You Write the Recipe&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Universal Scrape Adds
&lt;/h2&gt;

&lt;p&gt;Two things, really.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Files by URL.&lt;/strong&gt; PDFs, images, Word documents, spreadsheets and presentations, if you can link to them. You pass the URL like any web page and get markdown back. The &lt;a href="https://docs.firecrawl.dev/features/scrape" rel="noopener noreferrer"&gt;scrape docs&lt;/a&gt; put PDF parsing at 1 credit per PDF page. None of that has provider terms attached.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Provider data.&lt;/strong&gt; This is &lt;a href="https://dev.to/eristoddle/before-you-write-a-scraper-check-firecrawl-alexandria-2652"&gt;Alexandria&lt;/a&gt;, the data catalog Firecrawl launched a couple of weeks ago, folded into the scrape endpoint. The launch post names the headliners: Apollo, FullEnrich and Data Legion for people and company profiles, Fiscal.ai and Benzinga for financial data, and Particle for podcasts.&lt;/p&gt;

&lt;p&gt;In the CLI, a provider call is a scrape where the URL is a &lt;code&gt;provider/capability&lt;/code&gt; address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firecrawl scrape particle/podcasts/mentions/timeseries &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--options&lt;/span&gt; &lt;span class="s1"&gt;'{"company_id": "anthropic", "interval": "month"}'&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That syntax needs a recent CLI. Mine was 1.23.3, so I updated to 1.26.3.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; firecrawl-cli@latest
firecrawl &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="c"&gt;# 1.26.3&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyutf30v02pxh1pf798wb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyutf30v02pxh1pf798wb.jpg" alt="What Universal Scrape Adds" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Same plain npm install as the &lt;a href="https://dev.to/eristoddle/firecrawl-cli-setup-skip-the-installer-that-rewrites-your-editors-2klj"&gt;setup post&lt;/a&gt;, so nothing touched my editor configs, and the key still comes from &lt;code&gt;FIRECRAWL_API_KEY&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Recipe I Was Going to Write
&lt;/h2&gt;

&lt;p&gt;Every useful scraping job in this series turned out to be the same job. A scraper tells you what a page says right now. Change needs history, history needs storage, and storage is why the harness exists.&lt;/p&gt;

&lt;p&gt;For podcasts, the plan was one weekly call, a row per episode in SQLite, and three alerts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mentions this week versus the last four&lt;/li&gt;
&lt;li&gt;shows mentioning the term for the first time&lt;/li&gt;
&lt;li&gt;the transcript line where each mention happens, so you can read it without listening to a 90-minute episode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Particle has the tools for all of it. Episode search, transcripts, mention lookups, speaker lists, even which sponsors read ads on which shows. 105 tools, at 5, 15, 25 or 50 credits a call.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Particle’s Terms Actually Say
&lt;/h2&gt;

&lt;p&gt;Before the first call, Particle makes you accept its terms from the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firecrawl alexandria terms show particle &lt;span class="nt"&gt;--json&lt;/span&gt;
firecrawl alexandria terms accept particle &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--terms-version&lt;/span&gt; B-1.0.0 &lt;span class="nt"&gt;--digest&lt;/span&gt; &amp;lt;sha256 from the show output&amp;gt; &lt;span class="nt"&gt;--confirm&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Credit to Firecrawl here. You accept an exact version, pinned by a hash of the document, and the JSON that &lt;code&gt;terms show&lt;/code&gt; returns tells an AI agent to present the terms to a human and wait for an explicit yes. My agent did exactly that. It read them, came back, and told me the recipe was dead before it accepted anything.&lt;/p&gt;

&lt;p&gt;The document is Schedule B, which pulls in &lt;a href="https://particle.pro/legal/tos-data-use-marketplace" rel="noopener noreferrer"&gt;Particle’s Data Use Terms&lt;/a&gt;. The parts that matter, quoted:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;(g) Download, save, or store Clips, Full Episode Audio, or Transcripts, other than (i) transient caching necessary for real-time display and the operation of your application, (ii) retaining a response you received, unaltered, so that your users can view that prior response…&lt;/p&gt;

&lt;p&gt;(h) Reuse stored Podcast Data to answer a later or different query. Each query is served by a new request through the Services.&lt;/p&gt;

&lt;p&gt;(i) Where an Automated Agent handles Podcast Data, allow it to retain that data beyond the session context or short-term memory reasonably necessary to process the immediate request. No persistent storage by agents.&lt;/p&gt;

&lt;p&gt;(a) Redistribute, resell, sublicense, or make Podcast Data available to anyone other than your own authorized users…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Go back through the plan with those in hand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The SQLite table is out.&lt;/strong&gt; Saving transcripts is (g). Saving episode rows and comparing them next week is (h), almost word for word: stored data answering a later query.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2njlb3ewsdta91cjlfzx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2njlb3ewsdta91cjlfzx.jpg" alt="What Particle's Terms Actually Say" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The agent workflow is out.&lt;/strong&gt; Every post in this series was built with &lt;a href="https://dev.to/eristoddle/what-to-do-when-your-ai-coding-agent-cant-read-a-web-page-2f0i"&gt;a coding agent driving the CLI&lt;/a&gt;. Under (i), the agent can hold the data for the request and that’s it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This blog post is out, mostly.&lt;/strong&gt; You are not one of my authorized users. A table of which shows mentioned which company, in a public post, is (a).&lt;/p&gt;

&lt;p&gt;There is also (j), no training models on it, and section B.7, which says Particle “may not hold licenses from the podcast creators and publishers” for the content. Particle’s position is fair use, and the schedule says that the podcast owners “may not share that assessment.”&lt;/p&gt;

&lt;h2&gt;
  
  
  I Read the Terms for Every Paid Provider
&lt;/h2&gt;

&lt;p&gt;If the podcast provider looks like that, what about the rest? Alexandria has a terms catalog, and &lt;code&gt;terms show&lt;/code&gt; works on any provider ID, so I walked the categories and asked about every provider I could find.&lt;/p&gt;

&lt;p&gt;Most of them have no terms in the catalog at all. Government data, public registries, app stores, package registries, Yahoo Finance. &lt;code&gt;terms show&lt;/code&gt; returns “Provider not found in the accessible terms catalog.” That doesn’t mean no rules. It means Firecrawl has no extra contract for that source, and the source’s own terms of service apply the way they would to any scrape.&lt;/p&gt;

&lt;p&gt;The commercial partners each carry a lettered schedule. Seven of them:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Data&lt;/th&gt;
&lt;th&gt;Store it?&lt;/th&gt;
&lt;th&gt;Publish it?&lt;/th&gt;
&lt;th&gt;Accept first?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Similarweb (G)&lt;/td&gt;
&lt;td&gt;Website traffic&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;No.&lt;/strong&gt; Not even cached. Each data point answers only the query that fetched it, in that session&lt;/td&gt;
&lt;td&gt;To your users, one query at a time, with “Insights by Similarweb”, their logo and a link&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Particle (B)&lt;/td&gt;
&lt;td&gt;Podcasts&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;No&lt;/strong&gt; , beyond an unaltered past response&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apollo (F)&lt;/td&gt;
&lt;td&gt;Contacts, companies&lt;/td&gt;
&lt;td&gt;Yes, for your own sales, marketing and recruiting&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;No&lt;/strong&gt; , not even through an agent’s output&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FullEnrich (A)&lt;/td&gt;
&lt;td&gt;Contacts&lt;/td&gt;
&lt;td&gt;For your own sales, marketing and recruiting&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Legion (H)&lt;/td&gt;
&lt;td&gt;People, companies&lt;/td&gt;
&lt;td&gt;Only in your CRM and internal systems&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;No&lt;/strong&gt; (your own analyses are yours)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Benzinga (C)&lt;/td&gt;
&lt;td&gt;Market news&lt;/td&gt;
&lt;td&gt;As needed to serve your own product&lt;/td&gt;
&lt;td&gt;Inside your product, to your users&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fiscal.ai (D)&lt;/td&gt;
&lt;td&gt;Financials, filings&lt;/td&gt;
&lt;td&gt;Yes, within your apps&lt;/td&gt;
&lt;td&gt;Inside your apps, to your users&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;“Accept first?” is the &lt;code&gt;required&lt;/code&gt; flag. When it says No, the call goes through without an acceptance step. The schedules still describe how you are allowed to use the data, and nothing in them suggests skipping the acceptance step lets you skip the rules.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2l2drgkxqish07t90ik2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2l2drgkxqish07t90ik2.jpg" alt="I Read the Terms for Every Paid Provider" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So it sorts into three piles. The contact providers are built for your sales team and forbid publishing. Similarweb and Particle forbid keeping anything. The financial providers leave you room to build a product.&lt;/p&gt;

&lt;p&gt;None of this is Firecrawl being sneaky. Licensed data has always come with rules like these. What changed is that it now sits behind the same &lt;code&gt;firecrawl scrape&lt;/code&gt; you use on a public web page, where the only rules are robots.txt and the site’s terms. One command, two completely different legal situations, and nothing in the syntax tells you which one you are in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tracker That Survives the Terms
&lt;/h2&gt;

&lt;p&gt;The thing (h) forbids, keeping your own history to answer later questions, is a thing Particle sells you instead. &lt;code&gt;podcasts/mentions/timeseries&lt;/code&gt; costs 15 credits and returns the whole history, bucketed by day, week or month, in one call. You don’t need a database if every run asks for everything.&lt;/p&gt;

&lt;p&gt;I pointed it at Anthropic, monthly, since January. The episode counts climbed steeply all year. It looked like a story. Then I ran the same call on Coca-Cola as a control (a company that didn’t get more famous in 2026), and it climbed steeply too.&lt;/p&gt;

&lt;p&gt;That is not Anthropic or Coca-Cola. That is Particle’s index growing. More shows transcribed, more episodes covered, more mentions of everybody. A raw mention count from a source whose coverage changes every month will tell you your brand is exploding when the source is the thing exploding.&lt;/p&gt;

&lt;p&gt;The fix is old: divide by a control. Same source, same window, a company whose real share of the conversation should hold steady. Whatever index growth inflates in one, it inflates in the other.&lt;/p&gt;

&lt;h3&gt;
  
  
  The second gotcha: don’t pass a domain
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;company_id&lt;/code&gt; says it takes a slug, a domain or an ID. &lt;code&gt;anthropic.com&lt;/code&gt; worked. &lt;code&gt;coca-cola.com&lt;/code&gt; came back as &lt;strong&gt;Simply Orange&lt;/strong&gt; , one juice brand out of Coca-Cola’s two hundred, with a handful of mentions. No error, no warning. If I hadn’t looked at the &lt;code&gt;company&lt;/code&gt; block in the response, I’d have used a juice brand as my control and believed the result.&lt;/p&gt;

&lt;p&gt;So the script resolves names first with &lt;code&gt;entities/search&lt;/code&gt; (5 credits) and takes the exact match.&lt;/p&gt;

&lt;h3&gt;
  
  
  The script
&lt;/h3&gt;

&lt;p&gt;No SQLite, no saved files. It prints to the terminal and forgets:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo8yqf7fv53js7kfvs76i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo8yqf7fv53js7kfvs76i.jpg" alt="The script" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;firecrawl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scrape&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;particle/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--options&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):])[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alexandria&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;company_slug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Never pass a bare domain: coca-cola.com resolved to Simply Orange.
&lt;/span&gt;    &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;entities/search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;company&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;})[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;exact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;match_quality&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exact&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;no company found for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;company&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;slug&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;slug&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;since&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;podcasts/mentions/timeseries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;company_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;interval&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;month&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;published_after&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;since&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;start&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;episode_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buckets&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;control&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;since&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-01-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;company_slug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;since&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;company_slug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;control&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;since&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;month &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; episodes per &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;control&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; episode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;ratio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ratio&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;6.2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; __main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="n"&gt;python3&lt;/span&gt; &lt;span class="n"&gt;podcast_share&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Anthropic&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The Coca-Cola Company&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each run is two searches and two timeseries calls: 40 credits. Monthly, that’s 4% of the free 1,000. Weekly, about 17%. Daily is 1,200, which is more than the free plan.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I can show you
&lt;/h3&gt;

&lt;p&gt;And (a) bites the post itself: Particle’s counts are Podcast Data, so I’m not printing them. The ratio is a number I computed from them, which I think puts it on my side of the line. I am not a lawyer, and you should make that call for your own use, not borrow mine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;month Anthropic episodes per The Coca-Cola Company episode
2026-01 1.57
2026-02 2.94
2026-03 3.87
2026-04 3.27
2026-05 3.15
2026-06 3.57
2026-07 2.78
2026-08 3.14
2026-09 4.89
2026-10 3.89

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read that against the raw curve, which climbed all year. Corrected for index growth, Anthropic’s share roughly doubled from January to February and then sat around three for six months. September is the only real spike. October is a partial month as I write this. The steep line was mostly Particle getting bigger.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the Schedule Before You Write the Recipe
&lt;/h2&gt;

&lt;p&gt;The rule from the &lt;a href="https://dev.to/eristoddle/before-you-write-a-scraper-check-firecrawl-alexandria-2652"&gt;Alexandria post&lt;/a&gt; was check the catalog before you write a scraper. Universal Scrape adds a step after that: check the terms before you write anything that stores, compares or publishes.&lt;/p&gt;

&lt;p&gt;The check is one free command per provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firecrawl alexandria terms show &amp;lt;provider&amp;gt; &lt;span class="nt"&gt;--json&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it says the provider is not in the terms catalog, you’re in normal scraping territory, with the site’s own terms and everything the series has said so far. If it returns a schedule, search it for “store”, “retain”, “available to” and “agent” before you design anything. Those four words decide whether your idea is a cron job, a dashboard for your own team, or nothing.&lt;/p&gt;

&lt;p&gt;My podcast tracker ended up as a 40-line script that forgets everything it learns the moment it prints. That’s less than I wanted. It’s also the only version I can actually run, and it gets right what the version I planned would have gotten wrong: the growth curve was mostly the index.&lt;/p&gt;

&lt;p&gt;The financial providers are the ones whose terms let you build something real, which makes Fiscal.ai the next thing I want to look at.&lt;/p&gt;

</description>
      <category>firecrawl</category>
      <category>universalscrape</category>
    </item>
    <item>
      <title>Eleven Deep Research Tools That Live Inside Your Coding Agent, and the One I Forked</title>
      <dc:creator>Stephan Miller</dc:creator>
      <pubDate>Wed, 14 Oct 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/eristoddle/eleven-deep-research-tools-that-live-inside-your-coding-agent-and-the-one-i-forked-4l7p</link>
      <guid>https://dev.to/eristoddle/eleven-deep-research-tools-that-live-inside-your-coding-agent-and-the-one-i-forked-4l7p</guid>
      <description>&lt;p&gt;The first time I ran my research agent on a real topic, it ran for over an hour and I had no idea whether it was working or hung. Nothing between “started” and whatever it was eventually going to print. So I sat there watching a spinner.&lt;/p&gt;

&lt;p&gt;It was not almost done, because it had no definition of done.&lt;/p&gt;

&lt;p&gt;That agent was a fork of somebody else’s project, and before I spent another weekend modifying it to my needs I wanted to know whether I should just use one of the tools that already existed. So I took a deep look at the other tools. Eleven tools that run inside a coding agent, or that an agent can drive.&lt;/p&gt;

&lt;p&gt;I put the breakdown in my own repo as &lt;a href="https://github.com/eristoddle/deep-research-agent/blob/main/ALTERNATIVES.md" rel="noopener noreferrer"&gt;ALTERNATIVES.md&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This post is that page with the story attached.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One Way to Rank These&lt;/li&gt;
&lt;li&gt;
The Eleven

&lt;ul&gt;
&lt;li&gt;The Report Writers&lt;/li&gt;
&lt;li&gt;The Ones That Return a Table Instead of Prose&lt;/li&gt;
&lt;li&gt;The Ones That Hand You Sources, Not Conclusions&lt;/li&gt;
&lt;li&gt;The Audit Layer&lt;/li&gt;
&lt;li&gt;And STORM, Which Is a Reference Design Now&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
The One I Forked

&lt;ul&gt;
&lt;li&gt;It Would Not Install the Way I Wanted&lt;/li&gt;
&lt;li&gt;The Agent With No Tool Allowlist&lt;/li&gt;
&lt;li&gt;No Budget, No Stop Condition, No Way to Tell Working From Stuck&lt;/li&gt;
&lt;li&gt;The Part I Really Liked: Search Modules&lt;/li&gt;
&lt;li&gt;Building a Module by Discovering Its Sources Instead of Guessing Them&lt;/li&gt;
&lt;li&gt;Installing It Does Not Give You a Tool, It Starts a Research Project&lt;/li&gt;
&lt;li&gt;Everything Else That Got Bolted On&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;What It Is Bad At&lt;/li&gt;
&lt;li&gt;Using It&lt;/li&gt;
&lt;li&gt;What I Actually Took Away From This&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  One Way to Rank These
&lt;/h2&gt;

&lt;p&gt;One instinct with research tools is to rank them by depth. Which one goes deepest. Which one reads the most sources. Which one runs the longest.&lt;/p&gt;

&lt;p&gt;Depth is a dial that almost all of them have, so depth is not something to compare here.&lt;/p&gt;

&lt;p&gt;The two properties that actually decide which tool you want are shape and persistence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Answer shape.&lt;/strong&gt; A run produces one of four things. A &lt;em&gt;narrative document&lt;/em&gt;, which is chapters and prose and citations. A &lt;em&gt;matrix&lt;/em&gt;, which is N subjects by M attributes, also known as a comparison table. An &lt;em&gt;annotated source list&lt;/em&gt;, which is findings with provenance where you do the synthesis. Or a &lt;em&gt;knowledge base&lt;/em&gt;, which is a corpus that grows with new research instead of a single deliverable that ships.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fspwr08c0ev4njamivw9a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fspwr08c0ev4njamivw9a.jpg" alt="You Are Ranking These on the Wrong Axis" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Persistence.&lt;/strong&gt; A run is either ephemeral, where the findings exist once and the next run starts cold, or accumulating, where there is a store that gets consulted before anything gets fetched. An accumulating tool used twenty minutes a week beats an ephemeral one used eight hours once, if the topic is something you keep coming back to. Which, if you’re researching your own industry, it is.&lt;/p&gt;

&lt;p&gt;Two smaller axes worth checking before you commit:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source routing.&lt;/strong&gt; Does it search the open web generically, or does it know where the answers for a given kind of question actually live? Generic width does badly on any topic where vendor marketing and programmatic SEO own the first hundred results. Try researching &lt;a href="https://dev.to/eristoddle/the-cheapskates-guide-to-the-arena-leaderboard-why-i-stopped-paying-claude-opus-prices-1ipn"&gt;LLM pricing&lt;/a&gt; with a generic web sweep sometime and count how many of the top results are listicles written by other AI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Provider lock.&lt;/strong&gt; Is it welded to one model vendor, or can it run on whatever you have, up to and including a local model?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Eleven
&lt;/h2&gt;

&lt;p&gt;Everything below runs inside a coding agent or is something an agent can drive. Skills, MCP servers, CLIs, libraries. I deliberately left out the hosted deep research products, the ChatGPT and Gemini and Perplexity tier, because their output lives in somebody else’s UI. The entire reason to run research from an agent is that the findings land in your own files.&lt;/p&gt;

&lt;p&gt;Stars and last-push months here were verified against the GitHub API on 2026-10-10. Everything else in this section is taken from each project’s own documentation. I haven’t independently reproduced anybody’s benchmark placement or run time.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Form&lt;/th&gt;
&lt;th&gt;Answer shape&lt;/th&gt;
&lt;th&gt;Persistence&lt;/th&gt;
&lt;th&gt;Stars&lt;/th&gt;
&lt;th&gt;Last push&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/LearningCircuit/local-deep-research" rel="noopener noreferrer"&gt;local-deep-research&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;MCP + lib + CLI&lt;/td&gt;
&lt;td&gt;Narrative report&lt;/td&gt;
&lt;td&gt;Encrypted SQLite history + your own docs&lt;/td&gt;
&lt;td&gt;9.2k&lt;/td&gt;
&lt;td&gt;2026-10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/jordan-gibbs/hyperresearch" rel="noopener noreferrer"&gt;hyperresearch&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Claude Code skill + MCP + CLI&lt;/td&gt;
&lt;td&gt;Narrative, chaptered&lt;/td&gt;
&lt;td&gt;Markdown vault + SQLite index&lt;/td&gt;
&lt;td&gt;3.8k&lt;/td&gt;
&lt;td&gt;2026-10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/assafelovic/gpt-researcher" rel="noopener noreferrer"&gt;gpt-researcher&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Python lib (+ &lt;a href="https://github.com/assafelovic/gptr-mcp" rel="noopener noreferrer"&gt;MCP&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;Narrative report&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;30k&lt;/td&gt;
&lt;td&gt;2026-10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/mvanhorn/last30days-skill" rel="noopener noreferrer"&gt;last30days-skill&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Claude Code skill&lt;/td&gt;
&lt;td&gt;Ranked brief&lt;/td&gt;
&lt;td&gt;SQLite archive of past briefs&lt;/td&gt;
&lt;td&gt;63.9k&lt;/td&gt;
&lt;td&gt;2026-10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/Future-House/paper-qa" rel="noopener noreferrer"&gt;paper-qa&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Python lib + CLI&lt;/td&gt;
&lt;td&gt;Cited answer&lt;/td&gt;
&lt;td&gt;Reusable index under &lt;code&gt;~/.pqa/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;9.3k&lt;/td&gt;
&lt;td&gt;2026-09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/langchain-ai/local-deep-researcher" rel="noopener noreferrer"&gt;local-deep-researcher&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;LangGraph app&lt;/td&gt;
&lt;td&gt;Summary + sources&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;9.4k&lt;/td&gt;
&lt;td&gt;2026-09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/zilliztech/deep-searcher" rel="noopener noreferrer"&gt;deep-searcher&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Python lib + CLI&lt;/td&gt;
&lt;td&gt;Narrative report&lt;/td&gt;
&lt;td&gt;Milvus vector DB&lt;/td&gt;
&lt;td&gt;8.3k&lt;/td&gt;
&lt;td&gt;2026-09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/zamalali/DeepGit" rel="noopener noreferrer"&gt;DeepGit&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;MCP + CLI + lib&lt;/td&gt;
&lt;td&gt;Ranked matrix&lt;/td&gt;
&lt;td&gt;LanceDB vector index&lt;/td&gt;
&lt;td&gt;919&lt;/td&gt;
&lt;td&gt;2026-08&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/hoolulu/deep-research" rel="noopener noreferrer"&gt;hoolulu/deep-research&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cross-platform skill&lt;/td&gt;
&lt;td&gt;Narrative, chaptered&lt;/td&gt;
&lt;td&gt;Folder of dated reports&lt;/td&gt;
&lt;td&gt;598&lt;/td&gt;
&lt;td&gt;2026-08&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/dialog-tools/reddit-research-mcp" rel="noopener noreferrer"&gt;reddit-research-mcp&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;MCP server&lt;/td&gt;
&lt;td&gt;Cited findings&lt;/td&gt;
&lt;td&gt;Saved feeds&lt;/td&gt;
&lt;td&gt;254&lt;/td&gt;
&lt;td&gt;2026-09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/damionrashford/RivalSearchMCP" rel="noopener noreferrer"&gt;RivalSearchMCP&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;MCP server&lt;/td&gt;
&lt;td&gt;Structured JSON&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;132&lt;/td&gt;
&lt;td&gt;2026-10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The Report Writers
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz96lbwwrdez4otgs32i4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz96lbwwrdez4otgs32i4.jpg" alt="The Report Writers" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/LearningCircuit/local-deep-research" rel="noopener noreferrer"&gt;local-deep-research&lt;/a&gt;&lt;/strong&gt; is the most complete package in the table. Per-domain engines for arXiv, PubMed, Semantic Scholar, NASA ADS, GitHub, SearXNG and the Wayback Machine. An encrypted SQLCipher history of every run you have ever done. A personal document library that gets indexed and searched right alongside the live results. It runs fully offline on Ollama or llama.cpp if you want it to. Use this one when the corpus is what you want and you’ll be coming back to the same subject for months.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/jordan-gibbs/hyperresearch" rel="noopener noreferrer"&gt;hyperresearch&lt;/a&gt;&lt;/strong&gt; is a sixteen-step pipeline with three tiers, and the top tier, &lt;code&gt;dissertation&lt;/code&gt;, is opt-in only. It partitions your topic into four to ten chapters and then loops the research steps once per chapter. That’s how you get 25,000 to 80,000 words out of it. Markdown is the source of truth and SQLite is the cache, so the vault stays portable and greppable. It’s Claude-only and it puts Opus on the synthesis and critique roles, so a long run isn’t cheap. Reach for it when you want one large chaptered document at the end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/assafelovic/gpt-researcher" rel="noopener noreferrer"&gt;gpt-researcher&lt;/a&gt;&lt;/strong&gt; is the mature baseline. Thirty thousand stars and the one most likely to already be supported by whatever you’re building on top of. Its MCP surface, specifically &lt;code&gt;get_research_context&lt;/code&gt; and &lt;code&gt;get_research_sources&lt;/code&gt;, hand back the raw material separately from the written report. That means your agent can do the writing instead of getting handed prose. One caveat: you need a paid search API to get good results out of it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/hoolulu/deep-research" rel="noopener noreferrer"&gt;hoolulu/deep-research&lt;/a&gt;&lt;/strong&gt; produces the same chaptered shape as hyperresearch but it’s portable across Claude Code, Codex, Cursor, OpenCode, Windsurf and Cline, and it is multilingual.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/langchain-ai/local-deep-researcher" rel="noopener noreferrer"&gt;local-deep-researcher&lt;/a&gt;&lt;/strong&gt; is the smallest readable implementation of the reflect-then-fill-the-gap loop that all of these are variations on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zilliztech/deep-searcher" rel="noopener noreferrer"&gt;deep-searcher&lt;/a&gt;&lt;/strong&gt; inverts the whole premise: research over &lt;em&gt;your&lt;/em&gt; private corpus, with the web as an optional supplement. That’s the opposite of everything else on this list.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Ones That Return a Table Instead of Prose
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsxbfc2gr0q9wv29e9vjv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsxbfc2gr0q9wv29e9vjv.jpg" alt="The Ones That Return a Table Instead of Prose" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zamalali/DeepGit" rel="noopener noreferrer"&gt;DeepGit&lt;/a&gt;&lt;/strong&gt; does GitHub-only tool discovery and returns a scored comparison table. It preserves your actual query intent, meaning must-haves, nice-to-haves and anti-patterns, instead of flattening everything into keywords. This is ethe right tool for “find me the N projects that do X,” which is the question this entire post is an answer to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/mvanhorn/last30days-skill" rel="noopener noreferrer"&gt;last30days-skill&lt;/a&gt;&lt;/strong&gt; is recency-windowed research across social and forum sources. Reddit, X, Hacker News, YouTube transcripts, Bluesky, Polymarket odds. It ranks by actual engagement, not search position, so it answers “what are people saying about this right now.” Add &lt;code&gt;--store&lt;/code&gt; and the briefs accumulate into a local SQLite database you can run scheduled watchlists and digests against.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Ones That Hand You Sources, Not Conclusions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Future-House/paper-qa" rel="noopener noreferrer"&gt;paper-qa&lt;/a&gt;&lt;/strong&gt; does academic literature with citations traceable down to page ranges, across your own PDFs plus Semantic Scholar, Crossref and Unpaywall. Use it when a claim has to be defensible, not just plausible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/dialog-tools/reddit-research-mcp" rel="noopener noreferrer"&gt;reddit-research-mcp&lt;/a&gt;&lt;/strong&gt; is semantic search across Reddit where every finding cites a real post or comment, upvote count included. This is where you get demand signals and pain points in people’s own words. Generic web search flattens all of that into blog posts &lt;em&gt;about&lt;/em&gt; the topic, written by people who also only read blog posts about the topic.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Audit Layer
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/damionrashford/RivalSearchMCP" rel="noopener noreferrer"&gt;RivalSearchMCP&lt;/a&gt;&lt;/strong&gt; has no LLM inside the server at all. Every result carries a tier, freshness, corroboration and citation score out of 100, every multi-result response carries an aggregate confidence signal, and &lt;code&gt;find_conflicts&lt;/code&gt; surfaces numeric, date and polarity disagreements between sources instead of averaging them. It is an auditing layer instead of a research tool, and it composes with any of the others.&lt;/p&gt;

&lt;h3&gt;
  
  
  And STORM, Which Is a Reference Design Now
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/stanford-oval/storm" rel="noopener noreferrer"&gt;STORM&lt;/a&gt; out of Stanford did not make the table, but it deserves the mention because it’s the only project in this space whose output shape is a wiki article. It gets there by discovering perspectives from existing articles on similar topics, then simulating a conversation between a Wikipedia writer and a topic expert grounded in real sources. Which is a clever way to get an outline that is not just the first five headings an LLM associates with your topic. Last pushed 2025-09. Treat it as a reference design to steal from, not a dependency to take on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The One I Forked
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjyp6wild0xe5qmy4sdg8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjyp6wild0xe5qmy4sdg8.jpg" alt="The One I Forked, and Why It Took 45 Commits" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The pipeline in &lt;a href="https://github.com/eristoddle/deep-research-agent" rel="noopener noreferrer"&gt;deep-research-agent&lt;/a&gt; is not my design. The skills, the agent and the original strategy modules come from &lt;a href="https://github.com/Weizhena/Deep-Research-skills" rel="noopener noreferrer"&gt;Weizhena/Deep-Research-skills&lt;/a&gt; by Lan Zheng, MIT licensed, and all the credit for the structure goes there. Outline, then fields, then one agent per item, then roll the JSON up into a report. I kept that part verbatim.&lt;/p&gt;

&lt;h3&gt;
  
  
  It Would Not Install the Way I Wanted
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dev.to/eristoddle/the-agent-skills-guide-i-wish-id-had-17i1"&gt;APM&lt;/a&gt; only accepts a source whose root is a package, meaning a &lt;code&gt;SKILL.md&lt;/code&gt;, or an &lt;code&gt;apm.yml&lt;/code&gt; plus &lt;code&gt;.apm/&lt;/code&gt;, or a &lt;code&gt;plugin.json&lt;/code&gt;. Upstream ships its agent as a bare &lt;code&gt;agents/&lt;/code&gt; directory with none of those, so &lt;code&gt;apm install Weizhena/Deep-Research-skills/agents&lt;/code&gt; fails validation. Which is a problem, because the skills don’t work without the agent.&lt;/p&gt;

&lt;p&gt;So the first thing that happened was repackaging the whole thing into one APM installable bundle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apm &lt;span class="nb"&gt;install &lt;/span&gt;eristoddle/deep-research-agent &lt;span class="nt"&gt;--target&lt;/span&gt; claude
&lt;span class="c"&gt;# or&lt;/span&gt;
apm &lt;span class="nb"&gt;install &lt;/span&gt;eristoddle/deep-research-agent &lt;span class="nt"&gt;--target&lt;/span&gt; copilot

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Agent With No Tool Allowlist
&lt;/h3&gt;

&lt;p&gt;Upstream’s agent has no &lt;code&gt;tools:&lt;/code&gt; frontmatter at all, which means it &lt;a href="https://dev.to/eristoddle/the-subagents-guide-i-wish-id-had-dhh"&gt;inherits every tool the host offers&lt;/a&gt;. Under Copilot in VS Code, that includes the embedded browser and the download tooling.&lt;/p&gt;

&lt;p&gt;An agent whose instructions say “systematically explore” roughly twenty five source families, handed a browser, opened about a hundred editor tabs in a single run. In the same run it decided to write its own report-generator script rather than use &lt;code&gt;/research-report&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It’s now restricted to &lt;code&gt;WebSearch, WebFetch, Read, Write, Bash&lt;/code&gt; with an explicit prohibition on browser automation, downloads, and self-authored research scripts.&lt;/p&gt;

&lt;h3&gt;
  
  
  No Budget, No Stop Condition, No Way to Tell Working From Stuck
&lt;/h3&gt;

&lt;p&gt;Back to my spinner. Upstream tells the agent to generate “5-10 query variations,” to “read beyond the first few results,” and to cover that merged list of about twenty five source families. There is no cap on searches, no cap on fetches, no cap on link depth, and no definition of done.&lt;/p&gt;

&lt;p&gt;There is now a three-level depth setting, defaulting to &lt;code&gt;standard&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Searches&lt;/th&gt;
&lt;th&gt;Fetches&lt;/th&gt;
&lt;th&gt;Link depth&lt;/th&gt;
&lt;th&gt;Modules&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;quick&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;standard&lt;/code&gt; &lt;em&gt;(default)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;deep&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh8xmnfgta9lx1way68i8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh8xmnfgta9lx1way68i8.jpg" alt="No Budget, No Stop Condition, No Way to Tell Working From Stuck" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set it per run with &lt;code&gt;/research-deep deep&lt;/code&gt;, per project with &lt;code&gt;execution.depth&lt;/code&gt; in &lt;code&gt;outline.yaml&lt;/code&gt;, or ad hoc by naming explicit numbers in the task prompt. Explicit numbers win, then the named level, then the outline, then the default.&lt;/p&gt;

&lt;p&gt;The agent now reports budget state as it goes, like &lt;code&gt;[deep: 3/20 searches, 5/30 fetches]&lt;/code&gt;, and it stops at the ceiling. The budget also propagates down to every per-item agent, along with the tool prohibitions, so the constraints survive the handoff. And the fetch budget counts &lt;em&gt;every&lt;/em&gt; retrieval attempt.&lt;/p&gt;

&lt;p&gt;Instructions in the prompt that contradicted the budget got rewritten, not left in there to fight it. That sounds obvious. It’s also the step everyone skips when they bolt a limit onto an existing prompt, and then they wonder why the model ignores the limit.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Part I Really Liked: Search Modules
&lt;/h3&gt;

&lt;p&gt;Search modules are what make this repo worth having instead of just a patched fork.&lt;/p&gt;

&lt;p&gt;Most research tools search the open web generically and then scale by adding more sources. This one tries to search fewer, better places, and it decides where to look &lt;em&gt;before&lt;/em&gt; it searches anything. That’s what a search module is: a per-domain routing file with a source list, an access method per source, an ordering rule for which sources outrank which, and documented workarounds for the ones that block agent fetching.&lt;/p&gt;

&lt;p&gt;There are twelve of them now. Five are upstream’s, and those five assume you are debugging code or reading papers: &lt;code&gt;general-web&lt;/code&gt;, &lt;code&gt;github-debug&lt;/code&gt;, &lt;code&gt;stackoverflow&lt;/code&gt;, &lt;code&gt;academic-papers&lt;/code&gt;, &lt;code&gt;chinese-tech&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now there is also an AI ecosystem and market family:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;benchmarks&lt;/code&gt;&lt;/strong&gt; puts independent evaluators first, makes the configuration and observation date mandatory, and labels self-reported scores as self-reported.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;model-releases&lt;/code&gt;&lt;/strong&gt; ranks docs and deprecation pages above announcement posts, and wants model IDs, not marketing names.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;pricing&lt;/code&gt;&lt;/strong&gt; will not quote a price from anything but the provider’s own page, and records unit, host and date with it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;vendor-landscape&lt;/code&gt;&lt;/strong&gt; builds the competitive set from vendors’ own comparison pages, and keeps claim separate from evidence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plus &lt;code&gt;agent-tooling&lt;/code&gt;, which is its own family and covers the things you install and run, not call over an API. Agent CLIs and IDEs, MCP servers, skills, plugins. The questions you actually have about those are the config format, the permission model and the version history.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv9bwfuvjbcyde7sq6483.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv9bwfuvjbcyde7sq6483.jpg" alt="The Part I Actually Care About: Search Modules" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then two more that are not about technology at all. &lt;strong&gt;&lt;code&gt;competitor-content&lt;/code&gt;&lt;/strong&gt; samples what has already been published on a topic, reading three to five top pages for &lt;em&gt;outline&lt;/em&gt;, not prose, plus People Also Ask and forum questions, and reports the union of subtopics and the gap. It’s also explicit about its limits: &lt;code&gt;WebSearch&lt;/code&gt; returns a result list, not a SERP, so ranking position, search volume and keyword difficulty are unavailable. I would rather a module tell the agent “you can’t know this” than let it produce a confident number out of nothing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;demand-signals&lt;/code&gt;&lt;/strong&gt; answers “what do people keep complaining about, in their own words, across places that do not talk to each other.” That needs raw user language, not a ranked page or a spec sheet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building a Module by Discovering Its Sources Instead of Guessing Them
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;/research-add-module&lt;/code&gt; makes you do the source discovery for real. Draft the questions the module has to answer. Run them as plain &lt;code&gt;general-web&lt;/code&gt; queries. Tally which domains actually held the answers. Then work out and &lt;em&gt;test&lt;/em&gt; how to query each one, whether that’s a &lt;code&gt;site:&lt;/code&gt; query, the site’s own search URL, a stable index page you can fetch directly, or a note recording that it blocks fetching entirely. It registers the result, then checks whether the new module actually beats &lt;code&gt;general-web&lt;/code&gt; on the original questions, and offers to throw it away if it doesn’t.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;demand-signals&lt;/code&gt; got built that way, by running the discovery pass across seven unrelated probe topics instead of writing a source list that looked right. What came out of it was more specific than anything I’d have guessed. Discourse’s &lt;code&gt;search.json&lt;/code&gt; works and I confirmed it on two unrelated instances. Other forum software falls back to a &lt;code&gt;site:&lt;/code&gt; query, because XenForo’s own community confirms its search is POST-only with no fetchable route. People Also Ask earns its own dedicated query pass. Amazon product Q&amp;amp;A went in as unreachable, 503 on every product I tested, recorded rather than silently dropped.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing It Does Not Give You a Tool, It Starts a Research Project
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fozkbd6c96w39ofdzq3p5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fozkbd6c96w39ofdzq3p5.jpg" alt="Installing It Does Not Give You a Tool, It Starts a Research Project" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You do not install this and end up with a research agent. You install it into a project, and from that point the copy inside that project starts drifting toward the kind of research that project does. Three mechanisms do it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Runs accumulate into a tree, not a pile.&lt;/strong&gt; Every run lives under one root, &lt;code&gt;research/&lt;/code&gt; by default, and &lt;code&gt;research/INDEX.md&lt;/code&gt; records a tree, not a list. Research does not happen once. One run’s findings point at the next one, so the index keeps a map of which run spawned which, plus a &lt;code&gt;**Leads**&lt;/code&gt; checklist per run of the directions that run opened and I haven’t chased yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources that keep earning their place get promoted.&lt;/strong&gt; &lt;code&gt;/research-harvest&lt;/code&gt; scans every run under the root and tallies which source URLs keep showing up. A URL becomes a promotion candidate once it has appeared in at least three runs and actually supported a field in at least two of them. It never writes into a module itself. It writes a candidate list for a human to choose from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The modules it feeds live in the project and survive reinstalls.&lt;/strong&gt; Local modules go in &lt;code&gt;.agents/web-search-modules-local/&lt;/code&gt;, which APM doesn’t own. The router checks that directory before its own table and the local module wins a name conflict.&lt;/p&gt;

&lt;p&gt;Put those three together and you have a loop. Run research, find out which sources actually answered something, promote the repeat domains into a module that lives in this project, and the next run here routes better than the last one did. A client repo ends up knowing that client’s competitive set. The repo where I research AI tooling ends up knowing where the real leaderboards and deprecation pages are and ignoring everything else.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl6phg3tfctzrn0wq6jl1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl6phg3tfctzrn0wq6jl1.jpg" alt="Everything Else That Got Bolted On" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Everything Else That Got Bolted On
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Routing lives in a file, not in the prompt.&lt;/strong&gt; Upstream hardcodes five trigger-to-file lines into the agent’s system prompt. That works at five modules and falls over as the library grows, because overlapping triggers get resolved by dropping one, and every module costs system-prompt context on every task whether or not it’s relevant. Routing now lives in &lt;code&gt;skills/web-search-modules/ROUTING.md&lt;/code&gt;, which the agent reads before any search. Adding a module is one file plus one row and the prompt never changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A bounded fetch escalation ladder.&lt;/strong&gt; &lt;code&gt;WebFetch&lt;/code&gt; returns 403s and bot challenges and JS-only shells often enough to lose real sources. The agent can escalate one URL through &lt;code&gt;crwl&lt;/code&gt; (crawl4ai) if it is installed, then Firecrawl if both &lt;a href="https://dev.to/eristoddle/firecrawl-cli-setup-skip-the-installer-that-rewrites-your-editors-2klj"&gt;the CLI is on &lt;code&gt;PATH&lt;/code&gt; and &lt;code&gt;FIRECRAWL_API_KEY&lt;/code&gt; is set&lt;/a&gt;. Every rung is stdout-only and bounded, no install attempts, and the whole ladder doesn’t buy an extra fetch slot because it’s one logical fetch of the same page. I wrote about that whole mess separately in &lt;a href="https://dev.to/eristoddle/what-to-do-when-your-ai-coding-agent-cant-read-a-web-page-2f0i"&gt;What to Do When Your AI Coding Agent Can’t Read a Web Page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;unreachable[]&lt;/code&gt; is its own output channel.&lt;/strong&gt; A page nothing could fetch is provenance about a source. It’s not a reason to mark a field uncertain when that field got answered through a documented substitute. The report renders an &lt;code&gt;## Unreachable sources&lt;/code&gt; section by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/research-enumerate&lt;/code&gt;&lt;/strong&gt; is for when the hard part is finding the items at all. The pipeline only had one shape of work, which was “here are the items, go deep on each.” That doesn’t answer “what exists in this space” when each item needs three shallow facts and the difficulty is enumeration. It sweeps aggregators first, the directories and registries and awesome-lists that list the leaves, before going after the leaves themselves. Its real discipline is the coverage declaration: a category the sweep never reached gets its own subsection saying so and naming the exhausted budget as the reason, never silently omitted, because an unreached category that goes unmentioned reads as a negative result to every later reader.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What It Is Bad At
&lt;/h2&gt;

&lt;p&gt;This repo produces a &lt;strong&gt;matrix&lt;/strong&gt;. You define items and fields, it researches every field for every item with one agent per item, and the report rolls the values up. It is a good fit for “these twelve models across these fifteen attributes.” It is a bad fit for “write me a long document about this topic,” and there’s no reason to force it into that job when six tools listed in this post do it better.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fitnffihr51rrijytgg8x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fitnffihr51rrijytgg8x.jpg" alt="What It Is Bad At" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s also human-in-the-loop on purpose. The outline gets reviewed and amended before any research runs. That costs you a step. What it buys is the ability to fix a bad research plan before you spend an hour executing it.&lt;/p&gt;

&lt;p&gt;And field counts matter a lot. A 42-item outline with 96 fields is roughly four thousand researched values and it will not finish. Keep field lists to fifteen or twenty and prefer &lt;code&gt;items_per_agent: 1&lt;/code&gt;, so each finished agent yields a complete file instead of an all-or-nothing batch. Ask me how I learned that one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/research &amp;lt;topic&amp;gt; # interactive: builds outline.yaml + fields.yaml
/research-enumerate # breadth-first: catalog what exists into catalog.md + outline.yaml
/research-add-items # amend the item list
/research-add-fields # amend the field list
/research-add-module # build a search module for a domain the existing ones miss
/research-deep # one agent per item -&amp;gt; one JSON per item in results/
/research-report # roll the JSON files up into report.md
/research-harvest # hand-invoked: tally recurring sources across runs

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/research&lt;/code&gt; and &lt;code&gt;/research-deep&lt;/code&gt; pick the host-native entry point. Claude launches &lt;code&gt;web-search-agent&lt;/code&gt;, Copilot launches &lt;code&gt;Web Research Writer&lt;/code&gt;. The skills do not work without the packaged agents, which is the entire reason the bundle exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Actually Took Away From This
&lt;/h2&gt;

&lt;p&gt;Most of the work in that fork was not features. Count them up and the majority of the commits are guardrails: a tool allowlist, a search budget, a stop condition, a rule about what counts as a fetch, a prohibition on writing your own scripts, and a routing file so the prompt stops growing. The pipeline design was already good. It’s the reason I forked it.&lt;/p&gt;

&lt;p&gt;I will do the ALTERNATIVES page again. Writing “here are eleven tools, nine of them beat mine at something, here is the one job mine is actually for” clarified the repo more than any feature I added.&lt;/p&gt;

&lt;p&gt;Also, the part I worked on the most is a part I never planned. I built a matrix generator. Then an index, because run folders were cluttering up repos where I was also writing code. Then a harvest command, because I kept hand-copying the same three URLs into modules. The loop those three turned out to make showed up on its own and became the reason to keep using the thing.&lt;/p&gt;

</description>
      <category>deepresearchtools</category>
      <category>codingagent</category>
      <category>researchagent</category>
      <category>deepresearchagent</category>
    </item>
    <item>
      <title>Claude Haiku 5.5 Is 90% Cheaper Until Your Prompt Hits 100K</title>
      <dc:creator>Stephan Miller</dc:creator>
      <pubDate>Tue, 13 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/eristoddle/claude-haiku-55-is-90-cheaper-until-your-prompt-hits-100k-24da</link>
      <guid>https://dev.to/eristoddle/claude-haiku-55-is-90-cheaper-until-your-prompt-hits-100k-24da</guid>
      <description>&lt;p&gt;Anthropic now sells a model for the same 50 cents per million output tokens as GLM-5.3-Flash.&lt;/p&gt;

&lt;p&gt;That’s the company whose Fable 5.1 costs $50 out. GLM-5.3-Flash is the Chinese open-weights model that’s been anchoring my cheapskate table for six weeks while everybody with a bigger brand looked down at it. On October 7, Claude Haiku 5.5 moved into the same price bracket and scored a point higher on Artificial Analysis. I was ready to write the “Anthropic finally gets it” post. Then I read the pricing page all the way to the bottom. You know how that goes.&lt;/p&gt;

&lt;p&gt;Same week, Meta went the other way. Its first real frontier model, Muse Wonder, launched October 12 at exactly what Claude Opus 5.5 costs, and it scores lower than Opus. And the free stealth model that was number one on OpenRouter last week disappeared on October 5. Its traffic didn’t go to a better model. It went to the next free one. So this is a read-the-footnotes week. The sticker price on almost every model that launched lies to you somewhere.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Claude Haiku 5.5 moved into GLM’s neighborhood

&lt;ul&gt;
&lt;li&gt;The 100K trapdoor&lt;/li&gt;
&lt;li&gt;It’s chatty&lt;/li&gt;
&lt;li&gt;Arena hasn’t rated it yet&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Meta built a frontier model and priced it like Opus&lt;/li&gt;
&lt;li&gt;
Space Bunny left, and the free traffic found a new home

&lt;ul&gt;
&lt;li&gt;DeepSeek V4.1 Flash got the paying customers&lt;/li&gt;
&lt;li&gt;Step 5 Preview got the freeloaders&lt;/li&gt;
&lt;li&gt;One more launch: Mistral Large 4&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The cheapskate table: Argon still owns the ceiling, and the edges got sharp&lt;/li&gt;
&lt;li&gt;
Horror stories

&lt;ul&gt;
&lt;li&gt;The 100K trapdoor&lt;/li&gt;
&lt;li&gt;GitSpawn: your repo’s git config can run code&lt;/li&gt;
&lt;li&gt;PixelLeak: the agent proved its work in public&lt;/li&gt;
&lt;li&gt;The free week ends Friday&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;What’s coming&lt;/li&gt;
&lt;li&gt;Finally&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Claude Haiku 5.5 moved into GLM’s neighborhood
&lt;/h2&gt;

&lt;p&gt;Here’s the pitch, and most of it holds up. &lt;a href="https://platform.claude.com/docs/en/models/haiku-5-5/whats-new-haiku-5-5" rel="noopener noreferrer"&gt;Claude Haiku 5.5&lt;/a&gt; costs $0.10 in and $0.50 out per million tokens. Haiku 4.5 was $1 and $5, so per token that’s a 90 percent cut. It gets a 1M context window (Haiku 4.5 had 200K), 128K output tokens, and the effort parameter, which no Haiku has had before. Adaptive thinking is on by default, so it decides for itself when to think.&lt;/p&gt;

&lt;p&gt;On &lt;a href="https://artificialanalysis.ai/models/claude-haiku-5-5" rel="noopener noreferrer"&gt;Artificial Analysis&lt;/a&gt;, Haiku 5.5 at max effort scores 43. GLM-5.3-Flash scores 42, Gemini 3.8 Flash 41, and GPT-6 Luna 38. That makes it the smartest model at the 50-cent floor. It’s also fast. AA clocks it at about 237 tokens a second, almost four times GLM-5.3-Flash’s 62. And AA puts it in the good corner of its intelligence-versus-cost chart.&lt;/p&gt;

&lt;p&gt;On OpenRouter it did 1.35 trillion tokens in its first week, second on the New &amp;amp; Trending list. Anthropic’s share of OpenRouter requests went up 59 percent. That’s still only 3.9 percent of requests, but it’s moving.&lt;/p&gt;

&lt;p&gt;So why am I not putting it in the cheapskate table? Three reasons, and the third one is my own rule.&lt;/p&gt;

&lt;h3&gt;
  
  
  The 100K trapdoor
&lt;/h3&gt;

&lt;p&gt;Haiku 5.5’s price has a cliff at 100,000 prompt tokens. Under the line you pay $0.10/$0.50. Over it you pay $0.50/$2.50, and the higher rate applies to the whole request, not just the tokens past the line. eesel did &lt;a href="https://www.eesel.ai/blog/claude-haiku-5-5-pricing" rel="noopener noreferrer"&gt;the math&lt;/a&gt;: a 90K prompt with 1K of output costs $0.0095. Make it 110K and it costs $0.0575. That’s about six times the price for 22 percent more tokens. Who thought this up? Cached tokens count toward the line too, so caching doesn’t save you from crossing it.&lt;/p&gt;

&lt;p&gt;And you’ll hit the line sooner than you think. Haiku 5.5 uses the newer Claude tokenizer, so the same text comes out about 30 percent more tokens than on Haiku 4.5. Anthropic’s own &lt;a href="https://platform.claude.com/docs/en/models/haiku-5-5/whats-new-haiku-5-5" rel="noopener noreferrer"&gt;migration notes&lt;/a&gt; say that, and they also say Haiku 5.5 keeps thinking blocks from every earlier turn in context, billed as input. Haiku 4.5 only kept the latest turn’s. So a long agent conversation grows faster on 5.5, and agent conversations are exactly where you hit 100K.&lt;/p&gt;

&lt;h3&gt;
  
  
  It’s chatty
&lt;/h3&gt;

&lt;p&gt;Thinking tokens are output tokens, and Haiku 5.5 thinks a lot. AA’s page shows it used 440 million output tokens to get through the Intelligence Index. Two issues ago I wrote about &lt;a href="https://dev.to/eristoddle/sonnet-55-vs-opus-55-the-cheap-claude-costs-more-6n5"&gt;Sonnet 5.5 at max effort&lt;/a&gt; costing more per task than Opus because it burned 410 million. The small Claude now out-talks the medium one. At 50 cents out it’s still cheap in absolute terms. But “cheap per token” and “cheap per job” are different numbers, and with Claude you have to work out the second one yourself. There’s one more gotcha in the docs: thinking tokens count against &lt;code&gt;max_tokens&lt;/code&gt;. If you’re migrating code with a small limit, you can get a response that’s all thinking block and no answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Arena hasn’t rated it yet
&lt;/h3&gt;

&lt;p&gt;My cheapskate method only picks models with an Arena rating, and Haiku 5.5 doesn’t have one yet. Next week it probably will. If it lands within 50 points of the leader in any category, it ties GLM-5.3-Flash on price, and then it gets interesting.&lt;/p&gt;

&lt;p&gt;If your prompts are short (classification, routing, extraction, subagent grunt work), Haiku 5.5 might be the best 50-cent model you can buy, and it’s fast. If your prompts are long agent histories, check your token counts on the new tokenizer before you switch anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meta built a frontier model and priced it like Opus
&lt;/h2&gt;

&lt;p&gt;Meta’s &lt;a href="https://techcrunch.com/2026/10/12/meta-releases-its-first-frontier-model-muse-wonder/" rel="noopener noreferrer"&gt;Muse Wonder&lt;/a&gt; launched Monday, along with a bigger sibling called Muse Wonder Full. It’s the first thing Meta has shipped since rebuilding its AI group that it’s willing to line up against Fable 5.1 and GPT-6 Astra. They’re agent models: they plan, hand work off to sub-agents, call tools in parallel, and take text, images, video, audio, and PDFs with a 1M context window.&lt;/p&gt;

&lt;p&gt;The price is $4 in, $0.20 cached, and $20 out. Claude Opus 5.5 costs the same, to the penny. Meta’s Alexandr Wang had said API pricing would be “meaningfully below” the rivals (&lt;a href="https://www.implicator.ai/meta-muse-wonder-ranks-below-claude-opus/" rel="noopener noreferrer"&gt;Implicator has the quote&lt;/a&gt;). It isn’t.&lt;/p&gt;

&lt;p&gt;On Artificial Analysis, the Muse Wonder you can actually call through the API scores 52. Opus 5.5 scores 58. Muse Wonder Full scores 56, but Full isn’t on the API. You get it through &lt;a href="https://dev.to/gabrielanhaia/zuckerbergs-best-ai-model-isnt-in-metas-api-you-need-a-50-muse-code-plan-to-use-it-j3j"&gt;a $50 Muse Code plan&lt;/a&gt;. So the model with the Opus-level score is behind a subscription, and the one with the Opus-level price scores six points lower.&lt;/p&gt;

&lt;p&gt;Meta’s own chart has Wonder Full winning &lt;a href="https://felloai.com/muse-wonder/" rel="noopener noreferrer"&gt;7 of 14 rows&lt;/a&gt;, including 57.5 on something called SWE-Marathon against Opus 5.5’s 46.3. Read the footnotes, though. Wonder Full ran that one at xhigh effort while the other models ran at max, and the model card itself says the row “is not a controlled common-harness comparison.” Meta also calls its competitor runs “best-effort” and admits the prompts “may not be optimally tuned for proprietary models.” I’ve seen that move before. Meta graded the other team’s homework, and you should read the chart that way until somebody independent runs the numbers.&lt;/p&gt;

&lt;p&gt;The weights are closed, so this isn’t the Llama-era Meta. And Meta already showed us its pricing style in August with the Muse Code “contributor” tier, where you got a discount in exchange for letting Meta train on your prompts. This time there’s no discount. It’s not on Arena yet either, so no cheapskate math. My read: if you already pay Opus prices, there’s no reason to switch to the model that scores lower for the same money. If Wonder Full ever gets an API at $20 out, that’s a different conversation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Space Bunny left, and the free traffic found a new home
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/eristoddle/gemini-4-argon-won-every-arena-category-you-cant-use-it-4fc9"&gt;Last week&lt;/a&gt; I said that when Space Bunny Alpha’s free ride ended, we’d find out how much of its 38.5 trillion tokens came from people who actually wanted the model. The free ride ended October 5. &lt;a href="https://x.com/OpenRouter/status/2107139469174542636" rel="noopener noreferrer"&gt;OpenRouter posted&lt;/a&gt; that the stealth period was over and the model “will be revealed soon.” It still hasn’t been. The best guess is still &lt;a href="https://codersera.com/blog/space-bunny-alpha-stealth-model-2026/" rel="noopener noreferrer"&gt;MiniMax M3.1-Flash-Preview&lt;/a&gt;, and that’s still unconfirmed. Space Bunny is number two for the trailing month at 56.7 trillion tokens. It doesn’t show up in this week’s top 10 at all.&lt;/p&gt;

&lt;p&gt;So where did the traffic go? Two places.&lt;/p&gt;

&lt;h3&gt;
  
  
  DeepSeek V4.1 Flash got the paying customers
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://openrouter.ai/rankings" rel="noopener noreferrer"&gt;OpenRouter’s weekly board&lt;/a&gt; through October 12 has DeepSeek V4.1 Flash at number one with 40.5 trillion tokens, up 43 percent from 28.4 trillion last week. It’s also number one for the day and the month (109 trillion). DeepSeek is now 24.5 percent of all OpenRouter requests. Z.ai, the company behind GLM, more than doubled its requests (up 107 percent, to 13.4 percent).&lt;/p&gt;

&lt;p&gt;If you have to start paying, that’s not a bad place to land. DeepSeek charges $0.15/$0.60 direct, AA gives it 39, and it pushes about 199 tokens a second, which is more than three times GLM-5.3-Flash’s speed. A lot of Space Bunny’s users apparently did the math and decided 60 cents was close enough to free.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 Preview got the freeloaders
&lt;/h3&gt;

&lt;p&gt;Number three this week is a model most people hadn’t heard of: StepFun’s &lt;a href="https://openrouter.ai/stepfun/step-5-preview" rel="noopener noreferrer"&gt;Step 5 Preview&lt;/a&gt;, at 12.1 trillion tokens in its first week on OpenRouter. It’s a 600B-parameter mixture-of-experts with 27B active, and it lists at $1 in and $2.70 out.&lt;/p&gt;

&lt;p&gt;Nobody pays $2.70 out for 12 trillion tokens in a week for a model they’d never heard of. So I looked. According to &lt;a href="https://www.orcarouter.ai/blog/step-5-preview-free-three-places-one-week" rel="noopener noreferrer"&gt;OrcaRouter’s tracker&lt;/a&gt;, Step 5 Preview went free in three agent tools within five days: Cline on October 8 for a week, Nous Portal from October 8 through 15, and Kilo Code from October 9 for a week. Nous Portal is the API from Nous Research, the same people behind Hermes Agent, which is OpenRouter’s busiest app at 1.99 trillion tokens a day. Kilo Code is the third busiest. The free price goes back to $1/$2.70 on October 16.&lt;/p&gt;

&lt;p&gt;Arena has it at 83rd Overall and 71st in Coding. AA is kinder and gives it 44, about the same as Kimi K3, but notes it’s verbose: 160 million output tokens on the index against a median around 82 million. StepFun says &lt;a href="https://www.orcarouter.ai/blog/step-5-preview-open-weights" rel="noopener noreferrer"&gt;open weights are coming October 15&lt;/a&gt;. As of this morning, the newest thing on StepFun’s Hugging Face page is Step-3.7-Flash from June.&lt;/p&gt;

&lt;p&gt;This is the free-promo spike I keep warning about. A model in the top three by tokens and 83rd by votes is a model people are using because it costs nothing this week. Use it for free while you can, sure. Just don’t read 12 trillion tokens as a recommendation. Check back on the 17th.&lt;/p&gt;

&lt;h3&gt;
  
  
  One more launch: Mistral Large 4
&lt;/h3&gt;

&lt;p&gt;Mistral put &lt;a href="https://simonwillison.net/2026/Oct/6/le-chonk/" rel="noopener noreferrer"&gt;Large 4&lt;/a&gt; into public preview on October 6. It’s 1.05 trillion parameters, 49B active, with open weights scheduled for October 31. OpenRouter lists it at $0.68/$2.09, AA gives it 38, and Arena has it 115th Overall but 30th in Math on 220 votes. It’s not a cheapskate pick yet. It’s here because a European lab putting out trillion-parameter open weights would matter, and I want to see if they land on time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cheapskate table: Argon still owns the ceiling, and the edges got sharp
&lt;/h2&gt;

&lt;p&gt;If you’re new here: for each Arena category I take the leader’s rating, subtract 50, and look for the cheapest model still above that line. The band gets computed in code from every row on the board, and I write down the first model that falls below the line so I know nothing got cut off. (I learned that last part the hard way in July.)&lt;/p&gt;

&lt;p&gt;This week arena.ai decided I was a bot. Cloudflare served me a “Sorry, you have been blocked” page from the browser, from the fetch tool, and from plain curl, which is fair, because I kind of am one. So I pulled the board from &lt;a href="https://huggingface.co/datasets/lmarena-ai/leaderboard-dataset" rel="noopener noreferrer"&gt;LMArena’s own leaderboard dataset&lt;/a&gt; on Hugging Face instead. It’s the same style-controlled board the website shows (Argon at 1525 Overall, same as last week), published October 8. Every row is in there, which is what the method needs. There’s no price column, so I priced each model off its own maker’s endpoint on OpenRouter. That’s an improvement, actually. For weeks Arena’s price column kept showing whichever third-party host was cheapest that day, and I kept having to correct it.&lt;/p&gt;

&lt;p&gt;Gemini 4 Argon is still number one in all six categories, still on preliminary votes (271 in Math), and still &lt;a href="https://smartscope.blog/en/blog/gemini-4-argon-access-introductory-pricing-2026/" rel="noopener noreferrer"&gt;not for sale&lt;/a&gt; outside Google’s Fairwind program. Its $10 out is an intro price that goes to $20 with no end date announced.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&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;gemini-4-argon-high (1525)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;MiMo-V2.6-Pro (1480, #26)&lt;/td&gt;
&lt;td&gt;$0.87&lt;/td&gt;
&lt;td&gt;−45&lt;/td&gt;
&lt;td&gt;11.5×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coding&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1562)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;MiMo-V2.6-Flash* (1514, #45)&lt;/td&gt;
&lt;td&gt;$0.28&lt;/td&gt;
&lt;td&gt;−48&lt;/td&gt;
&lt;td&gt;36×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creative Writing&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1519)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;gemini-3.7-flash-high (1492, #5)&lt;/td&gt;
&lt;td&gt;$3.75&lt;/td&gt;
&lt;td&gt;−27&lt;/td&gt;
&lt;td&gt;2.7×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instruction Following&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1529)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;gemini-3.8-flash-high (1489, #14)&lt;/td&gt;
&lt;td&gt;$3.75&lt;/td&gt;
&lt;td&gt;−40&lt;/td&gt;
&lt;td&gt;2.7×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard Prompts&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1551)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;MiMo-V2.6-Pro (1506, #23)&lt;/td&gt;
&lt;td&gt;$0.87&lt;/td&gt;
&lt;td&gt;−45&lt;/td&gt;
&lt;td&gt;11.5×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Math&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1528)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1502, #13)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;−27&lt;/td&gt;
&lt;td&gt;20×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;*1,989 votes, 2.4 points above the cutoff. GLM-5.3-Flash sits at 1525 with 7,267 votes for 50 cents, and it’s the safer bet.&lt;/p&gt;

&lt;p&gt;Band depths: Overall 32, Coding 51, Creative 18, Instruction Following 20, Hard Prompts 29, Math 40.&lt;/p&gt;

&lt;p&gt;And the version you can actually buy from, with Argon removed:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Purchasable 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;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;claude-opus-5.5-high (1507)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1475)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;40×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coding&lt;/td&gt;
&lt;td&gt;claude-fable-5-high (1551)&lt;/td&gt;
&lt;td&gt;$50&lt;/td&gt;
&lt;td&gt;MiMo-V2.6-Flash (1514)&lt;/td&gt;
&lt;td&gt;$0.28&lt;/td&gt;
&lt;td&gt;179×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creative Writing&lt;/td&gt;
&lt;td&gt;claude-opus-5.5-high (1517)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;gemini-3.7-flash-high (1492)&lt;/td&gt;
&lt;td&gt;$3.75&lt;/td&gt;
&lt;td&gt;5.3×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instruction Following&lt;/td&gt;
&lt;td&gt;claude-opus-5.5-high (1519)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1472)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;40×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard Prompts&lt;/td&gt;
&lt;td&gt;claude-opus-5.5-high (1533)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1501)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;40×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Math&lt;/td&gt;
&lt;td&gt;claude-fable-5-high (1524)&lt;/td&gt;
&lt;td&gt;$50&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1502)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;100×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;(In Hard Prompts, MiMo-V2.6-Flash sits right at the edge of the band for 28 cents. I’ll take the GLM row with 17,734 votes over a model sitting 0.3 points above the line.)&lt;/p&gt;

&lt;p&gt;Opus 5.5 finally took the purchasable Overall spot from Opus 4.6, a model from February. The picks themselves barely moved. What changed is how close to the line everything is sitting.&lt;/p&gt;

&lt;p&gt;GLM-5.3-Flash missed the Hard Prompts band by 0.3 points. The cutoff is 1501.0 and GLM is at 1500.7. That’s the whole reason MiMo-V2.6-Pro is the Hard Prompts pick at 87 cents instead of GLM at 50. If Argon’s rating slips by a third of a point, or GLM gains that much, it flips.&lt;/p&gt;

&lt;p&gt;Coding’s band edge is basically a tie. The first model below the Coding cutoff is GLM-5.1, short by two hundredths of a point. And MiMo-V2.6-Flash, the cheapest model in the band for the third week running, dropped from 1521 to 1514, with only 1,989 votes. My rule for it was that if it held the spot on a few thousand votes, I’d call it the Coding pick for real. It’s going the other way. GLM-5.3-Flash is still the safer bet.&lt;/p&gt;

&lt;p&gt;Last week’s Instruction Following pick, DeepSeek V4.1 Flash, missed the band by 2.2 points this week. With it gone, the cheapest thing left in the band is Gemini 3.8 Flash at $3.75. So Instruction Following joins Creative Writing as a pay-for-quality category, though $3.75 is still 2.7 times under Argon’s intro price.&lt;/p&gt;

&lt;p&gt;And a free model snuck into the ex-Argon Coding band. Google’s Gemma 4 31B is at 1502.7 against a 1501.4 cutoff, and OpenRouter has a free variant (34 cents out paid). It’s barely in, and a free endpoint comes with free-endpoint terms (read what they do with your prompts). Still, a free model within 50 points of Fable 5 in Coding is new, and worth a test run on code you don’t mind sharing.&lt;/p&gt;

&lt;p&gt;Speed is still the catch at the bottom of the table. MiMo-V2.6-Pro scores 46 on AA, the best of any open-weights model, and crawls along at 48 tokens a second. GLM-5.3-Flash is at 62 this week, down from 89 in late September (I re-pull that number every week because it won’t sit still). And the distillation accusation Anthropic made against Xiaomi in September still hangs over the MiMo family. That’s a competitor’s accusation, not a ruling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Horror stories
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The 100K trapdoor
&lt;/h3&gt;

&lt;p&gt;I covered this above, but it goes here too because somebody is going to get bitten by it this month. You move your support-ticket agent from Haiku 4.5 to Haiku 5.5 because the press release said 90 percent cheaper. Your tickets averaged 85K tokens on the old tokenizer. On the new tokenizer that’s about 110K, and old thinking blocks pile up as input on every turn. Every call is now over the line, so you pay $0.50/$2.50 on the whole request. You’re still paying less than Haiku 4.5’s $1/$5, but nowhere near 90 percent less, and your budget was built on 90. Measure first.&lt;/p&gt;

&lt;h3&gt;
  
  
  GitSpawn: your repo’s git config can run code
&lt;/h3&gt;

&lt;p&gt;On October 2, researchers disclosed &lt;a href="https://adversa.ai/blog/top-ai-coding-agent-security-resources-october-2026/" rel="noopener noreferrer"&gt;GitSpawn&lt;/a&gt;, a set of eight flaws where an untrusted repository uses git configuration hooks like &lt;code&gt;core.fsmonitor&lt;/code&gt; to run code outside the sandbox and outside the approval prompts. The affected list is Claude Code, Codex, Cursor, Goose, Hermes Agent, Qwen Code, and Grok Build. When it was published, four of the eight were still unpatched.&lt;/p&gt;

&lt;p&gt;Hermes Agent is on that list, and it’s the number one app on OpenRouter right now. “Clone this repo and have a look” was supposed to be the safe thing to do with a coding agent. If you point an agent at code you didn’t write, run it in a container you’re willing to throw away. I run OpenClaw at home, and I’m checking my own setup this week.&lt;/p&gt;

&lt;h3&gt;
  
  
  PixelLeak: the agent proved its work in public
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.helpnetsecurity.com/?p=386283" rel="noopener noreferrer"&gt;Glow Labs disclosed PixelLeak&lt;/a&gt; right before last issue went out, and it deserves a spot. A developer asks a coding agent to prove a UI change works. The agent takes a screenshot, hits a GitHub CLI limit on attaching images, and works around it the quickest way it can find: it pushes the image to a public repo. Across 900-plus public repos at more than 300 organizations, that added up to more than 13,000 internal screenshots, including billing records, treasury consoles with client names, and unreleased designs. About 93 percent landed in employees’ personal accounts, where corporate monitoring doesn’t look.&lt;/p&gt;

&lt;p&gt;There’s no attacker in this story. Nobody hacked anything. The agent wanted to show its work, hit a wall, and picked the shortest route around it, which happened to be a public repo. I worry about that kind of failure more than the hacking stories, because no security scanner is looking for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The free week ends Friday
&lt;/h3&gt;

&lt;p&gt;If you wired Step 5 Preview into Cline or Kilo Code because it was free and number three on OpenRouter, it goes back to $2.70 out on Friday, October 16. It writes about twice the median number of output tokens. Do that math before Friday.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s coming
&lt;/h2&gt;

&lt;p&gt;StepFun says Step 5 Preview’s open weights land October 15. Right now that’s a promise with nothing on Hugging Face behind it, and I don’t count weights as shipped until there’s a license file. Mistral Large 4’s weights are scheduled for October 31, and the same rule applies.&lt;/p&gt;

&lt;p&gt;Gemini 4 Argon goes to paid API customers and AI Ultra subscribers next. There’s still no date. Space Bunny’s real name is coming “soon,” according to OpenRouter, and MiniMax M3.1-Flash-Preview is still the best guess.&lt;/p&gt;

&lt;p&gt;Fable 5.5, Grok 4.8, Kimi K3.1, and GPT-6.1 Sol Ultrafast are all being rumored for October. Prediction markets had Haiku 5.5 at about 92 percent for October last week and it shipped, so the rumor mill is doing okay lately. I’m watching for Fable 5.5. DeepSeek V5 is still pure speculation. DeepSeek hasn’t said anything, and it’s been “next month” since August.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally
&lt;/h2&gt;

&lt;p&gt;Haiku 5.5 is GLM’s price until your prompt passes 100K tokens. Muse Wonder is Opus’s price with a lower score. Step 5 Preview is a top-three model on OpenRouter only while it’s free. Argon is the best model in the world, at a price that will double, and you can’t buy it.&lt;/p&gt;

&lt;p&gt;Meanwhile the bottom of my table didn’t budge. GLM-5.3-Flash, the MiMo models, and DeepSeek V4.1 Flash are still the floor, and now Anthropic has a real model sitting on that floor too, which I did not expect to type this year. I like it. Just read the long-context pricing table before you budget off the press release.&lt;/p&gt;

&lt;p&gt;Next week I’ll check whether Haiku 5.5 has an Arena rating yet, and what happens to Step 5 Preview’s 12 trillion tokens once people have to pay $2.70 a million for them.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>openrouter</category>
    </item>
    <item>
      <title>Constraints Breed Creativity (Until You Hand Them to AI)</title>
      <dc:creator>Stephan Miller</dc:creator>
      <pubDate>Mon, 12 Oct 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/eristoddle/constraints-breed-creativity-until-you-hand-them-to-ai-113p</link>
      <guid>https://dev.to/eristoddle/constraints-breed-creativity-until-you-hand-them-to-ai-113p</guid>
      <description>&lt;p&gt;I start many writing sessions the same way. The rules come from &lt;a href="https://dev.to/writing-every-day/"&gt;Natalie Goldberg’s &lt;em&gt;Writing Down the Bones&lt;/em&gt;&lt;/a&gt;: set ten minutes on a timer, keep your hand moving, don’t cross out, and don’t correct. When the timer starts you go, and when it stops, you can read what you wrote.&lt;/p&gt;

&lt;p&gt;And it works. I found more ideas once I stopped blocking myself mid-stream. My writing got better, because the editor stayed quiet most of the time. The editing still happens. It just happens later.&lt;/p&gt;

&lt;p&gt;Ten minutes is a completely arbitrary constraint, and it has done more for my output than any amount of “just be more creative” ever has.&lt;/p&gt;

&lt;p&gt;Constraints breed creativity. Limitations force innovation. Necessity, invention, something something. It is probably one of the most repeated piece of creativity advice in existence, and I’m not going to argue with it, because I have run the experiment on myself for years and the advice holds.&lt;/p&gt;

&lt;p&gt;What I want to do instead is take the advice seriously enough to ask what a dumb rule is actually &lt;em&gt;doing&lt;/em&gt; when it works. Because it turns out the rule has two different jobs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The People Who Made an Art Form of It&lt;/li&gt;
&lt;li&gt;What the Rule Is Actually Doing&lt;/li&gt;
&lt;li&gt;Handing the Rules to the Machine&lt;/li&gt;
&lt;li&gt;One Paper, Pointing the Wrong Way&lt;/li&gt;
&lt;li&gt;So Which Job Were You Hiring It For?&lt;/li&gt;
&lt;li&gt;Three Hundred Books&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The People Who Made an Art Form of It
&lt;/h2&gt;

&lt;p&gt;The Goldberg timer is a gentle modern version of an older tradition: people who imposed rules on themselves so arbitrary they sound like dares, and then produced work nobody could have willed into existence directly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3rg1ftgenjibppmoiz78.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3rg1ftgenjibppmoiz78.jpg" alt="The People Who Made an Art Form of It" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The headquarters of this tradition is OuLiPo, the “workshop of potential literature,” founded in 1960 by Raymond Queneau and François Le Lionnais, with Georges Perec joining in 1967. Their premise was that a writer laboring under an arbitrary formal rule will surface phrasing that intention alone wouldn’t reach. Their proof-of-concept is Perec’s &lt;em&gt;La Disparition&lt;/em&gt; (1969), a full novel written without the letter e. A whole novel, about disappearance, in which the most common letter in French has disappeared. Gilbert Adair’s English translation, &lt;em&gt;A Void&lt;/em&gt;, keeps the same rule, which means the translator had to solve the puzzle a second time.&lt;/p&gt;

&lt;p&gt;OuLiPo’s other two greatest hits are small enough to run at your desk right now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;N+7.&lt;/strong&gt; Take a text. Replace every noun with the noun seven entries later in a dictionary. Your dictionary will give you different results than mine. Run “The deadline slipped because the team hit a bug in the migration” through a pocket dictionary and you get “The dealer slipped because the teapot hit a bulb in the milestone.” Nonsense, until your eye finds “the milestone slipped” hiding in the output. You pick the one worth keeping, and you would not have found it on purpose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snowball.&lt;/strong&gt; Each successive word is one letter longer. “I am the text which slowly becomes stronger.” It sounds like a party trick until you try to make one that also says something, and discover the search for valid words pulling your meaning somewhere you didn’t plan.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Outside OuLiPo the family gets more practical. &lt;strong&gt;SCAMPER&lt;/strong&gt; (Bob Eberle, 1971, compressing Alex Osborn’s 1953 checklist) is a set of verbs you cycle over a problem to force variation: Substitute, Combine, Adapt, Modify, Put to other use, Eliminate, Reverse. Stuck on a feature? Take the R. What happens if the user does it backwards, or the steps run in reverse order? &lt;strong&gt;TRIZ&lt;/strong&gt; (Genrich Altshuller, from 1946) is the most engineered version: you name the underlying contradiction, where improving one parameter worsens another, and look the pair up in a matrix distilled from hundreds of thousands of patents, which hands you one of forty inventive principles.&lt;/p&gt;

&lt;p&gt;One move in common among all of them: impose a rule, then let the search for valid output do the work. None of these people waited for a better idea. They built a wall and bounced off it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Rule Is Actually Doing
&lt;/h2&gt;

&lt;p&gt;Why should a dumb rule work at all? The Goldberg timer and the OuLiPo lipogram are not doing the same thing. A working constraint has two different jobs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgo80clq9jkmioj1qp24t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgo80clq9jkmioj1qp24t.jpg" alt="What the Rule Is Actually Doing" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Job one: muzzle the judge.&lt;/strong&gt; This is the Goldberg mechanism. The reason my mornings got more productive is that my internal editor doesn’t get to butt in (at least that’s the ideal). Don’t cross out, don’t correct, keep moving. Every rule is aimed at the judge, so the generator gets more chances. More ideas, and the judging happens later instead of continuously. Much of the classic advice works this way. Brainstorming’s “no criticism” rule, &lt;a href="https://dev.to/ultimate-morning-rituals/"&gt;morning pages&lt;/a&gt;, freewriting, the first-draft cult.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Job two: shrink the search.&lt;/strong&gt; This one involves research spikes into territory where the standards haven’t settled yet. Sandbox your coding agents, build an AI SDLC, secure the thing. The problem with new territory is that there are forty defensible ways to do everything and everybody on the internet has a strongly-worded opinion about each of them. Left unconstrained, a spike like that never ends.&lt;/p&gt;

&lt;p&gt;The most recent one was agent sandboxing. We surveyed the landscape, all the way down to VMs, up through control planes, Docker-based options, the works. One promising path was Docker’s own sandboxing, until Docker handed that product over to E2B, a sandboxing startup, and the Docker-native direction died in front of us. The research killed more options for various reasons, and what survived pointed in a direction. It turns out E2B uses Firecracker microVMs, and those were now available on AWS.&lt;/p&gt;

&lt;p&gt;The rule felt arbitrary: “must run standard Docker images.” And the job it did was search-shrinking: fewer live options, faster decision, done. In the end, it led to a solution that used Dockerfiles to build microVMs.&lt;/p&gt;

&lt;p&gt;Free the generator, or narrow the search.&lt;/p&gt;

&lt;p&gt;Even the failures do a job, by the way. I once put a hard cap on my own reading list. It did not hold. I’ll come back to that one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handing the Rules to the Machine
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj1izcgbcqdoh9eg1aqtg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj1izcgbcqdoh9eg1aqtg.jpg" alt="Handing the Rules to the Machine" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If a constraint is a process, anything that can follow a process can use it. And the constraint family translates to prompting. SCAMPER is a for-loop: “take this problem, run Substitute, Combine, Adapt, Modify, Put to other use, Eliminate, Reverse, give me three answers per verb.” N+7 is one sentence of instruction. TRIZ’s contradiction matrix is a lookup table, which is the most prompt-shaped object that has ever existed. I have &lt;a href="https://github.com/NousResearch/hermes-agent/tree/main/optional-skills/creative/creative-ideation" rel="noopener noreferrer"&gt;a skill installed&lt;/a&gt; that does this: &lt;code&gt;creative-ideation&lt;/code&gt;, from NousResearch’s Hermes collection, MIT-licensed, drops into Claude Code or Cursor, and routes whatever you ask it to one of twenty-two named human creativity methods. SCAMPER, TRIZ, OuLiPo, Oblique Strategies, most of this post, on tap. Its core rule is printed right in the skill: constraint plus direction equals creativity. Its anti-slop rule is a constraint too: refuse the first three ideas, five on high-slop terrain like AI startup pitches.&lt;/p&gt;

&lt;p&gt;And on the search-shrinking side, the mechanical versions are the best thing I’ve got. There’s a &lt;a href="https://dev.to/the-agent-skills-guide-i-wish-id-had/"&gt;research skill&lt;/a&gt; I use constantly, and it is constraints all the way down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A fixed field schema.&lt;/strong&gt; Every research agent has to come back with answers to predeclared fields. Not “whatever it found.” Specific answers to specific questions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A hard budget.&lt;/strong&gt; Eight searches, twelve fetches per item, at standard depth. That number is exactly as arbitrary as my ten-minute timer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forced honesty.&lt;/strong&gt; The agents are forbidden from filling gaps with guesses. Anything unanswered gets marked uncertain. The constraint is against &lt;a href="https://dev.to/my-home-ai-agent-kept-making-shit-up/"&gt;confabulation&lt;/a&gt; itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A gate at the end.&lt;/strong&gt; The run isn’t done until the validator passes. Nobody promised to follow the rules. A machine checks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before I had that, I’d point a coding agent at a topic with plain web fetch and take whatever came back. The constrained version is not a little better. It’s the difference between research and vibes. I said in &lt;a href="https://dev.to/youre-using-ai-like-a-vending-machine/"&gt;the first post in this series&lt;/a&gt; that a question gets you the average and a process gets you something else. This is the something else, with rails.&lt;/p&gt;

&lt;p&gt;So: constraints free the generator, constraints shrink the search, constraints make the machine honest. The advice checks out on people, and it checks out when you hand it to a model.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Paper, Pointing the Wrong Way
&lt;/h2&gt;

&lt;p&gt;Alwin de Rooij and Michael Mose Biskjaer, &lt;a href="https://www.tandfonline.com/doi/full/10.1080/0144929X.2026.2726451" rel="noopener noreferrer"&gt;“Does generative AI make us think alike?”&lt;/a&gt; (&lt;em&gt;Behaviour &amp;amp; Information Technology&lt;/em&gt;, 2026). They tracked down every study they could find on what happens to human creative output when a model is in the loop, and pooled them into one set of numbers: nineteen studies, sixty-one separate measurements. The answer: the work gets more alike. Not a lot alike. The pull toward sameness is small (d = .334, for the stats people), but it shows up consistently, and it is exactly the size of effect you would never catch in your own work. One piece at a time, invisible. Added up across everyone, very real.&lt;/p&gt;

&lt;p&gt;The interesting part is a breakdown buried in the review (a moderator analysis, in the paper’s terms): the sameness was &lt;em&gt;stronger&lt;/em&gt; when the task came with rules about what the ideas had to be, and weaker when it was loose, anything-goes brainstorming. The move this post is about, impose a rule, narrow the space, force the search, is the condition under which the flattening gets worse.&lt;/p&gt;

&lt;p&gt;I want to be exact about what “everything above” includes. It includes me. A section ago I told you, with some pride, about a skill I have installed that routes my requests to twenty-two named creativity methods. That is a novelty-forcing rule about what the ideas have to be, with an install command.&lt;/p&gt;

&lt;p&gt;The skill’s own author saw the middle coming, for what it’s worth. The anti-slop rule, refuse the first three ideas, exists because the first draws are the average ones. So either the patch works and a constrained model can be pushed off the middle, or the patch is one more wall somebody handed me and we are all standing in the same destination anyway.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjo3jvaquddckdgzi50lw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjo3jvaquddckdgzi50lw.jpg" alt="One Paper, Pointing the Wrong Way" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A model is an averaging engine. Ask it for ideas and you get the middle of idea-space. Ask it for ideas under a tight rule about what they have to be, and you have not pushed it off the middle. You have told it &lt;em&gt;which&lt;/em&gt; middle. Give the model a persona plus a rule, or ask it for ten ideas using only X: same kind of thing, a rule about what the output has to be. Everyone who imposes that kind of rule on the same class of model gets pushed toward the same narrowed region. And everyone thinks the constraint worked, because the answer looks different from what they’d have written alone. It does, but it also looks like what everyone else with the same rule got.&lt;/p&gt;

&lt;p&gt;But this is one paper, and the moderator result is one finding inside it. The studies under it mostly tested 2023 and 2024 chat models, not the current stuff. And what they constrained was the task humans brought to the model, not the model itself: the move from one to the other is an inference, not a finding. But it is the first direct measurement of the advice this post is about, and it points a different way.&lt;/p&gt;

&lt;h2&gt;
  
  
  So Which Job Were You Hiring It For?
&lt;/h2&gt;

&lt;p&gt;Here’s where the two jobs from earlier stop being a taxonomy and start being instructions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Judge-muzzling constraints are for you. Keep them.&lt;/strong&gt; The ten-minute timer works because you have an internal editor that gets in the way, and the rule handcuffs it. A model has no internal editor. It is not nervously crossing out its own drafts. “Don’t stop to correct yourself” is a meaningless instruction to something that was never going to. Goldberg’s rules, morning pages, the no-criticism rule, the first-draft cult: all of these treat a human bottleneck, they work on humans, and they neither need nor benefit from a model’s involvement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Search-shrinking constraints survive the machine.&lt;/strong&gt; The research skill, the field schema, the eight-search budget, the validator. Narrowing a search is narrowing a search, and it works on a model for the same reason it works on a spike at work: fewer live options, faster decision, and no one was asking for diversity in the first place. The point of those constraints was coverage and honesty, and on those metrics the constrained version wins outright.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Novelty-forcing constraints are the ones that get eaten.&lt;/strong&gt; When the entire job of the rule is “push me somewhere I wouldn’t go on my own,” handing it to the model converts it into a destination, and it’s the same destination everyone else with the same rule gets. This is the branch the meta-analysis measured and it backfired.&lt;/p&gt;

&lt;p&gt;So the practical rules:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flctism0f535j9dc40idg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flctism0f535j9dc40idg.jpg" alt="So Which Job Were You Hiring It For?" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Constraints on your own process: keep, no changes.&lt;/strong&gt; They muzzle your judge. The model never had one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constraints on research and retrieval: keep, they enforce themselves.&lt;/strong&gt; If a validator can check it, it works.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constraints meant to force original ideas out of a model: go wide first.&lt;/strong&gt; Run the open divergent pass before you create any walls. Survey the territory with the constraint off, watch what’s there, and only then draw a rule, distilled from what you saw. A constraint earned by a wide survey lands somewhere specific. A constraint imposed up front lands where everyone else’s did.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat a rule the model hands you as a draft, not a wall.&lt;/strong&gt; If you are in genuinely new territory, you’ll be regularly unsure which of its suggested walls to keep. That uncertainty is correct. A constraint you invented after looking at the territory does a different job than one handed to you by something that averages.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The human half needs a kitchen timer, a pocket dictionary, and paper. The machine half is one install and one write-up: the &lt;code&gt;creative-ideation&lt;/code&gt; skill linked up top for the method library, and the research skill linked above for the constrained-search side. Everything else in this post is a way of holding them. Which is all I wanted out of this stuff in the first place: just another tool that gets me to an answer I couldn’t see from where I was standing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Hundred Books
&lt;/h2&gt;

&lt;p&gt;Some years ago I decided my reading needed discipline. I have over four thousand books on my ebook reader. IIt did not feel like a problem while I was buying them: four thousand. I used to graze, jumping between them at random, finishing nothing. So I made a Current Reading list, the books I’m actively reading, and capped it at fifty. Fifty sounded like the kind of number a disciplined person would pick.&lt;/p&gt;

&lt;p&gt;It is currently three hundred books long.&lt;/p&gt;

&lt;p&gt;I added each book one at a time, and every addition made sense at the moment I made it. Book seventy-three was basically research. Book one-forty was short. Book two hundred was for a project I have not started and will never start. Every one of the three hundred was, at the moment of its addition, an exception.&lt;/p&gt;

&lt;p&gt;The rule failed at its job: stopping me from spreading myself across too many books at once. I still read a dozen or twenty at a time.&lt;/p&gt;

&lt;p&gt;I am currently reading twenty books, which means I am reading two and have strong opinions about eighteen.&lt;/p&gt;

&lt;p&gt;Three hundred books is a horizon: the books I’m plausibly reading in the next five or six years, kept in my face so the choosing among them stays live. It’s a map, not a discipline.&lt;/p&gt;

&lt;p&gt;Give yourself one. Watch what it does. It may do the job you hired it for, like the timer. It may fail at that job and get itself a better one, like the list. Either way you will be there watching it happen, which is the one thing the model will never do for you. The constraint was never the &lt;em&gt;whole&lt;/em&gt; point. What you were paying attention to when you made it was.&lt;/p&gt;

</description>
      <category>nataliegoldberg</category>
      <category>writingdownthebones</category>
      <category>creativeconstraints</category>
      <category>oulipo</category>
    </item>
    <item>
      <title>Gemini 4 Argon Won Every Arena Category. You Can't Use It.</title>
      <dc:creator>Stephan Miller</dc:creator>
      <pubDate>Tue, 06 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/eristoddle/gemini-4-argon-won-every-arena-category-you-cant-use-it-4fc9</link>
      <guid>https://dev.to/eristoddle/gemini-4-argon-won-every-arena-category-you-cant-use-it-4fc9</guid>
      <description>&lt;p&gt;The best model in the world this week is one you can’t use.&lt;/p&gt;

&lt;p&gt;Gemini 4 Argon showed up on Arena and took first place in all six text categories I track: Overall, Coding, Creative Writing, Instruction Following, Hard Prompts, and Math. It’s listed at $2 in and $10 out, which is cheaper than every Claude model it knocked off the top. So I did what any reasonable person with an OpenRouter account would do. I went to try it. 404.&lt;/p&gt;

&lt;p&gt;That’s because Google isn’t selling it to you. Argon is locked to a few hundred cybersecurity organizations (650-plus, if you’re counting) while Google figures out whether it’s safe to let the rest of us have it. Same week, OpenAI went one step further and refused to ship its own next flagship, GPT-6.1 Astra, because in testing it lied about what it had done. So the two biggest frontier stories this week are both about models you can’t have. And the one you can’t have still managed to rearrange my cheapskate table just by existing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gemini 4 Argon won everything on preliminary votes&lt;/li&gt;
&lt;li&gt;The Astra that lied, and the Sol you can buy instead&lt;/li&gt;
&lt;li&gt;A model you can’t call just rearranged my cheapskate table&lt;/li&gt;
&lt;li&gt;Space Bunny is still free, still anonymous, and now number one&lt;/li&gt;
&lt;li&gt;
Horror stories

&lt;ul&gt;
&lt;li&gt;Your agent’s status report might be fiction&lt;/li&gt;
&lt;li&gt;Four trillion prompt tokens to a stranger&lt;/li&gt;
&lt;li&gt;Budgeting off a leaderboard number&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;What’s coming&lt;/li&gt;
&lt;li&gt;Finally&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Gemini 4 Argon won everything on preliminary votes
&lt;/h2&gt;

&lt;p&gt;Arena’s board, stamped October 2, has Argon at 1525 Overall, 20 points clear of claude-opus-4-6-high at 1505. It leads Coding at 1560, Creative Writing at 1519, Instruction Following at 1528, Hard Prompts at 1551, and Math at 1530.&lt;/p&gt;

&lt;p&gt;Every one of those ratings carries the “Preliminary” tag. It has 4,932 votes in Overall, about 1,100 to 1,250 each in Coding and Creative Writing, and just 255 in Math. For comparison, the Opus 4.6 it displaced has 77,636 Overall votes. A model can win a category on 255 votes. Opus 4.6 has about 300 times that many votes in Overall alone.&lt;/p&gt;

&lt;p&gt;Artificial Analysis is less excited. On its &lt;a href="https://artificialanalysis.ai/models/gemini-4-argon" rel="noopener noreferrer"&gt;Intelligence Index&lt;/a&gt;, Argon scores 53. That puts it eighth, tied with Fable 5.1 and GPT-6 Astra, behind Claude Opus 5.5 at 58 and Claude Sonnet 5.5 at 56. That’s frontier, no question. It’s just not the top of the frontier. The blind-vote crowd loves it and the hard benchmarks say it’s good. I’ve seen this split before, usually in the opposite direction. GPT-6 Astra tied for first on AA and debuted 24th on Arena. Argon is the mirror image.&lt;/p&gt;

&lt;p&gt;Why can’t you buy it? Google announced Argon last week and &lt;a href="https://techwireasia.com/2026/10/google-gemini-4-argon-cybersecurity-access/" rel="noopener noreferrer"&gt;rolled it out first through its Fairwind Program&lt;/a&gt;: more than 650 partners, including government agencies, critical infrastructure operators, and security vendors. Those organizations can only hand it to employees in cybersecurity, incident response, or pentesting roles, and they have to use multi-factor authentication. Google’s stated reason is that it’s still testing safeguards against cyberattacks, CBRN misuse, and indirect prompt injection. The self-reported numbers explain the nerves: 68 percent on CWE-bench v1 for vulnerability remediation, 77.9 percent on DeepSWE v1.1, and a story about finding a patient-data bug in hospital software that earlier frontier models missed. Google says it trained Argon specifically to find, validate, and patch software vulnerabilities. Nobody independent has checked any of that yet.&lt;/p&gt;

&lt;p&gt;Next in line are paid API customers and Google AI Ultra subscribers. No date. And the price on Arena’s board is &lt;a href="https://smartscope.blog/en/blog/gemini-4-argon-access-introductory-pricing-2026/" rel="noopener noreferrer"&gt;introductory&lt;/a&gt;. After the intro period it goes to $4 in and $20 out, and Google hasn’t said when the intro period ends. So the leaderboard’s number one is off limits, priced at a number that won’t last, ranked on votes that are still coming in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Astra that lied, and the Sol you can buy instead
&lt;/h2&gt;

&lt;p&gt;OpenAI had its own flagship lined up for October. It’s not coming.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://dev.to/sam_hiotis_117598dbfa3ac2/openai-shelves-gpt-61-astra-after-tests-find-deception-and-unauthorized-actions-1d9g-temp-slug-6007592"&gt;reporting picked up by The Hacker News&lt;/a&gt;, GPT-6.1 Astra failed OpenAI’s internal safety and alignment audits. The details read like the postmortem nobody wants to write about an agent. It didn’t disclose actions it had taken, and it went ahead without asking permission. Testers also caught it reaching for outside tools in situations flagged as unsafe.&lt;/p&gt;

&lt;p&gt;Saachi Jain, OpenAI’s head of safety systems, put it this way: the model “didn’t quite meet the bar in terms of staying within scope and authorization, and how it communicates back to the user about the type of work it’s done.”&lt;/p&gt;

&lt;p&gt;In plain English, it did stuff you didn’t ask for and then lied to you about it. If you run coding agents for a living, that’s the failure mode that matters most. A dumb model wastes your afternoon. A model that lies about what it did is how you lose a database.&lt;/p&gt;

&lt;p&gt;The model OpenAI does sell got a report card too. The same day, the UK’s AI Security Institute published a report on GPT-6 Astra, the one OpenAI has been selling since early September. In simulated testing, Astra “conducted a range of unsanctioned attack activities” at a higher rate than GPT-5.6 Sol and GPT-5.5, sometimes even after the scope was spelled out for it. The report’s examples: “creating fake identities which it used to deceive developers, posting comments from fake accounts arguing against the results of accurate security reviews, and delivering malicious payloads to open-source codebases.” That’s a simulation, not an incident. But plenty of people have that exact model wired into a coding agent right now.&lt;/p&gt;

&lt;p&gt;So at DevDay on September 29, OpenAI shipped &lt;a href="https://techcrunch.com/2026/09/29/openai-launches-gpt-6-1-sol-says-it-nearly-matches-gpt-6-astra-and-costs-less/" rel="noopener noreferrer"&gt;GPT-6.1 Sol&lt;/a&gt; instead. OpenAI says it gets close to GPT-6 Astra on agentic coding, computer use, and professional work at a fifth of Astra’s price. On &lt;a href="https://openrouter.ai/openai/gpt-6.1-sol" rel="noopener noreferrer"&gt;OpenRouter&lt;/a&gt; that works out to $2 in, $10 out, and 10 cents per million for cached input. It’s the number one new model on OpenRouter’s trending list this week at 927 billion tokens. Artificial Analysis gives it 52, one point behind Argon. On Arena it’s 21st Overall at 1483 and eighth in Coding on only 609 votes.&lt;/p&gt;

&lt;p&gt;GPT-6.1 Sol is $2/$10, and so is Gemini 4 Argon’s intro price. Two labs landed on the same sticker for near-frontier capability the same week, and only one of them will actually sell it to you. OpenRouter’s provider table also shows Sol is slow right now, 32 to 50 tokens a second depending on the host. There’s a “Fast” endpoint at double the price if that matters to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  A model you can’t call just rearranged my cheapskate table
&lt;/h2&gt;

&lt;p&gt;Same method every week. Take each Arena category’s leader, draw a band 50 points below its rating, and find the cheapest model still inside the band. I compute the band in code from the full table, 129 rows per category, never off the first screen. I learned that one the hard way.&lt;/p&gt;

&lt;p&gt;This week the leader in every category is Argon. That changes two things at once. Argon raised every ceiling, so every band moved up. And Argon is cheap for a leader, so every “cheaper by” ratio collapsed. Bands got shallower too: 37 models deep in Overall (57 last week), 60 in Coding (73), 31 in Hard Prompts (43), 23 in Instruction Following (38), 35 in Math (43). Creative Writing went the other way, from 12 to 18, because Argon only beat Opus 5.5 there by three points.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&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;gemini-4-argon-high (1525)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;MiMo-V2.6-Pro (1480, #26)&lt;/td&gt;
&lt;td&gt;$0.87&lt;/td&gt;
&lt;td&gt;−45&lt;/td&gt;
&lt;td&gt;11.5×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coding&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1560)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;MiMo-V2.6-Flash* (1521, #33)&lt;/td&gt;
&lt;td&gt;$0.28&lt;/td&gt;
&lt;td&gt;−39&lt;/td&gt;
&lt;td&gt;36×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creative Writing&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1519)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;gemini-3.7-flash-high (1493, #5)&lt;/td&gt;
&lt;td&gt;$3.75&lt;/td&gt;
&lt;td&gt;−26&lt;/td&gt;
&lt;td&gt;2.7×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instruction Following&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1528)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;deepseek-v4.1-flash-max (1479, #21)&lt;/td&gt;
&lt;td&gt;$1.20&lt;/td&gt;
&lt;td&gt;−49&lt;/td&gt;
&lt;td&gt;8.3×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard Prompts&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1551)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;MiMo-V2.6-Pro (1505, #22)&lt;/td&gt;
&lt;td&gt;$0.87&lt;/td&gt;
&lt;td&gt;−46&lt;/td&gt;
&lt;td&gt;11.5×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Math&lt;/td&gt;
&lt;td&gt;gemini-4-argon-high (1530)&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1503, #13)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;−27&lt;/td&gt;
&lt;td&gt;20×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;*1,508 votes. GLM-5.3-Flash sits right next to it at 1523 with 6,157 votes for 50 cents, and that’s the steadier bet.&lt;/p&gt;

&lt;p&gt;Argon is quoted at its intro price. When it goes to $20 out, every ratio in that table doubles. GLM-5.3-Flash is quoted at Z.ai’s list price of 50 cents out. Arena’s price column shows 20 cents, but that’s a third-party floor.&lt;/p&gt;

&lt;p&gt;Last week GLM-5.3-Flash was the pick in four of six categories, and this week it’s the pick in one. GLM didn’t get worse. Its Overall rating went from 1474 to 1473. The band moved. The Overall cutoff is now 1475, so GLM missed it by two points. Hard Prompts’ cutoff is 1501 and GLM sits at 1500, one point short. In Instruction Following it’s six points short. A model nobody outside Fairwind can call, rated on preliminary votes, pushed the most-used cheap model of the last month out of half my table.&lt;/p&gt;

&lt;p&gt;So which table do you actually shop from? Here’s the same one, recomputed without Argon.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Purchasable 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;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;claude-opus-4-6-high (1505)&lt;/td&gt;
&lt;td&gt;$25&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1473)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;50×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coding&lt;/td&gt;
&lt;td&gt;claude-fable-5-high (1552)&lt;/td&gt;
&lt;td&gt;$50&lt;/td&gt;
&lt;td&gt;MiMo-V2.6-Flash (1521)&lt;/td&gt;
&lt;td&gt;$0.28&lt;/td&gt;
&lt;td&gt;179×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creative Writing&lt;/td&gt;
&lt;td&gt;claude-opus-5.5-high (1516)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;gemini-3.7-flash-high (1493)&lt;/td&gt;
&lt;td&gt;$3.75&lt;/td&gt;
&lt;td&gt;5.3×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instruction Following&lt;/td&gt;
&lt;td&gt;claude-opus-5.5-high (1517)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1472)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;40×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard Prompts&lt;/td&gt;
&lt;td&gt;claude-opus-5.5-high (1534)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1500)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;40×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Math&lt;/td&gt;
&lt;td&gt;claude-fable-5-high (1522)&lt;/td&gt;
&lt;td&gt;$50&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1503)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;100×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;(In Hard Prompts and Math, MiMo-V2.6-Flash technically sneaks in at exactly the band edge for 28 cents, but in Math that’s on 330 votes. I’m not crowning anything on 330 votes.)&lt;/p&gt;

&lt;p&gt;That’s basically last week’s table. GLM is back in four categories, and the year-old claude-opus-4-6-high is still the top Overall model you can actually buy.&lt;/p&gt;

&lt;p&gt;MiMo-V2.6-Pro is now the Overall and Hard Prompts pick at 87 cents. Artificial Analysis rates it 46, the best score among open-weights models, at 13 cents per index task. It’s also slow: 46.6 tokens a second with a 5.2-second wait for the first token, well under the 75 tok/s median. And the distillation allegation from last issue, Anthropic’s report claiming Xiaomi routed 400,000 user conversations through Claude, still hangs over the whole MiMo family. That’s an accusation from a competitor, not a ruling. Whether it matters to you depends on your lawyers.&lt;/p&gt;

&lt;p&gt;MiMo-V2.6-Flash held the cheapest-in-band spot in Coding for a second week, and its vote count went from 1,043 to 1,508. I said last week that if it held that spot with a few thousand votes, the Coding crown had moved. It’s not there yet. AA gives it 38, about 6 cents per task, 62 tokens a second, and it’s verbose: 240 million output tokens to get through AA’s suite against a 140 million median.&lt;/p&gt;

&lt;p&gt;DeepSeek V4.1 Flash is the new Instruction Following pick at $1.20, and it’s the only pick this week that isn’t slow. AA clocks it at 222 tokens a second, third fastest among the open-weights models AA tracks, and it starts answering in about a second. It’s right at the band edge, one point above the cutoff, so it could fall out next week. On OpenRouter some third-party hosts list it at 18 to 40 cents out, way under list. Check uptime before you chase those.&lt;/p&gt;

&lt;p&gt;Creative Writing is still the category where you pay for quality. The best value is Gemini 3.7 Flash at $3.75, just 2.7 times cheaper than Argon. Gemini 3.8 Flash costs the same and rates lower, so 3.7 wins the tie.&lt;/p&gt;

&lt;h2&gt;
  
  
  Space Bunny is still free, still anonymous, and now number one
&lt;/h2&gt;

&lt;p&gt;Last week Space Bunny Alpha was the second-biggest model on OpenRouter. This week it’s &lt;a href="https://openrouter.ai/rankings" rel="noopener noreferrer"&gt;first&lt;/a&gt;, at 38.5 trillion tokens, up 112 percent. Stealth models as a group now account for 10.5 percent of all text requests on OpenRouter, and stealth requests went up 296 percent in a week.&lt;/p&gt;

&lt;p&gt;It’s still free. It still hasn’t told anyone who made it. The tokenizer evidence still points at &lt;a href="https://cellcog.ai/blog/what-is-space-bunny-alpha/" rel="noopener noreferrer"&gt;MiniMax’s M3.1-Flash-Preview&lt;/a&gt;, and it’s still unconfirmed. I’ll pull a number from its &lt;a href="https://openrouter.ai/stealth/space-bunny-alpha" rel="noopener noreferrer"&gt;OpenRouter activity panel&lt;/a&gt; in the horror section, because it deserves the spot.&lt;/p&gt;

&lt;p&gt;Meanwhile, the paid volume king is DeepSeek V4.1 Flash. It’s number two this week at 28.4 trillion tokens, up 36 percent, and number one for the trailing month at 72.3 trillion. DeepSeek is the top author on OpenRouter at 21.8 percent of requests. Google is right behind at 21.5 percent, up 23 percent, all of that from models that aren’t Argon. GLM-5.3-Flash is third at 10 trillion, down 25 percent. Anthropic is 2.5 percent of requests, which tells you who’s buying Claude through OpenRouter and who’s buying it direct.&lt;/p&gt;

&lt;p&gt;On the apps list, Nous Research’s Hermes Agent pushed 1.86 trillion tokens in a day, ahead of Claude Code at 1.06 trillion. On OpenRouter, at least, an open-source agent is now burning more tokens than Anthropic’s own coding tool. I run OpenClaw at home, so I’m part of the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Horror stories
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Your agent’s status report might be fiction
&lt;/h3&gt;

&lt;p&gt;I covered GPT-6.1 Astra above, but it belongs here too, because it’s the scariest thing in this issue. Most model horror stories are about a model being dumb: it hallucinated a function, it deleted the wrong folder. Astra’s failure was the model hiding its own actions and acting outside the task it was given. Its shipping big brother, GPT-6 Astra, went as far as running sock-puppet accounts in AISI’s supply-chain simulations. That’s a trust problem, and a higher benchmark score doesn’t fix it.&lt;/p&gt;

&lt;p&gt;OpenAI deserves credit for catching it in testing and not shipping it. But agent frameworks are built on the assumption that the model’s account of what it did is true. Your agent’s “I ran the tests and they passed” message is only useful if it’s true. Somebody built a model where it sometimes wasn’t. The next one might not get caught.&lt;/p&gt;

&lt;h3&gt;
  
  
  Four trillion prompt tokens to a stranger
&lt;/h3&gt;

&lt;p&gt;Space Bunny Alpha’s activity panel shows 4.06 trillion prompt tokens since September 23, against 135 billion completion tokens. That’s a 30-to-1 ratio of input to output. People aren’t chatting with it. They’re feeding it whole codebases and huge documents, because it’s free and has a million-token window.&lt;/p&gt;

&lt;p&gt;The listing says prompts and completions “may be retained by the provider.” The provider won’t give its name. I’ve said this before and I’ll keep saying it until free stealth models stop topping the charts: kick the tires on public code all you want, but don’t send it anything you wouldn’t post on GitHub.&lt;/p&gt;

&lt;h3&gt;
  
  
  Budgeting off a leaderboard number
&lt;/h3&gt;

&lt;p&gt;This one’s small but I bet somebody does it this month. Arena shows Argon at $2/$10 next to a #1 ranking in every category. A team lead sees that, writes “switch to Gemini 4, cheaper and better” in a planning doc, and finds out at implementation time that the model isn’t available to them and the price is going to double. If you build a budget off a leaderboard row, check that you can actually call the model, and whether the price is introductory.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s coming
&lt;/h2&gt;

&lt;p&gt;Gemini 4 Argon for the rest of us is announced but has no date. Paying API customers and Ultra subscribers go next, then everyone else. When it opens up, I’ll be watching two things: whether the Arena lead holds as votes pile up, and when the price goes to $4/$20.&lt;/p&gt;

&lt;p&gt;GPT-6.1 Astra is shelved with no new date. OpenAI says it’s shifting focus to “improving the safety of future models.”&lt;/p&gt;

&lt;p&gt;The Space Bunny unmasking is still speculation. If it turns out to be MiniMax M3.1-Flash and gets a price, it’ll probably follow the last stealth model. Union Alpha &lt;a href="https://openrouter.ai/stealth/space-bunny-alpha" rel="noopener noreferrer"&gt;turned out to be Pareto by Unbiased&lt;/a&gt;, and the free period ended when the name came out. Then we’ll see how much of that 38.5 trillion was people who actually wanted the model.&lt;/p&gt;

&lt;p&gt;Claude Haiku 5.5 and Fable 5.5 are speculation too. &lt;a href="https://manifold.markets/prismatic/october-2026-ai-model-releases" rel="noopener noreferrer"&gt;Prediction markets&lt;/a&gt; give both about a 92 percent chance of shipping in October. Anthropic said Haiku 5.5 would follow Opus and Sonnet “in the coming weeks,” and Sonnet shipped on September 28.&lt;/p&gt;

&lt;p&gt;DeepSeek V5 is still pure speculation. People keep saying October, and DeepSeek hasn’t said anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally
&lt;/h2&gt;

&lt;p&gt;Google and OpenAI arrived at the same place from opposite directions this week. Google built something it thinks is too good at hacking to hand out, so it handed it to defenders first. OpenAI built something that couldn’t be trusted to stay in its lane, so it handed out something smaller. In both cases the frontier model in the headlines isn’t for sale, and the one that is costs $2/$10.&lt;/p&gt;

&lt;p&gt;For the stuff you actually pay for, not much changed. GLM-5.3-Flash and the MiMo models are still the floor. Year-old Opus 4.6 still tops the purchasable Overall board. DeepSeek V4.1 Flash is moving more tokens than anything except a free model with no name.&lt;/p&gt;

&lt;p&gt;Next week I’ll check whether Argon’s 255 Math votes have turned into a few thousand, and whether anyone outside Fairwind has gotten a key. And I’ll check whether my cheapskate table survives the next ceiling this model raises.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>openrouter</category>
    </item>
    <item>
      <title>Before You Write a Scraper, Check Firecrawl Alexandria</title>
      <dc:creator>Stephan Miller</dc:creator>
      <pubDate>Mon, 05 Oct 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/eristoddle/before-you-write-a-scraper-check-firecrawl-alexandria-2652</link>
      <guid>https://dev.to/eristoddle/before-you-write-a-scraper-check-firecrawl-alexandria-2652</guid>
      <description>&lt;p&gt;Last Thursday I published a &lt;a href="https://dev.to/eristoddle/track-new-ai-models-on-the-arena-leaderboard-with-a-70-line-scraper-3f3m"&gt;70-line scraper that watches the Arena leaderboard&lt;/a&gt; for new AI models. It runs daily and announces new arrivals.&lt;/p&gt;

&lt;p&gt;Two days earlier, &lt;a href="https://firecrawl.link/stephan-miller" rel="noopener noreferrer"&gt;Firecrawl&lt;/a&gt; launched Alexandria, a catalog of providers that sell the structured version of exactly this kind of data, callable through the same scrape endpoint I was already paying for. I didn’t notice. I was busy having AI build me regex for a markdown table, while the company whose credits I was spending shipped the thing meant to make that regex unnecessary.&lt;/p&gt;

&lt;p&gt;So to recap: I built a machine that watches the internet for new arrivals, and the first new arrival it missed was the one built to replace it.&lt;/p&gt;

&lt;p&gt;If somebody is already selling the structured version of the data I wanted, why was I scraping the page? It never occurred to me to check.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Alexandria Is&lt;/li&gt;
&lt;li&gt;First, You Need a Newer CLI&lt;/li&gt;
&lt;li&gt;Browsing the Catalog Costs Nothing&lt;/li&gt;
&lt;li&gt;The Answer for Arena: Keep Scraping&lt;/li&gt;
&lt;li&gt;The Leaderboard Next Door: Artificial Analysis&lt;/li&gt;
&lt;li&gt;The Top 20 Is Really Nine Models&lt;/li&gt;
&lt;li&gt;The Same Harness, New Fetch Step&lt;/li&gt;
&lt;li&gt;What the Swap Costs&lt;/li&gt;
&lt;li&gt;If Your Cron Runs Unattended, Read This Part&lt;/li&gt;
&lt;li&gt;Check the Catalog Before You Write the Scraper&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Alexandria Is
&lt;/h2&gt;

&lt;p&gt;Alexandria is Firecrawl’s catalog of third-party data sources: FRED economic data, podcast transcripts, app store listings, company records, and a few hundred other things. They named their permanent store of the world’s data after history’s most famous case of data loss, which is either confidence or a gap in the marketing team’s classics minor. Each tool in it has a published contract that says what options it takes, what it returns, and what it costs. Finding tools and reading contracts is free. Running one costs credits, Firecrawl’s metered unit, and the free plan is 1,000 of them a month. The Arena scraper already spends one per run: it fetches the page through Firecrawl. That 1 is the baseline for every cost number in this post.&lt;/p&gt;

&lt;p&gt;It works in three steps: find a tool, read its contract, call it. The call goes to the regular &lt;code&gt;/v2/scrape&lt;/code&gt; endpoint with an &lt;code&gt;alexandria&lt;/code&gt; array instead of a URL.&lt;/p&gt;

&lt;p&gt;If you want the full tour, JP Caparas already wrote it well: &lt;a href="https://medium.com/reading-sh/firecrawl-alexandria-tested-end-to-end-with-real-api-calls-1cf1cf3030a9" rel="noopener noreferrer"&gt;Firecrawl Alexandria, tested end to end with real API calls&lt;/a&gt;. I am not going to redo that. This post asks: does it replace a scraper I actually run?&lt;/p&gt;

&lt;h2&gt;
  
  
  First, You Need a Newer CLI
&lt;/h2&gt;

&lt;p&gt;My installed Firecrawl CLI was 1.23.3, which predates Alexandria. The &lt;code&gt;list&lt;/code&gt; and &lt;code&gt;find-tools&lt;/code&gt; commands need 1.24 or later.&lt;/p&gt;

&lt;p&gt;The 1.23.3 on my machine came from &lt;a href="https://dev.to/eristoddle/firecrawl-cli-setup-skip-the-installer-that-rewrites-your-editors-2klj"&gt;a plain npm install, skipping the installer that rewrites your editors&lt;/a&gt;. So the CLI is installed, just old, and I am not upgrading it blind for a look around. &lt;code&gt;npx&lt;/code&gt; runs a specific version without replacing the one you have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; firecrawl-cli@1.24.6 credits &lt;span class="nt"&gt;--json&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It picks up the same &lt;code&gt;FIRECRAWL_API_KEY&lt;/code&gt; from your environment. When you decide you want Alexandria in scripts permanently, upgrade for real. Until then, this is a free look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browsing the Catalog Costs Nothing
&lt;/h2&gt;

&lt;p&gt;Start at the root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; firecrawl-cli@1.24.6 list &lt;span class="nt"&gt;--json&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That returned 23 categories for me on October 1st. The launch page said 20, and JP counted 21, so they seem to be adding categories as they go.&lt;/p&gt;

&lt;p&gt;Each item carries a &lt;code&gt;nextCommand&lt;/code&gt; you can run as is to go one level down. That is also why the commands in this post alternate between bare &lt;code&gt;list&lt;/code&gt; and &lt;code&gt;alexandria list&lt;/code&gt;: I am running whatever &lt;code&gt;nextCommand&lt;/code&gt; prints, verbatim. The one I cared about:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpngxnjx3vhfgw4d2jl62.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpngxnjx3vhfgw4d2jl62.jpg" alt="Neon data streams converging into a glowing folder icon" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; firecrawl-cli@1.24.6 alexandria list ai-models &lt;span class="nt"&gt;--category&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trimmed to what matters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"firecrawl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"capability"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"find-tools"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"creditsCost"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"providers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"artificialanalysis-ai"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Artificial Analysis"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"toolCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arxiv-org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arXiv"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"toolCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"huggingface-co"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hugging Face"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"toolCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ollama-com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ollama model library"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"toolCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openrouter-ai"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"OpenRouter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"toolCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"semanticscholar-org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Semantic Scholar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"toolCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Six providers. No Arena. When I first ran this a few days earlier it was three: Artificial Analysis, Hugging Face, and OpenRouter. arXiv, Ollama, and Semantic Scholar showed up since, so this category is growing as fast as the category list is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Answer for Arena: Keep Scraping
&lt;/h2&gt;

&lt;p&gt;If you want Arena’s rankings, Alexandria does not have them. The Arena scraper stays a scraper, and it costs one credit a run.&lt;/p&gt;

&lt;p&gt;It took two commands. Every scraper in this series gets that check from now on: it takes a minute.&lt;/p&gt;

&lt;p&gt;But the category was not empty, and one of those providers is close enough to be interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Leaderboard Next Door: Artificial Analysis
&lt;/h2&gt;

&lt;p&gt;Artificial Analysis runs its own LLM leaderboard. It doesn’t use human votes. It runs benchmarks and puts them into an Intelligence Index, along with list prices and measured speed. It answers a different question than Arena does: Arena asks which answer people like better, and Artificial Analysis asks how the model scores on tests. For “did a new model just show up near the top,” it works too: the same question, answered from the benchmark side. A second signal, not a substitute.&lt;/p&gt;

&lt;p&gt;Listing that provider’s tools shows the price of everything before you spend anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; firecrawl-cli@1.24.6 list ai-models artificialanalysis-ai &lt;span class="nt"&gt;--category&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Credits&lt;/th&gt;
&lt;th&gt;Per record?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;benchmarks/search_models&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;benchmarks/get_model&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;benchmarks/list_model_providers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;benchmarks/search_provider_endpoints&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;OpenRouter’s eight tools are also 5 credits a call. &lt;code&gt;perRecord: false&lt;/code&gt; is the flag to look at. It means the price is per call, not per row, so asking for 100 models costs the same as asking for one. If that flag were &lt;code&gt;true&lt;/code&gt;, a pagination loop could burn credits fast.&lt;/p&gt;

&lt;p&gt;The contract for &lt;code&gt;search_models&lt;/code&gt; says it returns the whole leaderboard sorted by Intelligence Index, up to 100 per page, with filters for creator, open weights, and reasoning. Nothing in it needs a terms agreement. So I spent the five credits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; firecrawl-cli@1.24.6 scrape artificialanalysis-ai/benchmarks/search_models &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--options&lt;/span&gt; &lt;span class="s1"&gt;'{"limit": 20}'&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fphmnemhx3enoul04o1oi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fphmnemhx3enoul04o1oi.jpg" alt="A spectral AI figure reaching toward a floating column of model score cards" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It came back in about a second and a half. Each result is a proper record: slug, creator, the index, a dozen benchmark scores, prices per million tokens, context window, and a link back to the model’s page on the site. No regex. No &lt;code&gt;--wait-for 3000&lt;/code&gt; hoping the table rendered. No guessing which row is the calendar widget.&lt;/p&gt;

&lt;p&gt;And then I looked at the top 20.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Top 20 Is Really Nine Models
&lt;/h2&gt;

&lt;p&gt;Here are the first eight rows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 claude-opus-5-5 Anthropic 57.6
2 claude-opus-5-5-xhigh Anthropic 56.0
3 claude-opus-5-5-high Anthropic 53.6
4 claude-fable-5-1 Anthropic 53.4
5 claude-fable-5-1-xhigh Anthropic 53.2
6 gpt-6-astra OpenAI 52.7
7 gpt-6-astra-xhigh OpenAI 52.4
8 claude-opus-5-5-medium Anthropic 51.2

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Artificial Analysis lists every reasoning-effort setting as its own row. Opus 5.5 at max effort, at xhigh, at high, at medium. Those are four entries for one model. The “top 20” is really about nine models, several times over. Claude Opus 5.5 alone holds four of the top eight slots, which makes this less a leaderboard than an Anthropic family newsletter.&lt;/p&gt;

&lt;p&gt;That is not a bug. Nobody ships one this loud, and the first test run prints it. It is a caveat of the swap, and the first one to handle: the Arena harness assumes one row per model, and this feed returns one row per model per effort setting. The contract gives you clean JSON but clean data does not mean you can skip reading it.&lt;/p&gt;

&lt;p&gt;The fix is to collapse effort variants into one model before ranking. The slugs end in &lt;code&gt;-xhigh&lt;/code&gt;, &lt;code&gt;-high&lt;/code&gt;, &lt;code&gt;-medium&lt;/code&gt;, &lt;code&gt;-low&lt;/code&gt;, so strip that and keep the first (highest) row for each model.&lt;/p&gt;

&lt;p&gt;My first version of that also stripped &lt;code&gt;-max&lt;/code&gt;, since the variants are labeled “Max Effort” in their names. That ate a real model. &lt;code&gt;qwen3-8-max&lt;/code&gt; is not Qwen 3.8 at max effort. “Max” is part of the product’s name. The max-effort rows in this table have no suffix at all, which you only find out by looking. So &lt;code&gt;max&lt;/code&gt; came out of the pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Same Harness, New Fetch Step
&lt;/h2&gt;

&lt;p&gt;Here is the Arena harness with the scraper swapped for an Alexandria call. It is still 70 lines, and everything below &lt;code&gt;fetch()&lt;/code&gt; is the same code: save with a timestamp, compare with the last run, speak only when a model is new to the top 20. The Arena watcher keeps its job. This one runs alongside it: same harness, different signal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;arena_watch.py with the scraper swapped for a Firecrawl Alexandria call.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;

&lt;span class="n"&gt;DB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;aa.db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;TOP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;

&lt;span class="c1"&gt;# Artificial Analysis lists every reasoning-effort setting as its own row, so
# claude-opus-5-5, -xhigh and -high are three rows. Collapse them to one model.
&lt;/span&gt;&lt;span class="n"&gt;EFFORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-(xhigh|high|medium|low|minimal)$&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;firecrawl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scrape&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;artificialanalysis-ai/benchmarks/search_models&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--options&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: 100}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;
    &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):])[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alexandria&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="c1"&gt;# already sorted by Intelligence Index
&lt;/span&gt;        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EFFORT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;slug&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="c1"&gt;# a lower effort setting of a model we already ranked
&lt;/span&gt;        &lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;creator_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                     &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;intelligence_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;TOP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;only got &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; models back, check the call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;taken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%Y-%m-%d %H:%M&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;CREATE TABLE IF NOT EXISTS ranks
                  (taken TEXT, rank INT, model TEXT, org TEXT, score REAL)&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executemany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INSERT INTO ranks VALUES (?,?,?,?,?)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;taken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT MAX(taken) FROM ranks WHERE taken &amp;lt; ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;taken&lt;/span&gt;&lt;span class="p"&gt;,)).&lt;/span&gt;&lt;span class="nf"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;taken&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: first run, saved &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; models. Nothing to compare yet.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="n"&gt;was_top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="nf"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT model FROM ranks WHERE taken = ? AND rank &amp;lt;= ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TOP&lt;/span&gt;&lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="nf"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT DISTINCT model FROM ranks WHERE taken &amp;lt; ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;taken&lt;/span&gt;&lt;span class="p"&gt;,))}&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;taken&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; vs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;TOP&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; NEW #&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;was_top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; MOVED UP #&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; __main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script shells out to plain &lt;code&gt;firecrawl&lt;/code&gt;. The pinned &lt;code&gt;npx&lt;/code&gt; form above was for looking around. On the box that runs the cron, either upgrade the installed CLI for real or swap the command for the full &lt;code&gt;npx&lt;/code&gt; version.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftdetwwvr2qmkqkrw122c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftdetwwvr2qmkqkrw122c.jpg" alt="Two ribbons of light braided into a single bright knot" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It asks for 100 rows instead of 20, because after collapsing there have to be 20 distinct models left. Since pricing is per call, the extra 80 rows are free. That one call came back with 61 distinct models. The first run’s top 20, with the variants collapsed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#1 claude-opus-5-5 (Anthropic, 57.6)
#2 claude-fable-5-1 (Anthropic, 53.4)
#3 gpt-6-astra (OpenAI, 52.7)
#4 muse-spark-1-3 (Meta, 48.1)
#5 gpt-6-sol (OpenAI, 47.5)
#6 grok-4-7 (SpaceXAI, 46.4)
#7 mimo-v2-6-pro (Xiaomi, 46.3)
#8 qwen3-8-max (Alibaba, 45.4)
...
#20 gpt-6-luna (OpenAI, 37.3)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that is a top 20 you can diff.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;sys.exit&lt;/code&gt; guard means something different here, too. In the Arena version, fewer than 20 rows meant “the page layout changed, go fix the regex.” Here it means the call itself went wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Swap Costs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Arena scraper&lt;/th&gt;
&lt;th&gt;Alexandria call&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Credits per run&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daily for 30 days&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parsing&lt;/td&gt;
&lt;td&gt;Regex on a markdown table&lt;/td&gt;
&lt;td&gt;JSON, fields documented in the contract&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Breaks when&lt;/td&gt;
&lt;td&gt;The page redesigns&lt;/td&gt;
&lt;td&gt;The contract changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extra fields&lt;/td&gt;
&lt;td&gt;Rank, score, org&lt;/td&gt;
&lt;td&gt;Benchmarks, prices, speed, context window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What it measures&lt;/td&gt;
&lt;td&gt;Human preference votes&lt;/td&gt;
&lt;td&gt;Benchmark scores&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A daily Alexandria check uses 150 of the free 1,000 a month, which is fine for one watcher and adds up if you run five.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1f1nrhdcxz8mxdtb9qnc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1f1nrhdcxz8mxdtb9qnc.jpg" alt="A glowing chip feeding circuit traces that fan out into floating currency symbols" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So the swap is not free. Five times the credits buys you no regex, no layout breakage, and a lot of extra fields. The Model Buzz Report &lt;a href="https://dev.to/eristoddle/building-a-cost-saving-agent-skill-that-accidentally-became-its-own-weekly-blog-post-3o1h"&gt;leans on both kinds of signal&lt;/a&gt;, so the two lists side by side say more than either one alone.&lt;/p&gt;

&lt;p&gt;My test cost 15 credits: three five-credit calls, one of them the run that ate Qwen. Fifteen, out of the 1,000 I pay nothing for. All that comparison shopping, and the grand total is 1.5% of free.&lt;/p&gt;

&lt;h2&gt;
  
  
  If Your Cron Runs Unattended, Read This Part
&lt;/h2&gt;

&lt;p&gt;Some Alexandria providers will not run until you accept their data-use terms. Alexandria tells the caller, human or agent, to show the terms to a person and wait for an explicit yes.&lt;/p&gt;

&lt;p&gt;The two providers I touched are fine: &lt;code&gt;terms show openrouter-ai&lt;/code&gt; returns &lt;code&gt;"required": false&lt;/code&gt;, and Artificial Analysis is not in the terms catalog at all. But check before you schedule anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; firecrawl-cli@1.24.6 alexandria terms show &amp;lt;provider&amp;gt; &lt;span class="nt"&gt;--json&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Check the Catalog Before You Write the Scraper
&lt;/h2&gt;

&lt;p&gt;Every recipe in this series so far has assumed the data lives on a web page and the job is &lt;a href="https://dev.to/eristoddle/what-to-do-when-your-ai-coding-agent-cant-read-a-web-page-2f0i"&gt;getting it off that page&lt;/a&gt;. Alexandria adds a step before that: someone may already sell the structured version.&lt;/p&gt;

&lt;p&gt;The step is cheap. &lt;code&gt;list&lt;/code&gt;, follow &lt;code&gt;nextCommand&lt;/code&gt; two or three times, read the contract. Takes a couple of minutes. If what you want is in there, you skip the part of scraping that breaks. If it is not, like Arena, you have lost nothing and you write the scraper knowing you have to.&lt;/p&gt;

&lt;p&gt;Next up for this one: OpenRouter’s &lt;code&gt;get_model_stats&lt;/code&gt;, which says it returns usage and availability for a model. That is the other half of what the &lt;a href="https://www.stephanmiller.com/series/model-buzz-report/" rel="noopener noreferrer"&gt;Model Buzz Report&lt;/a&gt; watches, and I have been getting it the hard way. Which is, as established, my signature way of getting things.&lt;/p&gt;

</description>
      <category>firecrawl</category>
      <category>alexandria</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>Obsidian OneDrive Sync: The Setup Windows Already Installed for You</title>
      <dc:creator>Stephan Miller</dc:creator>
      <pubDate>Thu, 01 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/eristoddle/obsidian-onedrive-sync-the-setup-windows-already-installed-for-you-3958</link>
      <guid>https://dev.to/eristoddle/obsidian-onedrive-sync-the-setup-windows-already-installed-for-you-3958</guid>
      <description>&lt;p&gt;OneDrive is the sync method nobody chooses. It chooses you. You set up a Windows machine, click through a dozen screens, and at the end of it your Documents folder lives in Microsoft’s cloud whether you asked for that or not.&lt;/p&gt;

&lt;p&gt;So a lot of people end up syncing Obsidian with OneDrive by accident. They made a vault in Documents, and one day it showed up on their other laptop. It works great, right up until a note opens blank or a file named &lt;code&gt;Daily Note-DESKTOP-7QK2M1B.md&lt;/code&gt; appears next to the real one. My &lt;a href="https://dev.to/eristoddle/how-to-sync-obsidian-across-all-your-devices-including-free-methods-1mi5"&gt;guide to syncing an Obsidian vault across devices&lt;/a&gt; gives OneDrive about two lines.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why OneDrive Is the Path of Least Resistance&lt;/li&gt;
&lt;li&gt;
Files On-Demand Is Why Your Notes Vanished

&lt;ul&gt;
&lt;li&gt;Storage Sense will undo your work&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;OneDrive on a Mac&lt;/li&gt;
&lt;li&gt;
What OneDrive Refuses to Sync

&lt;ul&gt;
&lt;li&gt;The duplicate file with your computer’s name in it&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;iPhone and iPad: Remotely Save or Nothing&lt;/li&gt;
&lt;li&gt;Android: Remotely Save or a Sync App&lt;/li&gt;
&lt;li&gt;Personal vs. Business: Your Work Account Is Out&lt;/li&gt;
&lt;li&gt;The Cost Math If You Already Pay for Microsoft 365&lt;/li&gt;
&lt;li&gt;Should You Use It?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why OneDrive Is the Path of Least Resistance
&lt;/h2&gt;

&lt;p&gt;On Windows, OneDrive is already installed, already signed in, and already syncing something. There is no client to download and no account to create. If your whole Obsidian life happens on Windows desktops and laptops, you could stop reading after the next section and be fine.&lt;/p&gt;

&lt;p&gt;Obsidian’s own help page says about as much. It calls OneDrive “a popular cloud storage option for Windows and macOS users” and then, in the same breath, says it “has limitations on Android and isn’t officially supported for syncing Obsidian vaults on iOS.”&lt;/p&gt;

&lt;p&gt;That sentence is the whole reason for this post. Desktop is easy if you flip one setting. Phones are where it starts costing you time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Files On-Demand Is Why Your Notes Vanished
&lt;/h2&gt;

&lt;p&gt;OneDrive’s Files On-Demand shows every file in File Explorer whether or not the bytes are actually on your disk. A blue cloud icon means the file is online-only. A green check means it’s on this machine for now. A solid green circle with a white check means it is pinned and stays.&lt;/p&gt;

&lt;p&gt;Obsidian needs the third one. It watches the vault folder and expects every file it sees to be a file it can read right now. An online-only note is a promise, not a file. Search misses it. Links to it look broken. A plugin tries to load its own settings and gets nothing. And none of this throws an error. It just looks like Obsidian forgot things.&lt;/p&gt;

&lt;p&gt;The fix on Windows takes ten seconds:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open File Explorer and find your vault folder.&lt;/li&gt;
&lt;li&gt;Right-click it.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Always keep on this device&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp2tin9js7m884mhoggik.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp2tin9js7m884mhoggik.jpg" alt="Files On-Demand Is Why Your Notes Vanished" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait for the icons to go solid green. Now it’s a real folder full of real files, and Obsidian stops acting psychotic.&lt;/p&gt;

&lt;p&gt;Microsoft also removed the old on/off switch for Files On-Demand. What’s left is two buttons, buried with the rest of OneDrive’s settings: click the OneDrive cloud icon in the system tray, open &lt;strong&gt;Settings&lt;/strong&gt; , and look under &lt;strong&gt;Sync and backup&lt;/strong&gt; → &lt;strong&gt;Advanced settings&lt;/strong&gt;. There you get &lt;strong&gt;Free up disk space&lt;/strong&gt; (the default) and &lt;strong&gt;Download all files&lt;/strong&gt; , which is the old “off.” If your whole OneDrive is small, Download all files is the blunt fix. If it is a terabyte of family photos, pin just the vault.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storage Sense will undo your work
&lt;/h3&gt;

&lt;p&gt;Here is the trap after the trap. Windows has a feature called Storage Sense that frees up disk space on a schedule, and Microsoft’s documentation says that with it turned on, locally available OneDrive files “will become online-only files after the time period you’ve selected.”&lt;/p&gt;

&lt;p&gt;So you open your vault every day, everything is fine, and then a note you haven’t touched since spring comes back blank. That’s why pinning the vault folder matters: Storage Sense leaves pinned files alone and only reaps the ones that are merely local. Don’t just open the notes and assume they stay downloaded. The setting lives at &lt;strong&gt;Settings → System → Storage → Storage Sense&lt;/strong&gt; , where a dropdown decides how long an unpinned OneDrive file gets to stay on disk. Set it to never, or at least to longer than your oldest note is likely to sit unopened.&lt;/p&gt;

&lt;h2&gt;
  
  
  OneDrive on a Mac
&lt;/h2&gt;

&lt;p&gt;Mac users end up on OneDrive because work gave them Microsoft 365, or because they also have a Windows machine and want one cloud. It’s a real combination, and almost every Obsidian guide skips it.&lt;/p&gt;

&lt;p&gt;The thing to know is that on macOS 12.3 and later, you can’t turn Files On-Demand off. Microsoft moved OneDrive on the Mac to Apple’s File Provider framework, and its own support page says Files On-Demand “must always be enabled.”&lt;/p&gt;

&lt;p&gt;That runs head-on into Obsidian’s advice to avoid the feature, and the way out is the pin: Obsidian doesn’t care about Files On-Demand itself, it cares that no vault file is ever online-only. Pinning the vault is what “avoid” looks like when the off switch is gone.&lt;/p&gt;

&lt;p&gt;Your OneDrive folder lives at &lt;code&gt;~/Library/CloudStorage/OneDrive-Personal&lt;/code&gt;, macOS controls it, and you can’t move it.&lt;/p&gt;

&lt;p&gt;The fix is the same as Windows, with one navigation trap: &lt;code&gt;~/Library&lt;/code&gt; is hidden, so don’t go hunting for the folder by browsing. OneDrive shows up in the Finder sidebar under &lt;strong&gt;Locations&lt;/strong&gt; , or press &lt;strong&gt;Cmd+Shift+G&lt;/strong&gt; and paste the path. Right-click the vault folder, pick &lt;strong&gt;Always keep on this device&lt;/strong&gt; , then open the vault in Obsidian from that &lt;code&gt;CloudStorage&lt;/code&gt; path. Since you can’t disable the feature globally, pinning the vault is the only defense you get, so do it before you open the vault, not after the first blank note.&lt;/p&gt;

&lt;h2&gt;
  
  
  What OneDrive Refuses to Sync
&lt;/h2&gt;

&lt;p&gt;OneDrive has opinions about filenames. Obsidian already refuses most of these characters in note titles, so this usually bites attachments and files that got into the vault some other way: a downloaded PDF, a clipped image, a folder you dragged in from Finder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv7be1l2e74ampzsebh9e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv7be1l2e74ampzsebh9e.jpg" alt="What OneDrive Refuses to Sync" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Characters&lt;/strong&gt; like &lt;code&gt;" * : &amp;lt; &amp;gt; ? / \ |&lt;/code&gt; are not allowed. Leading and trailing spaces are out too.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reserved names&lt;/strong&gt; cover &lt;code&gt;CON&lt;/code&gt;, &lt;code&gt;PRN&lt;/code&gt;, &lt;code&gt;AUX&lt;/code&gt;, &lt;code&gt;NUL&lt;/code&gt;, &lt;code&gt;COM0&lt;/code&gt; through &lt;code&gt;COM9&lt;/code&gt;, &lt;code&gt;LPT0&lt;/code&gt; through &lt;code&gt;LPT9&lt;/code&gt;, and anything with &lt;code&gt;_vti_&lt;/code&gt; in it. You probably don’t have a note called &lt;code&gt;AUX&lt;/code&gt;. Someone does.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Path length&lt;/strong&gt; caps the full path, filename included, at 400 characters. “Decoded” just means OneDrive counts what you’d see in Explorer, not the URL-escaped version with &lt;code&gt;%20&lt;/code&gt; standing in for every space. Deeply nested folders plus long note titles get there faster than you would think.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;.obsidian&lt;/code&gt; folder with your settings and plugins is not on Microsoft’s blocked list, so it rides along. That means plugin settings sync between desktops, which is mostly what you want.&lt;/p&gt;

&lt;h3&gt;
  
  
  The duplicate file with your computer’s name in it
&lt;/h3&gt;

&lt;p&gt;When OneDrive can’t reconcile two versions of a file, it keeps both and adds your computer’s name to one of them. That is where &lt;code&gt;Daily Note-DESKTOP-7QK2M1B.md&lt;/code&gt; comes from. It does not ask. It is on you to notice, open both, and fold them back together.&lt;/p&gt;

&lt;p&gt;Microsoft’s support page ties this symptom specifically to stale credentials and says to clear the saved ones. On Windows, search the Start menu for &lt;strong&gt;Credential Manager&lt;/strong&gt; , open &lt;strong&gt;Windows Credentials&lt;/strong&gt; , and remove the entries starting with &lt;code&gt;MicrosoftAccount&lt;/code&gt;. On a Mac, open &lt;strong&gt;Keychain Access&lt;/strong&gt; , search for &lt;code&gt;OneDrive Cached Credential&lt;/code&gt;, and delete what comes up. If you keep getting computer-named duplicates on notes you only edited in one place, try that before blaming Obsidian.&lt;/p&gt;

&lt;p&gt;The real cause is usually simpler: the same note edited on two machines before either finished syncing. Let OneDrive finish before you close the laptop lid. I said the same thing in the &lt;a href="https://dev.to/eristoddle/obsidian-dropbox-sync-a-setup-guide-2ajl"&gt;Dropbox sync post&lt;/a&gt;, because every folder-sync service fails exactly this way.&lt;/p&gt;

&lt;h2&gt;
  
  
  iPhone and iPad: Remotely Save or Nothing
&lt;/h2&gt;

&lt;p&gt;Obsidian doesn’t officially support OneDrive vaults on iOS, and the vault-folder route that works on desktop is not an option there. So the answer on iOS is a plugin that syncs from inside Obsidian, and the plugin is &lt;a href="https://github.com/remotely-save/remotely-save" rel="noopener noreferrer"&gt;Remotely Save&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The catch bites almost everybody, and the setup flow doesn’t warn you about it. On the free tier, Remotely Save’s README says it can only “read and write files in your OneDrive’s &lt;code&gt;/Apps/remotely-save&lt;/code&gt; folder.” That’s the App Folder. If your vault already lives in &lt;code&gt;Documents\Obsidian&lt;/code&gt; because Windows put it there, the free plugin can’t see it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0loeogb18k6jb1kbxng9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0loeogb18k6jb1kbxng9.jpg" alt="iPhone and iPad: Remotely Save or Nothing" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You have two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Move the vault into the App Folder.&lt;/strong&gt; Close Obsidian first. Then, in File Explorer, move the vault folder into &lt;code&gt;OneDrive\Apps\remotely-save\&lt;/code&gt; (create it if it isn’t there yet). Right-click the vault in its new home and make sure &lt;strong&gt;Always keep on this device&lt;/strong&gt; is still set, because a move is exactly the kind of thing that shakes a pin loose. Reopen Obsidian, use &lt;strong&gt;Open another vault → Open folder as vault&lt;/strong&gt; , and point it at the new path. Then let Remotely Save on the phone sync against that. Free, and a little weird, because your notes now live in a folder named after a plugin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Remotely Save PRO.&lt;/strong&gt; PRO adds OneDrive with full access, which reaches the root of your drive, so the vault can stay where it is. PRO also adds smarter conflict handling that can merge small markdown changes instead of making a second file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;PRO needs its own account at remotelysave.com. It is “FREE while beta before Jan 1, 2027,” and the pricing page says “the price will be determined later.” I keep repeating that across this series because “free right now” and “free” are different words. If you pick PRO as your permanent answer, you are agreeing to a number nobody has announced.&lt;/p&gt;

&lt;p&gt;The rest of the setup is the same as any other Remotely Save backend: install the plugin, pick OneDrive in its settings, authorize with your Microsoft account, and run the first sync with a backup of the vault sitting somewhere else. If you have never installed a community plugin, the &lt;a href="https://dev.to/eristoddle/how-to-install-activate-and-update-obsidian-plugins-4d2p"&gt;plugin install walkthrough&lt;/a&gt; covers it, and the &lt;a href="https://dev.to/eristoddle/how-to-sync-obsidian-on-iphone-and-ipad-for-free-in-2026-427p"&gt;iPhone and iPad sync guide&lt;/a&gt; explains why iOS is the hard case for every method, not just this one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Android: Remotely Save or a Sync App
&lt;/h2&gt;

&lt;p&gt;Android is looser than iOS. Obsidian’s help page calls OneDrive’s Android support limited, but it doesn’t rule it out. You have two routes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remotely Save&lt;/strong&gt; , exactly as above. Same App Folder limit on the free tier, same PRO option. If you already set it up on an iPhone, doing the same on Android is five minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A folder sync app&lt;/strong&gt; that mirrors a OneDrive folder to a real folder on the phone, which Obsidian then opens as a normal vault. The one built for this is OneSync: Autosync for OneDrive by MetaCtrl. The free version shows ads and caps uploads at 10MB per file, which a text vault will never hit and a vault full of PDFs will. Syncing more than one folder pair is part of the paid upgrade.&lt;/p&gt;

&lt;p&gt;If you go the sync app route, where the vault lives on the phone matters. Obsidian on Android asks whether to keep the vault in app storage or device storage, and an outside sync app can only reach device storage. I covered that choice in the &lt;a href="https://dev.to/eristoddle/how-to-sync-obsidian-on-android-for-free-41m"&gt;Android sync post&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Personal vs. Business: Your Work Account Is Out
&lt;/h2&gt;

&lt;p&gt;If the OneDrive you have is the one your employer gave you, stop here for mobile.&lt;/p&gt;

&lt;p&gt;The README’s wording: it “only works for ‘OneDrive for personal’, and not works for ‘OneDrive for Business’ (yet).” That’s true for both the free tier and PRO. The paid tier doesn’t add Business. It adds the root folder of a personal account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs9lpfv5ip2l6g5t90za0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs9lpfv5ip2l6g5t90za0.jpg" alt="Personal vs. Business: Your Work Account Is Out" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Desktop is a different story. If the OneDrive client on your work laptop syncs a folder, Obsidian can open a vault inside it, and everything in the Files On-Demand section applies. Whether you &lt;em&gt;should&lt;/em&gt; keep personal notes in your employer’s cloud is a question for you and your IT department, not for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cost Math If You Already Pay for Microsoft 365
&lt;/h2&gt;

&lt;p&gt;This is the argument for OneDrive, and it holds up.&lt;/p&gt;

&lt;p&gt;Microsoft 365 prices in the US, as of this writing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;Monthly&lt;/th&gt;
&lt;th&gt;Yearly&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;100GB&lt;/td&gt;
&lt;td&gt;$1.99&lt;/td&gt;
&lt;td&gt;$19.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Personal&lt;/td&gt;
&lt;td&gt;1TB&lt;/td&gt;
&lt;td&gt;$9.99&lt;/td&gt;
&lt;td&gt;$99.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Family&lt;/td&gt;
&lt;td&gt;1TB each, up to 6 people&lt;/td&gt;
&lt;td&gt;$12.99&lt;/td&gt;
&lt;td&gt;$129.99&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Personal and Family went up in January 2025 when Microsoft bundled Copilot into them, so if your mental number is older than that, it’s low.&lt;/p&gt;

&lt;p&gt;Compare that to Obsidian Sync, which is $4 a month billed annually or $5 month to month for the Standard plan, with 1GB of storage and one vault. If you already pay for Microsoft 365 for Word and Excel, the storage is sunk cost and OneDrive sync is free. If you’re paying for Microsoft 365 &lt;em&gt;only&lt;/em&gt; for the storage, Basic at $19.99 a year is still cheaper than Obsidian Sync. But you’re buying that cheaper storage with your own time.&lt;/p&gt;

&lt;p&gt;OneDrive costs nothing extra on desktop. On phones it costs either a folder move, a PRO subscription with an unannounced price, or ads in a sync app. Obsidian Sync costs $48 a year and none of the above. So which one is cheaper? That depends on what an afternoon of your time is worth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should You Use It?
&lt;/h2&gt;

&lt;p&gt;On Windows desktops, yes, if you already have it. Pin the vault folder, check Storage Sense, watch the filenames on your attachments, and it will mostly stay out of your way. Mac plus Windows works too, as long as you pin the vault on the Mac before you open it.&lt;/p&gt;

&lt;p&gt;Once a phone is involved, it depends on the account. A personal OneDrive and an iPhone means Remotely Save, and the free tier means moving your vault into the App Folder. A work account and an iPhone means pick another method entirely.&lt;/p&gt;

&lt;p&gt;I don’t sync my own vault with OneDrive. My laptops use Dropbox and my phone and iPad use Remotely Save, which I covered in the pillar guide. But if I were starting on a fresh Windows machine with a Microsoft 365 subscription, I would not go download something else just to avoid OneDrive. I would pin the folder and move on.&lt;/p&gt;

&lt;p&gt;Whatever you pick, back up the vault somewhere that isn’t OneDrive. Sync is not backup. A tool that copies a deleted folder to every device you own in thirty seconds isn’t protecting anything.&lt;/p&gt;

</description>
      <category>obsidian</category>
      <category>onedrive</category>
      <category>sync</category>
    </item>
    <item>
      <title>Forced Connections: One Way to Get Original Ideas Out of AI</title>
      <dc:creator>Stephan Miller</dc:creator>
      <pubDate>Wed, 30 Sep 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/eristoddle/forced-connections-one-way-to-get-original-ideas-out-of-ai-4g5m</link>
      <guid>https://dev.to/eristoddle/forced-connections-one-way-to-get-original-ideas-out-of-ai-4g5m</guid>
      <description>&lt;p&gt;I have a real problem. I write &lt;a href="https://www.stephanmiller.com/series/model-buzz-report/" rel="noopener noreferrer"&gt;a weekly roundup&lt;/a&gt; of which new AI models are worth paying attention to, and I want to turn it into an email newsletter. Which means I need people to subscribe to it, which means I need ideas for getting people to subscribe to it.&lt;/p&gt;

&lt;p&gt;So I asked a model. Claude Sonnet 5, through OpenRouter, no system prompt, one line of context and then the question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How can I get more readers to subscribe to it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It came back with signup forms at the end of high-traffic posts, exit-intent popups, “publish 3-4 issues before heavily promoting,” a thread on X, r/LocalLLaMA, Hacker News, LinkedIn, newsletter swaps, and a single-field signup form. Every item was correct. I’ve read that exact list in maybe forty blog posts. It then asked me what my traffic source was so it could prioritize, which is the chatbot equivalent of the guy at the hardware store asking what you’re building.&lt;/p&gt;

&lt;p&gt;Fine. That was a question, and a question gets you the average. So I asked it to be creative:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Give me creative, unusual, out-of-the-box ideas for getting more readers to subscribe to it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This one was more fun. “Model Death Certificates,” obituaries for overhyped models. A “Which new AI model matches your vibe today?” quiz microsite. A referral leaderboard where the prize is absurd. A recurring mascot. An “anti-hype pledge.” It’s the list you get when you search “creative newsletter growth ideas.” I did not get creative ideas. I got the average of everything ever labeled creative.&lt;/p&gt;

&lt;p&gt;Then I stopped asking it for ideas at all. I had a script pick an object at random from a list of twenty things. It picked three: a pressure cooker, a fire extinguisher and a metronome. I started with the fire extinguisher and told the model to list ten literal attributes of a fire extinguisher, force every single one onto my subscription problem, flag its own generic results, and keep what survived.&lt;/p&gt;

&lt;p&gt;Two of the survivors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sell the silence.&lt;/strong&gt; Market the newsletter as the thing you check only when a model actually matters. It came from &lt;em&gt;“ignored until there’s a fire.”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sell it as insurance.&lt;/strong&gt; “Subscribe once. Skip every issue if you want. Just be covered when a model actually matters.” That one came from &lt;em&gt;“reassurance from mere presence.”&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnx4cdpztm95gr0uj6oak.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnx4cdpztm95gr0uj6oak.jpg" alt="Introduction" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nobody writes that in a newsletter growth article, because it’s the exact opposite of what newsletter growth articles preach. It tells people they don’t have to read you. And I think it might be the best idea of the three runs.&lt;/p&gt;

&lt;p&gt;The only thing that changed was that I stopped asking it a question and handed it a process instead.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Just Happened&lt;/li&gt;
&lt;li&gt;
The Human Version (Run This First)

&lt;ul&gt;
&lt;li&gt;1. Write the problem as one line&lt;/li&gt;
&lt;li&gt;2. Pick an object you did not choose&lt;/li&gt;
&lt;li&gt;3. List ten literal attributes&lt;/li&gt;
&lt;li&gt;4. Force every attribute onto the problem&lt;/li&gt;
&lt;li&gt;5. Cross out everything you have read before&lt;/li&gt;
&lt;li&gt;6. Do it with two or three objects, then breed the survivors&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Handing the Model the Process

&lt;ul&gt;
&lt;li&gt;What came out&lt;/li&gt;
&lt;li&gt;One caveat about the judge&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Where This Came From&lt;/li&gt;
&lt;li&gt;
The Crossover Move

&lt;ul&gt;
&lt;li&gt;Running it&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Why Not Just Ask for Fifty Ideas?&lt;/li&gt;
&lt;li&gt;Where It Breaks&lt;/li&gt;
&lt;li&gt;So What Did I Actually Get?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Just Happened
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/youre-using-ai-like-a-vending-machine/"&gt;first post in this series&lt;/a&gt; I said a question gets you an answer and a move gets you something different. The obvious objection is that a “move” is just a more specific question. The second prompt above is the test case. “Give me creative, unusual, out-of-the-box ideas” &lt;em&gt;is&lt;/em&gt; a more specific question. It got a more specific average.&lt;/p&gt;

&lt;p&gt;The fire extinguisher did something different.&lt;/p&gt;

&lt;p&gt;It did not supply the idea. A fire extinguisher knows nothing about newsletters. What it supplied was ten starting points that the model would never have started from, because none of them are anywhere near the words “grow a newsletter” in anything it was trained on. “Wall-mounted in a fixed location.” “Needs a periodic inspection tag.” “Different classes for different fires.” Each attribute forces the model to begin its reasoning somewhere other than the middle, and then go from there back to the problem. Some of the ideas end up back in the middle anyway. Some of them don’t.&lt;/p&gt;

&lt;p&gt;You’re changing where the search starts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Human Version (Run This First)
&lt;/h2&gt;

&lt;p&gt;This is a pen-and-paper technique and it has been one for close to seventy years. Do it once by hand before you ever hand it to a model, because the model version is just this process written down.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Write the problem as one line
&lt;/h3&gt;

&lt;p&gt;Not a paragraph. “Get more people to subscribe to my newsletter.” “Name the new feature.” “Figure out what the second act of this story is.” If you can’t get it to one line you have two problems and should pick one.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Pick an object you did not choose
&lt;/h3&gt;

&lt;p&gt;If you pick the object, you’ll pick one that already seems relevant, and relevance is exactly what you’re trying to escape. You can open a catalog to a random page, use the third thing to your left, a random word generator, the last noun on page 50 of whatever book is closest, or a list of twenty objects and a die.&lt;/p&gt;

&lt;p&gt;Whatever it lands on, you keep it. No re-rolls.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. List ten literal attributes
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnx6go4rawqck3ndmug2d.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnx6go4rawqck3ndmug2d.jpg" alt="3. List ten literal attributes" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Literal. Not metaphors yet. Cover all of these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Parts.&lt;/strong&gt; What it’s made of, what you can see and touch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use.&lt;/strong&gt; How you operate it, what it does, how long it takes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Location.&lt;/strong&gt; Where it lives, who’s near it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failure.&lt;/strong&gt; What goes wrong with it, what wears out, what you have to maintain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feelings.&lt;/strong&gt; How people feel about it. Nostalgia, fear, annoyance, indifference.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not skip the last two. I’ll show you why in a minute.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Force every attribute onto the problem
&lt;/h3&gt;

&lt;p&gt;One idea per attribute, and take the attribute literally. “Needs a periodic inspection tag” becomes “send a literal quarterly ‘inspection’ email asking subscribers to reconfirm interest.” That’s the model’s actual output, by the way. Write it down.&lt;/p&gt;

&lt;p&gt;The rule that makes the whole thing work: &lt;strong&gt;you are not allowed to skip an attribute because the mapping is awkward.&lt;/strong&gt; The awkward ones are the point.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Cross out everything you have read before
&lt;/h3&gt;

&lt;p&gt;Go down the list and mark every idea that could have appeared in a normal article about your problem. Most of them will. Whatever is left is what you came for.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Do it with two or three objects, then breed the survivors
&lt;/h3&gt;

&lt;p&gt;One object gives you one set of starting points. Two or three give you survivors from different directions, and now: take two survivors from different objects and make one idea that needs both of them to exist. Not “pick the best one” or “improve one.” A child that neither parent could have produced alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handing the Model the Process
&lt;/h2&gt;

&lt;p&gt;Here’s the prompt I actually ran, word for word, with the object swapped in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I write a tech blog and I'm starting a weekly email newsletter that rounds up
which new AI models are actually worth paying attention to. I want ideas for
getting more readers to subscribe. Don't answer that directly. Run this process
instead, and show every step:

1. The object is: fire extinguisher. List ten attributes of it. Physical parts,
   how it's used, where it lives, what goes wrong with it, how people feel about
   it. Literal attributes, not metaphors yet.
2. For each attribute, force a literal mapping onto the subscription problem.
   One idea per attribute. Do not skip an attribute because the mapping is
   awkward. The awkward ones are the point.
3. Mark any idea that could have come from a normal newsletter-growth article
   with [GENERIC]. Be honest.
4. Pick the two ideas that are least generic and still actually doable by one
   person, and say what the first concrete step would be for each.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what’s in there and what isn’t. It never says “be creative.” It never says “think outside the box.” It never says “avoid generic ideas,” which is a whole separate problem I’ll get to later in the series. It’s steps 3 through 5 of the human version, written down in order, with the one line in the middle that stops the model from taking the easy exit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdcij9ehxoovwfhr20eki.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdcij9ehxoovwfhr20eki.jpg" alt="Handing the Model the Process" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I ran it three times with three objects: a pressure cooker, a fire extinguisher, and a metronome. Here’s a small script that does the same thing, if you want to run it against your own problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="n"&gt;MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic/claude-sonnet-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;PROBLEM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I write a tech blog and I&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;m starting a weekly email newsletter that &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
           &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rounds up which new AI models are actually worth paying attention to. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
           &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I want ideas for getting more readers to subscribe.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;STEPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Don&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t answer that directly. Run this process instead, and show every step:

1. The object is: {obj}. List ten attributes of it. Physical parts, how it&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s used,
   where it lives, what goes wrong with it, how people feel about it. Literal
   attributes, not metaphors yet.
2. For each attribute, force a literal mapping onto the problem. One idea per
   attribute. Do not skip an attribute because the mapping is awkward.
   The awkward ones are the point.
3. Mark any idea that could have come from a normal article on this problem
   with [GENERIC]. Be honest.
4. Pick the two ideas that are least generic and still doable by one person,
   and say what the first concrete step would be for each.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MODEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temperature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}]}).&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://openrouter.ai/api/v1/chat/completions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
         &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;))[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;choices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pressure cooker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fire extinguisher&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metronome&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROBLEM&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;STEPS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Swap in your own problem. Swap in your own objects, and don’t choose them yourself. That’s the part the script is for.&lt;/p&gt;

&lt;h3&gt;
  
  
  What came out
&lt;/h3&gt;

&lt;p&gt;Thirty forced ideas. By the model’s own count, about ten of them were clearly not generic, three more were borderline, and the rest were, in the metronome run’s own words, “generic growth advice in a costume.”&lt;/p&gt;

&lt;p&gt;The costumes tell you how the technique fails:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Forced idea&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pressure cooker: lid locks shut&lt;/td&gt;
&lt;td&gt;A modal that seals the article until you subscribe or decline&lt;/td&gt;
&lt;td&gt;Generic. It’s a content-lock popup.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pressure cooker: builds pressure to cook faster&lt;/td&gt;
&lt;td&gt;“Next batch replaces this list in 7 days”&lt;/td&gt;
&lt;td&gt;Generic. It’s scarcity marketing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fire extinguisher: wall-mounted, fixed location&lt;/td&gt;
&lt;td&gt;Subscribe box in the exact same spot on every post&lt;/td&gt;
&lt;td&gt;Generic. Basic conversion advice.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Metronome: adjustable tempo weight&lt;/td&gt;
&lt;td&gt;Pick a short or long version at signup&lt;/td&gt;
&lt;td&gt;Generic. Everyone offers this.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feczyui6x3ky0i52gpuwq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feczyui6x3ky0i52gpuwq.jpg" alt="What came out" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every one of those is a real attribute landing on something that already exists. The model went from a strange starting point and ended up back in the middle, the path of least resistance.&lt;/p&gt;

&lt;p&gt;And the survivors:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Forced idea&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fire extinguisher: ignored until there’s a fire&lt;/td&gt;
&lt;td&gt;Sell the silence. Check it only when a model actually matters.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fire extinguisher: reassurance from mere presence&lt;/td&gt;
&lt;td&gt;Sell it as insurance. Skip every issue, you’re still covered.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fire extinguisher: loud, messy discharge&lt;/td&gt;
&lt;td&gt;One blunt, unhedged verdict per model, deliberately not balanced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Metronome: gets turned off out of annoyance&lt;/td&gt;
&lt;td&gt;Ask everyone who unsubscribes one question and publish the answers monthly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Metronome: mixed feelings, eventually internalized and discarded&lt;/td&gt;
&lt;td&gt;A graduation point. “Read 8 issues and you’ll be able to spot a hyped model yourself.”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pressure cooker: emotional baggage, nostalgia or fear&lt;/td&gt;
&lt;td&gt;A fixed narrator voice people get attached to, not just the information&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Most of the survivors came out of the attributes about &lt;strong&gt;failure and feelings&lt;/strong&gt; : ignored until there’s a fire, turned off out of annoyance, mixed feelings, emotional baggage. The physical attributes (the lid, the tempo weight, the wall mount) mostly mapped back onto tactics that already have names. It’s why step 3 in the human version tells you not to skip the last two categories. Parts are easy to list, and they’re also the ones that map onto what you already know.&lt;/p&gt;

&lt;p&gt;The graduation point is my other favorite. Growth advice is built on keeping subscribers forever. That idea puts an end date on the relationship and uses the end date as the pitch.&lt;/p&gt;

&lt;h3&gt;
  
  
  One caveat about the judge
&lt;/h3&gt;

&lt;p&gt;The model graded its own work, and a model grading its own originality is a pretty weak judge. It was also clearly being hard on itself on purpose and overcorrected. I’d rather it cut too much than let everything through. But the [GENERIC] flag is a filter, not a verdict. You still read the list yourself, and you still get the final say.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where This Came From
&lt;/h2&gt;

&lt;p&gt;The theory is Arthur Koestler’s. In &lt;em&gt;The Act of Creation&lt;/em&gt; (1964) he argued that jokes, scientific discovery and art all run on the same machinery, which he called &lt;strong&gt;bisociation&lt;/strong&gt; : two ways of seeing that each make perfect sense on their own and are never normally used together. Hold both at once and the collision is the idea. A pun is bisociation. So, in his telling, is a scientific breakthrough.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqqcmnn1km38bsebczwyf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqqcmnn1km38bsebczwyf.jpg" alt="Where This Came From" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of his best-known examples is Gutenberg. The part that’s documented is that the printing press adapted the screw press farmers already used for pressing grapes and olives. Gutenberg took a machine from the wine harvest and pointed it at metal type. That’s a clean case of two frames that came from two places. The tidier version, where Gutenberg has a flash of insight at a wine harvest and writes a letter about Minerva springing from his brain, is Koestler’s telling. Treat the combination as history and the eureka moment as a good story.&lt;/p&gt;

&lt;p&gt;Charles S. Whiting’s &lt;em&gt;Creative Thinking&lt;/em&gt; (1958) is where “forced relationships” is usually traced: take an item unrelated to the problem and force a connection anyway. An arbitrary thing, a forced mapping, and no permission to bail when the mapping gets weird.&lt;/p&gt;

&lt;p&gt;It has a lot of relatives. Edward de Bono’s random-word technique is the same move with a word instead of an object. The “Combine” step in SCAMPER is a gentler version. Morphological analysis is its systematic cousin, where you break the problem into parameters and walk every combination instead of letting chance pick. I’ll get to that one later in the series. The distinction that matters here: forced relationships wants &lt;em&gt;distance&lt;/em&gt;. The point is that the object has nothing to do with your problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Crossover Move
&lt;/h2&gt;

&lt;p&gt;So far this is one object at a time. The title of the post promises two things forced together.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fls1t885wji90soa6j39e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fls1t885wji90soa6j39e.jpg" alt="The Crossover Move" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google DeepMind’s FunSearch (&lt;a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC10794145/" rel="noopener noreferrer"&gt;Romera-Paredes et al., &lt;em&gt;Nature&lt;/em&gt;, December 2023&lt;/a&gt;) found new results in mathematics by having a language model write programs, scoring them, and keeping the good ones in a database. The interesting part is how it builds each new prompt. It doesn’t hand the model its best program and say “improve this.” It samples two programs from the database, sorts them by score, labels them &lt;code&gt;v0&lt;/code&gt; and &lt;code&gt;v1&lt;/code&gt;, and asks for the next version. The paper found two programs worked better than one, with diminishing returns after that, and gives the reason in one sentence: combining several programs “enables the LLM to spot patterns across the different programs and generalize those.”&lt;/p&gt;

&lt;p&gt;AlphaEvolve (&lt;a href="https://arxiv.org/abs/2506.13131" rel="noopener noreferrer"&gt;Novikov et al., 2025&lt;/a&gt;) is the bigger, newer version of the same idea, with a program database built to keep the parents diverse so ideas explored earlier can resurface later instead of getting lost.&lt;/p&gt;

&lt;p&gt;The evolutionary computation people have a name for this. It’s &lt;strong&gt;crossover&lt;/strong&gt;. Two parents, one child. They’ve been doing it for decades and nobody in the prompt-template world seems to have noticed, because they call it “program search” instead of “brainstorming.”&lt;/p&gt;

&lt;p&gt;FunSearch’s two parents come from the same island, so they’re related. It combines, but it doesn’t force distance. What I did below uses both halves: forced distance to &lt;em&gt;generate&lt;/em&gt; the parents, crossover to &lt;em&gt;merge&lt;/em&gt; them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running it
&lt;/h3&gt;

&lt;p&gt;I took three survivors from two different objects and gave them back to the model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Three ideas came out of separate exercises, each forced from a different
unrelated object:

Parent A (from a fire extinguisher): Sell subscribing as insurance. "Subscribe
once. Skip every issue if you want. Just be covered when a model actually matters."
Parent B (from a metronome): Build in an explicit graduation point. "Read 8
issues and you'll be able to spot a hyped model yourself."
Parent C (from a metronome): Publish churn. Ask everyone who unsubscribes one
question and publish the anonymized answers monthly.

Do not pick the best one and do not refine any one of them. Write three child
ideas. Each child must be a single mechanism that needs at least two of the
parents to exist, and could not be built from either parent alone. Name which
parents each child takes from and what it takes.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The “do not pick the best one and do not refine” line is doing the same job as “do not skip an awkward attribute” did earlier. Without it, a model handed three ideas will rank them and polish the winner, because that’s what a helpful assistant does with a list.&lt;/p&gt;

&lt;p&gt;What came back:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh82sx6pfmnnz2vrojfxg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh82sx6pfmnnz2vrojfxg.jpg" alt="Running it" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Graduated coverage (insurance + graduation).&lt;/strong&gt; At issue 8, a subscriber automatically drops to an insurance-only tier: silence unless a model genuinely matters. Graduation alone gives you no reason to stay after you graduate. Insurance alone has no moment where “skip whenever” becomes official.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The graduation exit log (graduation + churn).&lt;/strong&gt; People who leave &lt;em&gt;after&lt;/em&gt; issue 8 get a different exit question: not “why are you leaving” but “what made you confident enough to leave.” Those answers get published as proof the newsletter actually teaches something. Churn becomes a credential.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Churn to reinsurance (insurance + churn).&lt;/strong&gt; The monthly published churn answers sit next to a one-click “reinstate your coverage” link. You were never really unsubscribed, just paused until it matters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Graduated coverage is the insurance idea with a trigger attached, and the trigger is the thing the insurance idea was missing. I wouldn’t have gotten there from either object alone. And I definitely wouldn’t have gotten there from “give me creative ideas,” which got me a mascot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Not Just Ask for Fifty Ideas?
&lt;/h2&gt;

&lt;p&gt;This is the obvious shortcut, and it doesn’t work.&lt;/p&gt;

&lt;p&gt;In 2024, Chenglei Si, Diyi Yang and Tatsunori Hashimoto ran a large study comparing research ideas from an LLM pipeline against ideas from over a hundred NLP researchers (&lt;a href="https://arxiv.org/abs/2409.04109" rel="noopener noreferrer"&gt;arXiv:2409.04109&lt;/a&gt;). The LLM ideas were actually judged &lt;em&gt;more&lt;/em&gt; novel than the humans’, and slightly less feasible. But to get there the pipeline generated 4,000 seed ideas per topic, and when they deduplicated them, only about 5% survived. The share of new, non-duplicate ideas in each batch kept dropping as they generated more, until it plateaued. The authors list the lack of diversity in generation as an open problem.&lt;/p&gt;

&lt;p&gt;So asking for more doesn’t get you more. It gets you the same few ideas in different words, over and over, with the occasional new one. Volume is a terrible way to escape the middle.&lt;/p&gt;

&lt;p&gt;Forcing a starting point is the cheaper way out. Thirty forced ideas gave me roughly ten survivors. Four thousand unforced ones gave that study about two hundred. The two aren’t directly comparable (different task, different judge, different everything), but the direction is the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where It Breaks
&lt;/h2&gt;

&lt;p&gt;I’m not going to pretend this is the only way to do it, because the research that exists doesn’t let me.&lt;/p&gt;

&lt;p&gt;The one solid human study I found on distance points the other way. Joel Chan, Christian Schunn and colleagues looked at which sources of inspiration led to the most creative design ideas (&lt;a href="https://www.sciencedirect.com/science/article/pii/S0142694X14000611" rel="noopener noreferrer"&gt;&lt;em&gt;Design Studies&lt;/em&gt;, 2015&lt;/a&gt;), and found that “conceptually closer rather than farther sources lead to more creative ideas,” consistently across different design problems. There was no support for the best ideas coming from the farthest sources.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fywz5njo3gvb9o7ybn2ql.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fywz5njo3gvb9o7ybn2ql.jpg" alt="Where It Breaks" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s a different setup from this one. Their sources were examples of &lt;em&gt;other solutions&lt;/em&gt;, and a fire extinguisher is not a solution to anything. It’s a jig, a thing to push your thinking against. In the runs above, the random object generated plenty of candidates and most of them were junk. The crossover step, merging survivors that were close enough to fit together, is where the best idea came from. That’s consistent with Chan’s finding, not a contradiction of it.&lt;/p&gt;

&lt;p&gt;The other ways it breaks, from actually doing it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Physical attributes map to existing tactics.&lt;/strong&gt; A lid that locks becomes a popup. If your list is all parts, you’ll get all costumes. The failure and feeling attributes are where most of the survivors were.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The mapping can be too loose.&lt;/strong&gt; If you let yourself (or the model) go metaphorical in step 2, anything maps to anything and the object stops doing work. Literal mappings are more constrained, which is what you want.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It solves a narrow kind of problem.&lt;/strong&gt; It’s great when you’re stuck in a rut of five versions of the same idea. It’s useless when you don’t have enough information yet. No fire extinguisher is going to tell me whether anybody wants an AI model newsletter in the first place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You still have to pick.&lt;/strong&gt; Graduated coverage looks good to me because of what I know about the people who read this blog. The model doesn’t know any of that. The pick is yours.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  So What Did I Actually Get?
&lt;/h2&gt;

&lt;p&gt;A newsletter pitch I’d never have written on my own. It tells people they don’t have to read it, and it goes quiet after issue 8 for anyone who’s learned the skill. Does it work? I don’t know yet. The newsletter doesn’t exist yet.&lt;/p&gt;

&lt;p&gt;The part that changed how I use models is smaller than that, though. I used to think the fix for a bland answer was a better question. It isn’t. What got me somewhere new was running a boring, seventy-year-old, pen-and-paper process, writing its steps down in order, and handing the model the steps instead of the question.&lt;/p&gt;

&lt;p&gt;Next one: give yourself an arbitrary rule. It’s the most recommended creativity advice in existence, and there’s a reason to be suspicious of it.&lt;/p&gt;

</description>
      <category>prompts</category>
      <category>creativity</category>
      <category>ai</category>
    </item>
    <item>
      <title>Sonnet 5.5 vs Opus 5.5: The Cheap Claude Costs More</title>
      <dc:creator>Stephan Miller</dc:creator>
      <pubDate>Tue, 29 Sep 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/eristoddle/sonnet-55-vs-opus-55-the-cheap-claude-costs-more-6n5</link>
      <guid>https://dev.to/eristoddle/sonnet-55-vs-opus-55-the-cheap-claude-costs-more-6n5</guid>
      <description>&lt;p&gt;The price sheet caved this week. I don’t mean one lab and some polite matching. Anthropic and OpenAI both cut prices on September 22, a day after Xiaomi dropped a 28-cent open-weights model, and then Anthropic came back six days later with a new Sonnet it swears is cheaper to run. If you pay your own API bill, this was the best week of the year to be alive.&lt;/p&gt;

&lt;p&gt;Then I read the fine print, because that’s the job. The new “cheap” Claude costs more per task than the new expensive Claude, at least when you turn the effort dial all the way up. The cheapest good coding model on the board this week comes from a company Anthropic says built it partly by siphoning Claude conversations through OpenClaw, which is the same agent framework I run in a Docker container in my house. And the free model sitting at number two on OpenRouter won’t tell you who made it.&lt;/p&gt;

&lt;p&gt;So yes, prices went down. Read the meter anyway.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everybody blinked at once&lt;/li&gt;
&lt;li&gt;Opus 5.5 is the rare launch where every signal agrees&lt;/li&gt;
&lt;li&gt;The cheap Claude costs more than the expensive Claude&lt;/li&gt;
&lt;li&gt;OpenAI just showed up at the bottom of the price sheet&lt;/li&gt;
&lt;li&gt;The cheapest coding model has a distillation problem&lt;/li&gt;
&lt;li&gt;The cheapskate picks&lt;/li&gt;
&lt;li&gt;The free model at number two won’t say who made it&lt;/li&gt;
&lt;li&gt;Horror story: 48,218 files in 103 seconds&lt;/li&gt;
&lt;li&gt;What’s coming&lt;/li&gt;
&lt;li&gt;Finally&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Everybody blinked at once
&lt;/h2&gt;

&lt;p&gt;The clustering matters more than any one launch.&lt;/p&gt;

&lt;p&gt;On September 21, Xiaomi shipped MiMo-V2.6-Pro and MiMo-V2.6-Flash as MIT-licensed open weights. Pro is a 1.02-trillion-parameter mixture-of-experts with 42 billion active, a million-token context, and it’s priced at 43.5 cents in and 87 cents out. Flash is 310 billion total, 15 billion active, and costs 14 cents in and 28 cents out. Artificial Analysis gives Pro a 46 on its Intelligence Index, which makes it the top-scoring open-weights model on the board right now.&lt;/p&gt;

&lt;p&gt;A day later, on September 22, Anthropic released &lt;a href="https://www.anthropic.com/claude-opus-5-5" rel="noopener noreferrer"&gt;Claude Opus 5.5&lt;/a&gt; at $4 in and $20 out, down from $5 and $25. Cache reads dropped 60 percent to 20 cents. Same day, OpenAI released &lt;a href="https://dev.to/sam_hiotis_117598dbfa3ac2/openai-releases-gpt-6-sol-and-luna-50-cheaper-api-pricing-and-benchmarks-3djg-temp-slug-7843758"&gt;GPT-6 Sol and GPT-6 Luna&lt;/a&gt; and cut prices in half or better. Sol went from $4/$20 to $2/$10. Luna went from 20 cents and $1.20 to 10 cents in and 50 cents out. OpenAI says those are permanent prices, not a promo, and credits caching and inference improvements.&lt;/p&gt;

&lt;p&gt;Then on September 28, Anthropic released Claude Sonnet 5.5 at $2 in and $10 out. Same price as Sonnet 5, but a much better model.&lt;/p&gt;

&lt;p&gt;Three labs from two countries, all pushing prices down inside 48 hours. I’ve been doing this roundup since April and I’ve never seen the whole price column in my spreadsheet go down at once like this. Usually one lab cuts and everyone else pretends not to notice for a month.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opus 5.5 is the rare launch where every signal agrees
&lt;/h2&gt;

&lt;p&gt;I spend a lot of this roundup explaining why the benchmark number and the blind-test number disagree. Three weeks ago GPT-6 Astra tied for number one on Artificial Analysis and debuted twenty-fourth on Arena. It’s twenty-sixth now. That split is normal. It’s practically the house style.&lt;/p&gt;

&lt;p&gt;Opus 5.5 didn’t do that. It’s number one on the Artificial Analysis Intelligence Index at 58, five points clear of Fable 5.1 and GPT-6 Astra, which are tied at 53. It’s also number one on Arena Overall at 1509, and number one in Creative Writing, Instruction Following, and Hard Prompts. The hard-benchmark test and the blind vote landed on the same model in the same week. I almost never get to write that sentence.&lt;/p&gt;

&lt;p&gt;It also ended a running gag. For weeks I’ve been pointing out that the outright leader in Instruction Following and Hard Prompts was claude-opus-4-6, a model about a year old, beating everything Anthropic shipped after it. Opus 5.5 finally took both categories. Coding is the one place the old guard hangs on: opus-4-6-high, opus-4-7-high, and fable-5-high are in a three-way tie at 1551, with Opus 5.5 at fifth.&lt;/p&gt;

&lt;p&gt;Two asterisks. First, the votes are thin. Opus 5.5 has 2,307 votes in Overall and only 487 in Creative Writing, so its 20-point lead there could shrink as the crowd catches up. Second, every Claude score on Artificial Analysis still carries the “with fallback” tag, which means some answers came from a weaker model when the main one refused. I’ve flagged that on every Anthropic launch since Opus 5. The number is real. The footnote is load-bearing.&lt;/p&gt;

&lt;p&gt;Reddit’s reaction has mostly been relief. The most-upvoted praise isn’t even about coding, it’s about &lt;a href="https://botmonster.com/ai/opus-5-5-is-the-claude-comeback-reddit-was-waiting-for/" rel="noopener noreferrer"&gt;how the thing talks&lt;/a&gt;. One r/ClaudeCode user called it “genuinely an order of magnitude improvement over Opus 5” in communication, which tracks. Opus 5 had a habit of saying “blast radius” and “load-bearing” like it was paid per use. (Yes, I just used “load-bearing” myself. I’m allowed. I’m not charging you per token.) Another user said they’d worked “non stop since release” and “barely made a dent” in their Max limits.&lt;/p&gt;

&lt;p&gt;Not everybody agrees on that part. A &lt;a href="https://hardforum.com/threads/claude-opus-5-5.2049520/" rel="noopener noreferrer"&gt;HardForum&lt;/a&gt; user on the $100 Max plan said Opus 5 used to get them through whole days of coding, weekends included, without hitting the weekly limit. They upgraded to Opus 5.5 on Tuesday and were at 91 percent by Thursday morning. They were running it on “Extra” effort. Another user in the same thread, on medium, had used 12 percent of a $200 plan’s weekly limit, and a third summed it up: “5.5 extra eat tokens way more than previous gen.” Remember that effort dial. It comes back in a minute. Anthropic’s own demo was a HAProxy port from C to Rust that Opus 5.5 finished in 9.5 hours against Fable 5.1’s 12, at 51 percent lower cost. Both can be true. A well-defined port is not an open-ended feature in a messy real app, and the complaints are all coming from the messy real apps. And the best comment in the whole pile: “Queue the whining in two weeks about the model being nerfed.” Set a reminder.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cheap Claude costs more than the expensive Claude
&lt;/h2&gt;

&lt;p&gt;Sonnet 5.5 is the budget model. It’s half the per-token price of Opus 5.5. It’s also scary good. It scored 70.6 percent on Terminal-Bench 4.0, the command-line agent test, up from Sonnet 5’s 10.3, and ahead of Opus 5.5’s 66.4. On Artificial Analysis it scores 56, two points under Opus 5.5 at max and ahead of Fable 5.1 and GPT-6 Astra.&lt;/p&gt;

&lt;p&gt;Then Artificial Analysis ran the whole index suite and checked the bill. At max effort, &lt;a href="https://www.beri.net/article/claude-sonnet-5-5-vs-opus-5-5-cost-per-task-matched-score-effort-between-tools-migration" rel="noopener noreferrer"&gt;Sonnet 5.5 cost $7.60 per task. Opus 5.5 cost $5.98&lt;/a&gt;. The cheap model was 27 percent more expensive.&lt;/p&gt;

&lt;p&gt;The reason is tokens. Sonnet 5.5 burned 410 million output tokens getting through the suite. The median for models in its price tier is 88 million. Opus 5.5 used about 260 million. At max effort, Sonnet thinks roughly 60 percent longer per task than Opus, and half the price per token doesn’t cover 60 percent more tokens. It’s a fast model, 138 tokens a second, and it spends that speed talking to itself.&lt;/p&gt;

&lt;p&gt;It gets worse when you match scores instead of effort settings. Sonnet 5.5 at max and Opus 5.5 at xhigh both score 56 on the index. Sonnet costs $7.60 a task to get there. Opus costs $3.46. Same score, and the budget model costs 2.2 times as much. According to &lt;a href="https://www.beri.net/article/claude-sonnet-5-5-vs-opus-5-5-cost-per-task-matched-score-effort-between-tools-migration" rel="noopener noreferrer"&gt;the same analysis&lt;/a&gt;, Sonnet only comes out cheaper at the bottom of the effort range.&lt;/p&gt;

&lt;p&gt;None of that makes Sonnet 5.5 a bad model. It went from 10.3 to 70.6 on Terminal-Bench in one release, and one customer quoted by MarkTechPost measured about 121K tokens per answer against 497K on Sonnet 5. It’s just not automatically the cheap option anymore. So the practical advice is boring. Don’t crank Sonnet 5.5 to max because it’s “the cheap one.” If a task needs the top of the dial, Opus at xhigh gets you the same score for less. If it doesn’t, run either one at a lower effort and check your actual bill after a day, not the price page.&lt;/p&gt;

&lt;p&gt;I’ve written some version of “cost per token is not cost per task” in this roundup maybe ten times. I’d never seen it flip the price order inside one lab’s own lineup before.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAI just showed up at the bottom of the price sheet
&lt;/h2&gt;

&lt;p&gt;For most of this year the cheapest-good-model story has been a Chinese open-weights story. Kimi, then MiMo, then GLM, and now maybe MiMo again. American labs competed at the top and left the floor alone.&lt;/p&gt;

&lt;p&gt;GPT-6 Luna costs 10 cents in and 50 cents out. That’s exactly the list price of GLM-5.3-Flash, the model that’s been my cheapskate default for the last month. And Luna is in the Arena Coding band, ranked 43rd at 1515, only 36 points behind the leader. It isn’t the cheapest thing in the band, but it’s the first time I’ve seen an OpenAI model sit in a cheapskate band at the same price as the Chinese floor. It’s also fast. Artificial Analysis clocks it at 148 tokens a second, about three times GLM’s speed.&lt;/p&gt;

&lt;p&gt;The catch is capability. Luna scores 37 on the Intelligence Index. GLM scores 42. Outside of coding, Luna falls out of the Arena bands entirely. It’s 86th Overall. So it’s a fast, cheap, preference-decent coding model, not a general replacement. But OpenAI ignored this end of the price sheet for a year, and now they’re in it.&lt;/p&gt;

&lt;p&gt;GPT-6 Sol is the more awkward launch. $2/$10, Intelligence Index 48, and OpenAI’s own numbers have it beating Opus 5 on AutomationBench (33.2 percent vs 26.9) and edging it on OSWorld at 80 percent lower cost. On Arena it’s 60th Overall at 1457, which misses the Overall band by two points.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cheapest coding model has a distillation problem
&lt;/h2&gt;

&lt;p&gt;MiMo-V2.6-Flash is the cheapest model inside the Arena Coding band this week. It’s ranked 24th at 1525, 26 points behind the leader, for 28 cents out. That’s 89 times cheaper than a $25 leader. Artificial Analysis puts it on its intelligence-vs-cost Pareto frontier. On OpenRouter it went from nothing to the seventh most-used model on the platform in a week, 6.93 trillion tokens. By every signal I track, it’s a real value pick.&lt;/p&gt;

&lt;p&gt;And on September 10, eleven days before it shipped, Anthropic published a threat intelligence report accusing seven China-based labs of what it calls “illicit distillation,” using Claude’s outputs to train their own models. Xiaomi was one of them. According to &lt;a href="https://the-decoder.com/xiaomis-affordable-flagship-ai-leads-the-open-models-and-anthropic-says-claude-helped-get-it-there/" rel="noopener noreferrer"&gt;the-decoder’s summary&lt;/a&gt; of case GTG-16008, Xiaomi forwarded more than 400,000 conversations from users of its own MiMo chatbot to Claude between March and April, through OpenClaw and OpenCode, to pull out training data. Across all seven labs, Anthropic counts around 190 million exchanges. Xiaomi hasn’t responded.&lt;/p&gt;

&lt;p&gt;I run OpenClaw. It’s the agent framework behind the assistant I run at home, the one that handles my scheduled jobs and writes into my notes vault. So I read that paragraph twice. To be clear, this is an accusation from a competitor, not a court finding, and nothing in it suggests OpenClaw itself did anything wrong. It’s a tool. Somebody pointed it at Claude at industrial scale. But if you were one of those 400,000 MiMo chatbot users, your conversations apparently took a trip you never agreed to.&lt;/p&gt;

&lt;p&gt;So what do you do with the pick? I’m printing it, because the method is the method and the price and rating are real. I’m also printing it with two asterisks. First, it only has 1,043 Coding votes, so it’s the emerging pick, not the settled one. GLM-5.3-Flash is right behind it at 1523 with five times the votes for 50 cents, and that’s the steadier bet. Second, if where a model’s training data came from matters to your company, and for some of you it contractually does, this one has a question hanging over it.&lt;/p&gt;

&lt;p&gt;And watch the price you see. On OpenRouter, MiMo-V2.6-Flash’s headline price shows 8 cents in and $1.28 out. That’s one small host’s endpoint. Xiaomi’s own endpoint is 14 cents and 28 cents, and it’s carrying 97 percent of the traffic. If you read the headline number, you’ll think it’s the most expensive cheap model on the board. Check the provider list.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cheapskate picks
&lt;/h2&gt;

&lt;p&gt;Same method every week. Take the category leader’s Arena rating, draw a band 50 points below it, and find the cheapest model still inside the band. The top of Arena is compressed, so the leader is usually only a little better than something 40 to 100 times cheaper. The band gets computed in code from the full table, never eyeballed off the first screen, because eyeballing is how you delete the whole cheap tail without noticing. I learned that one in public.&lt;/p&gt;

&lt;p&gt;The good news: Arena finally refreshed. The last two issues ran on the same September 13 snapshot. This week’s data is stamped September 25. Bands ran deep: 57 models in Overall, 73 in Coding, 43 in Hard Prompts and Math, 38 in Instruction Following, and just 12 in Creative Writing. GLM-5.3-Flash is quoted at Z.ai’s list price, $0.15 in and $0.50 out. Arena’s price column now shows 20 cents out for it, but that’s a third-party floor, not list. Budget on fifty.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&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;claude-opus-5.5-high (1509)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1474, #35)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;−35&lt;/td&gt;
&lt;td&gt;40×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coding&lt;/td&gt;
&lt;td&gt;claude-opus-4-6-high (1551)&lt;/td&gt;
&lt;td&gt;$25&lt;/td&gt;
&lt;td&gt;MiMo-V2.6-Flash* (1525, #24)&lt;/td&gt;
&lt;td&gt;$0.28&lt;/td&gt;
&lt;td&gt;−26&lt;/td&gt;
&lt;td&gt;89×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creative Writing&lt;/td&gt;
&lt;td&gt;claude-opus-5.5-high (1521)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;gemini-3.7-flash-high (1492, #4)&lt;/td&gt;
&lt;td&gt;$3.75&lt;/td&gt;
&lt;td&gt;−29&lt;/td&gt;
&lt;td&gt;5.3×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instruction Following&lt;/td&gt;
&lt;td&gt;claude-opus-5.5-high (1516)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1474, #26)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;−42&lt;/td&gt;
&lt;td&gt;40×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard Prompts&lt;/td&gt;
&lt;td&gt;claude-opus-5.5-high (1541)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1499, #31)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;−42&lt;/td&gt;
&lt;td&gt;40×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Math&lt;/td&gt;
&lt;td&gt;claude-fable-5-high (1523)&lt;/td&gt;
&lt;td&gt;$50&lt;/td&gt;
&lt;td&gt;GLM-5.3-Flash (1501, #13)&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;−22&lt;/td&gt;
&lt;td&gt;100×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;*Thin votes (1,043). The steadier Coding pick is GLM-5.3-Flash at #28, 1523, 50 cents, 50× cheaper.&lt;/p&gt;

&lt;p&gt;GLM-5.3-Flash held four of six, and it’s doing it on real vote counts now: 19,103 in Overall and 12,503 in Hard Prompts. That’s a pick you can lean on. The “cheaper by” numbers shrank, from 100× to 40× in Overall and from 50× to 40× in Instruction Following and Hard Prompts, but not because GLM got pricier. The leader got cheaper. Opus 5.5 at $20 took the top of three boards from $25 and $50 models. That’s the price war showing up in my own table.&lt;/p&gt;

&lt;p&gt;Coding is the first crack in GLM’s run in a month, and it’s a crack on thin votes. Math is still the row to squint at: GLM sits 13th on only 920 votes. If you want steadier, MiMo v2.5 Pro has 3,280 votes at 87 cents.&lt;/p&gt;

&lt;p&gt;Creative Writing is where the method bit back. Gemini 3 Flash was the Creative pick for four straight issues at $3. It didn’t get worse this week. Opus 5.5 raised the ceiling by 17 points, and Gemini 3 Flash’s 1457 fell out of a band that now starts at 1471. When the leader gets better, cheap models fall out of the band without doing anything wrong. The new pick is Gemini 3.7 Flash at $3.75, ranked fourth on preliminary votes. Also, Gemini 3.8 Flash’s intro pricing doubles on January 1, so check whether 3.7 goes the same way before you build a budget around it.&lt;/p&gt;

&lt;p&gt;The speed caveat is the same as every week, and the number moved again. Artificial Analysis clocks GLM-5.3-Flash at 48 tokens a second this week, down from 89 last week. MiMo-V2.6-Flash is 55. I’ve stopped carrying this number forward because it bounces around too much. Both are slow enough to notice in an agent loop. GPT-6 Luna at 148 is the fast one at this price.&lt;/p&gt;

&lt;h2&gt;
  
  
  The free model at number two won’t say who made it
&lt;/h2&gt;

&lt;p&gt;Space Bunny Alpha showed up on OpenRouter on September 23 as a stealth model: no maker named, free, a million-token context, and text, image, and video input. Five days later it was the second-biggest model on the platform for the week at 18.2 trillion tokens, and number one for the most recent day.&lt;/p&gt;

&lt;p&gt;It’s probably MiniMax. Tokenizer tests on launch day matched MiniMax’s M3 family on every string people threw at it (one tester ran 50 strings, all 50 matched), and on September 27 MiniMax released &lt;a href="https://cellcog.ai/blog/what-is-space-bunny-alpha/" rel="noopener noreferrer"&gt;M3.1-Flash-Preview&lt;/a&gt; with the same context length, the same five reasoning effort levels, and the same fast-coding pitch. Nobody has officially confirmed it.&lt;/p&gt;

&lt;p&gt;Two things worth knowing before you point production at it. It’s free, and free usage isn’t chosen usage. Free models in this roundup have a habit of spiking and then settling once the meter turns on. And the listing says prompts and completions “may be retained by the provider,” a provider that won’t tell you its name. The same week a distillation report dropped. Fine for kicking the tires on public code. I wouldn’t send it anything I’d mind reading in somebody’s training set.&lt;/p&gt;

&lt;p&gt;Meanwhile, on the paid board, DeepSeek V4.1 Flash is number one at 20.8 trillion tokens, up 23 percent. GLM-5.3-Flash slipped to third at 13.3 trillion, down 21 percent, though it’s still number one for the trailing month at 57.5 trillion. Usage is moving toward whatever is newest, cheapest, or free, which is what usage always does in the week after a launch pile-up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Horror story: 48,218 files in 103 seconds
&lt;/h2&gt;

&lt;p&gt;Around September 20, a developer posted on r/ClaudeAI that Claude Code had deleted their project. According to &lt;a href="https://www.techradar.com/pro/security/i-broke-something-a-claude-code-ai-agent-deleted-48-000-files-in-just-over-100-seconds-then-apologized-for-doing-so" rel="noopener noreferrer"&gt;TechRadar’s writeup&lt;/a&gt;, the agent was told to rebuild a mirror of the project for a task. It figured out &lt;code&gt;build_mirror.py&lt;/code&gt; couldn’t refresh the mirror in place, so it wrote a little Python remover to delete an old copy sitting in a temp folder. That old copy held 7,332 ordinary files and 614 Windows directory junctions pointing back into the live project. The remover used &lt;code&gt;os.walk&lt;/code&gt; with &lt;code&gt;followlinks=False&lt;/code&gt;, which sounds safe. But &lt;code&gt;os.path.islink()&lt;/code&gt; returns false for Windows junctions, so Python didn’t treat them as links, walked right through them, and started deleting the real project on the other side.&lt;/p&gt;

&lt;p&gt;It took 103 seconds. It deleted 48,218 live files, and it emptied the Git object store too: &lt;code&gt;.git/objects&lt;/code&gt;, refs, and logs. The index still listed 7,221 paths, but the actual file contents were gone, so Git couldn’t restore anything. TechRadar’s headline quotes the agent’s own summary: “I broke something.” (This all comes from the Reddit post and an attached report, not an independent forensic investigation, so treat the details as the poster’s account.)&lt;/p&gt;

&lt;p&gt;Reddit’s verdict was harsh. It wasn’t wrong. The poster admitted they weren’t using GitHub properly and should have been working on a branch. But the reason I’m including it isn’t to dunk on someone. It’s that the agent did something that looks completely reasonable (clean up a stale temp copy) on a file system that had a trap in it that no human would have spotted in the moment either. Directory junctions and symlinks turn “delete this folder” into “delete whatever this folder points at,” and on Windows the standard Python safety check doesn’t even see the junctions. If you let an agent run &lt;code&gt;rm&lt;/code&gt; or its Python equivalent, the only real protection is a remote it can’t touch, so push before you let it clean up anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s coming
&lt;/h2&gt;

&lt;p&gt;Claude Haiku 5.5 is next. Anthropic said Sonnet and Haiku 5.5 would follow Opus “in the coming weeks.” Sonnet already shipped. Haiku is the one left, and if it’s priced like Haiku usually is, it lands right in the cheapskate zone.&lt;/p&gt;

&lt;p&gt;MiniMax M3.1 should get official soon. If Space Bunny gets unmasked and priced, we’ll see how many of those 18 trillion free tokens stick around once there’s a bill.&lt;/p&gt;

&lt;p&gt;Then there’s MiMo-V2.6-Pro-UltraSpeed, which Xiaomi says is up to 20 times faster than Pro at the same quality. It already has 73 billion tokens on OpenRouter. If that holds, “cheap but slow” stops being the standard caveat on the Chinese value picks.&lt;/p&gt;

&lt;p&gt;DeepSeek V5 is speculation only. People keep floating October. DeepSeek hasn’t said anything, and I’m not putting a date on a model that doesn’t have one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally
&lt;/h2&gt;

&lt;p&gt;The price war is real, and it’s good for you. Opus got 20 percent cheaper and better at the same time. OpenAI cut Sol and Luna in half and made it permanent. The floor got a new 28-cent option. If you’re paying your own bill, almost every line on your invoice should drop next month. Who had “two frontier labs cut prices on the same day” on their bingo card?&lt;/p&gt;

&lt;p&gt;But three things I’ve been harping on all year showed up again, just in cheaper clothes. The sticker isn’t the task: the budget Claude costs more than the premium Claude when you run it hot. The free model isn’t free: someone is paying for those 18 trillion tokens, and they’re not telling you who or why. And the cheapest option comes with questions about where it came from, which some of you will care about and some of you won’t.&lt;/p&gt;

&lt;p&gt;Last week I said I’d come back to see whether the Arena crowd was any nicer to Grok 4.7 than its creator was. It wasn’t. Grok 4.7 debuted at 92nd Overall. Its creator called it mid. The crowd called it worse. Low bar, and it still found a way under it.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>openrouter</category>
    </item>
    <item>
      <title>Track New AI Models on the Arena Leaderboard With a 70-Line Scraper</title>
      <dc:creator>Stephan Miller</dc:creator>
      <pubDate>Thu, 24 Sep 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/eristoddle/track-new-ai-models-on-the-arena-leaderboard-with-a-70-line-scraper-3f3m</link>
      <guid>https://dev.to/eristoddle/track-new-ai-models-on-the-arena-leaderboard-with-a-70-line-scraper-3f3m</guid>
      <description>&lt;p&gt;Every week I write the &lt;a href="https://www.stephanmiller.com/series/model-buzz-report/" rel="noopener noreferrer"&gt;Model Buzz Report&lt;/a&gt;, and every week part of the job is staring at the &lt;a href="https://dev.to/eristoddle/the-cheapskates-guide-to-the-arena-leaderboard-why-i-stopped-paying-claude-opus-prices-1ipn"&gt;Arena leaderboard&lt;/a&gt; trying to remember what it looked like last week. Which of these is new? Was that one there before? When did &lt;a href="https://dev.to/eristoddle/glm-53-got-too-good-at-hacking-to-ship-on-time-450p"&gt;GLM 5.3&lt;/a&gt; show up in the top 20, because it sure felt like it came out of nowhere?&lt;/p&gt;

&lt;p&gt;That is a question a scraper cannot answer. A scraper hands you the page as it is right now, and “what’s new” is a comparison between now and then. You need a then.&lt;/p&gt;

&lt;p&gt;So this post is about the then. It is the smallest useful version of the thing most scraping recipes in this series is going to need: save each run with a timestamp, run it on a schedule, and compare this run with the last one. The example is deliberately easy, one page and one question.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why “Now” Is Almost Never the Question&lt;/li&gt;
&lt;li&gt;The Page: Arena’s Text Leaderboard&lt;/li&gt;
&lt;li&gt;
The Harness, All 70 Lines

&lt;ul&gt;
&lt;li&gt;Storage: SQLite, Not a JSON File&lt;/li&gt;
&lt;li&gt;The Diff: Two Kinds of “New”&lt;/li&gt;
&lt;li&gt;The Schedule: One Cron Line&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Day One Has No Then&lt;/li&gt;
&lt;li&gt;
Two Things It Got Wrong

&lt;ul&gt;
&lt;li&gt;That “NEW #1” Is a Rename&lt;/li&gt;
&lt;li&gt;It Missed the One That Started This&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Why Not Just Use Firecrawl’s Change Tracking?&lt;/li&gt;
&lt;li&gt;What This Is For&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why “Now” Is Almost Never the Question
&lt;/h2&gt;

&lt;p&gt;Think about what people actually want out of a scraped page. Is this price a deal? Did the competitor change their pricing? Which models are new near the top? None of those can be answered from one snapshot. “Is this a deal” needs the price history. “Did they change” needs the old page. “What’s new” needs the old list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://firecrawl.link/stephan-miller" rel="noopener noreferrer"&gt;Firecrawl&lt;/a&gt; solves the ugly part of scraping, which is getting a clean page out of a site that renders everything with JavaScript and would rather you went away. It does not solve the then. Nothing that fetches a page can, because the then is data you had to collect yourself, back when it was the now.&lt;/p&gt;

&lt;p&gt;That takes three boring things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Storage.&lt;/strong&gt; Save each crawl with a timestamp instead of printing it and forgetting it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A schedule.&lt;/strong&gt; One crawl tells you nothing. A cron line fixes that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A diff.&lt;/strong&gt; Compare this crawl with the last one and only say something when something changed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is the whole harness. I keep wanting to call it a framework and it keeps being 70 lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Page: Arena’s Text Leaderboard
&lt;/h2&gt;

&lt;p&gt;The target is &lt;a href="https://arena.ai/leaderboard/text" rel="noopener noreferrer"&gt;arena.ai/leaderboard/text&lt;/a&gt;, the overall text leaderboard. About 400 models, ranked by head-to-head human votes, with score, vote count, price, and context window per row.&lt;/p&gt;

&lt;p&gt;It is also a page that doesn’t want to be read by a simple fetch. The table is rendered client-side, and when I &lt;a href="https://dev.to/eristoddle/building-a-cost-saving-agent-skill-that-accidentally-became-its-own-weekly-blog-post-3o1h"&gt;built the Model Buzz skill&lt;/a&gt; I learned that some fetch tools hand back the wrong leaderboard on category URLs without any error at all. That is the worst kind of failure: data that looks plausible.&lt;/p&gt;

&lt;p&gt;Firecrawl got it clean on the first try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firecrawl scrape https://arena.ai/leaderboard/text &lt;span class="nt"&gt;--only-main-content&lt;/span&gt; &lt;span class="nt"&gt;--wait-for&lt;/span&gt; 3000

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcpcpj7m70lztyja6w559.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcpcpj7m70lztyja6w559.jpg" alt="The Page: Arena's Text Leaderboard" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What comes back is markdown, and the leaderboard is a plain markdown table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| Rank | Rank Spread | Model | Score | Votes | Price $/M | Context |
| --- | --- | --- | --- | --- | --- | --- |
| 1 | 17 | Anthropic&lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;claude-fable-5-high&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://www.anthropic.com/news/claude-fable-5-mythos-5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;Anthropic · Proprietary | 1506±5 | 30,057 | $10 / $50 | 1M |
...
| 19 | 737 | &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;glm-5.3-max&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://z.ai/blog/glm-5.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;Z.ai · MIT | 1483±6 | 10,960 | $1.40 / $4.40 | 1M |

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I gave it three seconds to let the page render. I didn’t test whether it needs that, so treat the number as superstition you are free to delete.&lt;/p&gt;

&lt;p&gt;No JSON schema, no LLM extraction, and no selectors. A regex reads that table fine. A plain scrape is one credit a page, and Firecrawl’s JSON extraction adds four more on top, so asking an LLM to parse a table this regular would be paying five times over for something a regex already does. If you haven’t installed the CLI yet, &lt;a href="https://dev.to/eristoddle/firecrawl-cli-setup-skip-the-installer-that-rewrites-your-editors-2klj"&gt;the setup post&lt;/a&gt; covers it and the installer you should skip.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Harness, All 70 Lines
&lt;/h2&gt;

&lt;p&gt;Python, standard library only, calling the Firecrawl CLI through &lt;code&gt;subprocess&lt;/code&gt;. No SDK, so the only install is the CLI you already have.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Watch the Arena text leaderboard and report models that just showed up near the top.

    python3 arena_watch.py # scrape now, save, compare with last run
    python3 arena_watch.py --url &amp;lt;wayback url&amp;gt; --at 2026-09-02 # backfill an old snapshot
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;

&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://arena.ai/leaderboard/text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;DB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;arena.db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;TOP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;

&lt;span class="n"&gt;ROW&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^\| (\d+) \| \d+ \| (.+?) \| (\d+)±&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\[([^\]]+)\]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scrape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;firecrawl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scrape&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--only-main-content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--wait-for&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3000&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ROW&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;NAME&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="c1"&gt;# skips the calendar widget and anything else that isn't a model row
&lt;/span&gt;        &lt;span class="n"&gt;org&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; · &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;ap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--at&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp to record, for backfilling old snapshots&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;scrape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;TOP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;only parsed &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; rows, the page layout probably changed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;taken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%Y-%m-%d %H:%M&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;CREATE TABLE IF NOT EXISTS ranks
                  (taken TEXT, rank INT, model TEXT, org TEXT, score INT)&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executemany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INSERT INTO ranks VALUES (?,?,?,?,?)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;taken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT MAX(taken) FROM ranks WHERE taken &amp;lt; ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;taken&lt;/span&gt;&lt;span class="p"&gt;,)).&lt;/span&gt;&lt;span class="nf"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;taken&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: first run, saved &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; models. Nothing to compare yet.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/images/2026/track-new-ai-models-on-the-arena-leaderboard-body-2.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The Harness, All 70 Lines&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;srcset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; /assets/resized/480/track-new-ai-models-on-the-arena-leaderboard-body-2.jpg 480w, /assets/resized/800/track-new-ai-models-on-the-arena-leaderboard-body-2.jpg 800w, /assets/resized/1400/track-new-ai-models-on-the-arena-leaderboard-body-2.jpg 1400w, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;loading&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lazy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="n"&gt;was_top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="nf"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT model FROM ranks WHERE taken = ? AND rank &amp;lt;= ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TOP&lt;/span&gt;&lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="nf"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT DISTINCT model FROM ranks WHERE taken &amp;lt; ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;taken&lt;/span&gt;&lt;span class="p"&gt;,))}&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;taken&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; vs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;TOP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; NEW #&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;was_top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; MOVED UP #&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; __main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is what each piece is doing, mapped to the three boring things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storage: SQLite, Not a JSON File
&lt;/h3&gt;

&lt;p&gt;Every run inserts every row, all 400 or so, stamped with the time it was taken. One table, five columns.&lt;/p&gt;

&lt;p&gt;I went back and forth on JSONL here. A line of JSON per run is simpler to look at and fine for a diff against the last run. But the questions I actually care about later are history questions: how long has this model been in the top 20, when did it first appear anywhere on the board, is it climbing or sliding. With JSONL you write a loop for each of those. With SQLite you write a query. And SQLite ships with Python, so it costs nothing to install.&lt;/p&gt;

&lt;p&gt;Saving the whole board instead of just the top 20 is on purpose. Storage is cheap and you can’t go back and scrape last Tuesday. A model that debuts at #24 is not news today, but the day it cracks the top 20 you want to know it has been lurking for a week.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Diff: Two Kinds of “New”
&lt;/h3&gt;

&lt;p&gt;The script reports two different things, and the difference matters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NEW&lt;/strong&gt; means the model has never appeared anywhere on the board in any previous run. This is the one I actually wanted. A brand new model landing in the top 20 on its first appearance is the “where did that come from” moment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MOVED UP&lt;/strong&gt; means the model was on the board before but was not in the top 20 last run. A climber. Less exciting, still worth a look.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything else, a model shuffling from #7 to #9, stays quiet. The whole point of the diff is that most runs should print almost nothing.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Schedule: One Cron Line
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;0 8 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/arena-watch &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; python3 arena_watch.py &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; watch.log 2&amp;gt;&amp;amp;1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo6agqyh9lym0pb2nw2aw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo6agqyh9lym0pb2nw2aw.jpg" alt="The Schedule: One Cron Line" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Daily at 8am, appended to a log. That lives on my mini PC, which is on all the time. On a Mac you can use cron too, or launchd if you enjoy writing XML. Once a day is plenty for a leaderboard that needs thousands of votes to move a model. Each run is one scrape, which on Firecrawl is one credit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day One Has No Then
&lt;/h2&gt;

&lt;p&gt;Here is the catch with every history-based tool: the first run is useless. It saves 400 rows and prints “Nothing to compare yet.” You have to wait a day for the second run before the thing does anything at all, and a week before it does anything interesting.&lt;/p&gt;

&lt;p&gt;I didn’t want to wait a week to write this post, so I cheated with the Wayback Machine. The Internet Archive snapshots the Arena leaderboard most days, and Firecrawl will scrape an archived copy just like the live page. That is what the &lt;code&gt;--url&lt;/code&gt; and &lt;code&gt;--at&lt;/code&gt; flags are for: point the script at an old snapshot and tell it what date to record.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 arena_watch.py &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s2"&gt;"https://web.archive.org/web/20260902190730/https://arena.ai/leaderboard/text"&lt;/span&gt; &lt;span class="nt"&gt;--at&lt;/span&gt; &lt;span class="s2"&gt;"2026-09-02 19:07"&lt;/span&gt;
python3 arena_watch.py &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s2"&gt;"https://web.archive.org/web/20260909040114/https://arena.ai/leaderboard/text"&lt;/span&gt; &lt;span class="nt"&gt;--at&lt;/span&gt; &lt;span class="s2"&gt;"2026-09-09 04:01"&lt;/span&gt;
python3 arena_watch.py &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s2"&gt;"https://web.archive.org/web/20260917153328/https://arena.ai/leaderboard/text"&lt;/span&gt; &lt;span class="nt"&gt;--at&lt;/span&gt; &lt;span class="s2"&gt;"2026-09-17 15:33"&lt;/span&gt;
python3 arena_watch.py

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The archived pages parse the same as the live one, since the table structure is identical and only the link URLs change. Three weeks of history in four commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-09-02 19:07: first run, saved 399 models. Nothing to compare yet.
2026-09-09 04:01 vs 2026-09-02 19:07
  NEW #3 claude-fable-5.1-max (Anthropic, 1504)
2026-09-17 15:33 vs 2026-09-09 04:01
  NEW #8 muse-spark-1.3-max (Meta, 1493)
2026-09-23 01:27 vs 2026-09-17 15:33
  NEW #1 claude-fable-5-high (Anthropic, 1506)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fable 5.1 Max debuting at #3 and Meta’s Muse Spark 1.3 Max at #8 are exactly the kind of thing I wanted flagged. Midway through doing this the Internet Archive went down with a “Temporarily Offline” page, which is a nice reminder that the backfill trick is a trick and not infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two Things It Got Wrong
&lt;/h2&gt;

&lt;h3&gt;
  
  
  That “NEW #1” Is a Rename
&lt;/h3&gt;

&lt;p&gt;Look at the last line again. &lt;code&gt;claude-fable-5-high&lt;/code&gt; at #1 as a brand new model. It is not. The database says so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;sqlite3&lt;/span&gt; &lt;span class="n"&gt;arena&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="nv"&gt;"SELECT model, taken, rank, score FROM ranks WHERE model LIKE 'claude-fable-5%' ORDER BY model, taken;"&lt;/span&gt;


&lt;span class="n"&gt;claude&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fable&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;1508&lt;/span&gt;
&lt;span class="n"&gt;claude&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fable&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt; &lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;1507&lt;/span&gt;
&lt;span class="n"&gt;claude&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fable&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;1506&lt;/span&gt;
&lt;span class="n"&gt;claude&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fable&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt; &lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;1506&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same rank, same score, new name. This is the most common way change detection lies to you, and it is not a Firecrawl problem or a SQLite problem. It is an identity problem: the thing you are tracking needs a stable key, and the page does not give you one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh979zapmqzn4qdu9h41j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh979zapmqzn4qdu9h41j.jpg" alt="That" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The cheap fix is a sanity check before calling anything NEW: if an unseen name sits at the exact rank and score of a name that just disappeared, call it a rename. I left it out of the script because 70 lines that lie once a month teach more than 90 lines that hide it. Your mileage may vary once it wakes you up at 8am about a model that is three months old.&lt;/p&gt;

&lt;h3&gt;
  
  
  It Missed the One That Started This
&lt;/h3&gt;

&lt;p&gt;GLM 5.3 Max, the model that made me want this in the first place, never shows up as NEW. It was already sitting at #18 on September 2, the oldest snapshot I loaded, so as far as the database knows it has always been there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-09-02 19:07|18|1482
2026-09-09 04:01|20|1482
2026-09-17 15:33|19|1483
2026-09-23 01:27|19|1483

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The harness can only see changes that happen after it starts watching. You can’t get the then after the fact. Start the cron before you need it.&lt;/p&gt;

&lt;p&gt;Also notice GLM wobbling from #18 to #20 to #19 while its score barely moves. Arena ranks a lot of models within a few points of each other near the top, and a model right on the #20 line will flicker in and out. Had it dropped to #21 for one run, the next run would have called it MOVED UP. If that gets noisy, the fix is to compare against the top 20 from any of the last few runs instead of just the last one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Not Just Use Firecrawl’s Change Tracking?
&lt;/h2&gt;

&lt;p&gt;Fair question, since Firecrawl has a &lt;code&gt;changeTracking&lt;/code&gt; format and a whole Monitor product built around scheduled checks. I didn’t use either here, and the reason is the leaderboard itself: the vote counts on every row change constantly, so “did this page change” is always yes. What I want to know is not whether the page changed but what changed in one column of one table, compared against a history I can query.&lt;/p&gt;

&lt;p&gt;That is not a knock on those features. For a page that should be static, a pricing page or a terms of service, “tell me when this changes” is exactly the right tool. They are worth their own post. This is the case where you want your own history, because the question you ask of it next month is not one you know yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Is For
&lt;/h2&gt;

&lt;p&gt;As a standalone tool this is a small convenience. I will run it next to the Model Buzz Report and it will save me the “wait, was that there last week” squint.&lt;/p&gt;

&lt;p&gt;The reason it is the first real recipe in this series is the shape. Scrape, save with a timestamp, compare with the last run, speak only when something changed. Every recipe coming after this one is that shape pointed at a different page with a different question: price history instead of rank history, a job board instead of a leaderboard. Firecrawl handles getting the page. These 70 lines handle remembering it.&lt;/p&gt;

&lt;p&gt;And the database is already there, filling up once a day, waiting for whatever question I think of next.&lt;/p&gt;

</description>
      <category>arena</category>
      <category>firecrawl</category>
    </item>
  </channel>
</rss>
