# opencode status popup
**A second screen for your agent: a floating pill or a tray icon that shows what OpenCode is doing right now.**
[](https://www.npmjs.com/package/opencode-status-popup)
[](LICENSE)
[](#requirements)
[](https://opencode.ai/v2/docs/)

*the pill typing itself out while the agent works · the tray icon, the letter o building pixel by pixel*
---
OpenCode can work for minutes in a terminal you are not looking at. This plugin puts a small status light outside that terminal, so you can tell at a glance whether the agent is working, stuck, retrying, or waiting for you.
- **Working?** The pill types `opencode` letter by letter, in blue; the tray icon draws the o pixel by pixel.
- **Something failed?** Amber while a provider request is retried, red with an `!` when an execution failed.
- **Does it need me?** Violet with a `?` when OpenCode is blocked on a permission decision or on a question — the one state you should never miss.
- **Several projects, one indicator:** every OpenCode instance reports in, and the popup shows the union.
It stays out of the way: no window frame, no taskbar button, it never steals focus, it reopens where you left it, and you can drag it anywhere. If you would rather have nothing on screen, use the tray icon.
## Quick start
```sh
opencode plugin add opencode-status-popup
```
The popup appears as soon as OpenCode loads the plugin — idle until a session starts working. To use the tray icon instead, or to tweak anything, add an options block to `opencode.json(c)`:
```jsonc
{
"$schema": "https://opencode.ai/config.json",
"plugins": [
{
"package": "opencode-status-popup",
"options": { "mode": "tray" }
}
]
}
```
### Requirements
- **OpenCode V2**
- **Windows**: the popup is a small PowerShell process (WPF for the pill, WinForms for the tray icon) that uses the `pwsh.exe` or `powershell.exe` already on the machine.
## The five states
| State | Pill | Tray | Meaning |
|---|---|---|---|
| `idle` | `opencode`, white, slow breathing | the o, slow blink | nothing is running |
| `busy` | `opencode` typing itself, blue | the o drawing itself pixel by pixel, blue | the agent is working |
| `retry` | `opencode` typing itself, amber | the o drawing itself pixel by pixel, amber | a provider request failed and another attempt is scheduled |
| `error` | `opencode!`, red, breathing | the o, red, blink | an execution failed (kept for `errorHoldSeconds`, or until the session works again) |
| `permission` | `opencode?`, violet, faster breathing | the o, violet, fast blink | OpenCode is waiting for a permission decision or an answer from you |
Priority is `permission` > `error` > `retry` > `busy` > `idle`, so a session waiting for you is never hidden behind work happening in another session.
In tray mode, `Show details` (right click) opens a balloon with the live detail — `needs you: bash git push origin main`, `needs you: Put the popup in the tray?`, `error: 429 provider.rate-limit` — and lists the projects involved (shortened to fit the balloon).

Tray icons for the same states, at 8x and at real size:

The letter is drawn on a 6x7 pixel grid, one cell of stroke thick, clockwise from the top left, about 2 pixels every 250 ms; a finished letter holds for half a second and starts over. Every image in this README is rendered from the real popup, off screen: `npm run docs:images` for the stills and `npm run docs:gif` for the animations.
## Window or tray?
Two renderers, chosen with the `mode` option:
| | `window` (default) | `tray` |
|---|---|---|
| What you see | frameless translucent pill, top of the z-order | system tray icon with the letter o of the wordmark |
| Animation | the word types itself out | the o building itself pixel by pixel while it works, blinking while it waits |
| Cost | ~45–60 MB (PowerShell + WPF) | ~30–40 MB (PowerShell + WinForms) |
| Intrusiveness | floats above other windows, but no window frame, no taskbar button, does not steal focus | nothing covers the screen |
| Legibility of the word | fully readable | the word does not fit in a 16px slot, hence the letter o |
Both are the same single PowerShell process: started on demand, shared by every OpenCode instance, and gone by itself `idleSeconds` after the last instance goes away (25 seconds by default).
### Switching anytime
None of these needs a config edit or a restart, and the pill comes back where it was.
- **Click it.** Right click the pill for `Show in tray`; right click the tray icon for `Show as window`. The change lands in about a second.
- **Ask the agent.** A prompt like *"put the popup in the tray"* works through the `popup_mode` tool:
```
popup_mode({ mode: "window" | "tray" | "toggle" | "reset" })
```
- **Commands.** `/popup-window`, `/popup-tray`, `/popup-toggle`, `/popup-reset` and `/popup-static` work from the command palette (`ctrl+p`) and from the `/` autocomplete. The palette entries run in the client and answer immediately; the slash commands run on the server, which is also what makes them work through the API:
```sh
opencode api post /api/session/