Claude in Chrome native-host wrapper hardcodes a CLI version path → silent CIC death on every CC version bump
Summary
The CIC (Claude in Chrome) extension's native-host wrapper at ~/.claude/chrome/chrome-native-host is auto-generated with a hardcoded path to a specific CC version directory, e.g.:
#!/bin/sh
# Chrome native host wrapper script
# Generated by Claude Code - do not edit manually
exec "/Users/<user>/.local/share/claude/versions/2.1.132" --chrome-native-host
Every CC version bump (CLI auto-upgrade OR Desktop App auto-upgrade of the bundled CC binary) breaks CIC pairing in one of two ways:
| Failure path | Trigger | Symptom |
|---|---|---|
| (A) Version dir deleted | CLI auto-upgrade deletes the old ~/.local/share/claude/versions/X.Y.Z/ directory | Wrapper execs a deleted binary → Chrome native-messaging handshake fails silently |
| (B) Bundle version drift | Desktop App updates its bundled CC to N+1, user-CLI symlink still at N | Wrapper points at stale binary, IPC protocol mismatches live CC sessions → list_connected_browsers returns [] |
In both cases, the failure is silent: no error log, no banner, no exception. list_connected_browsers just returns [] and the user has no idea why CIC tools stopped working. Path (A) was observed on MM1 2026-06-13, broke CIC for ~24h before being caught during a Ratify gate. Path (B) was observed on MM2 2026-06-19, where the Desktop App had auto-bumped to 2.1.181 while the CLI symlink still pointed at 2.1.170 — 11 patch versions behind — and the IPC handshake silently failed.
Reproduction
Any machine with:
- Claude Code CLI installed via the auto-updating installer
- Claude Desktop App installed with
claude-codebundled (auto-updates independently) - CIC extension installed in Chrome / Comet / Chromium-based browser
After ANY CC version bump:
cat ~/.claude/chrome/chrome-native-host
ls -la "$(grep -oE '/[^"]+' ~/.claude/chrome/chrome-native-host | head -1)"
# If missing OR stale, CIC is broken.
From a CC session:
mcp__Claude_in_Chrome__list_connected_browsers
# Returns: [] (silently)
Why it matters
CIC is the only path for logged-in browser verification in CC. When it breaks silently: verification work stalls, users don't know to debug a 4-line shell script, failure persists across all parallel CC sessions, and the diagnostic chain (extension → manifest → wrapper → native-host subprocess → Unix socket bridge → CC session) is opaque to most users.
Proposed fix — dynamic resolver template
Replace the hardcoded version path with a dynamic resolver that picks the highest-version CC binary the Desktop App has installed, with the user-CLI symlink as a fallback. Survives BOTH update paths:
#!/bin/sh
# Chrome native host wrapper script
# Auto-generated by Claude Code. Resolves the highest-version CC binary at runtime
# so future version bumps don't require regenerating this file.
CC_DIR="$HOME/Library/Application Support/Claude/claude-code"
LATEST=$(ls -1 "$CC_DIR" 2>/dev/null | sort -V | tail -1)
BIN="$CC_DIR/$LATEST/claude.app/Contents/MacOS/claude"
if [ ! -x "$BIN" ]; then
BIN="$HOME/.local/bin/claude"
fi
exec "$BIN" --chrome-native-host
This:
- ✅ Picks the freshest CC binary even when CLI and Desktop App update at different cadences
- ✅ Survives CLI version dir deletion (Desktop App bundle dir is the primary lookup)
- ✅ Falls back to
~/.local/bin/claudefor machines without the Desktop App - ✅ POSIX shell + standard tools (
ls,sort -V,tail) — zero new dependencies - ✅ Self-documents
Linux paths need adapting (likely $XDG_DATA_HOME/claude/...), but the pattern (highest-version directory pick) is portable.
Self-healing already shipped at the user layer
Until Anthropic ships an installer-side fix, users can wire a SessionStart hook that auto-heals the wrapper. Reference implementation:
- Hook source: pai-system/hooks/cic-wrapper-autoheal.sh — sentinel-aware (recognizes the canonical dynamic-resolver form, sandbox-resolves
$BINviaawk+bash) - Regression tests: pai-system/hooks/__tests__/cic-wrapper-autoheal.test.sh — 15 cases including the
$BINfalse-positive regression - Diagnostic CLI: pai-system/scripts/cic-doctor.sh — 8-point pairing check in <2s with
--repairfor autonomous self-heal - Error pattern doc: pai-system/troubleshooting/error-patterns.md § "CIC Native-Host Wrapper Version-Path Rot"
These are maintained at <https://github.com/growthpigs/pai-system> and would be useful as templates for the CC installer team.
Diagnostic evidence (the live failure that prompted this issue)
Diag log from cic-wrapper-autoheal.sh showing the false-positive heal on a dynamic-resolver wrapper (the v1 hook used literal-string grep, extracted $BIN as a string, declared the target missing, reverted to the static-symlink form, which was stale by 11 patch versions on MM2):
2026-06-19T07:03:44Z HEALED target=$BIN → symlink=/Users/<user>/.local/bin/claude
2026-06-19T07:04:08Z OK target=/Users/<user>/.local/bin/claude (exists, executable)
Live system state when CIC was broken on MM2 (Mac mini, T77WYLQMXJ):
~/.claude/chrome/chrome-native-host:
exec "/Users/<user>/.local/bin/claude" --chrome-native-host (resolves to 2.1.170)
Live CC sessions running: 2.1.181 (from ~/Library/Application Support/Claude/claude-code/2.1.181/)
Result: list_connected_browsers → []
After applying the dynamic-resolver fix, the wrapper resolves to the matching 2.1.181 binary and list_connected_browsers returns the connected browser.
Acceptance for the upstream fix
If Anthropic accepts the dynamic-resolver template:
- [ ] CC installer regenerates the wrapper using the dynamic-resolver pattern (or equivalent)
- [ ] Comment block in the generated wrapper documents the lookup chain
- [ ] Linux variant uses the appropriate XDG base directory
- [ ] CHANGELOG entry naming the fix so users on the broken pattern know to delete their old wrapper
The user-layer autoheal hook can then be retired (or kept as belt-and-suspenders).
Related
- pai-system #252 — v1 autoheal doctrine (static-symlink fix)
- pai-system #319 — v2 autoheal doctrine (dynamic-resolver fix)
- pai-system main commits:
b8f4c76d4a(v1 hook),fe0fa7c373(v2 hook + tests),5e564416ac(cic-doctor + smoke test),6b4692bcbc(error-patterns evolution)
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