Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- This is a great example of a user sharing a practical, real-world productivity hack. Let's break it down and critique it based on the provided documentation.
- ### Overall Assessment: Is it accurate?
- **Yes, the information in the Reddit post is highly accurate.** The user has correctly understood and implemented the `hooks` feature as described in the provided Claude Code documentation. They are using the correct hook names, file structure, and a valid configuration file location (`settings.local.json`).
- ---
- ### Detailed Critique
- #### The Good (What the Redditor Got Right)
- * **Correct Feature Usage:** The post correctly identifies the `hooks` feature as the right way to achieve deterministic, event-driven notifications.
- * **Accurate Hook Events:** The user correctly identifies and uses the `Notification`, `Stop`, and `SubagentStop` hooks for their intended purposes, demonstrating a good understanding of the agent's lifecycle.
- * `Notification`: Fires when Claude is waiting for user input (e.g., a permission prompt).
- * `Stop`: Fires when the main agent loop is complete.
- * `SubagentStop`: Fires when a specialized subagent finishes its task.
- * **Valid Configuration:** The JSON snippet is structured correctly according to the `hooks` reference documentation. It uses the right keys (`hooks`, `matcher`, `type`, `command`).
- * **Good Scoping:** The user astutely places the configuration in `settings.local.json`. This is the perfect place for personal, machine-specific preferences (like using macOS's `say` command) that should not be committed to a shared project repository.
- * **Practical and Useful:** The post solves a genuine productivity problem. Instead of "babysitting" the terminal, the developer can be notified audibly, which is a great use case for this feature.
- * **Foresight:** The user's idea to specialize the notification by worktree name is an excellent advanced use case that shows they are thinking about how to scale this pattern.
- #### Areas for Improvement & Nuances
- * **Platform Specificity:** The biggest limitation of the post is that the `say` command is **macOS-specific**. This solution will not work out-of-the-box for users on Linux or Windows (via WSL). A more complete guide would mention this and provide alternatives.
- * **Lack of Security Mention:** The provided `hooks` documentation includes a very prominent **"USE AT YOUR OWN RISK"** disclaimer because hooks execute arbitrary shell commands. While the `say` command is harmless, the post doesn't mention the potential security implications of the `hooks` feature in general. It's a critical piece of context for anyone looking to implement this.
- * **Simplicity vs. Robustness:** The implementation is very simple. It doesn't handle cases where the `say` command might fail or isn't installed. For a simple notification, this is fine, but more complex hooks would require more robust scripting.
- ---
- ### A More Robust and Cross-Platform Implementation
- We can improve upon the redditor's excellent idea by making it work across different operating systems and making the message more dynamic, as they suggested.
- Here is an improved `settings.local.json` that is cross-platform and provides more context in the notification.
- This version uses a shell one-liner with a `case` statement to check the operating system (`uname`) and uses `jq` to parse the project's directory name from the hook's JSON input.
- ```json
- {
- "hooks": {
- "Notification": [
- {
- "matcher": "",
- "hooks": [
- {
- "type": "command",
- "command": "PROJECT_NAME=$(jq -r '.cwd | split(\"/\")[-1]' | sed 's/\\(.*\\)/\\L\\1/'); case \"$(uname -s)\" in Darwin) say \"Claude needs attention in ${PROJECT_NAME}\" ;; Linux) spd-say \"Claude needs attention in ${PROJECT_NAME}\" ;; *) ;; esac"
- }
- ]
- }
- ],
- "Stop": [
- {
- "matcher": "",
- "hooks": [
- {
- "type": "command",
- "command": "PROJECT_NAME=$(jq -r '.cwd | split(\"/\")[-1]' | sed 's/\\(.*\\)/\\L\\1/'); case \"$(uname -s)\" in Darwin) say \"Claude is done in ${PROJECT_NAME}\" ;; Linux) spd-say \"Claude is done in ${PROJECT_NAME}\" ;; *) ;; esac"
- }
- ]
- }
- ],
- "SubagentStop": [
- {
- "matcher": "",
- "hooks": [
- {
- "type": "command",
- "command": "case \"$(uname -s)\" in Darwin) say \"Subagent finished\" ;; Linux) spd-say \"Subagent finished\" ;; *) ;; esac"
- }
- ]
- }
- ]
- }
- }
- ```
- **Why this version is better:**
- 1. **Cross-Platform:** It works on both macOS (`say`) and Linux (`spd-say`, a common text-to-speech dispatcher). Users can swap `spd-say` for `espeak` or another command if they prefer. It fails silently on unsupported systems (like Windows).
- 2. **Dynamic Messages:** It reads the JSON data piped to the hook via `stdin`, uses `jq` to extract the current working directory (`.cwd`), and includes the project's folder name in the audio notification. This directly implements the user's idea about knowing *which* agent needs attention.
- 3. **Self-Contained:** It accomplishes this without needing separate script files, keeping the configuration clean.
- **To use this, a user would need to have `jq` and a text-to-speech command-line tool (`say` on Mac, `speech-dispatcher` which provides `spd-say` on Linux) installed.**
- ### Final Verdict
- The Reddit post is an excellent, accurate, and practical example of how to use Claude Code's hooks. It serves as a great starting point. Its main weakness is its platform-specificity, but for its intended audience (likely macOS users), it's a perfect tip. My suggested improvements build on the user's solid foundation to make the solution more powerful and universally applicable.
Advertisement
Add Comment
Please, Sign In to add comment