claude-agent-sdk 0.0.23__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of claude-agent-sdk might be problematic. Click here for more details.

Files changed (32) hide show
  1. claude_agent_sdk-0.0.23/.gitignore +50 -0
  2. claude_agent_sdk-0.0.23/LICENSE +21 -0
  3. claude_agent_sdk-0.0.23/PKG-INFO +309 -0
  4. claude_agent_sdk-0.0.23/README.md +276 -0
  5. claude_agent_sdk-0.0.23/pyproject.toml +108 -0
  6. claude_agent_sdk-0.0.23/src/claude_agent_sdk/__init__.py +325 -0
  7. claude_agent_sdk-0.0.23/src/claude_agent_sdk/_errors.py +56 -0
  8. claude_agent_sdk-0.0.23/src/claude_agent_sdk/_internal/__init__.py +1 -0
  9. claude_agent_sdk-0.0.23/src/claude_agent_sdk/_internal/client.py +121 -0
  10. claude_agent_sdk-0.0.23/src/claude_agent_sdk/_internal/message_parser.py +172 -0
  11. claude_agent_sdk-0.0.23/src/claude_agent_sdk/_internal/query.py +523 -0
  12. claude_agent_sdk-0.0.23/src/claude_agent_sdk/_internal/transport/__init__.py +68 -0
  13. claude_agent_sdk-0.0.23/src/claude_agent_sdk/_internal/transport/subprocess_cli.py +456 -0
  14. claude_agent_sdk-0.0.23/src/claude_agent_sdk/_version.py +3 -0
  15. claude_agent_sdk-0.0.23/src/claude_agent_sdk/client.py +325 -0
  16. claude_agent_sdk-0.0.23/src/claude_agent_sdk/py.typed +0 -0
  17. claude_agent_sdk-0.0.23/src/claude_agent_sdk/query.py +126 -0
  18. claude_agent_sdk-0.0.23/src/claude_agent_sdk/types.py +412 -0
  19. claude_agent_sdk-0.0.23/tests/conftest.py +4 -0
  20. claude_agent_sdk-0.0.23/tests/mock_transport.py +177 -0
  21. claude_agent_sdk-0.0.23/tests/test_changelog.py +85 -0
  22. claude_agent_sdk-0.0.23/tests/test_client.py +123 -0
  23. claude_agent_sdk-0.0.23/tests/test_errors.py +52 -0
  24. claude_agent_sdk-0.0.23/tests/test_hooks.py +148 -0
  25. claude_agent_sdk-0.0.23/tests/test_integration.py +214 -0
  26. claude_agent_sdk-0.0.23/tests/test_message_parser.py +284 -0
  27. claude_agent_sdk-0.0.23/tests/test_sdk_mcp_integration.py +193 -0
  28. claude_agent_sdk-0.0.23/tests/test_streaming_client.py +828 -0
  29. claude_agent_sdk-0.0.23/tests/test_subprocess_buffering.py +307 -0
  30. claude_agent_sdk-0.0.23/tests/test_tool_callbacks.py +289 -0
  31. claude_agent_sdk-0.0.23/tests/test_transport.py +438 -0
  32. claude_agent_sdk-0.0.23/tests/test_types.py +151 -0
