Idiosyncratic Software

🇦🇷 Clickeá acá para leer este artículo en español.

I think turning 40 and now having a kid (hi Dodo) is making me notice details that, throughout my life, hovered as a floating vibe around what I do and what I believe. One of these details is a horrible feeling that, when you use most software, it tells you how you have to think, it reshapes you to its liking.

Not long ago I managed to understand that the moment-to-moment of using any tool is directly related to the design decisions its creators made, and that by using their tools, you become a little bit like them. It sounds like science fiction, but it's literally true. Using tools modifies your brain.

I felt this tension using Windows when I was 12, and I installed Linux and fell in love with what everyone around me calls "that black screen with letters." I've been a free software militant ever since. I hated Unity from minute one at Nastycloud and Hidden People Club, and enjoyed my days with the Moai SDK and building little engines in C++ or Rust.

I'm not naive, I understand that a big part of software's value is that it can be redistributed and reused easily, that the cost of building complex, well-made workflows is sky-high. This was our reality for all these years. Free software opened a window, however small, for the possibility of adapting software, but the difficulty of doing it made that promise rather impractical. Only large companies with many developers could take advantage of this, exactly the ones who needed it least. Beyond that, the trade-off was more or less clear: adopting other people's decisions was the price you had to pay to be able to do anything with a computer.

I find an echo of this in the article where I wrote that productivity is a colonization of the technical over the human. Software is just one more instance of this. But I think that, from now on, things changed.

Idiosyncratic Software

If you've been paying attention this past year, you'll have noticed that artificial intelligence is everywhere, with grand promises to revolutionize everything. The reality is that, so far, the only thing I believe it has truly revolutionized is the way we produce software.

