Doing things because they're easy, not hard

# July 3, 2025

Indragie Karunaratne had a great blog post this week on building a side project almost entirely with Claude Code. It's worth a full read if you haven't seen it yet. He lays out his workflow, MCP tools that he needed for Xcode builds & Swift, and some of the back and forth of improving the initial prototype.

I love seeing stuff like this. What engineer doesn't have a list of the 1000 things they would build if they just had capacity or the luxury of going into an early retirement? The struggle has always been time. It might not be so much of a struggle anymore.

As the tedious parts of engineering are becoming trivial, that leaves some time to take more onto your same sized plate. What's left is the creative problem-solving, the architectural decisions, and the POV that sets your solution apart.

Side projects just for the sake of them

Side projects are a bit funny. Most people that do them fall into three camps:

  1. You have some itch and are just making it for yourself.
  2. You think the side project might evolve into your main project / startup.
  3. You're just trying to hone your skills (new language, framework, tech POC) that you'll then adopt in some other setting.

So either the next billion dollar idea or a complete throwaway project. Got it.

I find (3) to be the only way to really learn a new skill. The old I hear and I forget. I see and I remember. I do and I understand. That part doesn't change even with LLMs.1

But for (1) and (2), you're just trying to get it done. You have some aesthetic sense of the solution: how it feels to use it, how it looks when it will be complete. The building is the secondary priority. The electrifying sensation is when you finally have something that's working.2

Agents change the economics of all three goals. For learning projects, you can now focus on the concepts rather than fighting with syntax and setup. For personal tools, you can actually build the thing instead of settling for a mediocre existing solution. For potential startups, you can validate the idea before committing months to a fully baked implementation.

I want to focus on the second bullet.

Creativity vs constraints

There's something that feels more creative when using Agents. Perhaps similar to why designers prefer to be focused more on the pixels and less on the implementation. Prematurely constraining your solution space based on the technical realities doesn't let you dream quite as wide.

I can tell you anecdotally that Agents have certainly unlocked even more of my passion to build things on the side. When it's no longer a question of toiling for nights and weekends at the expense of your main gig, social commitments, or sanity - why not? Pick up something else. Make that desktop app. Host some utility for your family. Build animations for a blog post.

My main critique with Agents is it's hard to get into the flow state. Waiting for model latency and some false starts at the solution provides too many interrupts to really find flow. There are too many opportunities to context switch and progress is usually very nonlinear.

But you'll only mind that lack of flow when you're focused on your screen 9-5. For side projects these interrupts are actually perfect. You're probably juggling multiple things at once anyway. Being able to kick off a job, go away, pick up a book, and come back to it at some later time works perfectly well for the style of less serious development.

"Just make it nicer"

Going back to the original Self-Refine paper, having models critique some output and revise their answer is shockingly effective. The same technique works pretty cleanly in development. I use this prompt frequently and was interested to see Karunaratne doing the same.

You first ask the model to critique the current state of a function, file, UI, or whatever. Have it give detailed feedback about why the content doesn't conform to best practices. Then, with this input fed into the conversation context, ask it to improve. Usually that alone works like a charm. Where possible you should prioritize the guidance into the top 5 highest impact areas, otherwise the model usually takes into account too many long-tail critiques.

There are two different types of thinking at play. First, the analytical: "what's wrong with this?" Second, the creative: "how do we fix it?" I don't suspect there's really a deeper emergent property here with isolated thinking. Instead, we know through RLHF that LLMs are rewarded for giving us back exactly what we asked of them. The more detailed your prompts the better calibrated the output is going to be. A critique revise loop is acting to synthetically generate a more detailed prompt than you would probably write on your own.

The critique phase also forces you to articulate standards you might not have consciously considered. When you tell the model "this UI feels clunky," it responds with the spacing is inconsistent, the color contrast is poor, and the information hierarchy is unclear. It's providing the vocabulary for why things don't work. You can agree or disagree with the feedback. But defining the revision with as clear technical specifications as possible gives less ambiguity for the generation process3 to translate natural language into code.

It's a similar reason why design and code reviews are somewhat of an art form. You need the right vocabulary to get on the same page.

The things you would never make

Especially for side projects – but hell even for your corporate job – you usually know when something needs a better experience around it. Engineers want to sit around and run scripts, not have to refamiliarize ourselves with READMEs. But so often we shrug off that drive to improve process because it would take away from more important things. In the prioritization game, your own developer experience usually doesn't make the cut.

This is where the release script hits hardest:

This is 2,000 lines of Python code that, even if I had written it manually, I would've never bothered to automate more than the most critical steps, and certainly would not have put the effort into making the output look this nice.

Most people would never build that level of automation manually. Especially not for a side project. Sure, sometimes you're discouraged by the time investment to write it. But it's also the mental overhead of potentially having to maintain it in the future. It feels like you're embarking on another side project for your side project.

Self contained scripts are where agents4 can really shine. You can easily fit the entire logic into the context window. It's usually self contained and only imports very popular libraries (rich, click, etc). It's written in a scripting language with a large training dataset. All those factors bode very well to get a working draft done quickly with minimal manual guidance required.

This equation changes what's worth automating. In the past you'd only automate tasks that were both frequent and painful. Now you can automate things that are infrequent but annoying.

When good tooling is cheap, you start to expect it everywhere. When automation is easy, you become less tolerant of manual processes. Your baseline for an acceptable developer experience rises across the board. When things seem a bit too hard, you might not do them at all.

Conclusion

When it comes to side projects, you usually want to optimize for maximum iteration speed and minimum cognitive overhead. The code becomes a means to an end rather than an end in itself. There's an argument of "who cares about code quality". If spagetti code is written in a forest, will it even make a sound?

Maybe not on the first draft. Though I suspect any non-trivial side project benefits from encapsulation and the proper design choices for abstraction layers. But it matters more if you come back to it over time. You want that code to be modular enough to make one small change without the rest breaking. That doesn't change just because you can task an agent with "plz fix".5

Agents are another form of outsourcing. You can outsource to a person or you can outsource to a machine.6 You can also outsource with a clear specification or with a loose one. I guarantee you, a firm spec will always be better regardless of the humanity of the outsourcee.

You're in charge with having to keep up your own bar of quality. Code aesthetics haven't yet been fully internalized by models. They might not be for some time. Use your experience to guide them to writing code that you can really stand behind in a code review. You'll still end up far more efficient than having to write everything yourself.7

Whether you delegate to an Agent or you're still slinging C++ code by yourself, keep working on side projects. The Internet is a much more interesting place because of them.


  1. You'll get better output when you understand how a solution should be built & delegate the spec to language translation layer to an LLM, than to ask for the solution you want with none of the guidance. 

  2. The spark of seeing your code compile is only en route to the final sensation of it doing something useful

  3. And whatever sub-network ends up being most responsible for code generation. 

  4. Really just the underlying LLM engine. Once all the context can fit in the loop, the main agentic job is analyzing runtime output. But there are fewer tool calls needed to write a reasonable first draft. 

  5. Plus - if code is hard for you to parse why would a bot be able to do any better of a job? They're trained on human behavior. They're not magic. 

  6. This is a wild sentence to write if you consider even two years ago. 

  7. At least, usually. 

/dev/newsletter

Technical deep dives on machine learning research, engineering systems, and building scalable products. Published weekly.

Unsubscribe anytime. No spam, promise.