Skip to content

[BUG] Windows: ${CLAUDE_PLUGIN_ROOT} left unexpanded in Claude Desktop (Cowork), PreToolUse Bash hook fully blocked #65579

Description

@aozoraimura-crypto

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

Windows: plugin hook ${CLAUDE_PLUGIN_ROOT} left unsubstituted in
Claude Desktop (Cowork), breaking PreToolUse Bash hooks
Related: #39550 (canonical, closed, macOS), #43380, #18527 — this is the Windows manifestation with blocking (non-cosmetic) severity

Environment:

  • Claude Desktop (Cowork), latest, Windows 11
  • Python 3.14
  • Org-managed (remote) plugins with PreToolUse Bash hooks

Symptom:
Running a Bash tool call fails. The hook command is shell form:
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-bash.py"
and produces:
python.exe: can't open file
'...\outputs${CLAUDE_PLUGIN_ROOT}\hooks\scripts\check-bash.py':
[Errno 2] No such file or directory

Root cause:
On Windows, ${CLAUDE_PLUGIN_ROOT} is NOT substituted before the hook
subprocess is spawned. The literal string "${CLAUDE_PLUGIN_ROOT}" is
passed through and resolved relative to the session cwd, so the file
is never found. This matches #43380 (CLAUDE_PLUGIN_ROOT not injected
at hook execution time) and #11984 (portability). Related backslash-
handling variants on Windows: #18527, #22449, #23204.

Request:
Substitute ${CLAUDE_PLUGIN_ROOT} as a plain string into command/args
before spawning on Windows (as documented for exec form), and ensure
the path is correct for the target shell.

Note: a .sh-based hook in the same plugin also fails on Windows
(cannot be spawned directly); cf. #21847.

What Should Happen?

Expected Behavior:
${CLAUDE_PLUGIN_ROOT} should be substituted to the plugin's actual
installation directory before the hook subprocess is spawned on
Windows — the same as on macOS/Linux — so the hook script is found
and runs.

Concretely:

  • The literal string "${CLAUDE_PLUGIN_ROOT}" must never reach the
    spawned process unexpanded.
  • The substituted path must be in a form the target interpreter/shell
    can resolve on Windows (handle backslashes and spaces in the path).
  • This should hold for both shell form and exec form, and regardless
    of the interpreter (python3, node, bash, etc.).
  • Result: the PreToolUse Bash hook runs without error and the Bash
    tool is usable on Windows.

Error Messages/Logs

PreToolUse:mcp__workspace__bash hook error: 
[python3 ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-bash.py]: 
C:\Users\...\AppData\Local\Python\pythoncore-3.14-64\python.exe: 
can't open file 
'C:\Users\...\AppData\Roaming\Claude\local-agent-mode-sessions\
...\outputs\${CLAUDE_PLUGIN_ROOT}\hooks\scripts\check-bash.py': 
[Errno 2] No such file or directory

Steps to Reproduce

Steps to Reproduce:

Environment: Windows 11, Claude Desktop (Cowork), latest.

  1. Create a minimal plugin with a PreToolUse Bash hook in SHELL form
    (no "args"), referencing the placeholder. hooks/hooks.json:

    {
    "hooks": {
    "PreToolUse": [
    { "matcher": "Bash",
    "hooks": [
    { "type": "command",
    "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-bash.py" }
    ] }
    ]
    }
    }

  2. Add the referenced script so the path is valid when expanded:
    hooks/scripts/check-bash.py -> print("ok")

  3. Install/enable the plugin in Claude Desktop (Cowork) on Windows.

  4. In a session, trigger any Bash tool call.

Observed:
python.exe: can't open file
'...\outputs${CLAUDE_PLUGIN_ROOT}\hooks\scripts\check-bash.py':
[Errno 2] No such file or directory

-> "${CLAUDE_PLUGIN_ROOT}" is left literal and resolved relative to
the session cwd; the file is never found and the Bash tool is blocked.

Notes:

  • Same hooks.json works on macOS/Linux.
  • Reproduces regardless of whether the user profile path contains a
    space (a space makes it worse; cf. path tokenization).

Claude Model

None

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

Claude 1.11187.1 (370d3b) 2026-06-04T17:30:35.000Z

Platform

Other

Operating System

Windows

Terminal/Shell

PowerShell

Additional Information

No response

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    duplicateThis issue or pull request already exists

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions