explainx.ai350K+ learn from us
TrendingAI News TodayPathwaysSkills
Pricing
explainx.ai

Upskill in AI — 16 free pathways, live workshops & bootcamps, and 50+ courses from practitioners. Plus the skills, tools, and MCP servers to practice on.

follow us

follow on google

Add explainx.ai as a preferred source

corporate training

support@explainx.ai

get started

Find your pathTake Free Evaluation

community

Join the community

learn

mind: share how you thinkpathways — start freeworkshopsbootcampscoursescompare Explainxcertificationsmock testsexplainx universitycorporate traininglearn skills & mcp

discover

skillsmcp serversexplainx mcpestacktoolsmdx readeragentsllmsdesignsdictionarypeopleagi trackerfelony benchranks

company

aboutvisionmissionteaminstructorsteach on explainxpartnershipscommunityhackathonscareers

content

daily AI newsstate of AI — live resultsblogreleasespromptsgeneratorsresource libraryfor LLMsexplainx.ai kids

solutions

all solutionsdeveloper upskillingmarketing upskillingproduct manager upskillingleadership upskilling

newsletter · weekly

Get AI news, tools, and insights in your inbox.

supportcontactprivacytermsdata rightshow we create contentsubmission guidelines

© 2026 AISOLO Technologies Pvt Ltd

explainx.ai

On this page

  • TL;DR
  • What Willison asked Opus 5.5 to do
  • Behavior rules the model chose
  • Benchmark numbers from the research README
  • Size and complexity trade-offs
  • Correctness checks you can rerun
  • How this compares to agent harness workflows
  • Links to wider Claude and local-AI coverage
  • Limits and caveats
  • What people building with agents should try
  • Related reading
← Back to blog

explainx / blog

Claude Opus 5.5 Built a SQLite parse_number() Extension: C Beat Rust on Speed

Claude, Opus 5.5, SQLite, Agentic Coding, Local AI

Part of Anthropic and Claude

Simon Willison used Claude Opus 5.5 chat to ship four SQLite loadable parse_number() extensions, benchmarked C versus Rust, and published the full research repo. Numbers, build steps, and limits.

Nov 8, 2026·9 min read·Yash Thakker
add explainx.ai
go deep
Claude Opus 5.5 Built a SQLite parse_number() Extension: C Beat Rust on Speed

On November 8, 2026, developer Simon Willison published a walkthrough of how regular Claude chat with Opus 5.5 helped him build four loadable SQLite extensions that implement the same parse_number(value) scalar function, benchmark them against pure SQL, and ship a reproducible folder in simonw/research. The hook is practical: turn messy spreadsheet strings such as -$1,234.56 or 12.5% into numbers you can SUM and ORDER BY inside SQLite.

This is not a product launch from Anthropic or SQLite. It is a documented agent-assisted systems programming session with numbers readers can re-run. If you build analytics pipelines, local-first apps, or agent tools that ingest CSV exports, the lesson is how far a well-scoped native extension prompt can get before you touch a full coding agent repo.

TL;DR

table · 2 cols
QuestionAnswer
Which models?Claude Opus 5.5 in Claude chat (Willison's post; not Claude Code)
What function?parse_number(value) strips , $ £ %, trims space, handles one leading -, returns NULL on junk
How many builds?Four: plain C, c-fast, rusqlite, sqlite-loadable
Fastest?c-fast at about 16–19 ns/row net in published benches
Smallest binary?C at about 14 KB stripped .so
Slowest baseline?Nested SQL replace() at ~329–357 ns/row
Correctness?40 hand tests + 8M fuzz checks, no mismatches in published log
Where is source?GitHub research folder
Daily briefFrom Yash · 350K+ students taught

Catch up on AI

One AI story explained in plain English, plus one thing to try. Every day, free. Unsubscribe anytime.

What Willison asked Opus 5.5 to do

In his November 8 post, Willison says the idea started on a dog walk. He opened Claude and prompted for:

  • A parse_number(value) custom function that strips $ £ % ,, tolerates whitespace, allows one leading minus, and returns NULL when parsing fails.
  • A comparison between implementing it as a SQLite C extension versus Rust loadable modules, including performance, code complexity, and .so size.

The first pass surprised him: Rust binaries were hundreds of kilobytes but faster than plain C on mixed data because strtod in glibc lost on decimals. He followed up:

Try writing your own C function for parsing text into a decimal number that catches up to or beats the Rust implementation

That second prompt produced c-fast/, the eventual winner on the benchmark table.

He then asked Claude to clone the simonw/research layout and deliver a zip-style research package. The published README begins with a disclosure that all text and code in that report were model-generated, pointing readers to the parent repo's explanation of AI-authored research notes.

Behavior rules the model chose

Because the initial prompt left edge cases open, Opus 5.5 fixed a shared ruleset used by all four builds:

  • INTEGER and REAL inputs pass through unchanged; NULL and BLOB return NULL.
  • Strip spaces, tabs, and newlines at both ends; remove currency symbols and commas anywhere.
  • Allow one leading minus before the first digit; allow one decimal point with at least one digit.
  • Reject scientific notation, interior spaces, doubled minus signs, and ambiguous forms like 5-.

Example calls from the README:

sql
select parse_number(' -$1,234.56 '); -- -1234.56
select parse_number(' £1,000,000 '); -- 1000000 (INTEGER)
select parse_number(' 12.5% '); -- 12.5
select parse_number(' n/a '); -- NULL

Those rules matter for agents. If you let a model invent parsing ad hoc in SQL, you get inconsistent dashboards. Centralizing in a scalar function gives agents a single predicate to reference in generated queries.

Benchmark numbers from the research README

The repo runs select sum(parse_number(v)) over two million rows inside Python's sqlite3 module (SQLite 3.53.1). It subtracts a baseline scan to report net nanoseconds per row. Hardware was a 2 vCPU Linux x86-64 VM with gcc 13.3 and rustc 1.97.

table · 6 cols
Datasetplain Cfast Crusqlitesqlite-loadablepure SQL replace()
Mixed currency strings67.319.245.940.5328.9
Integers only25.115.836.432.1342.5
Decimals only106.317.554.546.5356.9

Willison's blog post rounds those to 16–19 ns for c-fast across suites. The takeaway for builders is not that C always wins. It is that library float parsing choices (strtod versus Rust's f64::from_str) dominated until the model rewrote a Clinger-style fast path inside the scan loop.

