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

Opt-in wrapper for permission-bypass queries.

Running the `claude` CLI with `--dangerously-skip-permissions` turns
off every confirmation prompt for tool use. It's legitimate for some
automation -- but it's also the fastest way to turn a bug into a
destructive action.

This module isolates that capability behind a type you have to
explicitly reach for (`ClaudeWrapper.DangerousClient`) and a runtime
env-var gate (`CLAUDE_WRAPPER_ALLOW_DANGEROUS`) you have to
explicitly set.

## Usage

    # At process start (deliberately):
    #   export CLAUDE_WRAPPER_ALLOW_DANGEROUS=1

    config = ClaudeWrapper.Config.new(working_dir: "/path/to/project")

    case ClaudeWrapper.DangerousClient.new(config) do
      {:ok, client} ->
        query = ClaudeWrapper.Query.new("clean up the build artifacts")
        {:ok, result} = ClaudeWrapper.DangerousClient.query_bypass(client, query)

      {:error, %ClaudeWrapper.Error{kind: :dangerous_not_allowed} = error} ->
        # The caller forgot to set the env var; refuse loudly rather
        # than silently running with (or without) bypass.
        {:error, error}
    end

## Why this shape

  * **Separate type.** `new/1` is the only path to building a bypassed
    query through this module. If a reader of calling code sees
    `DangerousClient`, the danger is obvious at the call site.
  * **Runtime env-var gate.** The check happens at construction, so a
    caller who forgot to set the env var gets a tagged error rather
    than silently running with bypass off (which might surprise them)
    or silently running with bypass on (which might destroy things).
  * **Checked on every construction.** The gate is read on each call
    to `new/1` rather than memoized, so a test that flips the env var
    mid-process sees the change.

The lower-level `ClaudeWrapper.Query.dangerously_skip_permissions/1`
setter is still available without this gate; this module is the
guarded, intention-revealing path on top of it.

Equivalent to the Rust crate's `dangerous::DangerousClient`. The Rust
type splits `query_bypass` into async (`query_bypass`) and blocking
(`query_bypass_sync`) variants gated by cargo features; the Elixir
port has a single synchronous `query_bypass/2` since `Query.execute/2`
is synchronous and there are no feature gates.

# `t`

```elixir
@type t() :: %ClaudeWrapper.DangerousClient{config: ClaudeWrapper.Config.t()}
```

A guarded client. Holds the shared `t:ClaudeWrapper.Config.t/0` that
bypass queries run against.

# `allow_env`

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

The name of the env var that must equal `"1"` for `new/1` to succeed.

Exposed so callers and tests can reference the gate without hardcoding
the string.

## Examples

    iex> ClaudeWrapper.DangerousClient.allow_env()
    "CLAUDE_WRAPPER_ALLOW_DANGEROUS"

# `config`

```elixir
@spec config(t()) :: ClaudeWrapper.Config.t()
```

Return the underlying config for composition with other wrapper APIs.

# `new`

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

Build a guarded client, refusing unless the opt-in env var is set.

Succeeds only when `System.get_env("CLAUDE_WRAPPER_ALLOW_DANGEROUS") == "1"`. Otherwise
returns `{:error, %ClaudeWrapper.Error{kind: :dangerous_not_allowed}}`,
whose `:reason` is the name of the env var to set.

The check is made on each call rather than memoized, so a process that
sets the env var after start (or a test that flips it) is honored.

## Examples

    {:ok, client} = ClaudeWrapper.DangerousClient.new(ClaudeWrapper.Config.new())

    {:error, %ClaudeWrapper.Error{kind: :dangerous_not_allowed, reason: "CLAUDE_WRAPPER_ALLOW_DANGEROUS"}} =
      ClaudeWrapper.DangerousClient.new(ClaudeWrapper.Config.new())

# `query_bypass`

```elixir
@spec query_bypass(t(), ClaudeWrapper.Query.t()) ::
  {:ok, ClaudeWrapper.Result.t()} | {:error, term()}
```

Run `query` with `--dangerously-skip-permissions` set, against the
client's config.

Sets `dangerously_skip_permissions` on the query (replacing any prior
value) and delegates to `ClaudeWrapper.Query.execute/2`. Returns
whatever `execute/2` returns: `{:ok, %ClaudeWrapper.Result{}}` or
`{:error, reason}`.

---

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