fix(plugin): refuse an unset CLAUDE_PLUGIN_ROOT instead of guessing $PWD - #430
Merged
Conversation
All nine hook commands resolved their root as ${CLAUDE_PLUGIN_ROOT:-$PWD}.
That fallback cannot work: the launcher lives inside the plugin, never in
the user's working directory, so when the variable is unset the hook runs
python3 against a path that is wrong by construction and reports
"can't open file '<cwd>/scripts/launcher.py'" — an error that names the
wrong cause and sends the reader looking at their own project.
Measured 2026-08-10 from an unrelated repository: every Cortex hook failed
that way, silently, until the cause was traced back here. A fallback that
guarantees a wrong path is not a fallback; it converts a clear
configuration error into a misleading runtime one.
The hooks now refuse and name the missing variable. Verified both ways on
the final state: unset -> "CLAUDE_PLUGIN_ROOT is unset; refusing to guess
the plugin root", exit 1; set -> identical behaviour to before the change
(it reaches the launcher). JSON re-parsed after the edit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01263uv1QqR8TVzw2jXYUrXn
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
All nine hook commands in
.claude-plugin/plugin.jsonresolved their root as${CLAUDE_PLUGIN_ROOT:-$PWD}. That fallback cannot ever be correct:scripts/launcher.pylives inside the plugin, never in the user's working directory. When the variable is unset the hook runspython3against a path that is wrong by construction and reports— an error naming the wrong cause, which sends the reader looking at their own project instead of at the plugin.
How it surfaced. On 2026-08-10, every Cortex hook failed this way from an unrelated repository, repeatedly, before the cause was traced back here. The message pointed at a path that had never been right, so it read as a local problem rather than a plugin one.
A fallback that guarantees a wrong path is not a fallback. It converts a clear configuration error — "this variable is not set" — into a misleading runtime one, and it belongs to the same family as a gate that opens when it cannot decide.
The change
The hooks now refuse and name the missing variable:
Nine occurrences, no other edit. The file was re-parsed as JSON after the change.
Verified both directions on the final state
Unset — refuses, names the variable:
Set — behaviour identical to before the change; the hook reaches the launcher:
That trailing numpy failure is pre-existing and unrelated — the same command from
origin/mainproduces it identically in this virtualenv. It is the proof the guard does not change the normal path, not a regression introduced here.exit 1on these events is a non-blocking error by the hooks contract, so a misconfigured install now reports the real cause without stopping the session.