aboutsummaryrefslogtreecommitdiffstats
path: root/hooks/nvim-notify.hook.sh
blob: b070467c376ccacb31427b79e80eeb5f014315fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/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<Event>`
# 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/<dir>/<data>.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<Event>` 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 &