settings.json rewritten with only {env, statusLine} model — drops hooks key (440 captured occurrences)

Status Open
Reported on v2.1.207
Maintainer reply None cached
Activity 0 comments · opened Jul 17, 2026

Summary

Some settings writer in the Claude Code ecosystem repeatedly rewrites ~/.claude/settings.json as a whole-file write containing ONLY its own model of the file — dropping every other top-level key, most damagingly hooks (which silently disables a user's entire hook layer until manually restored).

Environment

  • Claude Code 2.1.207, macOS (darwin 23.6.0)
  • settings.json normally carries: hooks (6 events), env, statusLine, model, permissions etc.
  • statusLine is configured to a local command (claude-hud) via the standard statusLine.type=command config.

Evidence (1s-interval file watcher, snapshot on every mtime change, 3 days)

440 captured writes lacking the hooks key, in exactly two shapes:

Shape A — 148 bytes, env only (proxy keys, empty values):

{"env": {"HTTP_PROXY": "", "HTTPS_PROXY": "", "http_proxy": "", "https_proxy": "", "NO_PROXY": "", "no_proxy": ""}}

Shape B — 309 bytes, env + statusLine only:

{"statusLine": {"type": "command", "command": "\"/opt/homebrew/bin/node\" \"<home>/.../claude-hud/dist/index.js\""},
 "env": {"HTTP_PROXY": "", "HTTPS_PROXY": "", "http_proxy": "", "https_proxy": "", "NO_PROXY": "", "no_proxy": ""}}

Occurrences are spread around the clock (00:19, 02:04, 03:19, 07:19, 15:02, 23:56, …), including while multiple Claude Code sessions run concurrently.

Additional data point: a whole-file write that GAINED a model key (triggered by running /model in another session) PRESERVED hooks — so at least one writer merges correctly; the Shape A/B writer does not.

Impact

Every Shape A/B write silently kills all configured hooks (SessionStart/Stop/PreToolUse/PostToolUse/ConfigChange/InstructionsLoaded) until the user notices. We caught it twice by hand (once after 2 days of silent loss) before instrumenting; the watcher has since auto-restored 440 times.

Attribution uncertainty (stated honestly)

The two shapes look like an internal "managed settings" model (proxy env + statusLine) being serialized wholesale. We cannot tell from outside whether the writer is Claude Code's own settings subsystem (e.g. the statusline/config path) or a concurrent-session state sync — but the write pattern (whole-file replace with only known-to-writer keys, no read-merge-write) is the defect regardless of which component owns it.

Ask

Settings writers should read-merge-write (preserve unknown top-level keys) rather than serialize their own model wholesale — one writer in this install already behaves correctly (the /model path), so the fix pattern exists in-tree.

Repro sketch

  1. Configure hooks + a command statusLine in ~/.claude/settings.json.
  2. Run 2+ concurrent Claude Code sessions; watch the file at 1s resolution (stat -f %m loop, snapshot on change).
  3. Within hours, whole-file writes matching Shape A/B appear with hooks gone.

View original on GitHub ↗