v1.0.116 — Hotfix: heal settings.json.enabledPlugins (the file Claude Code actually reads)
A focused hotfix on top of v1.0.114. v1.0.114 self-heal was repairing the wrong file. This release fixes the right one.
What broke
After every /ctx-upgrade, users saw Plugin enabled: WARN — No enabledPlugins section found in ctx-doctor, /reload-plugins returned 0 plugins, and the MCP server disconnected. The only recovery was running /plugin install context-mode@context-mode manually inside Claude Code.
v1.0.114 self-heal repaired ~/.claude/plugins/installed_plugins.json.enabledPlugins, but Claude Code's plugin loader actually reads the truth from ~/.claude/settings.json.enabledPlugins. Different file. v1.0.114's heal was firing on every MCP boot but quietly fixing a file no one was checking.
The chicken-and-egg made this worse: when Claude Code's plugin loader rejects the plugin (because settings.json says it's disabled), the MCP server never boots, so the start.mjs heal never runs. Users were stuck.
What changed
New healSettingsEnabledPlugins() in scripts/heal-installed-plugins.mjs. Mirrors the existing healInstalledPlugins() but targets ~/.claude/settings.json — the truth source Claude Code's plugin loader actually reads.
Wired into both heal entrypoints alongside the existing v1.0.114 heal:
start.mjsHEAL 4 (every MCP boot — for users whose plugin currently loads)scripts/postinstall.mjs(everynpm install -g context-mode— for already-broken users who can't even boot MCP)
User opt-out respected. If settings.json.enabledPlugins["context-mode@context-mode"] === false (explicit disable), the heal skips with skipped: "explicit-opt-out" instead of flipping it back to true. No surprises for users who deliberately disabled the plugin.
Recovery path for already-broken users
Same as v1.0.114:
npm install -g context-mode@1.0.116
The npm postinstall hook now heals BOTH installed_plugins.json AND settings.json in one pass. Restart Claude Code; context-mode reconnects. No manual /plugin install needed.
Tests
5 new vertical TDD slices in tests/util/heal-installed-plugins.test.ts:
- creates
enabledPluginssection + adds key when settings.json is missing the section - adds the key when section exists but ours is missing (preserves other plugins)
- idempotent — no rewrite when key is already true
- respects explicit user opt-out — does NOT flip false to true
- silent skip when settings.json doesn't exist
Full suite: 2,821 passed, 8 baseline opencode failures (unrelated), 24 skipped, zero new regressions. Typecheck clean.
Cumulative defense (v1.0.113 → v1.0.116)
| Version | Layer | What |
|---|---|---|
| v1.0.113 | start.mjs guard | Don't auto-set env from plugin install path |
| v1.0.113 | Resolver env reject | Skip plugin-path env values, prefer PWD |
| v1.0.114 | Registry self-heal | Sync version mismatch + restore enabledPlugins (wrong file) |
| v1.0.114 | Upgrade asserts | Pre-bump verify + post-write consistency check |
| v1.0.115 | Transcript heuristic | Read literal cwd from active session's .jsonl
|
| v1.0.116 | settings.json heal | Heal the file Claude Code's plugin loader ACTUALLY reads |
Compatibility
15 adapters, 3 OS (macOS / Linux / Windows), no breaking changes, MCP surface unchanged.
Upgrade
ctx-upgrade # plugin
npm install -g context-mode # standalone (now also heals settings.json)