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:
2026-05-25 06:54:15 +03:00
parent ef6fad727c
commit f1be677b0a
2 changed files with 14 additions and 2 deletions

View File

@@ -1,6 +1,6 @@
---
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», «отбой», «разбегаемся»."
---

View File

@@ -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.
**Substitute `C:\\Users\\<you>` with your actual home path before pasting** — see "Why literal path" below.
```jsonc
{
"hooks": {
@@ -19,7 +21,7 @@ Add to `~/.claude/settings.json`. Use `powershell` for stock Windows (PS 5.1, al
"hooks": [
{
"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.
### 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)
```jsonc