Skip to content

Conversation

@ooples
Copy link
Owner

@ooples ooples commented Oct 30, 2025

Problem

PowerShell's Set-Content -Encoding UTF8 adds a UTF-8 BOM (Byte Order Mark: EF BB BF) to files, which breaks JSON parsers and causes Claude Code to show this error:

Invalid Settings C:\Users\username\.claude\settings.json └ Invalid or malformed JSON 

This makes Claude Code completely unusable after running the hook installation script.

Impact

Any user who runs install-hooks.ps1 will have their Claude Code settings corrupted with UTF-8 BOM, preventing Claude Code from starting.

Affected files:

  • C:\Users\username\.claude\settings.json (Claude Code main config)
  • C:\Users\username\.claude\state.json (workspace trust state)
  • Claude Desktop, Cursor, Cline, VS Code, and Windsurf config files

Solution

Replace all instances of Set-Content -Encoding UTF8 with a BOM-free write method:

Before (adds BOM):

$settings | ConvertTo-Json -Depth 10 | Set-Content $file -Encoding UTF8

After (no BOM):

$json = $settings | ConvertTo-Json -Depth 10 [System.IO.File]::WriteAllText($file, $json, (New-Object System.Text.UTF8Encoding $false))

The $false parameter prevents the BOM from being added.

Changes

Fixed 7 locations in install-hooks.ps1:

  1. Line 219-220: $CLAUDE_SETTINGS (Claude Code main config)
  2. Line 259-260: $CLAUDE_STATE (workspace trust state)
  3. Line 288-289: $claudeDesktopConfig (Claude Desktop)
  4. Line 311-312: $cursorConfig (Cursor IDE)
  5. Line 340-341: $clineConfig (Cline/VS Code)
  6. Line 363-364: $vscodeWorkspaceConfig (VS Code workspace)
  7. Line 386-387: $windsurfConfig (Windsurf IDE)

Testing

Added test-bom-fix.ps1 with comprehensive verification:

Test Results

[TEST 1] Writing JSON with BOM-free method... [PASS] File does NOT have BOM First 10 bytes: 7B 0D 0A 20 20 20 20 22 6E 75 [TEST 2] Verifying JSON is valid... [PASS] JSON is valid and parseable [TEST 3] Comparing with OLD method (Set-Content -Encoding UTF8)... [INFO] OLD method DOES add BOM (as expected) First 10 bytes: EF BB BF 7B 0D 0A 20 20 20 20 [TEST 4] Verifying file is compatible with JSON parsers... [PASS] Node.js JSON parser accepts the file ======================================== ALL TESTS PASSED ======================================== 

Hex Dump Comparison

OLD method (with BOM) - BREAKS JSON:

EF BB BF 7B 0D 0A ... ^^^^^^^ └ Opening brace └ UTF-8 BOM (causes JSON parse errors) 

NEW method (no BOM) - WORKS:

7B 0D 0A 20 20 20 ... └ Opening brace (valid JSON) 

Verification

To verify this fix locally:

cd ~/source/repos/token-optimizer-mcp git checkout fix/install-hooks-bom-issue .\test-bom-fix.ps1

All tests should pass with [PASS] status.

Priority

CRITICAL - This bug prevents Claude Code from functioning after hook installation.

@github-actions
Copy link

Commit Message Format Issue

Your commit messages don't follow the Conventional Commits specification.

Required Format:

<type>(<optional scope>): <description> [optional body] [optional footer] 

Valid Types:

  • feat: A new feature
  • fix: A bug fix
  • docs: Documentation only changes
  • style: Changes that don't affect code meaning (white-space, formatting)
  • refactor: Code change that neither fixes a bug nor adds a feature
  • perf: Code change that improves performance
  • test: Adding missing tests or correcting existing tests
  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Other changes that don't modify src or test files
  • revert: Reverts a previous commit

Examples:

