Chimes when a long turn finishes and when a permission prompt is waiting; /chime to toggle

A minimal Claude Code mod: a short sound when you can stop waiting.
Both are multi-note motifs, so they don't sound like macOS's single-tone alerts. The WAVs are synthesized for this mod (MIT, like the code).
/chime off # silence
/chime on # sound back
/chime # toggle
The setting persists across sessions. Default: on.
afplay, so macOS only. Linux and Windows terminals play nothing.claude plugin validate .
claude plugin test .hooks/register.ts 41 lines1import type { EngineInterface, Register } from 'claude-code'
2
3// 짧은 답변마다 울리면 피로 → 이 시간 이상 걸린 턴만 알림
4const MIN_TURN_MS = 30_000
5// 켜짐/꺼짐은 세션을 넘어 유지($.store) — 기본 켜짐
6const ENABLED = 'enabled'
7
8// 소리 = 직접 합성한 WAV(맥 시스템음과 구별되는 다음(多音) 모티프)
9// done = 마림바 2음 상승, ask = 짧은 사인 3연타
10async function chime($: EngineInterface, asset: string): Promise<void> {
11 if ((await $.store.get(ENABLED)) === false) return
12 // 재생 완료를 기다리지 않음 — 턴 종료·알림을 늦추지 않도록
13 $.audio.play({ asset }).catch(() => {})
14}
15
16export const register: Register = (on) => {
17 on('session.start', async ($, e, next) => {
18 await $.command.register({ name: 'chime', description: 'Turn done-chime sounds on or off (on | off | no arg = toggle)' })
19 return next(e)
20 })
21
22 on('command.run', { command: 'chime' }, async ($, e) => {
23 const arg = e.args.trim().toLowerCase()
24 const isOn = arg === 'on' ? true : arg === 'off' ? false : (await $.store.get(ENABLED)) === false
25 await $.store.set(ENABLED, isOn)
26 return { text: `done-chime ${isOn ? 'on' : 'off'}` }
27 })
28
29 on('turn.complete', async ($, e, next) => {
30 const result = await next(e)
31 // 서브에이전트 턴·Esc 중단(사람이 이미 화면 앞)은 제외
32 if (!e.agentId && !e.isAborted && e.durationMs >= MIN_TURN_MS) await chime($, 'sounds/done.wav')
33 return result
34 })
35
36 on('classic.Notification', async ($, e, next) => {
37 if (e.notification_type === 'permission_prompt') await chime($, 'sounds/ask.wav')
38 return next(e)
39 }).catch(($, e, next) => next(e)) // 실패해도 알림 흐름은 막지 않음
40}
41