This isn’t one of those posts where I’m going to tell you that I’ve figured out the perfect development environment. I haven’t. There isn’t even necessarily a winner here. Instead, this is a collection of lessons from probably 100+ hours of building, abandoning, rebuilding, and experimenting with different ways of doing AI-assisted development.
One question keeps coming back throughout all of these experiments: Where should the compute actually happen? I think there are basically three answers. It can happen on your computer, on a remote computer you control, or somewhere in the cloud. I’ve tried all three. I’ve also built tooling around these approaches, stopped using some of that tooling, returned to old approaches, and then built new things to solve problems I created with the previous things.
That’s actually why I wanted to write this post. My environment is still changing, and I don’t think that’s necessarily a bad thing. Rather than pretending I’ve solved the problem, I think it’s more interesting to document what I’ve learned along the way.
First, Some Context About Me
My computing setup has always been a little weird. For years, I was primarily a Windows user. I didn’t have anything against Macs. Windows simply did everything I needed. I could program, work, mess around with hardware, and, most importantly, play games on the same computer.
Eventually, though, I became interested in building iOS and macOS applications, and that’s where things started changing. You can build a lot of Windows-oriented and cross-platform software from a Mac, but building Mac and iOS software from Windows gets considerably more complicated without introducing another Mac somewhere into the workflow.
So for a while I had both. I had my Windows computer for normal work, development, and gaming, and I had a MacBook for Apple development. Eventually I found myself carrying around smaller laptops too. I went through the same evolution with Windows machines. A giant 17-inch laptop sounds great until you actually have to carry the damn thing around.
Over time, the MacBook became my primary development machine. But the laptop is really only a small part of my environment. At home I have multiple desktops of varying ages and power, two Unraid servers, a Linux machine I originally used for things like StepMania and Dance Dance Revolution, a pile of Docker services, Plex, local AI workloads, game servers, development VMs, and a large collection of locally stored assets. I’ve also built plenty of things using AWS EC2 and other cloud infrastructure.
I explain all of this because it matters when we start talking about where AI development should happen. My answer is heavily influenced by the fact that I already have a LAN full of useful stuff.
Cloud Compute
I’ve never completely fallen in love with cloud development environments, and I think I finally understand why. Cloud machines can be powerful. They’re disposable, relatively easy to reproduce, and great for parallel work. You also don’t have to maintain the physical hardware. But they’re somewhere else, and that seemingly obvious fact matters more than I initially expected.
My local network contains years of infrastructure and information that I’ve accumulated. For example, I’ve purchased a lot of game-development assets over the years. I built a site on my network that lets me search through and retrieve those assets. If I’m developing locally, that’s easy. The service is right there.
If I’m developing inside some cloud environment, suddenly I have another problem to solve. I could expose that service publicly. I could create an API endpoint, configure authentication, issue some special credential to the cloud environment, lock everything down, and make it work. Technically, none of this is particularly difficult.
But now I’m doing infrastructure work so that I can do the work I originally wanted to do.
There are dozens of little examples like that in my environment. Individually, none of them are a deal breaker. Together, though, they create friction. That’s one reason cloud development has never quite become my sweet spot.
That doesn’t mean I don’t like cloud compute. There are absolutely projects where it makes sense. If I’m building something that’s essentially a website + database + credentials, then a remote or cloud development environment can be fantastic. Everything is relatively self-contained.
Cloud compute also becomes incredibly useful when the job has almost nothing to do with my development environment. Suppose I want an agent to periodically check something on a website, pull some information, run a browser workflow, or execute a scheduled task. I don’t need my entire LAN for that. Give the agent a browser, whatever credentials it needs, and let it run somewhere else. That is exactly the type of problem where cloud compute feels natural.
My MacBook
For a long time, the obvious answer was simply to run everything on my MacBook, and there are very good reasons for doing that. Everything is immediate. My repositories are there. My credentials are there. My tools are there. My network resources are there. My editor is there. I open the laptop and start working.
Modern laptops also have extremely fast storage. When a tool needs to create, delete, index, compile, or move thousands of files, local NVMe storage is difficult to beat. There are no additional network hops, no VNC session, and no other machine I need to find before I can start.
That sounds boring, but I’ve increasingly realized that boring and immediate are extremely powerful properties in a development environment.
The problem is scale. I have a lot of projects. Repositories accumulate. Dependencies accumulate. Docker images accumulate. Build artifacts accumulate. Game-development assets can be enormous. Eventually, the laptop becomes both a workstation and a storage-management exercise.
That was one of the things that originally pushed me toward another idea.
Building My Own Development Cloud
I already owned Unraid servers, so I started asking a pretty obvious question: why not turn one into my own personal development cloud?
That led to something I called Unharnessed. The basic idea was to make Unraid a compute harness instead of forcing my MacBook to do everything. My laptop would essentially become the control surface while VMs on the server handled the actual development environments.
The system got surprisingly sophisticated. You could describe what you wanted to work on and spin up an environment. It could clone the appropriate Git repository, give each VM its own storage, and preload the environment variables and secrets required by a project. I built a web interface around it, experimented with VNC, and could SSH directly into the environments.
In theory, it was fantastic. New project? Spin up a machine. Clone the repository. Inject the environment. Start developing. My MacBook becomes the interface instead of having to be the place where all of the compute happens.
┌──────────────────────┐
│ MacBook │
│ Control Surface │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Unharnessed │
│ Orchestrator │
└──────────┬───────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Dev VM │ │ Dev VM │ │ Dev VM │
│Project A│ │Project B│ │Project C│
└─────────┘ └─────────┘ └─────────┘
I got pretty far with it.
And then something funny happened.
I didn’t use it very much.
The Most Important Measurement Might Be Clicks
This is probably one of my biggest lessons from the entire experiment. Unharnessed worked. That wasn’t really the problem. The problem was much more mundane: I had to open the application, find the VM, connect to the VM, get into the repository, and then start working.
None of those steps were difficult. That’s what makes this lesson so interesting. The system wasn’t unreliable. It wasn’t impossible to understand. It didn’t require me to spend 20 minutes getting an environment running every time. It simply added a handful of small steps between having an idea and actually doing something with it.
Compare that with opening my laptop, opening Codex or my editor, selecting the project, and working.
Open laptop
↓
Open Codex/editor
↓
Select project
↓
Work
Open laptop
↓
Open Unharnessed
↓
Find environment
↓
Start/check VM
↓
Connect
↓
Find project
↓
Work
That tiny amount of friction changed my behavior.
I think this is an underrated lesson when we’re designing AI development environments. The technically superior workflow can lose because it requires three extra clicks.
Then Game Development Changed the Equation Again
Web development is relatively forgiving. Game development isn’t. Now I need CPU, GPU, memory, fast storage, and probably an actual graphical desktop environment. Suddenly remote development gets considerably more complicated.
I don’t want to say remote development doesn’t work for game development, because that’s not true. You simply need a sufficiently powerful remote machine and a good connection to it. My setup isn’t really optimized for that right now.
VNC works, but it can be buggy. There is latency. I’m also running everything else on these servers. The same Unraid infrastructure might simultaneously be handling Plex, Docker services, local LLMs, game servers, storage, and development VMs. Those workloads are all competing for CPU, memory, disk I/O, and network bandwidth. Throw game development into the mix and things get interesting very quickly.
To be fair, some of this is a problem of my own making. I’m using older hardware for some of these systems, and I could invest more time and money into making the infrastructure significantly better. At some point, though, that raises another question: how much infrastructure do I want to build just so I can avoid developing directly on the computer sitting in front of me?
┌────────────────┐
│ Unraid Server │
└───────┬────────┘
│
┌───────────┬───────┼────────┬───────────┐
▼ ▼ ▼ ▼ ▼
Plex LLMs Docker Game Dev VMs
Servers
Your Network Becomes Part of Your Computer
This is another lesson I didn’t fully appreciate when I started. When development happens remotely, the network becomes part of your development machine.
My MacBook has fast solid-state storage. It can move an enormous number of small files quickly. Once those files need to cross the network, the characteristics of the system change. My home network is largely gigabit, and seeing somewhere around 100 MB/s isn’t unusual. That’s roughly what you’d expect near the practical ceiling of gigabit Ethernet.
That’s fantastic for normal home networking. But now imagine multiple machines doing builds while Plex is streaming, Docker services are running, VMs are accessing storage, local AI workloads are moving data, and game servers are operating. The network isn’t simply connecting my development machine anymore. It has become one of the resources my development environment is competing for.
LOCAL DEVELOPMENT
CPU ↔ RAM ↔ NVMe
FAST
REMOTE DEVELOPMENT
CPU ↔ RAM ↔ Disk ↔ Network ↔ Network ↔ Laptop
↑
New bottleneck
At that point I’m not simply debugging my application anymore. I’m debugging my infrastructure.
My long-term solution probably involves rebuilding parts of my Unraid environment with newer hardware and moving important systems toward 10 GbE networking. But that itself proves something interesting. I started with, “Wouldn’t it be cool if my server handled development?” and somehow ended up at, “Maybe I need to redesign my home datacenter.”
That’s how these projects get you.
The Windows Box Still Wins Sometimes
This is also why I haven’t abandoned my Windows desktop. For certain workloads, particularly game development, it simply makes sense.
My current Windows machine isn’t some monster workstation either. It has a relatively recent AMD X3D-class processor, 32 GB of RAM, an Intel Arc B580-class GPU, NVMe and SSD storage, and even a roughly 10 TB spinning disk because there was a period where large hard drives were ridiculously cheap and apparently my NAS habits die hard.
Looking back, I probably should have bought 64 GB of RAM. I wasn’t thinking about some of these workloads when I built it. Still, the important part isn’t the exact hardware specifications. It’s that everything is local.
The GPU is local. The disk is local. The editor is local. The game engine is local. There is no remote desktop protocol sitting between me and the application. Sometimes that’s worth more than having an elegant infrastructure architecture.
Where I’ve Landed Today
The funny answer is that I’ve landed everywhere.
My environment continues to change. For straightforward web projects, I’m increasingly comfortable with remote development. For isolated workloads and agents, cloud compute makes enormous sense. For development that needs access to my home infrastructure, local or LAN-based compute is much easier. For game development and resource-intensive graphical workloads, a powerful local workstation still makes a lot of sense.
My MacBook remains the machine I naturally reach for because the cost of starting work is almost zero. I’ve also been using Codex more because the organization around projects, conversations, prompts, and work feels natural to me. There are remote-host capabilities that I probably haven’t experimented with enough yet, and those may change my opinion again.
That’s part of the point. I don’t think this post needs a permanent answer because the tools themselves aren’t permanent.
AI Changes the Equation
There’s another dimension here that makes this entire conversation more interesting. AI agents don’t necessarily need to sit where I sit.
Historically, a development environment was designed around the developer. Keyboard, monitor, IDE, terminal, source code, compiler. Everything needed to be reasonably close because the human was driving every interaction.
Developer → Computer
┌───────────────┐
│ Developer │
└───────┬───────┘
│
┌───────▼───────┐
│ AI Interface │
└───────┬───────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
Local Agent Remote Agent Cloud Agent
│ │ │
▼ ▼ ▼
MacBook Home Lab Cloud VM
Agents change that assumption.
An agent might work for 30 minutes without me touching anything. Another might run tests. Another might investigate an issue. Another might work on a completely different repository. If I’m running several of these in parallel, suddenly remote and cloud compute become considerably more attractive.
Maybe the future isn’t choosing one computer.
Maybe the interface decides where a task should execute.
That’s actually pretty close to what I was trying to build with Unharnessed before I had a particularly good vocabulary for it. I was trying to separate the control surface from the compute. AI agents make that separation much more useful than it was when I originally started experimenting with it.
The Real Bottleneck Is Friction
After all these experiments, that’s probably my biggest takeaway.
I started by thinking about compute. CPU, GPU, memory, storage, VMs, containers, and networking. Those things matter, but the resource that seems to determine my behavior more than anything else is friction.
A theoretically perfect environment that takes five steps to access can lose to an imperfect environment that takes one. AI makes this even more important because these tools are supposed to reduce the distance between an idea and execution. Every additional click, login, connection, environment selection, SSH session, or VNC window pushes in the opposite direction.
That’s why I’ve found myself gravitating toward tools where projects, conversations, prompts, repositories, and execution environments feel like one workspace.
So Which One Wins?
I don’t think one does.
And that’s probably the point of this post.
After spending more than 100 hours experimenting with this stuff, I’ve stopped looking for the development environment. Instead, I’m starting to think about a compute continuum.
Sometimes the correct answer is my MacBook. Sometimes it’s the Windows machine. Sometimes it’s Unraid. Sometimes it’s a remote VM. Sometimes I absolutely want someone else’s cloud. Tomorrow that answer might change again.
LOW FRICTION HIGH SCALE
MacBook ─────► Home Compute ─────► Remote Host ─────► Cloud
│ │ │ │
Immediate LAN access Isolation Parallelism
Fast disk My hardware Disposable Elastic
GPU access Persistent Repeatable Agent-friendly
│ │ │ │
└───────────────────────┬───────────────────────────┘
│
Pick per workload
That’s probably what I’ve enjoyed most about this whole experiment. I built Unharnessed. I stopped using it. I came back to pieces of the idea. I built another IDE around similar concepts. I stopped using that as much. I moved workloads back to my laptop. AI tooling changed. Agents got better. Cloud environments became more useful. Suddenly some of the ideas I abandoned started making sense again.
I don’t consider those projects failures. They were experiments, and each one taught me something about how I actually work rather than how I imagine I work.
Maybe the biggest lesson from all of them is this:
Don’t optimize only for where your code can run. Optimize for how quickly you can go from wanting to do something to actually doing it.
Compute is cheap.
My attention isn’t.
And three unnecessary clicks can apparently defeat an entire home datacenter.