Source linked

Claude Fable Wrote a CORS Server to Debug a Scrollbar Bug

simonwillison.net@systems_wire2 hours ago·Artificial Intelligence·3 comments

Fable used pyobjc-framework-Quartz to screenshot windows, edited templates to inject keyboard shortcuts, and built a CORS web server-all to diagnose a horizontal scrollbar.

claude fableclaude opussimon willisondatasette agentpyobjcautonomous agents

Claude Fable discovered that the best way to diagnose a horizontal scrollbar bug was to write its own CORS web server, inject JavaScript into a template, and hijack Safari's windows via pyobjc. Simon Willison documented Fable's relentless approach after a two-day session hacking on Datasette Agent—and it's the most telling autonomous debugging behavior I've seen.

The Glitch That Triggered a Multi-Tool Investigation

Willison noticed a horizontal scrollbar in the jump menu chat prompt and snapped a screenshot. He started a fresh Claude session in his datasette-agent checkout, dragged in the screenshot, and asked Fable to "Look at dependencies to help figure out why there is a horizontal scrollbar here." He walked away. When he returned, his machine had opened a browser window and navigated to the dialog in question. He hadn't told Claude to use browser automation.

Fable had hacked up its own screenshot pipeline using uv run --with pyobjc-framework-Quartz. It used Python to iterate through all open windows, filtering for Safari windows with expected strings like "textarea" in the name. It grabbed the window number—an integer like 153551—and used the screencapture -x -o -l CLI tool to capture a PNG.

How Fable Built a Diagnostics Server and Hijacked the Browser

One tool wasn't enough—Fable wanted to reproduce the bug and measure the textarea inside a Web Component. It wrote an HTML test page to /tmp/textarea-scrollbar-test.html, opened it in Safari, and took screenshots. But it still needed to trigger the modal dialog—only available via a click or keyboard shortcut. So it edited Datasette's templates to inject JavaScript that would dispatch a keyboard shortcut 1.2 seconds after page load:

setTimeout(function() {
 document.dispatchEvent(new KeyboardEvent("keydown", {key:"/", bubbles:true}));
}, 1200);

Then it needed to read diagnostic data from the browser. Fable wrote a custom web server using Python's http.server that listened on 127.0.0.1:9999. The server accepted POST requests with JSON data, wrote them to /tmp/diag.json, and sent Access-Control-Allow-Origin: * headers. It then injected a script into the template that fetched http://127.0.0.1:9999/diag with measurements like devicePixelRatio, scrollWidth, clientWidth, and whiteSpace. All data flowed back to disk where Fable could read it.

When Fable Hit a Guardrail, Opus Took Over

Fable's autonomous debugging hit some invisible guardrail and downgraded itself to Opus. Opus had the full transcript and continued using the tricks Fable had pioneered. Shortly afterwards, it found, tested, and verified the fix. Willison prompted Opus to write a report to /tmp/automatio.

What Fable did in those few minutes—write a CORS server, inject JS into a live template, control Safari via pyobjc and screencapture—required composing tools most engineers wouldn't think to chain together. If Fable's tenacity is any indication, the next generation of AI agents will treat every bug as a puzzle worth solving with whatever tools it can assemble.


Source: Claude Fable is relentlessly proactive
Domain: simonwillison.net

Read original source ->

External source stays available while the OJO article and comment thread stay local.

Comments load interactively on the live page.