Simon Willison updated his blog-to-newsletter tool with a single, precise prompt to Claude AI. The change added support for “beats”—short external updates like open-source releases and museum visits—pulling only those with added descriptions. This took seconds to prompt and minutes to verify, handling a Datasette-backed blog’s new schema without manual coding.
Willison’s setup runs a static HTML/JavaScript app from his simonw/tools repo. It queries a Datasette instance at til.simonwillison.net, which powers his simonwillison.net blog. The app grabs the latest 10-15 posts, formats them as clipboard-ready rich HTML, and feeds into Substack’s editor. He sends newsletters weekly to ~50,000 subscribers, bypassing native RSS-to-email limits.
Beats entered the picture recently. Imported automatically from RSS feeds—GitHub releases for Datasette (2.0+ versions), LLMs (like his LLM CLI tool), and niche sites like niche-museums.com—these are lightweight entries. Most are noise: a 1.2.3 patch release. Willison flags interesting ones by adding descriptions in his Django admin, bumping them to the blog’s “everything” Atom feed.
The Prompt That Did the Work
He fed this to Claude Code on Anthropic’s web interface, targeting the simonw/tools repo:
Clone simonw/simonwillisonblog from github to /tmp for reference
Update blog-to-newsletter.html to include beats that have descriptions - similar to how the Atom everything feed on the blog works
Run it with python -m http.server and use `uvx rodney --help` to test it - compare what shows up in the newsletter with what's on the homepage of https://simonwillison.net
Claude cloned the blog repo to /tmp (smart isolation to avoid contaminating the tools repo), parsed the beat schema (entries with non-null description), mirrored the Atom feed logic in blog-to-newsletter.html‘s JS fetch/query, and tested locally. uvx rodney is Willison’s preview tool: it runs the HTML app, copies output, and opens Substack. Result matched the homepage perfectly—three recent described beats included.
Why This Prompt Wins
Three elements made it effective. First, explicit reference cloning: AI coding agents like Claude 3.5 Sonnet excel at schema comprehension but need context. simonw/simonwillisonblog has 1,000+ commits, beat tables in SQLite via Datasette. Cloning to /tmp keeps it sandboxed—no merge risks.
Second, pinpoint specificity: “blog-to-newsletter.html” narrows 200+ files in tools. “Beats that have descriptions” leverages the exact filter (non-empty description). “Similar to Atom everything feed” points to existing SQL: select * from beats where description is not null order by updated desc limit 5-ish.
Third, test instructions: Local server spin-up, rodney for end-to-end, visual homepage diff. This closes the loop—AI verifies, not just generates. Willison commits often; this pattern appears in his “agentic engineering” notes, where he logs 10x productivity on repo maintenance.
Skeptical take: This isn’t general AI magic. Claude fails on vague prompts or complex refactors (e.g., 20% error rate on multi-file changes per his benchmarks). But for schema tweaks in familiar codebases? 90% hit rate. Datasette’s SQL-first design helps—queries are declarative, easy to replicate.
Implications for Builders
This scales for solo maintainers. Willison’s blog processes 5,000+ entries yearly across posts, beats, quotes. Manual updates waste hours; AI handles schema evolutions in shots. Security angle: Cloning to /tmp mitigates supply-chain risks in agent workflows—treat repos as untrusted input.
Broader: Agentic patterns like this cut dev time 50-80% on CRUD tools. Tools repo has 300+ HTML/JS apps; prompting beats custom scripting. For finance/crypto devs: Adapt for Dune Analytics queries or on-chain event “beats” (e.g., filter described wallet moves). Test rigorously—AI hallucinations persist.
Why it matters: In a world of bloated no-code, this is lean engineering. Open-source it, iterate via PRs or agents. Willison’s repo now includes beats seamlessly; next newsletter hits inboxes with richer signal, no extra effort. Reproducible at github.com/simonw/tools.