or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration-options.mdcustom-tools.mderror-handling.mdhook-system.mdindex.mdinteractive-client.mdmessage-types.mdsimple-queries.mdtransport-system.md

configuration-options.mddocs/

0

# Configuration and Options

1

2

The `ClaudeCodeOptions` dataclass provides comprehensive configuration for controlling Claude Code behavior including tool permissions, working directory, system prompts, MCP server configurations, and advanced features.

3

4

## Capabilities

5

6

### Main Configuration Class

7

8

Central configuration object for all Claude Code SDK options and settings.

9

10

```python { .api }

11

@dataclass

12

class ClaudeCodeOptions:

13

"""Query options for Claude SDK."""

14

15

allowed_tools: list[str] = field(default_factory=list)

16

system_prompt: str | None = None

17

append_system_prompt: str | None = None

18

mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)

19

permission_mode: PermissionMode | None = None

20

continue_conversation: bool = False

21

resume: str | None = None

22

max_turns: int | None = None

23

disallowed_tools: list[str] = field(default_factory=list)

24

model: str | None = None

25

permission_prompt_tool_name: str | None = None

26

cwd: str | Path | None = None

27

settings: str | None = None

28

add_dirs: list[str | Path] = field(default_factory=list)

29

env: dict[str, str] = field(default_factory=dict)

30

extra_args: dict[str, str | None] = field(default_factory=dict)

31

debug_stderr: Any = sys.stderr

32

can_use_tool: CanUseTool | None = None

33

hooks: dict[HookEvent, list[HookMatcher]] | None = None

34

user: str | None = None

35

include_partial_messages: bool = False

36

```

37

38

### Permission Modes

39

40

Control how tool execution permissions are handled.

41

42

```python { .api }

43

PermissionMode = Literal["default", "acceptEdits", "plan", "bypassPermissions"]

44

```

45

46

**Permission Modes:**

47

- `"default"`: CLI prompts for dangerous tools (interactive)

48

- `"acceptEdits"`: Auto-accept file edits while prompting for other dangerous operations

49

- `"plan"`: Show execution plan without running tools

50

- `"bypassPermissions"`: Allow all tools without prompts (use with caution)

51

52

### MCP Server Configuration Types

53

54

Support for multiple MCP server types including in-process SDK servers.

55

56

```python { .api }

57

McpServerConfig = (

58

McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig

59

)

60

61

class McpStdioServerConfig(TypedDict):

62

"""MCP stdio server configuration."""

63

type: NotRequired[Literal["stdio"]] # Optional for backwards compatibility

64

command: str

65

args: NotRequired[list[str]]

66

env: NotRequired[dict[str, str]]

67

68

class McpSSEServerConfig(TypedDict):

69

"""MCP SSE server configuration."""

70

type: Literal["sse"]

71

url: str

72

headers: NotRequired[dict[str, str]]

73

74

class McpHttpServerConfig(TypedDict):

75

"""MCP HTTP server configuration."""

76

type: Literal["http"]

77

url: str

78

headers: NotRequired[dict[str, str]]

79

80

class McpSdkServerConfig(TypedDict):

81

"""SDK MCP server configuration."""

82

type: Literal["sdk"]

83

name: str

84

instance: "McpServer"

85

```

86

87

## Usage Examples

88

89

### Basic Configuration

90

91

```python

92

from claude_code_sdk import ClaudeCodeOptions, query

93

94

# Simple configuration

95

options = ClaudeCodeOptions(

96

system_prompt="You are a helpful Python developer",

97

allowed_tools=["Read", "Write", "Bash"],

98

max_turns=5

99

)

100

101

async def main():

102

async for message in query(

103

prompt="Create a simple web server",

104

options=options

105

):

106

print(message)

107

```

108

109

### Working Directory Configuration

110

111

```python

112

from pathlib import Path

113

from claude_code_sdk import ClaudeCodeOptions

114

115

# Using string path

116

options = ClaudeCodeOptions(

117

cwd="/home/user/my-project",

118

allowed_tools=["Read", "Write", "Bash"]

119

)

120

121

# Using Path object

122

project_path = Path.home() / "projects" / "my-app"

123

options = ClaudeCodeOptions(

124

cwd=project_path,

125

allowed_tools=["Read", "Write", "Bash"]

126

)

127

```

128

129

### Permission Configuration

130

131

