<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://blog.oak.ninja/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.oak.ninja/" rel="alternate" type="text/html" /><updated>2026-02-12T12:09:59+00:00</updated><id>https://blog.oak.ninja/feed.xml</id><title type="html">Blog</title><subtitle>Blogs are nice. We should do more blogs. </subtitle><entry><title type="html">Business is the Art of Maintenance</title><link href="https://blog.oak.ninja/shower-thoughts/2026/02/12/business-is-the-art-of-maintenance.html" rel="alternate" type="text/html" title="Business is the Art of Maintenance" /><published>2026-02-12T10:43:11+00:00</published><updated>2026-02-12T10:43:11+00:00</updated><id>https://blog.oak.ninja/shower-thoughts/2026/02/12/business-is-the-art-of-maintenance</id><content type="html" xml:base="https://blog.oak.ninja/shower-thoughts/2026/02/12/business-is-the-art-of-maintenance.html"><![CDATA[<p>The cost of running a business is the maintenance of the original idea behind the actual start of the company. The value of the company is that continuous maintenance. The cost of starting the business is small, and the cost of having the idea is zero. If the idea was good enough, the business will go into maintenance mode up until it’s sold, merged or liquidated.</p>

<p>Do people believe that the value of a company is the original idea and the concept of actually starting a company based on that idea? Rarely. People understand that the value in the company lies in its current state and future perceived trajectory.</p>

<p>The same thing is true about software and software development. People tend to believe that the value is in the idea or concept of software, where in reality the value of software is, just like with a company, the continuous maintenance of that concept combined with usage and perceived future value. Code is a liability - if you can run your company without a single line of code, you don’t have to maintain a single line of code. The cost is always in maintenance, so the less code you have the better.</p>

<p>This blog post titled <a href="https://habitatchronicles.com/2004/04/you-cant-tell-people-anything/">“You can’t tell people anything”</a> is something I often share and return to. The problem is that people <em>think</em> they understand, and when they get the chance to test your idea, new feature, or product, they will say, “Ah, you meant like <em>this</em>; why didn’t you say so?” - and that’s what you’ve been doing all along.</p>

<p>With generative AI, we <em>can</em> finally tell people. And we can show them, invite them to step into our ideas and actually try them out. And, maybe most importantly, we can reject ideas and fail fast. But if we decide to go with an idea and actually launch it, that’s when the <em>cost</em> of running a business will start or increase. That’s when the maintenance phase will begin.</p>

<p>The real test of Vibe coding is whether people will finally realize the cost of software development is in the maintenance, not in the creation.</p>]]></content><author><name></name></author><category term="shower-thoughts" /><summary type="html"><![CDATA[The cost of running a business is the maintenance of the original idea behind the actual start of the company. The value of the company is that continuous maintenance. The cost of starting the business is small, and the cost of having the idea is zero. If the idea was good enough, the business will go into maintenance mode up until it’s sold, merged or liquidated.]]></summary></entry><entry><title type="html">MakeMe: A Cross-Shell Makefile Navigator</title><link href="https://blog.oak.ninja/development/2026/01/02/makeme-a-cross-shell-makefile-navigator.html" rel="alternate" type="text/html" title="MakeMe: A Cross-Shell Makefile Navigator" /><published>2026-01-02T22:45:00+00:00</published><updated>2026-01-02T22:45:00+00:00</updated><id>https://blog.oak.ninja/development/2026/01/02/makeme-a-cross-shell-makefile-navigator</id><content type="html" xml:base="https://blog.oak.ninja/development/2026/01/02/makeme-a-cross-shell-makefile-navigator.html"><![CDATA[<p>Makefiles are awesome. Language-agnostic, flexible, easy to read, and easy to write. You can have one make target called setup that can run npm install, pip install, etc., and you can easily read the makefile in order to understand what is happening and in which order. The one area where Makefiles fall short is discoverability. As projects grow, it can be a challenge to find the right target to run, and making yourself familiar with a new project’s Makefile can take some time.</p>

