codeforge-dev 1.4.0
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.
- package/.devcontainer/.env +22 -0
- package/.devcontainer/CHANGELOG.md +197 -0
- package/.devcontainer/CLAUDE.md +117 -0
- package/.devcontainer/README.md +222 -0
- package/.devcontainer/config/main-system-prompt.md +502 -0
- package/.devcontainer/config/settings.json +47 -0
- package/.devcontainer/devcontainer.json +94 -0
- package/.devcontainer/features/README.md +113 -0
- package/.devcontainer/features/agent-browser/README.md +65 -0
- package/.devcontainer/features/agent-browser/devcontainer-feature.json +23 -0
- package/.devcontainer/features/agent-browser/install.sh +79 -0
- package/.devcontainer/features/ast-grep/README.md +24 -0
- package/.devcontainer/features/ast-grep/devcontainer-feature.json +24 -0
- package/.devcontainer/features/ast-grep/install.sh +51 -0
- package/.devcontainer/features/ccstatusline/README.md +296 -0
- package/.devcontainer/features/ccstatusline/devcontainer-feature.json +19 -0
- package/.devcontainer/features/ccstatusline/install.sh +290 -0
- package/.devcontainer/features/ccusage/README.md +205 -0
- package/.devcontainer/features/ccusage/devcontainer-feature.json +38 -0
- package/.devcontainer/features/ccusage/install.sh +132 -0
- package/.devcontainer/features/claude-code/README.md +498 -0
- package/.devcontainer/features/claude-code/config/settings.json +36 -0
- package/.devcontainer/features/claude-code/config/system-prompt.md +118 -0
- package/.devcontainer/features/claude-code/config/world-building-sp.md +1432 -0
- package/.devcontainer/features/claude-code/devcontainer-feature.json +42 -0
- package/.devcontainer/features/claude-code/install.sh +466 -0
- package/.devcontainer/features/claude-monitor/README.md +74 -0
- package/.devcontainer/features/claude-monitor/devcontainer-feature.json +38 -0
- package/.devcontainer/features/claude-monitor/install.sh +99 -0
- package/.devcontainer/features/lsp-servers/README.md +85 -0
- package/.devcontainer/features/lsp-servers/devcontainer-feature.json +40 -0
- package/.devcontainer/features/lsp-servers/install.sh +116 -0
- package/.devcontainer/features/mcp-qdrant/CHANGES.md +399 -0
- package/.devcontainer/features/mcp-qdrant/README.md +474 -0
- package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +57 -0
- package/.devcontainer/features/mcp-qdrant/install.sh +295 -0
- package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +129 -0
- package/.devcontainer/features/mcp-reasoner/README.md +177 -0
- package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +20 -0
- package/.devcontainer/features/mcp-reasoner/install.sh +177 -0
- package/.devcontainer/features/mcp-reasoner/poststart-hook.sh +67 -0
- package/.devcontainer/features/notify-hook/README.md +86 -0
- package/.devcontainer/features/notify-hook/devcontainer-feature.json +23 -0
- package/.devcontainer/features/notify-hook/install.sh +38 -0
- package/.devcontainer/features/splitrail/README.md +140 -0
- package/.devcontainer/features/splitrail/devcontainer-feature.json +34 -0
- package/.devcontainer/features/splitrail/install.sh +129 -0
- package/.devcontainer/features/tree-sitter/README.md +138 -0
- package/.devcontainer/features/tree-sitter/devcontainer-feature.json +52 -0
- package/.devcontainer/features/tree-sitter/install.sh +173 -0
- package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +106 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-file.py +101 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/lint-file.py +137 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/.claude-plugin/plugin.json +8 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/SKILL.md +387 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/references/cli-flags-and-output.md +312 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/references/sdk-and-mcp.md +569 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/SKILL.md +309 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/references/compose-services.md +438 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/references/dockerfile-patterns.md +340 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/SKILL.md +412 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/references/container-lifecycle.md +388 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/references/resources-and-security.md +444 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/SKILL.md +344 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/middleware-and-lifespan.md +254 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/pydantic-models.md +245 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/routing-and-dependencies.md +255 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/sse-and-streaming.md +318 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/SKILL.md +345 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/references/agents-and-tools.md +271 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/references/models-and-streaming.md +422 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/SKILL.md +220 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/cross-vendor-principles.md +139 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/patterns-and-antipatterns.md +376 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/skill-authoring-patterns.md +356 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/SKILL.md +329 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/advanced-queries.md +314 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/javascript-patterns.md +323 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/python-patterns.md +354 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/schema-and-pragmas.md +326 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/SKILL.md +356 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/ai-sdk-svelte.md +128 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/component-patterns.md +332 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/layercake.md +203 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/migration-guide.md +350 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/runes-and-reactivity.md +328 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/spa-and-routing.md +262 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/svelte-dnd-action.md +181 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/SKILL.md +414 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/references/fastapi-testing.md +411 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/references/svelte-testing.md +538 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codeforge-lsp/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py +110 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +108 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272create-pr.md +337 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272new.md +166 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272review-commit.md +290 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272work.md +257 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/plugin.json +8 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/system-prompt.md +184 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/.claude-plugin/plugin.json +6 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/config/planning-instructions.md +14 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/functional-conjuring-map.md +989 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/hooks/hooks.json +33 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/__pycache__/post-enhance-task.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhance-planning.py +71 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-plan.sh +68 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-task.sh +120 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-plan.py +133 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-task.py +253 -0
- package/.devcontainer/scripts/setup-aliases.sh +80 -0
- package/.devcontainer/scripts/setup-config.sh +28 -0
- package/.devcontainer/scripts/setup-irie-claude.sh +32 -0
- package/.devcontainer/scripts/setup-plugins.sh +80 -0
- package/.devcontainer/scripts/setup.sh +58 -0
- package/LICENSE.txt +674 -0
- package/README.md +267 -0
- package/package.json +44 -0
- package/setup.js +83 -0
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
# SDK and MCP — Deep Dive
|
|
2
|
+
|
|
3
|
+
## 1. TypeScript SDK
|
|
4
|
+
|
|
5
|
+
### Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @anthropic-ai/claude-agent-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### query() Function
|
|
12
|
+
|
|
13
|
+
The primary interface. Returns an async generator that yields SDK messages:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
17
|
+
|
|
18
|
+
function query(params: {
|
|
19
|
+
prompt: string | AsyncIterable<SDKUserMessage>;
|
|
20
|
+
options?: Options;
|
|
21
|
+
}): Query;
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The `Query` object extends `AsyncGenerator<SDKMessage, void>` and exposes control methods:
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
interface Query extends AsyncGenerator<SDKMessage, void> {
|
|
28
|
+
interrupt(): Promise<void>;
|
|
29
|
+
rewindFiles(userMessageUuid: string): Promise<void>;
|
|
30
|
+
setPermissionMode(mode: PermissionMode): Promise<void>;
|
|
31
|
+
setModel(model?: string): Promise<void>;
|
|
32
|
+
setMaxThinkingTokens(maxThinkingTokens: number | null): Promise<void>;
|
|
33
|
+
supportedCommands(): Promise<SlashCommand[]>;
|
|
34
|
+
supportedModels(): Promise<ModelInfo[]>;
|
|
35
|
+
mcpServerStatus(): Promise<McpServerStatus[]>;
|
|
36
|
+
accountInfo(): Promise<AccountInfo>;
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Full Options Reference
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
interface Options {
|
|
44
|
+
abortController?: AbortController;
|
|
45
|
+
additionalDirectories?: string[];
|
|
46
|
+
agents?: Record<string, AgentDefinition>;
|
|
47
|
+
allowDangerouslySkipPermissions?: boolean;
|
|
48
|
+
allowedTools?: string[];
|
|
49
|
+
betas?: SdkBeta[];
|
|
50
|
+
canUseTool?: CanUseTool;
|
|
51
|
+
continue?: boolean;
|
|
52
|
+
cwd?: string;
|
|
53
|
+
disallowedTools?: string[];
|
|
54
|
+
enableFileCheckpointing?: boolean;
|
|
55
|
+
env?: Record<string, string>;
|
|
56
|
+
executable?: "bun" | "deno" | "node";
|
|
57
|
+
executableArgs?: string[];
|
|
58
|
+
fallbackModel?: string;
|
|
59
|
+
forkSession?: boolean;
|
|
60
|
+
hooks?: Partial<Record<HookEvent, HookCallbackMatcher[]>>;
|
|
61
|
+
includePartialMessages?: boolean;
|
|
62
|
+
maxBudgetUsd?: number;
|
|
63
|
+
maxThinkingTokens?: number;
|
|
64
|
+
maxTurns?: number;
|
|
65
|
+
mcpServers?: Record<string, McpServerConfig>;
|
|
66
|
+
model?: string;
|
|
67
|
+
outputFormat?: { type: "json_schema"; schema: JSONSchema };
|
|
68
|
+
pathToClaudeCodeExecutable?: string;
|
|
69
|
+
permissionMode?: PermissionMode;
|
|
70
|
+
permissionPromptToolName?: string;
|
|
71
|
+
plugins?: SdkPluginConfig[];
|
|
72
|
+
resume?: string;
|
|
73
|
+
resumeSessionAt?: string;
|
|
74
|
+
sandbox?: SandboxSettings;
|
|
75
|
+
settingSources?: SettingSource[];
|
|
76
|
+
stderr?: (data: string) => void;
|
|
77
|
+
strictMcpConfig?: boolean;
|
|
78
|
+
systemPrompt?: string | { type: "preset"; preset: "claude_code"; append?: string };
|
|
79
|
+
tools?: string[] | { type: "preset"; preset: "claude_code" };
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Complete Usage Example
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { query, type SDKMessage } from "@anthropic-ai/claude-agent-sdk";
|
|
87
|
+
|
|
88
|
+
const controller = new AbortController();
|
|
89
|
+
|
|
90
|
+
const messages = query({
|
|
91
|
+
prompt: "Refactor the database module to use connection pooling",
|
|
92
|
+
options: {
|
|
93
|
+
model: "sonnet",
|
|
94
|
+
maxTurns: 25,
|
|
95
|
+
maxBudgetUsd: 5.0,
|
|
96
|
+
allowedTools: ["Read", "Write", "Edit", "Bash(npm *)"],
|
|
97
|
+
disallowedTools: ["Bash(rm *)"],
|
|
98
|
+
permissionMode: "acceptEdits",
|
|
99
|
+
systemPrompt: {
|
|
100
|
+
type: "preset",
|
|
101
|
+
preset: "claude_code",
|
|
102
|
+
append: "Follow the existing code style. Prefer named exports.",
|
|
103
|
+
},
|
|
104
|
+
abortController: controller,
|
|
105
|
+
cwd: "/home/user/project",
|
|
106
|
+
stderr: (data) => process.stderr.write(data),
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
let sessionId: string | undefined;
|
|
111
|
+
|
|
112
|
+
for await (const msg of messages) {
|
|
113
|
+
switch (msg.type) {
|
|
114
|
+
case "system":
|
|
115
|
+
if (msg.subtype === "init") {
|
|
116
|
+
sessionId = msg.session_id;
|
|
117
|
+
console.log(`Session: ${sessionId}`);
|
|
118
|
+
console.log(`Model: ${msg.model}`);
|
|
119
|
+
console.log(`Tools: ${msg.tools.join(", ")}`);
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
|
|
123
|
+
case "assistant":
|
|
124
|
+
for (const block of msg.message.content) {
|
|
125
|
+
if ("text" in block) {
|
|
126
|
+
process.stdout.write(block.text);
|
|
127
|
+
} else if ("name" in block) {
|
|
128
|
+
console.log(`\n[Tool: ${block.name}]`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
break;
|
|
132
|
+
|
|
133
|
+
case "result":
|
|
134
|
+
console.log(`\n--- Result ---`);
|
|
135
|
+
console.log(`Status: ${msg.subtype}`);
|
|
136
|
+
console.log(`Turns: ${msg.num_turns}`);
|
|
137
|
+
console.log(`Cost: $${msg.total_cost_usd}`);
|
|
138
|
+
console.log(`Duration: ${msg.duration_ms}ms`);
|
|
139
|
+
if (msg.is_error && msg.errors) {
|
|
140
|
+
console.error(`Errors: ${msg.errors.join(", ")}`);
|
|
141
|
+
}
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 2. Python SDK
|
|
150
|
+
|
|
151
|
+
### Installation
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
pip install claude-agent-sdk
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Two Interfaces
|
|
158
|
+
|
|
159
|
+
| Feature | `query()` | `ClaudeSDKClient` |
|
|
160
|
+
|---------|-----------|-------------------|
|
|
161
|
+
| Session lifecycle | Creates new each call | Reuses across calls |
|
|
162
|
+
| Conversation | Single exchange | Multi-turn |
|
|
163
|
+
| Interrupts | Not supported | `client.interrupt()` |
|
|
164
|
+
| Custom tools | Via MCP config | Via MCP config |
|
|
165
|
+
|
|
166
|
+
### query() Function
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
import asyncio
|
|
170
|
+
from claude_agent_sdk import query, ClaudeAgentOptions
|
|
171
|
+
|
|
172
|
+
async def main():
|
|
173
|
+
session_id = None
|
|
174
|
+
|
|
175
|
+
async for message in query(
|
|
176
|
+
prompt="Analyze the test coverage gaps",
|
|
177
|
+
options=ClaudeAgentOptions(
|
|
178
|
+
model="sonnet",
|
|
179
|
+
max_turns=15,
|
|
180
|
+
max_budget_usd=2.0,
|
|
181
|
+
allowed_tools=["Read", "Glob", "Grep", "Bash(pytest *)"],
|
|
182
|
+
permission_mode="plan",
|
|
183
|
+
system_prompt={
|
|
184
|
+
"type": "preset",
|
|
185
|
+
"preset": "claude_code",
|
|
186
|
+
"append": "Focus on untested edge cases.",
|
|
187
|
+
},
|
|
188
|
+
),
|
|
189
|
+
):
|
|
190
|
+
if hasattr(message, "subtype") and message.subtype == "init":
|
|
191
|
+
session_id = message.session_id
|
|
192
|
+
print(f"Session: {session_id}")
|
|
193
|
+
elif hasattr(message, "content"):
|
|
194
|
+
for block in message.content:
|
|
195
|
+
if hasattr(block, "text"):
|
|
196
|
+
print(block.text, end="")
|
|
197
|
+
elif hasattr(message, "total_cost_usd"):
|
|
198
|
+
print(f"\nCost: ${message.total_cost_usd}")
|
|
199
|
+
|
|
200
|
+
asyncio.run(main())
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### ClaudeSDKClient for Multi-Turn Sessions
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
import asyncio
|
|
207
|
+
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
|
|
208
|
+
|
|
209
|
+
async def main():
|
|
210
|
+
options = ClaudeAgentOptions(
|
|
211
|
+
allowed_tools=["Read", "Edit", "Bash"],
|
|
212
|
+
permission_mode="acceptEdits",
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
async with ClaudeSDKClient(options=options) as client:
|
|
216
|
+
# First turn
|
|
217
|
+
await client.query("Read the auth module and identify issues")
|
|
218
|
+
async for message in client.receive_response():
|
|
219
|
+
if hasattr(message, "content"):
|
|
220
|
+
for block in message.content:
|
|
221
|
+
if hasattr(block, "text"):
|
|
222
|
+
print(block.text, end="")
|
|
223
|
+
|
|
224
|
+
# Second turn — Claude retains full context
|
|
225
|
+
await client.query("Fix the issues and add error handling")
|
|
226
|
+
async for message in client.receive_response():
|
|
227
|
+
if hasattr(message, "content"):
|
|
228
|
+
for block in message.content:
|
|
229
|
+
if hasattr(block, "text"):
|
|
230
|
+
print(block.text, end="")
|
|
231
|
+
|
|
232
|
+
asyncio.run(main())
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Full Python Options
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
@dataclass
|
|
239
|
+
class ClaudeAgentOptions:
|
|
240
|
+
tools: list[str] | None = None
|
|
241
|
+
allowed_tools: list[str] = field(default_factory=list)
|
|
242
|
+
disallowed_tools: list[str] = field(default_factory=list)
|
|
243
|
+
system_prompt: str | dict | None = None
|
|
244
|
+
mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)
|
|
245
|
+
permission_mode: str | None = None
|
|
246
|
+
continue_conversation: bool = False
|
|
247
|
+
resume: str | None = None
|
|
248
|
+
max_turns: int | None = None
|
|
249
|
+
max_budget_usd: float | None = None
|
|
250
|
+
model: str | None = None
|
|
251
|
+
fallback_model: str | None = None
|
|
252
|
+
output_format: dict | None = None
|
|
253
|
+
permission_prompt_tool_name: str | None = None
|
|
254
|
+
cwd: str | Path | None = None
|
|
255
|
+
cli_path: str | Path | None = None
|
|
256
|
+
env: dict[str, str] = field(default_factory=dict)
|
|
257
|
+
can_use_tool: Callable | None = None
|
|
258
|
+
include_partial_messages: bool = False
|
|
259
|
+
fork_session: bool = False
|
|
260
|
+
agents: dict[str, dict] | None = None
|
|
261
|
+
setting_sources: list[str] | None = None
|
|
262
|
+
max_thinking_tokens: int | None = None
|
|
263
|
+
plugins: list[dict] = field(default_factory=list)
|
|
264
|
+
sandbox: dict | None = None
|
|
265
|
+
stderr: Callable[[str], None] | None = None
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## 3. canUseTool Callback
|
|
271
|
+
|
|
272
|
+
The `canUseTool` callback intercepts every tool invocation, enabling custom permission logic:
|
|
273
|
+
|
|
274
|
+
### TypeScript
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
import { query, type PermissionResult } from "@anthropic-ai/claude-agent-sdk";
|
|
278
|
+
|
|
279
|
+
const messages = query({
|
|
280
|
+
prompt: "Update the configuration files",
|
|
281
|
+
options: {
|
|
282
|
+
canUseTool: async (
|
|
283
|
+
toolName: string,
|
|
284
|
+
input: Record<string, unknown>,
|
|
285
|
+
{ signal, suggestions }
|
|
286
|
+
): Promise<PermissionResult> => {
|
|
287
|
+
// Block writes to protected paths
|
|
288
|
+
const filePath = (input.file_path as string) ?? "";
|
|
289
|
+
if (
|
|
290
|
+
(toolName === "Write" || toolName === "Edit") &&
|
|
291
|
+
filePath.startsWith("/etc/")
|
|
292
|
+
) {
|
|
293
|
+
return {
|
|
294
|
+
behavior: "deny",
|
|
295
|
+
message: "System directory modifications not allowed",
|
|
296
|
+
interrupt: true,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Redirect sandbox paths
|
|
301
|
+
if (toolName === "Write" && filePath.includes("config")) {
|
|
302
|
+
return {
|
|
303
|
+
behavior: "allow",
|
|
304
|
+
updatedInput: { ...input, file_path: `./sandbox/${filePath}` },
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Allow everything else
|
|
309
|
+
return { behavior: "allow", updatedInput: input };
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Python
|
|
316
|
+
|
|
317
|
+
```python
|
|
318
|
+
from claude_agent_sdk import query, ClaudeAgentOptions
|
|
319
|
+
|
|
320
|
+
async def permission_handler(tool_name, input_data, context):
|
|
321
|
+
file_path = input_data.get("file_path", "")
|
|
322
|
+
|
|
323
|
+
if tool_name in ("Write", "Edit") and file_path.startswith("/etc/"):
|
|
324
|
+
return {
|
|
325
|
+
"behavior": "deny",
|
|
326
|
+
"message": "System directory modifications not allowed",
|
|
327
|
+
"interrupt": True,
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if tool_name == "Write" and "config" in file_path:
|
|
331
|
+
return {
|
|
332
|
+
"behavior": "allow",
|
|
333
|
+
"updated_input": {**input_data, "file_path": f"./sandbox/{file_path}"},
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return {"behavior": "allow", "updated_input": input_data}
|
|
337
|
+
|
|
338
|
+
async def main():
|
|
339
|
+
async for msg in query(
|
|
340
|
+
prompt="Update the configuration files",
|
|
341
|
+
options=ClaudeAgentOptions(can_use_tool=permission_handler),
|
|
342
|
+
):
|
|
343
|
+
pass
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## 4. Custom MCP Tools
|
|
349
|
+
|
|
350
|
+
### TypeScript — createSdkMcpServer
|
|
351
|
+
|
|
352
|
+
Define custom tools that the agent can invoke, running in the same process:
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
|
|
356
|
+
import { z } from "zod";
|
|
357
|
+
|
|
358
|
+
const lookupUser = tool(
|
|
359
|
+
"lookup_user",
|
|
360
|
+
"Look up a user by email address",
|
|
361
|
+
{ email: z.string().email() },
|
|
362
|
+
async (args) => {
|
|
363
|
+
const user = await db.users.findByEmail(args.email);
|
|
364
|
+
return {
|
|
365
|
+
content: [{ type: "text", text: JSON.stringify(user) }],
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
const runQuery = tool(
|
|
371
|
+
"run_sql",
|
|
372
|
+
"Execute a read-only SQL query",
|
|
373
|
+
{ query: z.string() },
|
|
374
|
+
async (args) => {
|
|
375
|
+
const results = await db.query(args.query);
|
|
376
|
+
return {
|
|
377
|
+
content: [{ type: "text", text: JSON.stringify(results) }],
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
const server = createSdkMcpServer({
|
|
383
|
+
name: "app-tools",
|
|
384
|
+
tools: [lookupUser, runQuery],
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
for await (const msg of query({
|
|
388
|
+
prompt: "Find all users who signed up this week",
|
|
389
|
+
options: {
|
|
390
|
+
mcpServers: { appTools: server },
|
|
391
|
+
allowedTools: ["mcp__appTools__lookup_user", "mcp__appTools__run_sql"],
|
|
392
|
+
},
|
|
393
|
+
})) {
|
|
394
|
+
// Process messages
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Python — create_sdk_mcp_server
|
|
399
|
+
|
|
400
|
+
```python
|
|
401
|
+
from claude_agent_sdk import tool, create_sdk_mcp_server, query, ClaudeAgentOptions
|
|
402
|
+
|
|
403
|
+
@tool("lookup_user", "Look up a user by email", {"email": str})
|
|
404
|
+
async def lookup_user(args):
|
|
405
|
+
user = await db.users.find_by_email(args["email"])
|
|
406
|
+
return {"content": [{"type": "text", "text": str(user)}]}
|
|
407
|
+
|
|
408
|
+
server = create_sdk_mcp_server(name="app-tools", tools=[lookup_user])
|
|
409
|
+
|
|
410
|
+
async for msg in query(
|
|
411
|
+
prompt="Find the user with email admin@example.com",
|
|
412
|
+
options=ClaudeAgentOptions(
|
|
413
|
+
mcp_servers={"appTools": server},
|
|
414
|
+
allowed_tools=["mcp__appTools__lookup_user"],
|
|
415
|
+
),
|
|
416
|
+
):
|
|
417
|
+
pass
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
MCP tool names follow the pattern `mcp__<serverName>__<toolName>`. Include them in `allowedTools` to auto-approve invocations.
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## 5. CLI MCP Configuration
|
|
425
|
+
|
|
426
|
+
### --mcp-config
|
|
427
|
+
|
|
428
|
+
Load MCP servers from a JSON configuration file:
|
|
429
|
+
|
|
430
|
+
```bash
|
|
431
|
+
claude -p "Query the database" --mcp-config ./mcp-servers.json
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
```json
|
|
435
|
+
{
|
|
436
|
+
"mcpServers": {
|
|
437
|
+
"database": {
|
|
438
|
+
"command": "npx",
|
|
439
|
+
"args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/app"],
|
|
440
|
+
"env": {
|
|
441
|
+
"PGPASSWORD": "secret"
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
"filesystem": {
|
|
445
|
+
"command": "npx",
|
|
446
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/docs"]
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
MCP server types:
|
|
453
|
+
- **stdio** — spawns a subprocess communicating via stdin/stdout (most common)
|
|
454
|
+
- **sse** — connects to an HTTP server-sent events endpoint
|
|
455
|
+
- **http** — connects to an HTTP endpoint using the Streamable HTTP transport
|
|
456
|
+
|
|
457
|
+
### --strict-mcp-config
|
|
458
|
+
|
|
459
|
+
When set, only MCP servers defined in `--mcp-config` are used. All other configured servers (from settings, project config) are ignored:
|
|
460
|
+
|
|
461
|
+
```bash
|
|
462
|
+
claude -p "query" --strict-mcp-config --mcp-config ./ci-servers.json
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
This ensures reproducible behavior in CI/CD where the environment should not inherit user-level MCP configurations.
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## 6. Subagent Definitions
|
|
470
|
+
|
|
471
|
+
### --agents Flag
|
|
472
|
+
|
|
473
|
+
Define custom subagents that the main agent can delegate to:
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
claude -p "Review and fix all issues in this project" --agents '{
|
|
477
|
+
"code-reviewer": {
|
|
478
|
+
"description": "Expert code reviewer for quality and security analysis.",
|
|
479
|
+
"prompt": "Analyze code for bugs, security issues, and style violations. Report findings clearly.",
|
|
480
|
+
"tools": ["Read", "Grep", "Glob"],
|
|
481
|
+
"model": "haiku"
|
|
482
|
+
},
|
|
483
|
+
"fixer": {
|
|
484
|
+
"description": "Code fixer that applies targeted repairs.",
|
|
485
|
+
"prompt": "Apply minimal, focused fixes. Preserve existing style.",
|
|
486
|
+
"tools": ["Read", "Edit", "Write", "Bash"],
|
|
487
|
+
"model": "sonnet"
|
|
488
|
+
}
|
|
489
|
+
}'
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
Agent definition fields:
|
|
493
|
+
- `description` (required) — when to use this agent; helps the main agent decide delegation
|
|
494
|
+
- `prompt` (required) — system-level instructions for the subagent
|
|
495
|
+
- `tools` (optional) — restrict available tools; inherits all if omitted
|
|
496
|
+
- `model` (optional) — `sonnet`, `opus`, `haiku`, or `inherit` from parent
|
|
497
|
+
|
|
498
|
+
---
|
|
499
|
+
|
|
500
|
+
## 7. Non-Interactive Permission Handling
|
|
501
|
+
|
|
502
|
+
### --permission-prompt-tool
|
|
503
|
+
|
|
504
|
+
For fully automated pipelines where `bypassPermissions` is too broad, `--permission-prompt-tool` delegates permission decisions to an MCP tool:
|
|
505
|
+
|
|
506
|
+
```bash
|
|
507
|
+
claude -p "Deploy the application" \
|
|
508
|
+
--permission-prompt-tool mcp__auth__check_permission \
|
|
509
|
+
--mcp-config ./auth-server.json
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
The specified MCP tool receives each permission request and returns an allow/deny decision. This enables centralized policy enforcement without blanket permission bypass.
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
## 8. Session Continuation Patterns
|
|
517
|
+
|
|
518
|
+
### TypeScript — Capture and Resume
|
|
519
|
+
|
|
520
|
+
```typescript
|
|
521
|
+
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
522
|
+
|
|
523
|
+
// Phase 1: Analysis
|
|
524
|
+
let sessionId: string | undefined;
|
|
525
|
+
|
|
526
|
+
for await (const msg of query({
|
|
527
|
+
prompt: "Analyze the codebase architecture and identify improvements",
|
|
528
|
+
options: { permissionMode: "plan" },
|
|
529
|
+
})) {
|
|
530
|
+
if (msg.type === "system" && msg.subtype === "init") {
|
|
531
|
+
sessionId = msg.session_id;
|
|
532
|
+
}
|
|
533
|
+
if (msg.type === "result") {
|
|
534
|
+
console.log(`Analysis complete. Session: ${sessionId}`);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Phase 2: Implementation (resumes with full context)
|
|
539
|
+
for await (const msg of query({
|
|
540
|
+
prompt: "Implement the top 3 improvements identified",
|
|
541
|
+
options: {
|
|
542
|
+
resume: sessionId,
|
|
543
|
+
permissionMode: "acceptEdits",
|
|
544
|
+
maxBudgetUsd: 5.0,
|
|
545
|
+
},
|
|
546
|
+
})) {
|
|
547
|
+
if (msg.type === "result") {
|
|
548
|
+
console.log(`Implementation: ${msg.subtype} | Cost: $${msg.total_cost_usd}`);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### CLI — Capture and Resume
|
|
554
|
+
|
|
555
|
+
```bash
|
|
556
|
+
# Phase 1
|
|
557
|
+
session_id=$(claude -p "Analyze the auth module" \
|
|
558
|
+
--output-format json \
|
|
559
|
+
--permission-mode plan \
|
|
560
|
+
| jq -r '.session_id')
|
|
561
|
+
|
|
562
|
+
# Phase 2
|
|
563
|
+
claude -p "Fix the issues found" \
|
|
564
|
+
--resume "$session_id" \
|
|
565
|
+
--output-format json \
|
|
566
|
+
--permission-mode acceptEdits
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
Session continuation preserves the full conversation history, including tool results and file contents read during previous phases. This enables multi-phase workflows where analysis and implementation run as separate invocations with different permission modes.
|