:: bogs.io

May 24, 2026 // bogs // essay

What Good Local Software Is Supposed to Be

Good local software should feel like a tool you own, not a service that is temporarily allowing you to borrow its interface. It should work without the internet. It should not guzzle resources. It should hide complexity. It should make a best effort. It should fail clearly. And it should do a few things well. This used to be normal. Now it feels almost radical.

It Should Work on a Plane

The most basic property of local software is that it is local. That sounds obvious, but apparently it is not. Too many desktop apps are really just web clients with a prettier icon, permanently one expired token away from becoming decorative.

People will tell you that this no longer matters because planes have internet now. Sure. They do. It is slow, unreliable, expensive, and shared with two hundred other people trying to sync photos and watch YouTube. Modern apps are gluttons. They are constantly polling, syncing, loading avatars, refreshing timelines, checking entitlements, and downloading things they could have shipped with in the first place. A local app should not become useless the moment the connection gets bad.

If I have the binary and the data, the software should do its job. Notes should open. Images should edit. Music should play. Documents should save. Search should search. Network features can enhance the experience, but they should not be the foundation holding the entire thing up.

It Should Not Guzzle Resources

A local app is running on my machine. That means it should behave like a respectful guest. It should not casually occupy a gigabyte of RAM to render what is basically a text box, a sidebar, and some buttons. It should not spin fans, drain battery, and wake the CPU ten times a second because somebody decided the easiest way to build a desktop app was to smuggle an entire browser into memory.

Non-native apps are cancerous in this regard. They haul in enormous runtimes, duplicate half the platform, and then act surprised when the machine feels slower for no obvious reason. Obviously there are exceptions, and sometimes the tradeoff is worth it, but the baseline should still be discipline. Fast launch. Modest memory use. Low idle CPU. No drama.

Good software should feel light in the hand. You should be able to leave it open all day without feeling like you adopted another operating system by accident.

It Should Hide Complexity

Complexity in itself is not a sin. Some problems are genuinely hard. Video editing is hard. Compilers are hard. Databases are hard. The point is that the user should not have to manually carry that complexity just because the engineers failed to absorb it.

Good software is like a mechanical watch. Inside, there can be extraordinary complexity. On the outside, there is a crown and a dial. You do not open the caseback every morning and tweak the escapement yourself. That would be absurd. Yet modern software routinely asks users to reason about caches, sync conflicts, workspace state, providers, backends, feature flags, permissions, container health, and other implementation details that should have remained under the hood.

A good interface does not expose the shape of the org chart that built it. It does not make you learn the internal boundaries between three teams and four microservices just to rename a file. The complexity should exist in the code, not in the user's head.

It Should Try to Do the Job Anyway

One of the best pieces of software ever written is VLC. It has the mindset more software should have: here is a damaged file, a weird codec, a broken stream, some malformed metadata, and a container from a civilization long dead. Fine. Let's see what we can salvage.

That is the right instinct. Software should try. It should not throw up its hands at the first irregularity and make the user suffer for it. If a document is slightly corrupted, recover what can be recovered. If a config file has one bad field, point it out and load the rest. If a media file is missing an index, rebuild it. If a network share disappears, let me keep working locally until it comes back.

Computers are literal, but good software does not have to be brittle. Best effort matters because the real world is messy. Files are incomplete. Metadata lies. Humans make mistakes. Disks fill up. Connections flap. Systems restart halfway through writes. A tool that is useful only when the world is pristine is not robust software. It is a lab demo.

It Should Give Meaningful Errors

When something does fail, the software should tell the truth in a way that is useful. Not Unknown error. Not Something went wrong. Not a red banner with a UUID and no explanation. An error message should answer three questions: what happened, what still works, and what I can do next.

"Could not save because the disk is full" is a good error. "Connection lost; your changes are stored locally and will sync when you reconnect" is a good error. "Cannot open this file because it uses feature X from a newer version" is a good error. These messages respect the user's time. They turn a failure into a concrete situation.

