[PR #4944] [MERGED] fix(setup): admit only strict JSON for Claude Code configuration #6684

Closed
opened 2026-11-01 21:42:16 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/4944
Author: @kaoru0822-kitauji
Created: 10/18/2026
Status: ✅ Merged
Merged: 10/18/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: fix/claude-code-strict-json-config


📝 Commits (1)

  • 877c202 fix(setup): admit only strict JSON for Claude Code configuration

📊 Changes

5 files changed (+227 additions, -78 deletions)

View changed files

📝 src/application/ClientConfigurationDocument.ts (+7 -0)
📝 src/application/SupportedClients.ts (+2 -1)
➕ tests/acceptance/setup/claudeCodeStrictJsonSetup.test.ts (+128 -0)
📝 tests/boundary/filesystem/clientConfigurationBom.test.ts (+79 -74)
📝 tests/boundary/filesystem/windowsNpxRegistration.test.ts (+11 -3)

📄 Description

Summary

Fixes #4940. Claude Code setup reported ready for a .claude.json with a comment or trailing comma, kept that syntax in the file it wrote, and doctor then reported the registration aligned. The issue reporter found that native Claude Code rejects such a file as corrupt JSON. With this change, setup, doctor and uninstall refuse those files as malformed before writing anything or creating a backup. Plain JSON and BOM-prefixed JSON still configure.

Problem and expected behavior

Trigger: .claude.json = { // comment\n "mcpServers": {...} } (or a trailing comma). Claude Code shared the generic json client format. parseDocument reads that format through jsonc-parser with comments and trailing commas enabled. The broken rule: setup must not admit configuration the selected native client cannot load. Expected: needs_human with no write or backup, and doctor reporting the registration invalid rather than aligned.

Change and scope

  • SupportedClients.ts: Claude Code now uses its own claude_code configuration format instead of json.
  • ClientConfigurationDocument.ts (parseDocument): the new format is parsed with strict JSON.parse after removing a leading UTF-8 BOM. This matches the native behavior described in the issue and follows the existing per-client strict readers (Pi, Kimi, ZCode). Setup, doctor and uninstall already use this parser, so no downstream changes are needed.
  • Registration entries, server key and serialization still fall through to the defaults the json format used.
  • Not included: other json-format clients (Cursor, Claude Desktop, Windsurf, etc.) keep JSONC admission. Their native readers were not re-examined here. Empty-file handling for Claude Code is unchanged.
  • Contribution scope: not applicable (ordinary fix within existing setup boundaries).

Contract and boundary impact

  • Semantic owner and earliest changed stage: parseDocument in src/application/ClientConfigurationDocument.ts, selected by the client's format in SupportedClients.ts.

  • Contribution scope fit and linked maintainer decision: not applicable.

  • CLI and MCP/tool-catalog contract: setup's clientStates[].client.format for Claude Code changes from "json" to "claude_code". No tool catalog changes.

  • Provider, bridge, target-format, or platform compatibility: none.

  • Evidence, artifact, provenance, or reconstruction contract: none.

  • Target selection, authority, upstream behavior, and cleanup details: not applicable.

  • Generated metadata: setup_clients[].format for claude_code in the generated product catalog becomes "claude_code". npm run docs:check passes.

  • Read existing files or captured data.

  • Change process memory, registers, files, or configuration. (Only refusals change: fewer writes than before.)

Evidence and regression coverage

  • Tests added or updated:
    • New tests/acceptance/setup/claudeCodeStrictJsonSetup.test.ts (public CLI):
      • Comment and trailing-comma fixtures: setup --dry-run and --yes return needs_human with a "malformed" remediation, doctor reports invalid, uninstall reports failed, file bytes are unchanged and no .rea.backup exists.
      • Plain and BOM-prefixed JSON: setup returns configured, the backup is byte-exact, the BOM is kept, the output passes JSON.parse, and doctor reports aligned.
    • tests/boundary/filesystem/clientConfigurationBom.test.ts: removed claude_code from the comment-preserving JSONC matrix, which encoded the bug.
    • tests/boundary/filesystem/windowsNpxRegistration.test.ts: Claude Code fixtures now use the claude_code format.
  • Base reproduction:
    • On base 847472acf, node scripts/rea.mjs setup --client claude_code --skill=false --dry-run --json with HOME/CLAUDE_CONFIG_DIR pointed at an isolated directory holding the issue's fixture returned planned, exit 0. With this change it returns needs_human, exit 1.
    • With the source fix reverted, the new acceptance test fails both refusal cases (2 failed, 2 passed).
  • Remaining proof gaps: native Claude Code was not run. The strict-JSON behavior comes from the issue reporter's observation with Claude Code 2.1.263. Only macOS was tested.

Validation performed

  • npm run test:focused -- tests/acceptance/setup/claudeCodeStrictJsonSetup.test.ts tests/boundary/filesystem/clientConfigurationBom.test.ts tests/boundary/filesystem/windowsNpxRegistration.test.ts tests/acceptance/setup/clientConfigurationDiagnosticsCli.test.ts tests/boundary/filesystem/clientConfigurationDialects.test.ts tests/boundary/filesystem/clientLifecycle.test.ts tests/boundary/filesystem/clientRegistrationStatus.test.ts tests/boundary/filesystem/productCatalog.test.ts: 8 files passed, 167 passed, 2 skipped (Windows-only)
  • The same focused run of the new acceptance test with the source fix reverted: 2 failed, 2 passed (expected)
  • npm run check:fast: passed
  • npm run docs:check: passed
  • npx oxfmt --check on the changed files: passed
  • Issue reproduction CLI command, before and after: planned/exit 0 before, needs_human/exit 1 after

Compatibility, safety, and release

  • Breaking changes or migration steps: none intended. A Claude Code config with comments or trailing commas, which Claude Code itself reportedly rejects, is now refused instead of edited.
  • Real Hopper/Ghidra, browser, or OS coverage: not applicable. macOS only. Native Claude Code not run.
  • Package or release metadata impact: the product catalog format value for claude_code changes.
  • Security, privacy, process, or containment review: refusals happen before any write or backup.

Author readiness

Human owner:

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/4944 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/18/2026 **Status:** ✅ Merged **Merged:** 10/18/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/claude-code-strict-json-config` --- ### 📝 Commits (1) - [`877c202`](https://github.com/morluto/rea/commit/877c2022cdea14371a295ec1cb03be41da8dfba2) fix(setup): admit only strict JSON for Claude Code configuration ### 📊 Changes **5 files changed** (+227 additions, -78 deletions) <details> <summary>View changed files</summary> 📝 `src/application/ClientConfigurationDocument.ts` (+7 -0) 📝 `src/application/SupportedClients.ts` (+2 -1) ➕ `tests/acceptance/setup/claudeCodeStrictJsonSetup.test.ts` (+128 -0) 📝 `tests/boundary/filesystem/clientConfigurationBom.test.ts` (+79 -74) 📝 `tests/boundary/filesystem/windowsNpxRegistration.test.ts` (+11 -3) </details> ### 📄 Description ## Summary Fixes #4940. Claude Code setup reported `ready` for a `.claude.json` with a comment or trailing comma, kept that syntax in the file it wrote, and doctor then reported the registration `aligned`. The issue reporter found that native Claude Code rejects such a file as corrupt JSON. With this change, setup, doctor and uninstall refuse those files as malformed before writing anything or creating a backup. Plain JSON and BOM-prefixed JSON still configure. ## Problem and expected behavior Trigger: `.claude.json` = `{ // comment\n "mcpServers": {...} }` (or a trailing comma). Claude Code shared the generic `json` client format. `parseDocument` reads that format through `jsonc-parser` with comments and trailing commas enabled. The broken rule: setup must not admit configuration the selected native client cannot load. Expected: `needs_human` with no write or backup, and doctor reporting the registration `invalid` rather than `aligned`. ## Change and scope - `SupportedClients.ts`: Claude Code now uses its own `claude_code` configuration format instead of `json`. - `ClientConfigurationDocument.ts` (`parseDocument`): the new format is parsed with strict `JSON.parse` after removing a leading UTF-8 BOM. This matches the native behavior described in the issue and follows the existing per-client strict readers (Pi, Kimi, ZCode). Setup, doctor and uninstall already use this parser, so no downstream changes are needed. - Registration entries, server key and serialization still fall through to the defaults the `json` format used. - Not included: other `json`-format clients (Cursor, Claude Desktop, Windsurf, etc.) keep JSONC admission. Their native readers were not re-examined here. Empty-file handling for Claude Code is unchanged. - Contribution scope: not applicable (ordinary fix within existing setup boundaries). ## Contract and boundary impact - Semantic owner and earliest changed stage: `parseDocument` in `src/application/ClientConfigurationDocument.ts`, selected by the client's format in `SupportedClients.ts`. - Contribution scope fit and linked maintainer decision: not applicable. - CLI and MCP/tool-catalog contract: setup's `clientStates[].client.format` for Claude Code changes from `"json"` to `"claude_code"`. No tool catalog changes. - Provider, bridge, target-format, or platform compatibility: none. - Evidence, artifact, provenance, or reconstruction contract: none. - Target selection, authority, upstream behavior, and cleanup details: not applicable. - Generated metadata: `setup_clients[].format` for `claude_code` in the generated product catalog becomes `"claude_code"`. `npm run docs:check` passes. - [x] Read existing files or captured data. - [x] Change process memory, registers, files, or configuration. (Only refusals change: fewer writes than before.) ## Evidence and regression coverage - Tests added or updated: - New `tests/acceptance/setup/claudeCodeStrictJsonSetup.test.ts` (public CLI): - Comment and trailing-comma fixtures: setup `--dry-run` and `--yes` return `needs_human` with a "malformed" remediation, doctor reports `invalid`, uninstall reports `failed`, file bytes are unchanged and no `.rea.backup` exists. - Plain and BOM-prefixed JSON: setup returns `configured`, the backup is byte-exact, the BOM is kept, the output passes `JSON.parse`, and doctor reports `aligned`. - `tests/boundary/filesystem/clientConfigurationBom.test.ts`: removed `claude_code` from the comment-preserving JSONC matrix, which encoded the bug. - `tests/boundary/filesystem/windowsNpxRegistration.test.ts`: Claude Code fixtures now use the `claude_code` format. - Base reproduction: - On base `847472acf`, `node scripts/rea.mjs setup --client claude_code --skill=false --dry-run --json` with `HOME`/`CLAUDE_CONFIG_DIR` pointed at an isolated directory holding the issue's fixture returned `planned`, exit 0. With this change it returns `needs_human`, exit 1. - With the source fix reverted, the new acceptance test fails both refusal cases (2 failed, 2 passed). - Remaining proof gaps: native Claude Code was not run. The strict-JSON behavior comes from the issue reporter's observation with Claude Code 2.1.263. Only macOS was tested. ## Validation performed - `npm run test:focused -- tests/acceptance/setup/claudeCodeStrictJsonSetup.test.ts tests/boundary/filesystem/clientConfigurationBom.test.ts tests/boundary/filesystem/windowsNpxRegistration.test.ts tests/acceptance/setup/clientConfigurationDiagnosticsCli.test.ts tests/boundary/filesystem/clientConfigurationDialects.test.ts tests/boundary/filesystem/clientLifecycle.test.ts tests/boundary/filesystem/clientRegistrationStatus.test.ts tests/boundary/filesystem/productCatalog.test.ts`: 8 files passed, 167 passed, 2 skipped (Windows-only) - The same focused run of the new acceptance test with the source fix reverted: 2 failed, 2 passed (expected) - `npm run check:fast`: passed - `npm run docs:check`: passed - `npx oxfmt --check` on the changed files: passed - Issue reproduction CLI command, before and after: `planned`/exit 0 before, `needs_human`/exit 1 after ## Compatibility, safety, and release - Breaking changes or migration steps: none intended. A Claude Code config with comments or trailing commas, which Claude Code itself reportedly rejects, is now refused instead of edited. - Real Hopper/Ghidra, browser, or OS coverage: not applicable. macOS only. Native Claude Code not run. - Package or release metadata impact: the product catalog format value for `claude_code` changes. - Security, privacy, process, or containment review: refusals happen before any write or backup. ## Author readiness Human owner: - [ ] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [ ] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [ ] I declare this PR ready for initial maintainer review. ## Before merge - [ ] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [ ] The PR has one focused outcome and the title follows `type(scope): outcome`. - [ ] Related issue is linked, or the reason for not linking one is stated above. - [ ] Tests cover changed observable behavior and meaningful failure paths. - [ ] Owning docs, contracts, and generated metadata are updated where needed. - [ ] User-visible CLI/MCP changes include representative output. - [ ] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-01 21:42:16 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#6684
No description provided.