# `ClaudeWrapper.Bundled`
[🔗](https://github.com/genagent/claude_wrapper_ex/blob/main/lib/claude_wrapper/bundled.ex#L1)

Opt-in bundled-binary resolution for the `claude` CLI.

By default `claude_wrapper` expects `claude` on `PATH` (see
`ClaudeWrapper.Config.find_binary/0`). This module is the alternative:
resolve, install, and version-pin a `claude` binary under the package's
`priv/bin/`, so an app can depend on `claude_wrapper` and get a known
CLI without a separate install step on PATH.

It is **opt-in** -- nothing here runs unless you ask for it, via
`ClaudeWrapper.Config.new(binary: :bundled)`, the `mix claude_wrapper.*`
tasks, or calling `ensure!/0` directly. The stdlib-minimal default and
its dependency footprint are unchanged for everyone else.

## Resolution vs install

`path/0` is pure: it returns where the bundled binary lives, whether or
not it is present. `Config.new(binary: :bundled)` resolves to that path
and does **not** touch the network -- a struct constructor should not
download anything. Installing is an explicit step:

    mix claude_wrapper.install      # or: ClaudeWrapper.Bundled.ensure!()

`ensure/0` installs only when the binary is missing or its version is
below `minimum_version/0`.

## Minimum version

The bundled binary must be at least `2.0.0`.
`install/0` fetches the current stable CLI and verifies it reports a
version `>=` this floor; it does not coerce an exact version out of the
upstream installer (which takes no version argument).

# `ensure`

```elixir
@spec ensure() :: {:ok, String.t()} | {:error, ClaudeWrapper.Error.t()}
```

Ensure a bundled binary satisfying `minimum_version/0` is installed.

Installs when the binary is missing or reports a different version;
otherwise a no-op. Returns `{:ok, path}` or `{:error, %Error{}}`.

# `ensure!`

```elixir
@spec ensure!() :: String.t()
```

Like `ensure/0` but returns the path or raises on failure.

# `install`

```elixir
@spec install() :: {:ok, String.t()} | {:error, ClaudeWrapper.Error.t()}
```

Download and install the pinned `claude` binary into `priv/bin/`.

Runs Anthropic's official installer in a temporary `HOME`, copies the
resulting binary into place, marks it executable, and (on macOS) retries
once after clearing the Gatekeeper quarantine if the first run is killed
(exit 137). Returns `{:ok, path}` or `{:error, %Error{}}`.

# `installed?`

```elixir
@spec installed?() :: boolean()
```

Whether the bundled binary is present on disk.

# `installed_version`

```elixir
@spec installed_version() :: ClaudeWrapper.CliVersion.t() | nil
```

The version the installed bundled binary reports, or `nil` if it is not
installed (or `--version` could not be parsed).

# `minimum_version`

```elixir
@spec minimum_version() :: String.t()
```

The minimum CLI version the bundled binary must satisfy (a floor).

# `path`

```elixir
@spec path() :: String.t()
```

Absolute path to the bundled binary, `priv/bin/claude`.

Pure -- returns the path whether or not the binary is installed.

# `uninstall`

```elixir
@spec uninstall() :: :ok
```

Remove the bundled binary. Idempotent.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
