Files
claude-agent-sdk-python/examples/setting_sources.py
2025-09-28 14:52:53 -07:00

174 lines
5.5 KiB
Python

#!/usr/bin/env python3
"""Example demonstrating setting sources control.
This example shows how to use the setting_sources option to control which
settings are loaded, including custom slash commands, agents, and other
configurations.
Setting sources determine where Claude Code loads configurations from:
- "user": Global user settings (~/.claude/)
- "project": Project-level settings (.claude/ in project)
- "local": Local gitignored settings (.claude-local/)
IMPORTANT: When setting_sources is not provided (None), NO settings are loaded
by default. This creates an isolated environment. To load settings, explicitly
specify which sources to use.
By controlling which sources are loaded, you can:
- Create isolated environments with no custom settings (default)
- Load only user settings, excluding project-specific configurations
- Combine multiple sources as needed
Usage:
./examples/setting_sources.py - List the examples
./examples/setting_sources.py all - Run all examples
./examples/setting_sources.py default - Run a specific example
"""
import asyncio
import sys
from pathlib import Path
from claude_agent_sdk import (
ClaudeAgentOptions,
ClaudeSDKClient,
SystemMessage,
)
def extract_slash_commands(msg: SystemMessage) -> list[str]:
"""Extract slash command names from system message."""
if msg.subtype == "init":
commands = msg.data.get("slash_commands", [])
return commands
return []
async def example_default():
"""Default behavior - no settings loaded."""
print("=== Default Behavior Example ===")
print("Setting sources: None (default)")
print("Expected: No custom slash commands will be available\n")
sdk_dir = Path(__file__).parent.parent
options = ClaudeAgentOptions(
cwd=sdk_dir,
)
async with ClaudeSDKClient(options=options) as client:
await client.query("What is 2 + 2?")
async for msg in client.receive_response():
if isinstance(msg, SystemMessage) and msg.subtype == "init":
commands = extract_slash_commands(msg)
print(f"Available slash commands: {commands}")
if "commit" in commands:
print("❌ /commit is available (unexpected)")
else:
print("✓ /commit is NOT available (expected - no settings loaded)")
break
print()
async def example_user_only():
"""Load only user-level settings, excluding project settings."""
print("=== User Settings Only Example ===")
print("Setting sources: ['user']")
print("Expected: Project slash commands (like /commit) will NOT be available\n")
# Use the SDK repo directory which has .claude/commands/commit.md
sdk_dir = Path(__file__).parent.parent
options = ClaudeAgentOptions(
setting_sources=["user"],
cwd=sdk_dir,
)
async with ClaudeSDKClient(options=options) as client:
# Send a simple query
await client.query("What is 2 + 2?")
# Check the initialize message for available commands
async for msg in client.receive_response():
if isinstance(msg, SystemMessage) and msg.subtype == "init":
commands = extract_slash_commands(msg)
print(f"Available slash commands: {commands}")
if "commit" in commands:
print("❌ /commit is available (unexpected)")
else:
print("✓ /commit is NOT available (expected)")
break
print()
async def example_project_and_user():
"""Load both project and user settings."""
print("=== Project + User Settings Example ===")
print("Setting sources: ['user', 'project']")
print("Expected: Project slash commands (like /commit) WILL be available\n")
sdk_dir = Path(__file__).parent.parent
options = ClaudeAgentOptions(
setting_sources=["user", "project"],
cwd=sdk_dir,
)
async with ClaudeSDKClient(options=options) as client:
await client.query("What is 2 + 2?")
async for msg in client.receive_response():
if isinstance(msg, SystemMessage) and msg.subtype == "init":
commands = extract_slash_commands(msg)
print(f"Available slash commands: {commands}")
if "commit" in commands:
print("✓ /commit is available (expected)")
else:
print("❌ /commit is NOT available (unexpected)")
break
print()
async def main():
"""Run all examples or a specific example based on command line argument."""
examples = {
"default": example_default,
"user_only": example_user_only,
"project_and_user": example_project_and_user,
}
if len(sys.argv) < 2:
print("Usage: python setting_sources.py <example_name>")
print("\nAvailable examples:")
print(" all - Run all examples")
for name in examples:
print(f" {name}")
sys.exit(0)
example_name = sys.argv[1]
if example_name == "all":
for example in examples.values():
await example()
print("-" * 50 + "\n")
elif example_name in examples:
await examples[example_name]()
else:
print(f"Error: Unknown example '{example_name}'")
print("\nAvailable examples:")
print(" all - Run all examples")
for name in examples:
print(f" {name}")
sys.exit(1)
if __name__ == "__main__":
print("Starting Claude SDK Setting Sources Examples...")
print("=" * 50 + "\n")
asyncio.run(main())