fix(session-handoff): hook command literal path [v0.3.3]
PostToolUse hook in `~/.claude/settings.json` was using `$env:USERPROFILE` (PowerShell syntax), but Claude Code on Windows runs hook commands through git-bash. Bash treats `$env` as an empty variable, leaving `":USERPROFILE\..."` as the literal `-File` argument — PowerShell fails with "invalid filename format" and the hook never fires. Install snippet in hooks/README.md now uses literal absolute path `C:\Users\<you>\.claude\...` with a "Why literal path" section explaining why `$env:VAR` / `%VAR%` / `~` all break through the bash-harness chain on Windows. Retracts the v0.3.0 "live-hook e2e smoke done" closure — that result was from synthetic replay through the PowerShell tool, which bypassed the broken harness chain. Real e2e verification requires this fix plus a CC restart, then a substantive commit to observe `additionalContext` surface.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: session-handoff
|
name: session-handoff
|
||||||
version: 0.3.2
|
version: 0.3.3
|
||||||
description: "Sliding handoff between CC sessions via .tasks/NEXT_SESSION.md. Read on session start: orient agent, ask user before action. Write on session-end phrase or substantive commit. Session-end phrases: «завершаем сессию», «сворачиваемся», «закругляемся», «wrap up session», «end session», «we're done for now». Trigger-line in CLAUDE.md: `session handoff: read on start, write on end`. Skip task-zone phrases: «закрываем эту таску», «pause», «отбой», «разбегаемся»."
|
description: "Sliding handoff between CC sessions via .tasks/NEXT_SESSION.md. Read on session start: orient agent, ask user before action. Write on session-end phrase or substantive commit. Session-end phrases: «завершаем сессию», «сворачиваемся», «закругляемся», «wrap up session», «end session», «we're done for now». Trigger-line in CLAUDE.md: `session handoff: read on start, write on end`. Skip task-zone phrases: «закрываем эту таску», «pause», «отбой», «разбегаемся»."
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ Opt-in PostToolUse hook that detects substantive `git commit` invocations and si
|
|||||||
|
|
||||||
Add to `~/.claude/settings.json`. Use `powershell` for stock Windows (PS 5.1, always present); use `pwsh` if you have PowerShell 7+ installed. The hook script runs cleanly under both.
|
Add to `~/.claude/settings.json`. Use `powershell` for stock Windows (PS 5.1, always present); use `pwsh` if you have PowerShell 7+ installed. The hook script runs cleanly under both.
|
||||||
|
|
||||||
|
**Substitute `C:\\Users\\<you>` with your actual home path before pasting** — see "Why literal path" below.
|
||||||
|
|
||||||
```jsonc
|
```jsonc
|
||||||
{
|
{
|
||||||
"hooks": {
|
"hooks": {
|
||||||
@@ -19,7 +21,7 @@ Add to `~/.claude/settings.json`. Use `powershell` for stock Windows (PS 5.1, al
|
|||||||
"hooks": [
|
"hooks": [
|
||||||
{
|
{
|
||||||
"type": "command",
|
"type": "command",
|
||||||
"command": "powershell -NoProfile -ExecutionPolicy Bypass -File \"$env:USERPROFILE\\.claude\\skills\\session-handoff\\hooks\\commit-detector.ps1\""
|
"command": "powershell -NoProfile -ExecutionPolicy Bypass -File \"C:\\Users\\<you>\\.claude\\skills\\session-handoff\\hooks\\commit-detector.ps1\""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -34,6 +36,16 @@ If `hooks.PostToolUse` already exists — append the matcher block to the array.
|
|||||||
|
|
||||||
**Restart Claude Code after editing `settings.json`** — hooks are loaded at session start. A running session won't pick up the new hook until it's restarted (close + reopen the CC instance). Verify the hook is active by making a substantive commit and checking for a `Substantive commit detected on ...` system reminder in the next turn.
|
**Restart Claude Code after editing `settings.json`** — hooks are loaded at session start. A running session won't pick up the new hook until it's restarted (close + reopen the CC instance). Verify the hook is active by making a substantive commit and checking for a `Substantive commit detected on ...` system reminder in the next turn.
|
||||||
|
|
||||||
|
### Why literal path (no `$env:USERPROFILE` / `%USERPROFILE%` / `~`)
|
||||||
|
|
||||||
|
Claude Code on Windows invokes hook commands through **git-bash**, not PowerShell or cmd.exe directly. The outer-shell layer mangles shell-specific variable references before PowerShell ever sees the args:
|
||||||
|
|
||||||
|
- `$env:USERPROFILE` (PowerShell syntax) → bash treats `$env` as an empty variable and the rest `:USERPROFILE\...` becomes a literal, so PowerShell receives `-File ":USERPROFILE\..."` and fails with `неверный формат имени` / "invalid filename format".
|
||||||
|
- `%USERPROFILE%` (cmd syntax) → bash passes through literally, PowerShell doesn't expand it, same failure.
|
||||||
|
- `~/.claude/...` → bash expands `~` to git-bash-style `/c/Users/<you>/...`, which PowerShell's `-File` can't resolve to a real Windows path.
|
||||||
|
|
||||||
|
Literal absolute path with `C:\\Users\\<you>\\...` (escaped backslashes for JSON) survives every outer shell unchanged. `settings.json` is per-user anyway — portability across machines isn't a concern at this layer.
|
||||||
|
|
||||||
## Enable on Linux / macOS (bash)
|
## Enable on Linux / macOS (bash)
|
||||||
|
|
||||||
```jsonc
|
```jsonc
|
||||||
|
|||||||
Reference in New Issue
Block a user