#!/usr/bin/env bash # Generic Neovim notifier hook: tell the Neovim instance that owns this terminal # ($NVIM) that a state dump is available, by firing a `User Claude` # autocmd whose `data` is the dump's basename (no `.json`). A plugin listens for # the pattern it cares about and reads the matching dump under # $XDG_STATE_HOME/claude//.json. Reads the hook payload as JSON on # stdin. # # The signal is derived entirely from the payload, so this one script works on # every event it is registered against: # * `hook_event_name` -> the `Claude` autocmd pattern. # * `tool_use_id`, else `session_id[-source|-reason]` -> the `data`, matching # how `dump.hook.sh` names its files. # No-op when not inside a Neovim terminal ($NVIM unset), when nvim is missing, or # when the payload carries no identifier. The remote call is backgrounded with a # timeout and its output discarded, so a slow, busy, or gone editor never blocks # or breaks the tool call. [ -n "$NVIM" ] || exit 0 command -v nvim >/dev/null 2>&1 || exit 0 input=$(cat) event=$(jq --raw-output '.hook_event_name // empty' <<<"$input" 2>/dev/null) [ -n "$event" ] || exit 0 id=$(jq --raw-output '.tool_use_id // empty' <<<"$input" 2>/dev/null) if [ -z "$id" ]; then sid=$(jq --raw-output '.session_id // empty' <<<"$input" 2>/dev/null) suffix=$(jq --raw-output '.source // .reason // empty' <<<"$input" 2>/dev/null) id="$sid" [ -n "$sid" ] && [ -n "$suffix" ] && id="$sid-$suffix" fi [ -n "$id" ] || exit 0 # Fire the autocmd via luaeval (server-side, injects no keys); `_A` is the id. expr="luaeval(\"vim.api.nvim_exec_autocmds('User', " expr+="{pattern='Claude$event', data=_A}) or 1\", '$id')" timeout 2 nvim --server "$NVIM" --remote-expr "$expr" >/dev/null 2>&1 &