Skip to main content
← Blog

Calling Fecit from the Terminal — a Single-Binary CLI

VauDium·

We made Fecit — until now a screen-only app — something you can also call from the terminal. The story of a client that ships as one executable, no runtime required, speaking the same language as the apps.

Calling Fecit from the Terminal — a Single-Binary CLI

Fecit is an app you use through a screen. With your fingers on mobile, with a mouse on desktop. But sometimes you want to reach it without going through a screen at all — without lifting your hands off the keyboard. So we built one more thing: a client you call from the terminal — a CLI.

Why a Terminal for a To-Do App

A command-line tool for a task manager might sound like a mismatch. But for someone who lives in the terminal all day, the few seconds of spawning a new window and hunting across a screen break the flow. Finishing with a single word — fecit — is faster.

And a terminal tool isn’t called only by people. Scripts call it, automation calls it, other tools pipe into it. There’s a place a screen-bound app can’t reach, and that’s where it lives.

What It Can Do Today

The CLI started small. Right now it logs you in (fecit login), shows your account (fecit whoami), and logs you out (fecit logout). Next come the commands to view, create, and complete tasks straight from the terminal. The models and the API already exist, so adding commands is quick.

It Speaks the Same Language as the Apps

The most reassuring part of building it was that there was almost nothing to write from scratch.

Fecit’s data models already live in a shared package, @fecit/shared. Mobile uses them, desktop uses them. The CLI imports the very same ones. A task, an achievement — all three clients interpret them identically. The CLI isn’t an oddball; it’s just one more client calling the same backend.

That, really, is why a CLI can exist at all. When there’s a well-organized API behind the screen and the models sit in one place, attaching a new surface stops being construction and becomes connection.

One Executable

A tool only gets used if it’s light in the hand. So the CLI ships as a single executable.

Bun bundles the TypeScript into one binary: bun build --compile drops out a 59MB executable, and whoever receives it just runs it — no Node, no Bun to install. You can stamp out builds for macOS, Linux, and Windows separately. The question “what do I need to install first?” never even comes up.

Pick Your Way In

We kept the entrance open. Type fecit login and a browser opens, where you log in with one of three — Google, Apple, or an ID. Or skip the browser entirely and sign in with an ID and password right in the terminal (handy when you’re wiring it into a script). Either way, once you’re in, it remembers your token and you’re straight through next time. How we brought that login into the terminal is a short story of its own — I’ll unpack it in the next post.

A Lingering Thought

Bolting a CLI onto a product exposes its skeleton. Strip away the screen, and is there an API to call underneath? Is there a single set of models that interprets the data? Fecit happened to have both, which is why fitting a new surface — the terminal — took no major construction.

The screen is a product’s face, not the whole of it. The same product, now called in a single line.