<p>That’s why I wrote <a href="https://github.com/OakNinja/MakeMeFish">MakeMeFish</a> - A simple tool built on top of <code class="language-plaintext highlighter-rouge">fzf</code> and other open source tools. One of the hardest parts was finding a way to parse the Makefile and extract the targets (Newer versions of Make include —print-targets but I’ve so far never encountered that flag in the wild). I used <a href="https://stackoverflow.com/a/26339924">this</a> and other similar Stack Overflow answers as a foundation and got some help and feedback from contributors to MakeMeFish, and MakeMeFish has been stable for several years now. The problem with MakeMeFish is that it only works with fish shell.</p>

<p>Over the years, I’ve gotten a lot of requests to support other shells, and I’ve been wanting to make it cross-shell for several years but haven’t gotten around to doing it. When Gemini 2.5 Pro was released, I got curious on how well it could handle a rewrite of a <em>very</em> specialized tool (sed, awk, fish, make, fzf, etc.). The first tries, unsurprisingly, failed miserably. When I changed the approach by being more explicit in <em>how</em> I wanted to do the rewrite, things fared a lot better. I started out by making up a plan together with Gemini, where we co-wrote a plan in incremental steps. First, we discussed what language would be most suitable for the rewrite. I wanted to use Rust, but Gemini <em>insisted</em> on using Go, quote: <em>“You’re not building a new grep that needs to be the fastest in the world; you’re building a wrapper around existing tools. Go is the ideal choice for that.”</em>.</p>

<p>After settling on Go, I started doing the conversion in small incremental steps, guiding Gemini in a very similar way to how you would instruct an eager and competent junior developer to do it. The single most important instruction was to stop Gemini from trying to convert <a href="https://github.com/OakNinja/MakeMeFish/blob/677bf57330a6772624bfabb1f270cb5d301be68b/functions/mm.fish#L51">this</a> into Go. Even for a human, that would be a huge challenge, and Gemini quickly used up all of its quota by just trying stuff that obviously would never work. To make it easier to resume development over time, I created a GEMINI.md file, a MEMORY.md file, and a TODO.md file. GEMINI.md contains the plan, MEMORY.md contains the memory of the conversation, and TODO.md contains the TODO list. Over time, these files evolve together with the project and work great across different sessions and models.</p>

<p>The conversion went great up to the point where I tried to instruct Gemini to use <a href="https://gist.github.com/junegunn/193990b65be48a38aac6ac49d5669170">fzf as a library</a> instead of as an external dependency. I tried multiple times, attacking the problem from different angles, but Gemini 2.5 simply couldn’t do it. I settled with doing that part by myself. A few weeks later, Antigravity was announced together with Gemini 3. I downloaded Antigravity, opened my project, and Gemini 3 one-shotted the task of using fzf as a library. Impressive.</p>

<p>Now, I think MakeMe, the successor of MakeMeFish, is ready to be released, and you can find it <a href="https://github.com/OakNinja/MakeMe">here</a>.</p>

<h2 id="footnote">Footnote</h2>
<p>A <strong>bonus</strong> with MakeMe is that it’s a pretty good foundation for building other similar tools on top of fzf, using fzf as a library instead of a dependency. Please use it as a starting point for your own tools, and reach out if you have any questions!</p>]]></content><author><name></name></author><category term="development" /><summary type="html"><![CDATA[Makefiles are awesome. Language-agnostic, flexible, easy to read, and easy to write. You can have one make target called setup that can run npm install, pip install, etc., and you can easily read the makefile in order to understand what is happening and in which order. The one area where Makefiles fall short is discoverability. As projects grow, it can be a challenge to find the right target to run, and making yourself familiar with a new project’s Makefile can take some time.]]></summary></entry><entry><title type="html">A blog</title><link href="https://blog.oak.ninja/blog/2025/11/15/a-blog.html" rel="alternate" type="text/html" title="A blog" /><published>2025-11-15T20:40:50+00:00</published><updated>2025-11-15T20:40:50+00:00</updated><id>https://blog.oak.ninja/blog/2025/11/15/a-blog</id><content type="html" xml:base="https://blog.oak.ninja/blog/2025/11/15/a-blog.html"><![CDATA[<p>I missed having a blog. We should do more blogs. We should do more sharing. We should do more things without a bigger purpose than calming curiosity and finding new exciting things to learn and share.</p>]]></content><author><name></name></author><category term="blog" /><summary type="html"><![CDATA[I missed having a blog. We should do more blogs. We should do more sharing. We should do more things without a bigger purpose than calming curiosity and finding new exciting things to learn and share.]]></summary></entry></feed>