Skip to content

fix: quote CLAUDE_PLUGIN_ROOT in hooks.json to handle paths with spaces - #2704

Closed
Tom Meschter (tmeschter) with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-posttooluse-telemetry-hook
Closed

fix: quote CLAUDE_PLUGIN_ROOT in hooks.json to handle paths with spaces#2704
Tom Meschter (tmeschter) with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-posttooluse-telemetry-hook

Conversation

Copilot AI commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

On Windows, when the user profile path contains spaces (e.g. C:\Users\First Last), bash word-splits the unquoted ${CLAUDE_PLUGIN_ROOT} expansion in hooks.json, causing the PostToolUse hook to fail on every tool call before track-telemetry.sh ever runs.

Change

plugin/hooks/hooks.json — wrap the script path in escaped quotes:

-"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/track-telemetry.sh"
+"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/scripts/track-telemetry.sh\""

This ensures the expanded path is treated as a single argument regardless of embedded spaces.

Copilot AI changed the title [WIP] Fix PostToolUse telemetry hook failure on Windows with space in path fix: quote CLAUDE_PLUGIN_ROOT in hooks.json to handle paths with spaces Jun 25, 2026
@tmeschter
Tom Meschter (tmeschter) marked this pull request as ready for review June 25, 2026 22:25
Copilot AI review requested due to automatic review settings June 25, 2026 22:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a Windows-specific hook execution failure for Claude Code when the plugin root path contains spaces by ensuring the track-telemetry.sh script path is passed to bash as a single, properly-quoted argument.

Changes:

  • Quote the ${CLAUDE_PLUGIN_ROOT}-based script path in plugin/hooks/hooks.json to prevent bash word-splitting on paths with spaces.
Show a summary per file
File Description
plugin/hooks/hooks.json Wrapes the telemetry hook script path in escaped quotes so ${CLAUDE_PLUGIN_ROOT} expansions containing spaces remain a single argument.

Copilot's findings

  • Files reviewed: 1/1 changed files
  • Comments generated: 0

@JasonYeMSFT

JasonYeMSFT (JasonYeMSFT) commented Jun 25, 2026

Copy link
Copy Markdown
Member

The fix is also needed in .github/plugins/azure-skills/hooks/hooks.json. Do we need it in other hooks.json as well?

Edit: I see, that file is replicated from the edited hooks.json. However, I feel we need to make the same fix to cursor-hooks.json as well.

@jongio Jon Gallant (jongio) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreeing with JasonYeMSFT (@JasonYeMSFT)'s observation about sibling files. Beyond cursor-hooks.json, note that copilot-hooks.json also references an unquoted path:

"bash": "${PLUGIN_ROOT}/hooks/scripts/track-telemetry.sh"

Depending on how the consumer of that file invokes the script, the same word-splitting issue could apply. Worth checking whether the runner passes the bash field value through a shell or uses it as a direct file argument.

Not blocking since this is a targeted fix, but a follow-up to address both siblings (cursor-hooks.json and copilot-hooks.json) would close the gap entirely.

Also update the Cursor and Copilot hooks.
@tmeschter

Copy link
Copy Markdown
Member

JasonYeMSFT (@JasonYeMSFT) Jon Gallant (@jongio) I've updated the other hooks files to quote the path to the script.

@jongio Jon Gallant (jongio) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified the incremental change addressing the sibling-file feedback.

One non-blocking question on copilot-hooks.json: the powershell field value includes literal double quotes after JSON deserialization. This works if the hook runner evaluates through a shell (where quotes prevent splitting on spaces). It would break if the runner passes the expanded value directly to powershell -File (literal quote chars become part of the filename). Worth a quick smoke test on Windows with a spaced profile path to confirm the runner's PowerShell invocation model handles this correctly.

"bash": "${PLUGIN_ROOT}/hooks/scripts/track-telemetry.sh",
"powershell": "${PLUGIN_ROOT}/hooks/scripts/track-telemetry.ps1"
"bash": "\"${PLUGIN_ROOT}/hooks/scripts/track-telemetry.sh\"",
"powershell": "\"${PLUGIN_ROOT}/hooks/scripts/track-telemetry.ps1\""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (non-blocking): After JSON parse, this value is "${PLUGIN_ROOT}/hooks/scripts/track-telemetry.ps1" with literal double quotes. Works correctly if the hook runner evaluates through a shell or -Command, but would fail if it passes the path directly to powershell -File (quotes become part of the filename). Worth verifying the runner's invocation model on Windows with spaces in the user profile path.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it turns out, VS Code is calling powershell -Command <hook>. With the escaped quotes PowerShell sees "C:\<full>\<path>\<to>\track-telemetry.ps1" (with the double quotes), interprets it as a string, and returns the path as-is rather than executing it. So at least for "powershell" and VS Code the quotes are the wrong thing.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tom Meschter (@tmeschter) - that confirms the regression. With -Command, the quoted path becomes a string expression instead of an invocation, so the hook silently does nothing regardless of whether there are spaces.

Does the same apply to the bash field in this file? If VS Code passes it to bash as a direct file argument, the literal quote characters would become part of the filename and fail. If it evaluates through bash -c, the quotes would work as intended.

For the powershell field specifically, the fix would likely need the call operator (& '...') instead of double quotes. But whether single quotes or the & prefix survive the runner's variable expansion depends on when ${PLUGIN_ROOT} gets resolved.

@tmeschter

Copy link
Copy Markdown
Member

This fix was rolled into #2719.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants