<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom"><title>Simon Willison's Weblog: alex-gaynor</title><link href="http://simonwillison.net/" rel="alternate"/><link href="http://simonwillison.net/tags/alex-gaynor.atom" rel="self"/><id>http://simonwillison.net/</id><updated>2025-06-30T16:44:59+00:00</updated><author><name>Simon Willison</name></author><entry><title>llvm: InstCombine: improve optimizations for ceiling division with no overflow - a PR by Alex Gaynor and Claude Code</title><link href="https://simonwillison.net/2025/Jun/30/llvm/#atom-tag" rel="alternate"/><published>2025-06-30T16:44:59+00:00</published><updated>2025-06-30T16:44:59+00:00</updated><id>https://simonwillison.net/2025/Jun/30/llvm/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/llvm/llvm-project/pull/142869"&gt;llvm: InstCombine: improve optimizations for ceiling division with no overflow - a PR by Alex Gaynor and Claude Code&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Alex Gaynor maintains &lt;a href="https://github.com/alex/rust-asn1"&gt;rust-asn1&lt;/a&gt;, and recently spotted a missing LLVM compiler optimization while hacking on it, with &lt;a href="https://claude.ai/share/d998511d-45ee-4132-bee4-fe7f70350a67"&gt;the assistance of Claude&lt;/a&gt; (Alex works for Anthropic).&lt;/p&gt;
&lt;p&gt;He describes how he confirmed that optimization in &lt;a href="https://alexgaynor.net/2025/jun/20/serialize-some-der/"&gt;So you want to serialize some DER?&lt;/a&gt;, taking advantage of a tool called &lt;a href="https://github.com/AliveToolkit/alive2"&gt;Alive2&lt;/a&gt; to automatically verify that the potential optimization resulted in the same behavior.&lt;/p&gt;
&lt;p&gt;Alex &lt;a href="https://github.com/llvm/llvm-project/issues/142497"&gt;filed a bug&lt;/a&gt;, and then... &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Obviously the next move is to see if I can send a PR to LLVM, but it’s been years since I was doing compiler development or was familiar with the LLVM internals and I wasn’t really prepared to invest the time and energy necessary to get back up to speed. But as a friend pointed out… what about Claude?&lt;/p&gt;
&lt;p&gt;At this point my instinct was, "Claude is great, but I'm not sure if I'll be able to effectively code review any changes it proposes, and I'm &lt;em&gt;not&lt;/em&gt; going to be the asshole who submits an untested and unreviewed PR that wastes a bunch of maintainer time". But excitement got the better of me, and I asked &lt;code&gt;claude-code&lt;/code&gt; to see if it could implement the necessary optimization, based on nothing more than the test cases.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Alex reviewed the resulting code &lt;em&gt;very&lt;/em&gt; carefully to ensure he wasn't wasting anyone's time, then submitted &lt;a href="https://github.com/llvm/llvm-project/pull/142869"&gt;the PR&lt;/a&gt; and had Claude Code help implement the various changes requested by the reviewers. The optimization &lt;a href="https://github.com/llvm/llvm-project/commit/632151fbeea972f4aa3c14921eca1e45c07646f3"&gt;landed&lt;/a&gt; two weeks ago.&lt;/p&gt;
&lt;p&gt;Alex's conclusion (emphasis mine):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I am incredibly leery about &lt;a href="https://alexgaynor.net/2025/mar/05/generality/"&gt;over-generalizing&lt;/a&gt; how to understand the capacity of the models, but at a minimum it seems safe to conclude that &lt;strong&gt;sometimes you should just let the model have a shot at a problem and you may be surprised -- particularly when the problem has very clear success criteria&lt;/strong&gt;. This only works if you have the capacity to review what it produces, of course. [...]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This echoes Ethan Mollick's advice to "always invite AI to the table". For programming tasks the "very clear success criteria" is extremely important, as it helps fit the tools-in-a-loop pattern implemented by coding agents such as Claude Code.&lt;/p&gt;
&lt;p&gt;LLVM have &lt;a href="https://llvm.org/docs/DeveloperPolicy.html#ai-generated-contributions"&gt;a policy&lt;/a&gt; on AI-assisted contributions which is compatible with Alex's work here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[...] the LLVM policy is that contributors are permitted to use artificial intelligence tools to produce contributions, provided that they have the right to license that code under the project license. Contributions found to violate this policy will be removed just like any other offending contribution.&lt;/p&gt;
&lt;p&gt;While the LLVM project has a liberal policy on AI tool use, contributors are considered responsible for their contributions. We encourage contributors to review all generated code before sending it for review to verify its correctness and to understand it so that they can answer questions during code review.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Back in April Ben Evans &lt;a href="https://mastodon.social/@kittylyst/114397697851381604"&gt;put out a call&lt;/a&gt; for concrete evidence that LLM tools were being used to solve non-trivial problems in mature open source projects:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I keep hearing #AI boosters / talking heads claiming that #LLMs have transformed software development [...] Share some AI-derived pull requests that deal with non-obvious corner cases or non-trivial bugs from mature #opensource  projects.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think this LLVM optimization definitely counts!&lt;/p&gt;
&lt;p&gt;(I also like how this story supports the idea that AI tools amplify existing human expertise rather than replacing it. Alex had previous experience with LLVM, albeit rusty, and could lean on that knowledge to help direct and evaluate Claude's work.)


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/alex-gaynor"&gt;alex-gaynor&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/compilers"&gt;compilers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llvm"&gt;llvm&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/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="alex-gaynor"/><category term="compilers"/><category term="llvm"/><category term="open-source"/><category term="ai-assisted-programming"/><category term="anthropic"/><category term="claude"/><category term="coding-agents"/><category term="claude-code"/></entry><entry><title>Weeknotes: sqlite-utils 3.0 alpha, Git scraping in the zeitgeist</title><link href="https://simonwillison.net/2020/Nov/7/weeknotes-sqlite-utils-git-scraping/#atom-tag" rel="alternate"/><published>2020-11-07T02:17:55+00:00</published><updated>2020-11-07T02:17:55+00:00</updated><id>https://simonwillison.net/2020/Nov/7/weeknotes-sqlite-utils-git-scraping/#atom-tag</id><summary type="html">
    &lt;p&gt;Natalie and I decided to escape San Francisco for election week, and have been holed up in Fort Bragg on the Northern California coast. I've mostly been on vacation, but I did find time to make some significant changes to &lt;a href="https://github.com/simonw/sqlite-utils"&gt;sqlite-utils&lt;/a&gt;. Plus notes on an exciting Git scraping project.&lt;/p&gt;
&lt;h4&gt;Better search in the sqlite-utils 3.0 alpha&lt;/h4&gt;
&lt;p&gt;I practice &lt;a href="https://www.google.com/search?channel=cus2&amp;amp;client=firefox-b-1-d&amp;amp;q=semver"&gt;semantic versioning&lt;/a&gt; with sqlite-utils, which means it only gets a major version bump if I break backwards compatibility in some way.&lt;/p&gt;
&lt;p&gt;My goal is to avoid breaking backwards compatibility as much as possible, and I was proud to have made it all the way to &lt;a href="https://sqlite-utils.readthedocs.io/en/stable/changelog.html#v2-23"&gt;version 2.23&lt;/a&gt; representing 23 new feature releases since the 2.0 release without breaking any documented features!&lt;/p&gt;
&lt;p&gt;Sadly this run has come to an end: I realized that the &lt;code&gt;table.search()&lt;/code&gt; method was poorly designed, and I also needed to grab back the &lt;code&gt;-c&lt;/code&gt; command-line option (a shortcut for &lt;code&gt;--csv&lt;/code&gt; output) to be used for another purpose.&lt;/p&gt;
&lt;p&gt;The chances that either of these changes will break anyone are pretty small, but semantic versioning dictates a major version bump so here we are.&lt;/p&gt;
&lt;p&gt;I shipped a &lt;a href="https://github.com/simonw/sqlite-utils/releases/tag/3.0a0"&gt;3.0 alpha&lt;/a&gt; today, which should hopefully become a stable release very shortly (&lt;a href="https://github.com/simonw/sqlite-utils/milestone/4"&gt;milestone here&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The big new feature is &lt;code&gt;sqlite-utils search&lt;/code&gt; - a command-line tool for executing searches against a full-text search enabled table:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sqlite-utils search 24ways-fts4.db articles maps -c title
[{"rowid": 163, "title": "Get To Grips with Slippy Maps", "rank": -10.028754920576421},
 {"rowid": 220, "title": "Finding Your Way with Static Maps", "rank": -9.952534352591737},
 {"rowid": 27, "title": "Putting Design on the Map", "rank": -5.667327088267961},
 {"rowid": 168, "title": "Unobtrusively Mapping Microformats with jQuery", "rank": -4.662224207228984},
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's &lt;a href="https://sqlite-utils.readthedocs.io/en/latest/cli.html#cli-search"&gt;full documentation&lt;/a&gt; for the new command.&lt;/p&gt;
&lt;p&gt;Notably, this command works against both FTS4 and FTS5 tables in SQLite - despite FTS4 not shipping with a built-in ranking function. I'm using my &lt;a href="https://github.com/simonw/sqlite-fts4"&gt;sqlite-fts4&lt;/a&gt; package for this, which I described back in January 2019 in &lt;a href="https://simonwillison.net/2019/Jan/7/exploring-search-relevance-algorithms-sqlite/"&gt;Exploring search relevance algorithms with SQLite&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Git scraping to predict the election&lt;/h4&gt;
&lt;p&gt;It's not quite over yet but the end is in sight, and one of the best tools to track the late arriving vote counts is &lt;a href="https://alex.github.io/nyt-2020-election-scraper/battleground-state-changes.html"&gt;this Election 2020 results site&lt;/a&gt; built by Alex Gaynor and a growing cohort of contributors.&lt;/p&gt;
&lt;p&gt;The site is a beautiful example of &lt;a href="https://simonwillison.net/2020/Oct/9/git-scraping/"&gt;Git scraping&lt;/a&gt; in action, and I'm thrilled that it links to my article in the README!&lt;/p&gt;
&lt;p&gt;Take a look &lt;a href="https://github.com/alex/nyt-2020-election-scraper"&gt;at the repo&lt;/a&gt; to see how it works. Short version: this &lt;a href="https://github.com/alex/nyt-2020-election-scraper/blob/01060c06c35442c0654e18b84e22394ef3ef5a9c/.github/workflows/scrape.yml"&gt;GitHub Action workflow&lt;/a&gt; grabs the latest snapshot of this &lt;a href="https://static01.nyt.com/elections-assets/2020/data/api/2020-11-03/votes-remaining-page/national/president.json"&gt;undocumented New York Times JSON API&lt;/a&gt; once every five minutes and commits it to the repository. It then runs &lt;a href="https://github.com/alex/nyt-2020-election-scraper/blob/01060c06c35442c0654e18b84e22394ef3ef5a9c/print-battleground-state-changes"&gt;this Python script&lt;/a&gt; which iterates through the Git history and generates an HTML summary showing the different batches of new votes that were reported and their impact on the overall race.&lt;/p&gt;
&lt;p&gt;The resulting report is published to GitHub pages - resulting in a site that can handle a great deal of traffic and is updated entirely by code running in scheduled actions.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of the generated report" src="https://static.simonwillison.net/static/2020/election-data-git-scraper.png" style="max-width:100%;" /&gt;&lt;/p&gt;
&lt;p&gt;This is a perfect use-case for Git scraping: it takes a JSON endpoint that represents the current state of the world and turns it into a sequence of historic snapshots, then uses those snapshots to build a unique and useful new source of information to help people understand what's going on.&lt;/p&gt;
&lt;h4&gt;Releases this week&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/simonw/sqlite-utils/releases/tag/3.0a0"&gt;sqlite-utils 3.0a0&lt;/a&gt; - 2020-11-07&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/simonw/sqlite-fts4/releases/tag/1.0.1"&gt;sqlite-fts4 1.0.1&lt;/a&gt; - 2020-11-06&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/simonw/sqlite-fts4/releases/tag/1.0"&gt;sqlite-fts4 1.0&lt;/a&gt; - 2020-11-06&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/simonw/csvs-to-sqlite/releases/tag/1.2"&gt;csvs-to-sqlite 1.2&lt;/a&gt; - 2020-11-03&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/simonw/datasette/releases/tag/0.51.1"&gt;datasette 0.51.1&lt;/a&gt; - 2020-11-01&lt;/li&gt;
&lt;/ul&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/alex-gaynor"&gt;alex-gaynor&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/elections"&gt;elections&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/weeknotes"&gt;weeknotes&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/git-scraping"&gt;git-scraping&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sqlite-utils"&gt;sqlite-utils&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="alex-gaynor"/><category term="elections"/><category term="weeknotes"/><category term="git-scraping"/><category term="sqlite-utils"/></entry><entry><title>nyt-2020-election-scraper</title><link href="https://simonwillison.net/2020/Nov/6/nyt-2020-election-scraper/#atom-tag" rel="alternate"/><published>2020-11-06T14:24:36+00:00</published><updated>2020-11-06T14:24:36+00:00</updated><id>https://simonwillison.net/2020/Nov/6/nyt-2020-election-scraper/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/alex/nyt-2020-election-scraper"&gt;nyt-2020-election-scraper&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Brilliant application of git scraping by Alex Gaynor and a growing team of contributors. Takes a JSON snapshot of the NYT’s latest election poll figures every five minutes, then runs a Python script to iterate through the history and build an HTML page showing the trends, including what percentage of the remaining votes each candidate needs to win each state. This is the perfect case study in why it can be useful to take a “snapshot if the world right now” data source and turn it into a git revision history over time.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/alex-gaynor"&gt;alex-gaynor&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/data-journalism"&gt;data-journalism&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/elections"&gt;elections&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/git"&gt;git&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/new-york-times"&gt;new-york-times&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/git-scraping"&gt;git-scraping&lt;/a&gt;&lt;/p&gt;



</summary><category term="alex-gaynor"/><category term="data-journalism"/><category term="elections"/><category term="git"/><category term="new-york-times"/><category term="git-scraping"/></entry><entry><title>CSVs: The good, the bad, and the ugly</title><link href="https://simonwillison.net/2020/Nov/5/csvs-good-bad-and-ugly/#atom-tag" rel="alternate"/><published>2020-11-05T17:19:05+00:00</published><updated>2020-11-05T17:19:05+00:00</updated><id>https://simonwillison.net/2020/Nov/5/csvs-good-bad-and-ugly/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://alexgaynor.net/2020/sep/24/csv-good-bad-ugly/"&gt;CSVs: The good, the bad, and the ugly&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Useful, thoughtful summary of the pros and cons of the most common format for interchanging data.

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


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/alex-gaynor"&gt;alex-gaynor&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/csv"&gt;csv&lt;/a&gt;&lt;/p&gt;



</summary><category term="alex-gaynor"/><category term="csv"/></entry><entry><title>Django | Multiple Databases</title><link href="https://simonwillison.net/2009/Dec/22/django/#atom-tag" rel="alternate"/><published>2009-12-22T17:22:37+00:00</published><updated>2009-12-22T17:22:37+00:00</updated><id>https://simonwillison.net/2009/Dec/22/django/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://docs.djangoproject.com/en/dev/topics/db/multi-db/"&gt;Django | Multiple Databases&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Russell just checked in the final patch developed from Alex Gaynor’s Summer of Code project to add multiple database support to Django. I’d link to the 21,000 line changeset but it crashed our Trac, so here’s the documentation instead.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/alex-gaynor"&gt;alex-gaynor&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/databases"&gt;databases&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/django"&gt;django&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/multidb"&gt;multidb&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/russell-keith-magee"&gt;russell-keith-magee&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/scaling"&gt;scaling&lt;/a&gt;&lt;/p&gt;



</summary><category term="alex-gaynor"/><category term="databases"/><category term="django"/><category term="multidb"/><category term="python"/><category term="russell-keith-magee"/><category term="scaling"/></entry><entry><title>How to use Django with Apache and mod_wsgi</title><link href="https://simonwillison.net/2009/Apr/1/modwsgi/#atom-tag" rel="alternate"/><published>2009-04-01T00:24:04+00:00</published><updated>2009-04-01T00:24:04+00:00</updated><id>https://simonwillison.net/2009/Apr/1/modwsgi/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/"&gt;How to use Django with Apache and mod_wsgi&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
My favourite deployment option is now included in the official Django docs, thanks to Alex Gaynor. I tend to run a stripped down Apache with mod_wsgi behind an nginx proxy, and have nginx serve static files directly. This avoids the need for a completely separate media server (although a separate media domain is still a good idea for better client-side performance).


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/alex-gaynor"&gt;alex-gaynor&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deployment"&gt;deployment&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/django"&gt;django&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/modwsgi"&gt;modwsgi&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/nginx"&gt;nginx&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/proxies"&gt;proxies&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/wsgi"&gt;wsgi&lt;/a&gt;&lt;/p&gt;



</summary><category term="alex-gaynor"/><category term="deployment"/><category term="django"/><category term="modwsgi"/><category term="nginx"/><category term="proxies"/><category term="python"/><category term="wsgi"/></entry></feed>