Software Minimalism
August 17, 2025
To quote the troubled programmer of internet fame, Terry A. Davis, “An Idiot admires complexity, a genius admires simplicity.” Davis may have been taking aim at the complexity of academic writing, but the first part of his quote has a much broader resonance. The idea that simplicity is genius isn’t unique to him. It is at the heart of one of the most influential philosophies in computing history, the UNIX philosophy, articulated by Ken Thompson.
Thompson, one of the original developers behind UNIX, famously wrote a set of philosophical approaches when it comes to software development. Thompson states that each program in a system should do one thing well, and that overcomplicating said program with new features should be avoided. Instead, to do something new or execute a new job, write a new program. Thompson also advocates for modularity: the output of a a program should be reusable by another to accomplish something new, novel, or unique. Lastly, programs should avoid outputting complex strings or, god forbid, output in a binary format. Instead, they should either print or stream text, nothing more, nothing less, as text is a universal format that can be parsed by virtually anything (that supports ASCII).
Let's use sudo as an example here. Do note that I am writing from the perspective of someone who uses Linux on the desktop, as a personal system, and NOT as a server OS. sudo is an incredibly complex program for what it's designed to do. sudo, in a literal sense, translates to "do this as another user (root in most cases)." Yet, sudo's codebase weighs in at, give-or-take, ~250k lines of C. That is incredibly complex. That's more lines of code than wlroots, a compositor/API for Wayland, which has ~50k lines of code.
So how is a program that's used to elevate user privileges more complex than a compositor that draws windows to your screen? Simply put, features. sudo is much more a user management system than it is a privilege escalator. It has support for LDAP/NSS, different authentication methods like PAM or Kerberos, a restricted shell mode, support for plugins, environment variable preservation with -E or env_keep, running commands in the background, and so forth. That's a lot. For enterprise use? Probably justifiable. For desktop use, where sudo is only really used to elevate privileges? Not so much.
sudo is also a massive security vulnerability due to its bloated codebase. Just last month, sudo was hit with a 9.3 Critical CVE. The flaw allowed users to gain root access by exploiting how sudo handled the NSS configuration file when used with the --chroot option. This is a perfect example of how complexity, while often added with good intentions, can open the door to serious vulnerabilities.
If sudo represents the pitfalls of complexity, then doas represents the opposite approach. Originally developed for OpenBSD, doas was designed to replace sudo with a tool that does one thing and does it well: execute commands as another user, usually root.
The entire doas codebase is only a few thousand lines of C, compared to sudo’s ~250,000. Its configuration is a single, simple file, usually just a few lines long. There are no plugins, no LDAP integration, no restricted shell mode, no sprawling feature set. Instead, doas focuses on the core functionality that most users actually need: privilege escalation.
On Linux, doas has been ported and is available in most distributions. For desktop users, it’s often a drop-in replacement for sudo. The trade-off is obvious: you lose the enterprise-focused features, but in return you gain simplicity, readability, and a much smaller attack surface. One could say that doas simply sucks less *foreshadowing...*
If sudo is an example of complexity creeping into a small utility, then systemd is complexity at the scale of an entire operating system. Introduced in 2010, systemd was designed to replace the traditional init system on Linux. Its stated goal was to modernize service management, improve boot times, and provide a unified framework for handling processes.
On paper, that sounds reasonable. In practice, systemd has grown into a massive suite of tightly integrated components: not just an init system, but also a logging system (journald), a network manager, a time synchronization service, a container manager, and much more. The project now spans millions of lines of code and touches nearly every part of a modern Linux system.
A good example of this expansion is systemd-run0, a relatively new addition that provides functionality similar to sudo or doas. Instead of just being an init system, systemd now also offers its own privilege escalation tool. For some, this is convenient: one framework, one set of tools, tightly integrated. For me, it feels like yet another example of systemd absorbing functionality that could (and perhaps should) remain separate, smaller, and more auditable.
Supporters argue that systemd solves real problems, provides consistency across distributions, and reduces the fragmentation that has historically plagued Linux. But I would argue that Linux has always been about freedom of choice, and that “consistency” in this case is little more than the monopolization of the distro landscape. By making itself a dependency for so many core functions, systemd has effectively forced its adoption across nearly every major distribution.
This has led to a kind of homogenization. Once upon a time, choosing between Fedora, Ubuntu, Debian, or Arch meant choosing between different philosophies, different init systems, and different approaches to system management. Today, with systemd at the center of all of them, those differences are increasingly superficial. The init system, which was once a defining characteristic of a distribution, has been standardized under systemd, leaving little real distinction between many of the “big name” distros. In other words, systemd hasn’t just centralized functionality — it has centralized identity.
systemd is, in many ways, the opposite of doas. Where doas strips away everything but the essentials, systemd embraces integration and feature creep. Whether you see that as progress or bloat depends on your perspective, but it undeniably represents a philosophical shift away from the minimalism that defined UNIX.
If systemd represents the centralization and homogenization of Linux, then projects like suckless and distributions such as Void Linux or Artix Linux represent the resistance. They are modern attempts to preserve the UNIX philosophy of simplicity, modularity, and choice.
The suckless project is perhaps the most extreme expression of software minimalism. Their motto, “software that sucks less,” is a tongue-in-cheek jab at the bloat and complexity that dominate modern software. Tools like dwm (a tiling window manager), st (a simple terminal), and surf (a minimalist web browser) are all designed to be small, auditable, and hackable. The codebases are intentionally tiny, often just a few thousand lines, so that a single person can read, understand, and even modify them. This is software as craft, not as industry.
On the distribution side, Void Linux and Artix Linux take a similar stance against homogenization. Both reject systemd entirely, opting instead for alternative init systems like runit in the case of Void, or OpenRC and s6 in the case of Artix. This choice is not just technical, it is philosophical. By refusing to adopt systemd, these distros preserve diversity in the Linux ecosystem and keep alive the idea that there is more than one way to build a system.
There is also a practical benefit. Minimal systems demand less from the hardware. A Void or Artix install with a lightweight window manager like dwm or i3 can run smoothly on older laptops or low-power machines where a mainstream distro with GNOME and systemd would feel sluggish. Minimalism does not just mean cleaner code, it also means efficiency, speed, and the ability to extend the usable life of hardware. In an era where software bloat often drives unnecessary hardware upgrades, that is a powerful statement.
For example, I run Artix Linux with OpenRC and dwm on a ThinkPad X270 with an Intel i5-7300U (2 cores, 4 threads) and 8 GB of whatever-laptops-use RAM. Despite being several generations old, the machine feels fast and responsive, with memory usage staying low even under a full workload, and a battery life that even puts Apple's newest hardware to shame. A mainstream distro with GNOME or KDE would make the same hardware feel sluggish, but with a minimalist setup, it feels like a brand new machine.
At its core, software is about communication. A program communicates intent to a machine, and the machine communicates results back to us. The more layers of complexity we pile on, the more that communication gets distorted. Minimalism is not about doing less, it is about removing the noise so that what remains is clear, efficient, and trustworthy.
That is why this site is built with nothing more than HTML and CSS. No JavaScript, no frameworks, no unnecessary dependencies. It does not need them. The page loads instantly, and works everywhere, probably even on old versions of Internet Explorer/Netscape, but I haven't had the time to test that yet (not that i could either with SSL certificates being a major hurdle). Either way, in a world where JavaScript is being forced into everything, from static blogs to desktop applications, even terminal applications (where it DOES NOT BELONG), choosing not to use it is a reminder that software does not have to be bloated to be useful.
The modern web is a perfect example of what happens when complexity becomes the default. Pages that should be a few kilobytes of text and style are now multi-megabyte bundles of scripts, trackers, and frameworks. Applications that once ran natively are now shipped as entire browsers wrapped around JavaScript. Hardware that should last a decade is discarded early, not because it is broken, but because the software has grown too heavy for it. This is not progress, it is waste.
Minimalism is not nostalgia. It is not about clinging to the past or rejecting innovation. It is about clarity, efficiency, and respect for both the user and the machine. It is about writing software that does its job without demanding more than it should. If a blog can run without JavaScript, maybe more of the web can too. If a window manager can fit in a few thousand lines of code, maybe not every program needs to be a sprawling ecosystem.
Complexity is seductive. It promises features, integration, and convenience. But simplicity is liberating. It gives us speed, clarity, and control. The future of software does not have to be heavier, slower, and more centralized. It can be lighter, sharper, and more human. The choice is ours, and it begins with what we choose to build, what we choose to run, and what we choose to reject.