Query command -- the primary interface for executing prompts.
Wraps claude -p <prompt> with the full set of CLI flags.
Usage
config = ClaudeWrapper.Config.new(working_dir: "/path/to/project")
# Build a query
query = ClaudeWrapper.Query.new("Fix the failing test")
|> ClaudeWrapper.Query.model("sonnet")
|> ClaudeWrapper.Query.max_turns(5)
|> ClaudeWrapper.Query.permission_mode(:bypass_permissions)
# Execute (one-shot, returns full result)
{:ok, result} = ClaudeWrapper.Query.execute(query, config)
# Or stream events
ClaudeWrapper.Query.stream(query, config)
|> Stream.each(&IO.inspect/1)
|> Stream.run()
Summary
Functions
Add a directory for tool access.
Set agent name.
Provide custom agents as JSON.
Add an allowed tool.
Append to the system prompt.
Append to the system prompt from a file (--append-system-prompt-file). Verified against claude CLI 2.1.170 (hidden from --help).
Apply a keyword list of options to a query, calling the equivalent
Query setter for each known key. Unknown keys are silently ignored.
Minimal mode: skip hooks, LSP, plugins, and settings (--bare).
Set beta feature header(s).
Enable the SendUserMessage tool for agent-to-user communication (--brief).
Continue the most recent session.
Bypass all permission checks. Use in isolated worktrees.
Set debug log file.
Set debug filter.
Disable all slash commands / skills (--disable-slash-commands).
Add a disallowed tool.
Set effort level.
Exclude dynamic system-prompt sections (--exclude-dynamic-system-prompt-sections).
Execute the query synchronously, returning a parsed %Result{}.
Set a fallback model.
Add a file resource.
Fork to a new session.
Resume a session linked to a PR (--from-pr <number|url>).
Seal the ambient ~/.claude config so a programmatic run's surface is
exactly what was provided explicitly.
Include hook lifecycle events in the output stream (--include-hook-events).
Include partial messages in streaming output.
Set input format.
Set JSON schema for structured output.
Set maximum budget in USD.
Cap the thinking-token budget (--max-thinking-tokens), a finer control than --effort. Verified against claude CLI 2.1.170 (hidden from --help).
Set maximum turns.
Add an MCP config file path.
Set the model (e.g. "sonnet", "opus", "haiku").
Set a display name for the session (--name).
Create a new query with the given prompt.
Disable session persistence.
Set output format.
Set permission mode.
Delegate permission decisions to a custom MCP tool (--permission-prompt-tool <tool>) for programmatic headless gating. Verified against claude CLI 2.1.170 (hidden from --help).
Add a plugin directory.
Fetch a plugin .zip from a URL (--plugin-url). Repeatable.
Enable prompt suggestions (--prompt-suggestions).
Re-emit user messages from stdin (--replay-user-messages). Mainly for stream/duplex use.
Resume a specific session by ID.
Start with all customizations disabled (--safe-mode).
Use a specific session ID.
Set settings source list.
Set settings JSON.
The spawn-time flag subset of a query, for a long-lived
ClaudeWrapper.DuplexSession.
Execute the query and return a lazy stream of %StreamEvent{}.
Only use servers from --mcp-config.
Set the system prompt (overrides default).
Set the system prompt from a file (--system-prompt-file), avoiding ARG_MAX limits from inlining a large prompt as argv. Verified against claude CLI 2.1.170 (hidden from --help).
Create tmux session.
Build the shell command string (for debugging).
Add a tool.
Create a git worktree for execution (--worktree). See worktree/2 for a named worktree.
Create a named git worktree for execution (--worktree <name>).
Types
@type effort() :: :low | :medium | :high | :xhigh | :max
@type hermetic() :: :full | :project
@type input_format() :: :text | :stream_json
@type output_format() :: :text | :json | :stream_json
@type permission_mode() ::
:default | :accept_edits | :bypass_permissions | :dont_ask | :plan | :auto
@type t() :: %ClaudeWrapper.Query{ add_dir: [String.t()], agent: String.t() | nil, agents_json: String.t() | nil, allowed_tools: [String.t()], append_system_prompt: String.t() | nil, append_system_prompt_file: String.t() | nil, bare: boolean(), betas: String.t() | [String.t()] | nil, brief: boolean(), continue_session: boolean(), dangerously_skip_permissions: boolean(), debug_file: String.t() | nil, debug_filter: String.t() | nil, disable_slash_commands: boolean(), disallowed_tools: [String.t()], effort: effort() | nil, exclude_dynamic_system_prompt_sections: boolean(), fallback_model: String.t() | nil, files: [String.t()], fork_session: boolean(), from_pr: String.t() | nil, hermetic: hermetic() | nil, include_hook_events: boolean(), include_partial_messages: boolean(), input_format: input_format() | nil, json_schema: String.t() | nil, max_budget_usd: float() | nil, max_thinking_tokens: pos_integer() | nil, max_turns: pos_integer() | nil, mcp_config: [String.t()], model: String.t() | nil, name: String.t() | nil, no_session_persistence: boolean(), output_format: output_format() | nil, permission_mode: permission_mode() | nil, permission_prompt_tool: String.t() | nil, plugin_dirs: [String.t()], plugin_urls: [String.t()], prompt: String.t(), prompt_suggestions: boolean(), replay_user_messages: boolean(), resume: String.t() | nil, safe_mode: boolean(), session_id: String.t() | nil, setting_sources: String.t() | nil, settings: String.t() | nil, strict_mcp_config: boolean(), system_prompt: String.t() | nil, system_prompt_file: String.t() | nil, tmux: boolean(), tools: [String.t()], worktree: boolean() | String.t() }
Functions
Add a directory for tool access.
Set agent name.
Provide custom agents as JSON.
@spec allowed_tool(t(), String.t() | ClaudeWrapper.ToolPattern.t()) :: t()
Add an allowed tool.
Accepts either a plain CLI-format string ("Bash(git log:*)") or a
ClaudeWrapper.ToolPattern.t/0, which is rendered to its string
form. The stored field stays a list of strings.
Append to the system prompt.
Append to the system prompt from a file (--append-system-prompt-file). Verified against claude CLI 2.1.170 (hidden from --help).
Apply a keyword list of options to a query, calling the equivalent
Query setter for each known key. Unknown keys are silently ignored.
This is the shared mapping used by ClaudeWrapper.query/2,
ClaudeWrapper.stream/2, and ClaudeWrapper.Session.send/3. It
exists so the opt-to-setter mapping lives in one place rather than
being duplicated across each surface.
Boolean opts (e.g. :worktree, :dangerously_skip_permissions)
are applied when the value is true and ignored when false. List
opts (e.g. :allowed_tools, :add_dir) reduce over their list,
applying the per-item setter for each entry.
Examples
iex> q = ClaudeWrapper.Query.new("hi")
iex> q = ClaudeWrapper.Query.apply_opts(q, model: "sonnet", max_turns: 3, worktree: true)
iex> q.model
"sonnet"
iex> q.max_turns
3
iex> q.worktree
true
Minimal mode: skip hooks, LSP, plugins, and settings (--bare).
Set beta feature header(s).
Accepts a single string or a list -- the CLI's --betas is variadic, so a
list emits one --betas flag followed by every value (a single string is
still accepted, unchanged).
Enable the SendUserMessage tool for agent-to-user communication (--brief).
Continue the most recent session.
Bypass all permission checks. Use in isolated worktrees.
Set debug log file.
Set debug filter.
Disable all slash commands / skills (--disable-slash-commands).
@spec disallowed_tool(t(), String.t() | ClaudeWrapper.ToolPattern.t()) :: t()
Add a disallowed tool.
Accepts either a plain CLI-format string or a
ClaudeWrapper.ToolPattern.t/0, mirroring allowed_tool/2.
Set effort level.
Exclude dynamic system-prompt sections (--exclude-dynamic-system-prompt-sections).
@spec execute(t(), ClaudeWrapper.Config.t()) :: {:ok, ClaudeWrapper.Result.t()} | {:error, ClaudeWrapper.Error.t()}
Execute the query synchronously, returning a parsed %Result{}.
Automatically sets --output-format json for parsing.
Set a fallback model.
Add a file resource.
Fork to a new session.
Resume a session linked to a PR (--from-pr <number|url>).
Analogous to resume/2 but keyed on a pull request rather than a
session id. The value is a PR number or URL.
Seal the ambient ~/.claude config so a programmatic run's surface is
exactly what was provided explicitly.
A preset over three flags, expanded at flag-build time (never here), so
the seal is order-independent and an explicit setting_sources/2 always
wins over the scope's default:
--setting-sources(the ambient-config seal)--strict-mcp-config(only servers from--mcp-config)--exclude-dynamic-system-prompt-sections(reproducibility)
The scope sets the seal level:
:full->--setting-sources ""-- drops user + project + local ambient config; only claude's built-in agents remain.:project->--setting-sources user-- seals project + local ambient config, keeps the user's global~/.claude.
Hermetic seals the promptspace WITHOUT changing auth: it never emits
--bare (which would force ANTHROPIC_API_KEY billing). OAuth /
keychain / subscription auth is untouched.
Include hook lifecycle events in the output stream (--include-hook-events).
Include partial messages in streaming output.
@spec input_format(t(), input_format()) :: t()
Set input format.
Set JSON schema for structured output.
Set maximum budget in USD.
@spec max_thinking_tokens(t(), pos_integer()) :: t()
Cap the thinking-token budget (--max-thinking-tokens), a finer control than --effort. Verified against claude CLI 2.1.170 (hidden from --help).
@spec max_turns(t(), pos_integer()) :: t()
Set maximum turns.
Add an MCP config file path.
Set the model (e.g. "sonnet", "opus", "haiku").
Set a display name for the session (--name).
Create a new query with the given prompt.
Disable session persistence.
@spec output_format(t(), output_format()) :: t()
Set output format.
@spec permission_mode(t(), permission_mode()) :: t()
Set permission mode.
Delegate permission decisions to a custom MCP tool (--permission-prompt-tool <tool>) for programmatic headless gating. Verified against claude CLI 2.1.170 (hidden from --help).
Add a plugin directory.
Fetch a plugin .zip from a URL (--plugin-url). Repeatable.
Enable prompt suggestions (--prompt-suggestions).
Re-emit user messages from stdin (--replay-user-messages). Mainly for stream/duplex use.
Resume a specific session by ID.
Start with all customizations disabled (--safe-mode).
Use a specific session ID.
Set settings source list.
Set settings JSON.
The spawn-time flag subset of a query, for a long-lived
ClaudeWrapper.DuplexSession.
Reuses build_args/1 (the single source of flag emission, so the
duplex and one-shot paths cannot drift), then removes the flags a
duplex session owns itself: the transport formats
(--output-format / --input-format / --include-partial-messages,
which the session fixes to its stream-json protocol) and the leading
--print <prompt> pair (in duplex the prompt is a per-turn
stream-json message, not an argv). Everything else -- model, system
prompt, permission mode, tool allow/deny lists, mcp config, effort,
turn/budget caps, session continuity, and so on -- is spawn-safe and
passes through.
@spec stream(t(), ClaudeWrapper.Config.t()) :: Enumerable.t()
Execute the query and return a lazy stream of %StreamEvent{}.
Uses a Port with :line mode to read NDJSON output line-by-line.
The port is opened when the stream is consumed and closed when
the stream terminates.
A clean run ends with a terminal %StreamEvent{type: "result"}. If the stream
halts without one -- an idle timeout (Config.timeout is not a whole-run
bound here; only the per-frame idle deadline applies), a non-zero exit, or a
spawn failure -- the stream ends with a terminal
%StreamEvent{type: "error", data: %{"error" => "stream_truncated"}} so the
truncation is observable. Note the default runner orphans a stalled
subprocess; use the ClaudeWrapper.Runner.Forcola runner for leak-free
termination.
Only use servers from --mcp-config.
Set the system prompt (overrides default).
Set the system prompt from a file (--system-prompt-file), avoiding ARG_MAX limits from inlining a large prompt as argv. Verified against claude CLI 2.1.170 (hidden from --help).
Create tmux session.
@spec to_command_string(t(), ClaudeWrapper.Config.t()) :: String.t()
Build the shell command string (for debugging).
Add a tool.
Create a git worktree for execution (--worktree). See worktree/2 for a named worktree.
Create a named git worktree for execution (--worktree <name>).