You hand it shapeless information. It decides how to keep it, how to relate it, and what it should look like when you ask for it back.
Everything below is an attempt to build the first one properly, and to leave nothing in the way of the other two.
The screen you need at four o'clock is written at four o'clock and thrown away by five, because remaking it is cheaper than finding it.
The version you use is not the version anyone else uses. It was assembled around your files, your words, your way of counting a week. There is no shared build to ship to both of you.
Eventually there is no artifact to name at all. No install, no login, no product page, no icon. A folder, a conversation, and something that has read every word in it.
Most of the software that should exist was never written. Not because it was hard — because it was small. A shoe shop's jobs. A market stall's stock. One person's weight, one person's invoices, one person's patients. Each of those was a real application that nobody could ever justify building, so the world settled for a notebook, a WhatsApp thread with itself, and a spreadsheet that stopped matching reality in March.
The dark matter of software. Almost everything ever needed is in the dim part. Too small to build, never too small to need.
BlobWare is aimed at exactly that mass, and at nothing else. Single user. Local files. One subject per folder. It is not enterprise software with the price removed; it is the shape of the thing that was never made.
There is no schema to design, no form to fill, no screen someone drew for you in advance. There is a folder of plain files and a model with full write access to it.
you: I have a shoe shop, I charge 4500 an hour
→ rules/prices.md created · data/jobs.csv created
you: Marta came in, two resoles
→ data/jobs.csv +1 line
you: show me the week
→ [a chart and a table open beside the chat]
Every schema ever written was a bet placed before the game began: these are the things that exist, these are their fields, and anything that turns up later will have to be bent until it fits. That was a reasonable bet while the alternative was code that could not read its own data. It is not reasonable now.
Design the schema on the tenth message, not the first. Nobody was ever asked to predict the tenth message on the first day, which is the only reason it can be right.
Somewhere ahead there is a person who has never seen a dropdown. Who has never been told that a name is limited to forty characters, that a date must arrive as DD/MM/YYYY, that this field is required — required by whom? By a stranger who drew that screen four years ago in another country, guessing at a life they would never see.
Your children will not know what a required field is. Forms were never for you. They were armour for code that could not read what you wrote — and that code is ending.
You describe what happened, in the words you already use, and something that has read everything else you ever said works out where it goes. The form goes with the code it was protecting.
The model writes one ordinary reply and puts its file operations in the same message, tagged. The engine strips them out, shows the prose, applies the rest, and commits. Toggle the right-hand pane to see what the model actually sent.
The chat starts empty.
An empty Blob: three folders and a log.
Tool use would be the tidier protocol, but it costs a second round trip on every message that writes anything — and here almost every message writes something. Tags cost one call. The price is a parser, one rule (a closing tag sits alone on its line), and a repair path for when something does not apply.
Two claims about the near future. Both are testable, and if either turns out false the design deserves to be thrown away.
So the right place for judgement is the model, not code — and the right amount to delegate is more than feels comfortable today. An app built around what a model can just barely do is obsolete when it can do three times more.
Two years of a one-person business is a few tens of thousands of tokens. So there is no retrieval, no index, no embeddings, no chunking. The whole Blob goes up on every message.
The parts of this that look most extreme are the parts aimed at 2028. Sending the entire corpus on every message looks wasteful now and looks obvious when context is ten times longer at a tenth the price. Rewriting whole files instead of editing lines looks crude now and is simply correct once output is cheap. Having no schema looks reckless now and looks like the only sane option the moment a model can restructure two years of your data in a single pass.
It ages forward. Delegate more judgement than feels comfortable. Nothing here has to be rewritten to take advantage of a better model — that is the entire point of building it this way.
The usual arrangement is an application that calls a model for the hard parts. Here it is the reverse: the model is the application, and the code is plumbing around a folder.
The Python does four things. It reads a folder into a prompt. It parses tagged operations back out of the reply. It writes files and commits them. It serves a page. It contains no notion of a shoe shop, an appointment, a price or a date, and it never will.
Everything that looks like product behaviour — where a fact belongs, whether a CSV needs a new column, what a chart should show — lives in a 1,001-word system prompt. That is not a gap to be filled in later with real code. That is the architecture.
It also means this application has no roadmap in the ordinary sense. It gets better the day a better model ships: no release, no migration, no download, nobody touching the repository. Every piece of software ever written has depreciated from the moment it was compiled.
No release notes. It simply got smarter overnight. The changelog is written by someone else, at another company, and it is good news.
Most questions want a sentence. Some want a picture, and when one does, the picture is written on the spot and thrown away afterwards. That inverts a hundred billion dollars of habit: the interface stops being the thing that gets designed, shipped, versioned and maintained, and becomes a by-product of a question — like steam.
Interfaces on demand. Discarded on use. Ten seconds of work, no ticket, no designer, no release. A window that existed for eleven seconds.
One rule makes them work: an artifact never contains data, only the code to read it. It declares which files it needs; the engine hands those files over at open time. So a chart written in March shows September's numbers in September, untouched.
This is a real one, running here. Change a status — the chart recomputes from the table, the way it would from the CSV.
data/jobs.csv · 5 rows
no numbers are written into this panel
That rule also settles the arithmetic problem. A number computed in the browser from the CSV is a number that was computed, not remembered. Panels can write back too — a button that adds a row costs nothing, because it does not call the model.
Nothing is installed here in the sense you mean. You make a folder and give it a subject — the shop, the treatments, the boat, the year. From that moment the folder is an application: it has a memory, a way of showing itself, and opinions about how its own contents ought to be arranged. It acquired all of that the instant something that had read every word in it was pointed at the path.
One folder. One subject. One application. The install step of the future is naming the folder. An empty directory is a blank application.
shoe-shop/
rules/ how things work here. Injected before the data.
data/ what happened. CSV, JSON, notes, attachments.
artifacts/ HTML the model wrote and might reuse.
log.md what it remembers past the last few messages.
chat.jsonl the conversation
.git/ the undo
There is a particular sadness in old software. The company folds, the format dies, and a decade of somebody's actual work becomes a file that no living program can read. Nothing here can do that to you. It is folders and plain text, in a shape any machine can open, forever, including machines nobody has built yet.
No database. No format anyone but you owns. If this project is abandoned tomorrow you keep all of it, and every file still means exactly what it meant. The most futuristic decision in the design turned out to be the oldest format on earth.
Eight exchanges go up verbatim. Older than that, the model has only what it
chose to write into log.md — decisions, corrections, the reason
behind a change. An unbounded transcript makes every message more expensive
than the last, and most of what is in one was never worth keeping.
The old discipline was prevention: validate, constrain, refuse. Refusal is the most expensive thing a system can do, because the bill arrives as everything it could have done and did not. This one makes the opposite trade, deliberately.
Every message is a commit. If a reply mangles a file, you do not repair the file — you step back to the second before it happened, and the ruined version stays in the record, so the files, the log and the conversation go on agreeing about what occurred. You never have to know it is git.
The safety net is not prevention. It is reversal. The bad turn stays in the history rather than being erased. Every message has a yesterday.
It trusts the model, and it pays for that trust with an undo. Prevention constrains everything and costs a fortune. Reversal constrains nothing and costs almost nothing. The next decade belongs to systems that can be wrong cheaply.
Most repositories show you what was built. The more useful record is what was taken out, and in what order somebody stopped believing it.
It spent its entire design on how do we know the number is right? Quotes anchored to files and verified character by character. Arithmetic in an executor the model could not reach. A closed menu of seven operations. Nine enumerated ways to refuse. About six hundred lines of it.
It worked. It was also the wrong thing to build first: it answered is the number right before answering how does anything get in, and it bought correctness by making the system unable to do most of what a person actually wants.
An interpretation committed at write time, by someone who did not yet know what would be asked.
| Removed | What it was for | What removing it bought |
|---|---|---|
| The declared schema | A file listing which types exist and what fields they have | Types nobody has to guess before the first message |
Extracted fields: |
Numbers pulled out of the text at write time and frozen | The value stays in the sentence, where it can be re-read |
| Six frontmatter fields | status, supersedes, valid_from… recording what replaces what |
What a statement means is worked out when somebody asks |
| A menu of seven operations | The closed list of things a question could compute | Arithmetic the menu could not express |
| The verification engine | ~600 lines of anchored quotes, sealed arithmetic and enumerated refusals | An application, instead of a guarantee about one |
What replaced the guarantee is a cheaper arrangement — plain files you can read, one commit per message, and arithmetic that mostly happens in the browser from the CSV rather than in the model's head. That is weaker, and it is written down here rather than glossed.
Two of the three sentences at the top of this page are still ahead. The code does not have to change for them to arrive; that was the requirement the whole design was built against.
This is a prototype and a position, not a product. The list below is kept
current in V1.md.
MIT. Fork it, gut it, disagree with it. The parts most worth replacing are the ones easiest to find:
| If you want to change | It lives in |
|---|---|
| What the app actually does | blobware/prompt.py — the system prompt is the product |
| Tags → proper tool use | blobware/ops.py |
| The folder convention | space.FOLDERS |
| Another provider | blobware/llm.py — two wire formats sit side by side |
| What a panel can do | web/artifact.html |
git clone <this repository>
cd blobware
pip install -r requirements.txt
python run.py
Gemini has a free tier, so you can try the whole thing without spending
anything. Both test suites run offline and cost nothing:
tests/loop.py, tests/panels.py,
tests/gemini.py.