Skip to content

YunHerry/agent-ding

Repository files navigation

agent-ding

License: MIT Platforms Agents

English | 简体中文

A plugin for AI coding agent CLIs — plays a short notification sound the moment the agent needs you: a permission prompt, or a finished response. Stay in flow, look out the window, read docs in another tab; the ding pulls you back when (and only when) it matters.

Runs entirely on each agent's native plugin + hook system — no daemon, no background process, no extra dependencies beyond Node.js.

Supported agents

Agent Plugin manifest Hook events fired
Claude Code .claude-plugin/ Notification, Stop
Codex .codex-plugin/ PermissionRequest, Stop

Both agents share the same hooks/hooks.json and the same scripts/play.mjs. The plugin treats Codex's PermissionRequest as a synonym for Claude Code's Notification, so your config has a single surface regardless of which agent fired the event.

Why agent-ding?

Long-running agent sessions create a familiar rhythm: kick off work, wander away, come back a few minutes later. Two things break that rhythm:

  1. The agent finishes early and you didn't notice — minutes wasted.
  2. The agent blocks on a permission prompt for a tool call you forgot to allowlist — also minutes wasted.

A small audio cue closes that loop. You can leave the terminal entirely and trust that you'll hear about it the moment the agent needs you.

The plugin keeps the integration deliberately small:

  • Two logical events: "agent needs you" + "agent finished".
  • One Node.js script that picks the right OS player and plays one short sound.
  • Seven slash commands (Claude Code) or one JSON config file (Codex) to tune behavior.

How it works

┌─────────────────────────────────┬──────────────────────────────────┐
│ Claude Code                     │  Codex                           │
│   ├─ hooks: Notification, Stop  │  hooks: PermissionRequest, Stop  │
│   └─ slash: /ding-volume 0.3 …  │  (no slash commands; edit JSON)  │
└────────────────┬────────────────┴────────────────┬─────────────────┘
                 │                                 │
                 └────────────────┬────────────────┘
                                  ▼
                       node scripts/play.mjs
                                  │
                  ┌───────────────┴───────────────┐
                  ▼                               ▼
         read config →                  write config to
         build OS command →             ~/.config/agent-ding/
         spawn player                   (XDG-style, cross-platform)

hooks/hooks.json wires three events (Notification, PermissionRequest, Stop) to one Node entry point. Each agent fires only its known events; the others are inert. The script normalizes PermissionRequest to Notification internally, so user-facing config and slash commands stay simple.

Features

  • Plays on two logical events out of the box — "needs you" (Claude Code's Notification / Codex's PermissionRequest) and "finished" (Stop).
  • Per-event toggles, single source of truth across agents.
  • Global mute / unmute for meetings or focused listening.
  • Configurable volume from 0.0 to 1.0.
  • Replace the bundled sound with any audio file you own via config.sound.
  • Cross-platform: Windows (PowerShell + MCI), macOS (afplay), Linux (paplay / ffplay / aplay).
  • XDG-style config and state paths — no ~/.claude or ~/.codex lock-in.
  • Silent failure mode for hooks — never blocks or pollutes the agent's output.
  • Zero runtime dependencies; ships only a standard Node.js script and a 33 KB WAV file.

Requirements

  • Node.js ≥ 18 — both Claude Code and Codex are distributed via npm and require Node, so if either CLI works for you, Node is already installed.
  • An OS audio player — built-in on Windows (PowerShell + MCI) and macOS (afplay). On Linux you need one of paplay (PulseAudio, default on most distros), ffplay, or aplay — install whichever is missing.

Install

For Claude Code

From the public marketplace:

/plugin marketplace add YunHerry/agent-ding
/plugin install agent-ding@agent-ding

Or from a local clone (handy while hacking on the plugin):

/plugin marketplace add <path-to-your-clone>
/plugin install agent-ding@agent-ding

After install, run /ding-test to confirm audio works. Then trigger any permission prompt or wait for a response to finish — you should hear the ding.

For Codex

Codex's plugin hooks are still flagged "under development", so they're off by default. One-time setup:

# 1. Turn on the plugin_hooks feature
codex features enable plugin_hooks

# 2. Add the marketplace
codex plugin marketplace add YunHerry/agent-ding

Then start Codex and install in the TUI:

codex

Inside the TUI:

  1. /plugins — find Agent Ding under the agent-ding marketplace and select Install.
  2. /hooks — agent-ding will show up under PermissionRequest and Stop with status Review. Open each, confirm trust. Hooks won't fire until you do.
  3. Trigger any permission prompt or wait for a turn to finish — you'll hear the ding.

Codex prints a warning every session about under-development features. To silence it, add suppress_unstable_features_warning = true to ~/.codex/config.toml.

Quick start

/ding-test                  # Claude Code: confirm audio works
/ding-volume 0.3            # quieter
/ding-off Notification      # only ding on Stop, not on permission prompts
/ding-mute                  # silence everything (meeting mode)
/ding-unmute                # restore both events
/ding-config                # show current config

Codex doesn't ship custom slash commands via plugins. See For Codex users below for the equivalent operations via direct config-file edit.

Slash commands (Claude Code only)