The README documents why plain C lost on decimals and how c-fast detects when mantissa and fraction lengths fit exact IEEE operations, falling back to strtod only on long inputs.

Size and complexity trade-offs

table · 4 cols
VariantStripped .soLines of core code (per README)Build time from scratch
plain C14,408 B75~0.1 s
c-fast14,408 B104~0.1 s
rusqlite320,864 B36 + 41 shared parser~11 s
sqlite-loadable298,464 B30 + 41 shared parser~72 s (bindgen)

Rust builds drag dozens of crates even for one function. For desktop analytics that is fine. For shipping a single .so inside a mobile app or SQLite shell plugin, the 14 KB C artifact is the headline.

Willison also notes Rust's ergonomics: overflow-safe integer parsing, ValueRef matches, and less manual buffer bookkeeping. The README's "Notes on writing each one" section is essentially a micro trade study you can hand to a junior engineer before they pick a language for the next extension.

The README's micro-benchmark notes explain why rusqlite stayed slower than c-fast even after parser tweaks: each call pays for closure wrapping, Result handling, and a per-row Vec allocation. Swapping that Vec for a stack buffer only shaved a few nanoseconds on integer-only data. If your workload is mostly integers and you already ship Rust, the sqlite-loadable or rusqlite path may be good enough. When decimals dominate and binary size matters, c-fast/ is the documented winner on this VM.

Federated spools linking vessels, metaphor for SQLite parse_number feeding many analytic queriesFederated spools linking vessels, metaphor for SQLite parse_number feeding many analytic queries

Image: Library illustration for data parsing pipelines; not from the research repo.

Correctness checks you can rerun

The repo ships three scripts:

  1. test.py — 40 curated cases checking both value and typeof().
  2. fuzz.py — random junk and extreme-precision decimals against a Python float() reference; 4 seeds × 500k inputs × 4 extensions with no mismatches logged in results/fuzz.txt.
  3. bench.py — reproduction for mixed, int, or real suites.

Reproduction commands from the README:

bash
./build.sh
python test.py
python fuzz.py 1
python bench.py mixed

Or compile only the fast C path:

bash
gcc -O2 -fPIC -shared c-fast/parse_number.c -o parse_number.so

For readers already using Willison's LLM CLI 0.37, this repo is the same author showing chat models doing native code iteration outside that tool's Python packaging.

How this compares to agent harness workflows

Willison did not open a repository in Claude Code or Codex. He iterated in chat, then asked the model to format results like his research series. That is closer to how product managers prototype SQL UDFs than to how teams run hooked agent loops on monorepos.

Contrast with Battle Drones, where nearly all commits came from Claude Code across hundreds of iterations. The SQLite story shows narrow mechanical prompts still excel when:

  • The acceptance tests are numerical and fuzzable.
  • The deliverable is a self-contained directory, not a production service.
  • You can manually spot-check one .so file before merge.

For teams standardized on coding agents, the migration path is straightforward: drop the research folder into a repo, wire build.sh into CI, and let agents extend parse_number for locale-specific symbols under the same fuzz harness.

Links to wider Claude and local-AI coverage

