---
title: "Telling Your Terminal What Your PHP CLI Is Doing: OSC 7501 Comes to PHP"
url: https://www.exakat.io/telling-your-terminal-what-your-php-cli-is-doing-osc-7501-comes-to-php/
date: 2026-10-31
modified: 2026-10-31
lang: en
author: "dams"
description: "Telling Your Terminal What Your PHP CLI Is Doing: OSC 7501 Comes to PHP The problem: you keep guessing the CLI's status If you have more than one terminal tab..."
categories:
  - "Technology"
tags:
  - "AI"
  - "cli"
  - "php"
image: https://www.exakat.io/wp-content/uploads/2026/10/busstop.640.jpg
word_count: 1233
---

# Telling Your Terminal What Your PHP CLI Is Doing: OSC 7501 Comes to PHP

# Telling Your Terminal What Your PHP CLI Is Doing: OSC 7501 Comes to PHP

## The problem: you keep guessing the CLI's status

If you have more than one terminal tab open, you know the routine. You start a long-running command in one tab, switch to another, and come back periodically to check if it finished: or worse, if it stopped to ask you something. Is that `composer update` still resolving dependencies, or has it been sitting on a prompt for the last ten minutes?

AI coding agents have made this problem very very common. Anyone running several Claude Code, Codex, or Gemini sessions in parallel quickly learned that they had no reliable way to know which session was working, which was done, and which was quietly waiting for permission. That's why the major harnesses all shipped their own status reporting: Claude Code, Codex CLI, Crush, Amp, and others can now tell you when they're busy or blocked. But each one invents its own mechanism, may it be hooks, socket APIs, screen scraping, which is exactly the kind of fragmentation terminals hate.

In October 2026, Mitchell Hashimoto, of [Ghostty](https://ghostty.org/) fame, published a spec to fix this once and for all: [**OSC 7501, the Program Status Protocol**](https://mitchellh.com/writing/program-status-osc7501). And this isn't just for AI agents: it's for any program that runs longer than a few seconds. So, CLI brings us to PHP, naturally.

## Composer supports it

[**Composer 2.11 **](https://x.com/naderman/status/2115751978512912769)is the first major PHP tool to adopt OSC 7501. If you run `composer install` or `composer update` in a terminal that understands the protocol, Composer now reports its state: working while it resolves and downloads packages, blocked when it needs an answer, like a plugin prompt or a credential request, done when everything installed cleanly, and error when it failed or was cancelled.

Why is this useful? Composer commands are exactly the kind of somtimes long-running operations the spec has in mind. A `composer update` on a large project with a slow mirror can easily run for minutes. Meanwhile:

- Your terminal can show a small badge on the tab, working, or waiting for you, so you don't have to keep switching back.
- Multiplexers and "inbox" tools can list every running command across panes and sessions, telling you which ones finished and which one is blocked on a question you forgot to answer.
- It works over SSH and through `tmux`, because the reports travel through the pty the program already writes to, no side channel, no socket, no extra dependency.

Composer's implementation is careful and conservative. Reports are controlled by the `COMPOSER_TERMINAL_STATUS` environment variable, which defaults to `auto`: OSC 7501 reports are always sent, and terminals that don't know the sequence simply ignore it, while the older OSC 9;4 progress reports are only added when the environment identifies a known terminal such as Windows Terminal, ConEmu, Ghostty, or iTerm2. Reports are suppressed for quiet output, non-TTY streams, and redirected stderr. So piping Composer's output to a file won't fill it with escape sequences.

If you build PHP CLI tools, Composer's PR is worth reading: it registers an `OscHelper` in the Symfony Console helper set, which means the mechanism slots neatly into the same component most PHP CLI tools already use.

## Symfony is next: TUI and Console

Composer's implementation being built on Symfony Console is no coincidence, and it points to where this goes next. Symfony has an open pull request adding OSC 7501 support to its new TUI component, with an API along these lines:

```
use Symfony\Component\Tui\Terminal\ProgramStatus\ProgramBlockKind;
use Symfony\Component\Tui\Terminal\ProgramStatus\ProgramState;
use Symfony\Component\Tui\Terminal\ProgramStatus\ProgramStatus;

$terminal = $tui->getTerminal();
$terminal->setProgramStatus(new ProgramStatus(ProgramState::Working, 'Deploying v2.4.1', app: 'deploy'));
```

The discussions around the PR also cover the natural follow-up: bringing OSC 7501 to Symfony Console itself, which already emits the older OSC 9;4 progress from `ProgressBar` and pauses it while `QuestionHelper` waits for input. Once that lands in the component, every tool built on Symfony Console, which is to say, most of the PHP CLI ecosystem, gets status reporting for a very small effort. That was exactly the reasoning Pantheon's maintainers gave when they parked their own experimental OSC 7501 implementation in Terminus: don't maintain it per-tool, wait for the shared component.

## Who should be next in PHP?

The spec is deliberately easy to implement. It's a single escape sequence, `ESC ] 7501 ; state=working:msg=<base64> ESC \`, with a few key/value pairs. Any PHP CLI that runs longer than a coffee sip is a candidate. A few that come to mind:

- **Laravel Prompts**. It already makes PHP CLIs interactive: spinners, progress bars, forms, confirmations. Every one of those is a moment where a program is either working or blocked on the user. An opt-in status report emitted alongside its existing output would make any Laravel-based CLI instantly visible to OSC 7501-aware terminals, and it's the natural place for Laravel Artisan commands to inherit the behavior.
- **PHPUnit**. A test run is the textbook use case: it reports `working` while the suite runs, `done` when it's green, and `error`, with the failure count as the message, when it isn't. If you run tests in one tab while coding in another, your terminal could simply mark the tab red or green. Nobody has even opened an issue on it yet; PHPUnit also sits on top of the Console ecosystem, so it may prefer to wait for the upstream support.
- **PsySH and interactive consoles**. A REPL is idle most of the time, working while it evaluates, and blocked whenever it waits for multi-line input. Reporting `idle`/`blocked` states would let a multiplexer tell you which of your open PsySH sessions actually needs attention.
- **Other long-running PHP tools**. Deployment scripts, queue workers run from a terminal, migration tools, static analyzers grinding through a large codebase — the pattern is the same everywhere.

Beyond PHP, the early adopters set a good example of how fast this can move: [Bubble Tea](https://github.com/charmbracelet/bubbletea), the Go TUI framework behind many modern CLIs, shipped support within days, dedicated emitter libraries like osc-status in TypeScript and osc7501 in Python, already exist, and tools like Hugo have it too. The ecosystem pages tracking adoption, called ["Are we OSC 7501 yet?"](https://areweosc7501yet.com/), read like a land-grab at the moment, with a new tool shipping support every day or two. It includes a [test tool](https://areweosc7501yet.com/test).

There is also a [aweswome OSC 7501](https://github.com/hyeebeen/awesome-osc7501) page, and it is in Chinese.

## If you can't wait

You don't need to wait for your framework. The whole protocol is one `printf`:

Send it unconditionally: terminals that don't implement OSC 7501 ignore it, exactly as they ignore every other escape sequence they don't know. Only suppress it when stderr isn't a TTY.

## OSC 7501 for PHP

First the AI harnesses, then the package managers, and soon the frameworks: programs are finally learning to tell their terminal what they're doing instead of making it guess from spinner characters and window titles. Composer is the first mover in PHP, Symfony looks likely to be the foundation everyone else builds on, and Laravel Prompts, PHPUnit, PsySH, and the rest of the CLI ecosystem are all natural candidates. If you maintain a PHP command-line tool, now is a good time to think about what your tool would say — working, blocked, or done — because your terminal is finally listening.