v5.5.2
Fixed — tests/terse-hooks-shell.test.ts flaked on Windows runners
"less tokens please" activates the default mode failed intermittently
on windows-latest, Node 20 with ENOENT reading
.rulebook/.terse-mode, even though the hook had written it
successfully (CI run #25346776699). Root cause: the hook writes via
mktemp + mv -f; on GitHub-hosted Windows runners, antivirus / filter
drivers can briefly hold the renamed file invisible to other processes
after MoveFileExW returns success. macOS, Linux, and faster Windows
runners win the race; the slow Windows-Node20 runner occasionally
loses it.
Fix: replaced every readFileSync(...) after a run() in
tests/terse-hooks-shell.test.ts with a readFlag() helper that polls
existsSync up to ~1s before reading. No-op cost on POSIX.
Fixed — rulebook init produced CRLF shell scripts that broke Claude Code on macOS/Linux
Twelve .sh templates in templates/ were stored on disk with CRLF
line terminators despite .gitattributes declaring *.sh text eol=lf.
On macOS/Linux, bash interprets a trailing \r as part of the command
(set -\r u is invalid, function() {\r fails to parse), so every
hook crashed at session start. Because three of the affected hooks fire
on SessionStart, UserPromptSubmit, and Stop, Claude Code became
completely unresponsive — the user reported zero assistant responses
across a full session.
Root cause: templates were authored on Windows and committed without
honoring the .gitattributes rule, so the npm package shipped CRLF
bytes verbatim.
Fix:
- Re-normalized twelve template files to LF
(templates/hooks/{terse-activate,terse-mode-tracker,resume-from-handoff,on-compact-reinject,check-context-and-handoff,enforce-team-for-background-agents}.sh,
templates/ralph/ralph-{init,run,status,pause,history}.sh,
templates/skills/workflows/ralph/install.sh). - Defense in depth in init: new
writeShellScript/
normalizeLineEndingshelpers insrc/utils/file-system.ts. Wired
intoclaude-settings-manager.ts(hook installation),
ralph-scripts.ts(Ralph script copy), andgit-hooks.ts
(pre-commit/pre-push wrappers). Every.shwritten byrulebook initis now guaranteed LF, regardless of how the template is stored
on disk. POSIX writes also set mode0o755. - CI guard:
scripts/check-sh-eol.mjs(run vianpm run check:sh-eol) fails CI if any tracked*.sh/*.bashfile under
templates/orscripts/contains a CR byte. Wired into
.github/workflows/lint.ymlso a regression cannot reach a
published version again. - Regression tests in
tests/file-system.test.ts,
tests/claude-settings-manager.test.ts, and
tests/ralph-scripts.test.tsassert zero CR bytes in every emitted
.shfile.
Affected versions: 5.4.x and 5.5.x. Workaround for already-installed
projects: tr -d '\r' < hook.sh > hook.sh.tmp && mv hook.sh.tmp hook.sh && chmod +x hook.sh for each broken script in .claude/hooks/.