Three defects, each of which independently made a hook a no-op, and all
three failing silently — which is why the whole dynamic side of the plugin
looked "shipped" while doing nothing.
1. Wrong env var case. Claude Code exports userConfig to hooks as
CLAUDE_PLUGIN_OPTION_<KEY> with the key UPPERCASED. All four hooks read
CLAUDE_PLUGIN_OPTION_api_endpoint / _api_token, so both values were
always empty. That killed the SessionStart dynamic tier, process sync,
prompt auto-inject, and the write-path prior-art trigger at once.
2. jq -rR is line-oriented. `@uri` under -R encodes input LINE BY LINE, so
a multi-line payload came back as several encoded lines joined by raw
newlines — an invalid URL, curl fails, hook exits 0 in silence. Now
-sRr. This one hid behind (1): auto-inject only ever worked for
single-line prompts, and prior-art (which posts code, always
multi-line) could never have worked at all.
3. cut -c1-1200 caps each LINE, not the payload, so the prior-art code
budget wasn't a budget. Now head -c 1200.
Also widens the SessionStart warning: "neither URL nor token arrived" used
to be treated as a benign unconfigured install and stayed quiet. That is
exactly the state defect (1) produced, so the one install state that most
needed a signal was the only one that emitted none. It now says so, and
names the two other features it silently disables.
Verified against the live instance: dynamic rules + project context load,
auto-inject surfaces #2192 on a multi-line prompt, and the write-path
trigger returns the [here] place-arm hit on a multi-line edit with session
dedup suppressing the repeat.
Refs #2198, #2082
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs