settings.json read-modify-write race: /model save in one session clobbers another session's /effort save

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

Summary

With two Claude Code processes running, a /model save in one session appears to rewrite ~/.claude/settings.json from the settings that process loaded at startup, silently reverting an effortLevel another session had saved in the meantime. Result: the file no longer reflects any user intent, and — on 2.1.211, where transcripts carried no effort field — the effort a subsequent long automated run actually executed at was unrecoverable from any config source.

Environment

macOS (Darwin 24.6.0), Claude Code 2.1.211, two concurrent terminal sessions.

What happened (2026-07-16, reconstructed forensically)

  1. Session A: user ran /effort medium; the session confirmed it was saved as the default, and settings.json then carried "effortLevel": "medium".
  2. Session B (a separate Claude Code process, started earlier while the default was xhigh): user ran /model and saved.
  3. settings.json afterwards read "effortLevel": "xhigh" — session B evidently wrote the whole settings object from its stale in-memory copy, reverting session A’s save (file-change timing puts the revert at session B’s /model save, 09:07 HST).
  4. A ~2-hour automated run then executed with the file claiming xhigh while the session-inherited effort was actually medium. Which one had really applied had to be settled statistically from the transcripts (thinking-block frequency ~51% of messages ≈ the medium signature, vs 80–100% for xhigh on the same CC version) — about an hour of forensics for something a config file should answer.

This was not reproduced in isolation (the sequence above is inferred from file state, save timing, and session records), but the write-whole-object-from-stale-memory mechanism fits all observations.

Ask

Make settings saves read-modify-write against fresh file contents (re-read + merge the changed key, or take a file lock) so concurrent sessions cannot silently revert each other’s saves.

The recovery half of this incident is already addressed: 2.1.212’s “session transcripts record the reasoning effort level on each assistant message” makes the executed effort recoverable ground truth going forward — thank you. The race itself remains, and it still corrupts the _default_ that the next session will inherit.

View original on GitHub ↗