Class: Ace::LLM::Providers::CLI::ClaudeCodeClient

Inherits:
Organisms::BaseClient
  • Object
show all
Includes:
CliArgsSupport
Defined in:
lib/ace/llm/providers/cli/claude_code_client.rb

Overview

Client for interacting with Claude Code via the Claude CLI Provides access to Claude Code models through subprocess execution

Constant Summary collapse

API_BASE_URL =

Not used for CLI interaction but required by BaseClient

"https://claude.ai"
DEFAULT_GENERATION_CONFIG =
{}.freeze
DEFAULT_MODEL =

Default model (can be overridden by config)

"claude-sonnet-4-0"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model: nil, **options) ⇒ ClaudeCodeClient

Returns a new instance of ClaudeCodeClient.



34
35
36
37
38
39
40
# File 'lib/ace/llm/providers/cli/claude_code_client.rb', line 34

def initialize(model: nil, **options)
  @model = model || DEFAULT_MODEL
  # Skip normal BaseClient initialization that requires API key
  @options = options
  @generation_config = options[:generation_config] || {}
  @skill_name_reader = Molecules::SkillNameReader.new
end

Class Method Details

.provider_nameObject

Provider registration - auto-registers as “claude”



27
28
29
# File 'lib/ace/llm/providers/cli/claude_code_client.rb', line 27

def self.provider_name
  "claude"
end

Instance Method Details

#build_interactive_invocation(messages, **options) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/ace/llm/providers/cli/claude_code_client.rb', line 91

def build_interactive_invocation(messages, **options)
  validate_claude_availability!

  prompt = format_messages_as_prompt(messages)
  subprocess_env = options[:subprocess_env]
  working_dir = Atoms::ExecutionContext.resolve_working_dir(
    working_dir: options[:working_dir],
    subprocess_env: subprocess_env
  )
  prompt = rewrite_skill_commands(prompt, working_dir: working_dir)

  cmd = build_claude_interactive_command(prompt, options)
  env = {"CLAUDECODE" => nil}
  env.merge!(subprocess_env) if subprocess_env
  {
    command: cmd,
    env: env,
    working_dir: working_dir,
    prompt: prompt
  }
end

#generate(messages, **options) ⇒ Hash

Generate a response from the LLM

Parameters:

  • messages (Array<Hash>)

    Conversation messages

  • options (Hash)

    Generation options

Returns:

  • (Hash)

    Response with text and metadata



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/ace/llm/providers/cli/claude_code_client.rb', line 51

def generate(messages, **options)
  validate_claude_availability!

  # Convert messages to prompt format
  prompt = format_messages_as_prompt(messages)

  cmd = build_claude_command(options)
  subprocess_env = options.delete(:subprocess_env)
  working_dir = Atoms::ExecutionContext.resolve_working_dir(
    working_dir: options[:working_dir],
    subprocess_env: subprocess_env
  )
  stdout, stderr, status = execute_claude_command(
    cmd,
    prompt,
    subprocess_env: subprocess_env,
    working_dir: working_dir,
    subprocess_command_prefix: options[:subprocess_command_prefix]
  )

  parse_claude_response(stdout, stderr, status, prompt, options)
rescue => e
  handle_claude_error(e)
end

#interactive_supported?Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/ace/llm/providers/cli/claude_code_client.rb', line 87

def interactive_supported?
  true
end

#list_modelsObject

List available Claude Code models



77
78
79
80
81
82
83
84
85
# File 'lib/ace/llm/providers/cli/claude_code_client.rb', line 77

def list_models
  # Return models based on what the CLI supports
  # This is a simplified list - actual models come from YAML config
  [
    {id: "claude-opus-4-1", name: "Claude Opus 4.1", description: "Most capable model", context_size: 200_000},
    {id: "claude-sonnet-4-0", name: "Claude Sonnet 4.0", description: "Balanced model", context_size: 200_000},
    {id: "claude-3-5-haiku-latest", name: "Claude Haiku 3.5", description: "Fast model", context_size: 200_000}
  ]
end

#needs_credentials?Boolean

Override to indicate this client doesn’t need API credentials

Returns:

  • (Boolean)


43
44
45
# File 'lib/ace/llm/providers/cli/claude_code_client.rb', line 43

def needs_credentials?
  false
end