Skip to content

fix: support Claude Desktop asar 1.19367.0 (split entry + code moved to chunk)#152

Open
shawnyeager wants to merge 2 commits into
johnzfitch:masterfrom
shawnyeager:fix/asar-1.19367-split-entry
Open

fix: support Claude Desktop asar 1.19367.0 (split entry + code moved to chunk)#152
shawnyeager wants to merge 2 commits into
johnzfitch:masterfrom
shawnyeager:fix/asar-1.19367-split-entry

Conversation

@shawnyeager

@shawnyeager shawnyeager commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Problem

Claude Desktop 1.19367.0 restructured its Vite main bundle in two ways that broke the Linux port across the board.

1. Split entry point → launch crash

The main process is now index.pre.js (stashes the @sentry/electron/main namespace on globalThis.__sentryElectronMain, then require()s index.js) + index.js. A sentry shim guard throws if index.pre.js didn't run first:

Error: sentryMainShim: globalThis.__sentryElectronMain is unset — index.pre.js
must stash its @sentry/electron/main namespace before index.js loads.

frame-fix-entry.js require()d index.js directly, skipping the stash → main process crashes on launch.

2. Main code moved into a chunk → every patch silently no-op'd

index.js is now a ~800-byte shim that require()s the real main code from index.chunk-<hash>.js. Both patch mechanisms targeted .vite/build/index.js, so both stopped applying:

  • launch.sh (runtime seds): titlebar, file:// origin, --effort xhigh→max, macOS Handoff, resourcesPath, and the MCP node-host path. The last one surfaced as:
    MCP Filesystem: Node host not found at:
    …/.config/Claude/cowork-resources/app.asar/.vite/build/mcp-runtime/nodeHost.js
    
  • enable-cowork.py (install-time, the actual Cowork enablers): the platform gate → {status:"supported"}, 711 IPC origin-validation guards (file:// exemption), getHostPlatform(), and return-style platform gates. Result: zero cowork markers in the packed app.

Four patterns additionally hardcoded minifier-assigned identifiers (e, Ee, O, cA, arg i, validators like $m) that rotate every build.

Fix

  • stubs/frame-fix/frame-fix-entry.js — load index.pre.js when present (it chains to index.js), fall back to index.js for older single-entry builds.
  • launch.sh — discover the real code file(s) (index.js + the chunk it require()s) and apply every grep-guarded patch across them via a patch_index helper; generalize the four identifier-hardcoded patterns to [A-Za-z0-9_$]+.
  • install.shapply_patches runs enable-cowork.py against index.js plus every chunk it require()s (same discovery as launch.sh).
  • enable-cowork.py — generalize the IPC origin-guard regex: the sender-arg rotated in and some validators contain $, so match both with [\w$]+ and reuse the captured arg in the exemption. Matches all 711 sites on 1.19367.0.

Verification (end-to-end on asar 1.19367.0)

  • App launches, main window opens, no sentry crash.
  • MCP filesystem node-host resolves — error gone.
  • All eight launch.sh patch passes report applied (previously zero reached the relocated code).
  • All four enable-cowork.py patches apply to the chunk; patched chunk passes node --check; after repack the cowork markers are embedded in the running app.
  • No did not pass origin validation throws, no process is not defined.

shawnyeager and others added 2 commits July 8, 2026 10:34
Claude Desktop 1.19367.0 restructured its Vite main bundle in two ways
that broke the Linux port:

1. Split entry point. The main process is now index.pre.js (which stashes
   the @sentry/electron/main namespace on globalThis.__sentryElectronMain,
   then require()s index.js) + index.js. A sentry shim guard in the main
   code throws "globalThis.__sentryElectronMain is unset" if index.pre.js
   did not run first. frame-fix-entry.js require()d index.js directly,
   skipping the stash, so the main process crashed on launch. It now loads
   index.pre.js when present (chaining to index.js), falling back to
   index.js for older single-entry builds.

2. Main code moved to a chunk. index.js is now a thin shim that require()s
   the real main code from index.chunk-<hash>.js. launch.sh's patches all
   targeted .vite/build/index.js, so they silently no-op'd — most visibly
   "MCP Filesystem: Node host not found", but also the titlebar, origin,
   --effort, Handoff, and resourcesPath fixes. launch.sh now discovers the
   real code file(s) (index.js plus the chunk it require()s) and applies
   each grep-guarded patch across them. The four patches that hardcoded
   minifier identifiers (origin, --effort, Handoff, titlebar values) are
   generalized to [A-Za-z0-9_$]+ so they survive identifier rotation
   across builds.

Verified on asar 1.19367.0: app launches, main window opens, MCP
filesystem host resolves, and all eight patch passes report applied.

Follow-up: install.sh's fresh-install patcher (enable-cowork.py) targets
index.js the same way and has the same drift; it is currently masked
because launch.sh re-applies every patch on each launch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Correction to the previous commit's follow-up note: enable-cowork.py is
NOT masked by launch.sh. It applies a *different* set of patches — the
Cowork enablers: the platform gate (-> {status:"supported"}), ~700 IPC
origin-validation guards (file:// exemption), getHostPlatform(), and
return-style platform gates — none of which launch.sh performs. On asar
1.19367.0 these silently stopped applying because install.sh fed
enable-cowork.py only .vite/build/index.js, which is now a thin entry
shim; the real code (and every pattern above) moved into
index.chunk-<hash>.js. Result: zero cowork markers in the packed app.

- install.sh apply_patches now runs enable-cowork.py against index.js plus
  every chunk it require()s (same discovery launch.sh uses), so the
  patches land where the code actually is.
- enable-cowork.py's IPC origin-guard regex is generalized: the sender-arg
  name rotated from `i` to `n` across builds and some validator names
  contain `$` (e.g. `$m`), neither of which the old `\(i\)`/`\w+` pattern
  matched. Now [\w$]+ for both the validator and the arg, reusing the
  captured arg in the exemption. This matches all 711 guard sites on
  1.19367.0.

Verified end-to-end on 1.19367.0: all four cowork patches apply to the
chunk, the patched chunk passes `node --check`, and after repack the app
launches with the markers embedded — no sentry crash, no MCP error, no
"did not pass origin validation" throws, no "process is not defined".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@shawnyeager shawnyeager changed the title fix: support Claude Desktop asar 1.19367.0 split main entry fix: support Claude Desktop asar 1.19367.0 (split entry + code moved to chunk) Jul 8, 2026
@vsem-azamat

Copy link
Copy Markdown

Verified this PR's split-entry/chunk changes locally against Claude Desktop 1.20186.0 on Arch, but there is an additional AUR-specific gap: the current AUR PKGBUILD invokes enable-cowork.py directly on index.js and launches the packed ASAR directly, so it bypasses both the install.sh chunk discovery and the launch.sh package.json.main rewrite in this PR.

The AUR recipe therefore needs two matching changes after this PR lands:

  1. Patch index.js plus its referenced index.chunk-*.js targets, requiring at least one successful platform-gate match.
  2. Rewrite the packed package.json.main to frame-fix-entry.js; otherwise the copied frame wrapper is never loaded and 1.20186.0 crashes on systemPreferences.setUserDefault().

Full reproduction, proposed PKGBUILD change, and verification evidence are in #156. With both AUR changes applied locally: clean package build succeeds, 724 IPC guards patch, packaged markers are present, package.json.main is correct, 520/520 upstream tests pass, and runtime reaches [cowork-startup] all rails engaged with Cowork reported supported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants