The spinner was never an interface.
Long-running terminal programs already move through useful states. They work, wait for input, finish, or fail. Tools that collect several sessions often infer those states from window titles, spinner glyphs, screen text, or program-specific sockets. Mitchell Hashimoto's OSC 7501 proposal gives the program a terminal-native report instead.[1]
The timing matters. Claude Code 2.1.295 added Program Status Protocol support on October 8. Its release notes say compatible terminals can show whether Claude Code is working, waiting on the user, or done.[3] This is one implementation claim from one release. It does not establish broad terminal support.
A status inbox should read declared state before it tries to recognize animated punctuation.
The contract is small enough to inspect.
A report is an Operating System Command sequence with colon-separated key=value pairs. state is required. The defined values are idle, working, done, blocked, error, and clear. A blocked report can name permission, question, or auth as its kind. Working and blocked reports may carry an integer progress value between zero and 100.[2]
The protocol also supports record IDs. A parent task and its children can report separate states in one terminal. Reports replace the addressed record instead of patching old fields. That rule matters. A stale permission message should not survive when the program returns to work.
Lifetime is part of the meaning.
working and blocked disappear when the attached process exits or a new shell prompt begins. done and error can survive those events so the user can find an unseen result. There is no heartbeat. The terminal owns the records and decides how to present them.[2]
That separation is the strongest part of the proposal. A command reports facts. The terminal can use a tab marker, session list, quiet notification, or no visible treatment. A dashboard does not need every command to know its layout.
Structured status is still untrusted input.
A process that controls terminal output can also emit a false status report. The specification treats every field as untrusted. It bans control characters in decoded titles and messages, says terminals must not parse them as markup, caps a whole sequence at 4,096 bytes, and recommends rate limits for sounds or desktop notifications.[2]
A status message should identify the terminal that produced it. It should not become authority to approve a tool call, enter a credential, or claim that a deployment passed. State helps route attention. It is not execution proof.
The rough edge is vocabulary.
The Hacker News thread found the useful disagreement fast. One commenter argued that permission, question, and auth lean too hard toward agent interfaces. Another pointed out that ordinary command-line programs ask for passwords too.[4] That is the right argument to have before more programs depend on the names.
The design below makes the separation visible. One native control chooses the declared state. The app and message fields shape a report preview. The readout says what the state means and what it cannot prove.