Skip to content

Commit e621929

Browse files
sarahdeatonclaude
andauthored
fix: pass --setting-sources for empty list to disable filesystem settings (#822)
## Summary `setting_sources=[]` was treated as falsy and silently dropped, so it behaved the same as `None`: the spawned CLI loaded its default user/project/local setting sources. The TypeScript SDK already distinguishes `undefined` (CLI defaults) from `[]` (disable all) by checking `!== undefined` and using equals-syntax so the empty value survives argv parsing. This change applies the same pattern: check `is not None` and pass `--setting-sources=` (single argv element) so an empty list reaches the CLI parser as "disable all sources." ## Tests - `test_build_command_setting_sources_omitted_when_not_provided`: now uses `startswith` so it can't pass vacuously against the equals form - `test_build_command_setting_sources_empty_list_disables_all`: rewritten; previously asserted the flag was omitted for `[]` - `test_build_command_setting_sources_included_when_provided`: updated for single-element `--setting-sources=user,project` ``` 3 passed, 56 deselected ``` Companion docs change: anthropics/claude-code-docs branch `claude/clarify-cost-tracking-docs-3ILH3`. --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent ebc06f2 commit e621929

3 files changed

Lines changed: 44 additions & 16 deletions

File tree

examples/setting_sources.py

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
- "project": Project-level settings (.claude/ in project)
1111
- "local": Local gitignored settings (.claude-local/)
1212
13-
IMPORTANT: When setting_sources is not provided (None), NO settings are loaded
14-
by default. This creates an isolated environment. To load settings, explicitly
15-
specify which sources to use.
13+
When setting_sources is not provided (None), the CLI loads its default
14+
sources: user, project, and local. Pass an empty list to disable all
15+
filesystem setting sources.
1616
1717
By controlling which sources are loaded, you can:
18-
- Create isolated environments with no custom settings (default)
18+
- Disable filesystem settings with setting_sources=[]
1919
- Load only user settings, excluding project-specific configurations
2020
- Combine multiple sources as needed
2121
@@ -45,17 +45,46 @@ def extract_slash_commands(msg: SystemMessage) -> list[str]:
4545

4646

4747
async def example_default():
48-
"""Default behavior - no settings loaded."""
48+
"""Default behavior: None loads CLI default sources (user, project, local)."""
4949
print("=== Default Behavior Example ===")
5050
print("Setting sources: None (default)")
51-
print("Expected: No custom slash commands will be available\n")
51+
print("Expected: project slash commands like /commit ARE available\n")
5252

5353
sdk_dir = Path(__file__).parent.parent
5454

5555
options = ClaudeAgentOptions(
5656
cwd=sdk_dir,
5757
)
5858

59+
async with ClaudeSDKClient(options=options) as client:
60+
await client.query("What is 2 + 2?")
61+
62+
async for msg in client.receive_response():
63+
if isinstance(msg, SystemMessage) and msg.subtype == "init":
64+
commands = extract_slash_commands(msg)
65+
print(f"Available slash commands: {commands}")
66+
if "commit" in commands:
67+
print("✓ /commit is available (expected: CLI defaults loaded)")
68+
else:
69+
print("❌ /commit is NOT available (unexpected)")
70+
break
71+
72+
print()
73+
74+
75+
async def example_disable_all():
76+
"""Empty list disables all filesystem setting sources."""
77+
print("=== Disable All Sources Example ===")
78+
print("Setting sources: []")
79+
print("Expected: no custom slash commands will be available\n")
80+
81+
sdk_dir = Path(__file__).parent.parent
82+
83+
options = ClaudeAgentOptions(
84+
setting_sources=[],
85+
cwd=sdk_dir,
86+
)
87+
5988
async with ClaudeSDKClient(options=options) as client:
6089
await client.query("What is 2 + 2?")
6190

@@ -66,7 +95,7 @@ async def example_default():
6695
if "commit" in commands:
6796
print("❌ /commit is available (unexpected)")
6897
else:
69-
print("✓ /commit is NOT available (expected - no settings loaded)")
98+
print("✓ /commit is NOT available (expected: sources disabled)")
7099
break
71100

72101
print()
@@ -139,6 +168,7 @@ async def main():
139168
"""Run all examples or a specific example based on command line argument."""
140169
examples = {
141170
"default": example_default,
171+
"disable_all": example_disable_all,
142172
"user_only": example_user_only,
143173
"project_and_user": example_project_and_user,
144174
}

src/claude_agent_sdk/_internal/transport/subprocess_cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,8 @@ def _build_command(self) -> list[str]:
280280
# Agents are always sent via initialize request (matching TypeScript SDK)
281281
# No --agents CLI flag needed
282282

283-
if self._options.setting_sources:
284-
cmd.extend(["--setting-sources", ",".join(self._options.setting_sources)])
283+
if self._options.setting_sources is not None:
284+
cmd.append(f"--setting-sources={','.join(self._options.setting_sources)}")
285285

286286
# Add plugin directories
287287
if self._options.plugins:

tests/test_transport.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -434,16 +434,16 @@ def test_build_command_setting_sources_omitted_when_not_provided(self):
434434
options=make_options(),
435435
)
436436
cmd = transport._build_command()
437-
assert "--setting-sources" not in cmd
437+
assert not any(a.startswith("--setting-sources") for a in cmd)
438438

439-
def test_build_command_setting_sources_omitted_when_empty(self):
440-
"""Test that --setting-sources is omitted when setting_sources is empty list."""
439+
def test_build_command_setting_sources_empty_list_disables_all(self):
440+
"""Test that setting_sources=[] passes --setting-sources= to disable all sources."""
441441
transport = SubprocessCLITransport(
442442
prompt="test",
443443
options=make_options(setting_sources=[]),
444444
)
445445
cmd = transport._build_command()
446-
assert "--setting-sources" not in cmd
446+
assert "--setting-sources=" in cmd
447447

448448
def test_build_command_setting_sources_included_when_provided(self):
449449
"""Test that --setting-sources is included when setting_sources has values."""
@@ -452,9 +452,7 @@ def test_build_command_setting_sources_included_when_provided(self):
452452
options=make_options(setting_sources=["user", "project"]),
453453
)
454454
cmd = transport._build_command()
455-
assert "--setting-sources" in cmd
456-
idx = cmd.index("--setting-sources")
457-
assert cmd[idx + 1] == "user,project"
455+
assert "--setting-sources=user,project" in cmd
458456

459457
def test_build_command_with_extra_args(self):
460458
"""Test building CLI command with extra_args for future flags."""

0 commit comments

Comments
 (0)