Skip to content

fix(hooks): quote plugin-root paths with spaces (#1076)#1077

Merged
igorls merged 1 commit intoMemPalace:developfrom
mvalentsev:fix/hooks-quote-plugin-root
May 3, 2026
Merged

fix(hooks): quote plugin-root paths with spaces (#1076)#1077
igorls merged 1 commit intoMemPalace:developfrom
mvalentsev:fix/hooks-quote-plugin-root

Conversation

@mvalentsev
Copy link
Copy Markdown
Contributor

@mvalentsev mvalentsev commented Apr 21, 2026

Problem

Hook commands in .claude-plugin/hooks/hooks.json and .codex-plugin/hooks.json expand ${CLAUDE_PLUGIN_ROOT} / ${CODEX_PLUGIN_ROOT} without quoting. When the user profile path contains a space (e.g. C:\Users\Richard M on Windows), the shell splits the command on the space and the hook fails:

Stop hook error: Failed with non-blocking status code: bash: /c/Users/Richard: No such file or directory

Fix

Wrap the path variable in double quotes so shell word-splitting preserves the token boundary.

.claude-plugin/hooks/hooks.json (Stop + PreCompact):

"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/mempal-stop-hook.sh\""

.codex-plugin/hooks.json (SessionStart + Stop + PreCompact):

"command": "\"${CODEX_PLUGIN_ROOT}/hooks/mempal-hook.sh\" session-start"

On the Codex variant the argument stays outside the quotes so it remains a separate token after shell parsing. Same pattern used by the superpowers plugin reference in issue #1076.

Scope check

  • plugin.json / .mcp.json: MCP command is the mempalace-mcp entry point with no path arg, not affected.
  • hooks/*.sh (legacy): standalone scripts whose path the user writes into settings.local.json, out of scope for the plugin-shipped configs.
  • Internal .sh bodies already quote all path variables.

Test plan

  • Both JSON files remain valid (jq empty passes on both).
  • Local reproduction on Linux with a space-containing plugin path confirms the pre-fix vs post-fix delta:
    # path: /tmp/memp smoke <pid>
    # unquoted:  bash: /tmp/memp: No such file or directory
    # quoted:    {}   (hook ran to completion, empty decision)
    
    Matches the bash: /c/Users/Richard: No such file or directory shape reported on Windows.
  • Windows smoke with a space-containing profile path: unable to verify locally, would appreciate a sanity check from @dogskool on 3.3.1 once the fix is in.

Fixes #1076.

@mvalentsev mvalentsev marked this pull request as ready for review April 21, 2026 18:31
@mvalentsev mvalentsev requested a review from bensig as a code owner April 21, 2026 18:31
@igorls igorls added bug Something isn't working area/hooks Claude Code hook scripts (Stop, PreCompact, SessionStart) labels Apr 24, 2026
MemPalace#1076)

Shell splits hook command on whitespace after variable expansion, breaking
paths with spaces (e.g. C:\Users\Richard M on Windows). Wrapping the path
in double quotes preserves the token boundary.

Fixes the reported Stop/PreCompact pair in .claude-plugin/hooks/hooks.json
and applies the same fix to .codex-plugin/hooks.json (SessionStart/Stop/
PreCompact), which carries the identical bug.
@mvalentsev mvalentsev force-pushed the fix/hooks-quote-plugin-root branch from 68f64cd to 372cca3 Compare April 26, 2026 18:58
@igorls igorls added this to the v3.3.5 milestone May 2, 2026
@igorls igorls merged commit d07b730 into MemPalace:develop May 3, 2026
6 checks passed
xcarbo added a commit to xcarbo/mempalace that referenced this pull request May 4, 2026
Catches up on a month of upstream work. Highlights pulled in:

- MemPalace#1306 searcher: hybrid candidate union (vector ∪ BM25 reranking pool)
- MemPalace#1325 mcp security: omit absolute paths from tool_get_drawer / tool_status
- MemPalace#1322 chroma: wire quarantine_stale_hnsw to prevent SIGSEGV on stale HNSW
- MemPalace#1320 mcp: forward valid_to / source params in kg_add / kg_invalidate
- MemPalace#1321 cli: honor --palace flag in cmd_init
- MemPalace#1314 kg temporal params fix
- MemPalace#1244 cli: cmd_compress writes to mempalace_closets so palace can read
- MemPalace#1243 mcp: case-insensitive agent name in diary_write/diary_read
- MemPalace#1303 mcp_server: pass embedding_function= on collection reopen
- MemPalace#1076/MemPalace#1077 hooks: quote CLAUDE_PLUGIN_ROOT / CODEX_PLUGIN_ROOT in hooks.json
- Various ruff format passes on touched files

Conflict resolution (CHANGELOG.md only — code files all auto-merged):

- 3.3.5 unreleased section header from upstream kept above 3.3.4
- 3.3.4 section: kept our 2026-04-30 release date; merged upstream's new
  MemPalace#1299 SIGSEGV-on-default-EF entry in alongside our existing topic-tunnels
  (MemPalace#1194/MemPalace#1195/MemPalace#1197), HNSW-bloat (MemPalace#1191), max_seq_id (MemPalace#1135), and
  auto-ingest (MemPalace#1230/MemPalace#1231) entries. Kept our richer topic-tunnels detail
  (upstream's version was a strict subset).

xdev patches preserved (still on this branch, untouched by merge):
- 6ef44cb fix(hooks): route CC transcripts via convo_miner with cwd-based wings
- 3fad61d fix(config): allow leading dash in wing names

Not pushed to origin — run tests locally and decide when to push.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/hooks Claude Code hook scripts (Stop, PreCompact, SessionStart) bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stop/PreCompact hooks break on paths with spaces (unquoted CLAUDE_PLUGIN_ROOT)

2 participants