feat(auth): add OAuth2 authentication fix(api): resolve race condition in token refresh docs(readme): update installation instructions refactor(core): simplify token optimization logic 

Breaking Changes:

Add BREAKING CHANGE: in the footer or append ! after the type:

feat!: remove deprecated API endpoints 

Please amend your commit messages to follow this format.

Learn more: Conventional Commits

1 similar comment
@github-actions
Copy link

Commit Message Format Issue

Your commit messages don't follow the Conventional Commits specification.

Required Format:

<type>(<optional scope>): <description> [optional body] [optional footer] 

Valid Types:

  • feat: A new feature
  • fix: A bug fix
  • docs: Documentation only changes
  • style: Changes that don't affect code meaning (white-space, formatting)
  • refactor: Code change that neither fixes a bug nor adds a feature
  • perf: Code change that improves performance
  • test: Adding missing tests or correcting existing tests
  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Other changes that don't modify src or test files
  • revert: Reverts a previous commit

Examples:

feat(auth): add OAuth2 authentication fix(api): resolve race condition in token refresh docs(readme): update installation instructions refactor(core): simplify token optimization logic 

Breaking Changes:

Add BREAKING CHANGE: in the footer or append ! after the type:

feat!: remove deprecated API endpoints 

Please amend your commit messages to follow this format.

Learn more: Conventional Commits

@coderabbitai
Copy link

coderabbitai bot commented Oct 30, 2025

Warning

Rate limit exceeded

@ooples has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 12 minutes and 59 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between af0463e and 251c655.

📒 Files selected for processing (2)
  • install-hooks.ps1 (7 hunks)
  • test-bom-fix.ps1 (1 hunks)

Summary by CodeRabbit

  • Bug Fixes

    • Resolved JSON file encoding format to ensure compatibility with standard UTF-8 without byte order marks.
  • Tests

    • Added validation testing to verify JSON file encoding standards.

Walkthrough

The changes refactor JSON output handling in install-hooks.ps1 to write files without UTF-8 Byte Order Mark (BOM) using [System.IO.File]::WriteAllText. A new test script validates this BOM-free encoding and compares against the previous Set-Content method.

Changes

Cohort / File(s) Summary
Encoding refactor
install-hooks.ps1
Replaced piping JSON to Set-Content with [System.IO.File]::WriteAllText using UTF-8 encoding without BOM; computes JSON into variables and writes via WriteAllText($path, $json, new UTF8Encoding(false)) while preserving existing messaging and ConvertTo-Json depth
Test coverage
test-bom-fix.ps1
New PowerShell test script that validates JSON output lacks UTF-8 BOM by checking file header bytes, verifies JSON parseability, compares new method against legacy Set-Content -Encoding UTF8 approach, optionally tests parsing via Node.js, and reports PASS/FAIL status with cleanup

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • install-hooks.ps1: Verify all JSON write operations are consistently refactored with correct encoding parameters and variable assignments
  • test-bom-fix.ps1: Validate test logic for BOM detection (byte inspection at file start), error handling, and comparison methodology against the legacy approach

Possibly related PRs

Poem

🐰 A byte-order mark, so tiny yet vain,
Found lurking at file-starts, causing refrain,
But now with UTF-8 stripped clean and bright,
Our PowerShell scripts write JSON just right! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "fix: prevent BOM in JSON files written by install-hooks.ps1" clearly and directly describes the main change in the changeset. The title accurately summarizes the primary fix—preventing UTF-8 BOM insertion in JSON files—and specifies the affected script. It is concise, specific, and follows conventional commit format, making it clear to anyone reviewing the project history what the core change addresses.
Description Check ✅ Passed The pull request description is comprehensive and contains all substantive required information: a clear problem statement explaining the BOM issue and its impact, specific details of the seven locations changed in install-hooks.ps1, thorough testing information with test results and hex dump comparisons, and verification instructions. However, the description does not follow the required template structure—it lacks the Type of Change checkboxes, Related Issues section, formal Checklist, Commit Message Convention confirmation, and Performance Impact section. While the content quality is strong, the structural deviation from the template represents incomplete template compliance.

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

