Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/warp/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
28 changes: 25 additions & 3 deletions plugins/warp/scripts/build-payload.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# --arg response "$RESPONSE" \
# --arg transcript_path "$TRANSCRIPT_PATH")
#
# The function extracts common fields (session_id, cwd, project) from the
# The function extracts common fields (session_id, cwd, project, session_name) from the
# hook's stdin JSON (passed as $1), then merges any extra jq args you pass.

# The current protocol version this plugin knows how to produce.
Expand All @@ -27,6 +27,26 @@ negotiate_protocol_version() {
fi
}

# Look up the human-readable session name from Claude Code's session registry.
# Claude Code writes one JSON file per running session to ~/.claude/sessions/
# (keyed by pid) containing sessionId, name, status, etc. The name is kept
# up to date on /rename, so reading it at payload-build time reflects renames.
# Prints an empty string if the registry or session can't be found.
lookup_session_name() {
local session_id="$1"
[ -n "$session_id" ] || return 0

local sessions_dir="${CLAUDE_SESSIONS_DIR:-${CLAUDE_CONFIG_DIR:-$HOME/.claude}/sessions}"
[ -d "$sessions_dir" ] || return 0

local files=("$sessions_dir"/*.json)
[ -e "${files[0]}" ] || return 0

jq -rs --arg sid "$session_id" \
'[.[] | select(type == "object" and .sessionId == $sid)] | max_by(.updatedAt // 0) | .name // empty' \
"${files[@]}" 2>/dev/null
}

build_payload() {
local input="$1"
local event="$2"
Expand All @@ -36,13 +56,14 @@ build_payload() {
protocol_version=$(negotiate_protocol_version)

# Extract common fields from the hook input
local session_id cwd project
local session_id cwd project session_name
session_id=$(echo "$input" | jq -r '.session_id // empty' 2>/dev/null)
cwd=$(echo "$input" | jq -r '.cwd // empty' 2>/dev/null)
project=""
if [ -n "$cwd" ]; then
project=$(basename "$cwd")
fi
session_name=$(lookup_session_name "$session_id")

# Build the payload: common fields + any extra args passed by the caller.
# Extra args should be jq flag pairs like: --arg key "value" or --argjson key '{"a":1}'
Expand All @@ -53,6 +74,7 @@ build_payload() {
--arg session_id "$session_id" \
--arg cwd "$cwd" \
--arg project "$project" \
--arg session_name "$session_name" \
"$@" \
'{v:$v, agent:$agent, event:$event, session_id:$session_id, cwd:$cwd, project:$project} + $ARGS.named'
'{v:$v, agent:$agent, event:$event, session_id:$session_id, cwd:$cwd, project:$project, session_name:$session_name} + $ARGS.named'
}
23 changes: 23 additions & 0 deletions plugins/warp/tests/test-hooks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,29 @@ assert_json_field "empty session_id" "$PAYLOAD" ".session_id" ""
assert_json_field "empty cwd" "$PAYLOAD" ".cwd" ""
assert_json_field "empty project" "$PAYLOAD" ".project" ""

echo ""
echo "--- Session name lookup ---"
SESSIONS_FIXTURE=$(mktemp -d)
echo '{"pid":111,"sessionId":"sess-123","name":"my renamed session","status":"idle"}' > "$SESSIONS_FIXTURE/111.json"
echo '{"pid":222,"sessionId":"sess-other","name":"other session","status":"busy"}' > "$SESSIONS_FIXTURE/222.json"

export CLAUDE_SESSIONS_DIR="$SESSIONS_FIXTURE"
PAYLOAD=$(build_payload '{"session_id":"sess-123","cwd":"/Users/alice/my-project"}' "stop")
assert_json_field "session_name from registry" "$PAYLOAD" ".session_name" "my renamed session"

PAYLOAD=$(build_payload '{"session_id":"sess-unknown","cwd":"/tmp/proj"}' "stop")
assert_json_field "unknown session id yields empty name" "$PAYLOAD" ".session_name" ""

PAYLOAD=$(build_payload '{"cwd":"/tmp/proj"}' "stop")
assert_json_field "missing session id yields empty name" "$PAYLOAD" ".session_name" ""

export CLAUDE_SESSIONS_DIR="$SESSIONS_FIXTURE/does-not-exist"
PAYLOAD=$(build_payload '{"session_id":"sess-123","cwd":"/tmp/proj"}' "stop")
assert_json_field "missing registry dir yields empty name" "$PAYLOAD" ".session_name" ""

unset CLAUDE_SESSIONS_DIR
rm -rf "$SESSIONS_FIXTURE"

echo ""
echo "--- Extra args are merged ---"
PAYLOAD=$(build_payload '{"session_id":"s1","cwd":"/tmp/proj"}' "stop" \
Expand Down