#!/bin/bash # Claude Code hook (wired in via claude-settings.json) that tracks what Claude is # doing in each DevDesk session, for the sidebar's at-a-glance status: # UserPromptSubmit, PostToolUse -> working # Notification -> waiting (Claude needs input or a permission) # Stop, SessionStart -> idle # SessionEnd -> exited # Fires on every tool call, so it stays tiny and only writes when the state changes. input=$(cat) outer=${TMUX:-} [ "${outer%%,*}" = "${DEVDESK_SOCKET:-/run/devdesk/tmux.sock}" ] && [ -n "${TMUX_PANE:-}" ] || exit 0 session=$(tmux display-message -p -t "$TMUX_PANE" '#S' 2>/dev/null) [[ $session =~ ^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$ ]] || exit 0 IFS=$'\t' read -r event message < <(jq -rM '[.hook_event_name // "", (.message // "" | gsub("[\t\n]"; " "))] | @tsv' <<<"$input" 2>/dev/null) case $event in UserPromptSubmit | PostToolUse) state=working ;; Notification) state=waiting ;; Stop | SessionStart) state=idle ;; SessionEnd) state=exited ;; *) exit 0 ;; esac dir="${DEVDESK_STATE_DIR:-/var/lib/devdesk}/state" file="$dir/$session.json" # Unchanged state (the common case during tool runs): nothing to write. if [ "$state" != waiting ] && [ -f "$file" ] && grep -q "\"state\":\"$state\"" "$file"; then exit 0 fi mkdir -p "$dir" 2>/dev/null || exit 0 tmp=$(mktemp "$dir/.$session.XXXXXX" 2>/dev/null) || exit 0 if jq -cMn --arg s "$state" --arg m "$message" --arg e "$event" \ '{state: $s, since: (now | floor), event: $e, message: (if $m == "" then null else $m end)}' >"$tmp"; then mv -f "$tmp" "$file" else rm -f "$tmp" fi exit 0