```python

132

from claude_code_sdk import ClaudeCodeOptions

133

134

# Auto-accept file edits but prompt for other dangerous operations

135

options = ClaudeCodeOptions(

136

permission_mode="acceptEdits",

137

allowed_tools=["Read", "Write", "Edit", "Bash"]

138

)

139

140

# Bypass all permissions (use with extreme caution)

141

options = ClaudeCodeOptions(

142

permission_mode="bypassPermissions",

143

allowed_tools=["Read", "Write", "Edit", "Bash", "WebSearch"]

144

)

145

146

# Plan mode - show what would be done without executing

147

options = ClaudeCodeOptions(

148

permission_mode="plan",

149

allowed_tools=["Read", "Write", "Edit", "Bash"]

150

)

151

```

152

153

### MCP Server Configuration

154

155

```python

156

from claude_code_sdk import ClaudeCodeOptions, create_sdk_mcp_server, tool

157

158

# SDK (in-process) server

159

@tool("calculate", "Perform calculation", {"expression": str})

160

async def calculate(args):

161

result = eval(args["expression"]) # In production, use safe evaluation

162

return {"content": [{"type": "text", "text": f"Result: {result}"}]}

163

164

sdk_server = create_sdk_mcp_server("calculator", tools=[calculate])

165

166

# External stdio server

167

stdio_server = {

168

"type": "stdio",

169

"command": "python",

170

"args": ["-m", "external_server"],

171

"env": {"DEBUG": "1"}

172

}

173

174

# HTTP server

175

http_server = {

176

"type": "http",

177

"url": "http://localhost:8080/mcp",

178

"headers": {"Authorization": "Bearer token123"}

179

}

180

181

# SSE server

182

sse_server = {

183

"type": "sse",

184

"url": "http://localhost:8080/sse",

185

"headers": {"X-API-Key": "key123"}

186

}

187

188

options = ClaudeCodeOptions(

189

mcp_servers={

190

"calculator": sdk_server, # In-process server

191

"external": stdio_server, # External process

192

"remote_http": http_server, # HTTP server

193

"remote_sse": sse_server # SSE server

194

},

195

allowed_tools=[

196

"mcp__calculator__calculate",

197

"mcp__external__some_tool",

198

"mcp__remote_http__api_call",

199

"mcp__remote_sse__stream_data"

200

]

201

)

202

```

203

204

### Advanced Configuration

205

206

```python

207

from claude_code_sdk import ClaudeCodeOptions, HookMatcher

208

209

async def pre_tool_hook(input_data, tool_use_id, context):

210

# Custom validation logic

211

return {}

212

213

options = ClaudeCodeOptions(

214

# Basic settings

215

system_prompt="You are an expert developer",

216

append_system_prompt="Always explain your reasoning",

217

model="claude-3-5-sonnet-20241022",

218

max_turns=10,

219

user="developer_123",

220

221

# Tool configuration

222

allowed_tools=["Read", "Write", "Edit", "Bash", "WebSearch"],

223

disallowed_tools=["dangerous_tool"],

224

225

# Permission and security

226

permission_mode="acceptEdits",

227

228

# Working environment

229

cwd="/workspace/project",

230

add_dirs=["/workspace/shared", "/workspace/libs"],

231

env={

232

"PYTHON_PATH": "/workspace/python",

233

"NODE_PATH": "/workspace/node_modules",

234

"DEBUG": "1"

235

},

236

237

# Advanced features

238

continue_conversation=True,

239

resume="session_id_123",

240

include_partial_messages=True,

241

242

# Hooks

243

hooks={

244

"PreToolUse": [

245

HookMatcher(matcher="Bash|Write|Edit", hooks=[pre_tool_hook])

246

]

247

},

248

249

# CLI integration

250

settings="/path/to/claude/settings.json",

251

extra_args={

252

"--verbose": None,

253

"--output-style": "detailed",

254

"--custom-flag": "value"

255

},

256

debug_stderr=open("/tmp/claude_debug.log", "w")

257

)

258

```

259

260

### Permission Callback Configuration

261

262

```python

263

from claude_code_sdk import (

264

ClaudeCodeOptions, PermissionResultAllow, PermissionResultDeny,

265

ToolPermissionContext

266

)

267

268

async def custom_permission_checker(

269

tool_name: str,

270

tool_input: dict[str, Any],

271

context: ToolPermissionContext

272

) -> PermissionResult:

273

"""Custom permission checker for tool usage."""

274

275

# Allow read operations

276

if tool_name in ["Read", "Glob", "Grep"]:

277

return PermissionResultAllow()

278

279

# Require approval for write operations

280

if tool_name in ["Write", "Edit", "MultiEdit"]:

281

# In a real application, you might show a UI prompt

282

user_approval = await get_user_approval(f"Allow {tool_name} operation?")

283

284

if user_approval:

285

return PermissionResultAllow()

286

else:

287

return PermissionResultDeny(

288

message=f"User denied {tool_name} operation",

289

interrupt=False

290

)

291

292

# Deny dangerous operations

293

if tool_name == "Bash" and any(cmd in str(tool_input) for cmd in ["rm -rf", "format"]):

294

return PermissionResultDeny(

295

message="Dangerous command blocked",

296

interrupt=True

297

)

298

299

# Default allow

300

return PermissionResultAllow()

301

302

# Note: can_use_tool requires streaming mode (AsyncIterable prompt)

303

options = ClaudeCodeOptions(

304

can_use_tool=custom_permission_checker,

305

allowed_tools=["Read", "Write", "Edit", "Bash"]

306

)

307

308

# This requires using ClaudeSDKClient, not the query() function

309

async def main():

310

async with ClaudeSDKClient(options=options) as client:

311

await client.query("Create a new Python file")

312

313

async for msg in client.receive_response():

314

print(msg)

315

```

316

317

### Environment and Directory Configuration

318

319

```python

320

import os

321

from pathlib import Path

322

from claude_code_sdk import ClaudeCodeOptions

323

324

# Set up project environment

325

project_root = Path("/workspace/my-project")

326

venv_path = project_root / "venv"

327

328

options = ClaudeCodeOptions(

329

cwd=project_root,

330

add_dirs=[

331

project_root / "src",

332

project_root / "tests",

333

project_root / "docs"

334

],

335

env={

336

"VIRTUAL_ENV": str(venv_path),

337

"PATH": f"{venv_path / 'bin'}:{os.environ['PATH']}",

338

"PYTHONPATH": str(project_root / "src"),

339

"PROJECT_ROOT": str(project_root),

340

"ENVIRONMENT": "development"

341

},

342

allowed_tools=["Read", "Write", "Edit", "Bash", "WebSearch"]

343

)

344

```

345

346

## Configuration Validation

347

348

Some configuration options have validation rules:

349

350

### Permission System Validation

351

352

- `can_use_tool` callback requires streaming mode (AsyncIterable prompt)

353

- `can_use_tool` and `permission_prompt_tool_name` are mutually exclusive

354

- When using `can_use_tool`, the SDK automatically sets `permission_prompt_tool_name="stdio"`

355

356

### MCP Server Validation

357

358

- Server names in `mcp_servers` must be unique

359

- SDK MCP servers must have valid `McpServer` instances

360

- External server configurations must have valid command/URL paths

361

362

### Tool Configuration Validation

363

364

- Tools in `allowed_tools` must exist or be provided by configured MCP servers

365

- `disallowed_tools` takes precedence over `allowed_tools`

366

- MCP tool names follow the pattern `mcp__<server_name>__<tool_name>`

367

368

## Default Values

369

370

When `ClaudeCodeOptions()` is instantiated with no arguments:

371

372

```python

373

ClaudeCodeOptions(

374

allowed_tools=[], # No tools allowed by default

375

system_prompt=None, # No custom system prompt

376

permission_mode=None, # Use Claude Code's default behavior

377

cwd=None, # Use current working directory

378

mcp_servers={}, # No MCP servers

379

max_turns=None, # No turn limit

380

continue_conversation=False, # Start fresh conversation

381

include_partial_messages=False, # No streaming message updates

382

# ... other fields use their default values

383

)

384

```

385

386

## Integration with SDK Functions

387

388

- `query()`: Accepts `options` parameter with `ClaudeCodeOptions` instance

389

- `ClaudeSDKClient`: Accepts `options` parameter in constructor

390

- All configuration options work with both unidirectional and bidirectional communication patterns

391

392

For specific tool and permission configurations, see:

393

- [Custom Tools](./custom-tools.md) for MCP server setup

394

- [Hook System](./hook-system.md) for hook configuration

395

- [Error Handling](./error-handling.md) for debug and error handling options