惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
Microsoft Security Blog
Microsoft Security Blog
N
Netflix TechBlog - Medium
G
Google Developers Blog
L
LangChain Blog
腾讯CDC
大猫的无限游戏
大猫的无限游戏
U
Unit 42
Google DeepMind News
Google DeepMind News
人人都是产品经理
人人都是产品经理
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
小众软件
小众软件
The GitHub Blog
The GitHub Blog
博客园_首页
GbyAI
GbyAI

Oskar Wickström

How Antithesis Found and Explained a Bombadil Race Condition Coding on Paper The Bombadil Terminal Experiment There and Back Again: From Quickstrom to Bombadil Computer Says No: Error Reporting for LTL A Year with the Daylight Computer Finding Bugs in a Coding Agent with Lightweight DST Machine: Learning; Human: Unlearning; How I Built “The Monospace Web” A Flexible Minimalist Neovim for 2024 Statically Typed Functional Programming with Python 3.12 Specifying State Machines with Temporal Logic Clearing Weeds and Planting Trees Introducing Quickstrom: High-confidence browser testing The TodoMVC Showdown: Testing with WebCheck Time Travelling and Fixing Bugs with Property-Based Testing Property-Based Testing in a Screencast Editor, Case Study 3: Integration Testing Property-Based Testing in a Screencast Editor, Case Study 2: Video Scene Classification Property-Based Testing in a Screencast Editor, Case Study 1: Timeline Flattening Property-Based Testing in a Screencast Editor: Introduction Why I’m No Longer Taking Donations Writing a Screencast Video Editor in Haskell Declarative GTK+ Programming with Haskell Finite-State Machines, Part 2: Explicit Typed State Transitions Modeling with Haskell Data Types Motor: Finite-State Machines in Haskell Automating the Build of your Technical Presentation Tagless Final Encoding of a Test Language Hyper: Elegant Weapons for a More Civilized Page Taking a Step Back from Oden
Catching Typos on My Website with Browser Testing
Oskar Wickström · 2026-05-13 · via Oskar Wickström

One neat thing about Bombadil’s specification language is that it’s plain TypeScript, with access to external NPM packages. I’ve written a specification that spell-checks my website — what you’re reading now — and I want to share how that turned out.

The inner loop (spell-checking):

Bombadil randomly walks the website and collects misspelled words as property violations. The specification uses nspell with American and British English dictionaries and a personal word list in the repository. This is fast and strict.

The outer loop (triage):

I’m running Claude Code with a spell-checking skill, a triage loop that goes something like this:

  1. Run Bombadil against the local development server for 5 minutes and capture the output. If no words flagged, we’re done.
  2. Collect each flagged word and the URL it appeared on.
  3. Triage each word into one of these buckets:
    • Real typo: fix the markdown source
    • Legitimate common word: add to the custom dictionary
    • Legitimate uncommon or very technical word: mark inline with spellcheck="false"
    • Extraction noise: add a unit test and fix the word extractor
  4. Run Bombadil against each failing URL to confirm the corrections.
  5. Go to step 1.

This is slow and loose.

The hybrid model seems to work well; it has flagged words in almost every blog post. It has fixed 13 real typos and added 130+ words to my personal dictionary. Example typos include “forseeable”, “similiar”, “perculiar”, “occured”. Some of these were 10 years old.

Claude doesn’t have to waste tokens spell-checking everything over and over. Right now I’m just running this locally, but you could imagine a more elaborate setup for large websites where the “inner loop” runs as a nightly job, invoking the “outer loop” only on violations. You could involve a human where needed, and build up a domain-specific dictionary over time.

Note that using an LLM is entirely optional. It just saves me some time. You can do triage on your own.

Why not spell-check the sources directly? Yes, that is often preferable, and I use spell in Neovim all the time. But it’s not always practical. At least in my experience, the tooling trips up on syntax and templating in more complicated setups. Maybe your editor handles this better than mine does, or maybe you’re fine with tools like typos and codespell, but I like the fact that this approach is external and checks the rendered output. Given that Bombadil interacts with web applications, you could even run this against dynamic applications to spell-check states deep in the UI.

Speaking of source-level checking: since the custom dictionary is a plain word list, I point Neovim’s spellfile at it and use zg to add words while I edit. A single source of truth that both tools write to.

vim.opt.spellfile = "/path/to/custom.utf-8.add"
vim.opt.spelllang = "en"

Being able to use NPM packages in specifications has turned out to be more useful than I expected. In addition to nspell, I’m using tlds to identify URLs. Bombadil is built for property-based testing of web applications, but with a specification language and package ecosystem at hand, its uses might be broader than my original vision.

If you’re interested in setting up something like this on your own, you’ll find the sources in my Bombadil playground.

Disclosure: I’m the original author and lead for the Bombadil project at Antithesis.