codex-ruby

Ruby SDK for the Codex CLI. Provides subprocess management, JSONL event parsing, and a clean API for building AI-powered applications.

Prerequisites

Codex CLI must be installed and available in your PATH.

npm install -g @openai/codex

Supported platforms: macOS, Linux.

Installation

Add to your Gemfile:

gem "codex-ruby"

Requires Ruby 3.2+.

Usage

require "codex_sdk"

client = CodexSDK::Client.new(
  api_key: "your-api-key",      # or set CODEX_API_KEY env var
  base_url: "https://api.openai.com/v1"  # optional
)

# Start a new thread
thread = client.start_thread(
  model: "o4-mini",
  sandbox_mode: "read-only",
  working_directory: "/path/to/project"
)

# Blocking run - returns a Turn with all items
turn = thread.run("Explain this codebase")
puts turn.final_response
puts "Tokens used: #{turn.usage.input_tokens} in, #{turn.usage.output_tokens} out"
puts "Final context: #{turn.context_snapshot.context_tokens} / #{turn.context_snapshot.model_context_window}"

# Streaming run - yields events as they arrive
thread.run_streamed("Fix the failing tests") do |event|
  case event
  when CodexSDK::Events::ItemCompleted
    case event.item
    when CodexSDK::Items::AgentMessage
      puts event.item.text
    when CodexSDK::Items::CommandExecution
      puts "Ran: #{event.item.command} (exit #{event.item.exit_code})"
    when CodexSDK::Items::FileChange
      event.item.changes.each { |c| puts "#{c[:kind]}: #{c[:path]}" }
    end
  when CodexSDK::Events::TurnCompleted
    puts "Done! Used #{event.usage.output_tokens} output tokens"
  when CodexSDK::Events::TurnFailed
    puts "Error: #{event.error_message}"
  end
end

puts "Final context: #{thread.context_snapshot.context_tokens} / #{thread.context_snapshot.model_context_window}"

Resume a thread

thread = client.resume_thread("thread_abc123", model: "o4-mini")
turn = thread.run("Now add tests for the changes")

Interrupt

# From another Ruby thread
thread.interrupt

Thread options

client.start_thread(
  model: "o4-mini",
  sandbox_mode: "read-only",      # or "read-write"
  working_directory: "/path",
  approval_policy: "unless-allow-listed",
  reasoning_effort: "high",
  network_access: true,
  web_search: true,
  additional_directories: ["/other/path"],
  skip_git_repo_check: false
)

Config overrides

client = CodexSDK::Client.new(
  api_key: "key",
  config: {
    mcp_servers: {
      my_server: { url: "http://localhost:3000/mcp" }
    }
  }
)

Event types

Event Description
Events::ThreadStarted Thread created, provides thread_id
Events::TurnStarted Turn began processing
Events::TurnCompleted Turn finished, provides usage
Events::TurnFailed Turn failed, provides error_message
Events::ItemStarted Item processing started
Events::ItemUpdated Item updated with partial data
Events::ItemCompleted Item finished, provides typed item
Events::Error Stream-level error, provides message

Context snapshots

Codex CLI writes richer rollout logs under ~/.codex/sessions (or CODEX_HOME/sessions). After a run completes, Thread#run and Thread#run_streamed expose a final context_snapshot derived from the latest token_count entry in those rollout files.

snapshot = thread.context_snapshot
snapshot.context_tokens          # => current prompt/context footprint
snapshot.model_context_window    # => model max context window
snapshot.last_token_usage.total_tokens
snapshot.total_token_usage.total_tokens

This is separate from turn.completed.usage, which is still the per-turn API usage reported by the JSON event stream.

Item types

Item Fields
Items::AgentMessage id, text
Items::Reasoning id, text
Items::CommandExecution id, command, aggregated_output, exit_code, status
Items::FileChange id, changes (array of {path:, kind:}), status
Items::McpToolCall id, server, tool, arguments, result, error, status
Items::WebSearch id, query
Items::TodoList id, items (array of {text:, completed:})
Items::Error id, message

Development

bundle install
bundle exec rspec

License

MIT