{"article":{"slug":"a-terminal-protocol-for-program-status-osc-7501","title":"A Terminal Protocol for Program Status (OSC 7501)","subtitle":null,"summary":"Mitchell Hashimoto introduces OSC 7501, a generic terminal escape sequence that lets programs report whether they are idle, working, blocked on the user, finished or failed, and why. He argues heuristics and non-terminal APIs fall short, especially for agentic inboxes tracking many coding agents, and describes implementations in libghostty and Rex.","content_type":"blog_post","language":"en","canonical_url":"https://mitchellh.com/writing/program-status-osc7501","author":{"name":"Mitchell Hashimoto","url":null,"person_slug":"mitchell-hashimoto-3hdg4f9ppeubn","person_url":"https://listedstartups.com/people/mitchell-hashimoto-3hdg4f9ppeubn"},"authored_by":"human","publisher":{"name":"Mitchell Hashimoto","url":"https://mitchellh.com/","listing_slug":null,"listing":null},"topics":[{"name":"Developer Tools","slug":"developer-tools","url":"https://listedarticles.com/topics/developer-tools"},{"name":"AI Agents","slug":"ai-agents","url":"https://listedarticles.com/topics/ai-agents"},{"name":"Open Source","slug":"open-source","url":"https://listedarticles.com/topics/open-source"}],"about_listings":[],"cover_image_url":null,"license":"all-rights-reserved","word_count":1236,"reading_minutes":5,"published_at":"2026-10-06T00:00:00.000Z","added_at":"2026-10-06T23:15:02.280Z","updated_at":"2026-10-06T23:15:02.280Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":true},"profile_url":"https://listedarticles.com/articles/a-terminal-protocol-for-program-status-osc-7501","markdown_url":"https://listedarticles.com/articles/a-terminal-protocol-for-program-status-osc-7501.md","example":false,"citation":"Mitchell Hashimoto, Mitchell Hashimoto. \"A Terminal Protocol for Program Status (OSC 7501).\" 6 Oct 2026. https://mitchellh.com/writing/program-status-osc7501 (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://mitchellh.com/writing/program-status-osc7501"},"body_markdown":"# A Terminal Protocol for Program Status (OSC 7501)\n\nI wrote a specification for a new terminal escape sequence:\n[OSC 7501, the Program Status Protocol](https://www.superlogical.com/rex/docs/build/program-status).\nIt lets any program tell the terminal what it's doing: idle, working,\nwaiting on the user, finished, or failed, and why.\n\nFor example, here is how [Terraform](https://developer.hashicorp.com/terraform)\ncould indicate that it is blocked waiting for user input, with the\nmessage \"Apply 3 to add, 1 to change, 0 to destroy?\" (base64-encoded). A terminal (or any\nother tool running Terraform) could show this information however it feels\nappropriate: a notification, an inbox, a status icon, etc.\n\n`ESC ] 7501 ; state=blocked:kind=permission:app=terraform:msg=QXBwbHkgMyB0byBhZGQsIDEgdG8gY2hhbmdlLCAwIHRvIGRlc3Ryb3k/ ESC \\`\nThis 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.\n\n**This is a completely generic, terminal-native specification and protocol.**\nIt emerged from my work on [Superlogical](https://mitchellh.com/writing/superlogical) and\n[Ghostty](https://ghostty.org/) but [the specification](https://www.superlogical.com/rex/docs/build/program-status) has no product-specific\nfunctionality or language. It is designed as an idiomatic, well-formed\nspecification that any terminal developer will find familiar.\n\n## The Problem\n\nLong-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.\n\nAspects of this problem have been solved in various ways going back decades.\nFor example, some terminals monitor the active foreground process and have\nfeatures to notify when it changes. Or, they wait for some time period of\n\"quiet\" (for various definitions) output. The specification\nalso [lists the reasons why existing sequences aren't enough](https://www.superlogical.com/rex/docs/build/program-status#relationship-to-other-sequences).\n\nUltimately, 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.\n\n## Singling Out \"Agentic Inboxes\"\n\n**Don't care about AI, LLMs, etc.? Skip this section.** The problem\nis generic and applies in a compelling way without bringing in\nAI. It's particularly nasty with AI so I want to call it out, but if you\ndon't care about any of that, just skip this.\n\nIt'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.\n\nFrom this, a new category of tool has emerged that I'll simply call\nthe *agentic inbox*: a single view across every running agent showing\nwhich are working, which are done, and which are waiting on you.\n[Herdr](https://herdr.dev/), [cmux](https://cmux.com/), and\n[Agent Deck](https://github.com/asheshgoplani/agent-deck) are a few examples\nof [hundreds](https://github.com/andyrewlee/awesome-agent-orchestrators).\n\nWithout a dedicated protocol, they solve the agent status problem in two ways: heuristics and non-terminal APIs.\n\n### Heuristics\n\nThe first approach is to guess by reading the screen or the window title and matching it against known patterns.\n\nHerdr is a good example because it does this well and documents it\nopenly. Its [detection manifests](https://herdr.dev/docs/agents/#detection-manifests)\nare TOML rules that classify an agent as idle, working, or blocked. Here is\n[the first of 16 rules](https://github.com/herdrdev/herdr/blob/3d9d2b18dab139ba226ebc5a1c9a9f2c9c3ee4df/src/detect/manifests/claude.toml#L7-L14)\nfor Claude Code:\n\n```\n[[rules]]\nid = \"osc_title_working\"\nstate = \"working\"\npriority = 1100\nregion = \"osc_title\"\nvisible_working = true\n# Braille covers <= 2.1.227; half-circles are the 2.1.228 busy spinner.\nregex = ['^[\\x{2800}-\\x{28FF}\\x{25D0}-\\x{25D3}] ']\n```\nClaude Code is considered \"working\" if its window title starts with a\nBraille spinner character or, as of version 2.1.228, a half-circle one.\nThe [history of that file](https://github.com/herdrdev/herdr/commits/master/src/detect/manifests/claude.toml)\nshows ten changes in three months for just Claude Code.\n\n**This isn't a criticism of Herdr.** Its maintainers are doing the best\npossible job with the tools available. But it demonstrates well the\nbenefit [a unified protocol](https://www.superlogical.com/rex/docs/build/program-status) would have.\n\n### Non-Terminal APIs\n\nThe second approach is to have the program report its own state through\nan inbox-specific, out-of-band API such as\n[Herdr's socket API](https://herdr.dev/docs/socket-api/#agent-state-reporting)\nor [`cmux notify`](https://cmux.com/docs/notifications). This is better\nthan heuristics in some ways, because the program that actually knows its state is the\none reporting it. But every program has to integrate with every inbox\nseparately, and a local socket doesn't work over SSH or from within a\ncontainer without extra bridging. The pty already works across all of this.\n\n## The Program Status Protocol\n\n[OSC 7501](https://www.superlogical.com/rex/docs/build/program-status) is a terminal native answer to this problem. The program\nreports its own state directly via the pty that it always has, using a\nformat that is safe to send everywhere (well-behaved terminals ignore\nunknown OSCs).\n\nThe body of the sequence is a [list of `key=value` pairs](https://www.superlogical.com/rex/docs/build/program-status#syntax) separated by `:`.\nThe only required key is [`state`](https://www.superlogical.com/rex/docs/build/program-status#states), which is one of:\n\n| `state` | Meaning | \n|---|---|\n| `idle` | At rest, waiting for the user's next instruction. | \n| `working` | Running. May include a `progress` percentage. | \n| `done` | Finished. The result is ready and the user hasn't seen it yet. | \n| `blocked` | Can't continue until the user does something. `kind` says what (`permission` ,`question` , or`auth` ) and`msg` says why. | \n| `error` | Failed and stopped. | \n\n[Optional keys](https://www.superlogical.com/rex/docs/build/program-status#keys) include `app`, a stable\nmachine-readable program name like `cargo` or `claude-code`, and `msg`,\na single human-readable line encoded as base64.\n\nPrograms that run several things at once can report multiple records\nusing [hierarchical ids](https://www.superlogical.com/rex/docs/build/program-status#records-and-ids). A [deploy tool](https://www.superlogical.com/rex/docs/build/program-status#several-records)\ncan be `working` at the root while\n`us-east` pushes an image at 40% and `eu-west` is `blocked` waiting for\napproval to deploy to production. Both are true at the same time, and\nthe terminal decides what to show. A `clear` state removes records.\n\nHere's a [complete integration](https://www.superlogical.com/rex/docs/build/program-status#a-shell-function) for a shell script to wrap `rsync`\nto participate in this protocol:\n\n```\nstatus() {\n  printf '\\e]7501;state=%s:msg=%s\\e\\\\' \"$1\" \"$(printf '%s' \"$2\" | base64 | tr -d '\\n')\"\n}\nstatus working \"Syncing photos\"\nrsync -a ~/Photos backup:/photos && status done \"Photos synced\" || status error \"rsync failed\"\n```\nTrivial to script with plain old POSIX `sh`.\nNo SDK, no sockets, no environment variables, no JSON.\nNo bias towards specific GUI presentations. No bias to any specific\nworkload (like AI). A well-formed, generic foundation to build functionality\nabove that anyone and everyone can participate with.\n\nThe [full spec](https://www.superlogical.com/rex/docs/build/program-status)\ncovers the rest: [record lifetime](https://www.superlogical.com/rex/docs/build/program-status#states),\n[feature detection](https://www.superlogical.com/rex/docs/build/program-status#feature-detection),\n[terminfo](https://www.superlogical.com/rex/docs/build/program-status#terminfo), [size limits](https://www.superlogical.com/rex/docs/build/program-status#limits),\nand [security](https://www.superlogical.com/rex/docs/build/program-status#security). It's short. I wrote it all by hand. Please read it.\n\n## Implement It\n\nI wrote [this specification](https://www.superlogical.com/rex/docs/build/program-status) based on my experience maintaining a terminal\nemulator for many years now. It is written in a way that is easy for\napplication developers to emit, and easy for terminal emulators to consume\nand parse.\n\nI've already implemented this protocol twice. We have one implementation\nin [libghostty](https://github.com/ghostty-org/ghostty/pull/14560) and\nI have a parallel implementation in [Rex](https://www.superlogical.com/rex).\nI've also implemented it as a proof-of-concept in Terraform, Claude Code,\nCodex, and Homebrew via either plugins or forks. In each case, the\nimplementation was no more than a dozen lines.\n\nI'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.\n\n**If you've implemented the specification** please let me know via\nemail (mail icon in the footer) and I'll add you to the list of tools\nthat implement this. Thank you.\n\nI'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!\n","body_html":"<h1 id=\"a-terminal-protocol-for-program-status-osc-7501\">A Terminal Protocol for Program Status (OSC 7501)</h1>\n<p>I wrote a specification for a new terminal escape sequence:\n<a href=\"https://www.superlogical.com/rex/docs/build/program-status\" rel=\"nofollow ugc noopener\">OSC 7501, the Program Status Protocol</a>.\nIt lets any program tell the terminal what it&#39;s doing: idle, working,\nwaiting on the user, finished, or failed, and why.</p>\n<p>For example, here is how <a href=\"https://developer.hashicorp.com/terraform\" rel=\"nofollow ugc noopener\">Terraform</a>\ncould indicate that it is blocked waiting for user input, with the\nmessage &quot;Apply 3 to add, 1 to change, 0 to destroy?&quot; (base64-encoded). A terminal (or any\nother tool running Terraform) could show this information however it feels\nappropriate: a notification, an inbox, a status icon, etc.</p>\n<p><code>ESC ] 7501 ; state=blocked:kind=permission:app=terraform:msg=QXBwbHkgMyB0byBhZGQsIDEgdG8gY2hhbmdlLCAwIHRvIGRlc3Ryb3k/ ESC \\</code>\nThis post covers why I think this protocol needs to exist, why the existing approaches aren&#39;t good enough (especially for coding agents), and how the protocol works.</p>\n<p><strong>This is a completely generic, terminal-native specification and protocol.</strong>\nIt emerged from my work on <a href=\"https://mitchellh.com/writing/superlogical\" rel=\"nofollow ugc noopener\">Superlogical</a> and\n<a href=\"https://ghostty.org/\" rel=\"nofollow ugc noopener\">Ghostty</a> but <a href=\"https://www.superlogical.com/rex/docs/build/program-status\" rel=\"nofollow ugc noopener\">the specification</a> has no product-specific\nfunctionality or language. It is designed as an idiomatic, well-formed\nspecification that any terminal developer will find familiar.</p>\n<h2 id=\"the-problem\">The Problem</h2>\n<p>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.</p>\n<p>Aspects of this problem have been solved in various ways going back decades.\nFor example, some terminals monitor the active foreground process and have\nfeatures to notify when it changes. Or, they wait for some time period of\n&quot;quiet&quot; (for various definitions) output. The specification\nalso <a href=\"https://www.superlogical.com/rex/docs/build/program-status#relationship-to-other-sequences\" rel=\"nofollow ugc noopener\">lists the reasons why existing sequences aren&#39;t enough</a>.</p>\n<p>Ultimately, I felt there wasn&#39;t a cohesive, interaction-agnostic, generic solution to this problem that conveyed progress, blocking, completion, and trees of tasks. And it wasn&#39;t possible to cobble together pre-existing sequences to achieve it robustly, either.</p>\n<h2 id=\"singling-out-agentic-inboxes\">Singling Out &quot;Agentic Inboxes&quot;</h2>\n<p><strong>Don&#39;t care about AI, LLMs, etc.? Skip this section.</strong> The problem\nis generic and applies in a compelling way without bringing in\nAI. It&#39;s particularly nasty with AI so I want to call it out, but if you\ndon&#39;t care about any of that, just skip this.</p>\n<p>It&#39;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&#39;s done.</p>\n<p>From this, a new category of tool has emerged that I&#39;ll simply call\nthe <em>agentic inbox</em>: a single view across every running agent showing\nwhich are working, which are done, and which are waiting on you.\n<a href=\"https://herdr.dev/\" rel=\"nofollow ugc noopener\">Herdr</a>, <a href=\"https://cmux.com/\" rel=\"nofollow ugc noopener\">cmux</a>, and\n<a href=\"https://github.com/asheshgoplani/agent-deck\" rel=\"nofollow ugc noopener\">Agent Deck</a> are a few examples\nof <a href=\"https://github.com/andyrewlee/awesome-agent-orchestrators\" rel=\"nofollow ugc noopener\">hundreds</a>.</p>\n<p>Without a dedicated protocol, they solve the agent status problem in two ways: heuristics and non-terminal APIs.</p>\n<h3 id=\"heuristics\">Heuristics</h3>\n<p>The first approach is to guess by reading the screen or the window title and matching it against known patterns.</p>\n<p>Herdr is a good example because it does this well and documents it\nopenly. Its <a href=\"https://herdr.dev/docs/agents/#detection-manifests\" rel=\"nofollow ugc noopener\">detection manifests</a>\nare TOML rules that classify an agent as idle, working, or blocked. Here is\n<a href=\"https://github.com/herdrdev/herdr/blob/3d9d2b18dab139ba226ebc5a1c9a9f2c9c3ee4df/src/detect/manifests/claude.toml#L7-L14\" rel=\"nofollow ugc noopener\">the first of 16 rules</a>\nfor Claude Code:</p>\n<pre><code>[[rules]]\nid = &quot;osc_title_working&quot;\nstate = &quot;working&quot;\npriority = 1100\nregion = &quot;osc_title&quot;\nvisible_working = true\n# Braille covers &lt;= 2.1.227; half-circles are the 2.1.228 busy spinner.\nregex = [&#39;^[\\x{2800}-\\x{28FF}\\x{25D0}-\\x{25D3}] &#39;]</code></pre>\n<p>Claude Code is considered &quot;working&quot; if its window title starts with a\nBraille spinner character or, as of version 2.1.228, a half-circle one.\nThe <a href=\"https://github.com/herdrdev/herdr/commits/master/src/detect/manifests/claude.toml\" rel=\"nofollow ugc noopener\">history of that file</a>\nshows ten changes in three months for just Claude Code.</p>\n<p><strong>This isn&#39;t a criticism of Herdr.</strong> Its maintainers are doing the best\npossible job with the tools available. But it demonstrates well the\nbenefit <a href=\"https://www.superlogical.com/rex/docs/build/program-status\" rel=\"nofollow ugc noopener\">a unified protocol</a> would have.</p>\n<h3 id=\"non-terminal-apis\">Non-Terminal APIs</h3>\n<p>The second approach is to have the program report its own state through\nan inbox-specific, out-of-band API such as\n<a href=\"https://herdr.dev/docs/socket-api/#agent-state-reporting\" rel=\"nofollow ugc noopener\">Herdr&#39;s socket API</a>\nor <a href=\"https://cmux.com/docs/notifications\" rel=\"nofollow ugc noopener\"><code>cmux notify</code></a>. This is better\nthan heuristics in some ways, because the program that actually knows its state is the\none reporting it. But every program has to integrate with every inbox\nseparately, and a local socket doesn&#39;t work over SSH or from within a\ncontainer without extra bridging. The pty already works across all of this.</p>\n<h2 id=\"the-program-status-protocol\">The Program Status Protocol</h2>\n<p><a href=\"https://www.superlogical.com/rex/docs/build/program-status\" rel=\"nofollow ugc noopener\">OSC 7501</a> is a terminal native answer to this problem. The program\nreports its own state directly via the pty that it always has, using a\nformat that is safe to send everywhere (well-behaved terminals ignore\nunknown OSCs).</p>\n<p>The body of the sequence is a <a href=\"https://www.superlogical.com/rex/docs/build/program-status#syntax\" rel=\"nofollow ugc noopener\">list of <code>key=value</code> pairs</a> separated by <code>:</code>.\nThe only required key is <a href=\"https://www.superlogical.com/rex/docs/build/program-status#states\" rel=\"nofollow ugc noopener\"><code>state</code></a>, which is one of:</p>\n<div class=\"table-wrap\"><table><thead><tr><th><code>state</code></th><th>Meaning</th></tr></thead><tbody><tr><td><code>idle</code></td><td>At rest, waiting for the user&#39;s next instruction.</td></tr><tr><td><code>working</code></td><td>Running. May include a <code>progress</code> percentage.</td></tr><tr><td><code>done</code></td><td>Finished. The result is ready and the user hasn&#39;t seen it yet.</td></tr><tr><td><code>blocked</code></td><td>Can&#39;t continue until the user does something. <code>kind</code> says what (<code>permission</code> ,<code>question</code> , or<code>auth</code> ) and<code>msg</code> says why.</td></tr><tr><td><code>error</code></td><td>Failed and stopped.</td></tr></tbody></table></div>\n<p><a href=\"https://www.superlogical.com/rex/docs/build/program-status#keys\" rel=\"nofollow ugc noopener\">Optional keys</a> include <code>app</code>, a stable\nmachine-readable program name like <code>cargo</code> or <code>claude-code</code>, and <code>msg</code>,\na single human-readable line encoded as base64.</p>\n<p>Programs that run several things at once can report multiple records\nusing <a href=\"https://www.superlogical.com/rex/docs/build/program-status#records-and-ids\" rel=\"nofollow ugc noopener\">hierarchical ids</a>. A <a href=\"https://www.superlogical.com/rex/docs/build/program-status#several-records\" rel=\"nofollow ugc noopener\">deploy tool</a>\ncan be <code>working</code> at the root while\n<code>us-east</code> pushes an image at 40% and <code>eu-west</code> is <code>blocked</code> waiting for\napproval to deploy to production. Both are true at the same time, and\nthe terminal decides what to show. A <code>clear</code> state removes records.</p>\n<p>Here&#39;s a <a href=\"https://www.superlogical.com/rex/docs/build/program-status#a-shell-function\" rel=\"nofollow ugc noopener\">complete integration</a> for a shell script to wrap <code>rsync</code>\nto participate in this protocol:</p>\n<pre><code>status() {\n  printf &#39;\\e]7501;state=%s:msg=%s\\e\\\\&#39; &quot;$1&quot; &quot;$(printf &#39;%s&#39; &quot;$2&quot; | base64 | tr -d &#39;\\n&#39;)&quot;\n}\nstatus working &quot;Syncing photos&quot;\nrsync -a ~/Photos backup:/photos &amp;&amp; status done &quot;Photos synced&quot; || status error &quot;rsync failed&quot;</code></pre>\n<p>Trivial to script with plain old POSIX <code>sh</code>.\nNo SDK, no sockets, no environment variables, no JSON.\nNo bias towards specific GUI presentations. No bias to any specific\nworkload (like AI). A well-formed, generic foundation to build functionality\nabove that anyone and everyone can participate with.</p>\n<p>The <a href=\"https://www.superlogical.com/rex/docs/build/program-status\" rel=\"nofollow ugc noopener\">full spec</a>\ncovers the rest: <a href=\"https://www.superlogical.com/rex/docs/build/program-status#states\" rel=\"nofollow ugc noopener\">record lifetime</a>,\n<a href=\"https://www.superlogical.com/rex/docs/build/program-status#feature-detection\" rel=\"nofollow ugc noopener\">feature detection</a>,\n<a href=\"https://www.superlogical.com/rex/docs/build/program-status#terminfo\" rel=\"nofollow ugc noopener\">terminfo</a>, <a href=\"https://www.superlogical.com/rex/docs/build/program-status#limits\" rel=\"nofollow ugc noopener\">size limits</a>,\nand <a href=\"https://www.superlogical.com/rex/docs/build/program-status#security\" rel=\"nofollow ugc noopener\">security</a>. It&#39;s short. I wrote it all by hand. Please read it.</p>\n<h2 id=\"implement-it\">Implement It</h2>\n<p>I wrote <a href=\"https://www.superlogical.com/rex/docs/build/program-status\" rel=\"nofollow ugc noopener\">this specification</a> based on my experience maintaining a terminal\nemulator for many years now. It is written in a way that is easy for\napplication developers to emit, and easy for terminal emulators to consume\nand parse.</p>\n<p>I&#39;ve already implemented this protocol twice. We have one implementation\nin <a href=\"https://github.com/ghostty-org/ghostty/pull/14560\" rel=\"nofollow ugc noopener\">libghostty</a> and\nI have a parallel implementation in <a href=\"https://www.superlogical.com/rex\" rel=\"nofollow ugc noopener\">Rex</a>.\nI&#39;ve also implemented it as a proof-of-concept in Terraform, Claude Code,\nCodex, and Homebrew via either plugins or forks. In each case, the\nimplementation was no more than a dozen lines.</p>\n<p>I&#39;ve been in contact with the maintainers of many popular terminal programs and emulators and they&#39;ve helped review and shape the specification. But if you have any more feedback, I&#39;m happy to hear it.</p>\n<p><strong>If you&#39;ve implemented the specification</strong> please let me know via\nemail (mail icon in the footer) and I&#39;ll add you to the list of tools\nthat implement this. Thank you.</p>\n<p>I&#39;d like us all to stop guessing what programs are doing by reading their screens or process trees. The program already knows. Let&#39;s give it a way to tell us!</p>","headings":[{"level":1,"text":"A Terminal Protocol for Program Status (OSC 7501)","id":"a-terminal-protocol-for-program-status-osc-7501"},{"level":2,"text":"The Problem","id":"the-problem"},{"level":2,"text":"Singling Out \"Agentic Inboxes\"","id":"singling-out-agentic-inboxes"},{"level":3,"text":"Heuristics","id":"heuristics"},{"level":3,"text":"Non-Terminal APIs","id":"non-terminal-apis"},{"level":2,"text":"The Program Status Protocol","id":"the-program-status-protocol"},{"level":2,"text":"Implement It","id":"implement-it"}]}}