August 2, 2026
Read Gives Up URLs for Good
A single tool now owns every URL Chalie touches, read got demoted to files only, and a late-night fix stopped the installer's own verification matrix from reporting success on an install that didn't actually work.
Read had been doing two jobs for a while — files and URLs both — and the seam between them was never clean. Hand it a URL and it would fetch, convert, and hand back text; hand it a file path and it did something completely different under the same name. That’s the kind of ambiguity a strong model shrugs off and a weaker one trips over, guessing at which behavior it’s about to get. Today read gave up URLs for good. There’s now exactly one tool that owns fetching a URL, and read only knows about files that already exist on disk.
web_fetch is the new owner, and it does what actually makes sense for whatever comes back. HTML converts to markdown by default and lands in a page store, overwriting in place if you fetch the same URL twice; ask for the raw HTML and it keeps that instead. Anything else — a PDF, an image, an archive — streams to a downloads folder with a note on how to read it. Short pages come back inline; anything over 20k characters returns only the saved path, never a silent clip that quietly drops the second half of a page. It reuses the same SSRF protection and streaming cap the rest of the fetch path already had, and refuses file: and data: URLs before it opens a socket.
Splitting the tool out surfaced two bugs sitting in the old one. The guard that blocks editing a file you haven’t re-read since your last edit was counting a read as “seen” even when that read had errored — a too-large file returning nothing still counted as looked-at. And downloads were named off the bare URL filename, so the same filename from two different hosts silently overwrote each other, with a stray .. in a path able to crash the cleanup step outright. Both fixed with one shared naming rule, collision-free and safe against path traversal.
Riding in the same change: email got a similar tightening. Search rows dropped a snippet field nobody used, an empty search now comes back as a named error instead of a quiet nothing, and the more interesting fix — Chalie’s own sent mail was showing up in search as if it were new correspondence. Every outgoing message now stamps its own Message-ID into a ledger, and search and read check incoming mail against it, so a reply syncing back through the inbox reads as “you already sent this,” not as something new to react to.
Then, late at night, a different kind of bug: the install verification matrix had been reporting green on platforms where Chalie didn’t actually work. Arch Linux exited success while its browser component failed outright, missing a system library the install script never checked for — because the fallback for an unrecognized distro was to warn and carry on, assuming the build tools were already there. That fallback is gone; an unsupported distro now fails the install and says so, naming the two package managers Chalie actually supports. Verification is all-or-nothing now too: a platform passes only if every check — the app responds, the interface renders, a script actually runs — comes back proven, and a missing result counts as a fail, not a shrug.
Two structural cleanups and one honesty fix, in a single day. Next is watching whether the URL/file split holds up under real use the way the file-tool split from a few days back did, and whether the tighter install matrix catches the next broken distro before a user does.
-
Added web_fetch as the single URL-owning tool — fetches, converts HTML to markdown by default, and persists pages or downloads with a 20k-character inline cap and no silent truncation
-
Made read file-only; retired web_download entirely and repointed every skill playbook and search alias at web_fetch
-
Fixed two bugs the split exposed: the stale-read guard counting errored reads as “seen,” and download filenames colliding across hosts
-
Gave email a sent-mail ledger so Chalie recognizes its own outgoing messages echoing back through the inbox instead of reading them as new
-
Hardened the installer’s verification matrix to fail loud on unsupported distros and treat a missing result as a failure, after Arch reported a successful install with a broken browser component