Skip to content

Instantly share code, notes, and snippets.

@lamngockhuong
Created January 6, 2026 06:11
Show Gist options
  • Select an option

  • Save lamngockhuong/900630e7dd403e07644664f09283c37e to your computer and use it in GitHub Desktop.

Select an option

Save lamngockhuong/900630e7dd403e07644664f09283c37e to your computer and use it in GitHub Desktop.
Play sound for claude hook
#!/usr/bin/env node
const { execSync, spawn } = require("child_process");
const os = require("os");
const fs = require("fs");
const soundType = process.argv[2] || "default";
// Check if command exists
function commandExists(cmd) {
try {
execSync(`which ${cmd}`, { stdio: "ignore" });
return true;
} catch {
return false;
}
}
// Get Linux sound player
function getLinuxPlayer() {
const players = ["paplay", "aplay", "play", "mpv", "ffplay"];
for (const player of players) {
if (commandExists(player)) return player;
}
return null;
}
// Get platform-specific sound config
function getSoundConfig(type = "default") {
const platform = os.platform();
switch (platform) {
case "darwin":
const macSounds = {
default: "/System/Library/Sounds/Funk.aiff",
notification: "/System/Library/Sounds/Blow.aiff",
done: "/System/Library/Sounds/Frog.aiff",
};
return {
command: "afplay",
args: [macSounds[type] || macSounds.default],
};
case "linux":
const linuxSounds = {
default: "/usr/share/sounds/freedesktop/stereo/complete.oga",
notification: "/usr/share/sounds/freedesktop/stereo/message.oga",
done: "/usr/share/sounds/freedesktop/stereo/bell.oga",
};
const soundFile = linuxSounds[type] || linuxSounds.default;
const player = getLinuxPlayer();
if (!player || !fs.existsSync(soundFile)) {
return null;
}
// Player-specific args
const playerArgs = {
paplay: [soundFile],
aplay: [soundFile],
play: [soundFile],
mpv: ["--no-video", "--really-quiet", soundFile],
ffplay: ["-nodisp", "-autoexit", "-loglevel", "quiet", soundFile],
};
return {
command: player,
args: playerArgs[player] || [soundFile],
};
case "win32":
const winSounds = {
default: "C:\\Windows\\Media\\tada.wav",
notification: "C:\\Windows\\Media\\Windows Notify.wav",
done: "C:\\Windows\\Media\\Windows Ding.wav",
};
const winFile = winSounds[type] || winSounds.default;
return {
command: "powershell",
args: ["-c", `(New-Object Media.SoundPlayer "${winFile}").PlaySync()`],
};
default:
return null;
}
}
// Play sound and exit
function playSound() {
const config = getSoundConfig(soundType);
if (!config) {
process.exit(0);
}
const child = spawn(config.command, config.args, {
detached: true,
stdio: "ignore",
});
child.unref();
process.exit(0);
}
playSound();
@lamngockhuong
Copy link
Author

Hook config:

    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "node $HOME/.claude/hooks/custom/play-sound.cjs notification"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "node $HOME/.claude/hooks/custom/play-sound.cjs"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "node $HOME/.claude/hooks/custom/play-sound.cjs done"
          }
        ]
      }
    ],

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