Current section

Files

Jump to
claude_code lib claude_code cli.ex
Raw

lib/claude_code/cli.ex

defmodule ClaudeCode.CLI do
@moduledoc """
Handles CLI subprocess management for Claude Code.
This module is responsible for:
- Finding the claude binary
- Building command arguments from validated options
- Managing the subprocess lifecycle
"""
alias ClaudeCode.Options
@claude_binary "claude"
@required_flags ["--output-format", "stream-json", "--verbose", "--print"]
@doc """
Finds the claude binary in the system PATH.
Returns `{:ok, path}` if found, `{:error, :not_found}` otherwise.
"""
@spec find_binary() :: {:ok, String.t()} | {:error, :not_found}
def find_binary do
case System.find_executable(@claude_binary) do
nil -> {:error, :not_found}
path -> {:ok, path}
end
end
@doc """
Builds the command and arguments for running the Claude CLI.
Accepts validated options from the Options module and converts them to CLI flags.
If a session_id is provided, automatically adds --resume flag for session continuity.
Returns `{:ok, {executable, args}}` or `{:error, reason}`.
"""
@spec build_command(String.t(), String.t(), keyword(), String.t() | nil) ::
{:ok, {String.t(), [String.t()]}} | {:error, term()}
def build_command(prompt, _api_key, opts, session_id \\ nil) do
case find_binary() do
{:ok, executable} ->
args = build_args(prompt, opts, session_id)
{:ok, {executable, args}}
{:error, :not_found} ->
{:error, {:cli_not_found, cli_not_found_message()}}
end
end
@doc """
Validates that the Claude CLI is properly installed and accessible.
"""
@spec validate_installation() :: :ok | {:error, term()}
def validate_installation do
case find_binary() do
{:ok, path} ->
# Try to run claude --version to verify it's working
case System.cmd(path, ["--version"], stderr_to_stdout: true) do
{output, 0} ->
if String.contains?(output, "Claude Code") do
:ok
else
{:error, {:invalid_binary, "Binary at #{path} does not appear to be Claude CLI"}}
end
{error_output, _exit_code} ->
{:error, {:cli_error, error_output}}
end
{:error, :not_found} ->
{:error, {:cli_not_found, cli_not_found_message()}}
end
end
# Private Functions
defp build_args(prompt, opts, session_id) do
# Start with required flags
base_args = @required_flags
# Add resume flag if session_id is provided
resume_args =
if session_id do
["--resume", session_id]
else
[]
end
# Convert options to CLI flags using Options module
option_args = Options.to_cli_args(opts)
# Combine all arguments: base flags, resume (if any), options, then prompt
base_args ++ resume_args ++ option_args ++ [prompt]
end
defp cli_not_found_message do
"""
Claude CLI not found in PATH.
Please install Claude Code CLI:
1. Visit https://claude.ai/code
2. Follow the installation instructions for your platform
3. Ensure 'claude' is available in your PATH
You can verify the installation by running: claude --version
"""
end
end