diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index ab081b9..2e2bcc2 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "name": "warp", "description": "Native Warp notifications when Claude completes tasks or needs input", "source": "./plugins/warp", - "version": "2.2.0", + "version": "2.3.0", "category": "productivity", "tags": ["notifications", "terminal", "warp"] }, diff --git a/README.md b/README.md index e767524..9bd0c27 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Official [Warp](https://warp.dev) terminal integration for [Claude Code](https:/ Get native Warp notifications when Claude Code: - **Completes a task** — with a summary showing your prompt and Claude's response -- **Needs your input** — when Claude has been idle and is waiting for you +- **Needs your input** — when Claude is waiting for you, including background agents - **Requests permission** — when Claude wants to run a tool and needs your approval Notifications appear in Warp's notification center and as system notifications, so you can context-switch while Claude works and get alerted when attention is needed. @@ -47,10 +47,10 @@ The plugin communicates with Warp via OSC 777 escape sequences. Each hook script Payloads include a protocol version negotiated between the plugin and Warp (`min(plugin_version, warp_version)`), the session ID, working directory, and event-specific fields. -The plugin registers six hooks: +The plugin registers lifecycle hooks including: - **SessionStart** — emits the plugin version and a welcome system message - **Stop** — reads the transcript to extract your prompt and Claude's response, then sends a task-complete notification -- **Notification** (`idle_prompt`) — fires when Claude has been idle and needs your input +- **Notification** (`idle_prompt`, `agent_needs_input`) — fires when Claude is waiting for user input - **PermissionRequest** — fires when Claude wants to run a tool, includes the tool name and a preview of its input - **UserPromptSubmit** — fires when you submit a prompt, signaling the session is active again - **PostToolUse** — fires when a tool call completes, signaling the session is no longer blocked diff --git a/plugins/warp/.claude-plugin/plugin.json b/plugins/warp/.claude-plugin/plugin.json index 1e29217..219e43a 100644 --- a/plugins/warp/.claude-plugin/plugin.json +++ b/plugins/warp/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "warp", "description": "Warp terminal integration for Claude Code - native notifications, and more to come", - "version": "2.2.0", + "version": "2.3.0", "author": { "name": "Warp", "url": "https://warp.dev" diff --git a/plugins/warp/hooks/hooks.json b/plugins/warp/hooks/hooks.json index ba32f28..0274f49 100644 --- a/plugins/warp/hooks/hooks.json +++ b/plugins/warp/hooks/hooks.json @@ -24,7 +24,7 @@ ], "Notification": [ { - "matcher": "idle_prompt", + "matcher": "idle_prompt|agent_needs_input", "hooks": [ { "type": "command", diff --git a/plugins/warp/scripts/on-notification.sh b/plugins/warp/scripts/on-notification.sh index 8518ac1..6243aaf 100755 --- a/plugins/warp/scripts/on-notification.sh +++ b/plugins/warp/scripts/on-notification.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Hook script for Claude Code Notification event (idle_prompt only) -# Sends a structured Warp notification when Claude has been idle +# Hook script for Claude Code Notification event (idle_prompt and agent_needs_input) +# Sends a structured Warp notification when Claude has been idle or needs input SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/should-use-structured.sh" @@ -20,6 +20,9 @@ INPUT=$(cat) NOTIF_TYPE=$(echo "$INPUT" | jq -r '.notification_type // "unknown"' 2>/dev/null) MSG=$(echo "$INPUT" | jq -r '.message // "Input needed"' 2>/dev/null) [ -z "$MSG" ] && MSG="Input needed" +if [ ${#MSG} -gt 120 ]; then + MSG="${MSG:0:117}..." +fi BODY=$(build_payload "$INPUT" "$NOTIF_TYPE" \ --arg summary "$MSG") diff --git a/plugins/warp/tests/test-hooks.sh b/plugins/warp/tests/test-hooks.sh index 754bdd0..2dc273a 100755 --- a/plugins/warp/tests/test-hooks.sh +++ b/plugins/warp/tests/test-hooks.sh @@ -14,6 +14,8 @@ set -uo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../scripts" && pwd)" source "$SCRIPT_DIR/build-payload.sh" +PLUGIN_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +REPO_DIR="$(cd "$PLUGIN_DIR/../.." && pwd)" PASSED=0 FAILED=0 @@ -47,6 +49,20 @@ assert_json_field() { # --- Tests --- +echo "=== plugin configuration ===" + +PLUGIN_VERSION=$(jq -r '.version' "$PLUGIN_DIR/.claude-plugin/plugin.json") +MARKETPLACE_VERSION=$(jq -r '.plugins[] | select(.name == "warp") | .version' \ + "$REPO_DIR/.claude-plugin/marketplace.json") +NOTIFICATION_MATCHER=$(jq -r '.hooks.Notification[0].matcher' "$PLUGIN_DIR/hooks/hooks.json") + +assert_eq "plugin version bumped" "2.3.0" "$PLUGIN_VERSION" +assert_eq "marketplace version matches plugin" "$PLUGIN_VERSION" "$MARKETPLACE_VERSION" +assert_eq "notification matcher includes input-required events" \ + "idle_prompt|agent_needs_input" \ + "$NOTIFICATION_MATCHER" + +echo "" echo "=== build-payload.sh ===" echo "" @@ -103,6 +119,12 @@ PAYLOAD=$(build_payload '{"session_id":"s1","cwd":"/tmp/proj","notification_type --arg summary "Claude is waiting for your input") assert_json_field "event is idle_prompt" "$PAYLOAD" ".event" "idle_prompt" assert_json_field "summary present" "$PAYLOAD" ".summary" "Claude is waiting for your input" +echo "" +echo "--- Agent needs input event ---" +PAYLOAD=$(build_payload '{"session_id":"s1","cwd":"/tmp/proj","notification_type":"agent_needs_input"}' "agent_needs_input" \ + --arg summary "Agent requires user input") +assert_json_field "event is agent_needs_input" "$PAYLOAD" ".event" "agent_needs_input" +assert_json_field "generic summary present" "$PAYLOAD" ".summary" "Agent requires user input" echo "" echo "--- JSON special characters in values ---"