Expose terminal focus/blur events on the event bus #8823

Closed
opened 2026-02-16 18:10:56 -05:00 by yindo · 2 comments
Owner

Originally created by @mrm007 on GitHub (Feb 8, 2026).

Originally assigned to: @thdxr on GitHub.

Problem

Notification plugins (@mohak34/opencode-notifier, oh-my-opencode's session-notification, etc.) fire system notifications on session.idle regardless of whether the user is actively looking at the terminal. This is noisy — if I'm right there watching the agent work, I don't need a system notification telling me it finished.

I don't see a way for plugins to distinguish "user is here" from "user tabbed away."

Current state

opentui already captures terminal focus events via xterm focus reporting:

  1. Capability detection — queries \x1b[?1004$p to check terminal support (ansi.zig)
  2. Enables tracking — sends \x1b[?1004h when supported (terminal.zig)
  3. Parses events\x1b[I (focus in) / \x1b[O (focus out) (renderer.ts)
  4. Emits JS eventsrenderer.emit("focus") / renderer.emit("blur")

Works in terminals that implement xterm focus reporting (Ghostty, iTerm2, Kitty, WezTerm, Alacritty, etc.; tmux requires set -g focus-events on). Also handles tab switching within a terminal — switching away from the opencode tab triggers blur.

opencode doesn't subscribe to these renderer events, so the focus state never reaches the plugin event bus. Where a terminal doesn't support focus reporting, the signal would simply be absent — no breaking change.

Proposal

Wire opentui's focus/blur renderer events to the event bus as a new event (name and shape up to maintainers). For example:

renderer.on("focus", () => Bus.publish(Event.TerminalFocus, { focused: true }))
renderer.on("blur",  () => Bus.publish(Event.TerminalFocus, { focused: false }))

Optionally expose a readable focus state via the SDK for polling, in addition to the event.

Plugins would decide their own suppression policy — opencode just exposes the signal. This is additive with no breaking changes.

Originally created by @mrm007 on GitHub (Feb 8, 2026). Originally assigned to: @thdxr on GitHub. ## Problem Notification plugins (`@mohak34/opencode-notifier`, oh-my-opencode's `session-notification`, etc.) fire system notifications on `session.idle` regardless of whether the user is actively looking at the terminal. This is noisy — if I'm right there watching the agent work, I don't need a system notification telling me it finished. I don't see a way for plugins to distinguish "user is here" from "user tabbed away." ## Current state opentui already captures terminal focus events via xterm focus reporting: 1. **Capability detection** — queries `\x1b[?1004$p` to check terminal support ([`ansi.zig`](https://github.com/anomalyco/opentui/blob/main/packages/core/src/zig/ansi.zig)) 2. **Enables tracking** — sends `\x1b[?1004h` when supported ([`terminal.zig`](https://github.com/anomalyco/opentui/blob/main/packages/core/src/zig/terminal.zig#L264)) 3. **Parses events** — `\x1b[I` (focus in) / `\x1b[O` (focus out) ([`renderer.ts`](https://github.com/anomalyco/opentui/blob/main/packages/core/src/renderer.ts#L1047)) 4. **Emits JS events** — `renderer.emit("focus")` / `renderer.emit("blur")` Works in terminals that implement xterm focus reporting (Ghostty, iTerm2, Kitty, WezTerm, Alacritty, etc.; tmux requires `set -g focus-events on`). Also handles tab switching within a terminal — switching away from the opencode tab triggers `blur`. opencode doesn't subscribe to these renderer events, so the focus state never reaches the plugin event bus. Where a terminal doesn't support focus reporting, the signal would simply be absent — no breaking change. ## Proposal Wire opentui's `focus`/`blur` renderer events to the event bus as a new event (name and shape up to maintainers). For example: ```typescript renderer.on("focus", () => Bus.publish(Event.TerminalFocus, { focused: true })) renderer.on("blur", () => Bus.publish(Event.TerminalFocus, { focused: false })) ``` Optionally expose a readable focus state via the SDK for polling, in addition to the event. Plugins would decide their own suppression policy — opencode just exposes the signal. This is additive with no breaking changes.
yindo added the opentui label 2026-02-16 18:10:56 -05:00
yindo closed this issue 2026-02-16 18:10:56 -05:00
Author
Owner

@github-actions[bot] commented on GitHub (Feb 8, 2026):

This issue might be a duplicate of existing issues. Please check:

  • #8697: [FEATURE]: Add focus/attention change events to plugin API - Identical proposal to expose focus/blur events to the plugin API so plugins can distinguish when the user is looking at the terminal

Feel free to ignore if none of these address your specific case.

@github-actions[bot] commented on GitHub (Feb 8, 2026): This issue might be a duplicate of existing issues. Please check: - #8697: [FEATURE]: Add focus/attention change events to plugin API - Identical proposal to expose focus/blur events to the plugin API so plugins can distinguish when the user is looking at the terminal Feel free to ignore if none of these address your specific case.
Author
Owner

@mrm007 commented on GitHub (Feb 8, 2026):

Duplicate of #8697, which already has an open PR at #9110. Adding my support there instead.

@mrm007 commented on GitHub (Feb 8, 2026): Duplicate of #8697, which already has an open PR at #9110. Adding my support there instead.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#8823