feat: Windows shell write/delete detection (#46 follow-up)#75
Merged
Conversation
Task handoff for the Windows session: extend bash_detect to PowerShell commands (Remove-Item etc.) + Windows path resolution so neo-tree change indicators fire for shell deletes/writes on Windows. Includes the STEP 0 debug-sample gathering (only doable on Windows), the grammar requirements, the diff.lua git portability fix, and a note to coordinate the bash_detect -> shell_detect structure decision with the improve-architecture pass. Scratchpad — to be removed before this follow-up PR merges. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replaces the "structure decision is not yours" placeholder with the now- decided shape from the improve-codebase-architecture pass: split the two independent axes (path conventions vs command grammar — they don't align to OS), rename bash_detect -> shell_detect behind the same M.detect interface, extract a path-convention adapter, make command matchers table-shaped, and add the PowerShell grammar only after STEP 0 confirms it. Registry/engine and any per-OS file split are explicitly out of scope (deferred by the review). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…46) Records the fork-(b) decision from the architecture review: the shell write/delete detector splits path-convention from command-grammar (the two do not align onto OS — git-bash on Windows is POSIX grammar + Windows paths), renames bash_detect -> shell_detect behind the same M.detect interface, extracts a path-convention adapter, table-shapes the matchers, and defers the PowerShell grammar until an empirical finding confirms which shell the Windows Bash tool emits. Backs the shell_detect handoff on this branch. 0008 is intentionally reserved for the hook-entry consolidation ADR, which lands with its own PR. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
On Windows, Claude Code routes shell file ops through a distinct `PowerShell`
tool (the Haiku model deletes via `Remove-Item`, moves via `Move-Item`, writes
via `Set-Content`/`Out-File`), and the detector understood only POSIX commands +
Unix paths — so shell deletes/writes never marked neo-tree. STEP 0 ground truth
captured on the Windows box corrected the original macOS-written premise: it is
a SEPARATE tool, not the Bash tool emitting PowerShell, and the hook matcher
never fired for it.
Three layers:
- matcher: add `PowerShell` to the claudecode Pre/PostToolUse matchers so the
hook fires for those proposals at all.
- normaliser: fold tool_name="PowerShell" onto canonical Bash (shell proposal,
Tier-1 indicator-only, bash_* origin prefix) — no dispatcher/emitter change,
no permission gate.
- shell_detect (renamed from bash_detect): split the two axes the architecture
review identified —
* OS-selected path adapter: Unix (byte-identical) + Windows (C:\, C:/, UNC,
backslash, relative-vs-backslash-cwd). Emits canonical backslash to match
the registry keys Edit/Write use, since fnamemodify(":p") is a no-op on an
already-absolute Windows path.
* additive PowerShell grammar: Remove-Item/Set-Content/Out-File/Add-Content/
Move-Item/Copy-Item (+ aliases), -Path/-Destination/positional, comma-list
arrays (incl. spaces after commas) and here-strings. POSIX behaviour is
unchanged (PS verbs never collide with POSIX-handled rm/cp/mv/tee).
Also: diff.lua git reveal -> list-form systemlist (drop POSIX-only 2>/dev/null).
Tests: spec renamed to pre_tool_shell_detect_spec.lua with OS-branched rows
(POSIX pending on Windows; Windows + PowerShell rows from real samples, incl.
multi-delete comma-list regression); pending bash_modified case re-enabled
portably; normaliser + install specs updated; CI windows-test exclusion dropped.
Verified end-to-end on Windows: single and multi-file PowerShell deletes mark
neo-tree with correct backslash paths.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tion (#46) The deferral in ADR-0009 is closed: STEP 0 landed and the PowerShell grammar shipped in the same PR as the axis split. Append a resolution note correcting the two premises the original text got wrong — it is a separate `PowerShell` tool (not the Bash tool emitting PowerShell), so routing was NOT fine and a matcher + normaliser layer were needed on top of the detection split — and record what shipped for the detection layer, including the honest scope note that the POSIX matchers were not refactored into a unified grammar table. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Retitle ADR-0009 to "splits path-convention from command-grammar" (drop "defer grammar": the grammar shipped with the split, so the deferral framing never described a real shipped state). Rewrite as one coherent decision — fold in the STEP 0 premise corrections (distinct PowerShell tool; the matcher + normaliser layers) and the scope-honesty note. Fix stale bash_detect references to shell_detect. - Remove HANDOFF-shell-detect.md: a cross-machine scratchpad, now consumed (findings live in the ADR, the spec's real-sample rows, and code comments). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jun 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to the merged claudecode Windows slice (#73). Fixes the reported bug: on Windows, deleting/writing a file via the shell did not mark neo-tree.
Root cause (STEP 0, gathered on a real Windows box)
Claude Code on Windows exposes a distinct
PowerShelltool alongsideBashand routes shell file ops through it (the Haiku model deletes viaRemove-Item, moves viaMove-Item, writes viaSet-Content/Out-File).tool_nameis"PowerShell"with a Bash-shaped{command}payload. Two things were wrong, not one:Edit|Write|MultiEdit|Bash) never matchedPowerShell, so the hook never fired.rmwith Windows paths), the detector was Unix-path-only.The fix — three layers
PowerShell(harmless on Unix; no such tool there).tool_name="PowerShell"→ canonicalBash, so the dispatcher/emitters/detector need no awareness of a separate tool.bash_detect.lua→shell_detect.lua, behind the unchangedM.detect): split into two independent axes per ADR-0009 —C:\/C:/, UNC, backslashes, relative-against-backslash-cwd, canonical backslash output);Remove-Item/Set-Content/Out-File/Add-Content/Move-Item/Copy-Item+ aliases,-Path/-Destination/positional, comma-lists, here-strings). POSIX stays byte-identical — the PS tables exclude the bash aliases, so the vocabularies never collide.Also:
diff.luagit-root reveal switched to list-formsystemlist(drops the POSIX-only2>/dev/nullthat misbehaves under Windows cmd).Testing
shell_detectspec = 58, normaliser = 38, etc.). POSIX rows run on Unix.windows-test): now runs the wholetests/plugindir (the old bash_detect exclusion is removed); the spec's Windows rows (real Haiku samples — comma-lists, here-strings, UNC, aliases, Move/Copy) execute there. This PR'swindows-testrun is the first CI validation of those rows.test_install.shupdated to assert the new matcher (stricter, not looser).Docs
Known scope / minor follow-up
detect_ps()also runs on Unix. Harmless for known cases (PS tables exclude bash aliases), but a Unix command whose first word isdel/move/copy/etc. could yield a spurious Tier-1 indicator. Vanishingly rare; could be gated behindis_windows()in a later pass.🤖 Generated with Claude Code