A Ruby framework for building AI agents powered by Claude Code. This gem provides a simple, event-driven interface to interact with Claude through the Claude Code CLI.
Before using RubyAgent, you need to install Claude Code CLI:
curl -fsSL https://claude.ai/install.sh | bashirm https://claude.ai/install.ps1 | iexFor more information, visit the Claude Code documentation.
gem install ruby_agentOr add to your Gemfile:
gem 'ruby_agent'require 'ruby_agent'
agent = RubyAgent.new
agent.on_result { |e, _| agent.exit if e["subtype"] == "success" }
agent.connect { agent.ask("What is 2+2?") }That's it! Three lines to create an agent, ask Claude a question, and exit when done.
require 'ruby_agent'
agent = RubyAgent.new(
sandbox_dir: Dir.pwd,
system_prompt: "You are a helpful coding assistant",
model: "claude-sonnet-4-5-20250929",
verbose: true
)
agent.create_message_callback :assistant_text do |event, all_events|
if event["type"] == "assistant" && event.dig("message", "content", 0, "type") == "text"
event.dig("message", "content", 0, "text")
end
end
agent.on_system_init do |event, _|
puts "Session started: #{event['session_id']}"
end
agent.on_assistant_text do |text|
puts "Claude says: #{text}"
end
agent.on_result do |event, all_events|
if event["subtype"] == "success"
puts "Task completed successfully!"
agent.exit
elsif event["subtype"] == "error_occurred"
puts "Error: #{event['result']}"
agent.exit
end
end
agent.on_error do |error|
puts "Error occurred: #{error.message}"
end
agent.connect do
agent.ask("Write a simple Hello World function in Ruby", sender_name: "User")
endagent = RubyAgent.new(
session_key: "existing_session_123",
system_prompt: "You are a helpful assistant"
)
agent.connect do
agent.ask("Continue from where we left off", sender_name: "User")
endagent = RubyAgent.new(
system_prompt: "You are <%= role %> working on <%= project_name %>",
role: "a senior developer",
project_name: "RubyAgent"
)RubyAgent supports dynamic event callbacks using method_missing. You can create callbacks for any event type:
on_message(alias:on_event) - Triggered for every messageon_assistant- Triggered when Claude respondson_system_init- Triggered when a session startson_result- Triggered when a task completeson_error- Triggered when an error occurson_tool_use- Triggered when Claude uses a toolon_tool_result- Triggered when a tool returns results
You can also create custom callbacks with specific subtypes like on_system_init, on_error_timeout, etc.
Create custom message processors that filter and transform events:
agent.create_message_callback :important_messages do |message, all_messages|
if message["type"] == "assistant"
message.dig("message", "content", 0, "text")
end
end
agent.on_important_messages do |text|
puts "Important: #{text}"
endCreates a new RubyAgent instance.
Options:
sandbox_dir(String) - Working directory for the agent (default:Dir.pwd)timezone(String) - Timezone for the agent (default:"UTC")skip_permissions(Boolean) - Skip permission prompts (default:true)verbose(Boolean) - Enable verbose output (default:false)system_prompt(String) - System prompt for Claude (default:"You are a helpful assistant")model(String) - Claude model to use (default:"claude-sonnet-4-5-20250929")mcp_servers(Hash) - MCP server configuration (default:nil)session_key(String) - Resume an existing session (default:nil)- Additional keyword arguments are passed to the ERB template in
system_prompt
connect(&block)- Connect to Claude and execute the blockask(text, sender_name: "User", additional: [])- Send a message to Claudesend_system_message(text)- Send a system messageinterrupt- Interrupt Claude's current operationexit- Close the connection to Claudeon_message(&block)- Register a callback for all messageson_error(&block)- Register a callback for errors- Dynamic
on_*methods for specific event types
RubyAgent defines three error types:
RubyAgent::AgentError- Base error classRubyAgent::ConnectionError- Connection-related errorsRubyAgent::ParseError- System prompt parsing errors
begin
agent.connect do
agent.ask("Hello", sender_name: "User")
end
rescue RubyAgent::ConnectionError => e
puts "Connection failed: #{e.message}"
rescue RubyAgent::AgentError => e
puts "Agent error: #{e.message}"
end- Fork the repository: https://github.com/AllYourBot/ruby-agent
- Create a feature branch:
git checkout -b my-new-feature - Make your changes
- Run the CI suite locally to ensure everything passes:
# Run all CI tasks (linting + tests)
rake ci
# Or run tasks individually:
rake ci:test # Run test suite
rake ci:lint # Run RuboCop linter
rake ci:lint:fix # Auto-fix linting issues
rake ci:scan # Run security audit- Commit your changes:
git commit -am 'Add some feature' - Push to your fork:
git push origin my-new-feature - Create a Pull Request against the
mainbranch
The test suite includes an integration test that runs Claude Code CLI locally:
# Run all tests
rake test
# Run a specific test
ruby test/ruby_agent_test.rb --name test_simple_agent_queryNote: Tests require Claude Code CLI to be installed on your machine (see Prerequisites section).
We use RuboCop for code linting:
# Check for linting issues
rake ci:lint
# Auto-fix linting issues
rake ci:lint:fixPublishing to RubyGems happens automatically via GitHub Actions when code is merged to main. The version number is read from lib/ruby_agent/version.rb.
Before merging a PR, make sure to bump the version number appropriately:
- Patch version (0.2.1 → 0.2.2) for bug fixes
- Minor version (0.2.1 → 0.3.0) for new features
- Major version (0.2.1 → 1.0.0) for breaking changes
MIT