A status line that refuses to lie about tokens saved
Your status line is prime real estate — so what earns a spot? SpecShip’s segment shows index sync state, drift, and how many times it was actually called. Not “tokens saved”: that number has no honest source at runtime, so we don’t fake it.
The status line is the one strip of the terminal an agent never scrolls away. One to three lines, always visible, sitting right above where you type. That makes it the most expensive real estate in the whole tool — and the question for any feature that wants a spot there is brutally simple: is this worth a glance, every single render, forever?
SpecShip now ships a status-line segment for Claude Code. Building it turned out to be less about what to show and more about one thing we refused to show.
The line we refused to write
The obvious headline number for a code-intelligence tool is "tokens saved." It's the whole pitch: ask the graph instead of grepping and reading, and the agent burns far less context. A live counter ticking up — saved 412k tokens — would be the perfect flex in the corner of your screen.
We didn't build it, because it would be a lie.
"Tokens saved" is a counterfactual: it's the difference between what you spent and what you would have spent without SpecShip. That second number doesn't exist at runtime. There is no parallel session where the agent grepped and read its way to the same answer for us to subtract from. Our own benchmarks measure it by running both arms — with and without — across real repositories and comparing. That's a measurement you do in a lab, not a number you can mint live in a status bar. Any figure we printed would be a model multiplied by a guess, dressed up as telemetry.
So instead of an invented savings figure, the segment shows the honest thing right next to it: how many times specship was actually called this session. 7 calls is a fact — it happened, we counted it. It carries the same signal a user actually wants ("is this tool earning its place in my loop?") without pretending to know the road not taken.
"Tokens saved" needs a universe where you didn't install SpecShip. "7 calls" just needs a counter. Only one of those is true.
What does earn a spot
With the vanity metric out, four things were left — each one a fact the graph already knows, each one something you'd otherwise have to run a command to check:
There's also a quiet fifth: a warning when the index is running on a degraded, non-WAL database path (a network mount, a WSL2 /mnt drive) where reads can block — the kind of thing that silently makes everything feel slow until someone notices. The status line notices for you.
Composable, never a takeover
Plenty of tools install a status line by replacing yours. That's a non-starter — your status line is yours, and you've probably already got a model name, a token meter, a git branch, maybe a cost readout in there. So the segment is exactly that: a segment. The command reads Claude Code's status-line JSON on stdin and prints one line. You append it to whatever you already run.
# your existing line(s) above… specship_line=$(echo "$input" | specship statusline) # …then append "$specship_line" to your final output.
Prefer not to wire it by hand? specship install offers to do it for you — opt-in, off by default. And it will never overwrite a status line you already have: if one's configured, it leaves it untouched and just hands you the snippet above. uninstall removes only the entry it added, leaving yours exactly as it was.
NO_COLOR. The default look is gold art-deco bars and diamonds — but set NO_COLOR and you get clean, ANSI-free text that's safe in any terminal or log.Fast enough to render on every keystroke
Here's the constraint that shaped the whole design: a status line re-renders constantly — sub-second, on basically every update. Whatever the command does, it does that often. So the one thing it must never do is the obvious thing: open the database.
SpecShip's index is a SQLite knowledge graph. Cracking it open, running queries, and closing it on every render would lag your prompt into uselessness. So the read path never touches it. The segment reads two tiny JSON cache files and prints — no database handle, no query, no subprocess. If the database is mid-write, locked, or absent entirely, the status line doesn't care; it just renders what the caches last knew.
Keeping those caches warm is the job of the producers — the parts of SpecShip that already have the database open anyway:
- Index, sync, and the file watcher refresh the sync/drift/backend cache whenever the graph changes — so the moment you edit a file and it settles, the pending count is already current.
- The MCP server bumps a per-session counter each time the agent calls a specship tool. One Claude Code session spawns one server, so "calls since this server started" is your session's count.
- The workflow engine writes the active run's spec and status as it moves through plan → approve → implement, and clears it when the run ends.
Every one of those writes is best-effort and atomic — a cache refresh can never break an index, and a half-written file can never reach the reader. The expensive work happens where the database is already open; the cheap work happens where you can see it.
The reader is dumb on purpose. All the intelligence lives in the producers, which run where the database is already warm — never on the render path.
The shape of an honest dashboard
A status line is a tiny thing. But it's a tiny thing you stare at thousands of times a day, and that makes it a surprisingly sharp test of a tool's values. Every pixel is a claim. Show a fabricated number and you've taught the user to discount the real ones. Replace their setup and you've decided your information matters more than theirs. Open the database on the hot path and you've made the whole tool feel slow.
We tried to fail none of those. The segment shows four true things and one honest stand-in for a number we can't actually compute, composes into whatever you already run, and stays out of the way of the database it reports on. ◈ specship ◆ ✓ synced ◆ 7 calls ◈ — small, fast, and every glyph of it earned.