forked from ya-luotao/claude-agent-sdk-ruby
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhooks_example.rb
More file actions
100 lines (86 loc) · 2.78 KB
/
Copy pathhooks_example.rb
File metadata and controls
100 lines (86 loc) · 2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'bundler/setup'
require 'claude_agent_sdk'
require 'async'
# Example: Using hooks to control tool execution
Async do
# Define a hook that blocks dangerous bash commands
bash_hook = lambda do |input, _tool_use_id, _context|
return {} unless input.respond_to?(:tool_name) && input.tool_name == 'Bash'
tool_input = input.tool_input || {}
command = tool_input[:command] || tool_input['command'] || ''
block_patterns = ['rm -rf', 'foo.sh']
block_patterns.each do |pattern|
if command.include?(pattern)
return {
hookSpecificOutput: {
hookEventName: 'PreToolUse',
permissionDecision: 'deny',
permissionDecisionReason: "Command contains forbidden pattern: #{pattern}"
}
}
end
end
{} # Allow if no patterns match
end
# Create options with hook
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
allowed_tools: ['Bash'],
hooks: {
'PreToolUse' => [
ClaudeAgentSDK::HookMatcher.new(
matcher: 'Bash',
hooks: [bash_hook]
)
]
}
)
client = ClaudeAgentSDK::Client.new(options: options)
begin
puts "Connecting with hook-enabled client..."
client.connect
puts "Connected!\n"
# Test 1: Command with forbidden pattern (will be blocked)
puts "=== Test 1: Forbidden Command ==="
puts "Asking Claude to run: ./foo.sh --help"
client.query("Run the bash command: ./foo.sh --help")
client.receive_response do |msg|
if msg.is_a?(ClaudeAgentSDK::AssistantMessage)
msg.content.each do |block|
case block
when ClaudeAgentSDK::TextBlock
puts "Claude: #{block.text}"
when ClaudeAgentSDK::ToolUseBlock
puts "Tool attempted: #{block.name}"
end
end
elsif msg.is_a?(ClaudeAgentSDK::SystemMessage)
puts "System: #{msg.subtype} - #{msg.data[:message]}" if msg.data[:message]
end
end
puts "\n#{'=' * 50}\n"
# Test 2: Safe command (should work)
puts "=== Test 2: Safe Command ==="
puts "Asking Claude to run: echo 'Hello from hooks example!'"
client.query("Run the bash command: echo 'Hello from hooks example!'")
client.receive_response do |msg|
if msg.is_a?(ClaudeAgentSDK::AssistantMessage)
msg.content.each do |block|
case block
when ClaudeAgentSDK::TextBlock
puts "Claude: #{block.text}"
when ClaudeAgentSDK::ToolUseBlock
puts "Tool used: #{block.name}"
end
end
elsif msg.is_a?(ClaudeAgentSDK::ResultMessage)
puts "\nCompleted successfully!"
end
end
ensure
puts "\nDisconnecting..."
client.disconnect
puts "Done!"
end
end.wait