Skip to content

bug: Claude Code hooks broken — invalid schema + .sh not portable to Windows #46

Description

@koalashena

Description

.claude/settings.json has two problems that prevent the check-file-length.sh PostToolUse hook from running:

1. Invalid hooks schema

The config uses "hook" (singular string) instead of the required "hooks" (array of command objects). Claude Code skips the entire file on validation failure, so no hooks run at all.

// Current — "hook" is not a valid property
{
  "matcher": "Write|Edit",
  "hook": "scripts/hooks/check-file-length.sh"
}

// Correct — "hooks" array with type + command
{
  "matcher": "Write|Edit",
  "hooks": [
    { "type": "command", "command": "scripts/hooks/check-file-length.sh" }
  ]
}

2. Shell script not portable to Windows

The hook is a .sh bash script. On Windows, this has several known issues (anthropics/claude-code#23556, anthropics/claude-code#18610, anthropics/claude-code#24097):

  • Claude Code may resolve bash to WSL's bash.exe instead of Git Bash
  • .sh files may open in an editor instead of executing
  • No .gitattributes exists, so Git on Windows converts LF → CRLF, breaking the shebang

The original setup was done on macOS where none of these surface.

Steps to reproduce

  1. Clone the repo on Windows
  2. Open Claude Code
  3. See startup warning:
    .claude/settings.json
       └ hooks → PostToolUse → 0 → hooks: Expected array, but received undefined
    Files with errors are skipped entirely, not just the invalid settings.
    
  4. Edit any .tsx file — the 250-line limit hook does not fire

Expected behavior

The check-file-length.sh hook should run after every Write|Edit on all platforms, blocking files over 250 lines.

Suggested fix

  1. Fix the schema — rename hookhooks array with { type, command } objects
  2. Rewrite the hook as a Node.js script (check-file-length.js) for cross-platform portability
  3. Add .gitattributes with *.sh text eol=lf to prevent CRLF corruption

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingchoreDependencies, CI, configp1:highP1 — do this sprintsize:sSmall — a few hours

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    In Review

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions