←新闻详情

Mitchell Hashimoto 原创博客更新于 10月13日 04:34

Mitchell Hashimoto 提出终端程序状态协议 OSC 7501

A Terminal Protocol for Program Status (OSC 7501) – Mitchell Hashimoto

AI 导读

Mitchell Hashimoto 为终端写了一份新转义序列规范 OSC 7501,即 Program Status Protocol,让程序通过 pty 直接上报自身状态:idle、working、waiting on the user、finished 或 failed,并可附带原因。序列体由冒号分隔的 key=value 组成,唯一必填键是 state,可选 app 和 base64 编码的 msg,多任务可用层级 id 同时上报多条记录。他指出 agentic inbox 目前靠屏幕启发式或非终端 API 判断 agent 状态,前者需频繁维护规则,后者要逐个集成且难以跨 SSH 和容器;他已用不超过十几行代码在 libghostty、Rex、Terraform、Claude Code、Codex 和 Homebrew 中实现该协议。

推荐理由

AI 评分 59

作者提出终端原生状态协议并给出多语言实现,读者可据此理解现有 agent 状态检测的局限与替代方案。

主题

标签

正文

当前显示原文,中文全文译文尚未就绪。

I wrote a specification for a new terminal escape sequence: OSC 7501, the Program Status Protocol. It lets any program tell the terminal what it's doing: idle, working, waiting on the user, finished, or failed, and why.

For example, here is how Terraform could indicate that it is blocked waiting for user input, with the message "Apply 3 to add, 1 to change, 0 to destroy?" (base64-encoded). A terminal (or any other tool running Terraform) could show this information however it feels appropriate: a notification, an inbox, a status icon, etc.

This post covers why I think this protocol needs to exist, why the existing approaches aren't good enough (especially for coding agents), and how the protocol works.

This is a completely generic, terminal-native specification and protocol. It emerged from my work on Superlogical and Ghostty but the specification has no product-specific functionality or language. It is designed as an idiomatic, well-formed specification that any terminal developer will find familiar.

The Problem

Long-running work is common in terminals: builds, deployments, package upgrades, data processing, and, more and more today, coding agents. These programs alternate between working on their own, waiting on the user, and finishing. Meanwhile, users usually go off and do something else and want to know when the work finishes or needs them.

Aspects of this problem have been solved in various ways going back decades. For example, some terminals monitor the active foreground process and have features to notify when it changes. Or, they wait for some time period of "quiet" (for various definitions) output. The specification also lists the reasons why existing sequences aren't enough.

Ultimately, I felt there wasn't a cohesive, interaction-agnostic, generic solution to this problem that conveyed progress, blocking, completion, and trees of tasks. And it wasn't possible to cobble together pre-existing sequences to achieve it robustly, either.

Singling Out "Agentic Inboxes"

Don't care about AI, LLMs, etc.? Skip this section. The problem is generic and applies in a compelling way without bringing in AI. It's particularly nasty with AI so I want to call it out, but if you don't care about any of that, just skip this.

It's now increasingly common for people to run many long-running agents for any number of reasons: background research, issue monitoring, bug fixing, large features, etc. Each one works for a while and then stops to ask for permission, ask a question, or report it's done.

From this, a new category of tool has emerged that I'll simply call the agentic inbox: a single view across every running agent showing which are working, which are done, and which are waiting on you. Herdr, cmux, and Agent Deck are a few examples of hundreds.

Without a dedicated protocol, they solve the agent status problem in two ways: heuristics and non-terminal APIs.

Heuristics

The first approach is to guess by reading the screen or the window title and matching it against known patterns.

Herdr is a good example because it does this well and documents it openly. Its detection manifests are TOML rules that classify an agent as idle, working, or blocked. Here is the first of 16 rules for Claude Code:

Claude Code is considered "working" if its window title starts with a Braille spinner character or, as of version 2.1.228, a half-circle one. The history of that file shows ten changes in three months for just Claude Code.

This isn't a criticism of Herdr. Its maintainers are doing the best possible job with the tools available. But it demonstrates well the benefit a unified protocol would have.

Non-Terminal APIs

The second approach is to have the program report its own state through an inbox-specific, out-of-band API such as Herdr's socket API or cmux notify. This is better than heuristics in some ways, because the program that actually knows its state is the one reporting it. But every program has to integrate with every inbox separately, and a local socket doesn't work over SSH or from within a container without extra bridging. The pty already works across all of this.

The Program Status Protocol

OSC 7501 is a terminal native answer to this problem. The program reports its own state directly via the pty that it always has, using a format that is safe to send everywhere (well-behaved terminals ignore unknown OSCs).

The body of the sequence is a list of key=value pairs separated by :. The only required key is state, which is one of:

Optional keys include app, a stable machine-readable program name like cargo or claude-code, and msg, a single human-readable line encoded as base64.

Programs that run several things at once can report multiple records using hierarchical ids. A deploy tool can be working at the root while us-east pushes an image at 40% and eu-west is blocked waiting for approval to deploy to production. Both are true at the same time, and the terminal decides what to show. A clear state removes records.

Here's a complete integration for a shell script to wrap rsync to participate in this protocol:

Trivial to script with plain old POSIX sh. No SDK, no sockets, no environment variables, no JSON. No bias towards specific GUI presentations. No bias to any specific workload (like AI). A well-formed, generic foundation to build functionality above that anyone and everyone can participate with.

The full spec covers the rest: record lifetime, feature detection, terminfo, size limits, and security. It's short. I wrote it all by hand. Please read it.

Implement It

I wrote this specification based on my experience maintaining a terminal emulator for many years now. It is written in a way that is easy for application developers to emit, and easy for terminal emulators to consume and parse.

I've already implemented this protocol twice. We have one implementation in libghostty and I have a parallel implementation in Rex. I've also implemented it as a proof-of-concept in Terraform, Claude Code, Codex, and Homebrew via either plugins or forks. In each case, the implementation was no more than a dozen lines.

I've been in contact with the maintainers of many popular terminal programs and emulators and they've helped review and shape the specification. But if you have any more feedback, I'm happy to hear it.

If you've implemented the specification please let me know via email (mail icon in the footer) and I'll add you to the list of tools that implement this. Thank you.

I'd like us all to stop guessing what programs are doing by reading their screens or process trees. The program already knows. Let's give it a way to tell us!

来源

Mitchell Hashimoto 原创博客