Code agents flipped the table, and now what we always considered the effort of a team of 10 people over months, a single developer can do in a week (if they're feeling lazy). All of a sudden every bit of acquired "project management" knowledge blew up in the air and we're faced with having to answer very basic questions again, like whether it's worth paying for software or building it yourself.

I want to put a name to what's been rattling around in my head: idiosyncratic software. It's software that materializes your opinion about how something should work. As opposed to foreign software, the kind that never feels quite right. It's not home-cooked software in the humble sense, nor personal in the private and non-shareable sense. It's stubborn software. It has an opinion inside, like all software does, but the opinion is yours.

This isn't entirely new, other people have named nearby concepts, like home-cooked software (Sloan), personal/malleable software, barefoot development, and so on. My term is aligned, probably contained within these or containing them. But I like the focus the word idiosyncratic brings, it helps me so that, when I design, I design making the decisions that truly satisfy me, and if they don't, they get changed.

Some Examples

Design decisions live in many layers, the most obvious one being cost. For example, at Beezwax we used Render to spin up preview environments for the changes we make to the website. We were paying almost 2000 USD a month for this, insane. I got stubborn. I replaced it in three days with Dokku and a Sinatra app, vibing with Claude Code. Something that at another time would have been unthinkable (building that whole system from scratch), today is a weekend's worth of work. Render's competitive advantage hit the floor.

On the other hand, it makes me a bit nervous that other companies have a lot of my data. For now I can't escape code agents because I don't have the hardware or the money to run local models. But where I can, I do. Whispr Flow is an example, an AI voice dictation app that's amazing. The experience of using Whispr Flow vs any other voice dictation is remarkable. What I saw was that it was nothing more than a good Speech To Text (STT) model with an LLM in the middle correcting things. But I always felt nervous using it, especially when it showed me statistics about what I was using it for, that was the last straw. So, I vibe-coded a replacement in 4 hours, with whisper.cpp, a tiny local model, and a call to haiku. The truth is that, watching digital life unfold, not wanting to give your data to some random is a little stubborn. And it feels so good.

These are two recent examples of software I used and replaced, now I have the buttons I want, the prompts I want, and none of the junk features I don't want. Yay!

If I replaced these two services I considered untouchable in such a short time, what others are we paying for just because building them used to be a bad idea?

skulk

All of a sudden I ran into a new problem. I had close to 20 tabs open in my terminal, all of them with Claude Code sessions working on multiple projects and several tasks at once in each. My instinct was to download things like Conductor, or Omnara, but I felt that friction of someone else's decisions very quickly. On top of that, a hundred of them show up every week, all promising to be the definitive solution. All terrible. So I leaned into the UNIX philosophy and built my own. In one afternoon.

skulk is a very simple CLI for managing code agents that run remotely. Internally it's very simple, it uses SSH and tmux, creates git worktrees automatically, and that's it. It does one thing and does it well: managing remote Claude Code sessions.

A divine consequence: since it's a CLI, the whole agent orchestration can be done by an agent running on my computer, and for that I made a Claude Code skill.

$ skulk --help

Usage: skulk [OPTIONS] <COMMAND>

Commands:
  list         List all running agents on the remote server
  pull         Update the base clone on the remote server to latest main
  new          Create a new agent with worktree isolation
  destroy      Destroy a specific agent
  destroy-all  Destroy all agents at once
  init         Set up skulk for this project
  doctor       Verify the runtime environment is correctly set up
  gc           Clean up orphaned tmux sessions, worktrees, and branches
  connect      Attach to an agent's live tmux session
  diff         Show git diff between the default branch and an agent's branch
  disconnect   Detach all clients from an agent's tmux session
  logs         View an agent's terminal output
  send         Send a prompt to a running agent
  push         Push an agent's branch to `origin`
  archive      Archive an agent — kill its tmux session but keep worktree and branch intact
  restart      Restart an agent in its existing worktree with a fresh Claude session
  replay       Re-run an agent's original prompt on a fresh agent
  git-log      Show `git log` of commits on an agent's branch not in the default branch
  ship         Push an agent's branch and open a PR with a Claude-authored description
  transcript   Dump an agent's full tmux scrollback for archive or review
  status       Show detailed status for a single agent
  wait         Block until an agent has finished its current turn
  update       Update skulk to the latest version
  help         Print this message or the help of the given subcommand(s)

I don't know if skulk is better than every orchestrator on the market, because "better" is subjective, but to me it is, because it runs fast and each of those commands does what I want it to do and how I want it done, with no need to reach consensus with the dynamics of investors or markets that have nothing to do with me. In case you're curious, it's made in Rust, which to me is the best modern programming language/environment for agents.

cuentitos

Since 2020 I've had a problem. Every narrative engine for video games is pathetic. There are honorable mentions like Ink, which do things well but have design decisions I disagree with. At Hidden People Club I tried to solve this problem by designing a language we called cuentitos. It moved fast, but the cost of developing the engine plus a game became prohibitive. We didn't get funding and we had to shut everything down.

At the time it failed, not for lack of desire or ideas, but because the scale exceeded what we could do as a team.

Now I'm writing version 0.3 of cuentitos, designing it with a flow built around code agents: I'm doing what I called compatibility tests, a sort of TDD for the language. I use Markdown to put the tests together, there's a command that runs them, all written from scratch, with agents, and letting myself make the workflow exactly how I want it to be.

Now implementing a feature in cuentitos is very simple: I have a design session with the agent, I ask it to write the compatibility tests, I read them and leave them how I like, and then I have another design session for the internal architecture to satisfy those tests. I send the agent off to work and when it's done I do a code review.

The development workflow is based on CLIs in the terminal, like everything I do, which is why the agents have a blast without MCPs, computer use, or any of that stuff.

# Basic Two Options

Simple choice between two options, selecting the first option.

## Script
```cuentitos
What do you want to do?
  * Go left
    You went left
  * Go right
    You went right
```

## Input
```input
1
s
```

## Result
```result
START
What do you want to do?
  1. Go left
  2. Go right
> Selected: Go left
You went left
END
```
frantufro@everlong cuentitos % ./bin/run-compat
..........................................................................................................................................................................................................................................................................

Total: 266 | Failed: 0 | Pending: 0
frantufro@everlong cuentitos %

This loop gave my side project the chance to exist, because I have very little time, and I couldn't dedicate it to this right now. And yet, in between one thing and another, I send it a prompt, hours later I review, I ask it for something else, and it turned into something that's just there, moving forward in the background without any monumental effort.

Not all that glitters...

Obviously none of this is free or magical. There are very concrete consequences: there's no longer anyone whose door you can knock on if something breaks. Render guarantees uptime, say, now I have to guarantee it myself. There's a real risk of reinventing the wheel and doing it badly, let alone when you overdo it and write code you don't fully understand because an agent wrote it.

On the other hand, this unfortunately isn't for everyone, at least for now we have to know, and know a lot, about programming and computing to achieve good-quality software with agents, this can't be avoided for now, which is why now, more than ever, programmers have superpowers.

It's also important to note that I'm not saying "build everything yourself." For example, I pay for Fastmail and I'm going to keep paying for it happily, well-made email is genuinely hard and what they charge me is much less than the headaches of doing it myself (I know very well what it's like to manage email servers from my early years at Fundition, never again). What I am saying is that the answers don't change overnight, what changed is the selection criteria.

Before, "this would take me a lot of time" justified the 10, 15, 30 USD a month of almost any SaaS. Now I see how much software is a burden rather than a solution. If in a short time we can have something that works well enough, and that's minimal for our use case, why pay a premium for other people's use cases that don't even affect us?

The Heuristic

I'm not going to tell you how to decide, because it would be very meta in an article about the imposition of design criteria, but I've been developing a heuristic.

Does the value of software X come from the intrinsic difficulty of the problem it solves, or from the fact that someone already did it and that's that? How much do I care about having my own opinion expressed in this use case?

If the value is "it's already done" and on top of that I have strong opinions about how it should be done (and those opinions contradict the existing software), I throw myself into building it.

If the value is in the real difficulty (Fastmail) or I agree with most of the design decisions (I notice this by using the software intuitively and not finding irrationalities), I pay without hesitation.

One last babble

I find myself daily with this feeling of impatience, that life is the moment-to-moment and that there are thousands of decision-makers in every digital space I inhabit. Maybe this post is the flailing of that idealist who at 12 thought Linux was the end of Microsoft, and that the ground is set to fulfill the utopia of computing as a space of one's own, shaped by our opinions, not by other people's. But I have a feeling that for the first time in a long while we can make the machine adapt to our way of thinking, instead of the other way around.