claude_code 0.0.16 → 0.0.17
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 +4 -4
- data/.claude/settings.local.json +3 -1
- data/.rspec_status +1 -1
- data/USAGE_EXAMPLES.md +35 -35
- data/claude_code-0.0.16.gem +0 -0
- data/docs/README.md +27 -27
- data/docs/mcp_integration.md +64 -64
- data/docs/streaming.md +53 -53
- data/examples/irb_helpers.rb +21 -28
- data/lib/claude_code/client.rb +112 -82
- data/lib/claude_code/version.rb +1 -1
- data/lib/claude_code.rb +5 -0
- metadata +2 -1
data/docs/mcp_integration.md
CHANGED
@@ -8,7 +8,7 @@ The Ruby Claude Code SDK provides ergonomic integration with Model Context Proto
|
|
8
8
|
|
9
9
|
```ruby
|
10
10
|
# Simplest way to use MCP
|
11
|
-
|
11
|
+
ClaudeCode.quick_mcp_query(
|
12
12
|
"Use the about tool to describe yourself",
|
13
13
|
server_name: "ninja",
|
14
14
|
server_url: "https://mcp-creator-ninja-v1-4-0.mcp.soy/",
|
@@ -24,13 +24,13 @@ end
|
|
24
24
|
|
25
25
|
```ruby
|
26
26
|
# Simple URL string (auto-detected as HTTP)
|
27
|
-
mcp_servers =
|
28
|
-
"my_server",
|
27
|
+
mcp_servers = ClaudeCode.add_mcp_server(
|
28
|
+
"my_server",
|
29
29
|
"https://my-mcp-server.com/"
|
30
30
|
)
|
31
31
|
|
32
32
|
# Explicit HTTP configuration with headers
|
33
|
-
mcp_servers =
|
33
|
+
mcp_servers = ClaudeCode.add_mcp_server("api_server", {
|
34
34
|
type: "http",
|
35
35
|
url: "https://api.example.com/mcp",
|
36
36
|
headers: {
|
@@ -43,7 +43,7 @@ mcp_servers = ClaudeCodeSDK.add_mcp_server("api_server", {
|
|
43
43
|
### 2. Server-Sent Events (SSE)
|
44
44
|
|
45
45
|
```ruby
|
46
|
-
mcp_servers =
|
46
|
+
mcp_servers = ClaudeCode.add_mcp_server("sse_server", {
|
47
47
|
type: "sse",
|
48
48
|
url: "https://stream.example.com/mcp",
|
49
49
|
headers: {
|
@@ -56,13 +56,13 @@ mcp_servers = ClaudeCodeSDK.add_mcp_server("sse_server", {
|
|
56
56
|
|
57
57
|
```ruby
|
58
58
|
# Simple command string
|
59
|
-
mcp_servers =
|
59
|
+
mcp_servers = ClaudeCode.add_mcp_server(
|
60
60
|
"local_server",
|
61
61
|
"node my-mcp-server.js"
|
62
62
|
)
|
63
63
|
|
64
64
|
# Full stdio configuration
|
65
|
-
mcp_servers =
|
65
|
+
mcp_servers = ClaudeCode.add_mcp_server("github_server", {
|
66
66
|
command: "npx",
|
67
67
|
args: ["@modelcontextprotocol/server-github"],
|
68
68
|
env: {
|
@@ -77,19 +77,19 @@ mcp_servers = ClaudeCodeSDK.add_mcp_server("github_server", {
|
|
77
77
|
|
78
78
|
```ruby
|
79
79
|
# Build server configuration
|
80
|
-
mcp_servers =
|
81
|
-
"ninja",
|
80
|
+
mcp_servers = ClaudeCode.add_mcp_server(
|
81
|
+
"ninja",
|
82
82
|
"https://mcp-creator-ninja-v1-4-0.mcp.soy/"
|
83
83
|
)
|
84
84
|
|
85
85
|
# Configure options
|
86
|
-
options =
|
86
|
+
options = ClaudeCode::ClaudeCodeOptions.new(
|
87
87
|
allowed_tools: ["mcp__ninja__about"],
|
88
88
|
max_turns: 1
|
89
89
|
)
|
90
90
|
|
91
91
|
# Query with MCP servers
|
92
|
-
|
92
|
+
ClaudeCode.query(
|
93
93
|
prompt: "Use the about tool",
|
94
94
|
options: options,
|
95
95
|
mcp_servers: mcp_servers
|
@@ -102,12 +102,12 @@ end
|
|
102
102
|
|
103
103
|
```ruby
|
104
104
|
# Configure everything in options
|
105
|
-
options =
|
105
|
+
options = ClaudeCode::ClaudeCodeOptions.new(
|
106
106
|
mcp_servers: {
|
107
|
-
"ninja" =>
|
107
|
+
"ninja" => ClaudeCode::McpHttpServerConfig.new(
|
108
108
|
url: "https://mcp-creator-ninja-v1-4-0.mcp.soy/"
|
109
109
|
),
|
110
|
-
"local" =>
|
110
|
+
"local" => ClaudeCode::McpStdioServerConfig.new(
|
111
111
|
command: "node",
|
112
112
|
args: ["my-server.js"]
|
113
113
|
)
|
@@ -115,7 +115,7 @@ options = ClaudeCodeSDK::ClaudeCodeOptions.new(
|
|
115
115
|
allowed_tools: ["mcp__ninja__about", "mcp__local__my_tool"]
|
116
116
|
)
|
117
117
|
|
118
|
-
|
118
|
+
ClaudeCode.query(prompt: "Use available tools", options: options)
|
119
119
|
```
|
120
120
|
|
121
121
|
### Method 3: Multiple Servers
|
@@ -123,23 +123,23 @@ ClaudeCodeSDK.query(prompt: "Use available tools", options: options)
|
|
123
123
|
```ruby
|
124
124
|
# Build multiple servers
|
125
125
|
servers = {}
|
126
|
-
servers.merge!(
|
127
|
-
servers.merge!(
|
126
|
+
servers.merge!(ClaudeCode.add_mcp_server("ninja", "https://..."))
|
127
|
+
servers.merge!(ClaudeCode.add_mcp_server("github", {
|
128
128
|
command: "npx",
|
129
129
|
args: ["@modelcontextprotocol/server-github"],
|
130
130
|
env: { "GITHUB_TOKEN" => ENV["GITHUB_TOKEN"] }
|
131
131
|
}))
|
132
|
-
servers.merge!(
|
132
|
+
servers.merge!(ClaudeCode.add_mcp_server("filesystem", "npx @modelcontextprotocol/server-filesystem /allowed/path"))
|
133
133
|
|
134
|
-
options =
|
134
|
+
options = ClaudeCode::ClaudeCodeOptions.new(
|
135
135
|
allowed_tools: [
|
136
136
|
"mcp__ninja__about",
|
137
|
-
"mcp__github__search_repositories",
|
137
|
+
"mcp__github__search_repositories",
|
138
138
|
"mcp__filesystem__read_file"
|
139
139
|
]
|
140
140
|
)
|
141
141
|
|
142
|
-
|
142
|
+
ClaudeCode.query(
|
143
143
|
prompt: "Use available tools to help me",
|
144
144
|
options: options,
|
145
145
|
mcp_servers: servers
|
@@ -163,7 +163,7 @@ allowed_tools: ["mcp__ninja"] # Allows all ninja server tools
|
|
163
163
|
### Permission Modes
|
164
164
|
|
165
165
|
```ruby
|
166
|
-
options =
|
166
|
+
options = ClaudeCode::ClaudeCodeOptions.new(
|
167
167
|
permission_mode: "default", # Prompt for dangerous tools
|
168
168
|
# permission_mode: "acceptEdits", # Auto-accept file edits
|
169
169
|
# permission_mode: "bypassPermissions" # Allow all tools (dangerous)
|
@@ -175,7 +175,7 @@ options = ClaudeCodeSDK::ClaudeCodeOptions.new(
|
|
175
175
|
MCP tool calls stream in real-time, showing tool usage and results as they happen:
|
176
176
|
|
177
177
|
```ruby
|
178
|
-
|
178
|
+
ClaudeCode.quick_mcp_query(
|
179
179
|
"Use multiple tools to analyze this project",
|
180
180
|
server_name: "ninja",
|
181
181
|
server_url: "https://mcp-creator-ninja-v1-4-0.mcp.soy/",
|
@@ -183,27 +183,27 @@ ClaudeCodeSDK.quick_mcp_query(
|
|
183
183
|
max_turns: 3
|
184
184
|
).each do |message|
|
185
185
|
case message
|
186
|
-
when
|
186
|
+
when ClaudeCode::SystemMessage
|
187
187
|
puts "🔧 System: MCP servers: #{message.data['mcp_servers'].length}"
|
188
|
-
|
189
|
-
when
|
188
|
+
|
189
|
+
when ClaudeCode::AssistantMessage
|
190
190
|
message.content.each do |block|
|
191
191
|
case block
|
192
|
-
when
|
192
|
+
when ClaudeCode::TextBlock
|
193
193
|
puts "💬 #{block.text}"
|
194
|
-
|
195
|
-
when
|
194
|
+
|
195
|
+
when ClaudeCode::ToolUseBlock
|
196
196
|
puts "🔧 Using tool: #{block.name}"
|
197
197
|
puts "📥 Input: #{block.input}"
|
198
|
-
|
199
|
-
when
|
198
|
+
|
199
|
+
when ClaudeCode::ToolResultBlock
|
200
200
|
puts "📤 Tool result:"
|
201
201
|
puts " Content: #{block.content}"
|
202
202
|
puts " Error: #{block.is_error ? 'Yes' : 'No'}"
|
203
203
|
end
|
204
204
|
end
|
205
|
-
|
206
|
-
when
|
205
|
+
|
206
|
+
when ClaudeCode::ResultMessage
|
207
207
|
puts "✅ Completed - Cost: $#{format('%.6f', message.total_cost_usd || 0)}"
|
208
208
|
end
|
209
209
|
end
|
@@ -213,7 +213,7 @@ end
|
|
213
213
|
|
214
214
|
### Creator Ninja (Example/Testing)
|
215
215
|
```ruby
|
216
|
-
|
216
|
+
ClaudeCode.add_mcp_server(
|
217
217
|
"ninja",
|
218
218
|
"https://mcp-creator-ninja-v1-4-0.mcp.soy/"
|
219
219
|
)
|
@@ -222,7 +222,7 @@ ClaudeCodeSDK.add_mcp_server(
|
|
222
222
|
|
223
223
|
### Filesystem Server
|
224
224
|
```ruby
|
225
|
-
|
225
|
+
ClaudeCode.add_mcp_server("filesystem", {
|
226
226
|
command: "npx",
|
227
227
|
args: ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/path"],
|
228
228
|
})
|
@@ -231,8 +231,8 @@ ClaudeCodeSDK.add_mcp_server("filesystem", {
|
|
231
231
|
|
232
232
|
### GitHub Server
|
233
233
|
```ruby
|
234
|
-
|
235
|
-
command: "npx",
|
234
|
+
ClaudeCode.add_mcp_server("github", {
|
235
|
+
command: "npx",
|
236
236
|
args: ["-y", "@modelcontextprotocol/server-github"],
|
237
237
|
env: {
|
238
238
|
"GITHUB_TOKEN" => ENV["GITHUB_TOKEN"]
|
@@ -243,7 +243,7 @@ ClaudeCodeSDK.add_mcp_server("github", {
|
|
243
243
|
|
244
244
|
### Database Server (Example)
|
245
245
|
```ruby
|
246
|
-
|
246
|
+
ClaudeCode.add_mcp_server("database", {
|
247
247
|
command: "node",
|
248
248
|
args: ["database-mcp-server.js"],
|
249
249
|
env: {
|
@@ -257,7 +257,7 @@ ClaudeCodeSDK.add_mcp_server("database", {
|
|
257
257
|
|
258
258
|
```ruby
|
259
259
|
begin
|
260
|
-
|
260
|
+
ClaudeCode.quick_mcp_query(
|
261
261
|
"Use unavailable tool",
|
262
262
|
server_name: "ninja",
|
263
263
|
server_url: "https://bad-url.com/",
|
@@ -265,10 +265,10 @@ begin
|
|
265
265
|
).each do |message|
|
266
266
|
# Process message
|
267
267
|
end
|
268
|
-
rescue
|
268
|
+
rescue ClaudeCode::ProcessError => e
|
269
269
|
puts "MCP server failed: #{e.message}"
|
270
270
|
puts "Exit code: #{e.exit_code}"
|
271
|
-
rescue
|
271
|
+
rescue ClaudeCode::CLIConnectionError => e
|
272
272
|
puts "Connection failed: #{e.message}"
|
273
273
|
end
|
274
274
|
```
|
@@ -279,28 +279,28 @@ end
|
|
279
279
|
class McpService
|
280
280
|
def self.query_with_mcp(prompt, mcp_config = {})
|
281
281
|
servers = build_mcp_servers(mcp_config)
|
282
|
-
|
283
|
-
options =
|
282
|
+
|
283
|
+
options = ClaudeCode::ClaudeCodeOptions.new(
|
284
284
|
allowed_tools: mcp_config[:allowed_tools] || [],
|
285
285
|
permission_mode: "acceptEdits" # For automated environments
|
286
286
|
)
|
287
|
-
|
288
|
-
|
287
|
+
|
288
|
+
ClaudeCode.query(
|
289
289
|
prompt: prompt,
|
290
290
|
options: options,
|
291
291
|
mcp_servers: servers
|
292
292
|
)
|
293
293
|
end
|
294
|
-
|
294
|
+
|
295
295
|
private
|
296
|
-
|
296
|
+
|
297
297
|
def self.build_mcp_servers(config)
|
298
298
|
servers = {}
|
299
|
-
|
299
|
+
|
300
300
|
config[:servers]&.each do |name, server_config|
|
301
|
-
servers.merge!(
|
301
|
+
servers.merge!(ClaudeCode.add_mcp_server(name, server_config))
|
302
302
|
end
|
303
|
-
|
303
|
+
|
304
304
|
servers
|
305
305
|
end
|
306
306
|
end
|
@@ -344,7 +344,7 @@ CLAUDE_MCP_CONFIG = YAML.load_file(Rails.root.join('config/claude_mcp.yml'))[Rai
|
|
344
344
|
### Production Environment
|
345
345
|
```ruby
|
346
346
|
# Use environment variables for security
|
347
|
-
|
347
|
+
ClaudeCode.add_mcp_server("production_api", {
|
348
348
|
type: "http",
|
349
349
|
url: ENV["MCP_API_URL"],
|
350
350
|
headers: {
|
@@ -360,45 +360,45 @@ ClaudeCodeSDK.add_mcp_server("production_api", {
|
|
360
360
|
# spec/support/mcp_helpers.rb
|
361
361
|
module McpHelpers
|
362
362
|
def mock_mcp_server(name, tools = ["about"])
|
363
|
-
allow(
|
363
|
+
allow(ClaudeCode).to receive(:add_mcp_server).with(name, anything).and_return({
|
364
364
|
name => double("MockMcpServer")
|
365
365
|
})
|
366
|
-
|
367
|
-
allow(
|
366
|
+
|
367
|
+
allow(ClaudeCode).to receive(:query).and_return([
|
368
368
|
mock_assistant_message_with_tools(tools)
|
369
369
|
])
|
370
370
|
end
|
371
|
-
|
371
|
+
|
372
372
|
def mock_assistant_message_with_tools(tools)
|
373
373
|
content = tools.map do |tool|
|
374
|
-
|
374
|
+
ClaudeCode::ToolUseBlock.new(
|
375
375
|
id: "test-#{tool}",
|
376
376
|
name: "mcp__test__#{tool}",
|
377
377
|
input: {}
|
378
378
|
)
|
379
379
|
end
|
380
|
-
|
381
|
-
|
380
|
+
|
381
|
+
ClaudeCode::AssistantMessage.new(content)
|
382
382
|
end
|
383
383
|
end
|
384
384
|
|
385
385
|
# In tests
|
386
386
|
RSpec.describe "MCP Integration" do
|
387
387
|
include McpHelpers
|
388
|
-
|
388
|
+
|
389
389
|
it "uses MCP tools" do
|
390
390
|
mock_mcp_server("test", ["about"])
|
391
|
-
|
392
|
-
result =
|
391
|
+
|
392
|
+
result = ClaudeCode.quick_mcp_query(
|
393
393
|
"Test prompt",
|
394
394
|
server_name: "test",
|
395
395
|
server_url: "http://test.com",
|
396
396
|
tools: "about"
|
397
397
|
)
|
398
|
-
|
399
|
-
expect(result).to include(have_attributes(class:
|
398
|
+
|
399
|
+
expect(result).to include(have_attributes(class: ClaudeCode::AssistantMessage))
|
400
400
|
end
|
401
401
|
end
|
402
402
|
```
|
403
403
|
|
404
|
-
The MCP integration provides a powerful way to extend Claude's capabilities with custom tools while maintaining the same streaming performance and ergonomic API as the core SDK.
|
404
|
+
The MCP integration provides a powerful way to extend Claude's capabilities with custom tools while maintaining the same streaming performance and ergonomic API as the core SDK.
|
data/docs/streaming.md
CHANGED
@@ -12,20 +12,20 @@ All queries return lazy enumerators that stream messages in real-time, providing
|
|
12
12
|
|
13
13
|
```ruby
|
14
14
|
# All queries stream by default
|
15
|
-
|
15
|
+
ClaudeCode.query(
|
16
16
|
prompt: "Explain Ruby blocks",
|
17
17
|
options: ClaudeCodeOptions.new(max_turns: 1)
|
18
18
|
).each do |message|
|
19
19
|
case message
|
20
|
-
when
|
20
|
+
when ClaudeCode::SystemMessage
|
21
21
|
puts "🔧 System: #{message.subtype}"
|
22
|
-
when
|
22
|
+
when ClaudeCode::AssistantMessage
|
23
23
|
message.content.each do |block|
|
24
|
-
if block.is_a?(
|
24
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
25
25
|
puts "💬 #{block.text}"
|
26
26
|
end
|
27
27
|
end
|
28
|
-
when
|
28
|
+
when ClaudeCode::ResultMessage
|
29
29
|
puts "✅ Cost: $#{message.total_cost_usd}"
|
30
30
|
end
|
31
31
|
end
|
@@ -38,23 +38,23 @@ For multiple conversation turns without restarting the CLI:
|
|
38
38
|
```ruby
|
39
39
|
# Create multiple user messages
|
40
40
|
messages = [
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
ClaudeCode::JSONLHelpers.create_user_message("Hello! I need help with Ruby."),
|
42
|
+
ClaudeCode::JSONLHelpers.create_user_message("Can you explain how blocks work?"),
|
43
|
+
ClaudeCode::JSONLHelpers.create_user_message("Show me a practical example.")
|
44
44
|
]
|
45
45
|
|
46
46
|
# Process all messages in a single streaming session
|
47
|
-
|
47
|
+
ClaudeCode.stream_json_query(messages) do |message|
|
48
48
|
case message
|
49
|
-
when
|
49
|
+
when ClaudeCode::SystemMessage
|
50
50
|
puts "🔧 System: #{message.subtype}"
|
51
|
-
when
|
51
|
+
when ClaudeCode::AssistantMessage
|
52
52
|
message.content.each do |block|
|
53
|
-
if block.is_a?(
|
53
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
54
54
|
puts "💬 #{block.text}"
|
55
55
|
end
|
56
56
|
end
|
57
|
-
when
|
57
|
+
when ClaudeCode::ResultMessage
|
58
58
|
puts "✅ Completed #{message.num_turns} turns - Cost: $#{message.total_cost_usd}"
|
59
59
|
end
|
60
60
|
end
|
@@ -69,7 +69,7 @@ echo '{"type":"user","message":{"role":"user","content":[{"type":"text","text":"
|
|
69
69
|
|
70
70
|
```ruby
|
71
71
|
# Automatic pretty-printing
|
72
|
-
|
72
|
+
ClaudeCode.stream_query(
|
73
73
|
prompt: "Count from 1 to 5",
|
74
74
|
options: ClaudeCodeOptions.new(max_turns: 1)
|
75
75
|
)
|
@@ -84,19 +84,19 @@ ClaudeCodeSDK.stream_query(
|
|
84
84
|
```ruby
|
85
85
|
start_time = Time.now
|
86
86
|
|
87
|
-
|
87
|
+
ClaudeCode.stream_query(
|
88
88
|
prompt: "Explain inheritance in Ruby"
|
89
89
|
) do |message, index|
|
90
90
|
timestamp = Time.now - start_time
|
91
|
-
|
91
|
+
|
92
92
|
case message
|
93
|
-
when
|
93
|
+
when ClaudeCode::AssistantMessage
|
94
94
|
message.content.each do |block|
|
95
|
-
if block.is_a?(
|
95
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
96
96
|
puts "[#{format('%.2f', timestamp)}s] #{block.text}"
|
97
97
|
end
|
98
98
|
end
|
99
|
-
when
|
99
|
+
when ClaudeCode::ResultMessage
|
100
100
|
puts "[#{format('%.2f', timestamp)}s] 💰 $#{format('%.6f', message.total_cost_usd || 0)}"
|
101
101
|
end
|
102
102
|
end
|
@@ -107,12 +107,12 @@ end
|
|
107
107
|
Messages arrive in this typical order:
|
108
108
|
|
109
109
|
1. **SystemMessage** (`subtype: "init"`) - Session initialization with metadata
|
110
|
-
2. **AssistantMessage** - Claude's response with content blocks
|
110
|
+
2. **AssistantMessage** - Claude's response with content blocks
|
111
111
|
3. **ResultMessage** - Final statistics and cost information
|
112
112
|
|
113
113
|
### System Message (First)
|
114
114
|
```ruby
|
115
|
-
when
|
115
|
+
when ClaudeCode::SystemMessage
|
116
116
|
if message.subtype == "init"
|
117
117
|
puts "Session: #{message.data['session_id']}"
|
118
118
|
puts "Model: #{message.data['model']}"
|
@@ -123,14 +123,14 @@ when ClaudeCodeSDK::SystemMessage
|
|
123
123
|
|
124
124
|
### Assistant Message (Main Content)
|
125
125
|
```ruby
|
126
|
-
when
|
126
|
+
when ClaudeCode::AssistantMessage
|
127
127
|
message.content.each do |block|
|
128
128
|
case block
|
129
|
-
when
|
129
|
+
when ClaudeCode::TextBlock
|
130
130
|
puts "Text: #{block.text}"
|
131
|
-
when
|
131
|
+
when ClaudeCode::ToolUseBlock
|
132
132
|
puts "Tool: #{block.name} with #{block.input}"
|
133
|
-
when
|
133
|
+
when ClaudeCode::ToolResultBlock
|
134
134
|
puts "Result: #{block.content}"
|
135
135
|
end
|
136
136
|
end
|
@@ -138,9 +138,9 @@ when ClaudeCodeSDK::AssistantMessage
|
|
138
138
|
|
139
139
|
### Result Message (Last)
|
140
140
|
```ruby
|
141
|
-
when
|
141
|
+
when ClaudeCode::ResultMessage
|
142
142
|
puts "Duration: #{message.duration_ms}ms"
|
143
|
-
puts "API Time: #{message.duration_api_ms}ms"
|
143
|
+
puts "API Time: #{message.duration_api_ms}ms"
|
144
144
|
puts "Turns: #{message.num_turns}"
|
145
145
|
puts "Cost: $#{message.total_cost_usd}"
|
146
146
|
puts "Session: #{message.session_id}"
|
@@ -152,22 +152,22 @@ end
|
|
152
152
|
MCP tool calls also stream in real-time:
|
153
153
|
|
154
154
|
```ruby
|
155
|
-
|
155
|
+
ClaudeCode.quick_mcp_query(
|
156
156
|
"Use the about tool",
|
157
157
|
server_name: "ninja",
|
158
158
|
server_url: "https://mcp-creator-ninja-v1-4-0.mcp.soy/",
|
159
159
|
tools: "about"
|
160
160
|
).each do |message|
|
161
161
|
case message
|
162
|
-
when
|
162
|
+
when ClaudeCode::AssistantMessage
|
163
163
|
message.content.each do |block|
|
164
164
|
case block
|
165
|
-
when
|
165
|
+
when ClaudeCode::TextBlock
|
166
166
|
puts "📝 #{block.text}"
|
167
|
-
when
|
167
|
+
when ClaudeCode::ToolUseBlock
|
168
168
|
puts "🔧 Using: #{block.name}"
|
169
169
|
puts "📥 Input: #{block.input}"
|
170
|
-
when
|
170
|
+
when ClaudeCode::ToolResultBlock
|
171
171
|
puts "📤 Result: #{block.content}"
|
172
172
|
end
|
173
173
|
end
|
@@ -182,18 +182,18 @@ end
|
|
182
182
|
message_count = 0
|
183
183
|
total_text_length = 0
|
184
184
|
|
185
|
-
|
185
|
+
ClaudeCode.query(prompt: "Write a long story").each do |message|
|
186
186
|
message_count += 1
|
187
|
-
|
188
|
-
if message.is_a?(
|
187
|
+
|
188
|
+
if message.is_a?(ClaudeCode::AssistantMessage)
|
189
189
|
message.content.each do |block|
|
190
|
-
if block.is_a?(
|
190
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
191
191
|
total_text_length += block.text.length
|
192
192
|
puts "Progress: #{message_count} messages, #{total_text_length} characters"
|
193
193
|
end
|
194
194
|
end
|
195
195
|
end
|
196
|
-
|
196
|
+
|
197
197
|
# Early termination if needed
|
198
198
|
break if total_text_length > 10000
|
199
199
|
end
|
@@ -202,18 +202,18 @@ end
|
|
202
202
|
### Error Handling During Streaming
|
203
203
|
```ruby
|
204
204
|
begin
|
205
|
-
|
205
|
+
ClaudeCode.stream_query(prompt: "Complex operation") do |message, index|
|
206
206
|
case message
|
207
|
-
when
|
207
|
+
when ClaudeCode::ResultMessage
|
208
208
|
if message.is_error
|
209
209
|
puts "❌ Error detected: #{message.subtype}"
|
210
210
|
# Handle error immediately
|
211
211
|
end
|
212
212
|
end
|
213
213
|
end
|
214
|
-
rescue
|
214
|
+
rescue ClaudeCode::ProcessError => e
|
215
215
|
puts "Process failed: #{e.message}"
|
216
|
-
rescue
|
216
|
+
rescue ClaudeCode::CLIJSONDecodeError => e
|
217
217
|
puts "JSON parsing failed: #{e.message}"
|
218
218
|
end
|
219
219
|
```
|
@@ -222,19 +222,19 @@ end
|
|
222
222
|
```ruby
|
223
223
|
tool_calls = []
|
224
224
|
|
225
|
-
|
225
|
+
ClaudeCode.query(
|
226
226
|
prompt: "Analyze this codebase using available tools",
|
227
227
|
options: ClaudeCodeOptions.new(
|
228
228
|
allowed_tools: ["Read", "Bash", "Grep"],
|
229
229
|
max_turns: 5
|
230
230
|
)
|
231
231
|
).each do |message|
|
232
|
-
if message.is_a?(
|
232
|
+
if message.is_a?(ClaudeCode::AssistantMessage)
|
233
233
|
message.content.each do |block|
|
234
|
-
if block.is_a?(
|
234
|
+
if block.is_a?(ClaudeCode::ToolUseBlock)
|
235
235
|
tool_calls << { name: block.name, input: block.input, time: Time.now }
|
236
236
|
puts "🔧 Tool #{tool_calls.length}: #{block.name}"
|
237
|
-
|
237
|
+
|
238
238
|
# React to specific tools
|
239
239
|
case block.name
|
240
240
|
when "Bash"
|
@@ -255,13 +255,13 @@ puts "Total tools used: #{tool_calls.length}"
|
|
255
255
|
# Process large responses without storing everything in memory
|
256
256
|
text_chunks = []
|
257
257
|
|
258
|
-
|
259
|
-
if message.is_a?(
|
258
|
+
ClaudeCode.query(prompt: "Generate a very long document").each do |message|
|
259
|
+
if message.is_a?(ClaudeCode::AssistantMessage)
|
260
260
|
message.content.each do |block|
|
261
|
-
if block.is_a?(
|
261
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
262
262
|
# Process each chunk immediately
|
263
263
|
process_text_chunk(block.text)
|
264
|
-
|
264
|
+
|
265
265
|
# Only keep recent chunks in memory
|
266
266
|
text_chunks << block.text
|
267
267
|
text_chunks.shift if text_chunks.length > 10
|
@@ -274,7 +274,7 @@ end
|
|
274
274
|
## Performance Benefits
|
275
275
|
|
276
276
|
- **Memory Efficient**: No need to collect all messages before processing
|
277
|
-
- **Responsive UI**: Immediate feedback for long-running operations
|
277
|
+
- **Responsive UI**: Immediate feedback for long-running operations
|
278
278
|
- **Early Termination**: Stop processing when you have enough information
|
279
279
|
- **Real-time Monitoring**: Watch tool calls and results as they happen
|
280
280
|
- **Progress Tracking**: Monitor complex multi-step operations
|
@@ -285,7 +285,7 @@ For Rails applications, combine streaming with ActionCable for real-time WebSock
|
|
285
285
|
|
286
286
|
```ruby
|
287
287
|
# In a Sidekiq job
|
288
|
-
|
288
|
+
ClaudeCode.query(prompt: prompt, options: options).each do |message|
|
289
289
|
ActionCable.server.broadcast("claude_#{user_id}", {
|
290
290
|
type: 'claude_message',
|
291
291
|
data: serialize_message(message),
|
@@ -306,11 +306,11 @@ require_relative 'examples/irb_helpers'
|
|
306
306
|
# Auto-formatted streaming
|
307
307
|
auto_stream("Count to 5")
|
308
308
|
|
309
|
-
# Streaming with timestamps
|
309
|
+
# Streaming with timestamps
|
310
310
|
stream_claude("What is Ruby?")
|
311
311
|
|
312
312
|
# MCP streaming
|
313
313
|
ninja_test("Tell me about yourself")
|
314
314
|
```
|
315
315
|
|
316
|
-
The streaming support makes the Ruby SDK perfect for building responsive, interactive applications that provide immediate feedback to users.
|
316
|
+
The streaming support makes the Ruby SDK perfect for building responsive, interactive applications that provide immediate feedback to users.
|