I Shipped a Terminal HUD, Told Nobody, and Watched It Get 3,500 Downloads
I published an npm package in April and told exactly zero people it existed. Not a tweet, not a Reddit post, not even a message to the one friend who actually cares about my terminal setup. I just pushed it and went back to the thing I was actually supposed to be building. Six weeks later, I checked npm out of idle curiosity and found out strangers had downloaded it over 3,000 times without me.
That specific flavor of embarrassment — where you realize people have been using something you never documented, never announced, never even thought to explain — is what finally made me sit down and write this.
The Thing I Was Actually Building
It started with claude-setup, a project to standardize my Claude Code environment. Part of that was wiring up a custom statusline hook — the little strip at the bottom of the terminal that Claude Code lets you replace with your own script. I poked at the default hook, figured out the JSON it received, and thought: I can do something with this.
That "something" turned into Lumira. Named it that because claude-hud was already taken on npm, which I discovered after I'd already mentally committed to calling it a HUD. The original statusline showed model name and working directory. Fine for 10-minute sessions. Useless for the kind of 3-hour agentic run where you start to lose track of whether you're at 40% context or 80%, whether the thing you kicked off 45 minutes ago is still running, and whether you're burning through your rate limits faster than you'd like.
Flying Blind at Hour Three
It turns the Claude Code statusline into something that tells you what's actually happening. The context bar is the feature I use most. It's a visual fill that grows as the session consumes context window — I can see I'm at 74% and know I should compact before starting the next phase rather than hitting the wall mid-task. The bar shifts color as it climbs, and at 75-80% it throws a warning so I have time to act rather than react.
Burn rate is the one that made me actually change my behavior. Seeing $3.40/h in the corner during a dense agentic session is clarifying in a way that the end-of-month bill is not. You make different decisions when the cost is live.
Subagent tracking is the feature I'm most proud of, and the one I got most wrong on the first try. I'll come back to it.
The rest of what's in there now — themes, no dependencies, works with Qwen Code, a version that shipped last week — accumulated the way side projects accumulate when you keep opening them. The one piece I want to flag is the contrast checking. There are seven themes, and somewhere around theme three I added a CI step that fails the build if any foreground/background pair falls below WCAG AA 4.5:1. I did not plan to care about color contrast in a terminal toy. I cared a lot once I noticed how many "pretty" terminal themes are unreadable in bright rooms. That CI check is now the thing I'm quietly proudest of, which tells you something about either accessibility or my expectations for myself.
The Part That Actually Hurt
Subagent tracking sounds straightforward: Claude Code spawns subagents to run parallel tasks, you show the user how many are running and what they're doing. Simple.
My first implementation read state from the main JSONL file — the transcript that Claude Code writes for the session. Parse the events, infer which agents are active, display accordingly. I shipped it, it kind of worked, and I was mostly satisfied. Mostly.
The problem was buffering lag. The main JSONL gets written in batches, which means what you're reading is not the current state — it's the state from a few seconds ago, sometimes longer during heavy I/O. Subagents would appear still "running" after they'd already finished. Agents that had just been spawned wouldn't show up yet. The display was reliably, subtly wrong.
The specific moment I remember: I'd kicked off four parallel research subagents, watched the statusline show four green dots for a while, and then noticed that three of them had already posted their results in the transcript above. The dots were lying to me. I knew they were lying because I could read the actual output two inches higher on the same screen. And I still didn't change the approach. I added a shorter polling interval. The dots lied faster.
Over the next few evenings I tried every patch that didn't require admitting the foundation was wrong. Tighter polling. A heuristic that compared the JSONL tail timestamp to wall-clock time and dimmed stale entries. A "probably finished" state for agents whose last event was older than thirty seconds. Each fix made the display feel slightly more honest and remained, underneath, wrong in the same way. At one point I was writing test cases against a buffering model I had inferred from observation, which should have been my hint: I was building a theory of someone else's I/O behavior instead of reading the file they were actually writing for me.
The fix was embarrassingly obvious once I stopped defending my original approach: Claude Code writes per-agent transcript files directly, one per subagent. Reading those files gives you the actual current state with no lag. I switched to that, the tracking became accurate, and I wished I'd done it that way from the start.
The lesson wasn't about JSONL vs transcript files. It was about how long I was willing to keep patching something that was wrong in a foundational way because I didn't want to admit I'd built on the wrong assumption. A thousand tests across 51 test files exist partly because of that section of the code — by the time I got the subagent tracking right, "side project" wasn't really the right word for it anymore.
The Number That Made No Sense
v0.1.0 went up April 10. I didn't post about it anywhere. I checked npm a few weeks later and found that April 23 had 369 downloads in a single day.
I spent that evening trying to find a source. Searched the package name on Hacker News, on lobste.rs, on Reddit's r/commandline and r/programming, on Twitter and Bluesky. Checked GitHub for referring stars (there weren't any spikes). Looked at the npm download graph for the surrounding days hoping for a pattern that pointed somewhere — was it a region, a CI mirror, a single org pulling it across a fleet? Nothing surfaced. The day before was 12 downloads. The day after was 18. April 23 sat there like a typo.
I have no explanation for it. One day, 369 people — or CI pipelines, or install scripts, npm download counts don't distinguish — decided to install it. The most honest thing I can tell you is that I looked, I looked for a while, and I gave up.
Since then: 3,532 downloads last month, 615 last week. Healthy. Not a rocket ship. Growing, mostly without me doing anything to push it.
What The Strangers Taught Me
- Ship before you're ready to explain it. I published without a README because I wasn't done. The downloads happened anyway. Waiting for "ready" is often just waiting.
- The embarrassing version number tells the truth. Thirty-four versions in six weeks reads as chaotic. It was also the right pace for a tool I used every day. Real usage caught things that review wouldn't.
- Don't defend a wrong foundation. Eight hours trying to extract real-time state from a batched log file. Thirty minutes after I stopped: fixed. The JSONL thing wasn't a bug I could patch out. It was the wrong model of the problem.
- Zero dependencies is a constraint that pays for itself. Every version of Lumira ever shipped installs and runs the same. No peer-dependency hell, no upstream breaking changes, no audit warnings. I've never once regretted that decision.
- Not promoting something doesn't mean it won't find an audience. I still don't entirely understand why it grew. I think the problem is real and specific enough that people searching for it find it. Maybe that's enough.
The thing about Lumira is that I use it in every session. It's running right now, in the terminal behind this post, showing me a context bar and a burn rate and zero active subagents because I've finished the agentic work for today. It does exactly what I needed.
If you're using it and something's wrong or missing — I want to know. The project grew without me saying much. The conversation doesn't have to stay one-sided.
GitHub: github.com/cativo23/lumira npm: npmjs.com/package/lumira Install: npx lumira install License: MIT, no telemetry, no runtime dependencies
If your Powerline separators look wrong in tmux, add set -g allow-passthrough on to your tmux.conf and restart the server. Fixes 80% of the rendering complaints.