claude-code - 💡(How to fix) Fix settings.json env block: removed key reappears on session exit (in-memory snapshot flush?) [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#51843Fetched 2026-04-23 07:43:27
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Timeline (top)
labeled ×3commented ×1

Fix Action

Workaround

Restart all concurrent Claude sessions after editing settings.json, then immediately git commit to pin the clean state; only then resume work.

Code Example

{
     "env": {
       "SOME_VAR": "original_value"
     }
   }

---

> CLAUDE_CODE_EFFORT_LEVEL=
   > Not applied: CLAUDE_CODE_EFFORT_LEVEL=
   > Cleared effort from settings, but CLAUDE_CODE_EFFORT_LEVEL=
   >
RAW_BUFFERClick to expand / collapse

Problem

Removing a key from ~/.claude/settings.json's env block while a Claude Code session is active: the key silently reappears after that session exits or a new session starts. Git working copy gets flagged every time and users can't tell WHO wrote it back.

Version: Claude Code 2.1.117 (Bun-built Mach-O binary on macOS 15.x)

Reproducer

  1. Edit ~/.claude/settings.json:
    {
      "env": {
        "SOME_VAR": "original_value"
      }
    }
  2. Start claude. The process inherits SOME_VAR=original_value in env.
  3. In a second terminal, edit settings.json to remove "SOME_VAR". Save. cat confirms removed.
  4. Back in Claude: run a few interactions (optional — may not even be needed), then /exit.
  5. cat ~/.claude/settings.json again → SOME_VAR: original_value is back.

On my side reproduced with CLAUDE_CODE_EFFORT_LEVEL=max specifically (related to /effort UX from claude-hud plugin, but the write-back happens for any env key).

Expected

Once a key is removed from the env block on disk, it stays removed. Claude Code should either:

  • Never write env block back (it's user config, not session state), or
  • Re-read from disk before flushing (rather than flushing a stale in-memory snapshot), or
  • Diff & merge so that explicit user deletions are respected.

Actual

Timeline from my investigation (all 2026-04-22):

TimeEvent
12:34Edit settings.json, remove CLAUDE_CODE_EFFORT_LEVEL: "max"; git commit clean state
12:48Active Claude session c43c4405 exits
12:56New Claude session 46315 starts
12:58settings.json mtime updates; diff shows only CLAUDE_CODE_EFFORT_LEVEL: "max" re-added
13:04Remove again (session 46315 still alive)
13:04–13:05Wait 60 s with fswatch armed — no rewrite (runtime/periodic sync ruled out)
13:08/exit that session → restart
Post-restartThis time file stays clean; /effort xhigh works with no "overrides this session" warning

Evidence

  1. Binary contains write-back strings (strings ~/.local/bin/claude | grep CLAUDE_CODE_EFFORT_LEVEL):

    CLAUDE_CODE_EFFORT_LEVEL=
    Not applied: CLAUDE_CODE_EFFORT_LEVEL=
    Cleared effort from settings, but CLAUDE_CODE_EFFORT_LEVEL=

    Suggests internal awareness of the env/settings relationship, including a "cleared from settings but env still set" warning path — but no symmetric "env was removed from settings, honour it" path seems to fire.

  2. No filesystem watcher / plugin writes it (grep across ~/.claude/plugins, hooks, shell rc files, launchctl, LaunchAgents, .MacOSX/environment.plist, /etc/zshenv, VS Code terminal.integrated.env.osx, shell-snapshots 84 files) — zero matches for CLAUDE_CODE_EFFORT_LEVEL.

  3. Child process env ≠ parent shell env: ps eww -p <parent-zsh> has no CLAUDE_CODE_EFFORT_LEVEL, but env inside Claude does. Injection happens inside claude binary based on settings.json.env.

  4. Parallel-session pollution: when multiple Claude sessions run concurrently and one was started before the user's edit, its in-memory env snapshot still carries the old value. Its exit flushes the stale snapshot, re-adding the removed key.

Possible Explanations

(A) Shutdown flushes stale in-memory settings.json snapshot

Claude Code loads settings.json into memory at startup, merges internal transient fields (or not), and on /exit writes the full object back without re-reading disk. Any edit made to disk during the session is silently clobbered on shutdown. Most fits the observed timeline.

(B) --effort CLI flag / internal state persistence

If Claude Code persists the effective effort level back into settings.json.env.CLAUDE_CODE_EFFORT_LEVEL (e.g. for cross-session continuity), the persistence is asymmetric: persists value-set, doesn't persist user-deletion.

(C) Plugin-side /effort or update-config skill rewrites on session events

Some bundled skill reacts to Stop / SessionStart events and echoes in-memory state into settings. I grep'd my installed plugins; none match write logic for this specific key. Less likely given my environment but worth noting for users with many plugins.

(D) Symlink resolution / CloudStorage sync race

My ~/.claude/settings.json is a symlink into a Dropbox-synced git repo. Shouldn't matter (file hash stays consistent and stat -L resolves correctly), but mentioning in case Dropbox's CloudStorage virtual FS causes atomic-write replay that Claude's writer assumes will succeed unchanged.

Impact

  • git status in users' config repos flags settings.json after every Claude session — noise that masks real config drift.
  • Users can't delete an env override: remove → re-appears on exit → user thinks "my delete didn't work" → loses trust in own config.
  • Cross-session parallel work amplifies the problem: removing a key while 5 sessions are active means 5 restart-flushes to fully purge.

Suggested Fix Direction

  1. On flush, re-read settings.json from disk and merge with internal deltas, so user deletions are preserved.
  2. Never flush env block from in-memory cache — treat env as read-only user config.
  3. Provide a claude config purge <key> or claude --no-persist-env CLI to opt out.
  4. Print a warning if env block is rewritten by Claude itself (so users can trace it next time).

Workaround

Restart all concurrent Claude sessions after editing settings.json, then immediately git commit to pin the clean state; only then resume work.

Related reading

  • claude-hud plugin's /effort is a pure reader (execFileSync ps ... --effort), not the writer — just the user-facing command that surfaces the discrepancy.

Filed from a live debug session on 2026-04-22 after ~4 cycles of the symptom.

extent analysis

TL;DR

The most likely fix for the issue of Claude Code re-adding removed environment variables to settings.json is to modify the application to re-read the file from disk before flushing changes, preserving user deletions.

Guidance

  1. Verify the issue: Confirm that the problem occurs when removing an environment variable from settings.json while a Claude Code session is active, and the variable reappears after the session exits.
  2. Check for concurrent sessions: Ensure that all concurrent Claude sessions are restarted after editing settings.json to prevent parallel-session pollution.
  3. Test the suggested fix direction: Implement the suggested fix of re-reading settings.json from disk before flushing changes to verify that it resolves the issue.
  4. Consider a workaround: If a fix is not immediately available, use the provided workaround of restarting all concurrent Claude sessions after editing settings.json and immediately committing the clean state to prevent the variable from being re-added.

Example

No code snippet is provided as the issue is related to the internal behavior of the Claude Code application.

Notes

The issue may be specific to the CLAUDE_CODE_EFFORT_LEVEL environment variable or the claude-hud plugin, but the suggested fix direction and workaround should be applicable to other environment variables as well.

Recommendation

Apply the workaround of restarting all concurrent Claude sessions after editing settings.json and immediately committing the clean state, as this provides a reliable way to prevent the removed environment variable from being re-added until a permanent fix is available.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING