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.
- Repository: github.com/YunHerry/agent-ding
- Inspired by: the iChunUtil Ding mod, which adds the same sound to Minecraft itself.
| 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.
Long-running agent sessions create a familiar rhythm: kick off work, wander away, come back a few minutes later. Two things break that rhythm:
- The agent finishes early and you didn't notice — minutes wasted.
- 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.
┌─────────────────────────────────┬──────────────────────────────────┐
│ 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.
- Plays on two logical events out of the box — "needs you" (Claude Code's
Notification/ Codex'sPermissionRequest) and "finished" (Stop). - Per-event toggles, single source of truth across agents.
- Global mute / unmute for meetings or focused listening.
- Configurable volume from
0.0to1.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
~/.claudeor~/.codexlock-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.
- 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 ofpaplay(PulseAudio, default on most distros),ffplay, oraplay— install whichever is missing.
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.
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-dingThen start Codex and install in the TUI:
codexInside the TUI:
/plugins— find Agent Ding under theagent-dingmarketplace and select Install./hooks— agent-ding will show up underPermissionRequestandStopwith status Review. Open each, confirm trust. Hooks won't fire until you do.- 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.
/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.
| 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.
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).
{
"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 entirelyAGENT_DING_STATE_DIR— override the state/log directory entirely
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 | paplay → ffplay → aplay (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.
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.
-
No sound at all — Claude Code: run
/ding-test. Codex: edit the config and checkevents.*aren'tfalse, then runnode "$CLAUDE_PLUGIN_ROOT/scripts/play.mjs" config testmanually. -
Sound is too loud or too quiet —
/ding-volume 0.2(or editvolumein 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 builds —
node "$CLAUDE_PLUGIN_ROOT/scripts/play.mjs" --dry-run Notification(orPermissionRequest/Stop) prints the platform-specific player command without spawning audio. -
Enable structured debug logging — set the env var
CLAUDE_CODE_DING_DEBUG=1and 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=1to~/.bashrcor~/.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.
- macOS / Linux:
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.
- For Codex users — config without slash commands.
- Slash commands — Claude Code day-to-day surface.
- Config — every tunable, in one table.
- Platforms — what plays the sound on each OS.
- Troubleshooting — when the ding goes quiet.