Skip to content

[FEATURE]: bell ansi for user acknowledgment #36472

Closed as not planned
Closed as not planned

Description

@klonuo

Feature hasn't been suggested before.

  • I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

I created simple plugins for tmux/psmux acknowledgment in a sense of herdr, when model needs user input or finishes:

import type { TuiPlugin } from "@opencode-ai/plugin/tui"

function ringBell() {
  Bun.write(Bun.stdout, "\x07")
}

export const tui: TuiPlugin = async (api) => {
  api.event.on("question.asked", () => {
    ringBell()
  })
}

and

import type { Plugin } from "@opencode-ai/plugin"

export const TerminalBell: Plugin = async ({ project, client, $, directory, worktree }) => {
  let toolCallCount = 0

  return {
    "tool.execute.before": async () => {
      toolCallCount++
    },
    "tool.execute.after": async () => {
      toolCallCount--
      if (toolCallCount === 0) {
        await Bun.write(Bun.stdout, "\x07")
      }
    }
  }
}

It works nicely however I think this could be implemented in base for the best.

Activity

  1. github-actions commented on Jul 12, 2026

    @github-actions
    Contributor

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

    Please review these issues before continuing, and consider adding your plugin examples as a comment there if relevant.

  2. klonuo commented on Jul 12, 2026

    @klonuo
    Author

    wow, there is similar issue for any idea - nice
    kudos to guys reviewing

  3. prestonbrown commented on Aug 10, 2026

    @prestonbrown

    +1'ing with a concrete pain point: tmux's monitor-bell window flag (! in the status line) is the main reason BEL matters. The built-in attention.sound plays an audio file through system audio — it never writes \x07 to the PTY, so tmux/screen never light up. The result: in a multiplexed session the attention signal is invisible unless you're actively listening, even with attention.enabled: true.

    For anyone hitting this today, here's a working TuiPlugin on 1.17.x. The snippet in the OP is slightly stale — TuiPlugin now returns Promise<void> (not Hooks), and disposal goes through api.lifecycle.onDispose:

    // ~/.config/opencode/plugins/terminal-bell.ts
    import type { TuiPlugin } from "@opencode-ai/plugin/tui";
    
    const RING_EVENTS = [
      "session.idle",
      "question.asked",
      "question.v2.asked",
      "permission.asked",
      "permission.v2.asked",
      "session.error",
    ] as const;
    
    let last = 0;
    const ring = () => {
      const now = Date.now();
      if (now - last < 1000) return; // coalesce the v1/v2 event pairs
      last = now;
      try { process.stdout.write("\x07"); } catch { /* never throw from a hook */ }
    };
    
    export const tui: TuiPlugin = async (api) => {
      const off = RING_EVENTS.map((t) => api.event.on(t, ring));
      api.lifecycle.onDispose(() => off.forEach((u) => u()));
    };

    Still think this belongs built-in. An attention.terminal_bell: true option that writes \x07 alongside the sound (mirroring TuiAttentionSoundName — done, question, permission, error, subagent_done) would cover every multiplexer user without forcing them to ship a plugin, and the TuiAttention API already centralizes the "when to ring" logic.

  4. github-actions commented on Oct 11, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions