home / simonwillisonblog

Menu
  • GraphQL API
  • Search all tables

simonwillisonblog

Custom SQL query returning 5 rows (hide)

This data as json, CSV

idtitleslugbodycreatedmetadatatweet_htmlimport_refextra_head_htmlcard_imagecustom_templateseries_idis_draftlive_timezonereplacement_blogmark_idreplacement_note_idpoll_live_updates
9535 Hello Python 3.15, goodbye 3.10, and now I can use 3.11 python-3-15 <p>Python 3.15 <a href="https://www.python.org/downloads/release/python-3150/">is here</a>! Here's the essential <a href="https://docs.python.org/3.15/whatsnew/3.15.html">What's new in Python 3.15</a> guide, this year curated by 3.14 and 3.15 release manager Hugo van Kemenade. As someone who builds open source software that works in every supported Python version, I get to say goodbye to Python 3.10 and start embracing features from Python 3.11.</p> <p>First, some highlights from Python 3.15.</p> <h4 id="explicit-lazy-imports">Explicit lazy imports</h4> <p>I'm most excited about <a href="https://docs.python.org/3.15/whatsnew/3.15.html#pep-810-explicit-lazy-imports">Explicit lazy imports</a> from <a href="https://peps.python.org/pep-0810/">PEP 810</a>. These let you import modules like so:</p> <pre><span class="pl-s1">lazy</span> <span class="pl-k">import</span> <span class="pl-s1">json</span> <span class="pl-s1">lazy</span> <span class="pl-k">from</span> <span class="pl-s1">pathlib</span> <span class="pl-k">import</span> <span class="pl-v">Path</span></pre> <p>The module will then be imported the first time those symbols are used in the code that follows.</p> <p>My <a href="https://llm.datasette.io/">LLM</a> CLI tool implements plugins. I had to <a href="https://llm.datasette.io/en/stable/plugins/advanced-model-plugins.html#tip-lazily-load-expensive-dependencies">recommend manual lazy imports</a> in the plugin author documentation, because simply installing plugins that used heavy dependencies such as <code>sentence_transformers</code> could add multiple seconds to every invocation of the <code>llm</code> command. Lazy imports directly address this startup cost.</p> <h4 id="unpacking-in-comprehensions">Unpacking in comprehensions</h4> <p>The new <code>[*sublist for sublist in lists]</code> unpacking syntax is neat. Here's an illustration <a href="https://docs.python.org/3.15/whatsnew/3.15.html#pep-798-unpacking-in-comprehensions">lifted from the documentation</a>:</p> <pre><span class="pl-s1">lists</span> <span class="pl-c1">=</span> [[<span class="pl-c1">1</span>, <span class="pl-c1">2</span>], [<span class="pl-c1">3</span>, <span class="pl-c1">4</span>], [<span class="pl-c1">5</span>]] [<span class="pl-c1">*</span><span class="pl-c1">L</span> <span class="pl-k">for</span> <span class="pl-c1">L</span> <span class="pl-c1">in</span> <span class="pl-s1">lists</span>] <span class="pl-c"># [1, 2, 3, 4, 5]</span> <span class="pl-c"># equivalent to [x for L in lists for x in L]</span> <span class="pl-s1">sets</span> <span class="pl-c1">=</span> [{<span class="pl-c1">1</span>, <span class="pl-c1">2</span>}, {<span class="pl-c1">2</span>, <span class="pl-c1">3</span>}, {<span class="pl-c1">3</span>, <span class="pl-c1">4</span>}] {<span class="pl-c1">*</span><span class="pl-s1">s</span> <span class="pl-k">for</span> <span class="pl-s1">s</span> <span class="pl-c1">in</span> <span class="pl-s1">sets</span>} <span class="pl-c"># {1, 2, 3, 4}</span> <span class="pl-c"># equivalent to {x for s in sets for x in s}</span> <span class="pl-s1">dicts</span> <span class="pl-c1">=</span> [{<span class="pl-s">'a'</span>: <span class="pl-c1">1</span>}, {<span class="pl-s">'b'</span>: <span class="pl-c1">2</span>}, {<span class="pl-s">'a'</span>: <span class="pl-c1">3</span>}] {<span class="pl-c1">**</span><span class="pl-s1">d</span> <span class="pl-s1">for</span> <span class="pl-s1">d</span> <span class="pl-c1">in</span> <span class="pl-s1">dicts</span>} <span class="pl-c"># {'a': 3, 'b': 2}</span> <span class="pl-c"># equivalent to {k: v for d in dicts for k,v in d.items()}</span></pre> <p><a href="https://peps.python.org/pep-0798/">PEP 798: Unpacking in Comprehensions</a> by Adam Hartz and Erik Demaine proposed this as an extension of the unpacking syntax <a href="https://peps.python.org/pep-0448/">from PEP 448</a>, which landed <a href="https://docs.python.org/3/whatsnew/3.5.html#pep-448-additional-unpacking-generalizations">in Python 3.5</a> back in 2015.</p> <h4 id="a-sampling-profiler">A sampling profiler</h4> <p>Python's existing tracing profiler has been renamed from <code>cProfile</code> to <a href="https://docs.python.org/3.15/library/profiling.tracing.html#module-profiling.tracing">profiling.tracing</a>, and has been joined by an exciting new sampling profiler called Tachyon, aka <a href="https://docs.python.org/3.15/whatsnew/3.15.html#tachyon-high-frequency-statistical-sampling-profiler">profiling.sampling</a>.</p> <p>Sampling profilers work by periodically capturing stack traces from running processes, then using those to calculate which functions have the most time spent inside of them. They're very low overhead and can provide a deep insight into running systems, without needing to instrument those systems first.</p> <p>I've <a href="https://simonwillison.net/tags/profiling/">previously used tools</a> like <a href="https://github.com/benfred/py-spy">py-spy</a> for this. Now this capability is baked into the standard library.</p> <p>If you have the PID of an existing Python 3.15 process you can start gathering samples by running this (I had to use <code>sudo</code> on macOS):</p> <div class="highlight highlight-source-shell"><pre>sudo uv run --python 3.15 python -m profiling.sampling attach 1234</pre></div> <p>Interact with the main program a bit, then hit Ctrl+C to stop gathering and see a report, which looks something like this:</p> <p><img src="https://static.simonwillison.net/static/2026/profiler-output.webp" alt="Screenshot of terminal output from a Python sampling profiler with colored text on a black background. Header lines report 2,651 samples captured in 2.65 seconds at a sample rate of 999.98 samples/sec with an error rate of 0.19. A Profile Stats table with columns for nsamples, sample%, tottime, cumul%, cumtime and filename:lineno(function) shows that 99.9% of samples (2.644 seconds) were spent directly in selectors.py KqueueSelector.select, meaning the process was almost entirely idle waiting on the asyncio event loop. The rest of the table lists the call stack beneath it with zero direct time but 100% cumulative presence: asyncio base_events.py run_once, run_forever and run_until_complete, runners.py Runner.run and run, cli.py serve and sqlite_extensions wrapped, and several click core.py invoke, main and call frames. A legend explains each column, followed by a Summary of Interesting Functions section listing hot spots (KqueueSelector.select at 99.9% direct samples), the most frequently present functions on the stack (run_forever, run_until_complete and Runner.run at 100%), and the highest call magnification (2645.0x for BaseEventLoop._run_once)." style="max-width: 100%;" /></p> <p>It can also produce <a href="https://simonw.github.io/research/python-3-15-web-edit-profiling/artifacts/flamegraph.html">flame graphs like this</a> and <a href="https://simonw.github.io/research/python-3-15-web-edit-profiling/artifacts/heatmap/index.html">heat maps like this</a>, and can even output a format that can be viewed in the Firefox profiler UI.</p> <h4 id="3-15-isn-t-much-faster-than-3-14">3.15 isn't much faster than 3.14</h4> <p>Miguel Grinberg investigated <a href="https://blog.miguelgrinberg.com/post/how-fast-is-python-3-15">How fast is Python 3.15?</a> the other day against the 3.15.0rc3 release and found performance to be mostly the same as 3.14, with the exception of the experimental JIT. The JIT gave a 1.2x boost over the standard 3.15 interpreter (on a Fibonacci test), the first time Miguel observed a meaningful JIT performance increase.</p> <p>Miguel's <a href="https://blog.miguelgrinberg.com/post/python-3-14-is-here-how-fast-is-it">explorations of 3.14</a> last year found significant boosts against Python 3.13 across many more categories.</p> <h4 id="upgrading-to-python-3-15-with-uv">Upgrading to Python 3.15 with uv</h4> <p>I used the following sequence of commands to get <code>uv</code> to use Python 3.15 on my Mac. First I had to upgrade <code>uv</code> itself to ensure it knew about the new release:</p> <div class="highlight highlight-source-shell"><pre>uv self update</pre></div> <p>Then I installed the stable 3.15 release:</p> <div class="highlight highlight-source-shell"><pre>uv python install 3.15</pre></div> <p>And told <code>uv</code> that I wanted that to be the default for every <code>uv run</code> command, unless the project itself pinned a different version:</p> <div class="highlight highlight-source-shell"><pre>uv python pin --global 3.15</pre></div> <p>Now the following reports 3.15 as the version:</p> <div class="highlight highlight-source-shell"><pre>uv run python --version</pre></div> <p>I already have a bunch of tools installed using <code>uv tool install</code>. I reinstalled them to use Python 3.15 like this:</p> <div class="highlight highlight-source-shell"><pre>uv tool upgrade datasette --python 3.15</pre></div> <p>Then I can confirm the version like this:</p> <div class="highlight highlight-source-shell"><pre>datasette --get /-/versions.json <span class="pl-k">|</span> jq</pre></div> <h4 id="highlights-from-python-3-11">Highlights from Python 3.11</h4> <p>The release of 3.15 means that Python 3.10 (released in 2021) is officially <a href="https://devguide.python.org/versions/">no longer supported</a>.</p> <p>My policy for my main open source projects is to keep them working in every supported Python version. I can now drop 3.10 and start using features that were introduced in 3.11.</p> <p>Here's the <a href="https://docs.python.org/3/whatsnew/3.11.html">What's new in Python 3.11</a> document. I finally get to rely on <a href="https://docs.python.org/3/library/tomllib.html#module-tomllib">tomllib</a> being available!</p> <p>Datasette makes extensive use of <code>asyncio</code>. 3.11 adds <a href="https://docs.python.org/3/library/asyncio-task.html#asyncio.TaskGroup">TaskGroup</a> and <a href="https://docs.python.org/3/library… 2026-10-12T18:15:38+00:00 {}       https://static.simonwillison.net/static/2026/profiler-output.webp     0       0
9508 A new feature for my blog, built using my voice built-using-my-voice <p>I shipped a new feature for my blog today: the <a href="https://simonwillison.net/newsletters/">Newsletters</a> page, which offers an index of all of the newsletters I've sent out, both my free <a href="https://simonw.substack.com/">weekly Substack</a> and my <a href="https://github.com/sponsors/simonw/">monthly sponsors-only</a> updates. I built the feature almost entirely using my voice, chatting away to my laptop while I cooked dinner.</p> <h4 id="codex-voice-mode">Codex voice mode</h4> <p>I used the ChatGPT desktop app for this, in the Codex tab, using the voice conversation mode, running against a local development environment. Here's what that looks like:</p> <p><img src="https://static.simonwillison.net/static/2026/codex-voice.webp" alt="Three columns of the ChatGPT app. The left hand column shows my recent conversations. The middle column is a transcript of the conversation, with a throbbing black blob representing voice mode. The right hand column shows a local dev server version of my blog, with the Newsletters page visible." style="max-width: 100%;" /></p> <p>I started the session against my local <a href="https://github.com/simonw/simonwillisonblog">simonwillisonblog</a> checkout by typing:</p> <blockquote> <p><code>Start dev server and open in browser</code></p> </blockquote> <p>This gave me a preview of the site that it would be working on, and meant that I could later ask it to show me the new pages so I could visually track its progress.</p> <p>Then I clicked the "Start new voice chat" button - that's <em>not</em> the microphone button, it's the one to the right of it - and set my laptop up in the kitchen so I could talk to it while I cooked.</p> <h4 id="talking-to-my-computer">Talking to my computer</h4> <p>I had a pretty good idea of what I wanted to build, and it's a simple enough Django feature that I was certain the model (in this case GPT-6 Astra High) would be able to do it. A new model, a migration, some view code, templates, and a couple of import functions to populate the database from external sources.</p> <p>Here's an extract of my voice transcript that was captured by Codex:</p> <blockquote> <p>Um, they do not. Um, this is going to be a new type of content. Um, it's not going to show up... Oh, hold on. Yeah, no- I do not want this to show up in my, um, tag pages and date archive pages and... Actually, no, I think... I don't want it on the tag pages. I don't want it on the, um, blog index page. But I think I do want it to show up on the date-based pages. You know, if you navigate to September the 19th, and I sent a newsletter on that page, I think I want that to show up. So... this is- so I think we probably need a new model. The other thing is that I want them searchable, uh the Substack ones are not searchable, because those are actually just copies of other s- on content on my blog. These monthly ones do contain unique content, and spe- and once they're... published, like once they're made public a month after they've gone out, I want them to show up on my search results.</p> </blockquote> <p>Apparently this was clear enough that the model knew what I wanted to build! You can read the full transcript, <a href="https://en.wikipedia.org/wiki/Speech_disfluency">disfluencies</a> and all, <a href="https://gist.github.com/simonw/a65a22204f6f7228cc59b4bc34d7c7c8">in this Gist</a>.</p> <p>We went on like this for about half an hour (the time it took to cook dinner). The model would reply and occasionally ask clarifying questions, then get to work modifying the code.</p> <h4 id="what-we-built">What we built</h4> <p>We got a surprisingly long way entirely by voice:</p> <ul> <li>A new model and migration to represent imported newsletters in Django, plus Django Admin configuration for that</li> <li>Four working imports: <ul> <li>The most recent Substack items via RSS</li> <li>Every other Substack item via their undocumented API, which GPT-6 Astra knew about (it tried <code>/api/v1/archive</code> directly) and then ran a search to figure out how to paginate it and found <a href="https://wonderingaboutai.substack.com/p/i-connected-my-newsletter-archive">this article</a> by Karen Spinner</li> <li>All of my published monthly newsletters from my <a href="https://github.com/simonw/monthly-newsletter-archive">simonw/monthly-newsletter-archive</a> GitHub repository</li> <li>My most recent private sponsors-only newsletter from a private repository</li> </ul> </li> <li>The <a href="https://simonwillison.net/newsletters/">/newsletters/</a> and <a href="https://simonwillison.net/newsletters/2026/">/newsletters/2026/</a> public archive pages</li> <li>Newsletters showing up on day and month archive pages too, but not on tag pages or my homepage</li> <li>Weekly Substack newsletters link to Substack; archived monthly newsletters have their own pages</li> <li>Integration with my site search engine</li> </ul> <p>It was <em>almost</em> ready to ship. The catch was the imports: Astra offered to export data from my local copy so I could import that into production, but I wanted it to work like my other import scripts. Since some of the data lived in a private GitHub repository, this would involve creating a new API key, and for that I knew I'd have to sit at the keyboard for a while.</p> <h4 id="finishing-it-with-a-review">Finishing it with a review</h4> <p>Once I had finished cooking and judged it mostly feature-complete, I had Codex create a branch and open a pull request.</p> <p>I reviewed the code in the GitHub PR interface. It was nearly what I needed, except it had chosen to use Git in a subprocess for one of the import scripts. I needed one of the imports to pull from a private Git repository, so I figured the API would be a better bet. I switched to typing and had Codex swap that out for an API-based import instead.</p> <p>You can see the changes I made during the review <a href="https://github.com/simonw/simonwillisonblog/pull/719">in the extra commits on the PR</a>. I fixed the import mechanism and made a few tweaks to the display of those public pages. It took an additional half hour of typing-based prompting to get to the point where I was happy to deploy it to production by landing the PR.</p> <h4 id="the-end-result">The end result</h4> <p>You can see the end result at the new <a href="https://simonwillison.net/newsletters/">newsletters index page</a>, or view the <a href="https://simonwillison.net/newsletters/monthly-2026-08-august/">page for a previous monthly newsletter</a>.</p> <p><img src="https://static.simonwillison.net/static/2026/newsletters-page.webp" alt="Newsletters page. It shows two Substack posts (with thumbnails) and one LLM digest Sponsors-only newsletter with a list of headings. On the right is a CTA to subscribe to my Substack and another one for my $10/month monthly briefing newsletter." style="max-width: 100%;" /></p> <p>The index page shows my most recent Substack weekly newsletters and GitHub sponsors monthly newsletters mixed together in reverse chronological order. Further down the page are links to my by-year archive pages.</p> <p>GPT-6 Astra designed the page, and then tweaked that design based on my vocal feedback from glancing at the local preview across the kitchen.</p> <h4 id="better-for-multi-tasking-than-as-a-daily-driver">Better for multi-tasking than as a daily driver</h4> <p>OpenAI <em>love</em> using voice-driven demos like this one for <a href="https://simonwillison.net/2026/Sep/29/openai-devday-2026-live-blog/#live-update-504">things like DevDay</a> - and they do work well in that environment. I don't think this is going to be a daily driver for me though.</p> <p>I've <a href="https://simonwillison.net/search/?q=walking+dog">written before</a> about how much "work" I get done using ChatGPT voice mode on my phone while walking the dog - mostly research and brainstorming, but occasionally actual development work by having ChatGPT write and test out snippets of code.</p> <p>This feels different. The addition of the visual preview, plus being able to type or paste things in via the keyboard when I need to communicate something that doesn't work vocally, makes this a much more powerful way of interacting with a coding agent.</p> <p>I still switch back to typing once I get down to the details of things though. Being able to paste in examples and error messages, or directly highlight the code or feature that needs changing, remains more efficient than trying to describe it in words.</p> <p>I mainly work from home, which is good because there's no way I'd want to talk to my computer like this in a shared workspace!</p> <p>The killer feature for me is the ability to multi-task. I usually cook with a podcast or TikTok running; now I can actually build stuff instead.</p> 2026-10-09T12:54:06+00:00 {}       https://static.simonwillison.net/static/2026/newsletters-card.webp   12 0       0
9507 Claude Haiku 5.5 claude-haiku-5-5 <p>As previously <a href="https://simonwillison.net/2026/Sep/28/claude-sonnet-5-5/">promised</a>, here's Anthropic's new fast, low cost model: <a href="https://www.anthropic.com/claude-haiku-5-5">Introducing Claude Haiku 5.5</a>.</p> <p>The previous Haiku, 4.5, was very much showing its age. It came out <a href="https://simonwillison.net/2025/Oct/15/claude-haiku-45/">almost a year ago</a>, and was priced at $1/million input and $5/million output - relatively expensive even back then, and a full 10x the price of OpenAI's <a href="https://simonwillison.net/2026/Sep/22/opus-and-sol-and-luna/#gpt-6-sol-and-luna-are-half-the-price-of-their-gpt-5-6-equivalents">GPT-6 Luna</a>, released last month.</p> <p>The new Haiku exactly matches the price of GPT-6 Luna - $0.10/$0.50 - up to 100,000 tokens. Beyond 100,000 tokens the price increases 5x to $0.50/$2.50. Luna itself has a price increase at 272,000 tokens but only to $0.20/$0.75.</p> <p>Haiku 5.5 also uses a new, less generous tokenizer. My <a href="https://tools.simonwillison.net/claude-token-counter">Claude Token Counter</a> tool shows that the same long prompt uses around 1.25x as many tokens with Haiku 5.5 compared to Haiku 4.5, so there's a hidden price increase there.</p> <p>If your workloads fit in 100,000 tokens, Haiku is the same price as Luna and reports higher benchmark scores. Above 100,000 tokens, Luna looks like a much better deal.</p> <p>The <a href="https://github.com/simonw/llm-anthropic/releases/tag/0.30">most recent release of llm-anthropic</a> finally fixed it so I don't need to ship a new version of that plugin for every new model. I tested the new model like this:</p> <pre><code>llm install -U llm-anthropic llm anthropic refresh llm -m claude-haiku-5.5 "Generate an SVG of a pelican riding a bicycle" -o thinking_effort low </code></pre> <h4 id="pelicans">Pelicans</h4> <p>Here are <a href="https://tools.simonwillison.net/markdown-svg-renderer?url=https%3A%2F%2Fgist.github.com%2Fsimonw%2F485dfa24b4efa1267ee2d0911594fb81">pelicans for low, medium, high, xhigh, and max</a>. The new Haiku doesn't let you disable reasoning, and defaults to <code>medium</code>. I got a good bicycle frame for everything beyond <code>low</code>. The <a href="https://tools.simonwillison.net/markdown-svg-renderer?url=https%3A%2F%2Fgist.github.com%2Fsimonw%2F485dfa24b4efa1267ee2d0911594fb81#response">low effort pelican</a> cost 0.0936 cents and took 7 seconds.</p><p>This <code>max</code> effort pelican (with <a href="https://tools.simonwillison.net/markdown-svg-renderer?url=https%3A%2F%2Fgist.github.com%2Fsimonw%2F485dfa24b4efa1267ee2d0911594fb81#reasoning-3">a reasoning trace</a> that starts "This is the classic pelican-on-bicycle SVG test...") took 5 minutes 9 seconds to generate, but still only cost me <a href="https://www.llm-prices.com/#it=27&amp;ot=67647&amp;sel=claude-haiku-5.5">3.3826 cents</a>:</p> <p><img alt="Flat vector illustration: a white pelican wearing a red cap rides a dark grey bicycle from left to right across a green grassy strip, its long orange legs reaching down to the orange pedals, a grey wing stretched forward to grip the curved handlebars, and its large yellow-orange beak with a bulging orange throat pouch pointing ahead; behind it, white speed lines show motion, and above, a yellow sun with a pale halo and two white clouds sit in a gradient blue sky." src="https://static.simonwillison.net/static/2026-10-07/haiku-5.5-max.webp" /></p> <p><small>(Since the reasoning trace exhibits awareness of the benchmark, here's <a href="https://tools.simonwillison.net/markdown-svg-renderer?url=https%3A%2F%2Fgist.github.com%2Fsimonw%2F375ae4f2bb68999976b8da50548c788d#response">Generate an SVG of an armadillo in fishnet tights jaywalking on Mars (on xhigh)</a>, and the same prompt against <a href="https://tools.simonwillison.net/markdown-svg-renderer?url=https%3A%2F%2Fgist.github.com%2Fsimonw%2F18c9f7fc3b3705cf88514cb9170ec246">some other recent models</a>. <a href="https://news.ycombinator.com/item?id=49977979#49982139">Background on that</a>.)</small></p> <p>For comparison, here's the pelican I got <a href="https://simonwillison.net/2025/Oct/15/claude-haiku-45/">a year ago</a> from Haiku 4.5 (for <a href="https://www.llm-prices.com/#it=18&amp;ot=1513&amp;ic=1&amp;oc=5">0.7583 cents</a> - Haiku 4.5 did not support reasoning levels). It <em>sucked</em> at drawing pelicans:</p> <img src="https://static.simonwillison.net/static/2025/claude-haiku-4.5-pelican.jpg" alt="Described by Haiku 4.5: A whimsical illustration of a bird with a round tan body, pink beak, and orange legs riding a bicycle against a blue sky and green grass background." style="width: 60%; margin: 1em auto; display: block;" /> <h4 id="api-credits">And a generous API credit scheme for subscribers</h4> <p>In addition to Haiku 5.5, Anthropic announced today that they are halving the price of cache reads for Sonnet 5.5. They've also added API credits to subscription plans:</p> <blockquote> <p>Second, this week, we’ll roll out <strong>a new monthly API credit to all Max and Team subscribers for use on the Claude Platform</strong>. Max 5x users will get $100 in credits per month, Max 20x users will get $200, and Team subscribers will receive up to $500, pooled across their users.</p> </blockquote> <p>Claiming this is pleasantly easy: navigate to <a href="https://claude.ai/new#settings/billing">Settings -&gt; Billing</a> and select the API organization that should benefit from the credits every month:</p> <p><img alt="Screenshot of a Settings dialog with a close X button at top right and a row of tabs reading &quot;General&quot;, &quot;Account&quot;, &quot;Privacy&quot;, &quot;Billing&quot; (selected), &quot;Usage&quot;, &quot;Capabilities&quot;, &quot;Memory&quot; and &quot;Design sys&quot; (cut off at the edge). Beside a line-drawn icon of a branching plant with circular buds, the panel reads &quot;Max plan&quot;, &quot;20x more usage than Pro&quot; and &quot;Your subscription will auto renew on Nov 2, 2026.&quot; with an &quot;Adjust plan&quot; button on the right. Below is a section headed &quot;API credits&quot; with a blue &quot;New&quot; badge, reading &quot;Your Max 20x plan includes $200 USD in API credits each month.&quot; followed by grey text &quot;Link an API organization to start receiving credits.&quot; with a &quot;Link organization&quot; button on the right." src="https://static.simonwillison.net/static/2026-10-07/claude-credits.webp" /></p> <p>The API credits exactly match the cost of the subscription itself. This is really generous - it makes it much easier for subscribers to use the API. Anthropic also let you disable auto-reload for the API, with the consequence that "API requests will stop when your balance runs out" - exactly what you want if you're planning to burn through those API credits without <a href="https://simonwillison.net/2026/Oct/3/default-hard-budget-caps/">risk of a nasty billing surprise</a>.</p> <p>Note that the monthly credits <a href="https://support.claude.com/en/articles/17154008-monthly-api-credits-for-max-and-team-plans#h_dfc1659cee">do not roll over</a> - use them or lose them.</p> <p>OpenAI still allow you to use your Codex subscription for personal API use, which works out as a better deal for heavy API users. This new credit scheme goes at least some way to overcoming that difference.</p> 2026-10-07T20:56:21+00:00 {}       https://static.simonwillison.net/static/2026/claude-haiku-5-5-card.webp     0       0
9506 We're going to need default hard budget caps on pretty much everything default-hard-budget-caps <p>Here's a product feature which the world is going to need a whole lot more of over the coming months and years: <strong>default hard budget caps</strong>. I'm talking about the feature of pay-by-usage services and APIs that lets you say "after $X/month, cut this thing off and return errors". These need to be <strong>hard</strong> limits. Soft caps, "after $X/month, send me a warning email", will not cut it.</p> <p>Coding agents, and personal agents (coding agents wrapped in a less threatening UI), greatly reduce the friction of spinning up code that can do useful things. Sometimes those things cost money - calls to paid APIs, or hosted web applications, or systems that can bill for additional storage and compute.</p> <p>Nobody wants to wake up to an email sent at midnight warning about a budget limit and find that, while they slept, their rogue service had consumed several hundred (or several thousand) more dollars of usage.</p> <p>An argument against this is that businesses don't want their hosted applications to start throwing errors because some budget was exceeded. I expect that most businesses and individuals would prefer errors to a surprise $10,000+ bill.</p> <p>I think hard budget caps need to be the default. If someone wants to live dangerously they should be able to do that, but it needs to be on an opt-in basis. Have a nice, clear checkbox somewhere prominent:</p> <blockquote> <p><input type="checkbox" disabled="disabled" /> Remove the budget cap. My application will not be shut down if I exceed the configured budget limit, and I will be responsible for subsequent charges.</p> </blockquote> <p>The service I most want to see this from is AWS. I've heard plenty of stories from people who refuse to use AWS for personal projects out of (justified) fear that a runaway service might bankrupt them. I've also heard stories from people who <em>didn't</em> anticipate this and ended up seriously burned.</p> <p>... and it turns out AWS finally launched spending limits a few weeks ago! From their announcement <a href="https://aws.amazon.com/about-aws/whats-new/2026/09/New-AWS-Builder-Experience/">New AWS experience helps builders get started and ship faster</a> on 16th September:</p> <blockquote> <p>When you're ready to upgrade to a paid plan, you can set a monthly spend limit for your project based on your usage patterns so that you stay within your budget. If a project's usage reaches its spend limit, your project is paused for that month.</p> </blockquote> <p>See also <a href="https://docs.aws.amazon.com/accounts/latest/reference/create-spend-limit.html">Create a spend limit in AWS Settings</a>, though that page warns that "We're currently releasing our new experience to a limited number of customers." Here's hoping that hits general availability for existing accounts soon.</p> <p>Google Cloud <a href="https://cloud.google.com/blog/topics/cost-management/new-early-anomalies-and-spend-caps-on-google-cloud-budgets">launched a similar feature</a> in July, called Spend Caps, which lets you "set a monthly financial cap on specific services within a project". Looks like this is becoming a trend!</p> <p>In an ideal world, our agents could help with this. It would be great if agents started biasing towards recommending providers with hard budget caps, and warning new and inexperienced builders against deploying applications using uncapped services that might get them into trouble.</p> 2026-10-03T23:34:02+00:00 {}             0       0
9505 OpenAI DevDay 2026 live blog openai-devday-2026-live-blog <p>I'm at <a href="https://devday.openai.com/">OpenAI DevDay</a> today, in Fort Mason, San Francisco. Same as <a href="https://simonwillison.net/2025/Oct/6/openai-devday-live-blog/">last year</a> I'll be live blogging the keynote and some other notes during the day.</p> <p><em>OpenAI gave me a free ticket and a seat in the "creator" area for the keynote.</em></p> 2026-09-29T15:55:13+00:00 {}     <style> div[data-update-id] img { margin-top: 1em } </style> https://static.simonwillison.net/static/2026/live-20260929-092441.webp     0       0
Powered by Datasette