Claude Code statusline: the cheapest feedback loop you are not using

The status line is the one place in Claude Code to surface state you would otherwise stop and ask for. Almost everyone leaves it empty. Here is the mechanism, and a real one taken apart line by line.

The kitstarter robot pointing at a status line under a terminal prompt

The default Claude Code status line is blank. That is a wasted channel. It is the one strip of screen the agent updates for free on every turn, and most people never wire it. This post explains exactly how the mechanism works, then takes apart the real Claude Code statusline we ship so you can see what belongs there and what is noise.

What a Claude Code statusline actually is

A Claude Code statusline is a script Claude Code runs and prints under your prompt. It hands the script a JSON payload on stdin (the model, the workspace including the current directory, cost, the context window) and renders whatever the script writes to stdout, verbatim, on the status line. That is the whole contract. Any language works, because the interface is just stdin in, one line of text out.

Because the payload carries live session state, the status line is the cheapest way to keep that state on screen. Without it you interrupt the agent to ask "which model is this" or "how much has this cost." With it, the answer is already sitting under your prompt, updated on the same events the session already fires.

How Claude Code invokes the script

Claude Code spawns the status line process on event-driven updates: after each assistant message, on /compact, and on permission-mode changes, debounced at 300ms. It does not poll on a timer unless you set refreshInterval. The script's stdout is a pipe, not a tty, so it must decide color from the environment rather than from isTTY.

Those two facts drive real decisions in our script. We deliberately leave refreshInterval unset, because everything the line shows changes on exactly the events Claude Code already refreshes on. A timer would just spawn a Node process to redraw an identical line. Here is the wiring, written into settings.json at install:

typecommand
commandan absolute node path, then the absolute path to statusline.mjs
padding0
refreshIntervalunset on purpose: a timer would spawn node to redraw nothing
The statusLine block our installer writes. The node path is explicit and absolute, because a bare "node" dies silently when Claude Code's shell has a different PATH.

That absolute-path detail is not fussiness. We wire every engine script with an explicit Node path because a bare node command dies silently when the shell Claude Code spawns has a different PATH, and a status line that fails silently is worse than none. If you are still getting set up, our install guide covers the environment this depends on.

Reading our real Claude Code statusline

Our statusline is 74 lines and its job is to be the navigator: always on screen, never in the way. It reads the JSON on stdin, pulls the current directory, loads the kit's config and the project journey, and renders one line. The spine looks like this:

readsworkspace.current_dir from stdin, then config + the saved journey for that dir
printsa violet glyph, "kitstarter", and a body that is either a prompt or your progress
example⬢ kitstarter · my-app · ▓▓▓░░ step 3 of 5 · wire the checkout
One line, three states: no plan yet, mid-plan with a progress bar, or all steps done.

The design choices are visible in the code. When there is no plan, it prints ready · /start to plan: a status line that also tells a beginner the next move. When a plan exists it shows the project name, a progress bar, step N of M, and the current step title truncated to 24 characters. When every step is done it says all N steps done · time to /ship. The line always points at the next action, never just at the state.

Two more things it appends only when true. If the clarity engine is armed it adds · asking first in coral, so you can see at a glance that the agent will ask before it builds. If the tutor is off it dims in · tutor off. Nothing static ever renders. That is the rule for a status line: every character has to earn its place, because it costs attention on every single turn.

Fail open, always

A status line must never break the terminal. Ours is wrapped so that a missing config, no journey, or any thrown error all resolve to an empty line rather than a stack trace under your prompt. The entire render is inside a try that swallows failures:

config offreturn an empty string
any throwcatch it, write nothing
resultworst case is a blank line, never a broken one
Fail open is the non-negotiable rule for anything that renders every turn.

The statusline is one part of the engine

The status line is the visible tip of a larger system. The kit wires eight hook scripts across eight lifecycle events: session start, prompt submit, pre-compact, subagent start, pre-tool-use, post-tool-use, stop, and session end. The clarity lock that forces the agent to ask first, the slop check that runs after edits, the tutor that fires at the right moment: those live in the hooks. The status line is where their state becomes something you can see.

That integration is why the line is worth the trouble. asking first is not decoration. It is the clarity hook reporting that it is armed. The progress bar is the journey the session-start hook loaded. The status line is a read-only window onto the engine, which is the honest use of the surface: show state, do not invent it.

What it costs, measured

We ran a clean-room benchmark of the kit against vanilla Claude Code, and we do not hide the losses. On asking-first the kit went 5 of 5 versus vanilla's 2 of 5, and produced about 40 percent less code for the same outcome. But the hooks that feed the status line are not free. On a simple todo app the kit was about twice as slow and about 75 percent pricier for near-identical output, and across the suite the hook context tokens added roughly a 25 percent average cost premium. That premium is real and disclosed. It buys the guardrails and the navigator you see on the line.

The takeaway is not that instrumentation is expensive. It is that instrumentation you never look at is pure cost. A status line is the one piece that pays for itself on every turn, because it turns state you would have interrupted to ask for into something already on screen. Wire it. Show the model, the directory, the cost, the step. Leave everything else off.

The status line, wired for you

kitstarter ships the navigator status line, the clarity lock, and eight lifecycle hooks, for Claude Code, Codex, and Antigravity.

Get the kit · $29Read the docs