This sits beside other November posts on Opus 5.5 capability and limits:

  • GDPx agentic benchmark scores show frontier models still fail most long-horizon tasks even while they ace tight numeric coding loops like this one.
  • Weight-space editing experiments quote Willison's earlier work interpreting weights locally, a different axis of "model meets low-level code."
  • Our MLX Apple Silicon guide covers local inference stacks; SQLite extensions pair naturally with on-device analytics when you do not want a server between CSV and chart.

If you embed SQLite inside agent tools, remember loadable extensions are native code. Review them like any supply-chain binary. Sandboxing patterns from our agent sandbox comparison still apply when an agent can LOAD EXTENSION from an untrusted path.

Red-team report folder for validating SQLite parse_number extension fuzz testsRed-team report folder for validating SQLite parse_number extension fuzz tests

Image: Library illustration for correctness testing discipline.

Limits and caveats

  • Locale: Both C paths ultimately depend on strtod on slow paths; README warns strtod respects the host locale unless the fast path handles the input.
  • Model authorship: The research README states LLM-generated text and code; human review still matters for security and maintenance.
  • Alpha Rust crate: sqlite-loadable is labeled alpha in the dependency table; expect API churn.
  • Not a SQLite release: Simon's work is third-party. Upstream SQLite docs remain the authority on extension APIs.
  • Chat versus Code: Reproducing this exact workflow needs Opus 5.5 access and manual copy-out; it is not an official Anthropic recipe.

What people building with agents should try

  1. Scope extensions narrowly. One scalar function with a written spec beats "build me a database engine."
  2. Demand fuzz parity across language variants before picking a winner.
  3. Measure net ns/row, not wall clock on toy tables.
  4. Publish research folders so teammates diff prompts, not only binaries.
  5. Promote winning code to CI once chat iteration stabilizes.

Packaging for teammates who do not use Claude

If you want others to review the work without an Anthropic login, mirror the simonw/research folder into your org git, pin the bench.py seed, and attach results/fuzz.txt to the pull request. Reviewers then argue about strtod fast paths and rusqlite closure overhead, not about chat transcripts. That habit transfers directly to agent pipelines that emit SQL against customer exports: the extension becomes a versioned artifact, while the prompt stays disposable. For embedding-heavy stacks that also load vectors beside SQLite, see how pgvector and peers compare when you outgrow single-file analytics.

Related reading

  • Simon Willison's November 8 announcement
  • Full GitHub research tree
  • LLM 0.37 CLI release from the same author
  • Battle Drones and Claude Code iteration count
  • GDPx and Opus 5.5 agentic scores
  • MLX local model guide for Apple Silicon
  • Agent sandboxes for untrusted code paths
  • Zvec and in-process data engines

Benchmark figures and file sizes are taken from the simonw/research README as of November 8, 2026. Claude model availability and chat features may differ by account region and plan.

Spotted something out of date? Let us know.
Daily briefFrom Yash · 350K+ students taught

Catch up on AI

One AI story explained in plain English, plus one thing to try. Every day, free. Unsubscribe anytime.

  • ✓ Free
  • ✓ One email a day, no spam
  • ✓ Unsubscribe anytime

People in this article

  • Simon Willison →Independent open source developer and creator of Datasette
Explore people in AI →
Yash Thakker

Written by

Yash Thakker

Yash is an AI expert with over 300K learners. Join his workshops →

View Yash Thakker in People in AI →

Related posts

Oct 7, 2026

Boris Cherny's Opus 5.5 Acquired Home Depot Companion: Prompt and Method

On October 6, 2026, Claude Code lead Boris Cherny shared a Claude artifact: an interactive, illustrated companion to the Acquired Home Depot episode, with a scrubbable timeline, data visualizations, sliders and watercolors drawn in code with OpenCV. He posted the prompt. Here is what the page contains, why it works, how to reproduce it for your own backlog, and the accuracy and copyright cautions.

Oct 7, 2026

TasteVal: Claude Opus 5.5 Scores 2.3x Human Experts on Research Taste, With Big Caveats

TasteVal, a paper posted October 2026, measures experimental research taste as compute efficiency and reports Claude Opus 5.5 at a 2.3x multiplier over the best human expert attempts, with a 95% confidence interval of 1.15 to 4.37, at roughly one thirtieth of the cost. Frontier models are improving fast on it. Here is what the number means and what it does not.

Oct 3, 2026

Antigravity Adds Claude Opus 5.5 and Sonnet 5.5 for Pro and Ultra, and Retires GPT-OSS and Claude 4.6 on November 2

Users spotted Claude Opus 5.5 and Sonnet 5.5 arriving in Antigravity on October 3, 2026, along with a warning that older third-party models will be removed. Google's own models page backs the core of it, including a catch for trial accounts and a November 2 removal date. Here is what is confirmed, what is rumor, and how to prepare.