Most of my personal tools start with the same thought: I should not have to do this by hand again. The useful ones solve that job and stop there.

Start close to the annoyance

My tool shelf includes a way to search Apple Voice Memo transcripts, a pipeline that turns place research into a real Maps list, a typed interface for a stubborn marketplace, local-first social research, and an Apple Music CLI that turns a list of songs into a playlist.

None began as a market category. Each began with a sentence like “I should not have to do this by hand again.” That proximity is useful. The user, failure mode, source data, and definition of done are already present.

Local-first is often the simpler promise

If the source and destination both live on the machine, a cloud service can be architectural vanity. Keeping transcripts and research artifacts on disk reduces moving parts, recurring cost, and the number of organisations invited into private material.

Local does not mean isolated. A tool can still retrieve a public URL, talk to a service the user chose, or produce files for another system. It means the durable state belongs somewhere the user can see, back up, inspect, and remove.

A CLI can be a humane interface

A command-line tool is not automatically austere. It can have clear verbs, useful defaults, readable errors, previews before mutation, and output that composes with the rest of a workflow. For repeated expert work, those qualities often beat a graphical interface with more chrome and less memory.

The Apple Music tool is a good example. The job is not “manage music through a terminal.” The job is to preserve the spark of a playlist idea while removing repetitive matching, ordering, and data entry. The command line is simply the shortest reliable bridge.

Stop when the loop is whole

Small software tends to get worse when it starts anticipating imaginary scale. Accounts appear. A database replaces a file. Configuration becomes a product. The maintenance surface expands faster than the usefulness.

The goal is not minimal code. It is a complete job with a small surface: get the right input, make the transformation inspectable, handle the likely failures, deliver the result, and stop. Once the whole job works, leave it alone.