fix(claude): stop passing --no-env-file to native binary in dev mode#1461
fix(claude): stop passing --no-env-file to native binary in dev mode#1461
Conversation
The Claude Agent SDK switched from shipping `cli.js` inside the package to per-platform native binaries via optional deps somewhere in the 0.2.x series. As of 0.2.121 there is no `cli.js` in the SDK package; dev mode resolves to `@anthropic-ai/claude-agent-sdk-darwin-arm64/claude` (Mach-O). That native binary rejects `--no-env-file` with `error: unknown option '--no-env-file'` and the subprocess exits 1. `shouldPassNoEnvFile` was returning true on `cliPath === undefined` on the assumption that "dev mode = JS executable run via Bun". That assumption is dead. Tighten the predicate to only return true on an explicit `.js` suffix, so we only emit the flag when the SDK is going to spawn a Bun-runnable script. CWD `.env` leak protection is unaffected. `stripCwdEnv()` in `@archon/paths` (#1067) deletes Bun-auto-loaded `.env`/`.env.local`/ `.env.development`/`.env.production` keys from `process.env` at every Archon entry point before any subprocess is spawned. The native Claude binary does not auto-load `.env` from its cwd either. `--no-env-file` was belt-and-suspenders for the JS-via-Bun case only. Verified end-to-end with a sentinel: added a unique `ARCHON_LEAK_SENTINEL_$$` to Archon's `.env`, ran e2e-claude-smoke with a bash probe checking the subprocess env. stderr shows `[archon] stripped 23 keys from /Users/rasmus/Projects/cole/Archon (.env, .env.local)` — sentinel was deleted. Bash node prints `PASS: simple='4', no sentinel leak`. Workflow completes cleanly, no `--no-env-file` rejection from the SDK binary. bun run validate: green across all 10 packages.
|
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 (5)
✅ Files skipped from review due to trivial changes (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe Claude provider now only applies Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 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 Summary (multi-agent)Ran Critical Issues (1 found)
Important Issues (3 found)
Suggestions (4 found)
Strengths
VerdictNEEDS FIXES — none of the issues block correctness of the predicate fix, but the stale file-level JSDoc at Recommended Actions
|
Critical: file-level JSDoc at provider.ts:18 still claimed dev mode resolves cli.js. Updated to reflect SDK 0.2.x's switch to per-platform native binaries. Important: security.md still listed --no-env-file as item 2 of target-repo .env isolation. Scoped that bullet to legacy Bun-runnable JS entry points and called out that native binaries don't auto-load .env from cwd. Added an Unreleased Fixed entry to CHANGELOG.md. Updated binary-resolver.ts JSDoc title that referenced cli.js. Polish: widened the predicate to accept .mjs and .cjs (also Bun-runnable JS — matches the SDK's own internal extension list). Dropped the redundant `passesNoEnvFile` log field that mirrored `isJsExecutable`. Added unit cases for .mjs/.cjs (now true) and .ts/.tsx/.jsx (deliberately false — never SDK entry points). Added an integration test that mocks resolveClaudeBinaryPath to return a .js path and asserts executableArgs: ['--no-env-file'] flows through buildBaseClaudeOptions all the way to the SDK call — catches future regressions in the conditional spread. bun run validate: green across all 10 packages.
|
Thanks for the thorough review. Pushed Critical
Important
Polish
|
Summary
UX Journey
Before
```
$ bun run cli workflow run e2e-claude-smoke --no-worktree "smoke"
[simple] Started
{...,"stderr":"error: unknown option '--no-env-file'"...,"msg":"subprocess_error"}
{...,"err":...,"errorClass":"crash","attempt":3,"maxRetries":3,"msg":"query_error"}
[simple] Failed: Claude Code crash: ... (stderr: error: unknown option '--no-env-file')
❌ DAG workflow 'e2e-claude-smoke' completed with no successful nodes.
```
After
```
$ bun run cli workflow run e2e-claude-smoke --no-worktree "smoke"
[archon] stripped 23 keys from /Users/rasmus/Projects/cole/Archon (.env, .env.local)
[simple] Started
4
[simple] Completed (2.4s)
[assert] Started
[assert] Completed (6ms)
PASS: simple='4', no sentinel leak
Workflow completed successfully.
```
Architecture Diagram
No architectural change — single-function predicate fix in the Claude provider. The two-layer leak-defense model is unchanged:
```
┌────────────────────────────────────┐
│ Layer 1 — Archon process boot │
bun run cli ────────────────▶ │ stripCwdEnv() deletes CWD .env │
│ keys from process.env │
└─────────────────┬──────────────────┘
│
▼
┌────────────────────────────────────┐
│ Layer 2 — subprocess spawn │
│ (was: --no-env-file for Bun-run │
│ cli.js; SDK no longer ships JS, │
│ so layer 2 is a no-op for dev) │
└─────────────────┬──────────────────┘
│
▼
┌────────────────────────────────────┐
│ Claude Code subprocess │
│ inherits already-cleaned env │
└────────────────────────────────────┘
```
Connection inventory:
Label Snapshot
Change Metadata
Linked Issue
Validation Evidence (required)
```bash
bun run validate
EXIT=0
```
All five gates pass — `check:bundled`, `type-check` (10 packages), `lint --max-warnings 0`, `format:check`, `test` (every package, every file `0 fail`).
End-to-end probe:
Security Impact (required)
Compatibility / Migration
Human Verification (required)
Side Effects / Blast Radius (required)
Rollback Plan (required)
Risks and Mitigations
Summary by CodeRabbit
Bug Fixes
Tests
Documentation / Changelog