anthropics / anthropics/claude-agent-sdk-python

discussion: ClaudeAgentOptions.env only supports implicit parent-env inheritance with no documented isolated environment mode

オープン
#934 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る
documentation enhancement question
主要言語
Python
スター
8.1k
フォーク
1.3k
平均マージ
2日 31分
マージ済み PR(30日)
1

説明

hey, i was exploring `src/claude_agent_sdk/_internal/transport/subprocess_cli.py` to understand how the SDK spawns the Claude Code CLI subprocess and noticed that `connect()` always builds the subprocess environment by inheriting the full parent `os.environ` and then merging user provided `ClaudeAgentOptions.env` on top of it

```python
inherited_env = {k: v for k, v in os.environ.items() if k != "CLAUDECODE"}

process_env = {
**inherited_env,
"CLAUDE_CODE_ENTRYPOINT": "sdk-py",
**self._options.env,
"CLAUDE_AGENT_SDK_VERSION": __version__,
}
```
at a normal usage level this makes sense because `env={"MY_VAR": "value"}` works as an override/addition mechanism, the confusing part is that this inheritance behaviour does not seem to be explicitly documented on `ClaudeAgentOptions.env` and there also does not appear to be a supported way to request a clean or isolated subprocess environment
this looks related to #573 but in this case the concern is broader as users currently get implicit full inheritance but no explicit way to choose between merge with parent env and isolated/clean subprocess env
### Impact
due to this, users cannot create a deterministic or sandboxed subprocess environment and also, sensitive parent variables may be inherited unintentionally and CI/reproducibility use cases become harder
(main point: current behaviour may be intentional but the API contract is not explicit enough to make that clear)

### How to reproduce

Reproduction

```python

import os
import anyio

from claude_agent_sdk import ClaudeAgentOptions
from claude_agent_sdk._errors import CLIConnectionError
from claude_agent_sdk._internal.transport.subprocess_cli import SubprocessCLITransport

class EnvCaptured(Exception):
pass

async def fake_open_process(*args, **kwargs):
env = kwargs["env"]

print("MY_CUSTOM_VAR:", env.get("MY_CUSTOM_VAR"))
print("HOME inherited:", "HOME" in env)
print("PATH inherited:", "PATH" in env)
print("ANTHROPIC_API_KEY inherited:", "ANTHROPIC_API_KEY" in env)

raise EnvCaptured("Stopped after capturing subprocess env")

async def fake_check_claude_version():
return None

async def main():
os.environ["ANTHROPIC_API_KEY"] = "dummy-secret"

options = ClaudeAgentOptions(
env={"MY_CUSTOM_VAR": "hello"},
max_turns=1,
)

transport = SubprocessCLITransport(prompt="hello", options=options)

transport._cli_path = "dummy-claude"
transport._build_command = lambda: ["dummy-claude"]
transport._check_claude_version = fake_check_claude_version

original_open_process = anyio.open_process
anyio.open_process = fake_open_process

try:
await transport.connect()
except CLIConnectionError as e:
if "Stopped after capturing subprocess env" in str(e):
print("Captured env successfully; reproduction complete.")
else:
raise
finally:
anyio.open_process = original_open_process

anyio.run(main)
```
Output:
Image

was the current inheritance-only behaviour intentional or is the lack of an isolated environment mode an oversight? happy to make a pr if this direction sounds useful

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。