Skip to content

fix: make the Read hook work on Windows - #5

Open
learte4 wants to merge 1 commit into
silverlogic:mainfrom
learte4:fix/windows-crlf-and-separators
Open

fix: make the Read hook work on Windows#5
learte4 wants to merge 1 commit into
silverlogic:mainfrom
learte4:fix/windows-crlf-and-separators

Conversation

@learte4

@learte4 learte4 commented Aug 11, 2026

Copy link
Copy Markdown

On Windows the plugin silently records nothing. The hook runs, exits 0, and never writes a line — so .skill-observer/logs/skills.jsonl stays empty forever and there is no error to point at.

Two causes, both in main() of scripts/skill-tracker.sh:

  1. jq.exe emits CRLF. Every value read out of the jq -r block carries a trailing \r, so tool_name is "Read\r". The [[ "${tool_name}" == "Read" ]] guard never matches and the script exits before reaching any logging code.
  2. file_path arrives with backslashes (D:\proj\.claude\skills\foo\SKILL.md), which never match the *".claude/skills/"* pattern in the guard below it.

Either one alone is enough to kill logging; together they make it look like the hook simply isn't registered.

Fix

Strip the CR from the five values, and normalize the separators before the path guard:

tool_name="${tool_name%$'\r'}" file_path="${file_path%$'\r'}"
session_id="${session_id%$'\r'}" offset="${offset%$'\r'}" limit="${limit%$'\r'}"
[[ "${tool_name}" == "Read" ]] || exit 0
file_path="${file_path//\\//}"

Both are no-ops on macOS and Linux: there is no CR to strip and no backslash to replace. ${var%$'\r'} removes at most one trailing CR and leaves LF-only values untouched.

Reproducing

On Windows with Git Bash, read any SKILL.md under .claude/skills/ with the hook installed. Before this change the log file is never created; after it, the skill_loaded event appears as expected.

I have been running this patch locally since 2026-07-17 across a few dozen sessions, which is how the second issue in the pair surfaced — fixing only the CRLF gets you past the tool_name guard and straight into the backslash one.

Related: I opened a separate PR for an unrelated performance issue in the same function. The two touch different lines a few apart; whichever lands first, the other needs at most a trivial rebase.

On Windows the hook silently logged nothing. Two causes, both in main():

- jq.exe emits CRLF, so every value read from its output carried a trailing
  \r. The `tool_name == "Read"` guard therefore never matched and the script
  exited before reaching any logging code.
- file_path arrives with backslash separators, which never match the
  `*".claude/skills/"*` pattern.

Strip the CR from all five values and normalize the separators before the
guards. No behavior change on macOS/Linux, where neither condition occurs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant