claude_agent 0.3.0 → 0.4.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c630af2842675c8aa126588105617fa1af823c437ef1095029b3f7e9efbc982c
4
- data.tar.gz: 16199aa31e03d542bf9128356594a0ea6659a16ecfba7fa2b3e1a97429662ef2
3
+ metadata.gz: 3dad011bddaedd68fe720527eeeda0a4dbe1f2b7ee9621e0ea6a0b2a3c09bc62
4
+ data.tar.gz: 161a59562a2cd86cfc6aca140259c996892dc68b604fc9500c3337dd814be4b5
5
5
  SHA512:
6
- metadata.gz: 8f555706af9480e572d8f310a73ab0d1294b9eaf6b162146364032450bbad86f0a2e962649f12e74e48dae4155fd1929221efd46a349253d1bf96ad09249db54
7
- data.tar.gz: fbf3a236589cad360dbfff15dfa8164a353a973e211e5f4ab4802d8b383d803359a137a9a312478bbd0175f7b866c4f40795f55c6d8b2eb8f028992f403b5182
6
+ metadata.gz: 4a157be028a9102d174db09a0298a63eb7051253d5c6d2173a5f6d111f72da5a9c7fd286d41e948cf35ddecfdd9c45a14d08e7dca397fe7391b0505f9cc8a507
7
+ data.tar.gz: f16dd8d278d5291145fae97cf14bc525f47cdae4b2c2de34cfa041b754a9bdd4bdc57aae2ee8b4e0ad0081de026e53affeded6c53e8d11549903d6d3a3c69f53
@@ -12,72 +12,18 @@ Follow [Semantic Versioning 2.0.0](https://semver.org/):
12
12
  | **MINOR** | New features (backward compatible) | `1.0.0` → `1.1.0` |
13
13
  | **PATCH** | Bug fixes (backward compatible) | `1.0.0` → `1.0.1` |
14
14
 
15
- ### Pre-release Versions
16
-
17
- For beta/alpha releases, append a pre-release identifier:
18
-
19
- ```
20
- 1.0.0-alpha.1
21
- 1.0.0-beta.1
22
- 1.0.0-rc.1
23
- ```
24
-
25
15
  ## Changelog Format
26
16
 
27
- Follow [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format:
28
-
29
- ```markdown
30
- ## [Unreleased]
31
-
32
- ## [1.2.0] - 2025-03-15
33
-
34
- ### Added
35
- - New feature description
36
-
37
- ### Changed
38
- - Modified behavior description
39
-
40
- ### Deprecated
41
- - Feature scheduled for removal
42
-
43
- ### Removed
44
- - Deleted feature description
45
-
46
- ### Fixed
47
- - Bug fix description
48
-
49
- ### Security
50
- - Security patch description
51
- ```
52
-
53
- ### Changelog Guidelines
54
-
55
- 1. **Maintain [Unreleased]** - Always keep an Unreleased section at the top
56
- 2. **Add entries as you work** - Don't wait until release time
57
- 3. **User-focused language** - Write for gem users, not developers
58
- 4. **Link to issues/PRs** - Reference GitHub issues when relevant
59
- 5. **Newest first** - Most recent version at top
60
-
61
- ### What to Include
62
-
63
- | Include | Exclude |
64
- |---------|---------|
65
- | API additions/changes | Internal refactors |
66
- | Bug fixes users might hit | Code style changes |
67
- | Deprecation notices | Test-only changes |
68
- | Breaking changes (prominent) | Documentation typos |
69
- | Security fixes | Dependency updates (minor) |
17
+ Follow [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format. Maintain an `[Unreleased]` section at the top for work in progress.
70
18
 
71
19
  ## Release Process
72
20
 
73
21
  ### Prerequisites
74
22
 
75
- Before releasing:
76
-
77
23
  1. All tests pass (`bundle exec rake`)
78
- 2. CHANGELOG.md has entry for new version
79
- 3. No uncommitted changes
80
- 4. On `main` branch (or confirm if not)
24
+ 2. CHANGELOG.md has entry for the new version
25
+ 3. You have push access to main branch
26
+ 4. You have RubyGems publish credentials configured
81
27
 
82
28
  ### Release Command
83
29
 
@@ -94,19 +40,40 @@ bin/release 1.2.0
94
40
 
95
41
  1. Validates version format (semantic versioning)
96
42
  2. Checks CHANGELOG.md has entry for version
97
- 3. Updates `lib/claude_agent/version.rb`
98
- 4. Updates `Gemfile.lock`
99
- 5. Commits with message "Release vX.Y.Z"
100
- 6. Creates annotated tag `vX.Y.Z`
101
- 7. Pushes commit and tag to remote
102
- 8. Builds and publishes gem to RubyGems
43
+ 3. Checks tag doesn't already exist
44
+ 4. Updates `lib/claude_agent/version.rb`
45
+ 5. Updates `Gemfile.lock`
46
+ 6. Commits with message "Bump version for X.Y.Z"
47
+ 7. Pushes to current branch
48
+ 8. Creates and pushes tag `vX.Y.Z`
49
+ 9. Builds and publishes gem to RubyGems
103
50
 
104
- ### Post-Release
51
+ ### Example Workflow
52
+
53
+ ```bash
54
+ # 1. Ensure tests pass
55
+ bundle exec rake
105
56
 
106
- After running `bin/release`:
57
+ # 2. Update CHANGELOG.md
58
+ # Move items from [Unreleased] to new version section:
59
+ ## [1.2.0] - 2025-03-15
60
+
61
+ ### Added
62
+ - New feature description
107
63
 
108
- 1. Create GitHub release at the new tag
109
- 2. Add `## [Unreleased]` section to CHANGELOG.md
64
+ # 3. Commit changelog
65
+ git add CHANGELOG.md
66
+ git commit -m "docs: update changelog for 1.2.0"
67
+ git push
68
+
69
+ # 4. Release
70
+ bin/release 1.2.0
71
+ ```
72
+
73
+ ### Post-Release
74
+
75
+ 1. Add `## [Unreleased]` section to CHANGELOG.md if needed
76
+ 2. Optionally create a GitHub release at the new tag
110
77
 
111
78
  ## Version Bumping Guidelines
112
79
 
@@ -115,7 +82,6 @@ After running `bin/release`:
115
82
  - Removing public methods/classes
116
83
  - Changing method signatures (required params)
117
84
  - Changing return types
118
- - Renaming public constants
119
85
  - Dropping Ruby version support
120
86
 
121
87
  ### When to Bump MINOR (Feature)
@@ -130,48 +96,3 @@ After running `bin/release`:
130
96
  - Bug fixes
131
97
  - Documentation corrections
132
98
  - Performance improvements (no API change)
133
- - Internal refactoring (no API change)
134
-
135
- ## Example Release Workflow
136
-
137
- ```bash
138
- # 1. Ensure tests pass
139
- bundle exec rake
140
-
141
- # 2. Update CHANGELOG.md
142
- # Add entry under [Unreleased], then rename to version:
143
- ## [1.2.0] - 2025-03-15
144
-
145
- ### Added
146
- - New `Client#foo` method for bar functionality
147
-
148
- ### Fixed
149
- - Resolved timeout issue in subprocess transport
150
-
151
- # 3. Commit changelog
152
- git add CHANGELOG.md
153
- git commit -m "docs: update changelog for 1.2.0"
154
-
155
- # 4. Release
156
- bin/release 1.2.0
157
-
158
- # 5. Add new Unreleased section
159
- # Edit CHANGELOG.md to add:
160
- ## [Unreleased]
161
-
162
- # 6. Commit
163
- git add CHANGELOG.md
164
- git commit -m "docs: add unreleased section"
165
- git push
166
- ```
167
-
168
- ## Gem Metadata
169
-
170
- The gemspec includes these URIs for RubyGems.org:
171
-
172
- ```ruby
173
- spec.metadata["source_code_uri"] = spec.homepage
174
- spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
175
- ```
176
-
177
- This enables the "Changelog" link on the RubyGems.org gem page.
data/CHANGELOG.md CHANGED
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.2] - 2026-01-18
11
+
12
+ ### Fixed
13
+ - Release script now uses `bundle install` (Bundler 4.x compatibility)
14
+
15
+ ### Changed
16
+ - Release script prompts for RubyGems OTP upfront
17
+ - Release script creates GitHub releases automatically
18
+
19
+ ## [0.4.1] - 2026-01-18
20
+
21
+ ### Changed
22
+ - Simplified release script to match Kamal's approach
23
+
24
+ ## [0.4.0] - 2026-01-18
25
+
26
+ ### Added
27
+ - `TaskNotificationMessage` for background task completion notifications
28
+ - `Setup` hook event with `SetupInput` for init/maintenance triggers
29
+ - `skills` and `max_turns` fields in `AgentDefinition` (TypeScript SDK v0.2.12 parity)
30
+ - `init`, `init_only`, `maintenance` options for running Setup hooks
31
+ - `ClaudeAgent.run_setup` convenience method for CI/CD pipelines
32
+ - Hook-specific output fields documentation (`additionalContext`, `permissionDecision`, `updatedMCPToolOutput`, etc.)
33
+ - Document `settings` option accepts JSON strings (for plansDirectory, etc.)
34
+
10
35
  ## [0.3.0] - 2026-01-16
11
36
 
12
37
  ### Added
data/README.md CHANGED
@@ -64,6 +64,26 @@ ClaudeAgent::Client.open do |client|
64
64
  end
65
65
  ```
66
66
 
67
+ ### Run Setup Hooks
68
+
69
+ Run Setup hooks without starting a conversation (useful for CI/CD pipelines):
70
+
71
+ ```ruby
72
+ require "claude_agent"
73
+
74
+ # Run init Setup hooks (default)
75
+ messages = ClaudeAgent.run_setup
76
+ result = messages.last
77
+ puts "Setup completed" if result.success?
78
+
79
+ # Run init Setup hooks with custom options
80
+ options = ClaudeAgent::Options.new(cwd: "/my/project")
81
+ ClaudeAgent.run_setup(trigger: :init, options: options)
82
+
83
+ # Run maintenance Setup hooks
84
+ ClaudeAgent.run_setup(trigger: :maintenance)
85
+ ```
86
+
67
87
  ## Configuration
68
88
 
69
89
  Use `ClaudeAgent::Options` to customize behavior:
@@ -161,7 +181,9 @@ agents = {
161
181
  description: "Runs tests and reports results",
162
182
  prompt: "You are a test runner. Execute tests and report failures clearly.",
163
183
  tools: ["Read", "Bash"],
164
- model: "haiku"
184
+ model: "haiku",
185
+ max_turns: 5, # Max agentic turns before stopping
186
+ skills: ["testing", "debug"] # Skills to preload into agent context
165
187
  )
166
188
  }
167
189
 
@@ -277,6 +299,20 @@ auth.output # Auth output messages
277
299
  auth.error # Error message (if any)
278
300
  ```
279
301
 
302
+ ### TaskNotificationMessage
303
+
304
+ Background task completion notifications:
305
+
306
+ ```ruby
307
+ notification.task_id # Background task ID
308
+ notification.status # "completed", "failed", or "stopped"
309
+ notification.output_file # Path to task output file
310
+ notification.summary # Task summary
311
+ notification.completed? # Convenience predicate
312
+ notification.failed? # Convenience predicate
313
+ notification.stopped? # Convenience predicate
314
+ ```
315
+
280
316
  ## Content Blocks
281
317
 
282
318
  Assistant messages contain content blocks:
@@ -449,6 +485,7 @@ All available hook events:
449
485
  - `SubagentStop` - When subagent stops
450
486
  - `PreCompact` - Before conversation compaction
451
487
  - `PermissionRequest` - When permission is requested
488
+ - `Setup` - Initial setup or maintenance (trigger: "init" or "maintenance")
452
489
 
453
490
  ### Hook Input Types
454
491
 
@@ -466,6 +503,7 @@ All available hook events:
466
503
  | SubagentStop | `SubagentStopInput` | stop_hook_active, agent_id, agent_transcript_path |
467
504
  | PreCompact | `PreCompactInput` | trigger, custom_instructions |
468
505
  | PermissionRequest | `PermissionRequestInput` | tool_name, tool_input, permission_suggestions |
506
+ | Setup | `SetupInput` | trigger (init/maintenance) |
469
507
 
470
508
  All hook inputs inherit from `BaseHookInput` with: `hook_event_name`, `session_id`, `transcript_path`, `cwd`, `permission_mode`.
471
509
 
data/SPEC.md CHANGED
@@ -3,8 +3,8 @@
3
3
  This document provides a comprehensive specification of the Claude Agent SDK, comparing feature parity across the official TypeScript and Python SDKs with this Ruby implementation.
4
4
 
5
5
  **Reference Versions:**
6
- - TypeScript SDK: v0.2.9 (npm package)
7
- - Python SDK: v0.1.20 from GitHub (commit 04da88d)
6
+ - TypeScript SDK: v0.2.12 (npm package)
7
+ - Python SDK: v0.1.20 from GitHub (commit 05d2eb4)
8
8
  - Ruby SDK: This repository
9
9
 
10
10
  ---
@@ -30,50 +30,54 @@ This document provides a comprehensive specification of the Claude Agent SDK, co
30
30
 
31
31
  Configuration options for SDK queries and clients.
32
32
 
33
- | Option | TypeScript | Python | Ruby | Notes |
34
- |-----------------------------------|:----------:|:------:|:----:|-------------------------------------------------------------|
35
- | `model` | ✅ | ✅ | ✅ | Claude model identifier |
36
- | `fallbackModel` | ✅ | ✅ | ✅ | Fallback if primary fails |
37
- | `systemPrompt` | ✅ | ✅ | ✅ | String or preset object |
38
- | `appendSystemPrompt` | ✅ | ❌ | ✅ | Append to system prompt (TS SDK has via preset) |
39
- | `tools` | ✅ | ✅ | ✅ | Array or preset |
40
- | `allowedTools` | ✅ | ✅ | ✅ | Auto-allowed tools |
41
- | `disallowedTools` | ✅ | ✅ | ✅ | Blocked tools |
42
- | `permissionMode` | ✅ | ✅ | ✅ | default/acceptEdits/plan/bypassPermissions/delegate/dontAsk |
43
- | `allowDangerouslySkipPermissions` | ✅ | ❌ | ✅ | Required for bypassPermissions |
44
- | `canUseTool` | ✅ | ✅ | ✅ | Permission callback |
45
- | `permissionPromptToolName` | ✅ | ✅ | ✅ | MCP tool for permission prompts |
46
- | `maxTurns` | ✅ | ✅ | ✅ | Max conversation turns |
47
- | `maxBudgetUsd` | ✅ | ✅ | ✅ | Max USD budget |
48
- | `maxThinkingTokens` | ✅ | ✅ | ✅ | Max thinking tokens |
49
- | `continue` | ✅ | ✅ | ✅ | Continue most recent conversation |
50
- | `resume` | ✅ | ✅ | ✅ | Resume session by ID |
51
- | `resumeSessionAt` | ✅ | ❌ | ✅ | Resume to specific message UUID |
52
- | `forkSession` | ✅ | ✅ | ✅ | Fork on resume |
53
- | `persistSession` | ✅ | ❌ | ✅ | Whether to persist to disk |
54
- | `enableFileCheckpointing` | ✅ | ✅ | ✅ | Track file changes for rewind |
55
- | `includePartialMessages` | ✅ | ✅ | ✅ | Include stream events |
56
- | `outputFormat` | ✅ | ✅ | ✅ | JSON schema for structured output |
57
- | `mcpServers` | ✅ | ✅ | ✅ | MCP server configurations |
58
- | `strictMcpConfig` | ✅ | ❌ | ✅ | Strict validation of MCP config |
59
- | `hooks` | ✅ | ✅ | ✅ | Hook callbacks |
60
- | `agents` | ✅ | ✅ | ✅ | Custom subagent definitions |
61
- | `cwd` | ✅ | ✅ | ✅ | Working directory |
62
- | `additionalDirectories` | ✅ | ✅ | ✅ | Extra allowed directories |
63
- | `env` | ✅ | ✅ | ✅ | Environment variables |
64
- | `sandbox` | ✅ | ✅ | ✅ | Sandbox settings |
65
- | `settingSources` | ✅ | | ✅ | Which settings to load |
66
- | `plugins` | ✅ | ✅ | ✅ | Plugin configurations |
67
- | `betas` | ✅ | ✅ | ✅ | Beta features (e.g., context-1m-2025-08-07) |
68
- | `agent` | ✅ | | ✅ | Agent name for main thread |
69
- | `abortController` | ✅ | ❌ | ✅ | Cancellation controller |
70
- | `stderr` | ✅ | | ✅ | Stderr callback |
71
- | `spawnClaudeCodeProcess` | ✅ | | ✅ | Custom spawn function |
72
- | `pathToClaudeCodeExecutable` | ✅ | | ✅ | Custom CLI path |
73
- | `executable` | ✅ | N/A | N/A | JS runtime (node/bun/deno) - JS-specific |
74
- | `executableArgs` | ✅ | N/A | N/A | JS runtime args - JS-specific |
75
- | `extraArgs` | ✅ | | | Extra CLI arguments |
76
- | `user` | | ✅ | ✅ | User identifier |
33
+ | Option | TypeScript | Python | Ruby | Notes |
34
+ |-----------------------------------|:----------:|:------:|:----:|--------------------------------------------------------------|
35
+ | `model` | ✅ | ✅ | ✅ | Claude model identifier |
36
+ | `fallbackModel` | ✅ | ✅ | ✅ | Fallback if primary fails |
37
+ | `systemPrompt` | ✅ | ✅ | ✅ | String or preset object |
38
+ | `appendSystemPrompt` | ✅ | ❌ | ✅ | Append to system prompt (TS SDK has via preset) |
39
+ | `tools` | ✅ | ✅ | ✅ | Array or preset |
40
+ | `allowedTools` | ✅ | ✅ | ✅ | Auto-allowed tools |
41
+ | `disallowedTools` | ✅ | ✅ | ✅ | Blocked tools |
42
+ | `permissionMode` | ✅ | ✅ | ✅ | default/acceptEdits/plan/bypassPermissions/delegate/dontAsk |
43
+ | `allowDangerouslySkipPermissions` | ✅ | ❌ | ✅ | Required for bypassPermissions |
44
+ | `canUseTool` | ✅ | ✅ | ✅ | Permission callback |
45
+ | `permissionPromptToolName` | ✅ | ✅ | ✅ | MCP tool for permission prompts |
46
+ | `maxTurns` | ✅ | ✅ | ✅ | Max conversation turns |
47
+ | `maxBudgetUsd` | ✅ | ✅ | ✅ | Max USD budget |
48
+ | `maxThinkingTokens` | ✅ | ✅ | ✅ | Max thinking tokens |
49
+ | `continue` | ✅ | ✅ | ✅ | Continue most recent conversation |
50
+ | `resume` | ✅ | ✅ | ✅ | Resume session by ID |
51
+ | `resumeSessionAt` | ✅ | ❌ | ✅ | Resume to specific message UUID |
52
+ | `forkSession` | ✅ | ✅ | ✅ | Fork on resume |
53
+ | `persistSession` | ✅ | ❌ | ✅ | Whether to persist to disk |
54
+ | `enableFileCheckpointing` | ✅ | ✅ | ✅ | Track file changes for rewind |
55
+ | `includePartialMessages` | ✅ | ✅ | ✅ | Include stream events |
56
+ | `outputFormat` | ✅ | ✅ | ✅ | JSON schema for structured output |
57
+ | `mcpServers` | ✅ | ✅ | ✅ | MCP server configurations |
58
+ | `strictMcpConfig` | ✅ | ❌ | ✅ | Strict validation of MCP config |
59
+ | `hooks` | ✅ | ✅ | ✅ | Hook callbacks |
60
+ | `agents` | ✅ | ✅ | ✅ | Custom subagent definitions |
61
+ | `cwd` | ✅ | ✅ | ✅ | Working directory |
62
+ | `additionalDirectories` | ✅ | ✅ | ✅ | Extra allowed directories |
63
+ | `env` | ✅ | ✅ | ✅ | Environment variables |
64
+ | `sandbox` | ✅ | ✅ | ✅ | Sandbox settings |
65
+ | `settings` | ✅ | | ✅ | Settings file path or JSON string (e.g., plansDirectory) |
66
+ | `settingSources` | ✅ | ✅ | ✅ | Which settings to load |
67
+ | `plugins` | ✅ | ✅ | ✅ | Plugin configurations |
68
+ | `betas` | ✅ | | ✅ | Beta features (e.g., context-1m-2025-08-07) |
69
+ | `agent` | ✅ | ❌ | ✅ | Agent name for main thread |
70
+ | `abortController` | ✅ | | ✅ | Cancellation controller |
71
+ | `stderr` | ✅ | | ✅ | Stderr callback |
72
+ | `spawnClaudeCodeProcess` | ✅ | | ✅ | Custom spawn function |
73
+ | `pathToClaudeCodeExecutable` | ✅ | | | Custom CLI path |
74
+ | `executable` | ✅ | N/A | N/A | JS runtime (node/bun/deno) - JS-specific |
75
+ | `executableArgs` | ✅ | N/A | N/A | JS runtime args - JS-specific |
76
+ | `extraArgs` | | ✅ | ✅ | Extra CLI arguments |
77
+ | `user` | ✅ | ✅ | ✅ | User identifier (V2 Session API) |
78
+ | `init` | ✅ | ❌ | ✅ | Run Setup hooks (init trigger), then continue (hidden CLI) |
79
+ | `initOnly` | ✅ | ❌ | ✅ | Run Setup hooks (init trigger), then exit (hidden CLI) |
80
+ | `maintenance` | ✅ | ❌ | ✅ | Run Setup hooks (maintenance trigger), continue (hidden CLI) |
77
81
 
78
82
  ---
79
83
 
@@ -94,6 +98,7 @@ Messages exchanged between SDK and CLI.
94
98
  | `ToolProgressMessage` | ✅ | ❌ | ✅ | Long-running tool progress |
95
99
  | `HookResponseMessage` | ✅ | ❌ | ✅ | Hook execution output |
96
100
  | `AuthStatusMessage` | ✅ | ❌ | ✅ | Authentication status |
101
+ | `TaskNotificationMessage`| ✅ | ❌ | ✅ | Background task completion |
97
102
 
98
103
  ### Message Fields
99
104
 
@@ -203,20 +208,21 @@ Event hooks for intercepting and modifying SDK behavior.
203
208
 
204
209
  ### Hook Events
205
210
 
206
- | Event | TypeScript | Python | Ruby | Notes |
207
- |----------------------|:----------:|:------:|:----:|------------------------|
208
- | `PreToolUse` | ✅ | ✅ | ✅ | Before tool execution |
209
- | `PostToolUse` | ✅ | ✅ | ✅ | After tool execution |
210
- | `PostToolUseFailure` | ✅ | ❌ | ✅ | After tool failure |
211
- | `Notification` | ✅ | ❌ | ✅ | System notifications |
212
- | `UserPromptSubmit` | ✅ | ✅ | ✅ | User message submitted |
213
- | `SessionStart` | ✅ | ❌ | ✅ | Session starts |
214
- | `SessionEnd` | ✅ | ❌ | ✅ | Session ends |
215
- | `Stop` | ✅ | ✅ | ✅ | Agent stops |
216
- | `SubagentStart` | ✅ | ❌ | ✅ | Subagent starts |
217
- | `SubagentStop` | ✅ | ✅ | ✅ | Subagent stops |
218
- | `PreCompact` | ✅ | ✅ | ✅ | Before compaction |
219
- | `PermissionRequest` | ✅ | ❌ | ✅ | Permission requested |
211
+ | Event | TypeScript | Python | Ruby | Notes |
212
+ |----------------------|:----------:|:------:|:----:|---------------------------|
213
+ | `PreToolUse` | ✅ | ✅ | ✅ | Before tool execution |
214
+ | `PostToolUse` | ✅ | ✅ | ✅ | After tool execution |
215
+ | `PostToolUseFailure` | ✅ | ❌ | ✅ | After tool failure |
216
+ | `Notification` | ✅ | ❌ | ✅ | System notifications |
217
+ | `UserPromptSubmit` | ✅ | ✅ | ✅ | User message submitted |
218
+ | `SessionStart` | ✅ | ❌ | ✅ | Session starts |
219
+ | `SessionEnd` | ✅ | ❌ | ✅ | Session ends |
220
+ | `Stop` | ✅ | ✅ | ✅ | Agent stops |
221
+ | `SubagentStart` | ✅ | ❌ | ✅ | Subagent starts |
222
+ | `SubagentStop` | ✅ | ✅ | ✅ | Subagent stops |
223
+ | `PreCompact` | ✅ | ✅ | ✅ | Before compaction |
224
+ | `PermissionRequest` | ✅ | ❌ | ✅ | Permission requested |
225
+ | `Setup` | ✅ | ❌ | ✅ | Initial setup/maintenance |
220
226
 
221
227
  ### Hook Input Types
222
228
 
@@ -234,6 +240,7 @@ Event hooks for intercepting and modifying SDK behavior.
234
240
  | `SubagentStopHookInput` | ✅ | ✅ | ✅ |
235
241
  | `PreCompactHookInput` | ✅ | ✅ | ✅ |
236
242
  | `PermissionRequestHookInput` | ✅ | ❌ | ✅ |
243
+ | `SetupHookInput` | ✅ | ❌ | ✅ |
237
244
 
238
245
  ### Hook Output Types
239
246
 
@@ -249,6 +256,62 @@ Event hooks for intercepting and modifying SDK behavior.
249
256
  | `reason` | ✅ | ✅ | ✅ | Reason feedback |
250
257
  | `hookSpecificOutput` | ✅ | ✅ | ✅ | Event-specific output |
251
258
 
259
+ ### Hook-Specific Output Fields
260
+
261
+ Event-specific fields returned via `hookSpecificOutput`:
262
+
263
+ #### PreToolUseHookSpecificOutput
264
+
265
+ | Field | TypeScript | Python | Ruby | Notes |
266
+ |----------------------------|:----------:|:------:|:----:|------------------------------------|
267
+ | `permissionDecision` | ✅ | ❌ | ✅ | `allow`, `deny`, or `ask` |
268
+ | `permissionDecisionReason` | ✅ | ❌ | ✅ | Reason for permission decision |
269
+ | `updatedInput` | ✅ | ✅ | ✅ | Modified tool input |
270
+ | `additionalContext` | ✅ | ❌ | ✅ | Context string returned to model |
271
+
272
+ #### PostToolUseHookSpecificOutput
273
+
274
+ | Field | TypeScript | Python | Ruby | Notes |
275
+ |------------------------|:----------:|:------:|:----:|----------------------------------|
276
+ | `additionalContext` | ✅ | ❌ | ✅ | Context string returned to model |
277
+ | `updatedMCPToolOutput` | ✅ | ❌ | ✅ | Modified MCP tool output |
278
+
279
+ #### PostToolUseFailureHookSpecificOutput
280
+
281
+ | Field | TypeScript | Python | Ruby | Notes |
282
+ |---------------------|:----------:|:------:|:----:|----------------------------------|
283
+ | `additionalContext` | ✅ | ❌ | ✅ | Context string returned to model |
284
+
285
+ #### SessionStartHookSpecificOutput
286
+
287
+ | Field | TypeScript | Python | Ruby | Notes |
288
+ |---------------------|:----------:|:------:|:----:|----------------------------------|
289
+ | `additionalContext` | ✅ | ❌ | ✅ | Context string returned to model |
290
+
291
+ #### SetupHookSpecificOutput
292
+
293
+ | Field | TypeScript | Python | Ruby | Notes |
294
+ |---------------------|:----------:|:------:|:----:|----------------------------------|
295
+ | `additionalContext` | ✅ | ❌ | ✅ | Context string returned to model |
296
+
297
+ #### SubagentStartHookSpecificOutput
298
+
299
+ | Field | TypeScript | Python | Ruby | Notes |
300
+ |---------------------|:----------:|:------:|:----:|----------------------------------|
301
+ | `additionalContext` | ✅ | ❌ | ✅ | Context string returned to model |
302
+
303
+ #### UserPromptSubmitHookSpecificOutput
304
+
305
+ | Field | TypeScript | Python | Ruby | Notes |
306
+ |---------------------|:----------:|:------:|:----:|----------------------------------|
307
+ | `additionalContext` | ✅ | ❌ | ✅ | Context string returned to model |
308
+
309
+ #### PermissionRequestHookSpecificOutput
310
+
311
+ | Field | TypeScript | Python | Ruby | Notes |
312
+ |------------|:----------:|:------:|:----:|------------------------------------------|
313
+ | `decision` | ✅ | ❌ | ✅ | `{ behavior: 'allow'/'deny', ... }` obj |
314
+
252
315
  ### Hook Matcher
253
316
 
254
317
  | Field | TypeScript | Python | Ruby |
@@ -415,6 +478,8 @@ Custom subagent definitions.
415
478
  | `model` | ✅ | ✅ | ✅ | Model override (sonnet/opus/haiku/inherit) |
416
479
  | `mcpServers` | ✅ | ❌ | ✅ | Agent-specific MCP servers |
417
480
  | `criticalSystemReminder_EXPERIMENTAL` | ✅ | ❌ | ✅ | Critical reminder (experimental) |
481
+ | `skills` | ✅ | ❌ | ✅ | Skills to preload into agent context |
482
+ | `maxTurns` | ✅ | ❌ | ✅ | Max agentic turns before stopping |
418
483
 
419
484
  ---
420
485
 
@@ -543,10 +608,13 @@ Public API surface for SDK clients.
543
608
  - Primary reference for API surface (most comprehensive)
544
609
  - Source is bundled/minified, but `sdk.d.ts` provides complete type definitions
545
610
  - Includes unstable V2 session API
546
- - Version 0.2.9 adds `agent` option for specifying main thread agent
547
611
  - Adds `deno` as supported executable option
548
612
  - Includes experimental `criticalSystemReminder_EXPERIMENTAL` for agent definitions
549
613
  - `SessionStartHookInput` includes `model` field
614
+ - v0.2.12 adds `Setup` hook event for init/maintenance
615
+ - v0.2.12 adds `skills` and `maxTurns` to AgentDefinition
616
+ - v0.2.12 adds `TaskNotificationMessage` for background task completion
617
+ - v0.2.12 adds `user` option to SDKSessionOptions
550
618
 
551
619
  ### Python SDK
552
620
  - Full source available (v0.1.20)
@@ -561,6 +629,6 @@ Public API surface for SDK clients.
561
629
  - Ruby-idiomatic patterns (Data.define, snake_case)
562
630
  - Complete control protocol support
563
631
  - Dedicated Client class for multi-turn conversations
564
- - Full hook event support including all 12 events
632
+ - Full hook event support including all 13 events
565
633
  - Full V2 Session API support (unstable)
566
634
  - `executable`/`executableArgs` marked N/A (JS runtime options not applicable to Ruby)
@@ -15,6 +15,7 @@ module ClaudeAgent
15
15
  SubagentStop
16
16
  PreCompact
17
17
  PermissionRequest
18
+ Setup
18
19
  ].freeze
19
20
 
20
21
  # Matcher configuration for hooks
@@ -227,4 +228,35 @@ module ClaudeAgent
227
228
  @permission_suggestions = permission_suggestions
228
229
  end
229
230
  end
231
+
232
+ # Input for Setup hook (TypeScript SDK parity)
233
+ #
234
+ # Triggered during initial setup or maintenance operations.
235
+ #
236
+ # @example
237
+ # input = SetupInput.new(trigger: "init", session_id: "abc-123")
238
+ # input.trigger # => "init"
239
+ # input.init? # => true
240
+ #
241
+ class SetupInput < BaseHookInput
242
+ attr_reader :trigger
243
+
244
+ # @param trigger [String] One of: "init", "maintenance"
245
+ def initialize(trigger:, **kwargs)
246
+ super(hook_event_name: "Setup", **kwargs)
247
+ @trigger = trigger
248
+ end
249
+
250
+ # Check if this is an init trigger
251
+ # @return [Boolean]
252
+ def init?
253
+ trigger == "init"
254
+ end
255
+
256
+ # Check if this is a maintenance trigger
257
+ # @return [Boolean]
258
+ def maintenance?
259
+ trigger == "maintenance"
260
+ end
261
+ end
230
262
  end
@@ -11,7 +11,7 @@ module ClaudeAgent
11
11
  # Parse a raw message hash into a typed message object
12
12
  #
13
13
  # @param raw [Hash] Raw message from CLI
14
- # @return [UserMessage, UserMessageReplay, AssistantMessage, SystemMessage, ResultMessage, StreamEvent, CompactBoundaryMessage, StatusMessage, ToolProgressMessage, HookResponseMessage, AuthStatusMessage]
14
+ # @return [UserMessage, UserMessageReplay, AssistantMessage, SystemMessage, ResultMessage, StreamEvent, CompactBoundaryMessage, StatusMessage, ToolProgressMessage, HookResponseMessage, AuthStatusMessage, TaskNotificationMessage]
15
15
  # @raise [MessageParseError] If message cannot be parsed
16
16
  def parse(raw)
17
17
  type = raw["type"]
@@ -30,6 +30,8 @@ module ClaudeAgent
30
30
  parse_status_message(raw)
31
31
  when "hook_response"
32
32
  parse_hook_response_message(raw)
33
+ when "task_notification"
34
+ parse_task_notification_message(raw)
33
35
  else
34
36
  parse_system_message(raw)
35
37
  end
@@ -258,5 +260,16 @@ module ClaudeAgent
258
260
  error: raw["error"]
259
261
  )
260
262
  end
263
+
264
+ def parse_task_notification_message(raw)
265
+ TaskNotificationMessage.new(
266
+ uuid: raw["uuid"] || "",
267
+ session_id: fetch_dual(raw, :session_id, ""),
268
+ task_id: fetch_dual(raw, :task_id, ""),
269
+ status: raw["status"] || "unknown",
270
+ output_file: fetch_dual(raw, :output_file, ""),
271
+ summary: raw["summary"] || ""
272
+ )
273
+ end
261
274
  end
262
275
  end
@@ -404,6 +404,70 @@ module ClaudeAgent
404
404
  end
405
405
  end
406
406
 
407
+ # Task notification message (TypeScript SDK parity)
408
+ #
409
+ # Sent when a background task completes, fails, or is stopped.
410
+ # Used for tracking async task execution status.
411
+ #
412
+ # @example
413
+ # msg = TaskNotificationMessage.new(
414
+ # uuid: "msg-123",
415
+ # session_id: "session-abc",
416
+ # task_id: "task-456",
417
+ # status: "completed",
418
+ # output_file: "/path/to/output.txt",
419
+ # summary: "Task completed successfully"
420
+ # )
421
+ # msg.completed? # => true
422
+ # msg.failed? # => false
423
+ #
424
+ # Status values:
425
+ # - "completed" - Task finished successfully
426
+ # - "failed" - Task encountered an error
427
+ # - "stopped" - Task was manually stopped
428
+ #
429
+ TaskNotificationMessage = Data.define(
430
+ :uuid,
431
+ :session_id,
432
+ :task_id,
433
+ :status,
434
+ :output_file,
435
+ :summary
436
+ ) do
437
+ def initialize(
438
+ uuid:,
439
+ session_id:,
440
+ task_id:,
441
+ status:,
442
+ output_file:,
443
+ summary:
444
+ )
445
+ super
446
+ end
447
+
448
+ def type
449
+ :task_notification
450
+ end
451
+
452
+ # Check if task completed successfully
453
+ # @return [Boolean]
454
+ def completed?
455
+ status == "completed"
456
+ end
457
+
458
+ # Check if task failed
459
+ # @return [Boolean]
460
+ def failed?
461
+ status == "failed"
462
+ end
463
+
464
+ # Check if task was stopped
465
+ # @return [Boolean]
466
+ def stopped?
467
+ status == "stopped"
468
+ end
469
+ end
470
+
407
471
  # All message types
408
472
  MESSAGE_TYPES = [
409
473
  UserMessage,
@@ -416,6 +480,7 @@ module ClaudeAgent
416
480
  StatusMessage,
417
481
  ToolProgressMessage,
418
482
  HookResponseMessage,
419
- AuthStatusMessage
483
+ AuthStatusMessage,
484
+ TaskNotificationMessage
420
485
  ].freeze
421
486
  end
@@ -38,7 +38,10 @@ module ClaudeAgent
38
38
  include_partial_messages: false,
39
39
  enable_file_checkpointing: false,
40
40
  persist_session: true,
41
- betas: []
41
+ betas: [],
42
+ init: false,
43
+ init_only: false,
44
+ maintenance: false
42
45
  }.freeze
43
46
 
44
47
  # All configurable attributes
@@ -55,6 +58,7 @@ module ClaudeAgent
55
58
  include_partial_messages output_format enable_file_checkpointing
56
59
  persist_session betas max_buffer_size stderr_callback
57
60
  abort_controller spawn_claude_code_process
61
+ init init_only maintenance
58
62
  ].freeze
59
63
 
60
64
  attr_accessor(*ATTRIBUTES)
@@ -83,6 +87,7 @@ module ClaudeAgent
83
87
  args.concat(settings_args)
84
88
  args.concat(environment_args)
85
89
  args.concat(output_args)
90
+ args.concat(setup_hook_args)
86
91
  args.concat(extra_cli_args)
87
92
  end
88
93
  end
@@ -230,6 +235,14 @@ module ClaudeAgent
230
235
  end
231
236
  end
232
237
 
238
+ def setup_hook_args
239
+ [].tap do |args|
240
+ args.push("--init") if init
241
+ args.push("--init-only") if init_only
242
+ args.push("--maintenance") if maintenance
243
+ end
244
+ end
245
+
233
246
  def extra_cli_args
234
247
  [].tap do |args|
235
248
  extra_args.each do |key, value|
@@ -262,6 +275,11 @@ module ClaudeAgent
262
275
  if max_budget_usd && (!max_budget_usd.is_a?(Numeric) || max_budget_usd <= 0)
263
276
  raise ConfigurationError, "max_budget_usd must be a positive number"
264
277
  end
278
+
279
+ setup_options = [ init, init_only, maintenance ].count { |opt| opt }
280
+ if setup_options > 1
281
+ raise ConfigurationError, "Only one of init, init_only, or maintenance can be set at a time"
282
+ end
265
283
  end
266
284
  end
267
285
  end
@@ -2,6 +2,48 @@
2
2
 
3
3
  module ClaudeAgent
4
4
  class << self
5
+ # Run Setup hooks and exit
6
+ #
7
+ # This is a convenience method for running Setup hooks without starting
8
+ # a conversation. Useful for CI/CD pipelines or scripts that need to
9
+ # ensure setup is complete before proceeding.
10
+ #
11
+ # @param trigger [Symbol] The setup trigger (:init or :maintenance)
12
+ # @param options [Options, nil] Additional configuration options
13
+ # @return [Array<Message>] All messages received during setup
14
+ #
15
+ # @example Run init setup
16
+ # messages = ClaudeAgent.run_setup
17
+ # result = messages.last
18
+ # puts "Setup completed" if result.success?
19
+ #
20
+ # @example Run init setup with custom options
21
+ # options = ClaudeAgent::Options.new(cwd: "/my/project")
22
+ # ClaudeAgent.run_setup(trigger: :init, options: options)
23
+ #
24
+ # @note The :maintenance trigger requires --maintenance flag which
25
+ # continues into a conversation. For maintenance-only behavior,
26
+ # use options with maintenance: true and handle accordingly.
27
+ #
28
+ def run_setup(trigger: :init, options: nil)
29
+ options ||= Options.new
30
+
31
+ case trigger
32
+ when :init
33
+ # Create new options with init_only set
34
+ setup_options = Options.new(**options_to_hash(options).merge(init_only: true))
35
+ when :maintenance
36
+ # Note: There's no --maintenance-only flag, so we use --maintenance
37
+ # which will continue into a conversation. The caller should handle this.
38
+ setup_options = Options.new(**options_to_hash(options).merge(maintenance: true))
39
+ else
40
+ raise ArgumentError, "Invalid trigger: #{trigger}. Must be :init or :maintenance"
41
+ end
42
+
43
+ # Run with an empty prompt - setup hooks run before the prompt is processed
44
+ query(prompt: "", options: setup_options).to_a
45
+ end
46
+
5
47
  # One-shot query to Claude Code CLI
6
48
  #
7
49
  # This is a simple, stateless interface for sending a single prompt
@@ -86,5 +128,17 @@ module ClaudeAgent
86
128
  end
87
129
  end
88
130
  end
131
+
132
+ private
133
+
134
+ # Convert an Options object to a hash for merging
135
+ # @param options [Options] The options object
136
+ # @return [Hash] Hash of option values
137
+ def options_to_hash(options)
138
+ Options::ATTRIBUTES.each_with_object({}) do |attr, hash|
139
+ value = options.send(attr)
140
+ hash[attr] = value unless value.nil?
141
+ end
142
+ end
89
143
  end
90
144
  end
@@ -150,7 +150,7 @@ module ClaudeAgent
150
150
 
151
151
  # Agent definition for custom subagents (TypeScript SDK parity)
152
152
  #
153
- # @example
153
+ # @example Basic agent
154
154
  # agent = AgentDefinition.new(
155
155
  # description: "Runs tests and reports results",
156
156
  # prompt: "You are a test runner...",
@@ -158,6 +158,14 @@ module ClaudeAgent
158
158
  # model: "haiku"
159
159
  # )
160
160
  #
161
+ # @example Agent with skills and max_turns
162
+ # agent = AgentDefinition.new(
163
+ # description: "Research agent with specialized skills",
164
+ # prompt: "You are a research expert...",
165
+ # skills: ["web-search", "summarization"],
166
+ # max_turns: 10
167
+ # )
168
+ #
161
169
  AgentDefinition = Data.define(
162
170
  :description,
163
171
  :prompt,
@@ -165,7 +173,9 @@ module ClaudeAgent
165
173
  :disallowed_tools,
166
174
  :model,
167
175
  :mcp_servers,
168
- :critical_system_reminder
176
+ :critical_system_reminder,
177
+ :skills,
178
+ :max_turns
169
179
  ) do
170
180
  def initialize(
171
181
  description:,
@@ -174,7 +184,9 @@ module ClaudeAgent
174
184
  disallowed_tools: nil,
175
185
  model: nil,
176
186
  mcp_servers: nil,
177
- critical_system_reminder: nil
187
+ critical_system_reminder: nil,
188
+ skills: nil,
189
+ max_turns: nil
178
190
  )
179
191
  super
180
192
  end
@@ -189,6 +201,8 @@ module ClaudeAgent
189
201
  result[:model] = model if model
190
202
  result[:mcpServers] = mcp_servers if mcp_servers
191
203
  result[:criticalSystemReminder_EXPERIMENTAL] = critical_system_reminder if critical_system_reminder
204
+ result[:skills] = skills if skills
205
+ result[:maxTurns] = max_turns if max_turns
192
206
  result
193
207
  end
194
208
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ClaudeAgent
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: claude_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Carr