#!/bin/sh # Хук Claude Code для панели «Claude» в iTerm2. # Пишет события сессий и субагентов в ~/.cache/claude-agents/.jsonl # вместе с тем, где запущена сессия: PID процесса claude, вкладка iTerm2 или панель tmux. # Нужен jq (в macOS 15+ встроен, иначе: brew install jq). # Никогда не мешает Claude Code: ничего не выводит и всегда выходит с кодом 0. dir="$HOME/.cache/claude-agents" input=$(cat) sid=$(printf '%s' "$input" | jq -r '.session_id // empty' 2>/dev/null | tr -cd 'A-Za-z0-9_-') [ -n "$sid" ] || exit 0 mkdir -p "$dir" 2>/dev/null || exit 0 # PID самого claude: идём вверх по родителям, пропуская оболочки, которыми запущен хук pid=$PPID comm="" i=0 while [ "$i" -lt 4 ] && [ "${pid:-1}" -gt 1 ]; do comm=$(ps -o comm= -p "$pid" 2>/dev/null | sed 's#.*/##; s/^-//') case "$comm" in sh|bash|zsh|dash|fish) pid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ') ;; *) break ;; esac i=$((i + 1)) done # Внутри tmux ITERM_SESSION_ID унаследован от сервера tmux и указывает не туда — не пишем его iterm="${ITERM_SESSION_ID:-}" tmux_socket="" tmux_pane="" if [ -n "${TMUX:-}" ] && [ -n "${TMUX_PANE:-}" ]; then iterm="" tmux_socket="${TMUX%%,*}" tmux_pane="$TMUX_PANE" fi printf '%s' "$input" | jq -c --arg iterm "$iterm" --arg pid "${pid:-}" --arg pid_comm "$comm" \ --arg tmux_socket "$tmux_socket" --arg tmux_pane "$tmux_pane" ' def cut: if type == "string" then .[0:300] else . end; { hook_event_name, session_id, transcript_path, cwd, agent_id, agent_type, model, session_title, source, from_model, to_model, tool_name, tool_use_id, notification_type, agent_transcript_path, reason, message: (.message | cut), description: (.description | cut), last_assistant_message: (.last_assistant_message | cut), tool_input: (if (.tool_input | type) == "object" then .tool_input | {subagent_type, description, model, name} | map_values(cut) | with_entries(select(.value != null)) else null end), t: now, iterm: $iterm, pid: ($pid | tonumber? // null), pid_comm: (if $pid_comm == "" then null else $pid_comm end), tmux_socket: (if $tmux_socket == "" then null else $tmux_socket end), tmux_pane: (if $tmux_pane == "" then null else $tmux_pane end) } | with_entries(select(.value != null)) ' >> "$dir/$sid.jsonl" 2>/dev/null exit 0