Command Effect
/ding-volume <0..1> Set volume. Clamped to [0.0, 1.0].
/ding-on <Event> Enable ding for Notification, Stop, or PermissionRequest (aliases to Notification).
/ding-off <Event> Disable ding for the same event names.
/ding-mute Set both events to disabled.
/ding-unmute Set both events to enabled.
/ding-test Play once with the current config, regardless of toggles.
/ding-config Print the current config as JSON.

Event names

  • Notification (Claude Code) / PermissionRequest (Codex) — the agent is requesting your attention; both resolve to the same config flag.
  • Stop — the agent finished a response/turn.

For Codex users

Codex doesn't ship plugin-distributed slash commands, so config tuning is direct file editing. The config file location follows the XDG spec:

Platform Path
macOS / Linux ~/.config/agent-ding/config.json (or $XDG_CONFIG_HOME/agent-ding/config.json)
Windows %APPDATA%\agent-ding\config.json

Edit it with any text editor:

# macOS / Linux
$EDITOR ~/.config/agent-ding/config.json

# Windows (cmd)
notepad "%APPDATA%\agent-ding\config.json"

# Windows (PowerShell)
code "$env:APPDATA\agent-ding\config.json"

The file is created on first interaction. To change a value, just edit and save — Codex picks up the new config on the next hook fire (no restart needed).

Config

{
  "volume": 0.5,
  "events": {
    "Notification": true,
    "Stop": true
  },
  "sound": null
}
Key Type Default Notes
volume number [0..1] 0.5 Out-of-range values are clamped.
events.Notification boolean true Plays when the agent requests attention. Covers both Claude Code's Notification and Codex's PermissionRequest.
events.Stop boolean true Plays when the agent finishes a response/turn.
sound string | null null Absolute path to override the bundled sound. Falls back to bundled if the file is missing or unreadable.
debug boolean false When true, every hook fire is logged to agent-ding.log in the state directory. Equivalent to CLAUDE_CODE_DING_DEBUG=1 but without touching environment variables.

Environment-variable escape hatches (for tests and unusual setups):

  • AGENT_DING_CONFIG_DIR — override the config directory entirely
  • AGENT_DING_STATE_DIR — override the state/log directory entirely

Platforms

The play script auto-detects the OS and picks the first available player.

Platform Player Notes
Windows PowerShell + MCI (mciSendString) No extra install. Bundled with all supported Windows versions.
macOS afplay Built into macOS.
Linux paplayffplayaplay (first one found on PATH) Install any one. PulseAudio (paplay) is the most common default.

The plugin ships assets/orb.wav (33 KB). WAV is chosen for universal playback — no codec dependencies on Windows.

Failure mode

Hooks must never block the agent or pour noise into its output. So every play-mode failure path degrades silently and exits 0:

  • Missing or invalid config file → use defaults.
  • Missing sound file → exit silently.
  • Unknown platform or no player on PATH (Linux) → exit silently.
  • Spawn errors of any kind → exit silently.

Slash commands and direct CLI invocations behave the opposite way — you triggered them, you want feedback. They print clear errors to stderr and exit non-zero on bad arguments.

Troubleshooting

  • No sound at all — Claude Code: run /ding-test. Codex: edit the config and check events.* aren't false, then run node "$CLAUDE_PLUGIN_ROOT/scripts/play.mjs" config test manually.

  • Sound is too loud or too quiet/ding-volume 0.2 (or edit volume in the config file).

  • Want a different sound — drop your file somewhere on disk, then edit the config file and set "sound": "/absolute/path/to/your.wav".

  • Debug what the hook buildsnode "$CLAUDE_PLUGIN_ROOT/scripts/play.mjs" --dry-run Notification (or PermissionRequest / Stop) prints the platform-specific player command without spawning audio.

  • Enable structured debug logging — set the env var CLAUDE_CODE_DING_DEBUG=1 and re-trigger the hook. Each invocation appends one structured line to the log file. Log file location:

    • macOS / Linux: ~/.local/state/agent-ding/agent-ding.log (or $XDG_STATE_HOME/agent-ding/agent-ding.log)
    • Windows: %LOCALAPPDATA%\agent-ding\agent-ding.log

    Lines describe the decision (played, skipped, unknown event, missing file, spawn error). Delete the file when you're done.

    • macOS / Linux: add export CLAUDE_CODE_DING_DEBUG=1 to ~/.bashrc or ~/.zshrc, then restart your shell so the agent inherits it.
    • Windows (PowerShell): [Environment]::SetEnvironmentVariable("CLAUDE_CODE_DING_DEBUG", "1", "User"), then restart the agent.
    • Windows (cmd): setx CLAUDE_CODE_DING_DEBUG 1, then restart the agent.

Credits & license

The plugin code is MIT-licensed — see LICENSE.

The bundled audio (assets/orb.wav) is derived from Minecraft's entity.experience_orb.pickup sound, copyright Mojang Studios. The audio is NOT covered by the MIT license. If you do not own a copy of Minecraft, point config.sound at a sound you do own outright.

Where to go next

About

A notification sound plugin for AI coding agent CLIs — Claude Code and Codex.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors