@hienlh/ppm 0.1.4 → 0.2.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.
Files changed (102) hide show
  1. package/CLAUDE.md +45 -0
  2. package/bun.lock +55 -0
  3. package/dist/ppm +0 -0
  4. package/dist/web/assets/api-client-BgVufYKf.js +1 -0
  5. package/dist/web/assets/arrow-up-from-line-DjfWTP75.js +1 -0
  6. package/dist/web/assets/button-KIZetva8.js +41 -0
  7. package/dist/web/assets/chat-tab-D7dR7kbZ.js +6 -0
  8. package/dist/web/assets/code-editor-r8P6Gk4M.js +2 -0
  9. package/dist/web/assets/copy-B-kLwqzg.js +1 -0
  10. package/dist/web/assets/dialog-D8ulRTfX.js +5 -0
  11. package/dist/web/assets/diff-viewer-vSvrem_i.js +4 -0
  12. package/dist/web/assets/dist-C4W3AGh3.js +1 -0
  13. package/dist/web/assets/dist-PA84y4Ga.js +1 -0
  14. package/dist/web/assets/external-link-Dim3NH6h.js +1 -0
  15. package/dist/web/assets/git-graph-Cn-s1k0-.js +1 -0
  16. package/dist/web/assets/git-status-panel-QjAQzNAi.js +1 -0
  17. package/dist/web/assets/index-DUBI96T5.css +2 -0
  18. package/dist/web/assets/index-nk1dAWff.js +10 -0
  19. package/dist/web/assets/{jsx-runtime-BnxRlLMJ.js → jsx-runtime-BFALxl05.js} +1 -1
  20. package/dist/web/assets/marked.esm-Cv8mjgnt.js +59 -0
  21. package/dist/web/assets/project-list-DqiatpaH.js +1 -0
  22. package/dist/web/assets/{react-Uzd0zARU.js → react-BSLFEYu8.js} +1 -1
  23. package/dist/web/assets/refresh-cw-DJSjl6Ev.js +1 -0
  24. package/dist/web/assets/settings-tab-iCGeFFdt.js +1 -0
  25. package/dist/web/assets/terminal-tab-DDf6S-Tu.js +36 -0
  26. package/dist/web/assets/trash-2-CjahwKg8.js +1 -0
  27. package/dist/web/assets/x-BxhOxZ5p.js +1 -0
  28. package/dist/web/index.html +11 -10
  29. package/dist/web/sw.js +1 -1
  30. package/docs/claude-agent-sdk-reference.md +780 -0
  31. package/docs/code-standards.md +74 -0
  32. package/docs/codebase-summary.md +22 -20
  33. package/docs/deployment-guide.md +81 -11
  34. package/docs/lessons-learned.md +58 -0
  35. package/docs/project-overview-pdr.md +62 -2
  36. package/docs/system-architecture.md +102 -10
  37. package/package.json +4 -1
  38. package/schemas/ppm-config.schema.json +87 -0
  39. package/src/cli/commands/init.ts +186 -43
  40. package/src/cli/commands/status.ts +73 -0
  41. package/src/cli/commands/stop.ts +24 -10
  42. package/src/index.ts +28 -5
  43. package/src/providers/claude-agent-sdk.ts +84 -3
  44. package/src/providers/registry.ts +0 -2
  45. package/src/server/index.ts +106 -15
  46. package/src/server/routes/settings.ts +70 -0
  47. package/src/server/ws/chat.ts +8 -6
  48. package/src/services/cloudflared.service.ts +99 -0
  49. package/src/services/git.service.ts +23 -1
  50. package/src/services/tunnel.service.ts +100 -0
  51. package/src/types/chat.ts +8 -1
  52. package/src/types/config.ts +50 -3
  53. package/src/web/app.tsx +10 -2
  54. package/src/web/components/auth/login-screen.tsx +1 -1
  55. package/src/web/components/chat/message-input.tsx +1 -1
  56. package/src/web/components/chat/message-list.tsx +112 -251
  57. package/src/web/components/chat/tool-cards.tsx +411 -0
  58. package/src/web/components/editor/code-editor.tsx +80 -20
  59. package/src/web/components/editor/diff-viewer.tsx +72 -7
  60. package/src/web/components/git/git-graph.tsx +3 -0
  61. package/src/web/components/git/git-status-panel.tsx +50 -1
  62. package/src/web/components/layout/command-palette.tsx +215 -0
  63. package/src/web/components/layout/mobile-drawer.tsx +143 -42
  64. package/src/web/components/layout/sidebar.tsx +103 -67
  65. package/src/web/components/layout/tab-bar.tsx +1 -2
  66. package/src/web/components/settings/ai-settings-section.tsx +166 -0
  67. package/src/web/components/settings/settings-tab.tsx +5 -0
  68. package/src/web/components/terminal/terminal-tab.tsx +45 -22
  69. package/src/web/components/ui/input.tsx +4 -3
  70. package/src/web/components/ui/label.tsx +24 -0
  71. package/src/web/components/ui/select.tsx +188 -0
  72. package/src/web/hooks/use-global-keybindings.ts +56 -0
  73. package/src/web/hooks/use-terminal.ts +14 -1
  74. package/src/web/lib/api-settings.ts +24 -0
  75. package/src/web/stores/project-store.ts +47 -2
  76. package/src/web/stores/tab-store.ts +1 -1
  77. package/src/web/styles/globals.css +20 -6
  78. package/test-tool.mjs +41 -0
  79. package/dist/web/assets/api-client-Bnf9LAt4.js +0 -1
  80. package/dist/web/assets/arrow-up-from-line-BXL5dtbG.js +0 -1
  81. package/dist/web/assets/button-DxRZgE8F.js +0 -1
  82. package/dist/web/assets/chat-tab-p2mwkdec.js +0 -61
  83. package/dist/web/assets/code-editor-vMRyRKV3.js +0 -2
  84. package/dist/web/assets/createLucideIcon-Dy1wlrF7.js +0 -1
  85. package/dist/web/assets/dialog-Db6prp1p.js +0 -45
  86. package/dist/web/assets/diff-viewer-BdDje3Wr.js +0 -4
  87. package/dist/web/assets/external-link-WSiY-639.js +0 -1
  88. package/dist/web/assets/git-graph-B-qwuFoO.js +0 -1
  89. package/dist/web/assets/git-status-panel-NkZFb5v1.js +0 -1
  90. package/dist/web/assets/index-BHEFCU01.js +0 -10
  91. package/dist/web/assets/index-DYd_2slk.css +0 -2
  92. package/dist/web/assets/project-list-NkR7IHT5.js +0 -1
  93. package/dist/web/assets/refresh-cw-DtopuYJf.js +0 -1
  94. package/dist/web/assets/settings-tab-DKx0s3Q1.js +0 -1
  95. package/dist/web/assets/terminal-tab-DHwn2LMT.js +0 -36
  96. package/dist/web/assets/trash-2-CHLebaNh.js +0 -1
  97. package/dist/web/assets/x-BISR7bpK.js +0 -1
  98. package/src/providers/claude-binary-finder.ts +0 -256
  99. package/src/providers/claude-code-cli.ts +0 -413
  100. package/src/providers/claude-process-registry.ts +0 -106
  101. /package/dist/web/assets/{dist-CSp7ir0r.js → dist-CBiGQxfr.js} +0 -0
  102. /package/dist/web/assets/{utils-CiBGfeHD.js → utils-DpJF9mAi.js} +0 -0
@@ -0,0 +1,780 @@
1
+ # Claude Agent SDK — Comprehensive Reference
2
+
3
+ > Tổng hợp từ [platform.claude.com/docs/en/agent-sdk](https://platform.claude.com/docs/en/agent-sdk/overview.md).
4
+ > Last updated: 2026-03-15.
5
+
6
+ ---
7
+
8
+ ## Table of Contents
9
+
10
+ - [1. Overview](#1-overview)
11
+ - [2. Installation & Setup](#2-installation--setup)
12
+ - [3. Core API — `query()`](#3-core-api--query)
13
+ - [4. Agent Loop](#4-agent-loop)
14
+ - [5. Message Types](#5-message-types)
15
+ - [6. Permissions](#6-permissions)
16
+ - [7. Hooks](#7-hooks)
17
+ - [8. Sessions](#8-sessions)
18
+ - [9. Subagents](#9-subagents)
19
+ - [10. MCP (Model Context Protocol)](#10-mcp-model-context-protocol)
20
+ - [11. Custom Tools](#11-custom-tools)
21
+ - [12. Streaming](#12-streaming)
22
+ - [13. User Input & Approvals](#13-user-input--approvals)
23
+ - [14. System Prompts & CLAUDE.md](#14-system-prompts--claudemd)
24
+ - [15. Skills, Slash Commands & Plugins](#15-skills-slash-commands--plugins)
25
+ - [16. File Checkpointing](#16-file-checkpointing)
26
+ - [17. Cost Tracking](#17-cost-tracking)
27
+ - [18. Hosting & Secure Deployment](#18-hosting--secure-deployment)
28
+ - [19. TypeScript V2 Preview](#19-typescript-v2-preview)
29
+ - [20. PPM Integration Notes](#20-ppm-integration-notes)
30
+
31
+ ---
32
+
33
+ ## 1. Overview
34
+
35
+ **Claude Agent SDK** (renamed from Claude Code SDK) gives programmatic access to the same tools, agent loop, and context management that power Claude Code.
36
+
37
+ - **Languages**: TypeScript (`@anthropic-ai/claude-agent-sdk`) & Python (`claude-agent-sdk`)
38
+ - **Built-in tools**: Read, Write, Edit, Bash, Glob, Grep, WebSearch, WebFetch, AskUserQuestion, Agent, Skill, TodoWrite, ToolSearch
39
+ - **Auth**: `ANTHROPIC_API_KEY` env var; also supports Bedrock (`CLAUDE_CODE_USE_BEDROCK=1`), Vertex AI (`CLAUDE_CODE_USE_VERTEX=1`), Azure (`CLAUDE_CODE_USE_FOUNDRY=1`)
40
+
41
+ ```typescript
42
+ import { query } from "@anthropic-ai/claude-agent-sdk";
43
+
44
+ for await (const message of query({
45
+ prompt: "Find and fix the bug in auth.py",
46
+ options: { allowedTools: ["Read", "Edit", "Bash"] }
47
+ })) {
48
+ console.log(message);
49
+ }
50
+ ```
51
+
52
+ **Source**: [overview.md](https://platform.claude.com/docs/en/agent-sdk/overview.md)
53
+
54
+ ---
55
+
56
+ ## 2. Installation & Setup
57
+
58
+ ```bash
59
+ npm install @anthropic-ai/claude-agent-sdk
60
+ ```
61
+
62
+ Requirements: Node.js 18+, Claude Code CLI installed globally.
63
+
64
+ ```bash
65
+ export ANTHROPIC_API_KEY=your-api-key
66
+ ```
67
+
68
+ **Source**: [quickstart.md](https://platform.claude.com/docs/en/agent-sdk/quickstart.md)
69
+
70
+ ---
71
+
72
+ ## 3. Core API — `query()`
73
+
74
+ ```typescript
75
+ function query({
76
+ prompt, // string | AsyncIterable<SDKUserMessage>
77
+ options // Options
78
+ }): Query; // extends AsyncGenerator<SDKMessage, void>
79
+ ```
80
+
81
+ ### Key Options (TypeScript)
82
+
83
+ | Option | Type | Description |
84
+ |--------|------|-------------|
85
+ | `allowedTools` | `string[]` | Pre-approved tools |
86
+ | `disallowedTools` | `string[]` | Blocked tools (overrides everything) |
87
+ | `permissionMode` | `string` | `"default"` / `"acceptEdits"` / `"bypassPermissions"` / `"dontAsk"` / `"plan"` |
88
+ | `systemPrompt` | `string \| object` | Custom or preset (`{ preset: "claude_code", append: "..." }`) |
89
+ | `settingSources` | `string[]` | `["user", "project", "local"]` to load CLAUDE.md, skills, hooks |
90
+ | `mcpServers` | `object` | MCP server configurations |
91
+ | `agents` | `object` | Subagent definitions |
92
+ | `hooks` | `object` | Hook callbacks per event |
93
+ | `canUseTool` | `function` | Approval callback |
94
+ | `maxTurns` | `number` | Max tool-use round trips |
95
+ | `maxBudgetUsd` | `number` | Max cost before stopping |
96
+ | `effort` | `string` | `"low"` / `"medium"` / `"high"` / `"max"` |
97
+ | `model` | `string` | Model ID override |
98
+ | `resume` | `string` | Session ID to resume |
99
+ | `continue` | `boolean` | Resume most recent session |
100
+ | `forkSession` | `boolean` | Fork from resumed session |
101
+ | `cwd` | `string` | Working directory |
102
+ | `plugins` | `array` | Plugin paths |
103
+ | `enableFileCheckpointing` | `boolean` | Track file changes |
104
+ | `includePartialMessages` | `boolean` | Stream text/tool deltas |
105
+ | `persistSession` | `boolean` | Save session to disk (default: true) |
106
+
107
+ ### Query Object Methods
108
+
109
+ | Method | Description |
110
+ |--------|-------------|
111
+ | `[Symbol.asyncIterator]()` | Iterate messages |
112
+ | `setPermissionMode(mode)` | Change mode mid-session |
113
+ | `rewindFiles(checkpointId)` | Restore files to checkpoint |
114
+ | `close()` | Abort the query |
115
+
116
+ **Source**: [typescript.md](https://platform.claude.com/docs/en/agent-sdk/typescript.md)
117
+
118
+ ---
119
+
120
+ ## 4. Agent Loop
121
+
122
+ ```
123
+ Prompt → Claude Evaluates → Tool Calls → Execute → Results → Repeat → Final Answer
124
+ ```
125
+
126
+ 1. **Receive prompt** → SDK yields `SystemMessage` (subtype `init`)
127
+ 2. **Evaluate & respond** → SDK yields `AssistantMessage` (text + tool_use blocks)
128
+ 3. **Execute tools** → SDK runs tools, yields `UserMessage` with results
129
+ 4. **Repeat** (steps 2-3 = 1 turn)
130
+ 5. **Return result** → SDK yields final `AssistantMessage` + `ResultMessage`
131
+
132
+ ### Controls
133
+
134
+ | Control | Effect |
135
+ |---------|--------|
136
+ | `maxTurns` | Cap tool-use round trips |
137
+ | `maxBudgetUsd` | Cap spend |
138
+ | `effort` | Reasoning depth (`low`→`max`) |
139
+ | Hooks | Intercept/block/modify tools |
140
+
141
+ ### Context Window
142
+
143
+ - Accumulates across turns (system prompt + tool defs + history)
144
+ - **Auto-compaction** when nearing limit → `SystemMessage` with `compact_boundary`
145
+ - CLAUDE.md content persists after compaction (re-injected each request)
146
+ - Subagents start fresh (only final result returns to parent)
147
+
148
+ **Source**: [agent-loop.md](https://platform.claude.com/docs/en/agent-sdk/agent-loop.md)
149
+
150
+ ---
151
+
152
+ ## 5. Message Types
153
+
154
+ | Type | Description |
155
+ |------|-------------|
156
+ | `SystemMessage` | Session lifecycle: `init`, `compact_boundary` |
157
+ | `AssistantMessage` | Claude's response (text + tool_use blocks) |
158
+ | `UserMessage` | Tool results, user inputs |
159
+ | `StreamEvent` | Raw streaming deltas (when `includePartialMessages: true`) |
160
+ | `ResultMessage` | Final message: `result`, `total_cost_usd`, `usage`, `session_id` |
161
+
162
+ ### ResultMessage Subtypes
163
+
164
+ | Subtype | Meaning |
165
+ |---------|---------|
166
+ | `success` | Task completed, `result` field available |
167
+ | `error_max_turns` | Hit maxTurns limit |
168
+ | `error_max_budget_usd` | Hit budget limit |
169
+ | `error_during_execution` | API failure or cancellation |
170
+
171
+ **Source**: [agent-loop.md](https://platform.claude.com/docs/en/agent-sdk/agent-loop.md)
172
+
173
+ ---
174
+
175
+ ## 6. Permissions
176
+
177
+ ### Evaluation Order
178
+
179
+ ```
180
+ Hooks → Deny rules → Permission mode → Allow rules → canUseTool callback
181
+ ```
182
+
183
+ - **Deny always wins** (even in `bypassPermissions`)
184
+
185
+ ### Permission Modes
186
+
187
+ | Mode | Behavior |
188
+ |------|----------|
189
+ | `default` | Unmatched tools → `canUseTool` callback |
190
+ | `dontAsk` (TS only) | Deny anything not pre-approved |
191
+ | `acceptEdits` | Auto-approve file edits (Edit, Write, mkdir, rm, mv, cp) |
192
+ | `bypassPermissions` | All tools run without prompts (**propagates to subagents**) |
193
+ | `plan` | No tool execution, planning only |
194
+
195
+ ### Allow/Deny Rules
196
+
197
+ ```typescript
198
+ {
199
+ allowedTools: ["Read", "Glob", "Grep"], // Auto-approved
200
+ disallowedTools: ["Bash"], // Always blocked
201
+ permissionMode: "dontAsk" // Deny everything else
202
+ }
203
+ ```
204
+
205
+ **Source**: [permissions.md](https://platform.claude.com/docs/en/agent-sdk/permissions.md)
206
+
207
+ ---
208
+
209
+ ## 7. Hooks
210
+
211
+ Callback functions that run at key execution points.
212
+
213
+ ### Available Events
214
+
215
+ | Event | Description |
216
+ |-------|-------------|
217
+ | `PreToolUse` | Before tool executes (can block/modify) |
218
+ | `PostToolUse` | After tool result |
219
+ | `PostToolUseFailure` | After tool error |
220
+ | `UserPromptSubmit` | On prompt submission |
221
+ | `Stop` | On execution stop |
222
+ | `SubagentStart` / `SubagentStop` | Subagent lifecycle |
223
+ | `PreCompact` | Before context compaction |
224
+ | `PermissionRequest` | Permission dialog would show |
225
+ | `Notification` | Agent status messages |
226
+ | `SessionStart` / `SessionEnd` | TS only |
227
+
228
+ ### Hook Structure
229
+
230
+ ```typescript
231
+ hooks: {
232
+ PreToolUse: [{
233
+ matcher: "Write|Edit", // Regex on tool name
234
+ hooks: [myCallback], // Callback array
235
+ timeout: 60 // Seconds
236
+ }]
237
+ }
238
+ ```
239
+
240
+ ### Callback Signature
241
+
242
+ ```typescript
243
+ const myHook: HookCallback = async (input, toolUseID, { signal }) => {
244
+ // Return {} to allow
245
+ // Return { hookSpecificOutput: { permissionDecision: "deny", ... } } to block
246
+ // Return { hookSpecificOutput: { updatedInput: {...} permissionDecision: "allow" } } to modify
247
+ // Return { systemMessage: "..." } to inject context
248
+ return {};
249
+ };
250
+ ```
251
+
252
+ ### Key Patterns
253
+
254
+ - **Block dangerous ops**: check `tool_input.file_path` for sensitive paths
255
+ - **Modify input**: return `updatedInput` + `permissionDecision: "allow"`
256
+ - **Auto-approve read-only**: return `permissionDecision: "allow"` for Read/Glob/Grep
257
+ - **Async side-effects**: return `{ async: true }` for logging/webhooks
258
+
259
+ **Source**: [hooks.md](https://platform.claude.com/docs/en/agent-sdk/hooks.md)
260
+
261
+ ---
262
+
263
+ ## 8. Sessions
264
+
265
+ ### Approaches
266
+
267
+ | Scenario | Approach |
268
+ |----------|----------|
269
+ | Single prompt | One `query()` call |
270
+ | Multi-turn, same process | `continue: true` (TS) |
271
+ | Resume specific session | Pass `resume: sessionId` |
272
+ | Try alternative approach | `forkSession: true` |
273
+ | No disk persistence (TS) | `persistSession: false` |
274
+
275
+ ### Capture Session ID
276
+
277
+ ```typescript
278
+ for await (const message of query({ prompt: "..." })) {
279
+ if (message.type === "result") {
280
+ sessionId = message.session_id;
281
+ }
282
+ }
283
+ ```
284
+
285
+ ### Resume
286
+
287
+ ```typescript
288
+ for await (const message of query({
289
+ prompt: "Follow-up question",
290
+ options: { resume: sessionId }
291
+ })) { ... }
292
+ ```
293
+
294
+ ### Fork
295
+
296
+ ```typescript
297
+ for await (const message of query({
298
+ prompt: "Try different approach",
299
+ options: { resume: sessionId, forkSession: true }
300
+ })) { ... }
301
+ ```
302
+
303
+ Sessions stored at `~/.claude/projects/<encoded-cwd>/<session-id>.jsonl`.
304
+
305
+ **Source**: [sessions.md](https://platform.claude.com/docs/en/agent-sdk/sessions.md)
306
+
307
+ ---
308
+
309
+ ## 9. Subagents
310
+
311
+ Separate agent instances for isolated subtasks.
312
+
313
+ ### Definition
314
+
315
+ ```typescript
316
+ agents: {
317
+ "code-reviewer": {
318
+ description: "Expert code reviewer.", // When to use
319
+ prompt: "You are a code review specialist...",
320
+ tools: ["Read", "Grep", "Glob"], // Restricted toolset
321
+ model: "sonnet" // Optional model override
322
+ }
323
+ }
324
+ ```
325
+
326
+ **Require `Agent` in `allowedTools`** for subagent invocation.
327
+
328
+ ### Key Properties
329
+
330
+ - **Context isolation**: fresh conversation, only final message returns to parent
331
+ - **Parallelization**: multiple subagents can run concurrently
332
+ - **No nesting**: subagents cannot spawn their own subagents
333
+ - **Inherit**: project CLAUDE.md, tool definitions; NOT parent conversation or system prompt
334
+ - **Resumable**: capture `agentId` from messages, pass in subsequent resume
335
+
336
+ ### Invocation
337
+
338
+ - **Automatic**: Claude matches task to description
339
+ - **Explicit**: `"Use the code-reviewer agent to check auth module"`
340
+
341
+ **Source**: [subagents.md](https://platform.claude.com/docs/en/agent-sdk/subagents.md)
342
+
343
+ ---
344
+
345
+ ## 10. MCP (Model Context Protocol)
346
+
347
+ Connect external tools via MCP servers.
348
+
349
+ ### Transport Types
350
+
351
+ | Type | Config |
352
+ |------|--------|
353
+ | **stdio** | `{ command: "npx", args: [...], env: {...} }` |
354
+ | **HTTP/SSE** | `{ type: "http"/"sse", url: "https://...", headers: {...} }` |
355
+ | **SDK MCP** | In-process via `createSdkMcpServer()` |
356
+
357
+ ### Tool Naming
358
+
359
+ Pattern: `mcp__<server-name>__<tool-name>`
360
+
361
+ ```typescript
362
+ mcpServers: {
363
+ github: {
364
+ command: "npx",
365
+ args: ["-y", "@modelcontextprotocol/server-github"],
366
+ env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN }
367
+ }
368
+ },
369
+ allowedTools: ["mcp__github__list_issues"] // or "mcp__github__*"
370
+ ```
371
+
372
+ ### Tool Search
373
+
374
+ Auto-enabled when MCP tools exceed 10% of context. Config via `ENABLE_TOOL_SEARCH` env var.
375
+
376
+ ### Config File
377
+
378
+ `.mcp.json` at project root auto-loaded by SDK.
379
+
380
+ **Source**: [mcp.md](https://platform.claude.com/docs/en/agent-sdk/mcp.md)
381
+
382
+ ---
383
+
384
+ ## 11. Custom Tools
385
+
386
+ Build in-process MCP tools via `createSdkMcpServer()` + `tool()`.
387
+
388
+ ```typescript
389
+ import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
390
+ import { z } from "zod";
391
+
392
+ const server = createSdkMcpServer({
393
+ name: "my-tools",
394
+ version: "1.0.0",
395
+ tools: [
396
+ tool(
397
+ "get_weather",
398
+ "Get temperature for coordinates",
399
+ {
400
+ latitude: z.number(),
401
+ longitude: z.number()
402
+ },
403
+ async (args) => {
404
+ const data = await fetch(`https://api.open-meteo.com/...`).then(r => r.json());
405
+ return { content: [{ type: "text", text: `${data.current.temperature_2m}°F` }] };
406
+ }
407
+ )
408
+ ]
409
+ });
410
+
411
+ // Requires streaming input mode (AsyncGenerator)
412
+ async function* messages() {
413
+ yield { type: "user", message: { role: "user", content: "Weather in SF?" } };
414
+ }
415
+
416
+ for await (const msg of query({
417
+ prompt: messages(),
418
+ options: {
419
+ mcpServers: { "my-tools": server },
420
+ allowedTools: ["mcp__my-tools__get_weather"]
421
+ }
422
+ })) { ... }
423
+ ```
424
+
425
+ **Important**: Custom MCP tools require streaming input mode (async generator).
426
+
427
+ **Source**: [custom-tools.md](https://platform.claude.com/docs/en/agent-sdk/custom-tools.md)
428
+
429
+ ---
430
+
431
+ ## 12. Streaming
432
+
433
+ ### Input Modes
434
+
435
+ | Mode | Description | Use case |
436
+ |------|-------------|----------|
437
+ | **Streaming** (recommended) | AsyncGenerator, persistent session | Interactive apps, image uploads, hooks |
438
+ | **Single Message** | String prompt | One-shot tasks, stateless lambdas |
439
+
440
+ ### Output Streaming
441
+
442
+ Enable with `includePartialMessages: true`.
443
+
444
+ ```typescript
445
+ for await (const message of query({
446
+ prompt: "...",
447
+ options: { includePartialMessages: true }
448
+ })) {
449
+ if (message.type === "stream_event") {
450
+ const event = message.event;
451
+ if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
452
+ process.stdout.write(event.delta.text);
453
+ }
454
+ }
455
+ }
456
+ ```
457
+
458
+ ### Stream Event Types
459
+
460
+ `message_start` → `content_block_start` → `content_block_delta` (text/tool chunks) → `content_block_stop` → `message_delta` → `message_stop`
461
+
462
+ **Sources**: [streaming-vs-single-mode.md](https://platform.claude.com/docs/en/agent-sdk/streaming-vs-single-mode.md), [streaming-output.md](https://platform.claude.com/docs/en/agent-sdk/streaming-output.md)
463
+
464
+ ---
465
+
466
+ ## 13. User Input & Approvals
467
+
468
+ ### canUseTool Callback
469
+
470
+ ```typescript
471
+ canUseTool: async (toolName, input) => {
472
+ if (toolName === "AskUserQuestion") {
473
+ // Handle clarifying questions
474
+ return {
475
+ behavior: "allow",
476
+ updatedInput: { questions: input.questions, answers: { ... } }
477
+ };
478
+ }
479
+ // Tool approval
480
+ return { behavior: "allow", updatedInput: input };
481
+ // or: { behavior: "deny", message: "Reason" }
482
+ }
483
+ ```
484
+
485
+ ### Responses
486
+
487
+ | Response | Effect |
488
+ |----------|--------|
489
+ | `{ behavior: "allow", updatedInput }` | Execute tool (can modify input) |
490
+ | `{ behavior: "deny", message }` | Block tool, Claude sees message |
491
+
492
+ ### AskUserQuestion
493
+
494
+ - Claude generates questions with `options[]` (2-4 choices each)
495
+ - Return answers as `{ "question text": "selected label" }`
496
+ - Supports `multiSelect` (join labels with `", "`)
497
+ - Optional `previewFormat: "html"` or `"markdown"` for visual previews (TS)
498
+
499
+ **Source**: [user-input.md](https://platform.claude.com/docs/en/agent-sdk/user-input.md)
500
+
501
+ ---
502
+
503
+ ## 14. System Prompts & CLAUDE.md
504
+
505
+ ### 4 Approaches
506
+
507
+ | Method | Persistence | Built-in tools |
508
+ |--------|-------------|----------------|
509
+ | **CLAUDE.md** | Per-project file | Preserved |
510
+ | **Output Styles** | Saved files | Preserved |
511
+ | **systemPrompt + append** | Session only | Preserved |
512
+ | **Custom systemPrompt** | Session only | **Lost** (unless included) |
513
+
514
+ ### Default Behavior
515
+
516
+ SDK uses **minimal system prompt** by default. For full Claude Code behavior:
517
+
518
+ ```typescript
519
+ systemPrompt: { type: "preset", preset: "claude_code" }
520
+ ```
521
+
522
+ ### CLAUDE.md
523
+
524
+ Loaded when `settingSources` includes `"project"` or `"user"`:
525
+
526
+ | Level | Location |
527
+ |-------|----------|
528
+ | Project root | `<cwd>/CLAUDE.md` or `<cwd>/.claude/CLAUDE.md` |
529
+ | Project rules | `<cwd>/.claude/rules/*.md` |
530
+ | Parent dirs | `CLAUDE.md` in dirs above cwd |
531
+ | User | `~/.claude/CLAUDE.md` |
532
+
533
+ **Source**: [modifying-system-prompts.md](https://platform.claude.com/docs/en/agent-sdk/modifying-system-prompts.md)
534
+
535
+ ---
536
+
537
+ ## 15. Skills, Slash Commands & Plugins
538
+
539
+ ### Skills
540
+
541
+ Markdown files (`.claude/skills/<name>/SKILL.md`) auto-discovered when `settingSources` enabled.
542
+
543
+ ```typescript
544
+ {
545
+ settingSources: ["user", "project"],
546
+ allowedTools: ["Skill", "Read", "Write", "Bash"]
547
+ }
548
+ ```
549
+
550
+ - Model-invoked autonomously based on description
551
+ - No programmatic API — filesystem artifacts only
552
+
553
+ ### Slash Commands
554
+
555
+ - Built-in: `/compact`, `/clear`, `/help`
556
+ - Custom: `.claude/commands/*.md` (legacy) or `.claude/skills/<name>/SKILL.md` (recommended)
557
+ - Support arguments (`$1`, `$2`, `$ARGUMENTS`), bash execution (`!`backtick``), file references (`@file`)
558
+
559
+ ### Plugins
560
+
561
+ Load from local paths:
562
+
563
+ ```typescript
564
+ plugins: [
565
+ { type: "local", path: "./my-plugin" }
566
+ ]
567
+ ```
568
+
569
+ Plugin structure: `.claude-plugin/plugin.json` + `skills/`, `agents/`, `hooks/`, `.mcp.json`
570
+
571
+ Namespaced: `plugin-name:skill-name`
572
+
573
+ **Sources**: [skills.md](https://platform.claude.com/docs/en/agent-sdk/skills.md), [slash-commands.md](https://platform.claude.com/docs/en/agent-sdk/slash-commands.md), [plugins.md](https://platform.claude.com/docs/en/agent-sdk/plugins.md)
574
+
575
+ ---
576
+
577
+ ## 16. File Checkpointing
578
+
579
+ Track & rewind file changes (Write, Edit, NotebookEdit tools only).
580
+
581
+ ### Enable
582
+
583
+ ```typescript
584
+ {
585
+ enableFileCheckpointing: true,
586
+ permissionMode: "acceptEdits",
587
+ extraArgs: { "replay-user-messages": null } // Required for checkpoint UUIDs
588
+ }
589
+ ```
590
+
591
+ ### Capture Checkpoint
592
+
593
+ ```typescript
594
+ for await (const message of response) {
595
+ if (message.type === "user" && message.uuid) {
596
+ checkpointId = message.uuid; // First user message = restore point
597
+ }
598
+ }
599
+ ```
600
+
601
+ ### Rewind
602
+
603
+ ```typescript
604
+ const rewindQuery = query({
605
+ prompt: "",
606
+ options: { ...opts, resume: sessionId }
607
+ });
608
+ for await (const msg of rewindQuery) {
609
+ await rewindQuery.rewindFiles(checkpointId);
610
+ break;
611
+ }
612
+ ```
613
+
614
+ **Limitations**: Bash changes not tracked; same session only; file content only.
615
+
616
+ **Source**: [file-checkpointing.md](https://platform.claude.com/docs/en/agent-sdk/file-checkpointing.md)
617
+
618
+ ---
619
+
620
+ ## 17. Cost Tracking
621
+
622
+ ### Total Cost
623
+
624
+ ```typescript
625
+ if (message.type === "result") {
626
+ console.log(`Cost: $${message.total_cost_usd}`);
627
+ }
628
+ ```
629
+
630
+ ### Per-Model Breakdown (TS only)
631
+
632
+ ```typescript
633
+ for (const [model, usage] of Object.entries(message.modelUsage)) {
634
+ console.log(`${model}: $${usage.costUSD}, in=${usage.inputTokens}, out=${usage.outputTokens}`);
635
+ }
636
+ ```
637
+
638
+ ### Deduplication
639
+
640
+ Parallel tool calls share same `message.message.id` → deduplicate by ID.
641
+
642
+ ### Cache Tokens
643
+
644
+ - `cache_creation_input_tokens`: higher rate (new cache entries)
645
+ - `cache_read_input_tokens`: reduced rate (cache hits)
646
+
647
+ **Source**: [cost-tracking.md](https://platform.claude.com/docs/en/agent-sdk/cost-tracking.md)
648
+
649
+ ---
650
+
651
+ ## 18. Hosting & Secure Deployment
652
+
653
+ ### Deployment Patterns
654
+
655
+ | Pattern | Description |
656
+ |---------|-------------|
657
+ | **Ephemeral** | New container per task, destroy when done |
658
+ | **Long-Running** | Persistent container, multiple Claude processes |
659
+ | **Hybrid** | Ephemeral + hydrated from DB/session resume |
660
+ | **Single Container** | Multiple agents in one container |
661
+
662
+ ### Requirements
663
+
664
+ - Node.js 18+ / Python 3.10+
665
+ - Claude Code CLI installed
666
+ - ~1 GiB RAM, 5 GiB disk, 1 CPU
667
+ - Outbound HTTPS to `api.anthropic.com`
668
+
669
+ ### Sandbox Providers
670
+
671
+ Modal, Cloudflare Sandboxes, Daytona, E2B, Fly Machines, Vercel Sandbox
672
+
673
+ ### Security
674
+
675
+ - **Isolation**: Containers (Docker), gVisor, VMs (Firecracker)
676
+ - **Credential management**: Proxy pattern (inject creds outside agent boundary)
677
+ - **Network**: `--network none` + Unix socket proxy for allowlisted domains
678
+ - **Filesystem**: Read-only mounts, tmpfs for writable areas
679
+
680
+ **Sources**: [hosting.md](https://platform.claude.com/docs/en/agent-sdk/hosting.md), [secure-deployment.md](https://platform.claude.com/docs/en/agent-sdk/secure-deployment.md)
681
+
682
+ ---
683
+
684
+ ## 19. TypeScript V2 Preview
685
+
686
+ > ⚠️ **Unstable** — APIs may change.
687
+
688
+ Simplified interface: `createSession()` → `send()` / `stream()`.
689
+
690
+ ```typescript
691
+ import { unstable_v2_createSession } from "@anthropic-ai/claude-agent-sdk";
692
+
693
+ await using session = unstable_v2_createSession({ model: "claude-opus-4-6" });
694
+
695
+ await session.send("Hello!");
696
+ for await (const msg of session.stream()) {
697
+ if (msg.type === "assistant") {
698
+ console.log(msg.message.content.filter(b => b.type === "text").map(b => b.text).join(""));
699
+ }
700
+ }
701
+
702
+ // Multi-turn: just call send() again
703
+ await session.send("Follow up question");
704
+ for await (const msg of session.stream()) { ... }
705
+ ```
706
+
707
+ Also: `unstable_v2_prompt()` for one-shot, `unstable_v2_resumeSession()` for resume.
708
+
709
+ **Source**: [typescript-v2-preview.md](https://platform.claude.com/docs/en/agent-sdk/typescript-v2-preview.md)
710
+
711
+ ---
712
+
713
+ ## 20. PPM Integration Notes
714
+
715
+ PPM uses `@anthropic-ai/claude-agent-sdk` in `src/providers/claude-agent-sdk.ts`.
716
+
717
+ ### Current Usage
718
+
719
+ - `query()` V1 API with streaming input (AsyncGenerator)
720
+ - `canUseTool` callback for tool approvals + AskUserQuestion → WebSocket events to frontend
721
+ - `listSessions()` / `getSessionMessages()` for session management
722
+ - Sessions persisted by SDK at `~/.claude/projects/`
723
+
724
+ ### Key Considerations
725
+
726
+ | Area | Recommendation |
727
+ |------|---------------|
728
+ | **System prompt** | SDK default is minimal; use `{ preset: "claude_code" }` if full behavior needed |
729
+ | **Settings sources** | Set `settingSources: ["project"]` to load project CLAUDE.md, skills, hooks |
730
+ | **Custom tools** | Use `createSdkMcpServer()` + `tool()` for PPM-specific tools (file tree, git, etc.) |
731
+ | **Streaming output** | `includePartialMessages: true` for real-time chat UI |
732
+ | **File checkpointing** | Enable for undo/redo in editor; track Write/Edit changes |
733
+ | **Cost tracking** | Read `total_cost_usd` from ResultMessage for usage dashboard |
734
+ | **Session resume** | Capture `session_id` for chat history persistence across restarts |
735
+ | **Subagents** | Define specialized agents (reviewer, tester) via `agents` param |
736
+ | **V2 Preview** | Monitor for stable release; `send()`/`stream()` pattern cleaner for chat UIs |
737
+ | **SDK .env poisoning** | Provider must neutralize `ANTHROPIC_API_KEY` from project `.env` files (see `docs/lessons-learned.md`) |
738
+
739
+ ### Gotchas
740
+
741
+ 1. **Custom MCP tools require streaming input** (async generator, not string prompt)
742
+ 2. **`allowedTools` does NOT constrain `bypassPermissions`** — use `disallowedTools` to block specific tools
743
+ 3. **Subagents cannot nest** — no `Agent` in subagent's `tools` array
744
+ 4. **`dontAsk` mode is TypeScript-only** — Python uses `disallowedTools` instead
745
+ 5. **Tool name was renamed** from `"Task"` to `"Agent"` in v2.1.63 — check both for compatibility
746
+ 6. **Session files are local** — can't resume across hosts without moving `.jsonl` files
747
+
748
+ ---
749
+
750
+ ## Quick Links
751
+
752
+ | Doc | URL |
753
+ |-----|-----|
754
+ | Overview | https://platform.claude.com/docs/en/agent-sdk/overview.md |
755
+ | Quickstart | https://platform.claude.com/docs/en/agent-sdk/quickstart.md |
756
+ | TypeScript Reference | https://platform.claude.com/docs/en/agent-sdk/typescript.md |
757
+ | Python Reference | https://platform.claude.com/docs/en/agent-sdk/python.md |
758
+ | Agent Loop | https://platform.claude.com/docs/en/agent-sdk/agent-loop.md |
759
+ | Permissions | https://platform.claude.com/docs/en/agent-sdk/permissions.md |
760
+ | Hooks | https://platform.claude.com/docs/en/agent-sdk/hooks.md |
761
+ | Sessions | https://platform.claude.com/docs/en/agent-sdk/sessions.md |
762
+ | Subagents | https://platform.claude.com/docs/en/agent-sdk/subagents.md |
763
+ | MCP | https://platform.claude.com/docs/en/agent-sdk/mcp.md |
764
+ | Custom Tools | https://platform.claude.com/docs/en/agent-sdk/custom-tools.md |
765
+ | Streaming Input | https://platform.claude.com/docs/en/agent-sdk/streaming-vs-single-mode.md |
766
+ | Streaming Output | https://platform.claude.com/docs/en/agent-sdk/streaming-output.md |
767
+ | User Input | https://platform.claude.com/docs/en/agent-sdk/user-input.md |
768
+ | System Prompts | https://platform.claude.com/docs/en/agent-sdk/modifying-system-prompts.md |
769
+ | Skills | https://platform.claude.com/docs/en/agent-sdk/skills.md |
770
+ | Slash Commands | https://platform.claude.com/docs/en/agent-sdk/slash-commands.md |
771
+ | Plugins | https://platform.claude.com/docs/en/agent-sdk/plugins.md |
772
+ | Claude Code Features | https://platform.claude.com/docs/en/agent-sdk/claude-code-features.md |
773
+ | File Checkpointing | https://platform.claude.com/docs/en/agent-sdk/file-checkpointing.md |
774
+ | Cost Tracking | https://platform.claude.com/docs/en/agent-sdk/cost-tracking.md |
775
+ | Hosting | https://platform.claude.com/docs/en/agent-sdk/hosting.md |
776
+ | Secure Deployment | https://platform.claude.com/docs/en/agent-sdk/secure-deployment.md |
777
+ | TS V2 Preview | https://platform.claude.com/docs/en/agent-sdk/typescript-v2-preview.md |
778
+ | Example Agents | https://github.com/anthropics/claude-agent-sdk-demos |
779
+ | TS Changelog | https://github.com/anthropics/claude-agent-sdk-typescript/blob/main/CHANGELOG.md |
780
+ | Python Changelog | https://github.com/anthropics/claude-agent-sdk-python/blob/main/CHANGELOG.md |