What We Learned Building Bento
The problem was ours first
We didn’t set out to build a product. We had a problem.
Our projects typically involve multiple services running simultaneously: an API server, a frontend dev server, a database, a background worker, maybe a reverse proxy. The standard workflow is: open a bunch of terminal tabs, start each service manually, and spend the rest of the day switching between them to check logs, restart crashed processes, and figure out which service is actually throwing the error.
It’s not hard. It’s just friction. Constant, low-grade friction that adds up across a full day of development. You lose focus every time you context-switch between tabs. You miss log output because it scrolled past in the wrong terminal. You forget to restart the service that depends on the one you just restarted.
We wanted a single command that started everything, showed us everything, and let us control everything from one place. That’s what Bento became.
Start with the config
The first design decision was the configuration format. We went with YAML. A bento.yaml file defines all the tasks for a project. Each task has a name, a command, and optional configuration like working directory, environment variables, dependencies, auto-start, and auto-restart behavior.
We chose YAML over code-based configuration for a specific reason: we wanted the config to be readable by anyone on the team, not just the person who wrote it. A YAML file that says command: npm run dev is self-documenting. A programmatic config that constructs process objects isn’t.
This ties back to a principle we talk about a lot: specifications should be readable by everyone involved. A bento.yaml is a specification for how to run the project. It should be as clear as a README.
The terminal as a constraint
Building for the terminal forces clarity in a way that graphical interfaces don’t.
In a GUI, you can always add another panel, another menu, another tooltip. The canvas is effectively infinite. In a terminal, you have rows and columns of text. Every piece of information competes for limited screen real estate. Every interaction has to work with a keyboard. There’s no hover state, no drag-and-drop, no floating popups.
These constraints turned out to be an advantage. They forced us to answer hard questions early: What’s the minimum information a developer needs to see at a glance? What interactions do they need most frequently? What can we hide until they need it?
The answers shaped Bento’s two-view architecture: a list view that shows all tasks with their status and recent log output, and a pane view that gives each task its own dedicated output area. The list view is for monitoring. The pane view is for debugging. Most of the time, developers live in list view. When something breaks, they switch to pane view to read the full output.
We tried more complex layouts early on, side-by-side splits, tree views, tabbed output panels. They all looked impressive in demos and were confusing in practice. The simpler two-view model won because it maps to how developers actually think: “Is everything running?” and “What’s wrong with this one thing?”
Dependencies matter more than you’d think
One feature that seemed like a nice-to-have turned out to be essential: task dependencies.
In a multi-service project, order matters. The database has to be running before the API server starts. The API server has to be healthy before the frontend can connect to it. Without dependencies, developers either start tasks manually in the right order or build wrapper scripts that sleep for arbitrary durations and hope for the best.
Bento’s dependency system lets you declare that task B depends on task A. When you start B, Bento ensures A is running first. When A restarts, B restarts automatically. This sounds simple, but it eliminates an entire class of “why isn’t this working” problems that eat time every day.
The lesson: developer tools should encode the knowledge that developers currently carry in their heads. The startup order for a project’s services is tribal knowledge. Making it explicit in the config and enforcing it automatically is a small thing that saves real time.
Theming was a surprise
We added theming almost as an afterthought. Bento ships with eight built-in color themes. We expected it to be a minor feature. It turned out to be one of the things people mention most.
Developer tools are personal. People spend hours a day in their terminal, and they have strong opinions about how it looks. A tool that lets you make it yours gets adopted faster than one that doesn’t.
The deeper lesson is about developer tool adoption in general. Functionality gets you in the door, but the experience keeps you there. Developers will use a tool with mediocre UX if it’s the only option. They’ll choose a tool with great UX when alternatives exist. Theming is a small part of UX, but it signals that the builders care about the experience, not just the functionality.
What we cut
We cut more features than we shipped. That was intentional.
Early versions had built-in health checks with HTTP polling. We cut it: too opinionated about infrastructure. We prototyped a plugin system for extending Bento with custom task types. We cut that too: too early to know what the right abstractions were. We designed a remote mode for managing tasks on remote servers. Scope creep. Cut.
The principle: ship the smallest thing that solves the core problem well, and learn from usage what to build next. It’s easy to say. It’s hard to do when you can see twenty good features on the horizon. But every feature you add is a feature you maintain, document, support, and defend against regressions. The cost of shipping is not the cost of building. It’s the cost of carrying.
Bento is better for what we cut. The features that survived are the ones that every multi-service developer needs. The ones we cut were the ones that some developers might want sometimes. That distinction matters.
Craft takes time
One of our values is “craft over speed.” Bento tested that value.
There were multiple points during development where we could have shipped something that worked but didn’t feel right. The list view had a rendering bug that only showed up with long task names. The keyboard shortcuts conflicted with common terminal emulator bindings. The auto-restart logic had a race condition that caused double-starts under specific timing.
None of these were showstoppers. Users probably would have tolerated them. But tolerating rough edges in a developer tool erodes trust. Developers are the most discerning users in software, they notice everything, they compare everything, and they remember the tools that annoyed them.
So we fixed them. It took longer. It was worth it.
Building in the open
Bento is part of Appology Labs, our research and open-tools arm. We’re releasing it publicly because we believe the best developer tools are shared ones.
Building tools for developers is how we sharpen our craft. Every tool we build teaches us something about developer workflows, about UX under constraints, about what matters in software and what doesn’t. Those lessons make us better at the consulting and custom development work that pays the bills.
And if Bento makes someone’s day a little less frustrating, one less context switch, one less “which terminal tab was that in”. That’s worth the investment.