Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/claude_agent_sdk/_internal/transport/subprocess_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,17 @@ def _find_bundled_cli(self) -> str | None:

return None

def _resolve_settings_path(self, path_str: str) -> Path:
"""Resolve a settings file path.

Relative paths are resolved against `options.cwd` when provided to keep
behavior consistent with how the CLI itself resolves paths.
"""
path = Path(path_str).expanduser()
if not path.is_absolute() and self._cwd:
path = Path(self._cwd) / path
return path

def _build_settings_value(self) -> str | None:
"""Build settings value, merging sandbox settings if provided.

Expand Down Expand Up @@ -143,13 +154,13 @@ def _build_settings_value(self) -> str | None:
f"Failed to parse settings as JSON, treating as file path: {settings_str}"
)
# Read the file
settings_path = Path(settings_str)
settings_path = self._resolve_settings_path(settings_str)
if settings_path.exists():
with settings_path.open(encoding="utf-8") as f:
settings_obj = json.load(f)
else:
# It's a file path - read and parse
settings_path = Path(settings_str)
settings_path = self._resolve_settings_path(settings_str)
if settings_path.exists():
with settings_path.open(encoding="utf-8") as f:
settings_obj = json.load(f)
Expand Down
27 changes: 27 additions & 0 deletions tests/test_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,33 @@ def test_build_command_with_sandbox_and_settings_json(self):
assert parsed["sandbox"]["enabled"] is True
assert parsed["sandbox"]["excludedCommands"] == ["git", "docker"]

def test_build_command_with_sandbox_and_relative_settings_file_uses_cwd(
self, tmp_path
):
"""Test sandbox+settings resolves relative paths against cwd before merging."""
import json

settings_path = tmp_path / "settings.json"
settings_path.write_text(
json.dumps({"permissions": {"allow": ["Read"]}}), encoding="utf-8"
)

transport = SubprocessCLITransport(
prompt="test",
options=make_options(
cwd=tmp_path,
settings="settings.json",
sandbox={"enabled": True},
),
)

cmd = transport._build_command()
settings_idx = cmd.index("--settings")
merged = json.loads(cmd[settings_idx + 1])

assert merged["permissions"] == {"allow": ["Read"]}
assert merged["sandbox"] == {"enabled": True}

def test_build_command_with_settings_file_and_no_sandbox(self):
"""Test that settings file path is passed through when no sandbox."""
transport = SubprocessCLITransport(
Expand Down