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()
:okWhen 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, passpermission_mode: "default"and anon_permissioncallback - All
ClaudeWrapper.Configoptions (:binary,:env,:timeout, etc.) are accepted and forwarded toClaudeWrapper.Config.new/1 - All
ClaudeWrapper.DuplexSessionoptions (: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
@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.
Cancel the current in-flight turn. Returns :ok once the CLI
acknowledges, or {:error, reason} if no session is running.
@spec pid() :: pid() | nil
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.
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.
@spec session_id() :: String.t() | nil
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.
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.
@spec status() :: :ok | :no_session
Print the current session's id and pid.