Repository navigation
fix(hooks): read the workspace from Cursor plugin hooks - #3
Merged
Merged
Conversation
A Cursor plugin hook runs in the plugin install and only accepts additional_context from sessionStart. session-start now inspects CURSOR_PROJECT_DIR, and format-on-save finds the fixer config there. The formatter stays on afterFileEdit. Co-authored-by: Cursor <cursoragent@cursor.com>
Without CURSOR_PROJECT_DIR both hooks now stay silent instead of reading the plugin install, which ships references/*.php and read as a PHP workspace. The session line is JSON-escaped for Cursor. format-on-save drops the unneeded "path" key and the relative-path join the cd already covers. The validator keeps its "when present" guard, rejects a non-integer version and a top-level non-object in cursor-hooks.json. The docs cite Cursor's hooks page with a check date, testing.md replays both hooks with Cursor's variables set, and the CHANGELOG is split per change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
Cursor runs a plugin hook from the plugin's install directory and reads JSON on stdout, not plain text (Cursor hooks). Both PHP hooks read the workspace from that install directory and printed plain text there.
session-start.shdetects Cursor byCURSOR_PLUGIN_ROOT,cds toCURSOR_PROJECT_DIRand returns its line as JSONadditional_context, escaped. On Cursor the line names/php-coding; Claude Code still gets the plainLoad the php-coding skillline.format-on-save.shstays onafterFileEdit, for which Cursor documents no output; it only rewrites the file. Itcds toCURSOR_PROJECT_DIR, so the fixer config,vendor/bin/php-cs-fixerand a relativefile_pathall resolve in the workspace.CURSOR_PROJECT_DIRboth hooks stay silent. Falling back to the install would read it as a PHP workspace, because it shipsreferences/*.php.hooks/cursor-hooks.jsonhas"version": 1and atimeout(in seconds) for each hook.scripts/validate.pyfails a Cursor hooks file without an integer"version": 1, with a non-object top level, or with${CLAUDE_PLUGIN_ROOT}.AGENTS.mdcites Cursor's hooks page with a check date, anddocs/testing.mdreplays both hooks with Cursor's variables set.There is no skill-nudge hook in this plugin, so nothing needed to move to
postToolUse.Not in this PR: in a multi-root Cursor workspace, the formatter uses the config of the root
CURSOR_PROJECT_DIRnames. Finding the config by searching upward from the edited file would fix that, but it would also change which config Claude Code picks in a monorepo, so it belongs in its own change.Test plan
python3 scripts/validate.pyandclaude plugin validate .python3 -m json.toolaccepts, naming/php-coding,guzzle.mdand Laravel Boost. It is silent whenCURSOR_PROJECT_DIRis unset, empty or missing, and in a non-PHP project.CURSOR_PROJECT_DIRthe fixer does not run, and apathkey no longer wins overfile_path."version": true,1.0or missing, a top-level list, and${CLAUDE_PLUGIN_ROOT}each fail. A missing file is reported once..phpedit is reformatted.Made with Cursor
🤖 Generated with Claude Code