claude_code 0.0.14
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 +7 -0
- data/.rspec +3 -0
- data/.rspec_status +114 -0
- data/.rubocop.yml +51 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +37 -0
- data/LICENSE +21 -0
- data/README.md +288 -0
- data/Rakefile +32 -0
- data/USAGE_EXAMPLES.md +428 -0
- data/claude_code.gemspec +47 -0
- data/docs/README.md +254 -0
- data/docs/mcp_integration.md +404 -0
- data/docs/streaming.md +316 -0
- data/examples/authentication_examples.rb +133 -0
- data/examples/basic_usage.rb +73 -0
- data/examples/conversation_resuming.rb +96 -0
- data/examples/irb_helpers.rb +168 -0
- data/examples/jsonl_cli_equivalent.rb +108 -0
- data/examples/mcp_examples.rb +166 -0
- data/examples/model_examples.rb +111 -0
- data/examples/quick_start.rb +75 -0
- data/examples/rails_sidekiq_example.rb +336 -0
- data/examples/streaming_examples.rb +195 -0
- data/examples/streaming_json_input.rb +171 -0
- data/hello.txt +1 -0
- data/lib/claude_code/client.rb +437 -0
- data/lib/claude_code/errors.rb +48 -0
- data/lib/claude_code/types.rb +237 -0
- data/lib/claude_code/version.rb +5 -0
- data/lib/claude_code.rb +265 -0
- metadata +219 -0
data/docs/streaming.md
ADDED
@@ -0,0 +1,316 @@
|
|
1
|
+
# Streaming Support
|
2
|
+
|
3
|
+
The Ruby Claude Code SDK provides **real-time streaming** of messages as they arrive from the Claude CLI, enabling responsive user experiences and efficient processing of long-running operations.
|
4
|
+
|
5
|
+
## Overview
|
6
|
+
|
7
|
+
All queries return lazy enumerators that stream messages in real-time, providing immediate feedback and lower memory usage compared to collecting all messages before processing.
|
8
|
+
|
9
|
+
## Streaming Methods
|
10
|
+
|
11
|
+
### 1. Default Streaming (query method)
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
# All queries stream by default
|
15
|
+
ClaudeCodeSDK.query(
|
16
|
+
prompt: "Explain Ruby blocks",
|
17
|
+
options: ClaudeCodeOptions.new(max_turns: 1)
|
18
|
+
).each do |message|
|
19
|
+
case message
|
20
|
+
when ClaudeCodeSDK::SystemMessage
|
21
|
+
puts "š§ System: #{message.subtype}"
|
22
|
+
when ClaudeCodeSDK::AssistantMessage
|
23
|
+
message.content.each do |block|
|
24
|
+
if block.is_a?(ClaudeCodeSDK::TextBlock)
|
25
|
+
puts "š¬ #{block.text}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
when ClaudeCodeSDK::ResultMessage
|
29
|
+
puts "ā
Cost: $#{message.total_cost_usd}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
### 1.5. Streaming JSON Input (Multi-turn Conversations)
|
35
|
+
|
36
|
+
For multiple conversation turns without restarting the CLI:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
# Create multiple user messages
|
40
|
+
messages = [
|
41
|
+
ClaudeCodeSDK::JSONLHelpers.create_user_message("Hello! I need help with Ruby."),
|
42
|
+
ClaudeCodeSDK::JSONLHelpers.create_user_message("Can you explain how blocks work?"),
|
43
|
+
ClaudeCodeSDK::JSONLHelpers.create_user_message("Show me a practical example.")
|
44
|
+
]
|
45
|
+
|
46
|
+
# Process all messages in a single streaming session
|
47
|
+
ClaudeCodeSDK.stream_json_query(messages) do |message|
|
48
|
+
case message
|
49
|
+
when ClaudeCodeSDK::SystemMessage
|
50
|
+
puts "š§ System: #{message.subtype}"
|
51
|
+
when ClaudeCodeSDK::AssistantMessage
|
52
|
+
message.content.each do |block|
|
53
|
+
if block.is_a?(ClaudeCodeSDK::TextBlock)
|
54
|
+
puts "š¬ #{block.text}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
when ClaudeCodeSDK::ResultMessage
|
58
|
+
puts "ā
Completed #{message.num_turns} turns - Cost: $#{message.total_cost_usd}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
**Equivalent CLI command:**
|
64
|
+
```bash
|
65
|
+
echo '{"type":"user","message":{"role":"user","content":[{"type":"text","text":"Explain this code"}]}}' | claude -p --output-format=stream-json --input-format=stream-json --verbose
|
66
|
+
```
|
67
|
+
|
68
|
+
### 2. Auto-formatted Streaming
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
# Automatic pretty-printing
|
72
|
+
ClaudeCodeSDK.stream_query(
|
73
|
+
prompt: "Count from 1 to 5",
|
74
|
+
options: ClaudeCodeOptions.new(max_turns: 1)
|
75
|
+
)
|
76
|
+
# Output:
|
77
|
+
# š¬ 1 - The first number...
|
78
|
+
# š¬ 2 - The second number...
|
79
|
+
# ā
Cost: $0.002345
|
80
|
+
```
|
81
|
+
|
82
|
+
### 3. Custom Streaming with Block
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
start_time = Time.now
|
86
|
+
|
87
|
+
ClaudeCodeSDK.stream_query(
|
88
|
+
prompt: "Explain inheritance in Ruby"
|
89
|
+
) do |message, index|
|
90
|
+
timestamp = Time.now - start_time
|
91
|
+
|
92
|
+
case message
|
93
|
+
when ClaudeCodeSDK::AssistantMessage
|
94
|
+
message.content.each do |block|
|
95
|
+
if block.is_a?(ClaudeCodeSDK::TextBlock)
|
96
|
+
puts "[#{format('%.2f', timestamp)}s] #{block.text}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
when ClaudeCodeSDK::ResultMessage
|
100
|
+
puts "[#{format('%.2f', timestamp)}s] š° $#{format('%.6f', message.total_cost_usd || 0)}"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
```
|
104
|
+
|
105
|
+
## Message Flow
|
106
|
+
|
107
|
+
Messages arrive in this typical order:
|
108
|
+
|
109
|
+
1. **SystemMessage** (`subtype: "init"`) - Session initialization with metadata
|
110
|
+
2. **AssistantMessage** - Claude's response with content blocks
|
111
|
+
3. **ResultMessage** - Final statistics and cost information
|
112
|
+
|
113
|
+
### System Message (First)
|
114
|
+
```ruby
|
115
|
+
when ClaudeCodeSDK::SystemMessage
|
116
|
+
if message.subtype == "init"
|
117
|
+
puts "Session: #{message.data['session_id']}"
|
118
|
+
puts "Model: #{message.data['model']}"
|
119
|
+
puts "Tools: #{message.data['tools'].length} available"
|
120
|
+
puts "MCP Servers: #{message.data['mcp_servers'].length}"
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
### Assistant Message (Main Content)
|
125
|
+
```ruby
|
126
|
+
when ClaudeCodeSDK::AssistantMessage
|
127
|
+
message.content.each do |block|
|
128
|
+
case block
|
129
|
+
when ClaudeCodeSDK::TextBlock
|
130
|
+
puts "Text: #{block.text}"
|
131
|
+
when ClaudeCodeSDK::ToolUseBlock
|
132
|
+
puts "Tool: #{block.name} with #{block.input}"
|
133
|
+
when ClaudeCodeSDK::ToolResultBlock
|
134
|
+
puts "Result: #{block.content}"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
### Result Message (Last)
|
140
|
+
```ruby
|
141
|
+
when ClaudeCodeSDK::ResultMessage
|
142
|
+
puts "Duration: #{message.duration_ms}ms"
|
143
|
+
puts "API Time: #{message.duration_api_ms}ms"
|
144
|
+
puts "Turns: #{message.num_turns}"
|
145
|
+
puts "Cost: $#{message.total_cost_usd}"
|
146
|
+
puts "Session: #{message.session_id}"
|
147
|
+
end
|
148
|
+
```
|
149
|
+
|
150
|
+
## MCP Streaming
|
151
|
+
|
152
|
+
MCP tool calls also stream in real-time:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
ClaudeCodeSDK.quick_mcp_query(
|
156
|
+
"Use the about tool",
|
157
|
+
server_name: "ninja",
|
158
|
+
server_url: "https://mcp-creator-ninja-v1-4-0.mcp.soy/",
|
159
|
+
tools: "about"
|
160
|
+
).each do |message|
|
161
|
+
case message
|
162
|
+
when ClaudeCodeSDK::AssistantMessage
|
163
|
+
message.content.each do |block|
|
164
|
+
case block
|
165
|
+
when ClaudeCodeSDK::TextBlock
|
166
|
+
puts "š #{block.text}"
|
167
|
+
when ClaudeCodeSDK::ToolUseBlock
|
168
|
+
puts "š§ Using: #{block.name}"
|
169
|
+
puts "š„ Input: #{block.input}"
|
170
|
+
when ClaudeCodeSDK::ToolResultBlock
|
171
|
+
puts "š¤ Result: #{block.content}"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
```
|
177
|
+
|
178
|
+
## Advanced Streaming Patterns
|
179
|
+
|
180
|
+
### Progress Tracking
|
181
|
+
```ruby
|
182
|
+
message_count = 0
|
183
|
+
total_text_length = 0
|
184
|
+
|
185
|
+
ClaudeCodeSDK.query(prompt: "Write a long story").each do |message|
|
186
|
+
message_count += 1
|
187
|
+
|
188
|
+
if message.is_a?(ClaudeCodeSDK::AssistantMessage)
|
189
|
+
message.content.each do |block|
|
190
|
+
if block.is_a?(ClaudeCodeSDK::TextBlock)
|
191
|
+
total_text_length += block.text.length
|
192
|
+
puts "Progress: #{message_count} messages, #{total_text_length} characters"
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Early termination if needed
|
198
|
+
break if total_text_length > 10000
|
199
|
+
end
|
200
|
+
```
|
201
|
+
|
202
|
+
### Error Handling During Streaming
|
203
|
+
```ruby
|
204
|
+
begin
|
205
|
+
ClaudeCodeSDK.stream_query(prompt: "Complex operation") do |message, index|
|
206
|
+
case message
|
207
|
+
when ClaudeCodeSDK::ResultMessage
|
208
|
+
if message.is_error
|
209
|
+
puts "ā Error detected: #{message.subtype}"
|
210
|
+
# Handle error immediately
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
rescue ClaudeCodeSDK::ProcessError => e
|
215
|
+
puts "Process failed: #{e.message}"
|
216
|
+
rescue ClaudeCodeSDK::CLIJSONDecodeError => e
|
217
|
+
puts "JSON parsing failed: #{e.message}"
|
218
|
+
end
|
219
|
+
```
|
220
|
+
|
221
|
+
### Tool Call Monitoring
|
222
|
+
```ruby
|
223
|
+
tool_calls = []
|
224
|
+
|
225
|
+
ClaudeCodeSDK.query(
|
226
|
+
prompt: "Analyze this codebase using available tools",
|
227
|
+
options: ClaudeCodeOptions.new(
|
228
|
+
allowed_tools: ["Read", "Bash", "Grep"],
|
229
|
+
max_turns: 5
|
230
|
+
)
|
231
|
+
).each do |message|
|
232
|
+
if message.is_a?(ClaudeCodeSDK::AssistantMessage)
|
233
|
+
message.content.each do |block|
|
234
|
+
if block.is_a?(ClaudeCodeSDK::ToolUseBlock)
|
235
|
+
tool_calls << { name: block.name, input: block.input, time: Time.now }
|
236
|
+
puts "š§ Tool #{tool_calls.length}: #{block.name}"
|
237
|
+
|
238
|
+
# React to specific tools
|
239
|
+
case block.name
|
240
|
+
when "Bash"
|
241
|
+
puts " Running command: #{block.input['command']}"
|
242
|
+
when "Read"
|
243
|
+
puts " Reading file: #{block.input['file_path']}"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
puts "Total tools used: #{tool_calls.length}"
|
251
|
+
```
|
252
|
+
|
253
|
+
### Memory-Efficient Processing
|
254
|
+
```ruby
|
255
|
+
# Process large responses without storing everything in memory
|
256
|
+
text_chunks = []
|
257
|
+
|
258
|
+
ClaudeCodeSDK.query(prompt: "Generate a very long document").each do |message|
|
259
|
+
if message.is_a?(ClaudeCodeSDK::AssistantMessage)
|
260
|
+
message.content.each do |block|
|
261
|
+
if block.is_a?(ClaudeCodeSDK::TextBlock)
|
262
|
+
# Process each chunk immediately
|
263
|
+
process_text_chunk(block.text)
|
264
|
+
|
265
|
+
# Only keep recent chunks in memory
|
266
|
+
text_chunks << block.text
|
267
|
+
text_chunks.shift if text_chunks.length > 10
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
```
|
273
|
+
|
274
|
+
## Performance Benefits
|
275
|
+
|
276
|
+
- **Memory Efficient**: No need to collect all messages before processing
|
277
|
+
- **Responsive UI**: Immediate feedback for long-running operations
|
278
|
+
- **Early Termination**: Stop processing when you have enough information
|
279
|
+
- **Real-time Monitoring**: Watch tool calls and results as they happen
|
280
|
+
- **Progress Tracking**: Monitor complex multi-step operations
|
281
|
+
|
282
|
+
## Rails Integration
|
283
|
+
|
284
|
+
For Rails applications, combine streaming with ActionCable for real-time WebSocket updates:
|
285
|
+
|
286
|
+
```ruby
|
287
|
+
# In a Sidekiq job
|
288
|
+
ClaudeCodeSDK.query(prompt: prompt, options: options).each do |message|
|
289
|
+
ActionCable.server.broadcast("claude_#{user_id}", {
|
290
|
+
type: 'claude_message',
|
291
|
+
data: serialize_message(message),
|
292
|
+
timestamp: Time.current
|
293
|
+
})
|
294
|
+
end
|
295
|
+
```
|
296
|
+
|
297
|
+
See `examples/rails_sidekiq_example.rb` for a complete Rails + Sidekiq + ActionCable integration example.
|
298
|
+
|
299
|
+
## IRB Helpers
|
300
|
+
|
301
|
+
For quick testing in IRB:
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
require_relative 'examples/irb_helpers'
|
305
|
+
|
306
|
+
# Auto-formatted streaming
|
307
|
+
auto_stream("Count to 5")
|
308
|
+
|
309
|
+
# Streaming with timestamps
|
310
|
+
stream_claude("What is Ruby?")
|
311
|
+
|
312
|
+
# MCP streaming
|
313
|
+
ninja_test("Tell me about yourself")
|
314
|
+
```
|
315
|
+
|
316
|
+
The streaming support makes the Ruby SDK perfect for building responsive, interactive applications that provide immediate feedback to users.
|
@@ -0,0 +1,133 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../lib/claude_code'
|
5
|
+
|
6
|
+
# Example: Different authentication methods for Claude Code SDK
|
7
|
+
|
8
|
+
puts "=== Authentication Examples ==="
|
9
|
+
|
10
|
+
# Method 1: Using ANTHROPIC_API_KEY environment variable
|
11
|
+
puts "\n1. Using ANTHROPIC_API_KEY environment variable"
|
12
|
+
puts "Set your API key:"
|
13
|
+
puts "export ANTHROPIC_API_KEY='your-api-key-here'"
|
14
|
+
|
15
|
+
if ENV['ANTHROPIC_API_KEY']
|
16
|
+
puts "ā
ANTHROPIC_API_KEY is set"
|
17
|
+
|
18
|
+
# Test basic query with API key authentication
|
19
|
+
puts "\nTesting with API key authentication..."
|
20
|
+
ClaudeCode.query("What is 2 + 2?") do |message|
|
21
|
+
case message
|
22
|
+
when ClaudeCode::AssistantMessage
|
23
|
+
message.content.each do |block|
|
24
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
25
|
+
puts "š¤ #{block.text}"
|
26
|
+
break
|
27
|
+
end
|
28
|
+
end
|
29
|
+
when ClaudeCode::ResultMessage
|
30
|
+
puts "š° Cost: $#{format('%.6f', message.total_cost_usd || 0)}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
else
|
34
|
+
puts "ā ANTHROPIC_API_KEY not set"
|
35
|
+
puts "Please set your API key before running this example"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Method 2: Amazon Bedrock authentication
|
39
|
+
puts "\n2. Using Amazon Bedrock"
|
40
|
+
puts "Set environment variables:"
|
41
|
+
puts "export CLAUDE_CODE_USE_BEDROCK=1"
|
42
|
+
puts "export AWS_ACCESS_KEY_ID='your-aws-access-key'"
|
43
|
+
puts "export AWS_SECRET_ACCESS_KEY='your-aws-secret-key'"
|
44
|
+
puts "export AWS_REGION='us-west-2'"
|
45
|
+
|
46
|
+
if ENV['CLAUDE_CODE_USE_BEDROCK']
|
47
|
+
puts "ā
Amazon Bedrock authentication enabled"
|
48
|
+
|
49
|
+
# Test with Bedrock
|
50
|
+
puts "\nTesting with Bedrock authentication..."
|
51
|
+
begin
|
52
|
+
ClaudeCode.query("Hello from Bedrock!") do |message|
|
53
|
+
case message
|
54
|
+
when ClaudeCode::AssistantMessage
|
55
|
+
message.content.each do |block|
|
56
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
57
|
+
puts "š¤ #{block.text}"
|
58
|
+
break
|
59
|
+
end
|
60
|
+
end
|
61
|
+
when ClaudeCode::ResultMessage
|
62
|
+
puts "š° Cost: $#{format('%.6f', message.total_cost_usd || 0)}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
rescue ClaudeCode::CLIConnectionError => e
|
66
|
+
puts "ā Bedrock connection failed: #{e.message}"
|
67
|
+
end
|
68
|
+
else
|
69
|
+
puts "ā Amazon Bedrock not configured"
|
70
|
+
end
|
71
|
+
|
72
|
+
# Method 3: Google Vertex AI authentication
|
73
|
+
puts "\n3. Using Google Vertex AI"
|
74
|
+
puts "Set environment variables:"
|
75
|
+
puts "export CLAUDE_CODE_USE_VERTEX=1"
|
76
|
+
puts "export GOOGLE_APPLICATION_CREDENTIALS='path/to/service-account.json'"
|
77
|
+
puts "export GOOGLE_CLOUD_PROJECT='your-project-id'"
|
78
|
+
|
79
|
+
if ENV['CLAUDE_CODE_USE_VERTEX']
|
80
|
+
puts "ā
Google Vertex AI authentication enabled"
|
81
|
+
|
82
|
+
# Test with Vertex AI
|
83
|
+
puts "\nTesting with Vertex AI authentication..."
|
84
|
+
begin
|
85
|
+
ClaudeCode.query("Hello from Vertex AI!") do |message|
|
86
|
+
case message
|
87
|
+
when ClaudeCode::AssistantMessage
|
88
|
+
message.content.each do |block|
|
89
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
90
|
+
puts "š¤ #{block.text}"
|
91
|
+
break
|
92
|
+
end
|
93
|
+
end
|
94
|
+
when ClaudeCode::ResultMessage
|
95
|
+
puts "š° Cost: $#{format('%.6f', message.total_cost_usd || 0)}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
rescue ClaudeCode::CLIConnectionError => e
|
99
|
+
puts "ā Vertex AI connection failed: #{e.message}"
|
100
|
+
end
|
101
|
+
else
|
102
|
+
puts "ā Google Vertex AI not configured"
|
103
|
+
end
|
104
|
+
|
105
|
+
# Method 4: Programmatically setting environment variables
|
106
|
+
puts "\n4. Setting authentication programmatically"
|
107
|
+
puts "You can also set authentication in your Ruby code:"
|
108
|
+
|
109
|
+
puts <<~RUBY
|
110
|
+
# Set API key programmatically (not recommended for production)
|
111
|
+
ENV['ANTHROPIC_API_KEY'] = 'your-api-key-here'
|
112
|
+
|
113
|
+
# Or for Amazon Bedrock
|
114
|
+
ENV['CLAUDE_CODE_USE_BEDROCK'] = '1'
|
115
|
+
ENV['AWS_ACCESS_KEY_ID'] = 'your-access-key'
|
116
|
+
ENV['AWS_SECRET_ACCESS_KEY'] = 'your-secret-key'
|
117
|
+
ENV['AWS_REGION'] = 'us-west-2'
|
118
|
+
|
119
|
+
# Or for Google Vertex AI
|
120
|
+
ENV['CLAUDE_CODE_USE_VERTEX'] = '1'
|
121
|
+
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = 'path/to/service-account.json'
|
122
|
+
ENV['GOOGLE_CLOUD_PROJECT'] = 'your-project-id'
|
123
|
+
RUBY
|
124
|
+
|
125
|
+
puts "\nā ļø Security Note:"
|
126
|
+
puts "For production applications, use secure methods to store credentials:"
|
127
|
+
puts "- Environment variables"
|
128
|
+
puts "- AWS IAM roles"
|
129
|
+
puts "- Google Cloud service accounts"
|
130
|
+
puts "- Secret management services"
|
131
|
+
puts "- Never commit API keys to version control"
|
132
|
+
|
133
|
+
puts "\nā
Authentication examples completed!"
|
@@ -0,0 +1,73 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Basic usage examples for Ruby Claude Code SDK
|
3
|
+
|
4
|
+
require_relative '../lib/claude_code'
|
5
|
+
|
6
|
+
def test_basic_query
|
7
|
+
puts "=== Testing Basic Query ==="
|
8
|
+
|
9
|
+
# Use the specific Claude path for your system
|
10
|
+
claude_path = "/Users/admin/.claude/local/claude"
|
11
|
+
|
12
|
+
begin
|
13
|
+
ClaudeCode.query(
|
14
|
+
prompt: "What is 2 + 2? Answer in one sentence.",
|
15
|
+
cli_path: claude_path
|
16
|
+
).each do |message|
|
17
|
+
puts "Message type: #{message.class}"
|
18
|
+
|
19
|
+
if message.is_a?(ClaudeCode::AssistantMessage)
|
20
|
+
message.content.each do |block|
|
21
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
22
|
+
puts "Claude: #{block.text}"
|
23
|
+
elsif block.is_a?(ClaudeCode::ToolUseBlock)
|
24
|
+
puts "Tool Use: #{block.name} with input #{block.input}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
elsif message.is_a?(ClaudeCode::ResultMessage)
|
28
|
+
puts "Result: #{message.result}"
|
29
|
+
puts "Cost: $#{message.total_cost_usd}" if message.total_cost_usd
|
30
|
+
else
|
31
|
+
puts "Other message: #{message.inspect}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
rescue => e
|
35
|
+
puts "Error: #{e.class} - #{e.message}"
|
36
|
+
puts e.backtrace.first(5)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_with_options
|
41
|
+
puts "\n=== Testing with Options ==="
|
42
|
+
|
43
|
+
claude_path = "/Users/admin/.claude/local/claude"
|
44
|
+
|
45
|
+
options = ClaudeCode::ClaudeCodeOptions.new(
|
46
|
+
max_turns: 1,
|
47
|
+
system_prompt: "You are a helpful assistant. Be very concise."
|
48
|
+
)
|
49
|
+
|
50
|
+
begin
|
51
|
+
ClaudeCode.query(
|
52
|
+
prompt: "Explain Ruby in one sentence.",
|
53
|
+
options: options,
|
54
|
+
cli_path: claude_path
|
55
|
+
).each do |message|
|
56
|
+
if message.is_a?(ClaudeCode::AssistantMessage)
|
57
|
+
message.content.each do |block|
|
58
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
59
|
+
puts "Claude: #{block.text}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
rescue => e
|
65
|
+
puts "Error: #{e.class} - #{e.message}"
|
66
|
+
puts e.backtrace.first(5)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
if __FILE__ == $0
|
71
|
+
test_basic_query
|
72
|
+
test_with_options
|
73
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../lib/claude_code'
|
5
|
+
|
6
|
+
# Example: Conversation resuming and continuation
|
7
|
+
|
8
|
+
puts "=== Conversation Resuming Example ==="
|
9
|
+
|
10
|
+
# Set your API key (you can also set this as an environment variable)
|
11
|
+
# ENV['ANTHROPIC_API_KEY'] = 'your-api-key-here'
|
12
|
+
|
13
|
+
# Start an initial conversation
|
14
|
+
puts "\n1. Starting initial conversation..."
|
15
|
+
session_id = nil
|
16
|
+
|
17
|
+
ClaudeCode.query("Hello! My name is John and I'm learning Ruby programming.") do |message|
|
18
|
+
case message
|
19
|
+
when ClaudeCode::AssistantMessage
|
20
|
+
message.content.each do |block|
|
21
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
22
|
+
puts "š¤ #{block.text}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
when ClaudeCode::ResultMessage
|
26
|
+
session_id = message.session_id
|
27
|
+
puts "\nš Session ID: #{session_id}"
|
28
|
+
puts "š° Cost: $#{format('%.6f', message.total_cost_usd || 0)}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Continue the most recent conversation (without session ID)
|
33
|
+
puts "\n2. Continuing the conversation..."
|
34
|
+
ClaudeCode.continue_conversation("What are some good Ruby resources for beginners?") do |message|
|
35
|
+
case message
|
36
|
+
when ClaudeCode::AssistantMessage
|
37
|
+
message.content.each do |block|
|
38
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
39
|
+
puts "š¤ #{block.text}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
when ClaudeCode::ResultMessage
|
43
|
+
puts "\nš° Cost: $#{format('%.6f', message.total_cost_usd || 0)}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Resume a specific conversation by session ID
|
48
|
+
if session_id
|
49
|
+
puts "\n3. Resuming specific session: #{session_id}"
|
50
|
+
ClaudeCode.resume_conversation(
|
51
|
+
session_id,
|
52
|
+
"Can you recommend a specific Ruby book?"
|
53
|
+
) do |message|
|
54
|
+
case message
|
55
|
+
when ClaudeCode::AssistantMessage
|
56
|
+
message.content.each do |block|
|
57
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
58
|
+
puts "š¤ #{block.text}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
when ClaudeCode::ResultMessage
|
62
|
+
puts "\nš° Cost: $#{format('%.6f', message.total_cost_usd || 0)}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Continue with additional options
|
68
|
+
puts "\n4. Continuing with custom options..."
|
69
|
+
options = ClaudeCode::ClaudeCodeOptions.new(
|
70
|
+
max_turns: 2,
|
71
|
+
system_prompt: "You are a Ruby programming tutor. Keep responses concise and practical.",
|
72
|
+
model: "claude-3-haiku"
|
73
|
+
)
|
74
|
+
|
75
|
+
ClaudeCode.continue_conversation(
|
76
|
+
"Show me a simple Ruby class example",
|
77
|
+
options: options
|
78
|
+
) do |message|
|
79
|
+
case message
|
80
|
+
when ClaudeCode::AssistantMessage
|
81
|
+
message.content.each do |block|
|
82
|
+
if block.is_a?(ClaudeCode::TextBlock)
|
83
|
+
puts "š¤ #{block.text}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
when ClaudeCode::ResultMessage
|
87
|
+
puts "\nš° Cost: $#{format('%.6f', message.total_cost_usd || 0)}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
puts "\nā
Conversation resuming examples completed!"
|
92
|
+
puts "\nNotes:"
|
93
|
+
puts "- Set ANTHROPIC_API_KEY environment variable for authentication"
|
94
|
+
puts "- Session IDs are returned in ResultMessage.session_id"
|
95
|
+
puts "- Use continue_conversation() to continue the most recent session"
|
96
|
+
puts "- Use resume_conversation(session_id) to resume a specific session"
|