Bad software treats errors as embarrassment to be hidden. Good software treats them as part of the job. If the program knows enough to stop, it usually knows enough to explain why.

It Should Do a Few Things Well

The easiest way to make software worse is to keep adding adjacent ideas. First it edits text. Then it publishes. Then it collaborates. Then it hosts a community. Then it becomes a workspace. Then it grows AI summaries and a billing portal and a template marketplace and seven tabs nobody opens. Focus is not a missing feature. Focus is the feature.

The software people remember fondly usually had a very clear shape. Winamp played music. IrfanView opened images instantly. Notepad edited text. 7-Zip handled archives. They might have had depth, but they had a center of gravity. You knew what they were for. They respected your time by not trying to annex the rest of your workflow.

This is especially true for local software because local tools live next to other local tools. They do not need to eat the whole stack. They can be small, sharp, and confident enough to leave other jobs to other programs.

It Should Not Scatter Files Everywhere

A program should also be tidy. If it creates caches, indexes, temp files, logs, thumbnails, previews, or recovery data, it should keep them in a predictable place. One neat home for the debris of running the software, not a trail of junk across Documents, the home directory, random hidden folders, and five vaguely named subdirectories under Library or AppData.

Messy software turns basic system hygiene into archaeology. You uninstall it and half of it is still there. You run a search and find caches from three years ago. You try to back up your real files and discover the app sprayed generated garbage right next to them. This is not a hard problem. It is a matter of respect.

If an app needs working files, fine. Give them a proper location. Name them clearly. Clean them up when possible. Let the user understand what is theirs and what belongs to the program.

It Should Let You Own Your Work

If software is local, then it should actually respect the idea that the machine and the data are yours. Your files should be stored in sane formats. Export should be real export, not a ceremonial gesture that strips half the value on the way out. You should be able to leave without feeling like you are escaping a cult.

Too much modern software treats your own work as hostage collateral for retention. The notes are yours until you want to move them. The project is yours until you stop paying. The library is yours until the vendor changes direction. This is backwards. Good software helps you make things. It does not build a moat around them.

Ownership means the tool is serving the work, not annexing it. The value should remain in your files, your habits, and your machine, not in some obscure proprietary container only one company can decode.

It Should Be Predictable

Good local software should also be unsurprising. Buttons should do what they say. Files should open where you expect. Settings should stay set. Keyboard shortcuts should not change because a product manager got bored. Good tools are boring in the best way.

Predictability sounds less glamorous than innovation, but it is one of the highest forms of respect a tool can show its user. You build muscle memory. You learn its edges. You stop thinking about the software and start thinking about the work. Then one day it ships a heroic redesign and the save button has moved, the menus are renamed, and your habits have to be rebuilt for no good reason.

A reliable tool should feel steady under the hand. Not frozen forever, but stable enough that improvement does not come at the cost of familiarity. When software keeps changing its mind, the user pays the bill.

Local Is a Philosophy

Running on your machine is not just a deployment detail. It is a design philosophy. It forces a certain honesty. You cannot hide latency behind a spinner forever. You cannot depend on a control plane in another country for every button click. You cannot hand-wave basic reliability by saying the backend team will fix it later.

Good local software has to earn its place on disk. It has to be fast enough, clear enough, and reliable enough that the user wants to keep it around for years. That usually means restraint. A smaller surface area. Better defaults. Cleaner failure modes. More respect for the machine and the person sitting in front of it.

What the Standard Should Be

I think the standard is actually simple. If I install a local app, it should keep being useful when the network is gone, when the input is a bit broken, and when I have no interest in learning how it is implemented. It should solve a real problem, explain itself honestly, and avoid growing into a lifestyle brand.

That is what good local software is supposed to be: capable, quiet, forgiving, and focused. A tool, not a hostage situation.

Back to blog