My 2025 Obsession: NeXTSTEP, OpenStep, and NEXTSPACE
- 13 minutes read - 2689 wordsYeah, so it’s been a minute since I’ve written. With a toddler, marriage, work, etc. my tiny little bits of free time have forced me to choose between blogging or Doing the Thing. Let me tell you about the Thing I Did.
I ported Sergeii’s NEXTSPACE project from Linux to FreeBSD—the operating system of my “Just Focus” laptop. NEXTSPACE recreates the NeXTSTEP desktop environment, that gorgeous UI from Steve Jobs’ NeXT computers. On top of this, I integrated GNUstep, the Free Objective-C development environment and graphical interface builder modeled on NeXTSTEP. This crisp UI and insightful programming environment were so elegant and ahead of their time that Apple would build OSX (now MacOS) on it. There’s a reason Sir Tim invented the World Wide Web on this platform.
A beautiful desktop and an elegant programming environment, together about to unleash Babel 2.0
While I’d been too young in 1989 to know about NeXT, I sought to re-create what John Perry Barlow described in my favorite episode of “This American Life #74: Conventions”:
the only computers…where the whole notion of design was really important to the product—elegance of design.
Or prove myself to be proudly of that cohort of individuals named by Barlow as “Unix weenies by Armani.”
Right before the end of 2025 I finished my proof of concept. It worked. I’ve made a few improvements since then and have chased down some battery-burning inefficiencies. In fact, I’m using it right now.
And along the way, I worked with AI through the development. My C is far too primitive, my Objective-C too narrow to deliver this beast of a project. So the success here suggests a certain type of success for AI-assisted development, in this case with Claude and later Claude Code. Some of my experiences suggest the positive case for AI that I hope critics can earnestly engage with.
Ultimately, succeeding in The Thing didn’t leave much time for blogging. Until now.
The Slow-Boiled Frog
We do these things not because they are easy, but because we thought they would be easy.
Attributed to Maciej Ceglowski
Starting Off with Claude
As of this summer, I had been trying various new laptops and putting them through their paces as far as being my new “Just Focus” machine. While testing various hardware platforms for FreeBSD support, I started leaning on Claude’s chatbot to get information about how to get diagnostics or correct bugs as I was getting oriented in the platform. Claude’s responses were largely correct and allowed me, in my small sessions to make progress.
While I was comfortable with my Wayland + Sway desktop environment, I started to want a lightweight, but also helpful desktop—something that could set my clock, change system volume, pick a screen saver. But I also wanted the interfaces to be unobtrusive and easily customized (eventually) for FreeBSD. What I really wanted was that NeXT experience.
While I was looking for that, I came across Sergeii’s NEXTSPACE…for Linux. I was struck by the quality and clarity of Sergeii’s codebase and figured that it couldn’t be that hard to port an awesome Linux application to FreeBSD ("because we thought they would be easy").
Phase I: Installer shell scripts
In this initial phase, I was using my knowledge of shell scripting and Claude’s web chat to migrate and debug NEXTSPACE’s installer shell scripts. This was very much the style of development I’ve done for years. I edit something, I keep my wiki and reference documentation handy. Effectively, the locus of knowledge is my head (or notes). But with the help of AI, I was able to remember long-forgotten patterns of string testing, return status checking, etc. I didn’t have to keep documentation open to make tiny changes
Additionally, Sergeii had written the scripts in bash shell and FreeBSD
prefers the portable sh shell. Again, Claude chat came to the rescue here to
port the idioms of one standard to another. That was pretty great, it was very
empowering, and it was work that I could accomplish in the duration of a
toddler’s nap.
Phase II: Embrace the hoosegow: jail-based development
As I’ve written several installers for Unix systems, I found that one critical problem gets in the way like none other: given a pristine machine, your first (failed) attempt to install will mean you can’t truly test your code on a clean machine again. You spend as much time trying to get back to guaranteed clean as you spent trying to change the system state to a new direction. Fortunately, FreeBSD provides jails. These are basically isolated file trees on your “host” FreeBSD that look like a Unix system. In short, they start off as pristine virtual machines. If I could get the code building and running in the jail, I could throw it away. Or if I got something wrong, it wouldn’t hurt my host (main laptop) system.
Phase III: Snapshots
The most common file-system used in FreeBSD is zfs (zed-eff-ess) which
features a really powerful feature: you can snapshot file system trees and name
them. In short, you can make “savepoints” in the evolution of a BSD jail.
Phase IV: Peanut butter meets jelly
Hopefully you’re excited by imagining what’s possible with the tools I just laid out.
So the workflow I discovered was: edit code on my host operating system. Share
that file tree into the file tree of the jail. Snapshot the jail. Edit / Debug
/ Test. Roll back to the pristine snapshot. Try again. When the installer
script worked correctly, I snapshotted the system e.g. after-script-2 to save
my work and then keep iterating. This was a powerful workflow that anyone using
AI really ought to leverage.
Phase V: Chase the Bugs
Once I got this development harness in place, I could dive into the real work of making sure these installing scripts did the right thing. And here’s where Claude really started to show value. You see, the NEXTSPACE codebase is divided into a number of applications written in Objective-C. It’s the language I chased many years ago while learning to program. I’ve never shipped anything of size in it.
It’s also the case that the window manager was written in C. This is a language that I have an understanding of, but no real comfort. I’ve never shipped anything of size in it.
And it just so happens that both of these codebases inside NEXTSPACE were
assembled by GNU Make. Now I’m not even that comfortable with regular BSD
Make that I’ve been, uh, using but not really understanding for decades. So
here’s a different dialect (say, Italian to Spanish) that I had never even
worked with.
And recall, all that is on top of shell scripting which I, by chance, happen to be decent at.
These areas of familiarity shortfall should have cost me lots of time. It
should have made this project impossible. But it didn’t. Why? Because I
had search results better than Google; I had a peer that could help me parse
dense man pages and generate instructive examples; I had something that could
take GNU documentation out of their bat-shit preferred documentation format
.info; I had Claude.
Slowly, by chat, by edit, by commit, by rollback, by roll-forward, I kept falling forward to success.
Phase VI: Integration is the Hard Part
While this human “stayed in the loop” the whole time, once all the pieces were installed, there were some real snags. Many of them had to do with library dependence order, installing fonts and handling the eventing queue. By mid-August, I had a working proof of concept.
First flickers of success
It took another 10 weeks or so, but eventually I got some of the hardest bugs worked out and got to this milestone.
All the applications running on a single thread
I thought I was pretty much home free at this point. But then I realized I’d made an error: I had all the work happening on a single thread. This meant that certain applications weren’t going to work. That is if I dragged a file into a recycling bin on the main user interface thread, the background thread that actually does the removal wouldn’t run. I found that I’d disabled this in development to keep moving forward. Whoops. So turning it back on shouldn’t be a big deal…but, oh, I was wrong. So wrong.
Phase VII: The Demons of Multithreading
And that’s when I started having multithreading bugs. As a class of bugs, these
are some of the hardest to battle because news of what failed and when it
failed not order may in the correct arrive – er may not arrive in the
correct order. Honestly, I was completely despairing at this point.
Under the old model of development and support, I was going to have to browse a thousand condescending forums and email lists. I was going to have to, I figured, go back and learn those three giant areas of knowledge so that I could have enough context and kudos to be able to ask for help. It was really dispiriting. I think my mental state comes through in this update:
WindowMaker [the underlying desktop package NEXTSPACE rests on] is from a single-threaded era and, in a number of points it tries to flush changes via X (Xlib, XCB, whatever). It doesn’t know that another process in another thread may have done something that it doesn’t know how to deal with.
I don’t know how this wasn’t a problem on Linux. And for whatever reason, in my prior hack-it-together approach, I somehow didn’t hit thread errors. Maybe I installed something wrong.
Interlude: Claude Code
In May, Anthropic released Claude Code. It was a text-based user interface
(yay) application that one could, in its earliest days, use to process output
and introspect into files. It cut down the non-ergonomic experience of running
code, compiling, seeing errors, copy and pasting into a browser, seeing
results, implemeting them while reading the web browser, and then retrying. I
started working with Claude Code and started realizing it could be a force
multiplier. Running it in my source code root, I simply said: “I think I have a
multithreading bug in this file, add print messages everywhere so I can see
what’s going on.” While adding tons of these isn’t hard for a human, it’s
certainly not fun. Claude made the execution path chatty like a preschool. It
made it non-painful for me to start accumulating data.
Having accumulated the data, I realized it was a really hard problem. I posted this update. It was a cry for help but also the moment before I started leaning even more on Claude Code. I was so close, but I just was not going to have the time to level up in all the required disciplines necessary in order to be able to make this work before the new year.
But helped by Claude Code, having it instrument all the code paths, having it build solutions and make edits (a step toward “agentic” or “autonomous” code patterns) I had a release ready. Roughly a week later, I had a developer release ready.
NEXTSPACE running on FreeBSD
Before the month was out, Sergeii chimed in to recognize my effort and even used my codebase to try running his creation on FreeBSD as well. He’s been exceedingly gracious and we’re going to see if we can merge my work with his architecture to have Linux and FreeBSD as supported platforms!
The Positive Case for AI-Assisted Development
There’s a concept in education called the “zone of proximal development”—the gap between what you can do alone and what you can pull off with guidance. I’ve got decent instincts for the abstract stuff: data structures, control flow, when to extract a function. But I simply cannot be bothered to learn GNU Make’s idiosyncratic dialect. Life’s too short. And while I’m always glad to invest time becoming a better C developer, having focused, contextual help with my specific struggles? Invaluable. Claude’s syntax knowledge paired with my architectural intuition let me expand what I could actually accomplish. That’s not nothing.
There’s also the matter of unattended edits. Once I agreed to a strategy, I
could let Claude Code make the changes while I stayed present as Dad. A quick
review of the diff, a nod, and the agent did the tedious work. I once wrote
that good instructional materials should let you complete one full step during
a toddler’s nap. AI-assisted development takes this further: you can make
meaningful progress in fragmented time. It raises real questions about
whether IDEs—even my beloved vim—will matter in the same way going forward.
There’s also what I’ll call the “code hype-man” effect. When you’re working on a significant changeset and life pulls you away for a day, you risk losing your mental model of the problem. Having an ongoing TUI-based chat agent means someone is there to remind you of the theory behind your bugfix when you return. It’s like having a pair programmer who never forgets. This alone saves enormous cognitive re-entry costs—the kind of friction that kills hobby projects.
And there’s the avoidance of condescension. I’ve been working among Unix users for most of my life. We are a condescending and pedantic group by nature. It’s keenly frustrating that anyone asking for help is told “Be more smarter” [sic] or “Read more books.” These aren’t objectively wrong responses, but they’re completely tone-deaf—and they suppose that those being flayed are lazy idiots rather than people caring for small children, or people who don’t inhabit professorial posts, or people who don’t have an English gentleman’s daily schedule of trifles. And as someone who looks the part of “software developer” out of central casting, I don’t have to chew on stereotype threat (Am I being treated hatefully because of my identity? Because these people are assholes? Because I’m not good enough?). AI doesn’t sneer. It just helps.
Finally, there’s the avoidance of toil. Let’s grant that the AI naysayers are 100% right—that AI will never help humanity generate one jot of new, good code. Any developer will readily tell you that their lives are full of incidental toil: setting up a web server, configuring a reverse proxy, setting up backups, cleaning up a repository for faster cloning on slow connections. If AI can help humanity avoid this work, it’s doing something good. I don’t see how that’s arguable.
I’m not going to deny that there are concerning externalities to mass AI adoption: heat emission, water consumption, resource scarcity. These are real concerns, and they should be deeply considered as we figure out how to array the material wealth of this planet. But to claim prima facie that there’s nothing good to AI seems tone-deaf and provably false—like talking to a Free Software Foundation zealot about the pragmatic benefits of a permissive license.
Conclusion
I set out to recreate something that mattered to me: the elegance of NeXTSTEP, the feeling that a computer could be both powerful and thoughtfully designed. I ended up with a working desktop environment on FreeBSD, a collaboration with the original NEXTSPACE author, and a much clearer sense of what AI-assisted development can actually do.
This wasn’t AI replacing a programmer. It was AI extending one—filling gaps in syntax, holding context across interrupted sessions, doing the mechanical work so I could focus on the decisions that mattered. The positive case for AI isn’t that it writes code for you. It’s that it lets you write code you otherwise couldn’t, in time you otherwise wouldn’t have.
Every iPhone is a NeXTPHONE. Every MacBook carries NeXT’s DNA. And now, on a FreeBSD laptop (a cousin of the BSD that NeXT was built on), I’m writing this post in a desktop environment that honors that lineage—built in the margins of a busy life, with a little help from an AI. It’s been a consuming bit of geekery, but when I open my laptop: Windows isn’t end-of-lifing me; Apple isn’t pushing their new movie “F1” in my (sacred!) system updates notifications; rage-driven click-bait headlines aren’t in my workspace. It’s superior tooling from a more civilized time.