Last active
May 25, 2026 09:16
-
-
Save stormychel/502e2a6da38bf5798750e5565a5324f7 to your computer and use it in GitHub Desktop.
[macOS] Claude Code Stop hook — announces 'Claude is done' via the macOS Zarvox voice (say -v Zarvox). Windows sibling: https://gist.github.com/stormychel/a2b6a437873b62b4e9750186babcc658
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| [macOS] Install a Claude Code "Stop" hook that announces completion out loud | |
| with the macOS Zarvox voice — i.e. it runs `say -v Zarvox "Claude is done"` | |
| every time Claude finishes a response. | |
| Windows sibling (SAPI / David voice): | |
| https://gist.github.com/stormychel/a2b6a437873b62b4e9750186babcc658 | |
| System-wide: writes to ~/.claude/settings.json (merges, preserves existing keys). | |
| Idempotent: re-running won't add a duplicate. | |
| Usage: | |
| python3 install-claude-zarvox-hook.py | |
| Disable later: remove the entry from the "hooks" -> "Stop" array in settings.json. | |
| Change the phrase/voice: edit CMD below (run `say -v '?'` to list voices). | |
| """ | |
| import json | |
| import pathlib | |
| CMD = 'say -v Zarvox "Claude is done"' | |
| def main() -> None: | |
| settings = pathlib.Path.home() / ".claude" / "settings.json" | |
| cfg = json.loads(settings.read_text()) if settings.exists() else {} | |
| stop = cfg.setdefault("hooks", {}).setdefault("Stop", []) | |
| already = any( | |
| hook.get("command") == CMD | |
| for entry in stop | |
| for hook in entry.get("hooks", []) | |
| ) | |
| if not already: | |
| stop.append({"hooks": [{"type": "command", "command": CMD}]}) | |
| settings.parent.mkdir(parents=True, exist_ok=True) | |
| settings.write_text(json.dumps(cfg, indent=2)) | |
| print(f"✅ Zarvox Stop hook {'already present' if already else 'installed'} at {settings}") | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment