fix(claude): embed SDK cli.js via /embed entry point for compiled binaries#990
fix(claude): embed SDK cli.js via /embed entry point for compiled binaries#990
Conversation
…aries
The Claude Agent SDK falls back to resolving its cli.js via
import.meta.url when pathToClaudeCodeExecutable is not set. In
bun build --compile binaries, import.meta.url of a bundled module
is frozen at build time to the build host's absolute node_modules
path — so every binary shipped from CI carried a
/Users/runner/work/Archon/Archon/node_modules/.bun/... path that
only existed on the GitHub Actions runner, and every workflow run
failed with 'Module not found' after three retries.
The SDK ships a dedicated /embed entry point for exactly this case:
it uses 'import cli.js with { type: "file" }' so bun embeds cli.js
into the compiled binary's $bunfs virtual filesystem, then extracts
it to a real temp path at runtime so the subprocess can exec it.
Verified by building a local binary (scripts/build-binaries.sh) and
running 'workflow run assist' — the binary now spawns Claude
successfully where v0.3.1 fails before the first token.
This bug has been latent since bun build --compile was first wired
up; it surfaced in v0.3.1 because that was the first release where
the homebrew formula SHAs were correct and a user could actually
install the binary.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe change imports the embedded Claude Agent SDK CLI binary path and passes it to the Claude SDK initialization. This configures the SDK to use the extracted embedded Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Review SummaryCritical Issues (0)None. Important Issues (0)None. Suggestions (1)
Strengths
VerdictREADY TO MERGE — add CHANGELOG entry before cutting v0.3.2. Recommended Actions
|
First post under a new docs site blog section. It's a post-mortem on the six bugs that broke every Archon binary release from v0.2.13 through v0.3.1: - #960 pino-pretty transport crash in compiled binaries - #961/#979 isBinaryBuild runtime detection fragility - #986/#987 release workflow bypassing scripts/build-binaries.sh - #988 SQLite schema missing allow_env_keys column - #990 Claude SDK cli.js path baked in at build time - #991/#992 env-leak gate firing on unregistered cwd paths Each bug masked the next. The test-release skill was the first thing that exercised the full chain (install the released binary on a clean machine, run real commands, verify end-to-end), and it found all six in sequence as the earlier layers got fixed. The post covers: - The bug onion metaphor and why it's particularly hard to debug - Each of the six bugs with root cause and fix PR - Why dev mode hid all of this - Why locally-built binaries passed all contributor tests but failed for every other user - The smoke test that finally broke the pattern - What changed in the release skill + what's still open - An honest 'note on blame' — the lesson is structural, not about being more careful Also adds a 'Blog' section to the Astro sidebar config so the new directory is discoverable. Positioned between Getting Started and Guides. Pre-post sanity check items for reviewer: - Factual accuracy of the bug-by-bug timeline - Whether to name the community contributor (leex279) explicitly or keep it generic - Whether the 'Note on blame' section is the right tone - Length (~3000 words) — fine for a post-mortem, could be trimmed to ~2000 for a shorter read
…dapter docs: add GitLab community adapter documentation
…dapter docs: add GitLab community adapter documentation
…aries (coleam00#990) The Claude Agent SDK falls back to resolving its cli.js via import.meta.url when pathToClaudeCodeExecutable is not set. In bun build --compile binaries, import.meta.url of a bundled module is frozen at build time to the build host's absolute node_modules path — so every binary shipped from CI carried a /Users/runner/work/Archon/Archon/node_modules/.bun/... path that only existed on the GitHub Actions runner, and every workflow run failed with 'Module not found' after three retries. The SDK ships a dedicated /embed entry point for exactly this case: it uses 'import cli.js with { type: "file" }' so bun embeds cli.js into the compiled binary's $bunfs virtual filesystem, then extracts it to a real temp path at runtime so the subprocess can exec it. Verified by building a local binary (scripts/build-binaries.sh) and running 'workflow run assist' — the binary now spawns Claude successfully where v0.3.1 fails before the first token. This bug has been latent since bun build --compile was first wired up; it surfaced in v0.3.1 because that was the first release where the homebrew formula SHAs were correct and a user could actually install the binary.
…dapter docs: add GitLab community adapter documentation
…aries (coleam00#990) The Claude Agent SDK falls back to resolving its cli.js via import.meta.url when pathToClaudeCodeExecutable is not set. In bun build --compile binaries, import.meta.url of a bundled module is frozen at build time to the build host's absolute node_modules path — so every binary shipped from CI carried a /Users/runner/work/Archon/Archon/node_modules/.bun/... path that only existed on the GitHub Actions runner, and every workflow run failed with 'Module not found' after three retries. The SDK ships a dedicated /embed entry point for exactly this case: it uses 'import cli.js with { type: "file" }' so bun embeds cli.js into the compiled binary's $bunfs virtual filesystem, then extracts it to a real temp path at runtime so the subprocess can exec it. Verified by building a local binary (scripts/build-binaries.sh) and running 'workflow run assist' — the binary now spawns Claude successfully where v0.3.1 fails before the first token. This bug has been latent since bun build --compile was first wired up; it surfaced in v0.3.1 because that was the first release where the homebrew formula SHAs were correct and a user could actually install the binary.
Summary
Fixes a P0 bug in v0.3.1 where every compiled binary fails to spawn Claude with
Module not found "/Users/runner/work/Archon/Archon/node_modules/.bun/@anthropic-ai+claude-agent-sdk@0.2.89+.../cli.js".Root cause
The Claude Agent SDK, when
pathToClaudeCodeExecutableis not set, falls back to:In a
bun build --compilebinary,import.meta.urlof a bundled module is frozen at build time to the absolute path where that module lived on the build host. In CI that's/Users/runner/work/Archon/Archon/node_modules/.bun/...— a path that only exists on the GitHub Actions runner. Every shipped binary carried the CI path, and every workflow run hitspawn ENOENTon the three-retry loop before failing.Fix
The SDK ships a dedicated
@anthropic-ai/claude-agent-sdk/embedentry point built for exactly this case. It usesimport cli.js with { type: 'file' }so Bun's bundler embedscli.jsinto the compiled binary's$bunfsvirtual filesystem, thenextractFromBunfs()copies it to a real temp path at runtime (child processes cannot read the parent's$bunfs). We import that entry point and pass the result aspathToClaudeCodeExecutable.Safe in dev (
bun link) too — the embed module resolves to the real on-diskcli.js.Verification
Built a local binary via
scripts/build-binaries.shon this branch and ran:Result: Claude subprocess spawned successfully, returned "Hello", workflow completed in 3.9s. Same test against v0.3.1 fails with
Module not foundafter three retries.Why this escaped every prior release
bun link) never exercises this path — normal node resolution findscli.js.node_modulespath, which exists locally, so the binary "works" for the person who built it./test-release brewcould actually run — and it surfaced this instantly.Related
createRequire(import.meta.url).resolve('@openai/codex/package.json')plus unembeddable native platform binaries). That's out of scope for this fix — filing separately.workflow run assistagainst the built binary inside the release workflow would have caught this. Worth adding as a follow-up.Test plan
bun run type-checkcleanscripts/build-binaries.shspawns Claude and completesassistworkflow/test-release brew 0.3.2end-to-end before announcingSummary by CodeRabbit