@@ -0,0 +1,50 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ MANIFEST
23
+
24
+ # Virtual environments
25
+ venv/
26
+ ENV/
27
+ env/
28
+ .venv
29
+
30
+ # IDEs
31
+ .vscode/
32
+ .idea/
33
+ *.swp
34
+ *.swo
35
+ *~
36
+ **/.DS_Store
37
+
38
+ # Testing
39
+ .tox/
40
+ .coverage
41
+ .coverage.*
42
+ .cache
43
+ .pytest_cache/
44
+ htmlcov/
45
+
46
+ # Type checking
47
+ .mypy_cache/
48
+ .dmypy.json
49
+ dmypy.json
50
+ .pyre/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Anthropic, PBC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,309 @@
1
+ Metadata-Version: 2.4
2
+ Name: claude-agent-sdk
3
+ Version: 0.0.23
4
+ Summary: Python SDK for Claude Code
5
+ Project-URL: Homepage, https://github.com/anthropics/claude-agent-sdk-python
6
+ Project-URL: Documentation, https://docs.anthropic.com/en/docs/claude-code/sdk
7
+ Project-URL: Issues, https://github.com/anthropics/claude-agent-sdk-python/issues
8
+ Author-email: Anthropic <support@anthropic.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai,anthropic,claude,sdk
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: anyio>=4.0.0
23
+ Requires-Dist: mcp>=0.1.0
24
+ Requires-Dist: typing-extensions>=4.0.0; python_version < '3.11'
25
+ Provides-Extra: dev
26
+ Requires-Dist: anyio[trio]>=4.0.0; extra == 'dev'
27
+ Requires-Dist: mypy>=1.0.0; extra == 'dev'
28
+ Requires-Dist: pytest-asyncio>=0.20.0; extra == 'dev'
29
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
30
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
31
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # Claude Agent SDK for Python
35
+
36
+ Python SDK for Claude Agent. See the [Claude Agent SDK documentation](https://docs.anthropic.com/en/docs/claude-code/sdk/sdk-python) for more information.
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ pip install claude-agent-sdk
42
+ ```
43
+
44
+ **Prerequisites:**
45
+ - Python 3.10+
46
+ - Node.js
47
+ - Claude Code: `npm install -g @anthropic-ai/claude-code`
48
+
49
+ ## Quick Start
50
+
51
+ ```python
52
+ import anyio
53
+ from claude_agent_sdk import query
54
+
55
+ async def main():
56
+ async for message in query(prompt="What is 2 + 2?"):
57
+ print(message)
58
+
59
+ anyio.run(main)
60
+ ```
61
+
62
+ ## Basic Usage: query()
63
+
64
+ `query()` is an async function for querying Claude Code. It returns an `AsyncIterator` of response messages. See [src/claude_agent_sdk/query.py](src/claude_agent_sdk/query.py).
65
+
66
+ ```python
67
+ from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock
68
+
69
+ # Simple query
70
+ async for message in query(prompt="Hello Claude"):
71
+ if isinstance(message, AssistantMessage):
72
+ for block in message.content:
73
+ if isinstance(block, TextBlock):
74
+ print(block.text)
75
+
76
+ # With options
77
+ options = ClaudeAgentOptions(
78
+ system_prompt="You are a helpful assistant",
79
+ max_turns=1
80
+ )
81
+
82
+ async for message in query(prompt="Tell me a joke", options=options):
83
+ print(message)
84
+ ```
85
+
86
+ ### Using Tools
87
+
88
+ ```python
89
+ options = ClaudeAgentOptions(
90
+ allowed_tools=["Read", "Write", "Bash"],
91
+ permission_mode='acceptEdits' # auto-accept file edits
92
+ )
93
+
94
+ async for message in query(
95
+ prompt="Create a hello.py file",
96
+ options=options
97
+ ):
98
+ # Process tool use and results
99
+ pass
100
+ ```
101
+
102
+ ### Working Directory
103
+
104
+ ```python
105
+ from pathlib import Path
106
+
107
+ options = ClaudeAgentOptions(
108
+ cwd="/path/to/project" # or Path("/path/to/project")
109
+ )
110
+ ```
111
+
112
+ ## ClaudeSDKClient
113
+
114
+ `ClaudeSDKClient` supports bidirectional, interactive conversations with Claude
115
+ Code. See [src/claude_agent_sdk/client.py](src/claude_agent_sdk/client.py).
116
+
117
+ Unlike `query()`, `ClaudeSDKClient` additionally enables **custom tools** and **hooks**, both of which can be defined as Python functions.
118
+
119
+ ### Custom Tools (as In-Process SDK MCP Servers)
120
+
121
+ A **custom tool** is a Python function that you can offer to Claude, for Claude to invoke as needed.
122
+
123
+ Custom tools are implemented in-process MCP servers that run directly within your Python application, eliminating the need for separate processes that regular MCP servers require.
124
+
125
+ For an end-to-end example, see [MCP Calculator](examples/mcp_calculator.py).
126
+
127
+ #### Creating a Simple Tool
128
+
129
+ ```python
130
+ from claude_agent_sdk import tool, create_sdk_mcp_server, ClaudeAgentOptions, ClaudeSDKClient
131
+
132
+ # Define a tool using the @tool decorator
133
+ @tool("greet", "Greet a user", {"name": str})
134
+ async def greet_user(args):
135
+ return {
136
+ "content": [
137
+ {"type": "text", "text": f"Hello, {args['name']}!"}
138
+ ]
139
+ }
140
+
141
+ # Create an SDK MCP server
142
+ server = create_sdk_mcp_server(
143
+ name="my-tools",
144
+ version="1.0.0",
145
+ tools=[greet_user]
146
+ )
147
+
148
+ # Use it with Claude
149
+ options = ClaudeAgentOptions(
150
+ mcp_servers={"tools": server},
151
+ allowed_tools=["mcp__tools__greet"]
152
+ )
153
+
154
+ async with ClaudeSDKClient(options=options) as client:
155
+ await client.query("Greet Alice")
156
+
157
+ # Extract and print response
158
+ async for msg in client.receive_response():
159
+ print(msg)
160
+ ```
161
+
162
+ #### Benefits Over External MCP Servers
163
+
164
+ - **No subprocess management** - Runs in the same process as your application
165
+ - **Better performance** - No IPC overhead for tool calls
166
+ - **Simpler deployment** - Single Python process instead of multiple
167
+ - **Easier debugging** - All code runs in the same process
168
+ - **Type safety** - Direct Python function calls with type hints
169
+
170
+ #### Migration from External Servers
171
+
172
+ ```python
173
+ # BEFORE: External MCP server (separate process)
174
+ options = ClaudeAgentOptions(
175
+ mcp_servers={
176
+ "calculator": {
177
+ "type": "stdio",
178
+ "command": "python",
179
+ "args": ["-m", "calculator_server"]
180
+ }
181
+ }
182
+ )
183
+
184
+ # AFTER: SDK MCP server (in-process)
185
+ from my_tools import add, subtract # Your tool functions
186
+
187
+ calculator = create_sdk_mcp_server(
188
+ name="calculator",
189
+ tools=[add, subtract]
190
+ )
191
+
192
+ options = ClaudeAgentOptions(
193
+ mcp_servers={"calculator": calculator}
194
+ )
195
+ ```
196
+
197
+ #### Mixed Server Support
198
+
199
+ You can use both SDK and external MCP servers together:
200
+
201
+ ```python
202
+ options = ClaudeAgentOptions(
203
+ mcp_servers={
204
+ "internal": sdk_server, # In-process SDK server
205
+ "external": { # External subprocess server
206
+ "type": "stdio",
207
+ "command": "external-server"
208
+ }
209
+ }
210
+ )
211
+ ```
212
+
213
+ ### Hooks
214
+
215
+ A **hook** is a Python function that the Claude Code *application* (*not* Claude) invokes at specific points of the Claude agent loop. Hooks can provide deterministic processing and automated feedback for Claude. Read more in [Claude Code Hooks Reference](https://docs.anthropic.com/en/docs/claude-code/hooks).
216
+
217
+ For more examples, see examples/hooks.py.
218
+
219
+ #### Example
220
+
221
+ ```python
222
+ from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient, HookMatcher
223
+
224
+ async def check_bash_command(input_data, tool_use_id, context):
225
+ tool_name = input_data["tool_name"]
226
+ tool_input = input_data["tool_input"]
227
+ if tool_name != "Bash":
228
+ return {}
229
+ command = tool_input.get("command", "")
230
+ block_patterns = ["foo.sh"]
231
+ for pattern in block_patterns:
232
+ if pattern in command:
233
+ return {
234
+ "hookSpecificOutput": {
235
+ "hookEventName": "PreToolUse",
236
+ "permissionDecision": "deny",
237
+ "permissionDecisionReason": f"Command contains invalid pattern: {pattern}",
238
+ }
239
+ }
240
+ return {}
241
+
242
+ options = ClaudeAgentOptions(
243
+ allowed_tools=["Bash"],
244
+ hooks={
245
+ "PreToolUse": [
246
+ HookMatcher(matcher="Bash", hooks=[check_bash_command]),
247
+ ],
248
+ }
249
+ )
250
+
251
+ async with ClaudeSDKClient(options=options) as client:
252
+ # Test 1: Command with forbidden pattern (will be blocked)
253
+ await client.query("Run the bash command: ./foo.sh --help")
254
+ async for msg in client.receive_response():
255
+ print(msg)
256
+
257
+ print("\n" + "=" * 50 + "\n")
258
+
259
+ # Test 2: Safe command that should work
260
+ await client.query("Run the bash command: echo 'Hello from hooks example!'")
261
+ async for msg in client.receive_response():
262
+ print(msg)
263
+ ```
264
+
265
+
266
+ ## Types
267
+
268
+ See [src/claude_agent_sdk/types.py](src/claude_agent_sdk/types.py) for complete type definitions:
269
+ - `ClaudeAgentOptions` - Configuration options
270
+ - `AssistantMessage`, `UserMessage`, `SystemMessage`, `ResultMessage` - Message types
271
+ - `TextBlock`, `ToolUseBlock`, `ToolResultBlock` - Content blocks
272
+
273
+ ## Error Handling
274
+
275
+ ```python
276
+ from claude_agent_sdk import (
277
+ ClaudeSDKError, # Base error
278
+ CLINotFoundError, # Claude Code not installed
279
+ CLIConnectionError, # Connection issues
280
+ ProcessError, # Process failed
281
+ CLIJSONDecodeError, # JSON parsing issues
282
+ )
283
+
284
+ try:
285
+ async for message in query(prompt="Hello"):
286
+ pass
287
+ except CLINotFoundError:
288
+ print("Please install Claude Code")
289
+ except ProcessError as e:
290
+ print(f"Process failed with exit code: {e.exit_code}")
291
+ except CLIJSONDecodeError as e:
292
+ print(f"Failed to parse response: {e}")
293
+ ```
294
+
295
+ See [src/claude_agent_sdk/_errors.py](src/claude_agent_sdk/_errors.py) for all error types.
296
+
297
+ ## Available Tools
298
+
299
+ See the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code/settings#tools-available-to-claude) for a complete list of available tools.
300
+
301
+ ## Examples
302
+
303
+ See [examples/quick_start.py](examples/quick_start.py) for a complete working example.
304
+
305
+ See [examples/streaming_mode.py](examples/streaming_mode.py) for comprehensive examples involving `ClaudeSDKClient`. You can even run interactive examples in IPython from [examples/streaming_mode_ipython.py](examples/streaming_mode_ipython.py).
306
+
307
+ ## License
308
+
309
+ MIT
@@ -0,0 +1,276 @@
1
+ # Claude Agent SDK for Python
2
+
3
+ Python SDK for Claude Agent. See the [Claude Agent SDK documentation](https://docs.anthropic.com/en/docs/claude-code/sdk/sdk-python) for more information.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install claude-agent-sdk
9
+ ```
10
+
11
+ **Prerequisites:**
12
+ - Python 3.10+
13
+ - Node.js
14
+ - Claude Code: `npm install -g @anthropic-ai/claude-code`
15
+
16
+ ## Quick Start
17
+
18
+ ```python
19
+ import anyio
20
+ from claude_agent_sdk import query
21
+
22
+ async def main():
23
+ async for message in query(prompt="What is 2 + 2?"):
24
+ print(message)
25
+
26
+ anyio.run(main)
27
+ ```
28
+
29
+ ## Basic Usage: query()
30
+
31
+ `query()` is an async function for querying Claude Code. It returns an `AsyncIterator` of response messages. See [src/claude_agent_sdk/query.py](src/claude_agent_sdk/query.py).
32
+
33
+ ```python
34
+ from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock
35
+
36
+ # Simple query
37
+ async for message in query(prompt="Hello Claude"):
38
+ if isinstance(message, AssistantMessage):
39
+ for block in message.content:
40
+ if isinstance(block, TextBlock):
41
+ print(block.text)
42
+
43
+ # With options
44
+ options = ClaudeAgentOptions(
45
+ system_prompt="You are a helpful assistant",
46
+ max_turns=1
47
+ )
48
+
49
+ async for message in query(prompt="Tell me a joke", options=options):
50
+ print(message)
51
+ ```
52
+
53
+ ### Using Tools
54
+
55
+ ```python
56
+ options = ClaudeAgentOptions(
57
+ allowed_tools=["Read", "Write", "Bash"],
58
+ permission_mode='acceptEdits' # auto-accept file edits
59
+ )
60
+
61
+ async for message in query(
62
+ prompt="Create a hello.py file",
63
+ options=options
64
+ ):
65
+ # Process tool use and results
66
+ pass
67
+ ```
68
+
69
+ ### Working Directory
70
+
71
+ ```python
72
+ from pathlib import Path
73
+
74
+ options = ClaudeAgentOptions(
75
+ cwd="/path/to/project" # or Path("/path/to/project")
76
+ )
77
+ ```
78
+
79
+ ## ClaudeSDKClient
80
+
81
+ `ClaudeSDKClient` supports bidirectional, interactive conversations with Claude
82
+ Code. See [src/claude_agent_sdk/client.py](src/claude_agent_sdk/client.py).
83
+
84
+ Unlike `query()`, `ClaudeSDKClient` additionally enables **custom tools** and **hooks**, both of which can be defined as Python functions.
85
+
86
+ ### Custom Tools (as In-Process SDK MCP Servers)
87
+
88
+ A **custom tool** is a Python function that you can offer to Claude, for Claude to invoke as needed.
89
+
90
+ Custom tools are implemented in-process MCP servers that run directly within your Python application, eliminating the need for separate processes that regular MCP servers require.
91
+
92
+ For an end-to-end example, see [MCP Calculator](examples/mcp_calculator.py).
93
+
94
+ #### Creating a Simple Tool
95
+
96
+ ```python
97
+ from claude_agent_sdk import tool, create_sdk_mcp_server, ClaudeAgentOptions, ClaudeSDKClient
98
+
99
+ # Define a tool using the @tool decorator
100
+ @tool("greet", "Greet a user", {"name": str})
101
+ async def greet_user(args):
102
+ return {
103
+ "content": [
104
+ {"type": "text", "text": f"Hello, {args['name']}!"}
105
+ ]
106
+ }
107
+
108
+ # Create an SDK MCP server
109
+ server = create_sdk_mcp_server(
110
+ name="my-tools",
111
+ version="1.0.0",
112
+ tools=[greet_user]
113
+ )
114
+
115
+ # Use it with Claude
116
+ options = ClaudeAgentOptions(
117
+ mcp_servers={"tools": server},
118
+ allowed_tools=["mcp__tools__greet"]
119
+ )
120
+
121
+ async with ClaudeSDKClient(options=options) as client:
122
+ await client.query("Greet Alice")
123
+
124
+ # Extract and print response
125
+ async for msg in client.receive_response():
126
+ print(msg)
127
+ ```
128
+
129
+ #### Benefits Over External MCP Servers
130
+
131
+ - **No subprocess management** - Runs in the same process as your application
132
+ - **Better performance** - No IPC overhead for tool calls
133
+ - **Simpler deployment** - Single Python process instead of multiple
134
+ - **Easier debugging** - All code runs in the same process
135
+ - **Type safety** - Direct Python function calls with type hints
136
+
137
+ #### Migration from External Servers
138
+
139
+ ```python
140
+ # BEFORE: External MCP server (separate process)
141
+ options = ClaudeAgentOptions(
142
+ mcp_servers={
143
+ "calculator": {
144
+ "type": "stdio",
145
+ "command": "python",
146
+ "args": ["-m", "calculator_server"]
147
+ }
148
+ }
149
+ )
150
+
151
+ # AFTER: SDK MCP server (in-process)
152
+ from my_tools import add, subtract # Your tool functions
153
+
154
+ calculator = create_sdk_mcp_server(
155
+ name="calculator",
156
+ tools=[add, subtract]
157
+ )
158
+
159
+ options = ClaudeAgentOptions(
160
+ mcp_servers={"calculator": calculator}
161
+ )
162
+ ```
163
+
164
+ #### Mixed Server Support
165
+
166
+ You can use both SDK and external MCP servers together:
167
+
168
+ ```python
169
+ options = ClaudeAgentOptions(
170
+ mcp_servers={
171
+ "internal": sdk_server, # In-process SDK server
172
+ "external": { # External subprocess server
173
+ "type": "stdio",
174
+ "command": "external-server"
175
+ }
176
+ }
177
+ )
178
+ ```
179
+
180
+ ### Hooks
181
+
182
+ A **hook** is a Python function that the Claude Code *application* (*not* Claude) invokes at specific points of the Claude agent loop. Hooks can provide deterministic processing and automated feedback for Claude. Read more in [Claude Code Hooks Reference](https://docs.anthropic.com/en/docs/claude-code/hooks).
183
+
184
+ For more examples, see examples/hooks.py.
185
+
186
+ #### Example
187
+
188
+ ```python
189
+ from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient, HookMatcher
190
+
191
+ async def check_bash_command(input_data, tool_use_id, context):
192
+ tool_name = input_data["tool_name"]
193
+ tool_input = input_data["tool_input"]
194
+ if tool_name != "Bash":
195
+ return {}
196
+ command = tool_input.get("command", "")
197
+ block_patterns = ["foo.sh"]
198
+ for pattern in block_patterns:
199
+ if pattern in command:
200
+ return {
201
+ "hookSpecificOutput": {
202
+ "hookEventName": "PreToolUse",
203
+ "permissionDecision": "deny",
204
+ "permissionDecisionReason": f"Command contains invalid pattern: {pattern}",
205
+ }
206
+ }
207
+ return {}
208
+
209
+ options = ClaudeAgentOptions(
210
+ allowed_tools=["Bash"],
211
+ hooks={
212
+ "PreToolUse": [
213
+ HookMatcher(matcher="Bash", hooks=[check_bash_command]),
214
+ ],
215
+ }
216
+ )
217
+
218
+ async with ClaudeSDKClient(options=options) as client:
219
+ # Test 1: Command with forbidden pattern (will be blocked)
220
+ await client.query("Run the bash command: ./foo.sh --help")
221
+ async for msg in client.receive_response():
222
+ print(msg)
223
+
224
+ print("\n" + "=" * 50 + "\n")
225
+
226
+ # Test 2: Safe command that should work
227
+ await client.query("Run the bash command: echo 'Hello from hooks example!'")
228
+ async for msg in client.receive_response():
229
+ print(msg)
230
+ ```
231
+
232
+
233
+ ## Types
234
+
235
+ See [src/claude_agent_sdk/types.py](src/claude_agent_sdk/types.py) for complete type definitions:
236
+ - `ClaudeAgentOptions` - Configuration options
237
+ - `AssistantMessage`, `UserMessage`, `SystemMessage`, `ResultMessage` - Message types
238
+ - `TextBlock`, `ToolUseBlock`, `ToolResultBlock` - Content blocks
239
+
240
+ ## Error Handling
241
+
242
+ ```python
243
+ from claude_agent_sdk import (
244
+ ClaudeSDKError, # Base error
245
+ CLINotFoundError, # Claude Code not installed
246
+ CLIConnectionError, # Connection issues
247
+ ProcessError, # Process failed
248
+ CLIJSONDecodeError, # JSON parsing issues
249
+ )
250
+
251
+ try:
252
+ async for message in query(prompt="Hello"):
253
+ pass
254
+ except CLINotFoundError:
255
+ print("Please install Claude Code")
256
+ except ProcessError as e:
257
+ print(f"Process failed with exit code: {e.exit_code}")
258
+ except CLIJSONDecodeError as e:
259
+ print(f"Failed to parse response: {e}")
260
+ ```
261
+
262
+ See [src/claude_agent_sdk/_errors.py](src/claude_agent_sdk/_errors.py) for all error types.
263
+
264
+ ## Available Tools
265
+
266
+ See the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code/settings#tools-available-to-claude) for a complete list of available tools.
267
+
268
+ ## Examples
269
+
270
+ See [examples/quick_start.py](examples/quick_start.py) for a complete working example.
271
+
272
+ See [examples/streaming_mode.py](examples/streaming_mode.py) for comprehensive examples involving `ClaudeSDKClient`. You can even run interactive examples in IPython from [examples/streaming_mode_ipython.py](examples/streaming_mode_ipython.py).
273
+
274
+ ## License
275
+
276
+ MIT