ClaudeCode.Adapter.Port.Installer (ClaudeCode v0.32.2)

View Source

Manages Claude CLI binary installation.

This module handles automatic CLI binary management following patterns from phoenixframework/esbuild and phoenixframework/tailwind, using the official Anthropic install scripts.

Installation Methods

  1. Automatic - CLI is auto-installed to priv/bin/ on first use when cli_path: :bundled (the default)
  2. Manual - Run mix claude_code.install to pre-install the CLI
  3. Pre-installed - Use a system CLI with cli_path: :global or cli_path: "/path/to/claude"

Configuration

# config/config.exs
config :claude_code,
  cli_path: :bundled,               # :bundled (default), :global, or "/path/to/claude"
  cli_version: "x.y.z",            # Version to install (default: SDK's tested version)
  cli_dir: nil                      # Directory for downloaded binary

CLI Resolution Modes

The :cli_path option controls how the CLI binary is found (see ClaudeCode.Adapter.Port.Resolver.find_binary/1):

  • :bundled (default) — Uses priv/bin/ binary. Auto-installs if missing. Verifies version matches the SDK's pinned version and re-installs on mismatch.
  • :global — Finds existing system install via PATH or common locations. No auto-install.
  • "/path/to/claude" — Uses that exact binary path.

Release Configuration

For releases, you have several options:

  1. Pre-install during build - Run mix claude_code.install in your release build
  2. Configure writable directory - Set :cli_dir to a writable runtime location
  3. Use system CLI - Set cli_path: :global and ensure claude is in PATH

Summary

Functions

Returns the path to the bundled CLI binary.

Returns the directory where the CLI binary should be stored.

Returns the error message shown when the CLI binary cannot be found.

Returns the configured CLI version to install.

Searches for the CLI in common installation locations.

Installs the Claude CLI using the official Anthropic install script.

Returns the version of the CLI binary at the given path.

Functions

bundled_path()

@spec bundled_path() :: String.t()

Returns the path to the bundled CLI binary.

This is the path where the installer places the CLI binary, not necessarily where it currently exists.

Examples

iex> ClaudeCode.Adapter.Port.Installer.bundled_path()
"/path/to/app/priv/bin/claude"

cli_dir()

@spec cli_dir() :: String.t()

Returns the directory where the CLI binary should be stored.

Defaults to priv/bin/ within the application directory.

Examples

iex> ClaudeCode.Adapter.Port.Installer.cli_dir()
"/path/to/app/priv/bin"

cli_not_found_message()

@spec cli_not_found_message() :: String.t()

Returns the error message shown when the CLI binary cannot be found.

Used by both the Installer and CLI modules to provide consistent error messaging.

configured_version()

@spec configured_version() :: String.t()

Returns the configured CLI version to install.

Defaults to the SDK's tested version if not configured.

Examples

iex> ClaudeCode.Adapter.Port.Installer.configured_version()
"2.1.76"

find_in_common_locations()

@spec find_in_common_locations() :: String.t() | nil

Searches for the CLI in common installation locations.

Returns the path if found, nil otherwise.

install!(opts \\ [])

@spec install!(keyword()) :: :ok | {:ok, map()}

Installs the Claude CLI using the official Anthropic install script.

The binary is installed to the configured cli_dir (default: priv/bin/).

Options

  • :version - Version to install (default: configured version)
  • :return_info - When true, returns {:ok, info_map} instead of :ok (default: false). The info map contains: version, path, size_bytes.

Examples

iex> ClaudeCode.Adapter.Port.Installer.install!()
:ok

iex> ClaudeCode.Adapter.Port.Installer.install!(version: "2.1.76")
:ok

iex> ClaudeCode.Adapter.Port.Installer.install!(return_info: true)
{:ok, %{version: "2.1.76", path: "/path/to/claude", size_bytes: 1234567}}

version_of(path)

@spec version_of(String.t()) :: {:ok, String.t()} | {:error, term()}

Returns the version of the CLI binary at the given path.

Runs claude --version and parses the output.

Examples

iex> ClaudeCode.Adapter.Port.Installer.version_of("/usr/local/bin/claude")
{:ok, "2.1.76"}

iex> ClaudeCode.Adapter.Port.Installer.version_of("/nonexistent")
{:error, {:execution_failed, "enoent"}}