The Unix philosophy has been dying for at least thirty years, which might be its most impressive feature. Each generation of developers discovers the ideal, finds that real software consistently violates it, and either writes a manifesto or quietly moves on. sdomi’s piece lands squarely in this tradition: systems grew complicated, composability became theoretical, and the elegant primitives gave way to sprawling processes that do hundreds of things. The frustration is legitimate; the history it invokes is more complicated.
What McIlroy Actually Said
The Unix philosophy, as usually cited, comes from Doug McIlroy’s summary in the 1978 Bell System Technical Journal:
“Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.”
This is elegant. It is also a description of specific constraints rather than a timeless prescription. The tools McIlroy was describing, grep, sed, awk, sort, worked on text because text was the common medium in the late 1970s. Memory was expensive, terminals were text-only, and the programs people wrote were mostly about processing lines of records. The philosophy was pragmatic first and principled second.
The composability those tools offered was genuine. Pipelines like:
ps aux | grep nginx | awk '{print $2}' | xargs kill
work because every program agrees on the same medium and the same delimiter conventions. The cost is visible in the pipeline itself: structured data (a process list) gets serialized to text, piped through, and parsed back out with a specialized tool. If ps changes its column layout, the pipeline silently breaks. The “universal interface” is universal because it discards structure, not because it preserves it.
The Worse-Is-Better Tension
Richard Gabriel identified this contradiction in his 1989 essay “The Rise of Worse is Better.” Gabriel contrasted what he called the “MIT/Stanford style,” correct, complete, consistent interfaces, with the Unix/C style, which prioritizes simplicity of implementation over correctness of interface. His conclusion was that the worse-is-better approach wins in practice because simpler implementations spread faster and accumulate mindshare before the better-designed alternatives can catch up.
He was right, and the Unix philosophy benefited from exactly this dynamic. Unix spread. The tools proliferated. The text-stream interface became default. And then, because worse-is-better has costs alongside its advantages, the ecosystem accumulated decades of inconsistency: flag formats that differ between GNU and BSD versions of the same tool, output formats that are technically human-readable but practically unparseable, programs that half-implement one-thing-well and half-grow into multi-function utilities because users kept asking for features.
curl now has more than 240 command-line options. git is famously difficult to approach. systemd manages services, handles logging, controls network interfaces, provides a container abstraction, and manages device state. These are not aberrations; they are the predictable outcome of a philosophy that ceded coherence in exchange for adoption.
Three Assumptions That Eroded
The Unix philosophy depends on assumptions that stopped being reliable as software scaled.
The first is that the “thing” a program does can be kept small. In 1978, a text editor was a relatively bounded problem. In 2026, a container runtime or a service mesh is not. The complexity of the domain outgrows the aspiration before the program gets anywhere near production.
The second is that text is a sufficient universal interface. It works for line-oriented data. It works poorly for binary formats, streaming data, structured nested records, or anything requiring type safety across program boundaries. Every shell script that parses ls -la output is performing ad-hoc deserialization of data that was never meant to be machine-readable.
The third is that composability is primarily a property of small programs. Large programs can expose composable interfaces through libraries, APIs, message queues, or protocol buffers. The question is whether the interface is well-specified; binary size is irrelevant. None of these assumptions broke overnight; they eroded gradually, and the philosophy kept being invoked as though the erosion were not happening.
What the Successors Look Like
Nushell is probably the most direct attempt to fix the interface problem while keeping the pipeline model. Instead of text streams, it passes structured data between commands. ls returns a table; where size > 1mb filters it by type-checked columns; sort-by modified sorts on a datetime field rather than a string. The composability is real and the types prevent the silent-breakage bugs that plague shell pipelines.
ps | where cpu > 10 | sort-by cpu --reverse | first 5
This is still a pipeline. Programs work together through a shared medium. The medium changed from text to structured records, and a whole class of column-parsing fragility disappears with it.
Plan 9 from Bell Labs was the most principled attempt to follow the Unix philosophy to its conclusions rather than compromise it away. Everything is a file, including network interfaces, window managers, and CPU schedulers. The composability is architectural rather than conventional. Plan 9 did not win adoption, but its ideas recur in container filesystems, FUSE drivers, and the 9P protocol, which has outlasted the operating system that invented it.
The suckless project represents a different response: strict source-line limits, minimal dependencies, patches for optional features rather than runtime configuration. A terminal emulator that stays under 2000 lines of C is achievable and maintainable. A Kubernetes controller is not. Suckless works within a scope where the philosophy can hold, which means it works well for a narrow category of software.
What Is Worth Preserving
The frustration in sdomi’s manifesto is not really about rules. It is about software that resists understanding: programs whose behavior you cannot predict, whose failures you cannot diagnose, whose interfaces shift without notice. The Unix philosophy, at its best, was a set of conventions that made programs predictable and diagnosable. You could read the source. You could trace the data flow. You could understand what was happening.
That value does not require small binaries or text streams. It requires stable, well-specified interfaces; behavior that follows from configuration rather than hidden internal state; and failure modes that are explicit rather than silent. These properties can exist in a large program or a small one, and they are absent from a lot of software in both categories.
The philosophy, as a checklist, did not survive contact with the software industry. The underlying concern, software you can reason about, remains as relevant as it ever was and is harder to achieve now than it was in 1978. That is what is worth preserving: not the specific mechanisms Unix chose, but the commitment to software whose behavior you can follow. Figuring out what that looks like under present constraints is more productive than mourning the era when it happened to look easy.