Your folder never leaves your machine.
The part people don't believe until they try it: a web page can open a real folder on your disk, list it, read it, write to it, parse the .git directory sitting inside it, read your actual Excel files, watch a folder and process what you drop in — and, if you want, run node and python on your machine for real. No upload, no server, no Electron. Here's how that layer is built, tool by tool, and where the line is drawn.
The hinge: one folder, granted once
Everything here rests on the File System Access API. You click, you pick a folder, the browser hands the page a handle — and that handle is the entire world the agent can touch. Not your home directory. Not "your files." That folder.
That constraint is doing more work than it appears to. A hosted coding assistant has to convince you to upload a repository; the honest answer to "what happens to my code" is a privacy policy. Here the answer is a scope: the page can't read what you didn't grant, and there is nowhere for it to send anything anyway.
Five tools, and why they're shaped like that
The agent's whole access to your project is five functions. The design pressure here isn't elegance — it's that a 4B model has to succeed with them:
| Tool | What it does | The detail that made it work |
|---|---|---|
code.tree | lists the project | the model orients before it guesses |
code.read | reads a file | paginated, 100 lines at a time, and it can centre on a line number — this single change moved the hit rate more than any prompt tweak |
code.search | greps the project, with line numbers | search-then-read beats read-everything: small models are good at locating and bad at holding |
code.edit | surgical edit | the editor refreshes instantly, so you watch the change land |
code.write | writes a whole file | the escape hatch, for new files |
code.read to 100 lines and letting it centre on around: 42 changed the agent's success rate more than swapping models did. Give a small model a smaller job and it stops being a small model.
The editor is the real one
The editor isn't a textarea with syntax colours: it's Monaco 0.52.2, the actual VS Code editor core, loaded from a CDN with its own AMD loader, wired to a file tree, tabs and Ctrl+S. There's no build step in this project at all — vanilla ES modules, served as-is.
And a small thing I'm fond of: the git status line — current branch, last commit — is produced by reading and parsing the .git directory directly. No isomorphic-git, no dependency. .git/HEAD points at a ref, the ref file holds a hash, the object gives you the message. Enough to orient you; committing is left to the agent or the terminal.
Beyond code: what a chat can do with your folders
The sibling app takes the same primitive somewhere else. Once a folder is granted, plain-language requests become filesystem work:
- Real spreadsheets.
.xlsxis parsed for real (SheetJS), so "visualise sales.xlsx" reads your actual sheet and generates a chart app from it — locally, from a binary Excel file, in a tab. - Folder automations. "Watch inbox and drop processed files in outbox": a poller re-lists the source folder while the tab is open, converts
.xlsx/.xlsto CSV and copies everything else, remembering what it has already handled by name and mtime — so re-saving a file reprocesses it, and nothing gets done twice. - Scheduled tasks. "Remind me in 20 minutes" fires later, from the page itself.
- A vault. Secrets encrypted with AES-256-GCM, key derived by PBKDF2, 310,000 iterations, held only in memory, auto-locked after 5 minutes, ciphertext in IndexedDB. Lose the master password and it's gone — there is no recovery path, because there is nobody to recover it from.
Each of those sits behind a permission scope that's asked for the first time and revocable afterwards. The tool layer refuses before the tool runs, not after.
The one thing the browser can't do — and the smallest possible fix
A web page cannot run npm test. That's not a gap to be clever about; it's the sandbox doing its job. So there's an opt-in bridge: a ~6 MB binary you download and run yourself, which opens a WebSocket on 127.0.0.1:8765 guarded by a token generated at startup. Connect the page to it and the agent gets real execution — node, npm, python — with the output streaming back into the chat.
Note what it is not: not a hosted runner, not a container in someone's cloud, not a daemon that phones home. It's a local process, on loopback, that you start and stop. The default remains no-install; this is the door for people who want the agent to close the loop by running the tests it just fixed.
The honest edges
- Chrome and Edge, effectively. File System Access isn't universal. Safari and Firefox users get the chat and the model, not the folder — and pretending the API is portable would just waste their time.
- Embedded iframes block the picker. The apps also run as Hugging Face Spaces, and inside that iframe the folder picker is blocked by design. The Spaces README says so and links to the full-screen URL. An honest caveat beats a mysterious dead button.
- Automations need the tab open. No tab, no poller. Service Workers with Periodic Background Sync could lift that; today it's a limitation stated out loud in the README.
- Permission fatigue is real. Every scope asks once. Ask too often and people click through without reading, which is worse than not asking.
What the whole series adds up to
Model, runtime, harness, editor, filesystem — five layers that all used to imply a server, a subscription and an upload, running in a tab that costs its author nothing to serve. That's the change worth noticing. Not that a browser can do inference: that the whole vertical fits, on hardware people already own, with the privacy question answered by architecture instead of by policy.
Source: js/tools/code.js, js/ide.js, js/bridge.js in elffuss-code; js/tools/{fs,watch,vault,apps}.js in elffuss-claw. Series: the stack · the runtime · the harness.