From 881ab7eedda650de55a348d23c394b0ca99ca3ed Mon Sep 17 00:00:00 2001 From: nscrdev Date: Sat, 18 Jul 2026 12:34:16 -0700 Subject: [PATCH 1/2] feat(warp): include session_name in structured payloads Claude Code maintains a session registry at ~/.claude/sessions/.json containing each session's human-readable name (kept current on /rename). Look it up by session_id at payload-build time and forward it as session_name on every warp://cli-agent payload, so Warp can label the sidebar/tab with the session name instead of duplicating the cwd path. Addresses the data half of #34; Warp-side rendering can adopt the field once it is present in payloads. Co-Authored-By: Claude Fable 5 --- plugins/warp/.claude-plugin/plugin.json | 2 +- plugins/warp/scripts/build-payload.sh | 26 +++++++++++++++++++++++-- plugins/warp/tests/test-hooks.sh | 23 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) 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/scripts/build-payload.sh b/plugins/warp/scripts/build-payload.sh index 9ad610e..cc60d63 100644 --- a/plugins/warp/scripts/build-payload.sh +++ b/plugins/warp/scripts/build-payload.sh @@ -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)] | last | .name // empty' \ + "${files[@]}" 2>/dev/null +} + build_payload() { local input="$1" local event="$2" @@ -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}' @@ -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' } diff --git a/plugins/warp/tests/test-hooks.sh b/plugins/warp/tests/test-hooks.sh index 754bdd0..6bb20d1 100755 --- a/plugins/warp/tests/test-hooks.sh +++ b/plugins/warp/tests/test-hooks.sh @@ -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" \ From 35aa9b790b8f28a538d2172503fc6b671127414a Mon Sep 17 00:00:00 2001 From: nscrdev Date: Sat, 18 Jul 2026 12:36:30 -0700 Subject: [PATCH 2/2] address review: doc comment + prefer most recently updated registry entry Co-Authored-By: Claude Fable 5 --- plugins/warp/scripts/build-payload.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/warp/scripts/build-payload.sh b/plugins/warp/scripts/build-payload.sh index cc60d63..429ece7 100644 --- a/plugins/warp/scripts/build-payload.sh +++ b/plugins/warp/scripts/build-payload.sh @@ -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. @@ -43,7 +43,7 @@ lookup_session_name() { [ -e "${files[0]}" ] || return 0 jq -rs --arg sid "$session_id" \ - '[.[] | select(type == "object" and .sessionId == $sid)] | last | .name // empty' \ + '[.[] | select(type == "object" and .sessionId == $sid)] | max_by(.updatedAt // 0) | .name // empty' \ "${files[@]}" 2>/dev/null }