v1.0.108 — Distribution unblocked, hooks made non-destructive, Windows hardened
One-line headline:
/ctx-upgradefinally advances the marketplace clone — without that single fix, none of the other six fixes in this release would actually reach users. Then we fixed the other six.
This is a major bug-fix release addressing 7 distinct user-reported issues plus operational hardening. The release closes 3 critical, 2 high, and 2 medium items and merges a community PR. Every change has new behavioral test coverage. No breaking changes. No adapter behavior change.
Upgrade
npm update -g context-modeThen run /ctx-upgrade inside Claude Code. In v1.0.108 this command actually does what its name says — see #418 below.
If you are stuck on v1.0.107 and
/ctx-upgradereports success but version never moves, that is exactly the bug #418 fixes. Bootstrap by runningnpm update -g context-modefrom a terminal first; from the next release on, in-product upgrade self-heals.
Critical fixes
[CRITICAL · DATA LOSS] #415 — pretooluse.mjs no longer destroys co-located user hooks
Reported by @asherepenko (Andrew Sherepenko) — #415.
What broke: Whenever a user's ~/.claude/settings.json placed a SessionStart hook in the same matcher entry as a context-mode hook, pretooluse.mjs ran an entries.filter(... !some(isCtxMode)) block that wiped the entire entry — including the user's sibling hooks. Fired once per machine per version (per-version marker), the destruction was silent and irreversible from the running session.
What changed (commit 10ce5fb):
pretooluse.mjs: removed the destructive entry-level filtersrc/adapters/claude-code/index.ts: replaced entry-level filter at theallCoveredbranch with inner-hook-level strip + empty-entry prune- The safe block at lines 357–385 (stale-path cleanup, gated by
isAnyContextModeHook) is intentionally untouched - 2 new co-location preservation tests added — they fail on
main, pass on this branch - Direct repro
/tmp/repro-415.shexits 1 on this build (bug eliminated)
[CRITICAL · DISTRIBUTION] #418 — /ctx-upgrade now syncs the marketplace clone
Reported by @cjduncana (Christopher John Duncan Araúz) — #418. Diagnosis was unusually well-instrumented; thank you.
Why this is the headline fix: Claude Code reads plugin metadata from ~/.claude/plugins/marketplaces/context-mode/, which /ctx-upgrade never advanced past its install-time commit. Users saw "ctx-upgrade succeeded" while the plugin system continued to treat them as the previous version forever. This compounded #411 / #181: every fix we shipped after install was invisible to the user until they manually re-installed the marketplace.
What changed (commit 7c159c2):
A new Step 0 runs before the existing /tmp clone in the upgrade pipeline:
- Detect the marketplace dir at
~/.claude/plugins/marketplaces/context-mode/ - Skip if no
.git(tarball install path) - Run
git status --porcelainfirst — if uncommitted edits exist (Mert-class users symlink the clone to a dev worktree), skip the destructive reset and surface a manual recovery command - Otherwise:
git fetch --tags origin+git reset --hard origin/HEAD - Failures land as a yellow log line; cache-dir update flow continues regardless
Tests in tests/core/cli.test.ts (Issue #418 describe block): targets correct path, runs fetch + reset, guards on .git existence, preserves user dev edits via porcelain check.
[CRITICAL · MCP] #411 — Cached .mcp.json no longer points to the previous version
Reported by @mateuszruszkowski (Mateusz Ruszkowski) — #411.
What broke: The upgrade flow wrote an absolute start.mjs path into the cached .mcp.json at write time. Once #181 lazy cleanup removed that old version directory, every MCP reconnect attempt failed because the file it was pointing to no longer existed.
What changed (commit 10ce5fb):
src/cli.ts upgrade()now writes the literal${CLAUDE_PLUGIN_ROOT}/start.mjsplaceholder instead ofresolve(pluginRoot, "start.mjs")- Matches the Anthropic canonical pattern (claude-mem, our own
.claude-plugin/plugin.json:23-29) - Inverted regression test added — confirms the absolute path is never written
High-severity fixes
[HIGH · WINDOWS] #414 — Crash-resilient hook wrapper, no more silent ghost hooks
What broke: Intermittent cjs/loader:1479 crashes on Windows during UserPromptSubmit and SessionStart while ctx-doctor reported clean. Static top-level side-effect imports (suppress-stderr, ensure-deps) threw at parse time and bypassed every try/catch block downstream. The hook then exited silently — no log, no diagnostic, no user-visible signal — while ctx-doctor still passed because it didn't exercise the crashing import path.
What changed (commit 10ce5fb):
- NEW
hooks/run-hook.mjs— universal crash-resilient wrapper. InstallsuncaughtException+unhandledRejectionhandlers before handler invocation - Side-effect modules are now dynamic-imported inside
try/catch(architect's critical finding — static top-level imports were the silent killer) - All 5 hook entries (
sessionstart,userpromptsubmit,pretooluse,posttooluse,precompact) refactored to one-linerunHook(async () => {...})pattern. Zero top-level static side-effect imports remain - Logs to
~/.claude/context-mode/hook-errors.logbeforeexit 0— silent ghost hooks are no longer architecturally possible scripts/postinstall.mjsnow also normalizeshooks.jsonat install time (was only normalized on MCP boot — but hooks fire independently of MCP)- 4 new behavioral tests in
tests/hooks/run-hook.test.ts(subprocess + poisoned-import staging)
[HIGH · WINDOWS] #408 — better-sqlite3 binding self-heals on Windows
Reported by @Asureu — #408.
Fixed by PR #410 from @ousamabenyounes (Ben Younes) — 6th merged community PR. Thank you.
What broke: Windows installs of v1.0.107 could land with a missing better-sqlite3 native binding, killing FTS5 indexing and ctx tooling without an actionable error.
What changed (commit 5432575):
3-layer self-heal in scripts/heal-better-sqlite3.mjs:
prebuild-installviaprocess.execPath(uses the active Node version, not whichever is on PATH)npm installfallback- Actionable stderr if both fail
Wired into postinstall, ensure-deps, and cli doctor hint. CI green across the 3-OS matrix.
[HIGH · /resume] #413 — Snapshot fallback in SessionStart hook
Reported by @JewelSamAmy — #413.
What broke: Per Claude Code docs, --continue, --resume, and /resume all fire SessionStart with source="resume" plus the active session_id. For /resume, that active id is a fresh uuid for the resumed conversation, so live-events lookup missed every time — even when prior context obviously existed. Users picking a non-latest session through /resume got a blank slate.
What changed (commit c3d0467):
- The
resumebranch inhooks/sessionstart.mjsnow falls back todb.claimLatestUnconsumedResume(currentSessionId)— same pattern OpenCode and OpenClaw plugins already use (opencode-plugin.ts:454) - Live-events path keeps precedence; snapshot only surfaces when no live rows match the incoming session_id (the
/resumecase, or when the prior session was previously compacted) —--continuebehavior is unchanged - Tests:
- "falls back to snapshot when resumed session has no live events"
- "prefers live events over snapshot when both exist (--continue stays correct)"
- README updated: Session Continuity intro now lists
--continue,--resume, and/resume
Medium-severity fixes
[MED · STATUSLINE] Heartbeat liveness + post-upgrade self-locate fallback
Commit c6d9cfd. Two related failure modes.
(1) False-stale during MCP idle / post-/compact — bin/statusline.mjs flips red when stats.updated_at > 30 min. Pre-fix, updated_at only advanced on MCP tool calls — long Bash/Read/Edit stretches or post-/compact pauses crossed the cliff while the server was healthy. Fix: setInterval(persistStats, 60_000).unref() in the MCP server. The 30-min threshold now reflects true server death, not user idle.
(2) Statusline disappears after upgrade — statuslineForward used only getPluginRoot() + bin/statusline.mjs. After ctx-upgrade, that path could resolve to a cache dir that sessionstart.mjs (#181) had cleaned. Fix: the resolver now tries (a) getPluginRoot, (b) marketplace clone (stable across upgrades, refreshed by #418 fix), (c) every installPath listed in installed_plugins.json. Total miss exits silently — statusline output is the user-facing surface; stderr would be visual noise.
6 new tests in tests/core/cli.test.ts cover heartbeat scheduling, threshold ordering, .unref()-ness, and all three resolver branches.
[MED · STATS] Lifetime monotonicity + value-forward Parallel I/O copy
Commit 3f204f2. Closes internal issues #2 and #3.
#2lifetime always ≥ session —ctx-statslifetime line + footer now combine disk-aggregated lifetime (events × 256 tokens) with current-session in-memory token savings at the render edge. Two accounting pipelines (server bytes vs hook session_events) unified so a fresh user / pre-flush session / pre-b8e11bfv1.0.103 sidecar no longer surfaces the surprising "$X this session · $0.00 lifetime"#3value-forward copy — the engineer-speak block becomes:Parallel I/O — one call did the work of many — faster runs, lower bill, same answer.
mcp__*__namespace stripped via non-greedy regex; section suppressed entirely whenmax_concurrency<=1(no false parallelism claim)- Renders identically across all 14 adapters via
formatReport(). Display-only — zero OS / runtime impact - 5 new format-report tests (3 monotonic, 2 copy/suppression). 50/50 analytics green
[MED · ROUTING BLOCK] Forbidden-actions template variable fix (#416)
PR #416 — commit dc892b1. Replaced hardcoded ctx_execute_file / ctx_execute strings in hooks/routing-block.mjs with proper template interpolation so toolname-prefixed adapters render the correct fully-qualified names.
Operational discipline (non-runtime)
Owner operating directive embedded at the top of /context-mode-ops
Commit 9c94232. The maintainer's standing directive (parallel agent army, ULTRATHINK posture, anti-hallucination via refs/, PO/OSS/Distribution hats, /tdd discipline, business-over-code reasoning, MUST-language for subagents, Windows-as-trust-cliff, sales-pressure context) is now a non-negotiable preamble at the top of skills/context-mode-ops/SKILL.md. Every future invocation loads it automatically; operating posture survives across sessions instead of resetting.
5 mattpocock operating-discipline skills vendored
Commit 89c0e83. The owner directive treats /diagnose, /tdd, /grill-me, /grill-with-docs, and /improve-codebase-architecture as MANDATORY tools — not advisory references. Without them locally available, every fresh invocation of /context-mode-ops would point users at skills they have never installed and the discipline collapses.
Vendored from mattpocock/skills @ b843cb5 (MIT, © 2026 Matt Pocock — license preserved upstream and referenced via skills/UPSTREAM-CREDITS.md). Each vendored SKILL.md carries a one-line attribution footer linking back to source. Refresh path documented for periodic upstream sync. No content modified — files are byte-for-byte from upstream plus the attribution footer.
Migration / Action Required
If you were affected by #415 (settings.json data loss)
If you ran v1.0.107 with co-located user SessionStart hooks in the same matcher entry as a context-mode hook, your prior ~/.claude/settings.json may have been silently truncated. Recovery options:
- Restore from your dotfiles repo or backup
- Recover via git history if you version-control your
~/.claude/:cd ~/.claude git log -p settings.json
- Re-create the lost user hooks; v1.0.108 preserves them on every PreToolUse fire
Everyone
Run /ctx-upgrade inside Claude Code after npm update -g context-mode. v1.0.108 is the first release where /ctx-upgrade actually advances the marketplace clone — without this round-trip, future fixes won't reach you in-product.
If you are a dev-mode user symlinking the marketplace clone to a worktree, the new Step 0 detects uncommitted edits via git status --porcelain and skips the destructive reset, surfacing a manual recovery command instead. Your edits are safe.
Compatibility
- Adapters: No behavior change across all 14 adapters (Claude Code, OpenCode, OpenClaw, Cursor, Kiro, VSCode Copilot, Pi, Qwen Code, Gemini CLI, JetBrains Copilot, Codex, Antigravity, Zed, Kilo). Display-only stats changes render identically via
formatReport() - Operating systems: macOS, Linux, Windows. CI green across the 3-OS matrix. Windows hook resilience and sqlite self-heal are net improvements
- Breaking changes: none
- Public API / MCP tool surface: unchanged
Test counts
- 4 new
run-hookbehavioral tests (subprocess + poisoned-import staging) - 2 new co-location preservation tests for #415
- Inverted
.mcp.jsonplaceholder test for #411 - 6 new statusline tests (heartbeat × 3 + resolver fallback × 3)
- 5 new format-report tests for stats monotonicity + copy
- 2 new continuity tests for #413 (
/resumesnapshot fallback) - Updated
cli.test.tsanchors for the newrunHookarchitecture - 9 pre-existing failures unrelated and confirmed pre-existing in main (8 opencode adapter tsx subprocess infra issue + 1 continuity parallel-spawn flake — both pass in isolation)
- TypeScript: clean
Contributors
Community wins drove this entire release. Six users, six commits worth of pressure on the fix list:
- @cjduncana (Christopher John Duncan Araúz) — #418: well-instrumented diagnosis of the marketplace-clone freeze. This is the fix that unlocks delivery of every other fix in this release
- @asherepenko (Andrew Sherepenko) — #415: caught the most damaging bug in v1.0.107 — silent destruction of co-located user hooks. Critical user-data report
- @mateuszruszkowski (Mateusz Ruszkowski) — #411: hardcoded path baked into cached
.mcp.jsonbreaking MCP reconnect post-cleanup - @Asureu — #414 and #408: two distinct, high-quality Windows reports — silent hook crashes and missing
better-sqlite3binding - @JewelSamAmy — #413: surfaced the
/resumecapability gap that the existingSessionStartsnapshot pattern already had the primitive for - @ousamabenyounes (Ben Younes) — PR #410 for #408 — 6th merged community PR. Ben has now contributed more PRs than any other external contributor
Special thanks to Matt Pocock (@mattpocock) for the MIT-licensed operating-discipline skills (/diagnose, /tdd, /grill-me, /grill-with-docs, /improve-codebase-architecture) vendored in this release.
What ships in this commit range
89c0e83 docs(skills): vendor 5 mattpocock operating-discipline skills referenced by ops directive
9c94232 docs(skill): embed owner operating directive at top of context-mode-ops
c6d9cfd fix(statusline): heartbeat liveness + post-upgrade self-locate fallback
3f204f2 fix(stats): lifetime monotonic + Parallel I/O PO copy (#2 #3)
7c159c2 fix(#418): /ctx-upgrade now syncs the marketplace clone (git fetch + reset)
c3d0467 fix(#413): /resume snapshot fallback in SessionStart hook
dc892b1 Fix/missing toolname prefix (#416)
10ce5fb fix(v1.0.108): #415 hook destruction + #411 mcp path + #414 win hook resilience
5432575 fix(install): self-heal missing better-sqlite3 binding on Windows (#408) (#410)
Full diff: v1.0.107...v1.0.108