#!/bin/sh
# Otty — Claude Code hook.
#
# Reports the agent's state to the Otty app over IPC so a terminal pane can
# show the processing / idle / awaiting-input badge. Otty registers this script
# in ~/.claude/settings.json (Settings → Agents → Install Hooks). It is shipped
# as a readable, code-signed file inside Otty.app so you can audit exactly what
# runs on every Claude hook event — Otty injects only the per-install paths.
#
# Args:
#   $1  state     — processing | idle | awaiting
#   $2  claude_pid — the Claude process's pid (its $PPID at hook time), used to
#                    detect --dangerously-skip-permissions ("bypass") mode
#   $3  "ctx"     — present only for PermissionRequest: forward the full hook
#                   stdin (base64) so Otty can offer auto-approve context
# Env:
#   OTTY_CLI — absolute path to the bundled otty-cli (injected by Otty; falls
#              back to the copy next to this script's bundle)
state="$1"
claude_pid="$2"
want_ctx="$3"

# Claude passes the hook payload as JSON on stdin.
input=$(cat)

# Suppress the spurious "task complete" that fires per Task subagent. A Task
# subagent runs in the background: while it works, the main agent often yields
# and Claude fires a Stop (this hook's state=idle) even though the turn isn't
# really over — the still-running subagent is listed in the Stop payload's
# background_tasks (`"type":"subagent","status":"running"`). Reporting that as
# idle made Otty fire a completion notification (and idle badge) for every
# subagent. Treat such a Stop as still-processing so the notification only
# fires on the genuine final Stop, whose background_tasks no longer lists a
# running subagent. Whitespace is stripped so the match survives pretty-printed
# JSON; both key orderings are covered. Older Claude builds without the field
# simply won't match, preserving the previous behaviour.
if [ "$state" = idle ]; then
    bt=$(printf '%s' "$input" | tr -d ' \t\n')
    case "$bt" in
        *'"type":"subagent","status":"running"'*|*'"status":"running","type":"subagent"'*)
            state=processing ;;
    esac
fi

# Prefer the env the Claude CLI exports; fall back to the stdin JSON.
sid="${CLAUDE_SESSION_ID:-$(printf '%s' "$input" | sed -n 's/.*"session_id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n 1)}"

# Bypass-permissions mode is read from the Claude process's own argv.
bypass=0
ps -o args= -p "$claude_pid" 2>/dev/null | grep -qF -- '--dangerously-skip-permissions' && bypass=1

# Otty injects OTTY_CLI; the fallback locates otty-cli relative to this script
# inside the bundle (…/Contents/Resources/agent-integration/claude → …/MacOS).
cli="${OTTY_CLI:-$(CDPATH= cd -- "$(dirname -- "$0")/../../../MacOS" 2>/dev/null && pwd)/otty-cli}"

# Backgrounded so the hook never blocks Claude. Errors are intentionally
# swallowed: a missing Otty app must not break the user's Claude session.
if [ "$want_ctx" = "ctx" ]; then
    ctx=$(printf '%s' "$input" | base64)
    "$cli" state:claude session-id="$sid" state="$state" bypass="$bypass" context-b64="$ctx" 2>/dev/null &
else
    "$cli" state:claude session-id="$sid" state="$state" bypass="$bypass" 2>/dev/null &
fi
