Battle Drones - a vibe coded RTS with audio-based multiplayer
In this newsletter:
Battle Drones - a vibe coded RTS with audio-based multiplayer
Plus 6 links, 2 quotations, 7 releases, 1 research report, and 3 tools
Thanks for reading Simon Willison’s Newsletter! Subscribe for free to receive new posts and support my work.
Sponsor message: What’s scarier than an engineer with prod access?
An AI agent with the same access. All jokes aside – agents spawn sub-agents, run a thousand sessions over lunch, and can delete prod before dessert. The old identity problems are the same, just faster and at a bigger scale. Teleport shows how ephemeral, least-privileged access keeps agents in check.
Battle Drones - a vibe coded RTS with audio-based multiplayer - 2026-10-20
My latest vibe coded game experiment is a Command & Conquer style RTS (Real Time Strategy) game called Battle Drones (play it here). Unlike my previous experiments, this one is actually fun to play. I’m somewhat embarrassed to admit that I got there by telling Claude to “Make it a LOT more fun”. It also supports multiplayer between nearby devices using audio to synchronize game state! Here’s what I’ve built so far, and some of the things I learned along the way.
Battle Drones
My initial goal was to build an RTS game I could play on my phone, in the style of Command & Conquer. I have fond memories of the 1995 original (I liked Red Alert too) and wanted to recapture a little bit of the magic.
After 12 major iterations (and 321 commits by coding agents, mainly Claude Code) I now have a browser-based game that works on mobile and desktop, has multiple play modes, several maps (including a random map generator) and even supports multiplayer for two devices within microphone range of each other.
Here’s a video demo of Battle Drones running in a desktop browser:
Features so far include:
9 buildings, 7 ground vehicles, 6 aerial vehicles, 3 infantry units - all 3D models, which you can browse here
Fog of war
Different weapons are needed to target aerial or ground vehicles
Six maps, across five biomes - temperate, desert, arctic, volcanic, tropical
A random map generator
Skirmish mode - red vs. blue on a rotationally symmetrical map
Last Stand mode - one player holds out against as many waves of enemies as possible
Area effect weapons: Barrage, EMP, Drop Pod, Sky Hammer
Crate drops with bonus resources
In-game music that responds to events - it gets more intense as fighting breaks out
Different in-game AI personalities (Balanced, Rush, Air Swarm, Boom, Skyforce, Ironclad)
AI vs. AI mode, to watch those personalities play each other
The Goliath - a giant stomping mech with laser eyes and arm cannons and the ability to establish a new base
Mutators that add extra rules or twists
A “Daily Op” challenge
Ranks and achievements (Medals)
Agent vs. Agent mode where two LLMs can play Battle Drones against each other
A multiplayer mode based on two nearby phones communicating via audio messages, an extension of my earlier experiment with Chirp Pong
How I built this
Battle Drones is heavily vibe coded - I’ve reviewed almost none of the code, and it’s built in a language (TypeScript) that I’ve hardly used myself. I’ve playtested it quite a bit though, and it’s been through a large number of iterations since I started the project.
Here’s a rough history of the project so far, including key prompts and links to transcripts.
v1: the initial prototype
I started out with Claude Fable 5 back in July:
We are going to build a mobile friendly RTS game - command and conquer style - called Battle Drones, in which two armies of drones (both flying and ground-based) battle for territory and resources
Let's start with a MVP design, ask me some questions
Here’s a shared transcript. I’d given Claude Code for Web an environment variable with an OpenAI API key and told it to use the OpenAI Image Generation API for assets, which got me some basic sprites.
You can try v1 here - it looked like this:
It’s recognizable as an RTS, has building mechanics and the ability to select and direct units, and a basic AI to play against.
This first version was barely a proof of concept, and it wasn’t any fun to play.
Claude used the Phaser 2D game framework for these early versions. I didn’t even realize this until several iterations later!
v2: full sprites
The second version (try v2 here) added sprites for all of the vehicles and the “AI vs. AI” mode, so I could watch the game playing without having to directly control it myself.
Claude proved reasonably competent at prompting OpenAI’s image models to generate sprites. You can browse the v2 sprites in the public/assets/sprites folder.
v3: varied terrain
It still wasn’t much fun, and the graphics were boring. It was now October, and I had upgraded to Claude Opus 5.5. I told it:
Massively improve this game. Make the graphics and gameplay better (keep it mobile friendly). Render new graphics using the latest OpenAI GPT image API (lookup details) with the API key in the environment variable. Add new unit types and balance the gameplay better. Also add new buildings and better, more varied terrain.
This resulted in five new maps with generated background tiles in a variety of styles, visible here. Opus also regenerated the sprites, making them much more visually appealing. You can try v3 here - it looks like this:
This is starting to feel like a real game! It still wasn’t very fun to play though - I found myself getting bored pretty quickly.
v4: the fun update
So far my Battle Drones experiment was confirming my previous belief that coding agents can build a thing that looks like a game but can’t actually make something that’s genuinely compelling to play.
I shared this theory with someone over dinner, and then thought to myself that I should give the models a proper chance to prove me wrong. I prompted Opus 5.5 on my phone:
This game isn't fun enough yet. Make it a LOT more fun.
This time I was running in Ultracode mode, where Claude Code (in this case Claude Code for Web) runs “dynamic workflows”, described in their docs as:
A dynamic workflow is a JavaScript script that orchestrates many subagents at once.
This kicked off many hours of work. I started it in the evening and didn’t get a playable result back until late into the next morning. But the results were spectacular.
You can try v4 here - it looks like this:
I had Claude write its own release notes - here are the highlights:
Every skirmish and Daily Op now opens with a choice, gives the side that’s losing a way back, and pulls the armies into the middle of the map. There are also two new ways to play.
Openers: pick Blitz, Industry or Air Wing before the clock starts.
Call-down powers: Barrage, EMP, Drop Pod and the Sky Hammer orbital strike.
Objectives and salvage: Uplink relays, supply drops and wrecks worth scrap.
Feel: combat juice, adaptive music, unit voices and an announcer.
Command: battle alerts, game speed, saved squads and touch placement.
New modes: Last Stand survival waves and an 8-mission Ops campaign.
Progression: heroes, an after-action report with awards, a career, 7 mutators and a Daily Op.
Fights run longer and swing more. In 1,200 AI-vs-AI test matches on Normal, games still undecided after 25 minutes fell from 14% to 0.9%. The share of wins by a side that had been 800+ scrap behind rose from 24% to 46%.
Part of the reason Claude took so long was that it ran over a thousand simulated playtest sessions, and used the results to rebalance the existing units, add new ones, and introduce new features.
v5: Battle Drones goes 3D
After the success of Ultracode at “Make it a LOT more fun”, I decided to be more ambitious:
Port this game to three.js with 3D models for all of the buildings and vehicles and landscapes
That was another overnight run. I woke up to this v5 version:
The new 3D models were entirely constructed by Claude in TypeScript code.
v6 (play v6 here) added some more visual polish. v7 (play v7) added robot infantry (troopers, rocket squads, snipers) and a “Condor” troop carrying aircraft.
v8: Archipelago
I was beginning to feel guilty at how little actual design input I had into the game - it really had been a case of me saying “make it more fun” and “add visual polish” for the past few releases.
I’d noticed that the AI didn’t use the new infantry and troop carrying aircraft from v7 very often - there wasn’t a great strategic reason to use them.
It would be neat if we had a new map with a new game mechanic that actively encouraged players to load up Condors with infantry robots and send them out into the map.
This resulted in my longest prompt yet:
Design a new map. Goal is to make different strategic incentives that encourage use of Infantry and Condors and aerial vehicles.
To do this the map will have limited harvester resources but several more uplinks - but uplinks will be on islands that are inaccessible by land vehicles or infantry. These uplinks can also not be claimed using air vehicles. The ONLY way to get them is to fly infantry there in a Condor.
Armies always start with a Condor and a single squad. If an army has no Condor a new one will be provided for free, flying in from the edge closest to their HQ and landing there. That free condor will come with a single free squad on board.
The two HQs should be entirely separated by water, but still accessible by vehicles thanks to two bridges across the map in different places
I want to encourage a battle over uplinks.
The map should be the times the size of other maps - still square
First research and then critique this design. Only build after we have agreed on any modifications
You get to design a new biome for this
The result was the tropical Archipelago map, with seven island uplinks that players can only capture by flying out infantry in a Condor. It’s definitely the most fun map to play, once you’ve got the hang of the basic game mechanics from the simpler maps. The v9 edition made that map a little more interesting - it now looks like this:
v10: Goliath, and agent battles
I decided to add giant robot mechs to the game - think Jaegers from Pacific Rim, or Titans from Warhammer 40,000.
Here are some of the prompts I used to brainstorm with Claude:
Help me brainstorm ideas for adding giant robots to this game - think dreadnoughts or titans from W20K - how could we do this in a way that enhanced gameplay, kept things balanced, added unique twist? Don't overthink this yet
Let's keep brainstorming. I like the idea that it's a mobile base - that can accept harvested scrap and can have buildings built near it (even if it later moves on) and can produce infantry units too. An interaction with condor would be neat but I don't know what that could be.
Idea: as it gets damage it loses the ability to fire some weapons - by default it has eye laser (like lancers) and arm canons (like titan) and two shoulder mounted mortars, plus machine guns similar to a squad of troops
Damage knocks out mortars and then laser - it always has guns. You can't build next to a building that was only put there because of the mech, you need the mech there for off-base building and only within three squares of it
[...] Lets do two condors can carry the mech
The end result is really cool.
Goliaths can be constructed using a Gantry - a building that can only be created after first building a Fab, Bay, Airpad, and Tech Lab. You can see the Goliath under construction, and it then walks out from the Gantry and can march around the map.
Goliaths can “anchor”, which digs them into the ground. In their anchored state they can act as a new HQ, constructing infantry units and additional buildings in a new area.
Two Condor aircraft can hook onto a Goliath, at which point it can be flown around the map!
The game now ends when you destroy the enemy’s HQ building and any Goliaths they might have built.
There are also a couple of mutators relating to Goliaths:
Goliath Armada starts each side with four airborne Goliaths (each with a pair of Condors) and no other units.
Robot Love adds a special rule: if enemy Goliaths get close to each other on the battlefield they fall in love and the game ends in a draw. (Thank Natalie for that one).
Agent battles
The other v10 feature is agent battles. In musing about how multiplayer could work I had an idea: what if different LLMs could fight it out in the game?
Fun extra challenge: think about how we might make multiplayer available to coding agents. It would be neat if we could set up a battle between eg GPT-6 Sol and Claude Opus 5.5 where each model has access to a tool which gives them information about the game (presumably non-visual, but only the information they could see through fog of war etc) and lets them control their units etc [...]
Consult ~/dev/llm/docs and include notes in that file about how LLM could be used here via a new tools plugin
Opus 5.5 went to work on this, producing this AGENT-BATTLES.md proposal and then implementing and testing it. The feature also includes the ability to record and replay these battles - here’s a replay of Claude Haiku 5.5 vs. GPT-6 Luna, and here’s that same battle in a separate debug tool that shows the underlying prompt responses.
The prompt that drives agent battles can be seen here.
There are a few more replays like this linked in the README. I hope to turn this into a full league table at some point in the future.
v11: Random Maps
This version exists purely because I glanced at my Claude Usage page one day and saw that I’d only used 75% of my weekly allowance and it was resetting in 45 minutes. I decided to see if I could get an extra Battle Drones feature from my remaining tokens, and picked “random map” as the target:
Design and implement a mechanism for generating a random map using any of the available biomes - it should be the size of the largest map and rivers and bridges and rocks and forest and scrap and crystals are all in play. Make them rotationally symmetric and use a seed to allow them to be selected or reused later. You have 45 minutes to build this! Be creative.
Here’s the transcript, and an image Claude generated to show me its work:
v12: Multiplayer via sound
I only just got this working, so I’ve not had much time to actively test it yet. The latest Battle Drones now supports multiplayer via two devices sat within microphone distance of each other!
This feature started out as my Chirp Pong experiment from last week. I pointed Claude Code at that working proof of concept:
Clone Simonw/tools from GitHub and look at recent branches for the example pong game that uses web microphone to implement multiplayer between two phones via audio signals
Build a version of that for battledrones
Opus built this Radio Probe tool to measure how much bandwidth we could get between two devices and, based on positive results from that, implemented a full audio modem system. I’ve tried it between laptops, iPhones and iPads so far and it seems to work really well!
Why use sound for this? Because I love static HTML that costs nothing to run, and I don’t want to spin up a server somewhere and then stay responsible for keeping it operating for as long as anyone might want to play the game.
Some thoughts
I know almost nothing about game development. This makes it a great opportunity to try out coding agents in a field where my existing software engineering experience has less impact on the results.
Games are also super low stakes. The worst that can happen is one of my silly game experiments suffers a bug.
This morning (via Hacker News) I found Steam Fans Are Begging for a No-AI Filter as Steam Next Fest Is Filled With Slop. I wouldn’t personally dream of submitting Battle Drones to an event like this - it’s still way too low effort to warrant consideration as a legitimate indie gaming project.
... but I can now see a path to vibe coded games like this being taken seriously. Battle Drones is fun, it looks good, it has innovative features (the multiplayer-over-audio thing is a first for an RTS as far as I can tell).
I’d love to see what someone with better taste than me and a driving passion to produce something truly exceptional could build!
A few other observations from this project:
Static HTML and JavaScript is a fantastic medium for games development. WebGL works great, and Three.js(and Phaser before it) are excellent platforms to build on that the current models know inside out.
This also lets them run as Progressive Web Apps - I didn’t ask for it, but Battle Drones works offline. I was able to play it on a plane despite never having directly installed it - my phone had it cached.
Giving Claude an OpenAI API key and telling it to generate images using OpenAI’s models works really well. It can view the images it has generated and iterate on the prompts.
Opus 5.5 is spectacular at 3D modeling using Three.js (and Blender, and no doubt other 3D applications as well). The same is true of GPT-6 Astra. They are absolutely capable of building models for 3D game projects.
For features like replay and multiplayer it’s useful to have a deterministic simulation engine. At one point Claude had to replace calls to
Math.sin()andMath.cos()and friends with custom versions because different browsers (Chrome vs. Safari, for example) returned very slightly different numbers, desynchronizing the replay.Opus 5.5 can write music! There are no audio files in this project - the soundtrack is entirely generated through code, varies across different maps, and even gets more intense as the battle heats up. See Scrimshaw Jukeboxfor a previous experiment with Claude for music composition.
I still can’t get over how well the prompt “Make it a LOT more fun” worked.
Tools are effectively free. I prompted up the Radio Probe, the Model browser, the Agent vs. Agent debug tool, and Claude Code built a bunch of tools for itself that I haven’t even explored myself.
Audio-based multiplayer between static HTML games works! I hope to see a whole lot more games use this same pattern - in digging around today I’ve not found much prior art beyond Siner by Alon Horesh and ggwave by Georgi Gerganov (also of
llama.cppfame).Claude Code “Ultracode” burns tokens like there’s no tomorrow, but it can also solve complex problems (like adding audio-based multiplayer) from a single prompt.
I’m still not quite over the guilt of building software in this way. I don’t feel like I’ve earned the right to create something this good, in a field in which I have so little prior experience! At this point I’ve shown it to enough people in private that it felt wrong not to publish it for everyone else to see and learn from.
Update: Online multiplayer support
Earlier in this article I said:
Games are also super low stakes. The worst that can happen is one of my silly game experiments suffers a bug.
Then I tried playing the multiplayer version with Natalie... and the high pitched modem sounds gave her a nasty headache!
That’s a pretty bad bug. I added a warning and was then inspired to build proper network multiplayer. I tried getting WebRTC to work but couldn’t get a connection going between two of my own devices even on my own WiFi network, so I had Claude build a simple, stateless WebSockets relay server instead:
If I wanted to support multiplayer between two devices at a very low cost without storing any state on the server could I do that with a tiny asyncio web server running on the cheapest Fly instance?
Build the server and the fly.toml for deploying it, use Fly application name battledrones-relay - put that in a folder in the repo, include deploy instructions in the README in that folder
Here’s the resulting server. Since this scales to zero and runs on a single Fly.io shared-cpu-1x instance it should cost me no more than $2.19/month - and that’s if it stays hot and serving connections the whole time.
Battle Drones now supports online multiplayer. Click “Duel a friend online”, then either share the resulting room URL via your messaging app of choice or have them snap a picture of the displayed QR Code.
I also added a feature where you can copy JSON of the match once it has ended and then feed that into the replay feature to rewatch your game.
I didn’t expect to introduce online multiplayer this soon, but the headache bug felt like it warranted an urgent alternative.
Release: web-edit 0.1a0
I was working on a project from my phone using Codex Remote when I found myself wanting to edit a credentials file without round-tripping those credentials through the LLM itself.
So... I had Codex and GPT-6 Astra Extra High build this Python web app which provides a web UI for viewing and editing files in a folder. It’s intended to be run over Tailscale, so I can have an agent start this running and then edit files via my Tailscale network directly from my phone.
Here’s the interface for browsing files in a folder:
Editing uses CodeMirror 6 - I was going to use Monaco but that still doesn’t have a great mobile experience yet.
Research: Profiling web-edit with Python 3.15: flame graphs and source heatmaps
I put the new Python 3.15 profiler through its paces by having GPT-6 Astra Extra High in Codex run it against my new web-edit app:
I need a Python 3.15 flame graph and heatmap demo of the "web-edit" app from PyPI - research first then make me those demos
Here’s the resulting example flame graph and heatmap.
Release: llm-meta-ai 0.2
Meta AI release Muse Wonder (and Muse Wonder Full), their new “most capable models”. These look like they may be Meta’s first Fable class models - Artificial Analysis scores Muse Wonder (Max) as equivalent to GPT-6.1 Sol.
I updated my llm-meta-ai plugin for the new model. Here are pelicans for Muse Wonder for the six reasoning levels: minimal, low, medium, high, xhigh, max. This is the max one:
For comparison, here are pelicans for Muse 1.3 (released September 2nd) and Muse 1.2 (released August 5th). Meta AI are putting out a new model a month, and the improvements between each model (at least in terms of drawing pelicans) are material.
Release: web-edit 0.1a1
Includes performance optimizations written by Claude Opus 5.5 after I fed it this Python 3.15 profiling report generated by GPT-6 Astra.
Quote 2026-10-13
If the agent isn’t using my diagnostics library, I could introspect and update AGENTS.md, but there’s still a delta, and it’ll drift. Instead, I write a pre-commit hook that checks the git diff for direct calls to observability modules that bypass my diagnostics module. Boom: fail the commit, inject a prompt telling the agent to use the diagnostics library. All of a sudden it’s ten out of ten.
Geoffrey Huntley, nobody should type code by hand anymore. here’s what’s left.
Release: llm-gemini 0.35
I added support to llm-gemini for the new Gemini 4 Argon model, made available today via the Gemini API and for customers of their $100/month subscription plan.
Here are the low, medium and high pelicans. As expected, they are all excellent: Gemini has a track record of producing great SVGs, and are the only lab where I know their staff have invested in SVG specifically (and who have boasted about their pelicans before.)
Here’s the “high” illustration, which cost me 17.166 cents:
The pricing is interesting. At launch, Argon is $2/million input and $10/million output - the same price as GPT-6 Sol, half the price of Claude Opus 5.5 and 1/5th the price of Claude Fable 5.1 and GPT-6 Astra.
But on December 1st Argon is set to double in price - so it will be the same price as Opus 5.5.
Prices like this aren’t really comparable these days since what really matters is how many tokens a model takes to achieve a goal within an agentic harness.
One useful clue for that comes from Artificial Analysis, who publish the total cost to run their benchmark using each model. Argon is looking very good there - costing $2,407 to run the benchmark, putting it close to GLM-5.3 and significantly cheaper than OpenAI, Anthropic, and Meta’s latest models.
When the price doubles it will still be a little cheaper than GPT-6 Astra.
(I used ChatGPT to edit that chart! The data is all correct, I checked - I needed to get that Gemini 4 Argon info box to display without overlapping the other numbers.)
Some bonus examples using Gemini 4 Argon: here’s Generate an SVG of an armadillo in fishnet tights jaywalking on Mars, here’s a Fabergé egg it created for me using Blender, and DeepMind staffer @fofrAI shared a video of a pelican riding a bike, using fourier epicycles. That’s a fun new twist!
Link 2026-10-13 Redesigning source control at Anthropic:
Interesting piece from Anthropic describing why and how they built their own custom alternative to Git, based on the dramatic increase in rate of changes to their code after the past six months.
In May 2026, Anthropic averaged around 2,500 code changes merged per day; as of September, we merged over 30,000 per day.
They included a chart showing those changes. I had Claude modify their chart (code here) to add markers for the public releases of each of their models in 2026:
This shows public release dates, not the date when models became available for Anthropic’s internal use. My guess is that the introduction of Fable/Mythos class models is a key factor in the increased coding velocity.
“Antique” is their new code review system. The source control system is called Scion, and sounds to me like a reinvention of centralized source control along the lines of Subversion.
(Update: Anthropic credit Google’s Piper and Meta’s Sapling as “prior art” - it looks like the core concept of “derived data” was heavily inspired by Mononoke, the server component of Sapling.)
They had some pretty extreme requirements:
The history of our main branch alone is almost 100 GB, and a compressed working copy is over 25 GB. We perform on the order of 25 million code checkouts per day for CI, before counting developer environments, agent sandboxes, and research jobs. Fetched naively, that would be over 600 PB of git traffic per day.
The new system was built by a team of seven people, and the migration from Git was completed in five months.
When asked on Hacker News about the lack of offline support, Scion engineer Nick G replied:
Since Claude is by far the heaviest user of Scion and is necessarily online, this just wasn’t important to do.
As an aside, I’ve been trying adversarial review in my own projects recently, where you have a model try and find flaws (I often play Claude and GPT off against each other). This note from the article reflected my own experience with that:
Anthropic also makes extensive use of adversarial review, and, while this is incredibly effective in many ways, it can also be myopic, so skilled engineers needed to steer Claude away from over-engineering parts of the system in response to hypothetical concerns.
Link 2026-10-14 AI is mass decompiling games. That’s both awesome and scary.:
Indie game developer Popcar talks about the recent wave of AI-powered decompilation of existing games, enabling weird mashups between existing games, and producing a boom in game preservation projects to get old games working on new hardware (often in a browser using WebAssembly).
I like how this piece captures both the positives and the negatives of this new development:
Most people already realized the scary part by now. If AI can decompile games and software, then the entire tech industry is about to explode. Anybody can decompile other software and use it any way they’d like, and nobody can stop them. Companies can steal from competitors. Your paid game or app can be open-sourced against your will. This isn’t exclusive to old video games, we can apply this to any software. [...]
This is also a big win for preservation. Old games can be ported, modified, enhanced, and made much more easily accessible than before. [...[
With console makers going all in on digital and games becoming entirely unplayable due to servers shutting down, this is fantastic news. We could own software we bought regardless of what the company thinks.
Tool: Tree Appreciator
Another game experiment with Claude. This one used the default Claude iPhone app (chat mode, not Claude Code mode), where I prompted Claude Opus 5.5 Max with:
Build a three js game called "Tree appreciator" - it shows you two algorithmically generated trees and the game mechanics is about appreciating the differences between them. Think hard about how to make sure it is both fun and beautiful.
Somewhat embarrassingly given my recent talk, I’ve found that telling Opus 5.5 “make sure it is fun” works uncomfortably well. In this case Claude crunched for 3 hours and 7 minutes before retuning a cosy little spot-the-difference game with music and animation and achievements that’s quite compelling to play.
Tool: LaTeX renderer
Inspired by Paul Ford and Aboard Foundary’s new web app Tiny Little Office, which provides a suite of web app content editors (a Word Processor, Outliner, Presentation Builder, Spreadsheet, Calculator, Drawing Tool, Diagram Maker, Animator, Calendar, and Trip Planner).
Tiny Little Office’s signature trick is to store all of the document data in the #fragment section of the URL, so every document created using it becomes a bookmarkable and shareable link.
It also has an llms.txt file telling agents how to construct URLs that will render as documents. Claude used that file to generate this link to a deck that explains how the URL format works:
Tiny Little Office inspired me to have Claude Code (Opus 5.5 Extra) build a similar tool that works with LaTeX. Here’s the sequence of prompts I used:
I want a tool where you can link to it with a fragment hash #code-here and it treats that code as LaTeX and renders it really effectively. It should also support a prefix which means the latex is compressed with a custom compression dictionary optimized for latex. Use the best available latex render library from a CDN (consider WebAssembly too). If loaded without a fragment hash show an editor you can paste latex into and then toggle to a "rendered" view. That rendered view should be bookmarkable. The #fragment view should let you switch to edit source too.
Since it was working in my tools repo I told it to take inspiration from the <iframe sandbox="..."> mechanism used by my existing SVG in Markdown tool as protection against XSS risks:
Safe from XSS? We could run in an iframe sandbox like we do on the SVG markdown render project
I had it copy the Gist/URL loading feature from that tool as well:
We should have an option to load latex from a URL (or gist) similar to the markdown SVG tool
Here’s an example link. The tool uses Pako 2.1.0, MathJax 4.1.3, faster-latex 0.3.1, and DOMPurify 3.4.16.
Link 2026-10-15 Anthropic tells investors quarterly revenue up nearly 50% to $16.8bn ahead of IPO:
The phrase “told investors” appears four times in this FT article, which reports on Anthropic’s day of hosting investors on Wednesday. Lots of details in here from “people with knowledge of the matter“.
Key things I learned from the article:
Q1 revenue (Jan/Feb/Mar) was “about $4.8bn”
Q2 (Apr/May/Jun) was $11.5bn
Q3 (Jul/Aug/Sep) was $16.8bn
In Q3: $1.70 in revenue for every $1 spent on “computing power”
Adjusted operating margins (excluding stock-based compensation) were 11%
This point about distillation is worth quoting in full (highlight mine):
The start-up has also clamped down on “distillation” — a controversial practice whereby rival AI labs train their models on the outputs of more advanced ones.
When rival companies “distil” their models from Anthropic’s models, that involves heavy usage and spending.
Anthropic told investors on Wednesday distillation accounted for 5 per cent to 7 per cent of revenueand that they had cut it back “materially” in the third quarter of the year, said four people with direct knowledge of the matter.
Napkin maths says that if distillation was 5% of their Q2 revenue (before they cut it back in Q3) then unnamed “other labs” spent over half a billion dollars distilling Anthropic’s models in that quarter!
Also notable: Anthropic appear to no longer be leaning on “annualized run-rate revenue” (previously) in these communications to their investors.
Tool: Chirp Pong
Another game experiment - I wanted to see if it was feasible to have a two player game on two separate phones running in static HTML where the networking code uses chirps sent via the microphone. It seems to work!
Build a two player competitive pong like game where two players use their phones close to each other and the game state is sent via audio noises which the web microphone API can interpret - but add graphical and gameplay twists to make it a lot more fun and intertwine than pong
Claude Opus 5.5 Extra in Claude Code.
Quote 2026-10-16
We think “did a human read the code?” is an imprecise proxy for “what could go wrong with this change, and which check—automated or human—is the right one to catch it?”
Asking that question also changed when review happens. Before, review was a gate at the end of the road: write the code, open a PR, wait for your colleague.
Now, review runs continuously, more like spellcheck while you write. Most changes have been reviewed and fixed by Claude at least once before a human is asked to look. This catches most routine mistakes, and saves team attention for higher-level questions and scrutiny.
Addy Osmani, Morgan Westlee Lunt, and Qing Wang, How the Claude Code team does code review
Release: web-edit 0.1a2
web-edit (previously) is my tiny web app for browsing and editing files in a folder. I mainly built it for editing files on different machines via Tailscale.
I added a “copy to clipboard” option for both text and image data. I needed this because I was running pelican prompts on a laptop from my phone (here’s DeepSeek 4.1 Flash 1017) and I wanted an easy way to copy the resulting logs into a Gist.
Link 2026-10-17 Inline rendering with document.currentScript:
Lean Rada describes a neat trick that takes advantage of the document.currentScript property. You can use that to drop in a tiny inline <script> element that replaces itself when the page loads:
The year is <script>
document.currentScript.replaceWith( new Date().getFullYear())</script>If you define a shortcut function like this:
$=(...n)=>document.currentScript.replaceWith(...n)You get a tiny template language:
The year is <script>$(new Date().getFullYear())</script>Release: llm-echo 0.5
I’m working towards a new LLM release, and testing PRs caused me to revisit the llm-echo debug plugin. This plugin provides a “model” which doesn’t involve an LLM at all - it just repeats back the prompts that have been fed to it. The new release now updates the simulated token usage counts to take tool calls, system prompts, and reasoning tokens into account.
Example usage:
uvx --with llm-echo llm -m echo 'hi there' -o thinking 1 --usageOutputs:
First I consider the prompt, then I decide what to say.
{ "prompt": "hi there", "system": "", "attachments": [], "stream": true, "previous": []
}
Token usage: 2 input, 24 outputRelease: llm-tools-datasette 0.1.1
When I switched LLM over to httpx2 in LLM 0.33 I forget that this would break any plugins which used httpx without directly depending on it. llm-tools-datasette was one of those plugins, now fixed.
Link 2026-10-19 My obituary for programming:
Jeremy Scheff poignantly captures the key loss caused by coding agents for career programmers who enjoyed the puzzle of developing code:
Programming turned into one of the greatest jobs you could imagine. You got paid to work on tricky little logic puzzles. The trickier the puzzle, the more you got paid. But even pretty simple puzzles were worth a lot of money because regular people just couldn’t do it! No, they needed us. They would give us a problem and we would solve it the way we wanted. We set the strategy, we made the timeline, we defined what was and was not possible.
If you’re a programmer who thrives on building working systems and doesn’t care too deeply about the problems solved along the way, LLMs are the gift that keeps on giving.
If directly solving those problems was a big part of your enjoyment, the loss is very real.
Link 2026-10-20 eMudhra Intermediate CA Compromise:
This is very, very bad news:
The private keys of eight eMudhra intermediate CA certificates have been compromised. They chain to roots trusted by the Mozilla, Microsoft, Apple and Chrome root programs and by many downstream trust stores.
Any software that bundles a list of trusted certificates needs to be updated. This site is tracking software updates via this GitHub repository - Linux distros need to update their ca-certificates packages.
In Python world uv 0.13.4 and pip 26.2.2 and certifi 2026.10.19 have been released with upgraded certificate lists.
If you find this newsletter useful, please consider sponsoring me via GitHub. $10/month and higher sponsors get a monthly newsletter with my summary of the most important trends of the past 30 days - here are previews from Juneand July and August.
Thanks for reading Simon Willison’s Newsletter! Subscribe for free to receive new posts and support my work.















