diff --git a/CLAUDE.md b/CLAUDE.md index abf2b11..96b6189 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -33,8 +33,9 @@ Configuration is stored in `~/.iamwaiting/config.edn` with the following structu ```clojure {:webhook-url "https://discord.com/api/webhooks/..." :user-id "123456789012345678" ; Optional: Discord user ID for @mentions - :toggles {:idle-prompt true ; Enable idle prompt notifications - :permission-prompt true}} ; Enable permission prompt notifications + :toggles {:idle-prompt true ; Enable idle prompt notifications + :permission-prompt true ; Enable permission prompt notifications + :permission-prompt-ping true}} ; Enable @mentions on permission prompts ``` Alternatively, configuration can be set via environment variables: @@ -55,6 +56,9 @@ iamwaiting toggle idle-prompt off # Enable permission prompt notifications iamwaiting toggle permission-prompt on + +# Disable @mentions on permission prompts +iamwaiting toggle permission-prompt-ping off ``` **Manually editing config file:** @@ -62,15 +66,33 @@ iamwaiting toggle permission-prompt on ;; Only get notified for permission prompts {:webhook-url "https://discord.com/api/webhooks/..." :toggles {:idle-prompt false - :permission-prompt true}} + :permission-prompt true + :permission-prompt-ping true}} + +;; Get permission prompt notifications but don't @mention +{:webhook-url "https://discord.com/api/webhooks/..." + :user-id "123456789012345678" + :toggles {:idle-prompt true + :permission-prompt true + :permission-prompt-ping false}} ;; Disable all notifications {:webhook-url "https://discord.com/api/webhooks/..." :toggles {:idle-prompt false - :permission-prompt false}} + :permission-prompt false + :permission-prompt-ping false}} ``` -**Default behavior:** If toggles are not specified in the config file, both notification types are enabled. +**Default behavior:** If toggles are not specified in the config file, all notification features are enabled. + +### Permission Prompt Pings + +The `:permission-prompt-ping` toggle controls whether you get @mentioned (pinged) on permission prompts. This is useful when: +- You want to disable pings during focus time +- You want notifications but not intrusive @mentions +- You want to keep your user ID configured without getting pinged + +**Note:** This toggle only has effect if you have a user ID configured. The ping toggle defaults to `true` for backwards compatibility. ## Installation @@ -123,6 +145,12 @@ iamwaiting toggle idle-prompt on # Disable permission prompt notifications iamwaiting toggle permission-prompt off + +# Disable @mentions on permission prompts +iamwaiting toggle permission-prompt-ping off + +# Enable @mentions on permission prompts +iamwaiting toggle permission-prompt-ping on ``` ### Running via Babashka Tasks @@ -171,16 +199,16 @@ Notifications include: - ā³ Waiting indicator - šŸ“ Current working directory / project name - šŸ• Timestamp (HH:mm:ss format) -- @mention (if user ID is configured and it's a permission prompt) +- @mention (if user ID is configured, it's a permission prompt, and ping toggle is enabled) -Example message (normal prompt): +Example message (idle prompt): ``` ā³ **Claude is waiting** in `ajet-industries` šŸ“ Path: `/home/user/repos/ajet-industries` šŸ• Time: 14:23:45 ``` -Example message (permission prompt with user ID configured): +Example message (permission prompt with ping enabled): ``` <@123456789012345678> ā³ **Claude is waiting** in `ajet-industries` šŸ“ Path: `/home/user/repos/ajet-industries` @@ -188,6 +216,14 @@ Example message (permission prompt with user ID configured): šŸ“¢ Type: `permission_prompt` ``` +Example message (permission prompt with ping disabled): +``` +ā³ **Claude is waiting** in `ajet-industries` +šŸ“ Path: `/home/user/repos/ajet-industries` +šŸ• Time: 14:23:45 +šŸ“¢ Type: `permission_prompt` +``` + ### Error Handling - Missing configuration prompts user to run `./iamwaiting setup` diff --git a/README.md b/README.md index 64ded08..1824a3f 100644 --- a/README.md +++ b/README.md @@ -126,15 +126,41 @@ bb run # Send waiting notification Configuration is stored in `~/.iamwaiting/config.edn`: ```clojure -{:webhook-url "https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN"} +{:webhook-url "https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN" + :user-id "123456789012345678" ; Optional: for @mentions + :toggles {:idle-prompt true + :permission-prompt true + :permission-prompt-ping true}} ``` You can also set the webhook URL via environment variable: ```bash export IAMWAITING_WEBHOOK_URL="https://discord.com/api/webhooks/..." +export IAMWAITING_USER_ID="123456789012345678" # Optional ``` +### Advanced Configuration + +Control which notifications you receive using toggles: + +```bash +# Show current toggle status +iamwaiting toggle status + +# Toggle notification types on/off +iamwaiting toggle idle-prompt on|off +iamwaiting toggle permission-prompt on|off + +# Control @mentions on permission prompts +iamwaiting toggle permission-prompt-ping on|off +``` + +**Use cases:** +- **Focus time:** Disable pings but keep notifications (`permission-prompt-ping off`) +- **Critical only:** Only notify on permission prompts (`idle-prompt off`) +- **Silent mode:** Disable all notifications (both toggles `off`) + ## How It Works When Claude Code is waiting for user input, the `agent-waiting-for-user` hook is triggered, which: @@ -149,15 +175,33 @@ The notification appears in your Discord channel with: - ā³ Waiting indicator - šŸ“ Project name and path - šŸ• Timestamp +- @mention (if configured and enabled for permission prompts) -## Example Notification +## Example Notifications +**Idle prompt (standard notification):** ``` ā³ **Claude is waiting** in `my-project` šŸ“ Path: `/home/user/repos/my-project` šŸ• Time: 14:23:45 ``` +**Permission prompt with ping enabled:** +``` +<@123456789012345678> ā³ **Claude is waiting** in `my-project` +šŸ“ Path: `/home/user/repos/my-project` +šŸ• Time: 14:23:45 +šŸ“¢ Type: `permission_prompt` +``` + +**Permission prompt with ping disabled:** +``` +ā³ **Claude is waiting** in `my-project` +šŸ“ Path: `/home/user/repos/my-project` +šŸ• Time: 14:23:45 +šŸ“¢ Type: `permission_prompt` +``` + ## Troubleshooting **"No webhook URL configured"** diff --git a/iamwaiting b/iamwaiting index 3baa7e7..14090a2 100755 --- a/iamwaiting +++ b/iamwaiting @@ -18,7 +18,8 @@ (System/getenv "IAMWAITING_USER_ID")) toggles (or (:toggles config) {:idle-prompt true - :permission-prompt true})] + :permission-prompt true + :permission-prompt-ping true})] {:webhook-url webhook-url :user-id user-id :toggles toggles})) @@ -38,7 +39,7 @@ (catch Exception e {:success false :error (.getMessage e)}))) -(defn format-waiting-message [event-data user-id] +(defn format-waiting-message [event-data user-id toggles] "Format a message for Claude waiting event" (let [cwd (or (:cwd event-data) (System/getProperty "user.dir")) project-name (fs/file-name cwd) @@ -54,8 +55,9 @@ ;; Check if this is a permission prompt is-permission-prompt? (or (= notification-type "permission_prompt") (some? permission-mode)) - ;; Ping user if configured and it's a permission prompt - user-ping (when (and user-id is-permission-prompt?) + ;; Ping user if configured, it's a permission prompt, and ping toggle is enabled + ping-enabled? (get toggles :permission-prompt-ping true) + user-ping (when (and user-id is-permission-prompt? ping-enabled?) (str "<@" user-id "> "))] (str user-ping "ā³ **Claude is waiting** in `" project-name "`\n" @@ -99,10 +101,20 @@ (let [perm-response (str/lower-case (str/trim (read-line))) perm-enabled? (not= perm-response "n") + ;; Ask about ping preference if user ID provided + ping-enabled? (if user-id + (do + (print "@mention you on permission prompts? (y/n, default: y): ") + (flush) + (let [ping-response (str/lower-case (str/trim (read-line)))] + (not= ping-response "n"))) + true) + ;; Build config with toggles config (cond-> {:webhook-url webhook-url :toggles {:idle-prompt idle-enabled? - :permission-prompt perm-enabled?}} + :permission-prompt perm-enabled? + :permission-prompt-ping ping-enabled?}} user-id (assoc :user-id user-id))] ;; Create config directory @@ -112,7 +124,8 @@ (spit config-file (pr-str config)) (println "\nāœ“ Configuration saved to" config-file) (when user-id - (println "āœ“ User ID configured - you will be @mentioned on permission prompts")) + (println (str "āœ“ User ID configured - you will be @mentioned on permission prompts: " + (if ping-enabled? "enabled" "disabled")))) (println (str "āœ“ Idle prompts: " (if idle-enabled? "enabled" "disabled"))) (println (str "āœ“ Permission prompts: " (if perm-enabled? "enabled" "disabled"))) (println "\nTest the webhook with: ./iamwaiting test")))))) @@ -177,7 +190,7 @@ (println (str "Notification disabled for " toggle-key))) ;; Original notification logic - (let [message (format-waiting-message event-data (:user-id config)) + (let [message (format-waiting-message event-data (:user-id config) (:toggles config)) result (send-discord-webhook (:webhook-url config) message)] (if (:success result) (println "āœ“ Notification sent") @@ -191,6 +204,7 @@ feature-key (case feature "idle-prompt" :idle-prompt "permission-prompt" :permission-prompt + "permission-prompt-ping" :permission-prompt-ping nil) action-bool (case action "on" true @@ -200,7 +214,7 @@ (cond (nil? feature-key) (do - (println "āŒ Invalid feature. Use: idle-prompt | permission-prompt") + (println "āŒ Invalid feature. Use: idle-prompt | permission-prompt | permission-prompt-ping") (System/exit 1)) (nil? action-bool) @@ -219,21 +233,27 @@ (let [config (load-config) toggles (or (:toggles config) {:idle-prompt true - :permission-prompt true})] + :permission-prompt true + :permission-prompt-ping true}) + user-id (:user-id config)] (println "šŸ“Š Current Toggle Status\n") - (println (str "Idle prompts: " (if (:idle-prompt toggles) "āœ… enabled" "āŒ disabled"))) - (println (str "Permission prompts: " (if (:permission-prompt toggles) "āœ… enabled" "āŒ disabled"))))) + (println (str "Idle prompts: " (if (:idle-prompt toggles) "āœ… enabled" "āŒ disabled"))) + (println (str "Permission prompts: " (if (:permission-prompt toggles) "āœ… enabled" "āŒ disabled"))) + (println (str "Permission ping: " (if (:permission-prompt-ping toggles) "āœ… enabled" "āŒ disabled"))) + (when user-id + (println (str "\nšŸ‘¤ User ID configured: " user-id))))) (defn show-help [] (println "iamwaiting - Send Discord notifications when Claude is waiting") (println "") (println "Usage:") - (println " iamwaiting setup Set up Discord webhook configuration") - (println " iamwaiting test Test webhook configuration") - (println " iamwaiting toggle status Show current toggle status") - (println " iamwaiting toggle idle-prompt Toggle idle prompt notifications") - (println " iamwaiting toggle permission-prompt Toggle permission prompt notifications") - (println " iamwaiting [event-data-json] Send waiting notification") + (println " iamwaiting setup Set up Discord webhook configuration") + (println " iamwaiting test Test webhook configuration") + (println " iamwaiting toggle status Show current toggle status") + (println " iamwaiting toggle idle-prompt Toggle idle prompt notifications") + (println " iamwaiting toggle permission-prompt Toggle permission prompt notifications") + (println " iamwaiting toggle permission-prompt-ping Toggle @mentions on permission prompts") + (println " iamwaiting [event-data-json] Send waiting notification") (println "") (println "Configuration:") (println " Config file: ~/.iamwaiting/config.edn") @@ -258,8 +278,9 @@ "status" (show-toggle-status) "idle-prompt" (toggle-feature "idle-prompt" (nth args 2 nil)) "permission-prompt" (toggle-feature "permission-prompt" (nth args 2 nil)) + "permission-prompt-ping" (toggle-feature "permission-prompt-ping" (nth args 2 nil)) (do - (println "Usage: iamwaiting toggle [on|off]") + (println "Usage: iamwaiting toggle [on|off]") (System/exit 1)))) "help" (show-help) "--help" (show-help)