ClaudeWrapper.DuplexIEx (ClaudeWrapper v0.6.0)

Copy Markdown View Source

Interactive helpers for driving ClaudeWrapper.DuplexSession from IEx.

Spawns a long-lived claude subprocess, holds it across many turns, and prints streaming text deltas to stdout as they arrive. Sibling to ClaudeWrapper.IEx, which uses the simpler per-call Query/Session flow.

Usage

iex> import ClaudeWrapper.DuplexIEx

iex> start(working_dir: ".")
Claude session started.

iex> say("Explain the README briefly.")
...streams text...
($0.0123, 1 turn)
:ok

iex> say("Now suggest a one-line tagline.")
...streams text...
:ok

iex> interrupt()
:ok

iex> close()
:ok

When to use this vs ClaudeWrapper.IEx

Both are interactive REPL surfaces. ClaudeWrapper.IEx (the pre-existing one) spawns a fresh claude subprocess per turn and is the simplest thing that works for casual use. ClaudeWrapper.DuplexIEx holds one subprocess open, so subsequent turns avoid CLI cold start and the experience feels more like talking to a chat UI -- partial tokens appear as they're generated, mid-turn cancel via interrupt/0 is clean, and a permission callback can react to tool requests in flight.

Defaults

  • Working dir defaults to File.cwd!() so the session sees your current project
  • Permission mode defaults to "bypassPermissions" so tool calls just work in the REPL without a permission callback. This is not safe for prompts you do not control. For trustworthy use, pass permission_mode: "default" and an on_permission callback
  • All ClaudeWrapper.Config options (:binary, :env, :timeout, etc.) are accepted and forwarded to Config.new/1
  • All ClaudeWrapper.DuplexSession options (:on_permission, :extra_args) are forwarded as well

Summary

Functions

Close the current session, kill the printer, and clear stored state.

Cancel the current in-flight turn. Returns :ok once the CLI acknowledges, or {:error, reason} if no session is running.

Return the raw DuplexSession pid for direct API access, or nil.

Send a prompt in the current session. Streaming text is printed as it arrives. Returns :ok on success or {:error, reason} on failure.

Return the CLI session id for resuming later, or nil if no session is running.

Start a new duplex session and a streaming printer process.

Print the current session's id and pid.

Functions

close()

@spec close() :: :ok

Close the current session, kill the printer, and clear stored state.

Named close/0 (rather than the more obvious stop/0) to avoid colliding with ClaudeWrapper.Workshop.stop/0 when both modules are imported. Mirrors the underlying ClaudeWrapper.DuplexSession.close/1.

interrupt(timeout \\ 10000)

@spec interrupt(timeout()) :: :ok | {:error, term()}

Cancel the current in-flight turn. Returns :ok once the CLI acknowledges, or {:error, reason} if no session is running.

pid()

@spec pid() :: pid() | nil

Return the raw DuplexSession pid for direct API access, or nil.

say(prompt, opts \\ [])

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

Send a prompt in the current session. Streaming text is printed as it arrives. Returns :ok on success or {:error, reason} on failure.

Per-call options:

  • :timeout -- override the 120-second default for this turn

All other options are ignored at this layer; pass DuplexSession options (such as :on_permission) to start/1 instead.

session_id()

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

Return the CLI session id for resuming later, or nil if no session is running.

start(opts \\ [])

@spec start(keyword()) :: :ok | {:error, term()}

Start a new duplex session and a streaming printer process.

Stores the session pid and printer pid in the process dictionary for the rest of the helpers to find. If a session is already running for this process, it is closed first.

status()

@spec status() :: :ok | :no_session

Print the current session's id and pid.