Skip to content

Add :inherit_env option for environment variable control#47

Merged
guess merged 14 commits intomainfrom
feature/inherit-env
Mar 29, 2026
Merged

Add :inherit_env option for environment variable control#47
guess merged 14 commits intomainfrom
feature/inherit-env

Conversation

@guess
Copy link
Copy Markdown
Owner

@guess guess commented Mar 29, 2026

Summary

  • Add :inherit_env session option to control which system env vars are inherited by the CLI subprocess. Supports :all (default, strips CLAUDECODE), [] (inherit nothing), or a list of exact strings / {:prefix, "..."} tuples for selective inheritance.
  • Widen :env to accept false values for unsetting vars, leveraging Erlang Port's native {charlist, false} behavior.
  • Add filter_system_env/3 to ClaudeCode.Adapter.Port with debug logging for unmatched entries.

Background

Supersedes the env filtering portion of #42 and closes #44.

#44 proposed 4 options (filter_env, allowed_env, disallowed_env, env) with a hardcoded allowlist of ~30 CLI-specific env vars plus 5 prefix patterns (ANTHROPIC_, CLAUDE_CODE_, CLAUDE_, VERTEX_REGION_, LC_) and ~14 system essentials (PATH, HOME, SHELL, etc.). While thorough, this approach had issues:

Maintenance burden. The allowlist is a snapshot of what Claude Code supports today. The CLI adds, renames, and removes env vars regularly — DISABLE_PROMPT_CACHING_HAIKU, SLASH_COMMAND_TOOL_CHAR_BUDGET, FORCE_AUTOUPDATE_PLUGINS, etc. Every CLI release could silently break users who depend on a new var that isn't in our list yet. We'd be permanently chasing upstream.

Unnecessary complexity. 4 options with 2 operating modes (filter_env: true vs false) and interactions between them (disallowed_env works in both modes, but allowed_env only in filtered mode; :env overrides disallowed_env but not the other way around). That's a lot of cognitive overhead for env var filtering.

Wrong default for an SDK. Filtering by default is a breaking change — existing users who rely on env vars like DATABASE_URL, HTTP_PROXY, or custom vars reaching the CLI would need to add allowed_env entries. The Python SDK passes everything through (minus CLAUDECODE), and so should we.

This PR takes a simpler approach — 1 new option instead of 3:

Use case Solution
Default (99% of users) Nothing to configure. Inherits all env minus CLAUDECODE, matching Python SDK.
Remove specific sensitive vars env: %{"RELEASE_COOKIE" => false} — leverages Erlang Port's native env unsetting.
Full sandboxing inherit_env: [] or inherit_env: ["PATH", "HOME", {:prefix, "ANTHROPIC_"}] — explicit allowlist with string and prefix matching.

No built-in allowlist to maintain. No multi-mode interaction rules. Two composable options that cover every use case.

Test plan

  • 7 unit tests for filter_system_env/3 (:all, empty list, exact strings, prefix tuples, mixed, CLAUDECODE pass-through, unmatched)
  • 5 integration tests for build_env/2 with :inherit_env (async: false, System.put_env with setup/on_exit cleanup)
  • 4 debug logging tests (capture_log for matched/unmatched entries)
  • 1 test for false value pass-through in build_env
  • 9 options validation tests (:inherit_env accepts/rejects, session-only enforcement, :env false values)
  • mix test --no-start — 1512 tests pass
  • mix quality — compile, format, credo --strict, dialyzer all pass

Test and others added 14 commits March 29, 2026 12:47
Adds :inherit_env session option for controlling which system env vars
the CLI subprocess inherits (:all, [], or a list of strings/{:prefix, ...}
tuples). Widens :env to accept false values for unsetting variables via
Erlang Port's native env unsetting behavior.
- Replace Enum.filter |> Map.new with Map.filter/2
- Remove unnecessary result binding in filter_system_env/3
- Use !!debug instead of debug != false for safer boolean coercion
- Replace throw/catch validators with Enum.find pattern (matches codebase style)
@guess guess merged commit 8d98cc1 into main Mar 29, 2026
2 checks passed
@guess guess deleted the feature/inherit-env branch March 29, 2026 19:09
@ppsplus-bradh
Copy link
Copy Markdown
Contributor

Excellent approach. Glad to have at least sparked the thought.

@guess
Copy link
Copy Markdown
Owner Author

guess commented Mar 30, 2026

Yes thank you 🙏 it needed serious improving

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