Performance Benchmark Results

 
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test-bom-fix.ps1 (1)

105-107: Consider using try-finally for guaranteed cleanup.

The cleanup code won't run if any test fails and exits early (lines 53, 68, 72, 99). While not critical for a test script, wrapping the tests in a try-finally block would ensure the temp directory is always removed.

Example structure:

try { # All tests here } finally { if (Test-Path $testDir) { Remove-Item $testDir -Recurse -Force } }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 14ddecd and af0463e.

📒 Files selected for processing (2)
  • install-hooks.ps1 (7 hunks)
  • test-bom-fix.ps1 (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test (Node 18)
  • GitHub Check: Test (Node 20)
🔇 Additional comments (1)
install-hooks.ps1 (1)

218-220: Excellent fix for the BOM issue!

The implementation correctly uses [System.IO.File]::WriteAllText with UTF8Encoding($false) to write JSON files without a Byte Order Mark. The $false parameter disables encoderShouldEmitUTF8Identifier, ensuring BOM-free UTF-8 output that JSON parsers can handle correctly.

All seven locations follow a consistent pattern:

  1. Serialize the object to JSON with ConvertTo-Json
  2. Write using WriteAllText with BOM-free UTF-8 encoding
  3. Properly guarded by DryRun checks and wrapped in try-catch blocks where appropriate

This resolves the critical issue where Set-Content -Encoding UTF8 was adding a BOM (EF BB BF) that broke Claude Code settings.

Also applies to: 259-260, 288-289, 311-312, 340-341, 363-364, 386-387

**Problem**: PowerShell's `Set-Content -Encoding UTF8` adds a UTF-8 BOM (Byte Order Mark: EF BB BF) to files, which breaks JSON parsers and causes Claude Code to show "Invalid or malformed JSON" errors. **Impact**: Users cannot use Claude Code after running install-hooks because settings.json becomes unparseable. **Root Cause**: 7 locations in install-hooks.ps1 used: ```powershell $settings | ConvertTo-Json -Depth 10 | Set-Content $file -Encoding UTF8 ``` **Solution**: Replace all instances with BOM-free write method: ```powershell $json = $settings | ConvertTo-Json -Depth 10 [System.IO.File]::WriteAllText($file, $json, (New-Object System.Text.UTF8Encoding $false)) ``` The third parameter `$false` prevents BOM from being added. **Changes**: - Fixed 7 JSON write operations in install-hooks.ps1 - Added test-bom-fix.ps1 to verify no BOM is added - All tests pass confirming the fix works **Testing**: Run `pwsh test-bom-fix.ps1` to verify: - NEW method does NOT add BOM (7B 0D 0A...) - OLD method DOES add BOM (EF BB BF 7B...) - JSON remains valid and parseable Fixes: Users unable to use Claude Code after hook installation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
@ooples ooples force-pushed the fix/install-hooks-bom-issue branch from af0463e to a86391a Compare October 30, 2025 19:01
@github-actions
Copy link

Performance Benchmark Results

 
CodeRabbit correctly identified that Test 4 was only reading the file as a Buffer and would pass even if JSON was malformed. **Changes**: - Added JSON.parse() to actually parse the file content - Added 'utf8' encoding parameter to readFileSync() - Test now properly verifies JSON parsability, not just file readability This ensures the test catches malformed JSON that would break Claude Code. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions
Copy link

Performance Benchmark Results

 
@ooples ooples merged commit 291e58a into master Oct 30, 2025
16 checks passed
@ooples ooples deleted the fix/install-hooks-bom-issue branch October 30, 2025 19:18
@github-actions
Copy link

This PR is included in version 3.0.2. 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2 participants