<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom"><title>Simon Willison's Weblog: rust</title><link href="http://simonwillison.net/" rel="alternate"/><link href="http://simonwillison.net/tags/rust.atom" rel="self"/><id>http://simonwillison.net/</id><updated>2026-02-27T20:43:41+00:00</updated><author><name>Simon Willison</name></author><entry><title>An AI agent coding skeptic tries AI agent coding, in excessive detail</title><link href="https://simonwillison.net/2026/Feb/27/ai-agent-coding-in-excessive-detail/#atom-tag" rel="alternate"/><published>2026-02-27T20:43:41+00:00</published><updated>2026-02-27T20:43:41+00:00</updated><id>https://simonwillison.net/2026/Feb/27/ai-agent-coding-in-excessive-detail/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://minimaxir.com/2026/02/ai-agent-coding/"&gt;An AI agent coding skeptic tries AI agent coding, in excessive detail&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Another in the genre of "OK, coding agents got good in November" posts, this one is by Max Woolf and is very much worth your time. He describes a sequence of coding agent projects, each more ambitious than the last - starting with simple YouTube metadata scrapers and eventually evolving to this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It would be arrogant to port Python's &lt;a href="https://scikit-learn.org/stable/"&gt;scikit-learn&lt;/a&gt; — the gold standard of data science and machine learning libraries — to Rust with all the features that implies.&lt;/p&gt;
&lt;p&gt;But that's unironically a good idea so I decided to try and do it anyways. With the use of agents, I am now developing &lt;code&gt;rustlearn&lt;/code&gt; (extreme placeholder name), a Rust crate that implements not only the fast implementations of the standard machine learning algorithms such as &lt;a href="https://en.wikipedia.org/wiki/Logistic_regression"&gt;logistic regression&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/K-means_clustering"&gt;k-means clustering&lt;/a&gt;, but also includes the fast implementations of the algorithms above: the same three step pipeline I describe above still works even with the more simple algorithms to beat scikit-learn's implementations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Max also captures the frustration of trying to explain how good the models have got to an existing skeptical audience:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The real annoying thing about Opus 4.6/Codex 5.3 is that it’s impossible to publicly say “Opus 4.5 (and the models that came after it) are an order of magnitude better than coding LLMs released just months before it” without sounding like an AI hype booster clickbaiting, but it’s the counterintuitive truth to my personal frustration. I have been trying to break this damn model by giving it complex tasks that would take me months to do by myself despite my coding pedigree but Opus and Codex keep doing them correctly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A throwaway remark in this post inspired me to &lt;a href="https://github.com/simonw/research/tree/main/rust-wordcloud#readme"&gt;ask Claude Code to build a Rust word cloud CLI tool&lt;/a&gt;, which it happily did.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/max-woolf"&gt;max-woolf&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/coding-agents"&gt;coding-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/agentic-engineering"&gt;agentic-engineering&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/november-2025-inflection"&gt;november-2025-inflection&lt;/a&gt;&lt;/p&gt;



</summary><category term="python"/><category term="ai"/><category term="rust"/><category term="max-woolf"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="coding-agents"/><category term="agentic-engineering"/><category term="november-2025-inflection"/></entry><entry><title>Rust Word Cloud CLI</title><link href="https://simonwillison.net/2026/Feb/27/rust-wordcloud/#atom-tag" rel="alternate"/><published>2026-02-27T19:02:00+00:00</published><updated>2026-02-27T19:02:00+00:00</updated><id>https://simonwillison.net/2026/Feb/27/rust-wordcloud/#atom-tag</id><summary type="html">
    &lt;p&gt;&lt;strong&gt;Research:&lt;/strong&gt; &lt;a href="https://github.com/simonw/research/tree/main/rust-wordcloud#readme"&gt;Rust Word Cloud CLI&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;Leveraging Rust’s performance and safety, this CLI tool generates PNG word clouds directly from text input using a custom spiral layout algorithm and efficient grid-based collision detection. It supports flexible options for image size, font scaling, color schemes, and background colors, with all core features—such as stopword filtering, spatial indexing, and layout—implemented from scratch without any external word cloud library.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="rust"/></entry><entry><title>Ladybird adopts Rust, with help from AI</title><link href="https://simonwillison.net/2026/Feb/23/ladybird-adopts-rust/#atom-tag" rel="alternate"/><published>2026-02-23T18:52:53+00:00</published><updated>2026-02-23T18:52:53+00:00</updated><id>https://simonwillison.net/2026/Feb/23/ladybird-adopts-rust/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://ladybird.org/posts/adopting-rust/"&gt;Ladybird adopts Rust, with help from AI&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Really interesting case-study from Andreas Kling on advanced, sophisticated use of coding agents for ambitious coding projects with critical code. After a few years hoping Swift's platform support outside of the Apple ecosystem would mature they switched tracks to Rust their memory-safe language of choice, starting with an AI-assisted port of a critical library:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Our first target was &lt;strong&gt;LibJS&lt;/strong&gt; , Ladybird's JavaScript engine. The lexer, parser, AST, and bytecode generator are relatively self-contained and have extensive test coverage through &lt;a href="https://github.com/tc39/test262"&gt;test262&lt;/a&gt;, which made them a natural starting point.&lt;/p&gt;
&lt;p&gt;I used &lt;a href="https://docs.anthropic.com/en/docs/claude-code"&gt;Claude Code&lt;/a&gt; and &lt;a href="https://openai.com/codex/"&gt;Codex&lt;/a&gt; for the translation. This was human-directed, not autonomous code generation. I decided what to port, in what order, and what the Rust code should look like. It was hundreds of small prompts, steering the agents where things needed to go. [...]&lt;/p&gt;
&lt;p&gt;The requirement from the start was byte-for-byte identical output from both pipelines. The result was about 25,000 lines of Rust, and the entire port took about two weeks. The same work would have taken me multiple months to do by hand. We’ve verified that every AST produced by the Rust parser is identical to the C++ one, and all bytecode generated by the Rust compiler is identical to the C++ compiler’s output. Zero regressions across the board.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Having an existing conformance testing suite of the quality of &lt;code&gt;test262&lt;/code&gt; is a huge unlock for projects of this magnitude, and the ability to compare output with an existing trusted implementation makes agentic engineering much more of a safe bet.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=47120899"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/browsers"&gt;browsers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/andreas-kling"&gt;andreas-kling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ladybird"&gt;ladybird&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/coding-agents"&gt;coding-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/swift"&gt;swift&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/conformance-suites"&gt;conformance-suites&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/agentic-engineering"&gt;agentic-engineering&lt;/a&gt;&lt;/p&gt;



</summary><category term="browsers"/><category term="javascript"/><category term="ai"/><category term="rust"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="andreas-kling"/><category term="ladybird"/><category term="coding-agents"/><category term="swift"/><category term="conformance-suites"/><category term="agentic-engineering"/></entry><entry><title>LadybirdBrowser/ladybird: Abandon Swift adoption</title><link href="https://simonwillison.net/2026/Feb/19/ladybird/#atom-tag" rel="alternate"/><published>2026-02-19T01:25:33+00:00</published><updated>2026-02-19T01:25:33+00:00</updated><id>https://simonwillison.net/2026/Feb/19/ladybird/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/LadybirdBrowser/ladybird/commit/e87f889e31afbb5fa32c910603c7f5e781c97afd"&gt;LadybirdBrowser/ladybird: Abandon Swift adoption&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Back &lt;a href="https://simonwillison.net/2024/Aug/11/ladybird-set-to-adopt-swift/"&gt;in August 2024&lt;/a&gt; the Ladybird browser project announced an intention to adopt Swift as their memory-safe language of choice.&lt;/p&gt;
&lt;p&gt;As of &lt;a href="https://github.com/LadybirdBrowser/ladybird/commit/e87f889e31afbb5fa32c910603c7f5e781c97afd"&gt;this commit&lt;/a&gt; it looks like they've changed their mind:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Everywhere: Abandon Swift adoption&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After making no progress on this for a very long time, let's acknowledge it's not going anywhere and remove it from the codebase.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 23rd February 2025&lt;/strong&gt;: They've &lt;a href="https://ladybird.org/posts/adopting-rust/"&gt;adopted Rust&lt;/a&gt; instead.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=47067678"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/browsers"&gt;browsers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ladybird"&gt;ladybird&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/swift"&gt;swift&lt;/a&gt;&lt;/p&gt;



</summary><category term="browsers"/><category term="rust"/><category term="ladybird"/><category term="swift"/></entry><entry><title>Running Pydantic's Monty Rust sandboxed Python subset in WebAssembly</title><link href="https://simonwillison.net/2026/Feb/6/pydantic-monty/#atom-tag" rel="alternate"/><published>2026-02-06T22:31:31+00:00</published><updated>2026-02-06T22:31:31+00:00</updated><id>https://simonwillison.net/2026/Feb/6/pydantic-monty/#atom-tag</id><summary type="html">
    &lt;p&gt;There's a jargon-filled headline for you! Everyone's &lt;a href="https://simonwillison.net/2026/Jan/8/llm-predictions-for-2026/#1-year-we-re-finally-going-to-solve-sandboxing"&gt;building sandboxes&lt;/a&gt; for running untrusted code right now, and Pydantic's latest attempt, &lt;a href="https://github.com/pydantic/monty"&gt;Monty&lt;/a&gt;, provides a custom Python-like language (a subset of Python) in Rust and makes it available as both a Rust library and a Python package. I got it working in WebAssembly, providing a sandbox-in-a-sandbox.&lt;/p&gt;
&lt;p&gt;Here's &lt;a href="https://github.com/pydantic/monty"&gt;how they describe Monty&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Monty avoids the cost, latency, complexity and general faff of using full container based sandbox for running LLM generated code.&lt;/p&gt;
&lt;p&gt;Instead, it let's you safely run Python code written by an LLM embedded in your agent, with startup times measured in single digit microseconds not hundreds of milliseconds.&lt;/p&gt;
&lt;p&gt;What Monty &lt;strong&gt;can&lt;/strong&gt; do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run a reasonable subset of Python code - enough for your agent to express what it wants to do&lt;/li&gt;
&lt;li&gt;Completely block access to the host environment: filesystem, env variables and network access are all implemented via external function calls the developer can control&lt;/li&gt;
&lt;li&gt;Call functions on the host - only functions you give it access to [...]&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;A quick way to try it out is via &lt;a href="https://github.com/astral-sh/uv"&gt;uv&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uv run --with pydantic-monty python -m asyncio
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then paste this into the Python interactive prompt - the &lt;code&gt;-m asyncio&lt;/code&gt; enables top-level await:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;import&lt;/span&gt; &lt;span&gt;pydantic_monty&lt;/span&gt;
&lt;span&gt;code&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;pydantic_monty&lt;/span&gt;.&lt;span&gt;Monty&lt;/span&gt;(&lt;span&gt;'print("hello " + str(4 * 5))'&lt;/span&gt;)
&lt;span&gt;await&lt;/span&gt; &lt;span&gt;pydantic_monty&lt;/span&gt;.&lt;span&gt;run_monty_async&lt;/span&gt;(&lt;span&gt;code&lt;/span&gt;)&lt;/pre&gt;
&lt;p&gt;Monty supports a &lt;em&gt;very&lt;/em&gt; small subset of Python - it doesn't even support class declarations yet!&lt;/p&gt;
&lt;p&gt;But, given its target use-case, that's not actually a problem.&lt;/p&gt;
&lt;p&gt;The neat thing about providing tools like this for LLMs is that they're really good at iterating against error messages. A coding agent can run some Python code, get an error message telling it that classes aren't supported and then try again with a different approach.&lt;/p&gt;
&lt;p&gt;I wanted to try this in a browser, so I fired up &lt;a href="https://simonwillison.net/2025/Nov/6/async-code-research/"&gt;a code research task&lt;/a&gt; in Claude Code for web and kicked it off with the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Clone &lt;a href="https://github.com/pydantic/monty"&gt;https://github.com/pydantic/monty&lt;/a&gt; to /tmp and figure out how to compile it into a python WebAssembly wheel that can then be loaded in Pyodide. The wheel file itself should be checked into the repo along with build scripts and passing pytest playwright test scripts that load Pyodide from a CDN and the wheel from a “python -m http.server” localhost and demonstrate it working&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then a little later:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I want an additional WASM file that works independently of Pyodide, which is also usable in a web browser - build that too along with playwright tests that show it working. Also build two HTML files - one called demo.html and one called pyodide-demo.html - these should work similar to &lt;a href="https://tools.simonwillison.net/micropython"&gt;https://tools.simonwillison.net/micropython&lt;/a&gt; (download that code with curl to inspect it) - one should load the WASM build, the other should load Pyodide and have it use the WASM wheel. These will be served by GitHub Pages so they can load the WASM and wheel from a relative path since the .html files will be served from the same folder as the wheel and WASM file&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here's &lt;a href="https://gisthost.github.io/?22d88e6367d7e002c4fb383c213c2df2/page-001.html"&gt;the transcript&lt;/a&gt;, and the &lt;a href="https://github.com/simonw/research/tree/main/monty-wasm-pyodide"&gt;final research report&lt;/a&gt; it produced.&lt;/p&gt;
&lt;p&gt;I now have the Monty Rust code compiled to WebAssembly in two different shapes - as a &lt;code&gt;.wasm&lt;/code&gt; bundle you can load and call from JavaScript, and as a &lt;code&gt;monty-wasm-pyodide/pydantic_monty-0.0.3-cp313-cp313-emscripten_4_0_9_wasm32.whl&lt;/code&gt; wheel file which can be loaded into &lt;a href="https://pyodide.org/"&gt;Pyodide&lt;/a&gt; and then called from Python in Pyodide in WebAssembly in a browser.&lt;/p&gt;
&lt;p&gt;Here are those two demos, hosted on GitHub Pages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://simonw.github.io/research/monty-wasm-pyodide/demo.html"&gt;Monty WASM demo&lt;/a&gt; - a UI over JavaScript that loads the Rust WASM module directly.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://simonw.github.io/research/monty-wasm-pyodide/pyodide-demo.html"&gt;Monty Pyodide demo&lt;/a&gt; - this one provides an identical interface but here the code is &lt;a href="https://github.com/simonw/research/blob/3add1ffec70b530711fa237d91f546da5bcf1f1c/monty-wasm-pyodide/pyodide-demo.html#L257-L280"&gt;loading Pyodide and then installing the Monty WASM wheel&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://static.simonwillison.net/static/2026/monty-pyodide.jpg" alt="Screenshot of a web app titled &amp;quot;Monty via Pyodide&amp;quot; with description &amp;quot;Run Monty (a sandboxed Python interpreter by Pydantic) inside Pyodide (CPython compiled to WebAssembly). This loads the pydantic-monty wheel and uses its full Python API. Code is saved in the URL for sharing.&amp;quot; A green banner reads &amp;quot;Code executed successfully!&amp;quot; Below are example buttons labeled &amp;quot;Basic&amp;quot;, &amp;quot;Inputs&amp;quot;, &amp;quot;Reuse&amp;quot;, &amp;quot;Error Handling&amp;quot;, &amp;quot;Fibonacci&amp;quot;, and &amp;quot;Classes&amp;quot;. A code editor labeled &amp;quot;Python Code (runs inside Monty sandbox via Pyodide):&amp;quot; contains: &amp;quot;import pydantic_monty\n\n# Create interpreter with input variables\nm = pydantic_monty.Monty('x + y', inputs=['x', 'y'])\n\n# Run with different inputs\nresult1 = m.run(inputs={&amp;quot;x&amp;quot;: 10, &amp;quot;y&amp;quot;: 20})\nprint(f&amp;quot;10 + 20 = {result1}&amp;quot;)\n\nresult2 = m.run(inputs={&amp;quot;x&amp;quot;: 100, &amp;quot;y&amp;quot;: 200})&amp;quot; with &amp;quot;Run Code&amp;quot; and &amp;quot;Clear&amp;quot; buttons. The Output section shows &amp;quot;10 + 20 = 30&amp;quot; and &amp;quot;100 + 200 = 300&amp;quot; with a &amp;quot;Copy&amp;quot; button. Footer reads &amp;quot;Executed in 4.0ms&amp;quot;." style="max-width: 100%;" /&gt;&lt;/p&gt;
&lt;p&gt;As a connoisseur of sandboxes - the more options the better! - this new entry from Pydantic ticks a lot of my boxes. It's small, fast, widely available (thanks to Rust and WebAssembly) and provides strict limits on memory usage, CPU time and access to disk and network.&lt;/p&gt;
&lt;p&gt;It was also a great excuse to spin up another demo showing how easy it is these days to turn compiled code like C or Rust into WebAssembly that runs in both a browser and a Pyodide environment.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sandboxing"&gt;sandboxing&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webassembly"&gt;webassembly&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pyodide"&gt;pyodide&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pydantic"&gt;pydantic&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/coding-agents"&gt;coding-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude-code"&gt;claude-code&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="javascript"/><category term="python"/><category term="sandboxing"/><category term="ai"/><category term="rust"/><category term="webassembly"/><category term="pyodide"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="pydantic"/><category term="coding-agents"/><category term="claude-code"/></entry><entry><title>Building PyO3/Maturin Rust Extension Modules as WebAssembly Wheels for Pyodide</title><link href="https://simonwillison.net/2026/Feb/6/pyo3-pyodide-wasm/#atom-tag" rel="alternate"/><published>2026-02-06T15:38:00+00:00</published><updated>2026-02-06T15:38:00+00:00</updated><id>https://simonwillison.net/2026/Feb/6/pyo3-pyodide-wasm/#atom-tag</id><summary type="html">
    &lt;p&gt;&lt;strong&gt;Research:&lt;/strong&gt; &lt;a href="https://github.com/simonw/research/tree/main/pyo3-pyodide-wasm#readme"&gt;Building PyO3/Maturin Rust Extension Modules as WebAssembly Wheels for Pyodide&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;Compiling Rust-based Python extension modules (via PyO3 and maturin) into WebAssembly wheels for Pyodide involves precise coordination of toolchain versions and build flags to ensure compatibility. The process relies on maturin (≥1.0) for packaging, the Emscripten SDK (with the exact version used by Pyodide), and a Rust nightly toolchain matching Pyodide&amp;#x27;s ABI, particularly the `-Z emscripten-wasm-eh` flag and a compatible sysroot for Python 3.13 (Pyodide 0.28+).&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="rust"/></entry><entry><title>One Human + One Agent = One Browser From Scratch</title><link href="https://simonwillison.net/2026/Jan/27/one-human-one-agent-one-browser/#atom-tag" rel="alternate"/><published>2026-01-27T16:58:08+00:00</published><updated>2026-01-27T16:58:08+00:00</updated><id>https://simonwillison.net/2026/Jan/27/one-human-one-agent-one-browser/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://emsh.cat/one-human-one-agent-one-browser/"&gt;One Human + One Agent = One Browser From Scratch&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
embedding-shapes was &lt;a href="https://emsh.cat/cursor-implied-success-without-evidence/"&gt;so infuriated&lt;/a&gt; by the hype around Cursor's &lt;a href="https://simonwillison.net/2026/Jan/23/fastrender/"&gt;FastRender browser project&lt;/a&gt; - thousands of parallel agents producing ~1.6 million lines of Rust - that they were inspired to take a go at building a web browser using coding agents themselves.&lt;/p&gt;
&lt;p&gt;The result is &lt;a href="https://github.com/embedding-shapes/one-agent-one-browser"&gt;one-agent-one-browser&lt;/a&gt; and it's &lt;em&gt;really&lt;/em&gt; impressive. Over three days they drove a single Codex CLI agent to build 20,000 lines of Rust that successfully renders HTML+CSS with no Rust crate dependencies at all - though it does (reasonably) use Windows, macOS and Linux system frameworks for image and text rendering.&lt;/p&gt;
&lt;p&gt;I installed the &lt;a href="https://github.com/embedding-shapes/one-agent-one-browser/releases/tag/0.1.0"&gt;1MB macOS binary release&lt;/a&gt; and ran it against my blog:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;chmod 755 ~/Downloads/one-agent-one-browser-macOS-ARM64 
~/Downloads/one-agent-one-browser-macOS-ARM64 https://simonwillison.net/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's the result:&lt;/p&gt;
&lt;p&gt;&lt;img alt="My blog rendered in a window. Everything is in the right place, the CSS gradients look good, the feed subscribe SVG icon is rendered correctly but there's a missing PNG image." src="https://static.simonwillison.net/static/2026/one-agent-simonwillison.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;It even rendered my SVG feed subscription icon! A PNG image is missing from the page, which looks like an intermittent bug (there's code to render PNGs).&lt;/p&gt;
&lt;p&gt;The code is pretty readable too - here's &lt;a href="https://github.com/embedding-shapes/one-agent-one-browser/blob/0.1.0/src/layout/flex.rs"&gt;the flexbox implementation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I had thought that "build a web browser" was the ideal prompt to really stretch the capabilities of coding agents - and that it would take sophisticated multi-agent harnesses (as seen in the Cursor project) and millions of lines of code to achieve.&lt;/p&gt;
&lt;p&gt;Turns out one agent driven by a talented engineer, three days and 20,000 lines of Rust is enough to get a very solid basic renderer working!&lt;/p&gt;
&lt;p&gt;I'm going to upgrade my &lt;a href="https://simonwillison.net/2026/Jan/8/llm-predictions-for-2026/#3-years-someone-will-build-a-new-browser-using-mainly-ai-assisted-coding-and-it-won-t-even-be-a-surprise"&gt;prediction for 2029&lt;/a&gt;: I think we're going to get a &lt;em&gt;production-grade&lt;/em&gt; web browser built by a small team using AI assistance by then.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=46779522"&gt;Show Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/browsers"&gt;browsers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/predictions"&gt;predictions&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/coding-agents"&gt;coding-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/codex-cli"&gt;codex-cli&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/browser-challenge"&gt;browser-challenge&lt;/a&gt;&lt;/p&gt;



</summary><category term="browsers"/><category term="predictions"/><category term="ai"/><category term="rust"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="coding-agents"/><category term="codex-cli"/><category term="browser-challenge"/></entry><entry><title>Wilson Lin on FastRender: a browser built by thousands of parallel agents</title><link href="https://simonwillison.net/2026/Jan/23/fastrender/#atom-tag" rel="alternate"/><published>2026-01-23T21:26:10+00:00</published><updated>2026-01-23T21:26:10+00:00</updated><id>https://simonwillison.net/2026/Jan/23/fastrender/#atom-tag</id><summary type="html">
    &lt;p&gt;Last week Cursor published &lt;a href="https://cursor.com/blog/scaling-agents"&gt;Scaling long-running autonomous coding&lt;/a&gt;, an article describing their research efforts into coordinating large numbers of autonomous coding agents. One of the projects mentioned in the article was &lt;a href="https://github.com/wilsonzlin/fastrender"&gt;FastRender&lt;/a&gt;, a web browser they built from scratch using their agent swarms. I wanted to learn more so I asked Wilson Lin, the engineer behind FastRender, if we could record a conversation about the project. That 47 minute video is &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4"&gt;now available on YouTube&lt;/a&gt;. I've included some of the highlights below.&lt;/p&gt;

&lt;iframe style="margin-top: 1.5em; margin-bottom: 1.5em;" width="560" height="315" src="https://www.youtube-nocookie.com/embed/bKrAcTf2pL4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="allowfullscreen"&gt; &lt;/iframe&gt;

&lt;p&gt;See my &lt;a href="https://simonwillison.net/2026/Jan/19/scaling-long-running-autonomous-coding/"&gt;previous post&lt;/a&gt; for my notes and screenshots from trying out FastRender myself.&lt;/p&gt;


&lt;h4 id="what-fastrender-can-do-right-now"&gt;What FastRender can do right now&lt;/h4&gt;
&lt;p&gt;We started the conversation with a demo of FastRender loading different pages (&lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=195s"&gt;03:15&lt;/a&gt;). The JavaScript engine isn't working yet so we instead loaded &lt;a href="https://github.com/wilsonzlin/fastrender"&gt;github.com/wilsonzlin/fastrender&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/"&gt;Wikipedia&lt;/a&gt; and &lt;a href="https://cnn.com"&gt;CNN&lt;/a&gt; - all of which were usable, if a little slow to display.&lt;/p&gt;
&lt;p&gt;JavaScript had been disabled by one of the agents, which decided to add a feature flag! &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=242s"&gt;04:02&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;JavaScript is disabled right now. The agents made a decision as they were currently still implementing the engine and making progress towards other parts... they decided to turn it off or put it behind a feature flag, technically.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="from-side-project-to-core-research"&gt;From side-project to core research&lt;/h4&gt;
&lt;p&gt;Wilson started what become FastRender as a personal side-project to explore the capabilities of the latest generation of frontier models - Claude Opus 4.5, GPT-5.1, and GPT-5.2. &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=56s"&gt;00:56&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;FastRender was a personal project of mine from, I'd say, November. It was an experiment to see how well frontier models like Opus 4.5 and back then GPT-5.1 could do with much more complex, difficult tasks.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A browser rendering engine was the ideal choice for this, because it's both &lt;em&gt;extremely&lt;/em&gt; ambitious and complex but also well specified. And you can visually see how well it's working! &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=117s"&gt;01:57&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As that experiment progressed, I was seeing better and better results from single agents that were able to actually make good progress on this project. And at that point, I wanted to see, well, what's the next level? How do I push this even further?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Once it became clear that this was an opportunity to try multiple agents working together it graduated to an official Cursor research project, and available resources were amplified.&lt;/p&gt;
&lt;p&gt;The goal of FastRender was never to build a browser to compete with the likes of Chrome. &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=2512s"&gt;41:52&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We never intended for it to be a production software or usable, but we wanted to observe behaviors of this harness of multiple agents, to see how they could work at scale.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The great thing about a browser is that it has such a large scope that it can keep serving experiments in this space for many years to come. JavaScript, then WebAssembly, then WebGPU... it could take many years to run out of new challenges for the agents to tackle.&lt;/p&gt;
&lt;h4 id="running-thousands-of-agents-at-once"&gt;Running thousands of agents at once&lt;/h4&gt;
&lt;p&gt;The most interesting thing about FastRender is the way the project used multiple agents working in parallel to build different parts of the browser. I asked how many agents were running at once: &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=324s"&gt;05:24&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;At the peak, when we had the stable system running for one week continuously, there were approximately 2,000 agents running concurrently at one time. And they were making, I believe, thousands of commits per hour.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The project has &lt;a href="https://github.com/wilsonzlin/fastrender/commits/main/"&gt;nearly 30,000 commits&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;How do you run 2,000 agents at once? They used &lt;em&gt;really big machines&lt;/em&gt;. &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=356s"&gt;05:56&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The simple approach we took with the infrastructure was to have a large machine run one of these multi-agent harnesses. Each machine had ample resources, and it would run about 300 agents concurrently on each. This was able to scale and run reasonably well, as agents spend a lot of time thinking, and not just running tools.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;At this point we switched to a live demo of the harness running on one of those big machines (&lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=392s"&gt;06:32&lt;/a&gt;). The agents are arranged in a tree structure, with planning agents firing up tasks and worker agents then carrying them out. &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=434s"&gt;07:14&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.simonwillison.net/static/2026/wilson-lin-agents.jpg" alt="Terminal window showing a tmux session running &amp;quot;grind-swarm&amp;quot; task manager with RUNNING status. Header shows &amp;quot;grind-swarm – 45:54:15&amp;quot; with stats &amp;quot;planners: 9 (0 done) | tasks: 111 working, 0 pending, 232 done | 12900.9M↑ 514.1M↓&amp;quot;. Task list includes: p1 Root (main), p2 CSS selector matching performance + bloom filter integration, p3 CSS stylesheet parsing semantics &amp;amp; at-rule handling, p4 Custom properties (@property) + var() resolution + incremental recompute/invalidation, p37 CSS at-rule artifact integration, p50 Selector engine correctness &amp;amp; spec coverage, p51 Computed-value + property coverage across css-cascade, p105 Style sharing / computed style caching in fastrender-style, p289 CSS cascade layers (@layer) global ordering, w5 Fix workspace lockfile drift, w7 Implement computed-style snapshot sharing, w15 Fix css-properties namespace handling, w17 (Stretch) Enable bloom fast-reject in HTML quirks mode, w18 Refactor css-properties stylesheet parsing. Activity log shows shell commands including cargo check, git status, git push origin main, and various test runs. Bottom status bar shows &amp;quot;grind-css0:target/release/grind-swarm*&amp;quot; and &amp;quot;streamyard.com is sharing your screen&amp;quot; notification with timestamp &amp;quot;12:02 22-Jan-26&amp;quot;." style="max-width: 100%;" /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This cluster of agents is working towards building out the CSS aspects of the browser, whether that's parsing, selector engine, those features. We managed to push this even further by splitting out the browser project into multiple instructions or work streams and have each one run one of these harnesses on their own machine, so that was able to further parallelize and increase throughput.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But don't all of these agents working on the same codebase result in a huge amount of merge conflicts? Apparently not: &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=501s"&gt;08:21&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We've noticed that most commits do not have merge conflicts. The reason is the harness itself is able to quite effectively split out and divide the scope and tasks such that it tries to minimize the amount of overlap of work. That's also reflected in the code structure—commits will be made at various times and they don't tend to touch each other at the same time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This appears to be the key trick for unlocking benefits from parallel agents: if planning agents do a good enough job of breaking up the work into non-overlapping chunks you can bring hundreds or even thousands of agents to bear on a problem at once.&lt;/p&gt;
&lt;p&gt;Surprisingly, Wilson found that GPT-5.1 and GPT-5.2 were a better fit for this work than the coding specialist GPT-5.1-Codex: &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=1048s"&gt;17:28&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some initial findings were that the instructions here were more expansive than merely coding. For example, how to operate and interact within a harness, or how to operate autonomously without interacting with the user or having a lot of user feedback. These kinds of instructions we found worked better with the general models.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I asked what the longest they've seen this system run without human intervention: &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=1108s"&gt;18:28&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So this system, once you give an instruction, there's actually no way to steer it, you can't prompt it, you're going to adjust how it goes. The only thing you can do is stop it. So our longest run, all the runs are basically autonomous. We don't alter the trajectory while executing. [...]&lt;/p&gt;
&lt;p&gt;And so the longest at the time of the post was about a week and that's pretty close to the longest. Of course the research project itself was only about three weeks so you know we probably can go longer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="specifications-and-feedback-loops"&gt;Specifications and feedback loops&lt;/h4&gt;
&lt;p&gt;An interesting aspect of this project design is feedback loops. For agents to work autonomously for long periods of time they need as much useful context about the problem they are solving as possible, combined with effective feedback loops to help them make decisions.&lt;/p&gt;
&lt;p&gt;The FastRender repo &lt;a href="https://github.com/wilsonzlin/fastrender/tree/19bf1036105d4eeb8bf3330678b7cb11c1490bdc/specs"&gt;uses git submodules to include relevant specifications&lt;/a&gt;, including csswg-drafts, tc39-ecma262 for JavaScript, whatwg-dom, whatwg-html and more. &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=846s"&gt;14:06&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Feedback loops to the system are very important. Agents are working for very long periods continuously, and without guardrails and feedback to know whether what they're doing is right or wrong it can have a big impact over a long rollout. Specs are definitely an important part—you can see lots of comments in the code base that AI wrote referring specifically to specs that they found in the specs submodules.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;GPT-5.2 is a vision-capable model, and part of the feedback loop for FastRender included taking screenshots of the rendering results and feeding those back into the model:
&lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=983s"&gt;16:23&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In the earlier evolution of this project, when it was just doing the static renderings of screenshots, this was definitely a very explicit thing we taught it to do. And these models are visual models, so they do have that ability. We have progress indicators to tell it to compare the diff against a golden sample.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The strictness of the Rust compiler helped provide a feedback loop as well: &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=952s"&gt;15:52&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The nice thing about Rust is you can get a lot of verification just from compilation, and that is not as available in other languages.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="the-agents-chose-the-dependencies"&gt;The agents chose the dependencies&lt;/h4&gt;
&lt;p&gt;We talked about the &lt;a href="https://github.com/wilsonzlin/fastrender/blob/19bf1036105d4eeb8bf3330678b7cb11c1490bdc/Cargo.toml"&gt;Cargo.toml dependencies&lt;/a&gt; that the project had accumulated, almost all of which had been selected by the agents themselves.&lt;/p&gt;
&lt;p&gt;Some of these, like &lt;a href="https://skia.org/"&gt;Skia&lt;/a&gt; for 2D graphics rendering or &lt;a href="https://github.com/harfbuzz/harfbuzz"&gt;HarfBuzz&lt;/a&gt; for text shaping, were obvious choices. Others such as &lt;a href="https://github.com/DioxusLabs/taffy"&gt;Taffy&lt;/a&gt; felt like they might go against the from-scratch goals of the project, since that library implements CSS flexbox and grid layout algorithms directly. This was not an intended outcome. &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=1673s"&gt;27:53&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Similarly these are dependencies that the agent picked to use for small parts of the engine and perhaps should have actually implemented itself. I think this reflects on the importance of the instructions, because I actually never encoded specifically the level of dependencies we should be implementing ourselves.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The agents vendored in Taffy and &lt;a href="https://github.com/wilsonzlin/fastrender/commits/main/vendor/taffy"&gt;applied a stream of changes&lt;/a&gt; to that vendored copy.
&lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=1878s"&gt;31:18&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It's currently vendored. And as the agents work on it, they do make changes to it. This was actually an artifact from the very early days of the project before it was a fully fledged browser... it's implementing things like the flex and grid layers, but there are other layout methods like inline, block, and table, and in our new experiment, we're removing that completely.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The inclusion of QuickJS despite the presence of a home-grown ecma-rs implementation has a fun origin story:
&lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=2115s"&gt;35:15&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I believe it mentioned that it pulled in the QuickJS because it knew that other agents were working on the JavaScript engine, and it needed to unblock itself quickly. [...]&lt;/p&gt;
&lt;p&gt;It was like, eventually, once that's finished, let's remove it and replace with the proper engine.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I love how similar this is to the dynamics of a large-scale human engineering team, where you could absolutely see one engineer getting frustrated at another team not having delivered yet and unblocking themselves by pulling in a third-party library.&lt;/p&gt;
&lt;h4 id="intermittent-errors-are-ok-actually"&gt;Intermittent errors are OK, actually&lt;/h4&gt;
&lt;p&gt;Here's something I found really surprising: the agents were allowed to introduce small errors into the codebase as they worked! &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=2382s"&gt;39:42&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;One of the trade-offs was: if you wanted every single commit to be a hundred percent perfect, make sure it can always compile every time, that might be a synchronization bottleneck. [...]&lt;/p&gt;
&lt;p&gt;Especially as you break up the system into more modularized aspects, you can see that errors get introduced, but small errors, right? An API change or some syntax error, but then they get fixed really quickly after a few commits. So there's a little bit of slack in the system to allow these temporary errors so that the overall system can continue to make progress at a really high throughput. [...]&lt;/p&gt;
&lt;p&gt;People may say, well, that's not correct code. But it's not that the errors are accumulating. It's a stable rate of errors. [...] That seems like a worthwhile trade-off.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you're going to have thousands of agents working in parallel optimizing for throughput over correctness turns out to be a strategy worth exploring.&lt;/p&gt;
&lt;h4 id="a-single-engineer-plus-a-swarm-of-agents-in-january-2026"&gt;A single engineer plus a swarm of agents in January 2026&lt;/h4&gt;
&lt;p&gt;The thing I find most interesting about FastRender is how it demonstrates the extreme edge of what a single engineer can achieve in early 2026 with the assistance of a swarm of agents.&lt;/p&gt;
&lt;p&gt;FastRender may not be a production-ready browser, but it represents over a million lines of Rust code, written in a few weeks, that can already render real web pages to a usable degree.&lt;/p&gt;
&lt;p&gt;A browser really is the ideal research project to experiment with this new, weirdly shaped form of software engineering.&lt;/p&gt;
&lt;p&gt;I asked Wilson how much mental effort he had invested in browser rendering compared to agent co-ordination. &lt;a href="https://www.youtube.com/watch?v=bKrAcTf2pL4&amp;amp;t=694s"&gt;11:34&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The browser and this project were co-developed and very symbiotic, only because the browser was a very useful objective for us to measure and iterate the progress of the harness. The goal was to iterate on and research the multi-agent harness—the browser was just the research example or objective.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;FastRender is effectively using a full browser rendering engine as a "hello world" exercise for multi-agent coordination!&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/browsers"&gt;browsers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/youtube"&gt;youtube&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/coding-agents"&gt;coding-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/cursor"&gt;cursor&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/parallel-agents"&gt;parallel-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/browser-challenge"&gt;browser-challenge&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="browsers"/><category term="youtube"/><category term="ai"/><category term="rust"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="coding-agents"/><category term="cursor"/><category term="parallel-agents"/><category term="browser-challenge"/></entry><entry><title>Scaling long-running autonomous coding</title><link href="https://simonwillison.net/2026/Jan/19/scaling-long-running-autonomous-coding/#atom-tag" rel="alternate"/><published>2026-01-19T05:12:51+00:00</published><updated>2026-01-19T05:12:51+00:00</updated><id>https://simonwillison.net/2026/Jan/19/scaling-long-running-autonomous-coding/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://cursor.com/blog/scaling-agents"&gt;Scaling long-running autonomous coding&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Wilson Lin at Cursor has been doing some experiments to see how far you can push a large fleet of "autonomous" coding agents:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This post describes what we've learned from running hundreds of concurrent agents on a single project, coordinating their work, and watching them write over a million lines of code and trillions of tokens.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;They ended up running planners and sub-planners to create tasks, then having workers execute on those tasks - similar to how Claude Code uses sub-agents. Each cycle ended with a judge agent deciding if the project was completed or not.&lt;/p&gt;
&lt;p&gt;In my predictions for 2026 &lt;a href="https://simonwillison.net/2026/Jan/8/llm-predictions-for-2026/#3-years-someone-will-build-a-new-browser-using-mainly-ai-assisted-coding-and-it-won-t-even-be-a-surprise"&gt;the other day&lt;/a&gt; I said that by 2029:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I think somebody will have built a full web browser mostly using AI assistance, and it won’t even be surprising. Rolling a new web browser is one of the most complicated software projects I can imagine[...] the cheat code is the conformance suites. If there are existing tests that it’ll get so much easier.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I may have been off by three years, because Cursor chose "building a web browser from scratch" as their test case for their agent swarm approach:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To test this system, we pointed it at an ambitious goal: building a web browser from scratch. The agents ran for close to a week, writing over 1 million lines of code across 1,000 files. You can explore &lt;a href="https://github.com/wilsonzlin/fastrender"&gt;the source code on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But how well did they do? Their initial announcement a couple of days ago was met with &lt;a href="https://embedding-shapes.github.io/cursor-implied-success-without-evidence/"&gt;unsurprising skepticism&lt;/a&gt;, especially when it became apparent that their GitHub Actions CI was failing and there were no build instructions in the repo.&lt;/p&gt;
&lt;p&gt;It looks like they addressed that within the past 24 hours. The &lt;a href="https://github.com/wilsonzlin/fastrender/blob/main/README.md#build-requirements"&gt;latest README&lt;/a&gt; includes build instructions which I followed on macOS like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /tmp
git clone https://github.com/wilsonzlin/fastrender
cd fastrender
git submodule update --init vendor/ecma-rs
cargo run --release --features browser_ui --bin browser
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This got me a working browser window! Here are screenshots I took of google.com and my own website:&lt;/p&gt;
&lt;p&gt;&lt;img alt="The browser chrome is neat but has a garbled tab name at the top. The Google homepage looks mostly correct but the buttons are not styled correctly and the Google Search one has a huge plus icon floating near it." src="https://static.simonwillison.net/static/2026/cursor-google.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="My blog looks mostly correct, but the right closing quotation mark on a quotation (which is implemented as a background image on the final paragraph) is displayed incorrectly multiple times." src="https://static.simonwillison.net/static/2026/cursor-simonwillison.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Honestly those are very impressive! You can tell they're not just wrapping an existing rendering engine because of those very obvious rendering glitches, but the pages are legible and look mostly correct.&lt;/p&gt;
&lt;p&gt;The FastRender repo even uses Git submodules &lt;a href="https://github.com/wilsonzlin/fastrender/tree/main/specs"&gt;to include various WhatWG and CSS-WG specifications&lt;/a&gt; in the repo, which is a smart way to make sure the agents have access to the reference materials that they might need.&lt;/p&gt;
&lt;p&gt;This is the second attempt I've seen at building a full web browser using AI-assisted coding in the past two weeks - the first was &lt;a href="https://github.com/hiwavebrowser/hiwave"&gt;HiWave browser&lt;/a&gt;, a new browser engine in Rust first announced &lt;a href="https://www.reddit.com/r/Anthropic/comments/1q4xfm0/over_christmas_break_i_wrote_a_fully_functional/"&gt;in this Reddit thread&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When I made my 2029 prediction this is more-or-less the quality of result I had in mind. I don't think we'll see projects of this nature compete with Chrome or Firefox or WebKit any time soon but I have to admit I'm very surprised to see something this capable emerge so quickly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 23rd January 2026&lt;/strong&gt;: I recorded a 47 minute conversation with Wilson about this project and published it on YouTube. Here's &lt;a href="https://simonwillison.net/2026/Jan/23/fastrender/"&gt;the video and accompanying highlights&lt;/a&gt;.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/browsers"&gt;browsers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/coding-agents"&gt;coding-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/cursor"&gt;cursor&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/parallel-agents"&gt;parallel-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/conformance-suites"&gt;conformance-suites&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/browser-challenge"&gt;browser-challenge&lt;/a&gt;&lt;/p&gt;



</summary><category term="browsers"/><category term="ai"/><category term="rust"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="coding-agents"/><category term="cursor"/><category term="parallel-agents"/><category term="conformance-suites"/><category term="browser-challenge"/></entry><entry><title>How uv got so fast</title><link href="https://simonwillison.net/2025/Dec/26/how-uv-got-so-fast/#atom-tag" rel="alternate"/><published>2025-12-26T23:43:15+00:00</published><updated>2025-12-26T23:43:15+00:00</updated><id>https://simonwillison.net/2025/Dec/26/how-uv-got-so-fast/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://nesbitt.io/2025/12/26/how-uv-got-so-fast.html"&gt;How uv got so fast&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Andrew Nesbitt provides an insightful teardown of why &lt;a href="https://github.com/astral-sh/uv"&gt;uv&lt;/a&gt; is so much faster than &lt;code&gt;pip&lt;/code&gt;. It's not nearly as simple as just "they rewrote it in Rust" - &lt;code&gt;uv&lt;/code&gt; gets to skip a huge amount of Python packaging history (which &lt;code&gt;pip&lt;/code&gt; needs to implement for backwards compatibility) and benefits enormously from work over recent years that makes it possible to resolve dependencies across most packages without having to execute the code in &lt;code&gt;setup.py&lt;/code&gt; using a Python interpreter.&lt;/p&gt;
&lt;p&gt;Two notes that caught my eye that I hadn't understood before:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HTTP range requests for metadata.&lt;/strong&gt; &lt;a href="https://packaging.python.org/en/latest/specifications/binary-distribution-format/"&gt;Wheel files&lt;/a&gt; are zip archives, and zip archives put their file listing at the end. uv tries PEP 658 metadata first, falls back to HTTP range requests for the zip central directory, then full wheel download, then building from source. Each step is slower and riskier. The design makes the fast path cover 99% of cases. None of this requires Rust.&lt;/p&gt;
&lt;p&gt;[...]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Compact version representation&lt;/strong&gt;. uv packs versions into u64 integers where possible, making comparison and hashing fast. Over 90% of versions fit in one u64. This is micro-optimization that compounds across millions of comparisons.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I wanted to learn more about these tricks, so I fired up &lt;a href="https://simonwillison.net/2025/Nov/6/async-code-research/"&gt;an asynchronous research task&lt;/a&gt; and told it to checkout the &lt;code&gt;astral-sh/uv&lt;/code&gt; repo, find the Rust code for both of those features and try porting it to Python to help me understand how it works.&lt;/p&gt;
&lt;p&gt;Here's &lt;a href="https://github.com/simonw/research/tree/main/http-range-wheel-metadata"&gt;the report that it wrote for me&lt;/a&gt;, the &lt;a href="https://github.com/simonw/research/pull/57"&gt;prompts I used&lt;/a&gt; and the &lt;a href="https://gistpreview.github.io/?0f04e4d1a240bfc3065df5082b629884/index.html"&gt;Claude Code transcript&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can try &lt;a href="https://github.com/simonw/research/blob/main/http-range-wheel-metadata/wheel_metadata.py"&gt;the script&lt;/a&gt; it wrote for extracting metadata from a wheel using HTTP range requests like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;uv run --with httpx https://raw.githubusercontent.com/simonw/research/refs/heads/main/http-range-wheel-metadata/wheel_metadata.py https://files.pythonhosted.org/packages/8b/04/ef95b67e1ff59c080b2effd1a9a96984d6953f667c91dfe9d77c838fc956/playwright-1.57.0-py3-none-macosx_11_0_arm64.whl -v&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The Playwright wheel there is ~40MB. Adding &lt;code&gt;-v&lt;/code&gt; at the end causes the script to spit out verbose details of how it fetched the data - &lt;a href="https://gist.github.com/simonw/a5ef83b6e4605d2577febb43fa9ad018"&gt;which looks like this&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Key extract from that output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[1] HEAD request to get file size...
    File size: 40,775,575 bytes
[2] Fetching last 16,384 bytes (EOCD + central directory)...
    Received 16,384 bytes
[3] Parsed EOCD:
    Central directory offset: 40,731,572
    Central directory size: 43,981
    Total entries: 453
[4] Fetching complete central directory...
    ...
[6] Found METADATA: playwright-1.57.0.dist-info/METADATA
    Offset: 40,706,744
    Compressed size: 1,286
    Compression method: 8
[7] Fetching METADATA content (2,376 bytes)...
[8] Decompressed METADATA: 3,453 bytes

Total bytes fetched: 18,760 / 40,775,575 (100.0% savings)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The section of the report &lt;a href="https://github.com/simonw/research/tree/main/http-range-wheel-metadata#bonus-compact-version-representation"&gt;on compact version representation&lt;/a&gt; is interesting too. Here's how it illustrates sorting version numbers correctly based on their custom u64 representation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Sorted order (by integer comparison of packed u64):
  1.0.0a1 (repr=0x0001000000200001)
  1.0.0b1 (repr=0x0001000000300001)
  1.0.0rc1 (repr=0x0001000000400001)
  1.0.0 (repr=0x0001000000500000)
  1.0.0.post1 (repr=0x0001000000700001)
  1.0.1 (repr=0x0001000100500000)
  2.0.0.dev1 (repr=0x0002000000100001)
  2.0.0 (repr=0x0002000000500000)
&lt;/code&gt;&lt;/pre&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/performance"&gt;performance&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/uv"&gt;uv&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/http-range-requests"&gt;http-range-requests&lt;/a&gt;&lt;/p&gt;



</summary><category term="performance"/><category term="python"/><category term="rust"/><category term="uv"/><category term="http-range-requests"/></entry><entry><title>Quoting OpenAI Codex CLI</title><link href="https://simonwillison.net/2025/Dec/13/openai-codex-cli/#atom-tag" rel="alternate"/><published>2025-12-13T03:47:43+00:00</published><updated>2025-12-13T03:47:43+00:00</updated><id>https://simonwillison.net/2025/Dec/13/openai-codex-cli/#atom-tag</id><summary type="html">
    &lt;blockquote cite="https://github.com/openai/codex/blob/ad7b9d63c326d5c92049abd16f9f5fb64a573a69/codex-rs/core/src/skills/render.rs#L20-L39"&gt;&lt;p&gt;How to use a skill (progressive disclosure):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;After deciding to use a skill, open its &lt;code&gt;SKILL.md&lt;/code&gt;. Read only enough to follow the workflow.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;SKILL.md&lt;/code&gt; points to extra folders such as &lt;code&gt;references/&lt;/code&gt;, load only the specific files needed for the request; don't bulk-load everything.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;scripts/&lt;/code&gt; exist, prefer running or patching them instead of retyping large code blocks.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;assets/&lt;/code&gt; or templates exist, reuse them instead of recreating from scratch.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;Description as trigger: The YAML &lt;code&gt;description&lt;/code&gt; in &lt;code&gt;SKILL.md&lt;/code&gt; is the primary trigger signal; rely on it to decide applicability. If unsure, ask a brief clarification before proceeding.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://github.com/openai/codex/blob/ad7b9d63c326d5c92049abd16f9f5fb64a573a69/codex-rs/core/src/skills/render.rs#L20-L39"&gt;OpenAI Codex CLI&lt;/a&gt;, core/src/skills/render.rs, &lt;a href="https://gist.github.com/simonw/25f2c3a9e350274bc2b76a79bc8ae8b2"&gt;full prompt&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/skills"&gt;skills&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/openai"&gt;openai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/codex-cli"&gt;codex-cli&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/prompt-engineering"&gt;prompt-engineering&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;&lt;/p&gt;



</summary><category term="skills"/><category term="openai"/><category term="ai"/><category term="llms"/><category term="codex-cli"/><category term="prompt-engineering"/><category term="rust"/><category term="generative-ai"/></entry><entry><title>Thoughts on Go vs. Rust vs. Zig</title><link href="https://simonwillison.net/2025/Dec/5/go-vs-rust-vs-zig/#atom-tag" rel="alternate"/><published>2025-12-05T04:28:05+00:00</published><updated>2025-12-05T04:28:05+00:00</updated><id>https://simonwillison.net/2025/Dec/5/go-vs-rust-vs-zig/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://sinclairtarget.com/blog/2025/08/thoughts-on-go-vs.-rust-vs.-zig/"&gt;Thoughts on Go vs. Rust vs. Zig&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Thoughtful commentary on Go, Rust, and Zig by Sinclair Target. I haven't seen a single comparison that covers all three before and I learned a lot from reading this.&lt;/p&gt;
&lt;p&gt;One thing that I hadn't noticed before is that none of these three languages implement class-based OOP.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=46153466"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/go"&gt;go&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/object-oriented-programming"&gt;object-oriented-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/programming-languages"&gt;programming-languages&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/zig"&gt;zig&lt;/a&gt;&lt;/p&gt;



</summary><category term="go"/><category term="object-oriented-programming"/><category term="programming-languages"/><category term="rust"/><category term="zig"/></entry><entry><title>Quoting Matthew Prince</title><link href="https://simonwillison.net/2025/Nov/19/matthew-prince/#atom-tag" rel="alternate"/><published>2025-11-19T08:02:36+00:00</published><updated>2025-11-19T08:02:36+00:00</updated><id>https://simonwillison.net/2025/Nov/19/matthew-prince/#atom-tag</id><summary type="html">
    &lt;blockquote cite="https://blog.cloudflare.com/18-november-2025-outage/"&gt;&lt;p&gt;Cloudflare's network began experiencing significant failures to deliver core network traffic [...] triggered by a change to one of our database systems' permissions which caused the database to output multiple entries into a “feature file” used by our Bot Management system. That feature file, in turn, doubled in size. The larger-than-expected feature file was then propagated to all the machines that make up our network. [...] The software had a limit on the size of the feature file that was below its doubled size. That caused the software to fail. [...]&lt;/p&gt;
&lt;p&gt;This resulted in the following panic which in turn resulted in a 5xx error:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;thread fl2_worker_thread panicked: called Result::unwrap() on an Err value&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://blog.cloudflare.com/18-november-2025-outage/"&gt;Matthew Prince&lt;/a&gt;, Cloudflare outage on November 18, 2025, &lt;a href="https://news.ycombinator.com/item?id=45973709#45974320"&gt;see also this comment&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/scaling"&gt;scaling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/postmortem"&gt;postmortem&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/cloudflare"&gt;cloudflare&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;&lt;/p&gt;



</summary><category term="scaling"/><category term="postmortem"/><category term="cloudflare"/><category term="rust"/></entry><entry><title>Reverse engineering Codex CLI to get GPT-5-Codex-Mini to draw me a pelican</title><link href="https://simonwillison.net/2025/Nov/9/gpt-5-codex-mini/#atom-tag" rel="alternate"/><published>2025-11-09T03:31:34+00:00</published><updated>2025-11-09T03:31:34+00:00</updated><id>https://simonwillison.net/2025/Nov/9/gpt-5-codex-mini/#atom-tag</id><summary type="html">
    &lt;p&gt;OpenAI partially released a new model yesterday called GPT-5-Codex-Mini, which they &lt;a href="https://x.com/OpenAIDevs/status/1986861734619947305"&gt;describe&lt;/a&gt; as "a more compact and cost-efficient version of GPT-5-Codex". It's currently only available via their Codex CLI tool and VS Code extension, with proper API access "&lt;a href="https://x.com/OpenAIDevs/status/1986861736041853368"&gt;coming soon&lt;/a&gt;". I decided to use Codex to reverse engineer the Codex CLI tool and give me the ability to prompt the new model directly.&lt;/p&gt;
&lt;p&gt;I made &lt;a href="https://www.youtube.com/watch?v=9o1_DL9uNlM"&gt;a video&lt;/a&gt; talking through my progress and demonstrating the final results.&lt;/p&gt;

&lt;p&gt;&lt;lite-youtube videoid="9o1_DL9uNlM" js-api="js-api" title="Reverse engineering Codex CLI to get GPT-5-Codex-Mini to draw me a pelican" playlabel="Play: Reverse engineering Codex CLI to get GPT-5-Codex-Mini to draw me a pelican"&gt; &lt;/lite-youtube&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://simonwillison.net/2025/Nov/9/gpt-5-codex-mini/#this-is-a-little-bit-cheeky"&gt;This is a little bit cheeky&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://simonwillison.net/2025/Nov/9/gpt-5-codex-mini/#codex-cli-is-written-in-rust"&gt;Codex CLI is written in Rust&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://simonwillison.net/2025/Nov/9/gpt-5-codex-mini/#iterating-on-the-code"&gt;Iterating on the code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://simonwillison.net/2025/Nov/9/gpt-5-codex-mini/#let-s-draw-some-pelicans"&gt;Let's draw some pelicans&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://simonwillison.net/2025/Nov/9/gpt-5-codex-mini/#bonus-the-debug-option"&gt;Bonus: the --debug option&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id="this-is-a-little-bit-cheeky"&gt;This is a little bit cheeky&lt;/h4&gt;
&lt;p&gt;OpenAI clearly don't intend for people to access this model directly just yet. It's available exclusively through Codex CLI which is a privileged application - it gets to access a special backend API endpoint that's not publicly documented, and it uses a special authentication mechanism that bills usage directly to the user's existing ChatGPT account.&lt;/p&gt;
&lt;p&gt;I figured reverse-engineering that API directly would be somewhat impolite. But... Codex CLI is an open source project released under an Apache 2.0 license. How about upgrading that to let me run my own prompts through its existing API mechanisms instead?&lt;/p&gt;
&lt;p&gt;This felt like a somewhat absurd loophole, and I couldn't resist trying it out and seeing what happened.&lt;/p&gt;
&lt;h4 id="codex-cli-is-written-in-rust"&gt;Codex CLI is written in Rust&lt;/h4&gt;
&lt;p&gt;The &lt;a href="https://github.com/openai/codex"&gt;openai/codex&lt;/a&gt; repository contains the source code for the Codex CLI tool, which OpenAI rewrote in Rust just a few months ago.&lt;/p&gt;
&lt;p&gt;I don't know much Rust at all.&lt;/p&gt;
&lt;p&gt;I made my own clone on GitHub and checked it out locally:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;git clone git@github.com:simonw/codex
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; codex&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then I fired up Codex itself (in dangerous mode, because I like living dangerously):&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;codex --dangerously-bypass-approvals-and-sandbox&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And ran this prompt:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Figure out how to build the rust version of this tool and then build it&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This worked. It churned away for a bit and figured out how to build itself. This is a useful starting point for a project like this - in figuring out the compile step the coding agent gets seeded with a little bit of relevant information about the project, and if it can compile that means it can later partially test the code it is writing while it works.&lt;/p&gt;
&lt;p&gt;Once the compile had succeeded I fed it the design for the new feature I wanted:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Add a new sub-command to the Rust tool called "codex prompt"&lt;/p&gt;
&lt;p&gt;codex prompt "prompt goes here" - this runs the given prompt directly against the OpenAI API that Codex uses, with the same code path and authentication credentials as the rest of Codex.&lt;/p&gt;
&lt;p&gt;codex prompt -m &amp;lt;model_name&amp;gt; "prompt goes here" - same again but lets you set the model&lt;/p&gt;
&lt;p&gt;codex prompt "prompt goes here" -s/--system "system prompt goes here" - runs with a custom system/developer message&lt;/p&gt;
&lt;p&gt;codex prompt --models - this lists all available models that can be used with the "codex prompt" command&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My design for this new sub-command is lifted directly from my own &lt;a href="https://llm.datasette.io/en/stable/help.html#llm-prompt-help"&gt;llm command&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id="iterating-on-the-code"&gt;Iterating on the code&lt;/h4&gt;
&lt;p&gt;Codex got to work. I've &lt;a href="https://gistpreview.github.io/?ddabbff092bdd658e06d8a2e8f142098"&gt;shared the full transcript here&lt;/a&gt; (using the tool &lt;a href="https://simonwillison.net/2025/Oct/23/claude-code-for-web-video/"&gt;I described here&lt;/a&gt;), but this TODO list it made itself is a useful summary of what it decided to do:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Updated Plan
└ ✔ Inspect CLI structure and relevant core utilities for sending prompts and listing models
  ✔ Implement new `codex prompt` subcommand (CLI plumbing + command handler)
  ✔ Format, lint, and test (`just fmt`, `just fix -p codex-cli`, `cargo test -p codex-cli`)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I like that it figured out &lt;a href="https://github.com/openai/codex/blob/a47181e471b6efe55e95f9858c913fc89a3a44fa/codex-rs/justfile"&gt;the justfile&lt;/a&gt; in the repo and decided to use it to run formatting and linting commands without me needing to tell it to. (Update: it turns out that was dictated by the &lt;a href="https://github.com/openai/codex/blob/f8b30af6dc275b3e64de5f1987e6cafe604cb72a/AGENTS.md"&gt;AGENTS.md&lt;/a&gt; file.)&lt;/p&gt;
&lt;p&gt;I tried running the first version of the code it wrote like this:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;./target/debug/codex prompt &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;Generate an SVG of a pelican riding a bicycle&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; -m gpt-5-codex-mini&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;... and it didn't quite work. I got this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(reasoning summary) **Seeking
(reasoning summary)  instructions
(reasoning summary)  and
(reasoning summary)  sandbox
(reasoning summary)  info
(reasoning summary) **
(reasoning summary) **Dec
(reasoning summary) iding
(reasoning summary)  on
(reasoning summary)  SVG
(reasoning summary)  creation
(reasoning summary)  approach
(reasoning summary) **
(reasoning summary) **Checking
(reasoning summary)  current
(reasoning summary)  directory
(reasoning summary) **
(reasoning summary) **Preparing
(reasoning summary)  to
(reasoning summary)  check
(reasoning summary)  current
(reasoning summary)  directory
(reasoning summary) **
I�m ready to help�what would you like me to do next?I�m ready to help�what would you like me to do next?
Token usage: total=2459 input=2374 cached_input=0 output=85 reasoning_output=64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that it DID think about SVG creation, but then decided it should look at the current directory. This isn't what I want - it appeared to be running in Codex's normal mode with a system prompt telling it to edit files on disk. I wanted it to respond to the prompt without acting as if it had a full workspace available to it.&lt;/p&gt;
&lt;p&gt;I prompted it again, pasting in the broken output:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;this did not seem to work - here is what happened - note that the reasoning summary comes out on a lot of lines when I would rather it streams out to stderr on the same line (flushing constantly) - and then despite the reasoning summary thinking about pelican on SVG it did not actually act on that and display the result, which is very surprising. [pasted content]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It churned for a bit more, but from the output it looked like it was still trying to include Codex-specific tools and workspace information. So I said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that this new 'codex prompt' command should NOT be able to execute any tools at all, and should not have to think about the workspace or sandbox - it should send a single prompt with no tools and then stream and display a response and then stop.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This got me a new build, but when I ran it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Error: unexpected status 400 Bad Request: {"detail":"Instructions are not valid"}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;My guess is that OpenAI's custom backend API for Codex doesn't like it if you attempt to call it &lt;em&gt;without&lt;/em&gt; passing in the expected instructions. Fair enough!&lt;/p&gt;
&lt;p&gt;Rather than paste that error in I got Codex to try the command itself, so it could see the error:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You try running this and see what happens: ./target/debug/codex prompt 'Generate an SVG of a pelican riding a bicycle'&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Codex switched back to the default instructions. From its reply:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;cli/src/prompt_cmd.rs#L1-L320&lt;/code&gt; now forces a tool-free request: we keep the workspace defaults, inject a lightweight system/developer message (“don’t run tools”), disable apply_patch/web search via config overrides, and build the outbound prompt as just that system span plus the user text.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I guess that will have to do. I asked for one more feature:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Add a --debug option to the codex prompt command which causes the full JSON request and response to be printed to stderr, plus the URL that is being accessed and the HTTP verb&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;... and we're ready to try this thing out!&lt;/p&gt;
&lt;p&gt;Notably I haven't written a single line of Rust myself here and paid almost no attention to what it was actually doing. My main contribution was to run the binary every now and then to see if it was doing what I needed yet.&lt;/p&gt;
&lt;p&gt;I've pushed the working code to &lt;a href="https://github.com/simonw/codex/compare/a47181e471b6efe55e95f9858c913fc89a3a44fa...ae5f98a9248a8edb5d3c53261273a482fc0b5306"&gt;a prompt-subcommand branch in my repo&lt;/a&gt; if you want to take a look and see how it all works.&lt;/p&gt;

&lt;h4 id="let-s-draw-some-pelicans"&gt;Let's draw some pelicans&lt;/h4&gt;
&lt;p&gt;With the final version of the code built, I drew some pelicans. Here's the &lt;a href="https://gistpreview.github.io/?a11f9ac456d2b2bc3715ba900ef1203d"&gt;full terminal transcript&lt;/a&gt;, but here are some highlights.&lt;/p&gt;
&lt;p&gt;This is with the default GPT-5-Codex model:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;./target/debug/codex prompt &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Generate an SVG of a pelican riding a bicycle&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I pasted it into my &lt;a href="https://tools.simonwillison.net/svg-render"&gt;tools.simonwillison.net/svg-render&lt;/a&gt; tool and got the following:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.simonwillison.net/static/2025/codex-hacking-default.png" alt="It's a dumpy little pelican with a weird face, not particularly great" style="max-width: 100%;" /&gt;&lt;/p&gt;
&lt;p&gt;I ran it again for GPT-5:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;./target/debug/codex prompt &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Generate an SVG of a pelican riding a bicycle&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; -m gpt-5&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src="https://static.simonwillison.net/static/2025/codex-hacking-gpt-5.png" alt="Much better bicycle, pelican is a bit line-drawing-ish but does have the necessary parts in the right places" style="max-width: 100%;" /&gt;&lt;/p&gt;
&lt;p&gt;And now the moment of truth... GPT-5 Codex Mini!&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;./target/debug/codex prompt &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Generate an SVG of a pelican riding a bicycle&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; -m gpt-5-codex-mini&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src="https://static.simonwillison.net/static/2025/codex-hacking-mini.png" alt="This is terrible. The pelican is an abstract collection of shapes, the bicycle is likewise very messed up" style="max-width: 100%;" /&gt;&lt;/p&gt;
&lt;p&gt;I don't think I'll be adding that one to my SVG drawing toolkit any time soon.&lt;/p&gt;

&lt;h4 id="bonus-the-debug-option"&gt;Bonus: the --debug option&lt;/h4&gt;
&lt;p&gt;I had Codex add a &lt;code&gt;--debug&lt;/code&gt; option to help me see exactly what was going on.&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;./target/debug/codex prompt -m gpt-5-codex-mini &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Generate an SVG of a pelican riding a bicycle&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; --debug&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The output starts like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[codex prompt debug] POST https://chatgpt.com/backend-api/codex/responses
[codex prompt debug] Request JSON:
&lt;/code&gt;&lt;/pre&gt;
&lt;div class="highlight highlight-source-json"&gt;&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"model"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;gpt-5-codex-mini&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"instructions"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;You are Codex, based on GPT-5. You are running as a coding agent ...&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"input"&lt;/span&gt;: [
    {
      &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;message&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"role"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;developer&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"content"&lt;/span&gt;: [
        {
          &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;input_text&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
          &lt;span class="pl-ent"&gt;"text"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;You are a helpful assistant. Respond directly to the user request without running tools or shell commands.&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
        }
      ]
    },
    {
      &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;message&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"role"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;user&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
      &lt;span class="pl-ent"&gt;"content"&lt;/span&gt;: [
        {
          &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;input_text&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
          &lt;span class="pl-ent"&gt;"text"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Generate an SVG of a pelican riding a bicycle&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
        }
      ]
    }
  ],
  &lt;span class="pl-ent"&gt;"tools"&lt;/span&gt;: [],
  &lt;span class="pl-ent"&gt;"tool_choice"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;auto&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"parallel_tool_calls"&lt;/span&gt;: &lt;span class="pl-c1"&gt;false&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"reasoning"&lt;/span&gt;: {
    &lt;span class="pl-ent"&gt;"summary"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;auto&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
  },
  &lt;span class="pl-ent"&gt;"store"&lt;/span&gt;: &lt;span class="pl-c1"&gt;false&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"stream"&lt;/span&gt;: &lt;span class="pl-c1"&gt;true&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"include"&lt;/span&gt;: [
    &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;reasoning.encrypted_content&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
  ],
  &lt;span class="pl-ent"&gt;"prompt_cache_key"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;019a66bf-3e2c-7412-b05e-db9b90bbad6e&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This reveals that OpenAI's private API endpoint for Codex CLI is &lt;code&gt;https://chatgpt.com/backend-api/codex/responses&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Also interesting is how the &lt;code&gt;"instructions"&lt;/code&gt; key (truncated above, &lt;a href="https://gist.github.com/simonw/996388ecf785ad54de479315bd4d33b7"&gt;full copy here&lt;/a&gt;) contains the default instructions, without which the API appears not to work - but it also shows that you can send a message with &lt;code&gt;role="developer"&lt;/code&gt; in advance of your user prompt.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/openai"&gt;openai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pelican-riding-a-bicycle"&gt;pelican-riding-a-bicycle&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llm-release"&gt;llm-release&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/vibe-coding"&gt;vibe-coding&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/coding-agents"&gt;coding-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gpt-5"&gt;gpt-5&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/codex-cli"&gt;codex-cli&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gpt-codex"&gt;gpt-codex&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="ai"/><category term="rust"/><category term="openai"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="pelican-riding-a-bicycle"/><category term="llm-release"/><category term="vibe-coding"/><category term="coding-agents"/><category term="gpt-5"/><category term="codex-cli"/><category term="gpt-codex"/></entry><entry><title>Quoting Julian Andres Klode</title><link href="https://simonwillison.net/2025/Nov/1/debian/#atom-tag" rel="alternate"/><published>2025-11-01T17:34:34+00:00</published><updated>2025-11-01T17:34:34+00:00</updated><id>https://simonwillison.net/2025/Nov/1/debian/#atom-tag</id><summary type="html">
    &lt;blockquote cite="https://lists.debian.org/debian-devel/2025/10/msg00285.html"&gt;&lt;p&gt;I plan to introduce hard Rust dependencies and Rust code into
APT, no earlier than May 2026. This extends at first to the
Rust compiler and standard library, and the Sequoia ecosystem.&lt;/p&gt;
&lt;p&gt;In particular, our code to parse .deb, .ar, .tar, and the
HTTP signature verification code would strongly benefit
from memory safe languages and a stronger approach to
unit testing.&lt;/p&gt;
&lt;p&gt;If you maintain a port without a working Rust toolchain,
please ensure it has one within the next 6 months, or
sunset the port.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://lists.debian.org/debian-devel/2025/10/msg00285.html"&gt;Julian Andres Klode&lt;/a&gt;, debian-devel mailing list&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/open-source"&gt;open-source&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/debian"&gt;debian&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/linux"&gt;linux&lt;/a&gt;&lt;/p&gt;



</summary><category term="open-source"/><category term="debian"/><category term="rust"/><category term="linux"/></entry><entry><title>nanochat</title><link href="https://simonwillison.net/2025/Oct/13/nanochat/#atom-tag" rel="alternate"/><published>2025-10-13T20:29:58+00:00</published><updated>2025-10-13T20:29:58+00:00</updated><id>https://simonwillison.net/2025/Oct/13/nanochat/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/karpathy/nanochat"&gt;nanochat&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Really interesting new project from Andrej Karpathy, described at length &lt;a href="https://github.com/karpathy/nanochat/discussions/1"&gt;in this discussion post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It provides a full ChatGPT-style LLM, including training, inference and a web Ui, that can be trained for as little as $100:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This repo is a full-stack implementation of an LLM like ChatGPT in a single, clean, minimal, hackable, dependency-lite codebase.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It's around 8,000 lines of code, mostly Python (using PyTorch) plus a little bit of Rust for &lt;a href="https://github.com/karpathy/nanochat/tree/master/rustbpe"&gt;training the tokenizer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Andrej suggests renting a 8XH100 NVIDA node for around $24/ hour to train the model. 4 hours (~$100) is enough to get a model that can hold a conversation - &lt;a href="https://twitter.com/karpathy/status/1977755430093980034"&gt;almost coherent example here&lt;/a&gt;. Run it for 12 hours and you get something that slightly outperforms GPT-2. I'm looking forward to hearing results from longer training runs!&lt;/p&gt;
&lt;p&gt;The resulting model is ~561M parameters, so it should run on almost anything. I've run a 4B model on my iPhone, 561M should easily fit on even an inexpensive Raspberry Pi.&lt;/p&gt;
&lt;p&gt;The model defaults to training on ~24GB from &lt;a href="https://huggingface.co/datasets/karpathy/fineweb-edu-100b-shuffle"&gt;karpathy/fineweb-edu-100b-shuffle&lt;/a&gt; derived from &lt;a href="https://huggingface.co/datasets/HuggingFaceFW/fineweb-edu"&gt;FineWeb-Edu&lt;/a&gt;, and then &lt;a href="https://github.com/karpathy/nanochat/blob/5fd0b138860a76beb60cf099fa46f74191b50941/scripts/mid_train.py"&gt;midtrains&lt;/a&gt; on 568K examples from &lt;a href="https://huggingface.co/datasets/HuggingFaceTB/smol-smoltalk"&gt;SmolTalk&lt;/a&gt; (460K), &lt;a href="https://huggingface.co/datasets/cais/mmlu"&gt;MMLU auxiliary train&lt;/a&gt; (100K), and &lt;a href="https://huggingface.co/datasets/openai/gsm8k"&gt;GSM8K&lt;/a&gt; (8K), followed by &lt;a href="https://github.com/karpathy/nanochat/blob/5fd0b138860a76beb60cf099fa46f74191b50941/scripts/chat_sft.py"&gt;supervised finetuning&lt;/a&gt; on 21.4K examples from &lt;a href="https://huggingface.co/datasets/allenai/ai2_arc#arc-easy-1"&gt;ARC-Easy&lt;/a&gt; (2.3K), &lt;a href="https://huggingface.co/datasets/allenai/ai2_arc#arc-challenge"&gt;ARC-Challenge&lt;/a&gt; (1.1K), &lt;a href="https://huggingface.co/datasets/openai/gsm8k"&gt;GSM8K&lt;/a&gt; (8K), and &lt;a href="https://huggingface.co/datasets/HuggingFaceTB/smol-smoltalk"&gt;SmolTalk&lt;/a&gt; (10K).&lt;/p&gt;
&lt;p&gt;Here's the code for the &lt;a href="https://github.com/karpathy/nanochat/blob/5fd0b138860a76beb60cf099fa46f74191b50941/scripts/chat_web.py"&gt;web server&lt;/a&gt;, which is fronted by this pleasantly succinct vanilla JavaScript &lt;a href="https://github.com/karpathy/nanochat/blob/5fd0b138860a76beb60cf099fa46f74191b50941/nanochat/ui.html"&gt;HTML+JavaScript frontend&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Sam Dobson pushed a build of the model to &lt;a href="https://huggingface.co/sdobson/nanochat"&gt;sdobson/nanochat&lt;/a&gt; on Hugging Face. It's designed to run on CUDA but I pointed Claude Code at a checkout and had it hack around until it figured out how to run it on CPU on macOS, which eventually resulted in &lt;a href="https://gist.github.com/simonw/912623bf00d6c13cc0211508969a100a"&gt;this script&lt;/a&gt; which I've published as a Gist. You should be able to try out the model using uv like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /tmp
git clone https://huggingface.co/sdobson/nanochat
uv run https://gist.githubusercontent.com/simonw/912623bf00d6c13cc0211508969a100a/raw/80f79c6a6f1e1b5d4485368ef3ddafa5ce853131/generate_cpu.py \
--model-dir /tmp/nanochat \
--prompt "Tell me about dogs."
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I got this (truncated because it ran out of tokens):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I'm delighted to share my passion for dogs with you. As a veterinary doctor, I've had the privilege of helping many pet owners care for their furry friends. There's something special about training, about being a part of their lives, and about seeing their faces light up when they see their favorite treats or toys.&lt;/p&gt;
&lt;p&gt;I've had the chance to work with over 1,000 dogs, and I must say, it's a rewarding experience. The bond between owner and pet&lt;/p&gt;
&lt;/blockquote&gt;

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/karpathy/status/1977755427569111362"&gt;@karpathy&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pytorch"&gt;pytorch&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/andrej-karpathy"&gt;andrej-karpathy&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/training-data"&gt;training-data&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/uv"&gt;uv&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gpus"&gt;gpus&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude-code"&gt;claude-code&lt;/a&gt;&lt;/p&gt;



</summary><category term="python"/><category term="ai"/><category term="rust"/><category term="pytorch"/><category term="andrej-karpathy"/><category term="generative-ai"/><category term="llms"/><category term="training-data"/><category term="uv"/><category term="gpus"/><category term="claude-code"/></entry><entry><title>httpjail</title><link href="https://simonwillison.net/2025/Sep/19/httpjail/#atom-tag" rel="alternate"/><published>2025-09-19T21:57:29+00:00</published><updated>2025-09-19T21:57:29+00:00</updated><id>https://simonwillison.net/2025/Sep/19/httpjail/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/coder/httpjail"&gt;httpjail&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Here's a promising new (experimental) project in the sandboxing space from Ammar Bandukwala at &lt;a href="https://coder.com/"&gt;Coder&lt;/a&gt;. &lt;code&gt;httpjail&lt;/code&gt; provides a Rust CLI tool for running an individual process against a custom configured HTTP proxy.&lt;/p&gt;
&lt;p&gt;The initial goal is to help run coding agents like Claude Code and Codex CLI with extra rules governing how they interact with outside services. From Ammar's blog post that introduces the new tool, &lt;a href="https://ammar.io/blog/httpjail"&gt;Fine-grained HTTP filtering for Claude Code&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;httpjail&lt;/code&gt; implements an HTTP(S) interceptor alongside process-level network isolation. Under default configuration, all DNS (udp:53) is permitted and all other non-HTTP(S) traffic is blocked.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;httpjail&lt;/code&gt; rules are either JavaScript expressions or custom programs. This approach makes them far more flexible than traditional rule-oriented firewalls and avoids the learning curve of a DSL.&lt;/p&gt;
&lt;p&gt;Block all HTTP requests other than the LLM API traffic itself:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ httpjail --js "r.host === 'api.anthropic.com'" -- claude "build something great"
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;I tried it out using OpenAI's Codex CLI instead and found this recipe worked:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brew upgrade rust
cargo install httpjail # Drops it in `~/.cargo/bin`
httpjail --js "r.host === 'chatgpt.com'" -- codex
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Within that Codex instance the model ran fine but any attempts to access other URLs (e.g. telling it "&lt;code&gt;Use curl to fetch simonwillison.net&lt;/code&gt;)" failed at the proxy layer.&lt;/p&gt;
&lt;p&gt;This is still at a really early stage but there's a lot I like about this project. Being able to use JavaScript to filter requests via the &lt;code&gt;--js&lt;/code&gt; option is neat (it's using V8 under the hood), and there's also a &lt;code&gt;--sh shellscript&lt;/code&gt; option which instead runs a shell program passing environment variables that can be used to determine if the request should be allowed.&lt;/p&gt;
&lt;p&gt;At a basic level it works by running a proxy server and setting &lt;code&gt;HTTP_PROXY&lt;/code&gt; and &lt;code&gt;HTTPS_PROXY&lt;/code&gt; environment variables so well-behaving software knows how to route requests.&lt;/p&gt;
&lt;p&gt;It can also add a bunch of other layers. On Linux it sets up &lt;a href="https://en.wikipedia.org/wiki/Nftables"&gt;nftables&lt;/a&gt; rules to explicitly deny additional network access. There's also a &lt;code&gt;--docker-run&lt;/code&gt; option which can launch a Docker container with the specified image but first locks that container down to only have network access to the &lt;code&gt;httpjail&lt;/code&gt; proxy server.&lt;/p&gt;
&lt;p&gt;It can intercept, filter and log HTTPS requests too by generating its own certificate and making that available to the underlying process.&lt;/p&gt;
&lt;p&gt;I'm always interested in new approaches to sandboxing, and fine-grained network access is a particularly tricky problem to solve. This looks like a very promising step in that direction - I'm looking forward to seeing how this project continues to evolve.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://ammar.io/blog/httpjail"&gt;Fine-grained HTTP filtering for Claude Code&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/http"&gt;http&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/proxies"&gt;proxies&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sandboxing"&gt;sandboxing&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/security"&gt;security&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/v8"&gt;v8&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude-code"&gt;claude-code&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/codex-cli"&gt;codex-cli&lt;/a&gt;&lt;/p&gt;



</summary><category term="http"/><category term="javascript"/><category term="proxies"/><category term="sandboxing"/><category term="security"/><category term="v8"/><category term="rust"/><category term="claude-code"/><category term="codex-cli"/></entry><entry><title>Geoffrey Huntley is cursed</title><link href="https://simonwillison.net/2025/Sep/9/cursed/#atom-tag" rel="alternate"/><published>2025-09-09T09:31:21+00:00</published><updated>2025-09-09T09:31:21+00:00</updated><id>https://simonwillison.net/2025/Sep/9/cursed/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://ghuntley.com/cursed/"&gt;I ran Claude in a loop for three months, and it created a genz programming language called cursed&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Geoffrey Huntley vibe-coded an entirely new programming language using Claude:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The programming language is called "cursed". It's cursed in its lexical structure, it's cursed in how it was built, it's cursed that this is possible, it's cursed in how cheap this was, and it's cursed through how many times I've sworn at Claude.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Geoffrey's initial prompt:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Hey, can you make me a programming language like Golang but all the lexical keywords are swapped so they're Gen Z slang?&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then he pushed it to keep on iterating over a three month period.&lt;/p&gt;
&lt;p&gt;Here's Hello World:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;vibe main
yeet "vibez"

slay main() {
    vibez.spill("Hello, World!")
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And here's &lt;a href="https://github.com/ghuntley/cursed/blob/ecda33d496e1562e0e02efb25b6936ad94e79b72/test_suite/leetcode_comprehensive_suite/binary_search/704_binary_search_backup.%F0%9F%92%80"&gt;binary search&lt;/a&gt;, part of &lt;a href="https://github.com/ghuntley/cursed/tree/zig/test_suite/leetcode_comprehensive_suite"&gt;17+ LeetCode problems&lt;/a&gt; that run as part of the test suite:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;slay binary_search(nums normie[], target normie) normie {
    sus left normie = 0
    sus right normie = len(nums) - 1    
    bestie (left &amp;lt;= right) {
        sus mid normie = left + (right - left) / 2
        ready (nums[mid] == target) {
            damn mid
        }
        ready (nums[mid] &amp;lt; target) {
            left = mid + 1
        } otherwise {
            right = mid - 1
        }
    }
    damn -1
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a &lt;em&gt;substantial&lt;/em&gt; project. The repository currently has &lt;a href="https://github.com/ghuntley/cursed/commits/zig/"&gt;1,198 commits&lt;/a&gt;. It has both an interpreter mode and a compiler mode, and can compile programs to native binaries (via LLVM) for macOS, Linux and Windows.&lt;/p&gt;
&lt;p&gt;It looks like it was mostly built using Claude running via &lt;a href="https://ampcode.com/"&gt;Sourcegraph's Amp&lt;/a&gt;, which produces &lt;a href="https://github.com/ghuntley/cursed/commit/ec5be8a4c4f6e82f6b93774a9b3b3f88308680dd"&gt;detailed commit messages&lt;/a&gt;. The commits include links to archived Amp sessions but sadly those don't appear to be publicly visible.&lt;/p&gt;
&lt;p&gt;The first version was written in C, then Geoffrey had Claude port it to Rust and then Zig. &lt;a href="https://twitter.com/GeoffreyHuntley/status/1965295152962097550"&gt;His cost estimate&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Technically it costs about 5k usd to build your own compiler now because cursed was implemented first in c, then rust, now zig. So yeah, it’s not one compiler it’s three editions of it. For a total of $14k USD.&lt;/p&gt;
&lt;/blockquote&gt;

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://x.com/GeoffreyHuntley/status/1965258228314636524"&gt;@GeoffreyHuntley&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/c"&gt;c&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/programming-languages"&gt;programming-languages&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/zig"&gt;zig&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/anthropic"&gt;anthropic&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude"&gt;claude&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/vibe-coding"&gt;vibe-coding&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/geoffrey-huntley"&gt;geoffrey-huntley&lt;/a&gt;&lt;/p&gt;



</summary><category term="c"/><category term="programming-languages"/><category term="ai"/><category term="rust"/><category term="zig"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="anthropic"/><category term="claude"/><category term="vibe-coding"/><category term="geoffrey-huntley"/></entry><entry><title>Codex upgrade</title><link href="https://simonwillison.net/2025/Aug/11/codex-upgrade/#atom-tag" rel="alternate"/><published>2025-08-11T16:06:39+00:00</published><updated>2025-08-11T16:06:39+00:00</updated><id>https://simonwillison.net/2025/Aug/11/codex-upgrade/#atom-tag</id><summary type="html">
    &lt;p&gt;If you've been experimenting with OpenAI's &lt;a href="https://github.com/openai/codex"&gt;Codex CLI&lt;/a&gt; and have been frustrated that it's not possible to select text and copy it to the clipboard, at least when running in the Mac terminal (I genuinely didn't know it was possible to build a terminal app that disabled copy and paste) you should know that they fixed that in &lt;a href="https://github.com/openai/codex/issues/1247"&gt;this issue&lt;/a&gt; last week.&lt;/p&gt;
&lt;p&gt;The new &lt;a href="https://github.com/openai/codex/releases/tag/rust-v0.20.0"&gt;0.20.0 version&lt;/a&gt; from three days ago also completely removes the old TypeScript codebase in favor of Rust. Even installations via NPM now get the Rust version.&lt;/p&gt;
&lt;p&gt;I originally installed Codex via Homebrew, so I had to run this command to get the updated version:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brew upgrade codex
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another Codex tip: to use GPT-5 (or any other specific OpenAI model) you can run it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export OPENAI_DEFAULT_MODEL="gpt-5"
codex
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;This no longer works, see update below.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I've been using a &lt;code&gt;codex-5&lt;/code&gt; script on my PATH containing this, because sometimes I like to live dangerously!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env zsh
# Usage: codex-5 [additional args passed to `codex`]
export OPENAI_DEFAULT_MODEL="gpt-5"
exec codex --dangerously-bypass-approvals-and-sandbox "$@"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: It looks like GPT-5 is &lt;a href="https://github.com/openai/codex/blob/c61911524d839f5d56842faee0c46f6ef52d4387/codex-rs/core/src/config.rs#L28"&gt;the default model&lt;/a&gt; in v0.20.0 already.&lt;/p&gt;
&lt;p&gt;Also the environment variable I was using no longer does anything, it was &lt;a href="https://github.com/openai/codex/commit/107d2ce4e74618968b2eb7016777121d9529a204#diff-b012ea51eb2b6d23db97b930526379af9c4c119a3e057e55ea29d056326242e0L6"&gt;removed in this commit&lt;/a&gt; (I used Codex Web to &lt;a href="https://chatgpt.com/s/cd_689a252794b081919099d5ade205b41d"&gt;help figure that out&lt;/a&gt;). You can use the &lt;code&gt;-m model_id&lt;/code&gt; command-line option instead.&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/openai"&gt;openai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/coding-agents"&gt;coding-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gpt-5"&gt;gpt-5&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/codex-cli"&gt;codex-cli&lt;/a&gt;&lt;/p&gt;



</summary><category term="ai"/><category term="rust"/><category term="openai"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="coding-agents"/><category term="gpt-5"/><category term="codex-cli"/></entry><entry><title>Shipping WebGPU on Windows in Firefox 141</title><link href="https://simonwillison.net/2025/Jul/16/webgpu-firefox/#atom-tag" rel="alternate"/><published>2025-07-16T13:51:26+00:00</published><updated>2025-07-16T13:51:26+00:00</updated><id>https://simonwillison.net/2025/Jul/16/webgpu-firefox/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://mozillagfx.wordpress.com/2025/07/15/shipping-webgpu-on-windows-in-firefox-141/"&gt;Shipping WebGPU on Windows in Firefox 141&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
WebGPU is coming to Mac and Linux soon as well:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Although Firefox 141 enables WebGPU only on Windows, we plan to ship WebGPU on Mac and Linux in the coming months, and finally on Android. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;From this article I learned that it's already available in &lt;a href="https://www.mozilla.org/en-US/firefox/channel/desktop/"&gt;Firefox Nightly&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that WebGPU has been available in Firefox Nightly on all platforms other than Android for quite some time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I tried the most recent Nightly on my Mac and now the &lt;a href="https://huggingface.co/spaces/reach-vb/github-issue-generator-webgpu"&gt;Github Issue Generator running locally w/ SmolLM2 &amp;amp; WebGPU&lt;/a&gt; demo (&lt;a href="https://simonwillison.net/2024/Nov/29/structured-generation-smollm2-webgpu/"&gt;previously&lt;/a&gt;) works! Firefox stable gives me an error message saying "Error: WebGPU is not supported in your current environment, but it is necessary to run the WebLLM engine."&lt;/p&gt;
&lt;p&gt;The Firefox implementation is based on &lt;a href="https://github.com/gfx-rs/wgpu"&gt;wgpu&lt;/a&gt;, an open source Rust WebGPU library.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=44579317"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/browsers"&gt;browsers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/firefox"&gt;firefox&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/mozilla"&gt;mozilla&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webgpu"&gt;webgpu&lt;/a&gt;&lt;/p&gt;



</summary><category term="browsers"/><category term="firefox"/><category term="mozilla"/><category term="rust"/><category term="webgpu"/></entry><entry><title>crates.io: Trusted Publishing</title><link href="https://simonwillison.net/2025/Jul/12/cratesio-trusted-publishing/#atom-tag" rel="alternate"/><published>2025-07-12T16:12:18+00:00</published><updated>2025-07-12T16:12:18+00:00</updated><id>https://simonwillison.net/2025/Jul/12/cratesio-trusted-publishing/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://blog.rust-lang.org/2025/07/11/crates-io-development-update-2025-07/"&gt;crates.io: Trusted Publishing&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
crates.io is the Rust ecosystem's equivalent of PyPI. Inspired by PyPI's GitHub integration (see &lt;a href="https://til.simonwillison.net/pypi/pypi-releases-from-github"&gt;my TIL&lt;/a&gt;, I use this for dozens of my packages now) they've added a similar feature:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Trusted Publishing eliminates the need for GitHub Actions secrets when publishing crates from your CI/CD pipeline. Instead of managing API tokens, you can now configure which GitHub repository you trust directly on crates.io.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;They're missing one feature that PyPI has: on PyPI you can create a "pending publisher" for your first release. crates.io currently requires the first release to be manual:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To get started with Trusted Publishing, you'll need to publish your first release manually. After that, you can set up trusted publishing for future releases.&lt;/p&gt;
&lt;/blockquote&gt;

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://x.com/charliermarsh/status/1943853345967423506"&gt;@charliermarsh&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/github"&gt;github&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/packaging"&gt;packaging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pypi"&gt;pypi&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;&lt;/p&gt;



</summary><category term="github"/><category term="packaging"/><category term="pypi"/><category term="rust"/></entry><entry><title>Agentic Coding Recommendations</title><link href="https://simonwillison.net/2025/Jun/12/agentic-coding-recommendations/#atom-tag" rel="alternate"/><published>2025-06-12T16:20:51+00:00</published><updated>2025-06-12T16:20:51+00:00</updated><id>https://simonwillison.net/2025/Jun/12/agentic-coding-recommendations/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://lucumr.pocoo.org/2025/6/12/agentic-coding/"&gt;Agentic Coding Recommendations&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
There's a ton of actionable advice on using Claude Code in this new piece from Armin Ronacher. He's getting excellent results from Go, especially having invested a bunch of work in making the various tools (linters, tests, logs, development servers etc) as accessible as possible through documenting them in a Makefile.&lt;/p&gt;
&lt;p&gt;I liked this tip on logging:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In general logging is super important. For instance my app currently has a sign in and register flow that sends an email to the user. In debug mode (which the agent runs in), the email is just logged to stdout. This is crucial! It allows the agent to complete a full sign-in with a remote controlled browser without extra assistance. It knows that emails are being logged thanks to a &lt;code&gt;CLAUDE.md&lt;/code&gt; instruction and it automatically consults the log for the necessary link to click.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Armin also recently shared a &lt;a href="https://www.youtube.com/watch?v=sQYXZCUvpIc"&gt;half hour YouTube video&lt;/a&gt; in which he worked with Claude Code to resolve two medium complexity issues in his &lt;code&gt;minijinja&lt;/code&gt; Rust templating library, resulting in &lt;a href="https://github.com/mitsuhiko/minijinja/pull/805"&gt;PR #805&lt;/a&gt; and &lt;a href="https://github.com/mitsuhiko/minijinja/pull/804"&gt;PR #804&lt;/a&gt;.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://bsky.app/profile/mitsuhiko.at/post/3lrfld3r74k2e"&gt;@mitsuhiko.at&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/armin-ronacher"&gt;armin-ronacher&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/go"&gt;go&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/anthropic"&gt;anthropic&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude"&gt;claude&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/coding-agents"&gt;coding-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude-code"&gt;claude-code&lt;/a&gt;&lt;/p&gt;



</summary><category term="armin-ronacher"/><category term="go"/><category term="ai"/><category term="rust"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="anthropic"/><category term="claude"/><category term="coding-agents"/><category term="claude-code"/></entry><entry><title>astral-sh/ty</title><link href="https://simonwillison.net/2025/May/7/ty/#atom-tag" rel="alternate"/><published>2025-05-07T18:37:33+00:00</published><updated>2025-05-07T18:37:33+00:00</updated><id>https://simonwillison.net/2025/May/7/ty/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/astral-sh/ty"&gt;astral-sh/ty&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Astral have been working on this "extremely fast Python type checker and language server, written in Rust" &lt;a href="https://simonwillison.net/2025/Jan/29/charlie-marsh/"&gt;quietly but in-the-open&lt;/a&gt; for a while now. Here's the first alpha public release - albeit &lt;a href="https://news.ycombinator.com/item?id=43918484#43919354"&gt;not yet announced&lt;/a&gt; - as &lt;a href="https://pypi.org/project/ty/"&gt;ty&lt;/a&gt; on PyPI (nice &lt;a href="https://news.ycombinator.com/item?id=43918484#43920112"&gt;donated&lt;/a&gt; two-letter name!)&lt;/p&gt;
&lt;p&gt;You can try it out via &lt;a href="https://docs.astral.sh/uv/guides/tools/#running-tools"&gt;uvx&lt;/a&gt; like this - run the command in a folder full of Python code and see what comes back:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uvx ty check
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I got zero errors for my recent, simple &lt;a href="https://github.com/simonw/condense-json"&gt;condense-json&lt;/a&gt; library and a &lt;em&gt;ton&lt;/em&gt; of errors for my more mature &lt;a href="https://sqlite-utils.datasette.io/"&gt;sqlite-utils&lt;/a&gt; library - &lt;a href="https://gist.github.com/simonw/a13e1720b03e23783ae668eca7f6f12a"&gt;output here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It really is &lt;em&gt;fast&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /tmp
git clone https://github.com/simonw/sqlite-utils
cd sqlite-utils
time uvx ty check
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reports it running in around a tenth of a second (0.109 total wall time) using multiple CPU cores:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uvx ty check  0.18s user 0.07s system 228% cpu 0.109 total
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running &lt;code&gt;time uvx mypy .&lt;/code&gt; in the same folder (both after first ensuring the underlying tools had been cached) took around 7x longer:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uvx mypy .  0.46s user 0.09s system 74% cpu 0.740 total
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This isn't a fair comparison yet as ty still isn't feature complete in comparison to mypy.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=43918484"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/pypi"&gt;pypi&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/mypy"&gt;mypy&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/uv"&gt;uv&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/astral"&gt;astral&lt;/a&gt;&lt;/p&gt;



</summary><category term="pypi"/><category term="python"/><category term="rust"/><category term="mypy"/><category term="uv"/><category term="astral"/></entry><entry><title>llm-fragments-rust</title><link href="https://simonwillison.net/2025/Apr/11/llm-fragments-rust/#atom-tag" rel="alternate"/><published>2025-04-11T17:36:27+00:00</published><updated>2025-04-11T17:36:27+00:00</updated><id>https://simonwillison.net/2025/Apr/11/llm-fragments-rust/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/huitseeker/llm-fragments-rust"&gt;llm-fragments-rust&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Inspired by Filippo Valsorda's &lt;a href="https://simonwillison.net/2025/Apr/10/llm-fragments-go/"&gt;llm-fragments-go&lt;/a&gt;, Francois Garillot created &lt;code&gt;llm-fragments-rust&lt;/code&gt;, an &lt;a href="https://simonwillison.net/2025/Apr/7/long-context-llm/"&gt;LLM fragments&lt;/a&gt; plugin that lets you pull documentation for any Rust crate directly into a prompt to LLM.&lt;/p&gt;
&lt;p&gt;I really like this example, which uses two fragments to load documentation for two crates at once:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;llm -f rust:rand@0.8.5 -f rust:tokio "How do I generate random numbers asynchronously?"&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;a href="https://github.com/huitseeker/llm-fragments-rust/blob/main/llm_fragments_rust.py"&gt;code&lt;/a&gt; uses some neat tricks: it creates a new Rust project in a temporary directory (similar to how &lt;code&gt;llm-fragments-go&lt;/code&gt; works), adds the crates and uses &lt;code&gt;cargo doc --no-deps --document-private-items&lt;/code&gt; to generate documentation. Then it runs &lt;code&gt;cargo tree --edges features&lt;/code&gt; to add dependency information, and &lt;code&gt;cargo metadata --format-version=1&lt;/code&gt; to include additional metadata about the crate.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/huitseeker/status/1910741742363562325"&gt;@huitseeker&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/plugins"&gt;plugins&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llm"&gt;llm&lt;/a&gt;&lt;/p&gt;



</summary><category term="plugins"/><category term="ai"/><category term="rust"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="llm"/></entry><entry><title>Stop syncing everything</title><link href="https://simonwillison.net/2025/Apr/8/stop-syncing-everything/#atom-tag" rel="alternate"/><published>2025-04-08T17:20:49+00:00</published><updated>2025-04-08T17:20:49+00:00</updated><id>https://simonwillison.net/2025/Apr/8/stop-syncing-everything/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://sqlsync.dev/posts/stop-syncing-everything/"&gt;Stop syncing everything&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
In which Carl Sverre announces &lt;a href="https://github.com/orbitinghail/graft"&gt;Graft&lt;/a&gt;, a fascinating new open source Rust data synchronization engine he's been working on for the past year.&lt;/p&gt;
&lt;p&gt;Carl's &lt;a href="https://www.youtube.com/watch?v=eRsD8uSAi0s"&gt;recent talk at the Vancouver Systems meetup&lt;/a&gt; explains Graft in detail, including this slide which helped everything click into place for me:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Diagram explaining Graft data organization: Left side text reads &amp;quot;Graft organizes data into Volumes. Volumes are sparse ordered sets of Pages.&amp;quot; Right side shows a grid of colored squares (purple, green, blue) representing data organization. Bottom text states &amp;quot;E.g. A SQLite database with three tables&amp;quot;" src="https://static.simonwillison.net/static/2025/graft-slide.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Graft manages a volume, which is a collection of pages (currently at a fixed 4KB size). A full history of that volume is maintained using snapshots. Clients can read and write from particular snapshot versions for particular pages, and are constantly updated on which of those pages have changed (while not needing to synchronize the actual changed data until they need it).&lt;/p&gt;
&lt;p&gt;This is a great fit for B-tree databases like SQLite.&lt;/p&gt;
&lt;p&gt;The Graft project includes a SQLite VFS extension that implements multi-leader read-write replication on top of a Graft volume. You can see a demo of that running at &lt;a href="https://www.youtube.com/watch?v=eRsD8uSAi0s&amp;amp;t=36m15s"&gt;36m15s&lt;/a&gt; in the video, or consult the &lt;a href="https://github.com/orbitinghail/graft/blob/main/docs/sqlite.md"&gt;libgraft extension documentation&lt;/a&gt; and try it yourself.&lt;/p&gt;
&lt;p&gt;The section at the end on &lt;a href="https://sqlsync.dev/posts/stop-syncing-everything/#what-can-you-build-with-graft"&gt;What can you build with Graft?&lt;/a&gt; has some very useful illustrative examples:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Offline-first apps&lt;/strong&gt;: Note-taking, task management, or CRUD apps that operate partially offline. Graft takes care of syncing, allowing the application to forget the network even exists. When combined with a conflict handler, Graft can also enable multiplayer on top of arbitrary data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cross-platform data&lt;/strong&gt;: Eliminate vendor lock-in and allow your users to seamlessly access their data across mobile platforms, devices, and the web. Graft is architected to be embedded anywhere&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stateless read replicas&lt;/strong&gt;: Due to Graft's unique approach to replication, a database replica can be spun up with no local state, retrieve the latest snapshot metadata, and immediately start running queries. No need to download all the data and replay the log.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Replicate anything&lt;/strong&gt;: Graft is just focused on consistent page replication. It doesn't care about what's inside those pages. So go crazy! Use Graft to sync AI models, &lt;a href="https://en.wikipedia.org/wiki/Apache_Parquet"&gt;Parquet&lt;/a&gt; or &lt;a href="https://github.com/lancedb/lance"&gt;Lance&lt;/a&gt; files, &lt;a href="https://docs.mapbox.com/help/glossary/mbtiles/"&gt;Geospatial tilesets&lt;/a&gt;, or just photos of your &lt;a href="https://www.google.com/search?udm=2&amp;amp;q=cats"&gt;cats&lt;/a&gt;. The sky's the limit with Graft.&lt;/p&gt;
&lt;/blockquote&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/open-source"&gt;open-source&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/replication"&gt;replication&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sqlite"&gt;sqlite&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;&lt;/p&gt;



</summary><category term="open-source"/><category term="replication"/><category term="sqlite"/><category term="rust"/></entry><entry><title>Quoting Ryan Cavanaugh</title><link href="https://simonwillison.net/2025/Mar/11/ryan-cavanaugh/#atom-tag" rel="alternate"/><published>2025-03-11T19:32:31+00:00</published><updated>2025-03-11T19:32:31+00:00</updated><id>https://simonwillison.net/2025/Mar/11/ryan-cavanaugh/#atom-tag</id><summary type="html">
    &lt;blockquote cite="https://github.com/microsoft/typescript-go/discussions/411"&gt;&lt;p&gt;Languages that allow for a structurally similar codebase offer a significant boon for anyone making code changes because we can easily port changes between the two codebases. In contrast, languages that require fundamental rethinking of memory management, mutation, data structuring, polymorphism, laziness, etc., might be a better fit for a ground-up rewrite, but we're undertaking this more as a &lt;em&gt;port&lt;/em&gt; that maintains the existing behavior and critical optimizations we've built into the language. Idiomatic Go strongly resembles the existing coding patterns of the TypeScript codebase, which makes this porting effort much more tractable.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://github.com/microsoft/typescript-go/discussions/411"&gt;Ryan Cavanaugh&lt;/a&gt;, on why TypeScript chose to rewrite in Go, not Rust&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/typescript"&gt;typescript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/go"&gt;go&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;&lt;/p&gt;



</summary><category term="typescript"/><category term="go"/><category term="rust"/></entry><entry><title>monolith</title><link href="https://simonwillison.net/2025/Mar/6/monolith/#atom-tag" rel="alternate"/><published>2025-03-06T15:37:48+00:00</published><updated>2025-03-06T15:37:48+00:00</updated><id>https://simonwillison.net/2025/Mar/6/monolith/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Y2Z/monolith"&gt;monolith&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Neat CLI tool built in Rust that can create a single packaged HTML file of a web page plus all of its dependencies.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cargo install monolith # or brew install
monolith https://simonwillison.net/ &amp;gt; simonwillison.html
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That command produced &lt;a href="https://static.simonwillison.net/static/2025/simonwillison.html"&gt;this 1.5MB single file result&lt;/a&gt;. All of the linked images, CSS and JavaScript assets have had their contents inlined into base64 URIs in their &lt;code&gt;src=&lt;/code&gt; and &lt;code&gt;href=&lt;/code&gt; attributes.&lt;/p&gt;
&lt;p&gt;I was intrigued as to how it works, so I dumped the whole repository into Gemini 2.0 Pro and asked for an architectural summary:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /tmp
git clone https://github.com/Y2Z/monolith
cd monolith
files-to-prompt . -c | llm -m gemini-2.0-pro-exp-02-05 \
  -s 'architectural overview as markdown'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's &lt;a href="https://gist.github.com/simonw/2c80749935ae3339d6f7175dc7cf325b"&gt;what I got&lt;/a&gt;. Short version: it uses the &lt;code&gt;reqwest&lt;/code&gt;, &lt;code&gt;html5ever&lt;/code&gt;, &lt;code&gt;markup5ever_rcdom&lt;/code&gt; and &lt;code&gt;cssparser&lt;/code&gt; crates to fetch and parse HTML and CSS and extract, combine and rewrite the assets. It doesn't currently attempt to run any JavaScript.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=42933383#42935115"&gt;Comment on Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/cli"&gt;cli&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/scraping"&gt;scraping&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/files-to-prompt"&gt;files-to-prompt&lt;/a&gt;&lt;/p&gt;



</summary><category term="cli"/><category term="scraping"/><category term="ai"/><category term="rust"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="files-to-prompt"/></entry><entry><title>Quoting Charlie Marsh</title><link href="https://simonwillison.net/2025/Jan/29/charlie-marsh/#atom-tag" rel="alternate"/><published>2025-01-29T18:53:56+00:00</published><updated>2025-01-29T18:53:56+00:00</updated><id>https://simonwillison.net/2025/Jan/29/charlie-marsh/#atom-tag</id><summary type="html">
    &lt;blockquote cite="https://bsky.app/profile/crmarsh.com/post/3lgvhzdfrps26"&gt;&lt;p&gt;We’re building a new static type checker for Python, from scratch, in Rust. From a technical perspective, it’s probably our most ambitious project yet. We’re about &lt;a href="https://github.com/astral-sh/ruff/pulls?q=is%3Aopen+is%3Apr+label%3Ared-knot"&gt;800 PRs deep&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Like Ruff and uv, there will be a significant focus on performance. The entire system is designed to be highly incremental so that it can eventually power a language server (e.g., only re-analyze affected files on code change). [...]&lt;/p&gt;
&lt;p&gt;We haven't publicized it to-date, but all of this work has been happening in the open, in the Ruff repository.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://bsky.app/profile/crmarsh.com/post/3lgvhzdfrps26"&gt;Charlie Marsh&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/charlie-marsh"&gt;charlie-marsh&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/uv"&gt;uv&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ruff"&gt;ruff&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/astral"&gt;astral&lt;/a&gt;&lt;/p&gt;



</summary><category term="charlie-marsh"/><category term="rust"/><category term="python"/><category term="uv"/><category term="ruff"/><category term="astral"/></entry><entry><title>In search of a faster SQLite</title><link href="https://simonwillison.net/2024/Dec/15/in-search-of-a-faster-sqlite/#atom-tag" rel="alternate"/><published>2024-12-15T18:09:17+00:00</published><updated>2024-12-15T18:09:17+00:00</updated><id>https://simonwillison.net/2024/Dec/15/in-search-of-a-faster-sqlite/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://avi.im/blag/2024/faster-sqlite/"&gt;In search of a faster SQLite&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Turso developer Avinash Sajjanshetty (&lt;a href="https://simonwillison.net/2021/Jul/19/one-billion-rows/"&gt;previously&lt;/a&gt;) shares notes on the April 2024 paper &lt;a href="https://penberg.org/papers/penberg-edgesys24.pdf"&gt;Serverless Runtime / Database Co-Design With Asynchronous I/O&lt;/a&gt; by Turso founder and CTO Pekka Enberg, Jon Crowcroft, Sasu Tarkoma and Ashwin Rao.&lt;/p&gt;
&lt;p&gt;The theme of the paper is rearchitecting SQLite for asynchronous I/O, and Avinash describes it as "the foundational paper behind &lt;a href="https://github.com/tursodatabase/limbo"&gt;Limbo&lt;/a&gt;, the SQLite rewrite in Rust."&lt;/p&gt;
&lt;p&gt;From the paper abstract:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We propose rearchitecting SQLite to provide asynchronous byte-code instructions for I/O to avoid blocking in the library and de-coupling the query and storage engines to facilitate database and
serverless runtime co-design. Our preliminary evaluation shows
up to a 100x reduction in tail latency, suggesting that our approach
is conducive to runtime/database co-design for low latency.&lt;/p&gt;
&lt;/blockquote&gt;

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://lobste.rs/s/bwovro/search_faster_sqlite"&gt;lobste.rs&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/async"&gt;async&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sqlite"&gt;sqlite&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/limbo"&gt;limbo&lt;/a&gt;&lt;/p&gt;



</summary><category term="async"/><category term="sqlite"/><category term="rust"/><category term="limbo"/></entry><entry><title>Introducing Limbo: A complete rewrite of SQLite in Rust</title><link href="https://simonwillison.net/2024/Dec/10/introducing-limbo/#atom-tag" rel="alternate"/><published>2024-12-10T19:25:21+00:00</published><updated>2024-12-10T19:25:21+00:00</updated><id>https://simonwillison.net/2024/Dec/10/introducing-limbo/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://turso.tech/blog/introducing-limbo-a-complete-rewrite-of-sqlite-in-rust"&gt;Introducing Limbo: A complete rewrite of SQLite in Rust&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
This looks absurdly ambitious:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Our goal is to build a reimplementation of SQLite from scratch, fully compatible at the language and file format level,  with the same or higher reliability SQLite is known for, but with full memory safety and on a new, modern architecture.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Turso team behind it have been maintaining their &lt;a href="https://github.com/tursodatabase/libsql"&gt;libSQL&lt;/a&gt; fork for two years now, so they're well equipped to take on a challenge of this magnitude.&lt;/p&gt;
&lt;p&gt;SQLite is justifiably famous for its &lt;a href="https://www.sqlite.org/testing.html"&gt;meticulous approach to testing&lt;/a&gt;. Limbo plans to take an entirely different approach based on "Deterministic Simulation Testing" - a modern technique &lt;a href="https://antithesis.com/blog/is_something_bugging_you/"&gt;pioneered by FoundationDB&lt;/a&gt; and now spearheaded by &lt;a href="https://antithesis.com/"&gt;Antithesis&lt;/a&gt;, the company Turso have been working with on their previous testing projects.&lt;/p&gt;
&lt;p&gt;Another bold claim (emphasis mine):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We have both added DST facilities to the core of the database, and partnered with Antithesis to achieve a level of reliability in the database that lives up to SQLite’s reputation.&lt;/p&gt;
&lt;p&gt;[...] With DST, &lt;strong&gt;we believe we can achieve an even higher degree of robustness than SQLite&lt;/strong&gt;, since it is easier to simulate unlikely scenarios in a simulator, test years of execution with different event orderings, and upon finding issues, reproduce them 100% reliably.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The two most interesting features that Limbo is planning to offer are first-party WASM support and fully asynchronous I/O:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SQLite itself has a synchronous interface, meaning driver authors who want asynchronous behavior need to have the extra complication of using helper threads. Because SQLite queries tend to be fast, since no network round trips are involved, a lot of those drivers just settle for a synchronous interface. [...]&lt;/p&gt;
&lt;p&gt;Limbo is designed to be asynchronous from the ground up. It extends &lt;code&gt;sqlite3_step&lt;/code&gt;, the main entry point API to SQLite, to be asynchronous, allowing it to return to the caller if data is not ready to consume immediately.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://datasette.io/"&gt;Datasette&lt;/a&gt; provides an &lt;a href="https://docs.datasette.io/en/stable/internals.html#await-db-execute-sql"&gt;async API&lt;/a&gt; for executing SQLite queries which is backed by all manner of complex thread management - I would be very interested in a native asyncio Python library for talking to SQLite database files.&lt;/p&gt;
&lt;p&gt;I successfully tried out Limbo's &lt;a href="https://github.com/tursodatabase/limbo/tree/main/bindings/python"&gt;Python bindings&lt;/a&gt; against a demo SQLite test database using &lt;code&gt;uv&lt;/code&gt; like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uv run --with pylimbo python
&amp;gt;&amp;gt;&amp;gt; import limbo
&amp;gt;&amp;gt;&amp;gt; conn = limbo.connect("/tmp/demo.db")
&amp;gt;&amp;gt;&amp;gt; cursor = conn.cursor()
&amp;gt;&amp;gt;&amp;gt; print(cursor.execute("select * from foo").fetchall())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It crashed when I tried against a more complex SQLite database that included SQLite FTS tables.&lt;/p&gt;
&lt;p&gt;The Python bindings aren't yet documented, so I piped them through &lt;a href="https://llm.datasette.io/"&gt;LLM&lt;/a&gt; and had the new &lt;code&gt;google-exp-1206&lt;/code&gt; model write &lt;a href="https://gist.github.com/simonw/bd1822f372c406d17ed24772f8b93eea"&gt;this initial documentation&lt;/a&gt; for me:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;files-to-prompt limbo/bindings/python -c | llm -m gemini-exp-1206 -s 'write extensive usage documentation in markdown, including realistic usage examples'
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=42378843"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/documentation"&gt;documentation&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/open-source"&gt;open-source&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sqlite"&gt;sqlite&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llm"&gt;llm&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/uv"&gt;uv&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/limbo"&gt;limbo&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/files-to-prompt"&gt;files-to-prompt&lt;/a&gt;&lt;/p&gt;



</summary><category term="documentation"/><category term="open-source"/><category term="python"/><category term="sqlite"/><category term="rust"/><category term="ai-assisted-programming"/><category term="llm"/><category term="uv"/><category term="limbo"/><category term="files-to-prompt"/></entry></feed>