Most software is a bus terminus
…and what replaces it when the application disappears. A paradigm I've been calling Pliantware.
The bus to Kollur was at 7:15. I reached the Bengaluru terminus at 7:00, which felt like plenty of time right up until the taxi left me at the wrong end of it.
It’s an enormous place. My bus was parked at terminal 2; I was standing in terminal 1. So now I had ten minutes and a question: how do you get from here to there. I asked a few people. Nobody knew. That’s the thing about a bus terminus, everyone in it is a stranger to the city, same as you. I found a policeman. He waved a hand in a direction and said it’s very close.
He was right. From the top of one of the walk-over bridges I could actually see my bus. I just couldn’t find a way to reach it. The bridge didn’t come down anywhere near it. I ran down to the ground and went straight for where I’d seen it, and hit a long wall with locked gates. No opening. I doubled back through a knot of little paths, none of which went where I needed. The driver had my number and kept calling, and I kept trying to explain a thing I myself could not see.
Eventually some random person took pity and showed me the one narrow gap, a slot you’d never find on your own, and a thin path through it. I made the bus.
Here’s what stayed with me. That terminus had everything a government builds into a terminus. An enquiry counter. A website. A toll-free number. Signboards. Not one of those facilities could do the single thing I needed, which was to take me from the exact spot I was standing to the exact spot the bus was parked. Ten feet of wall beat the whole apparatus.
Most software I’ve used in twenty-odd years is that terminus.
There’s always a path from your situation to the thing you want. The software even has a feature for it, somewhere. But finding the path is on you: click here, no, back out, try that menu, file a request, wait two quarters. You do the random walk into walls. The software stands there with its enquiry counter and its signboards and watches you do it.
I didn’t set out to have a theory about any of this. I started using Claude because I was curious.
The slow climb
I’d tried the others too, OpenAI and Gemini when they showed up. I stuck with Claude for a reason I couldn’t name at the time: it just seemed to get what I actually meant. (I learned the word for that much later. Alignment.) At first I kept it on a short leash, unit tests and code review, I wrote the real code myself. Then it got good enough that it wrote the code. Then I noticed I was asking it things that had nothing to do with code.
Then MCP landed, and that’s the part that changed everything. The moment I could give the model real tools, I started building my own: a filesystem server, wrappers around APIs I used, a thing to drive FFmpeg, another for pandoc. The model wasn’t trapped in a chat box anymore. It could reach into my actual work. After that I stopped reaching for apps for a whole class of problems and just described what I wanted.
The small surprises
The first time it really landed was a GST invoice. (I’m in India; if you’ve dealt with GST you feel this already.) My accountant had chased me four times, the deadline was two days out, and I didn’t even know what a correct invoice looked like, the rate, the mandatory fields, the format. Normally that’s an afternoon lost to Google and a half-finished Word doc bouncing between us. Instead I had Claude pull the current rules through Perplexity, checked the rates against the source myself, and told it to generate the invoice as HTML. A few minutes later the accountant had a clean file with the math already right, and was almost suspicious of how fast it came back. What stuck with me wasn’t the speed. There was no invoicing app. I never bought one. There was my data, a couple of tools, and a conversation, and out the other end came exactly the artifact I needed.
The next one changed how I thought about it, because this time the useful thing wasn’t conjured out of nothing. It was already sitting in my own data, and I couldn’t see it. One month my credit card bill was higher than usual and I couldn’t say why. So I pulled a year of statements, and instead of squinting at twelve PDFs I had a script load all of them into a small SQLite database on my laptop. (By now I was driving the model through the API with my own MCP servers, so “load these into a database” is a sentence, not a project.) Then I just asked questions. “What’s recurring” turned up three streaming subscriptions I’d forgotten I was paying for and three SaaS tools I’d stopped using and never cancelled. None of it was hidden. It had arrived in my inbox every month for a year. I’d just never had a way to ask.
The third one wasn’t about generating anything or finding anything. It was about judgment. A consulting firm I worked with decided, one morning, that it could move its consultants over to another company like a herd being sold. Calls, follow-ups, emails, all pushing me to sign a fresh agreement at lower pay, and to do it quickly. I dropped the whole email thread into Claude and asked it what was actually going on. It read the exchange more clearly than I had. It pointed out which of my questions they kept stepping around, the ones that actually mattered, and it turned out I was holding a far stronger hand than I’d assumed. We drafted the replies together. I took a firm line: the original agreement didn’t permit this transfer, and I wasn’t going to be treated as having accepted anything by staying quiet. They backed off. No app for that, obviously. But also no template, no script, nothing pre-built. The useful thing was judgment applied to my specific mess, at the moment I was in it.
Somewhere in here I stopped doing this ad hoc. The pattern repeated often enough that I built myself a standing thing for it, a desktop assistant wired to my files, my tools, and these little databases. It’s been running on my own machine for months. I bring it up only because the cheapest way to show a pattern is real and not a daydream is to point at one that actually runs.
The itch
It took me a while to see these weren’t three separate conveniences. Each time, something had walked me the last mile, through the one narrow gap I’d never have found alone. The invoice. The forgotten subscriptions. The standoff with the consulting firm. The useful thing was the stranger at the terminus, not the terminus.
And once you’ve seen that, you can’t stop seeing what’s missing from everything else. All that software with its features and its menus, none of it ever takes you the last mile. It can’t.
It was built before it ever met you.
The solution I needed in each of those moments didn’t exist on a shelf, in any app, because it didn’t exist until my situation did. It got assembled when I asked, out of my data and a couple of tools, and not one second before.
What’s actually ending
You’ve probably heard the framing that English is the new programming language. Karpathy put it best; you describe what you want, the model writes the code, and the cost of building software falls through the floor. It’s true as far as it goes. But look at what it still quietly assumes: a program gets written. You’ve changed who writes it and what language they write it in. At the end there’s still an application, a built thing with its logic welded to its interface, that somebody has to run and maintain and version and eventually throw away and rebuild.
That’s a faster horse. I got interested in the car.
The shift I actually believe in is that for a large class of software, the application stops being a thing you build ahead of time. Not the data. Not the rules. The application, the bespoke, shipped-in-advance, you-bend-to-fit-it bundle. That’s the part that dissolves. The behavior I needed in each of those stories was assembled at the moment I needed it, over data I already had.
This is the place people hear “so, no more programming” and get it backwards, so let me be exact. There is more code underneath this, not less. A generic backend that holds the data and enforces who is allowed to touch it. The tools the model calls. The clients people talk through. All of it real, programmed, and it has to be very good.
Programming doesn’t end. It relocates.
It moves down into a stable infrastructure layer, built once and changed rarely, so that everyone living above that line stops needing it. Your operating system kernel is a million lines of C and nobody calls answering email “programming.” The code receded until it was furniture.
You build the infrastructure at one hundred percent so the rest of the world can live at zero.
Pliantware
I needed a word for software that works this way, because “app” is exactly the thing it isn’t. I’ve been calling it Pliantware. Software that takes the shape of the work in front of it, and sets hard only where it has to, instead of making you take the shape of the software.
The single-user version already runs; that’s the desktop assistant. The hard problem, the one I’m writing a whole book about, starts the moment it isn’t just me.
When it isn’t just me
I started getting pulled into conversations with companies that wanted some version of this for their teams, and the same shape showed up that I’d hit at the bus terminus. Bigger, and a lot more expensive. Take an HVAC contractor, the kind of business I keep using as my worked example. Dozens of technicians, a parts supplier, someone running the schedule, customers calling all day. They bought the field-service software everyone in the trade buys. And the real business runs right next to it, in spreadsheets and a WhatsApp group and a whiteboard in the back office, because the software has no slot for “the part’s backordered, so we did a temporary fix and we’re going back Tuesday.”
This isn’t an HVAC problem. It’s everywhere, and people have written it down. There’s a line a SAP consultant on Hacker News says he actually teaches: “changing the business to fit SAP is preferable to changing SAP to fit the business.”[1] Read that twice. The software is the fixed point and the company is supposed to deform around it. A nurse put it more starkly, in a peer-reviewed paper on the workarounds people invent: “Even though I emptied the catheter bag at 11 pm, I enter this as emptied at 9.59 pm,”[2] because the system finalizes records at 10 and reality showed up late. Salesforce reps keep a private pipeline in Excel because they can’t change the CRM;[3] an Epic user in Montana has no dropdown for a patient who used to be male, so a prostate-cancer risk silently never makes the record.[4] Different industries, one complaint. Reality didn’t fit the schema, so the human either lied to the validator or kept a second, secret system that told the truth.
The vendors have made their peace with it. The polite phrasing is that their product is the system of record, the official ledger you keep for audit and compliance, and the actual work happens somewhere else, in the “system of work,” and gets copied back in afterward. A whole integration industry exists to automate that copying. That gap, the one everybody bridges by hand every day with a shadow spreadsheet, is the bus terminus at company scale. The path from the real work to the official record exists. Finding it and walking it is on the human, every single day.
Here’s what the new shape does to that. In the single-user world the permission question was trivial: it’s all my data, so the assistant can touch all of it. The instant there are many people over one shared dataset, that’s gone, and you hit the real engineering problem of the whole approach. It isn’t the conversation. The conversation is the easy part. It’s permission, who is allowed to read and write which tables, which columns, even which rows. The warehouse clerk and the marketer and a customer out on the open internet are all going to talk to the same system over the same data, and each is allowed to see and change a completely different slice of it.
So that’s what you build. A backend that holds the data and, more to the point, enforces who may touch what, down to the row. And once that backend exists, look at what the builder’s job turns into. In the old world the builder builds the application: the screens, the forms, the workflows, the reports, shipped frozen and identical for everyone, out of date the day it meets a real situation. In this world the builder sets up the data and the rules. These roles exist. This role may read these columns. That role may write these rows. This one only ever sees totals. And then they stop. There are no screens to build.
The one program that doesn’t go anywhere is the access policy itself, and it’s the most security-critical code in the building. That’s not a crack in the idea. That’s the load-bearing wall. It belongs in the infrastructure you build at one hundred percent and change carefully, not in the layer that gets assembled on the fly. Real policy is richer than rows and roles, too: conditional, time-bound, tangled up in who reports to whom. It’s a program. It should be.
Now go back to the contractor. It’s Thursday afternoon and a technician is standing in a restaurant kitchen with a walk-in cooler that’s died. The compressor he needs is backordered two weeks. He rigs a bypass that’ll hold the cooler cold through the weekend and tells the office he has to be back Tuesday when the part lands. In the old world that sentence has nowhere to go. A job is open or closed; there’s no field for “limping along on a temp fix, parked until a backordered part shows up.” So the fact lives in a WhatsApp message and a line on a whiteboard, and when the customer calls Monday morning, whoever picks up is guessing.
In the new shape he just says what happened, the way he’d say it to a coworker. Part’s backordered, I bypassed the compressor, it’ll hold but it’ll trip again, I need to be back Tuesday with the replacement. That one sentence is enough. It becomes a parts order to the supplier, a slot on Tuesday’s schedule, and a note on the cooler’s history, all at once, because nothing here is a fixed form the sentence has to squeeze into. No screen had to anticipate this exact situation, because the screen is built the moment the situation exists.
Monday morning, the customer calls. The dispatcher asks the system what’s going on with the restaurant and gets back what she’s cleared to see: temp fix in place, part due Monday, tech booked Tuesday at eight. She can tell the customer something true. The customer, on their own portal, sees one line, technician returning Tuesday with the part, and nothing about the margin on the job or where that tech is the rest of the week. The supplier sees a part order and no customer. The owner, closing out the month, asks how many jobs are sitting on backordered parts and gets a number that used to live only on a whiteboard. One spoken sentence from a technician, shown to four people as four different true things. The technician didn’t decide who gets which slice. The data layer did. And for once the record holds what actually happened, because the record and the work are the same thing now.
The same spoken sentence, shown to four people as four different true things. The data layer decides each slice, not the technician.
But this is just an agent
If you build software you’ve been waiting to say it, so let me say it for you. This is an agent with some tools wired to a database. People ship that today. Row-level security is a decade old. Scaffolding a form from a schema is older than that. Where’s the new thing.
The new thing is smaller than it sounds and bigger than it looks. In every system you’ve ever built, somebody decided ahead of time what the screens were, what the forms collected, which reports existed. The application is that set of decisions, frozen. An agent with tools is still wired to do a defined job; you wrote the job down. What I’m describing doesn’t write it down. The clerk’s form, the manager’s report, the customer’s portal, none of them exist as built artifacts. They’re composed when someone asks, against what that person is allowed to touch, and most of them are thrown away after. No two requests have to produce the same screen, because no screen was the product. The data and the rules are the product. The screen is exhaust.
I know what that sentence does to anyone who’s run support. If the interface is conjured fresh on every click, how do you train a new hire, how do you write a repro, how do you regression-test anything. You don’t conjure it fresh every time. The second time someone needs that form, the system promotes it to a pinned artifact you can name, version, diff, and test like any other, and a builder can pin one deliberately too. Only the genuine long tail, the request nobody anticipated, gets built live. The terminus had a signboard for the routes it expected. This builds you a path for the one it didn’t.
The old unit is a frozen bundle you bend to fit. The new one builds the infrastructure once and assembles the rest on demand.
Where the determinism lives
The first real question a careful engineer asks is where the exactness goes. Tax. Credit limits. Who can approve what. The discount that has to be the same discount every time. If there’s no application, where does that live, and what stops it drifting.
Two places, and neither is a program in the old sense.
Say a marketer wants a coupon-code discount the company has never offered before. There’s no six-month change request, but there’s still a gate, because a rule that runs on every sale is exactly the kind of change you want a name and a timestamp on. The marketer describes the discount and who it’s for. The system adds a coupon field to the sale and drafts a line for the procedure that gets consulted on every sale, in plain language, the same standing instruction you’d hand a new cashier: if this code is valid, take this much off, here’s how to check. Whoever is allowed to change pricing approves it, signed and version-controlled, and the change request that used to take two quarters becomes a conversation that still leaves a record. From then on the engine reads that line on every sale and applies it, the same standing rule for everyone. That’s the first place exactness can live, though it’s worth being exact about what it is. A procedure the engine follows at runtime is readable and auditable, version-controlled, in words a human wrote. It gives you the same intent every time. What it doesn’t give you, on its own, is a guarantee of the identical result down to the last edge case, because it’s still a model reading an instruction. For that you reach for the second place.
The second place is a script. When something runs often enough, or has to be exact to the paisa, the procedure hardens: the model writes a small function, tests it, and from then on the procedure calls the function instead of doing the arithmetic in its head. It runs like a lambda, fixed output, no model in the loop for that step. CalculateTax stops being a paragraph and becomes a tool.
So the exactness didn’t disappear, and it didn’t stay a frozen application either. It lives as a document the engine follows or a script the engine calls, and it moves between the two as the work demands. That movement is the part that isn’t an agent over a database. The behavior has somewhere to crystallize, and a human can read it in both forms.
The parts I haven’t solved
I’ll tell you the parts I haven’t worked out, because you’d find them in five minutes anyway.
The first is security, and it’s the one that genuinely worries me. A model running with your permissions can be talked into misusing them. Feed it the wrong text and the instruction hides inside the data it’s reading. The classic confused deputy.
Start with what’s bounded, because it isn’t nothing. The model can’t do anything you couldn’t already do; it acts inside your existing permissions and can’t escalate past them. It can’t invent operations either. It can only call the same fixed, audited set of procedures and scripts that everything else goes through, so a poisoned email can ask for a refund but can’t conjure a new way to move money. And authoring is its own privileged act. Writing or editing a procedure or script is a builder operation, gated and signed by a named person, not something the runtime model does on its own, so the poison can ask to run money through the existing rails but can’t write itself a new one. Every action is attributed to a responsible human and logged. The dangerous ones route through approval. The blast radius is whatever that one user could already have done by hand, no more.
What’s left after all that is the real hole, and it is real. Inside that envelope, with your legitimate permissions, the deputy can still be argued into doing a legitimate-looking wrong thing. Enforcing at the data layer narrows it. Teaching the model to tell the data it’s reading from the instructions it’s following narrows it. None of it closes it. I think it’s the central engineering problem of this whole approach, and I’d rather name it than dress it up.
The second thing people raise looks like a hole and is actually the opposite. “What is our refund policy, exactly?” sounds like the question this can’t answer, because there’s no application to open and read. It’s backwards. Today that policy is smeared across a validation rule in the UI, a stored procedure, a config table, and three people’s memory, and reconstructing it is archaeology. Here it’s the procedure the engine follows on every refund. One document, version-controlled, diffable, in words. Every decision it made is logged with the data it saw and the procedure it applied, attributed to a person. And keep one distinction straight: a log proves what happened, but to show exactly what someone saw on a Tuesday in March you snapshot the artifact they were shown along with the version of the procedure that produced it. The pinned forms and the scripts replay the same way every time; the one-off view composed live gets photographed, so the auditor sees the page itself, not a reconstruction. The audited system of record and the real system of work, which in most companies are two different things held together by a spreadsheet and a prayer, finally become one thing.
I’ll concede one piece of this to the other side, because it’s true and it matters. Not all rigidity is laziness. Some of it is a control. The Montana hospital with no dropdown for that patient has a schema feeding billing codes and a state registry downstream, and a field that goes fluid can break them silently. Segregation of duties, the rule that whoever creates a vendor can’t also approve paying it, is rigidity on purpose. So Pliantware doesn’t get to dissolve everything, and the real skill is choosing what stays hard. The downstream contracts and the separation-of-duties rules belong in the infrastructure you build once and change carefully. What dissolves is the frozen guess about how the work in front of you is supposed to go.
The last part is just engineering honesty. You do not put a reasoning engine on the hot path of a 100ms checkout, or a billing run that touches ten million rows at 2am. That’s what the scripts are for. The repeatable, high-volume, has-to-be-exact work gets pinned to a tested function, and at that point the error rate is the function’s, which is to say effectively zero, not the model’s. The model’s judgment stays where the volume is low and the situation is genuinely new, which in most businesses is more of the day than anyone likes to admit. Where the work is high-volume, latency-critical, or safety-critical, the old built thing is still the right answer. The claim was never that every application dissolves. The ones quietly running on shadow spreadsheets right now were never worth building as applications in the first place.
Which is roughly where I am. I can see the bus. I think most of the software we build today is the wall between you and it. I haven’t found every gap in my own argument yet.
So tell me where the wall is. The comments on a post like this are usually sharper than the post.
References
The SAP rule, Hacker News user mr_gibbins: “changing the business to fit SAP is preferable to changing SAP to fit the business.” news.ycombinator.com/item?id=22244750
Nurse back-dating a hardcoded 10 PM cutoff: “Even though I emptied the catheter bag at 11 pm, I enter this as emptied at 9.59 pm.” Persisting workarounds in EHR system use (peer-reviewed). pmc.ncbi.nlm.nih.gov/articles/PMC8186102
Salesforce reps keeping a parallel Excel pipeline because they can’t customize the CRM. backstory.ai (corroborated by revenue.io)
Sue Casperson, Sidney Health Center, Montana, on Epic having no field for the real patient and the missed prostate/PSA risk. hcinnovationgroup.com
I build Savant (usesavant.com), a desktop AI assistant, and it’s where this pattern comes from and where the single-user stories above actually ran.



