ClaudeCode (ClaudeCode v0.16.0)
View SourceElixir SDK for Claude Code CLI.
This module provides the main interface for interacting with Claude Code through the command-line interface. It manages sessions as GenServer processes that maintain persistent CLI subprocesses for efficient bidirectional communication.
API Overview
| Function | Purpose |
|---|---|
start_link/1 | Start a session (with optional resume: id) |
stop/1 | Stop a session |
stream/3 | Send prompt to session, get message stream |
query/2 | One-off query (auto start/stop) |
Quick Start
# Multi-turn conversation (primary API)
{:ok, session} = ClaudeCode.start_link(api_key: "sk-ant-...")
ClaudeCode.stream(session, "What is 5 + 3?")
|> Enum.each(&IO.inspect/1)
ClaudeCode.stream(session, "Multiply that by 2")
|> Enum.each(&IO.inspect/1)
ClaudeCode.stop(session)
# One-off query (convenience)
{:ok, result} = ClaudeCode.query("What is 2 + 2?", api_key: "sk-ant-...")
IO.puts(result)Session Lifecycle
Sessions automatically connect to the Claude CLI on startup and disconnect on stop. The persistent connection enables:
- Efficient multi-turn conversations without CLI restart overhead
- Automatic session continuity via session IDs
- Real-time streaming of responses
Supervision for Production
For production applications, use the supervisor for fault tolerance and automatic restart capabilities:
# In your application supervision tree
children = [
{ClaudeCode.Supervisor, [
[name: :code_reviewer, api_key: api_key, system_prompt: "You review Elixir code"],
[name: :test_writer, api_key: api_key, system_prompt: "You write ExUnit tests"]
]}
]
Supervisor.start_link(children, strategy: :one_for_one)
# Access supervised sessions from anywhere
:code_reviewer
|> ClaudeCode.stream("Review this function")
|> ClaudeCode.Stream.text_content()
|> Enum.join()Resume Previous Conversations
# Get session ID from a previous interaction
session_id = ClaudeCode.get_session_id(session)
# Later: resume the conversation
{:ok, new_session} = ClaudeCode.start_link(
api_key: "sk-ant-...",
resume: session_id
)
ClaudeCode.stream(new_session, "Continue where we left off")
|> Enum.each(&IO.inspect/1)
# Or fork to create a branch with a new session ID
{:ok, forked} = ClaudeCode.start_link(
resume: session_id,
fork_session: true
)See ClaudeCode.Supervisor for advanced supervision patterns.
Summary
Functions
Checks if a session is alive.
Clears the current session ID to start a fresh conversation.
Reads conversation history from a session's JSONL file.
Gets the current session ID for conversation continuity.
Sends a one-off query to Claude and returns the result.
Starts a new Claude Code session.
Stops a Claude Code session.
Sends a query to a session and returns a stream of messages.
Returns the SDK version string.
Types
@type message_stream() :: Enumerable.t(ClaudeCode.Message.t())
@type query_response() :: {:ok, ClaudeCode.Message.ResultMessage.t()} | {:error, ClaudeCode.Message.ResultMessage.t() | term()}
Functions
Checks if a session is alive.
Examples
true = ClaudeCode.alive?(session)
@spec clear(session()) :: :ok
Clears the current session ID to start a fresh conversation.
This will cause the next query to start a new conversation context rather than continuing the existing one. Useful when you want to reset the conversation history.
Examples
:ok = ClaudeCode.clear(session)
# Next stream will start fresh
ClaudeCode.stream(session, "Hello!")
|> Enum.each(&IO.inspect/1)
@spec conversation( session() | String.t(), keyword() ) :: {:ok, [ ClaudeCode.Message.AssistantMessage.t() | ClaudeCode.Message.UserMessage.t() ]} | {:error, term()}
Reads conversation history from a session's JSONL file.
Accepts either a session ID string or a running session reference. Returns user and assistant messages parsed into SDK message structs.
Options
:project_path- Specific project path to search in (optional):claude_dir- Override the Claude directory (default:~/.claude)
Examples
# Read conversation history by session ID
{:ok, messages} = ClaudeCode.conversation("abc123-def456")
# Or from a running session
{:ok, session} = ClaudeCode.start_link()
ClaudeCode.query(session, "Hello!")
{:ok, messages} = ClaudeCode.conversation(session)
Enum.each(messages, fn
%ClaudeCode.Message.UserMessage{message: %{content: content}} ->
IO.puts("User: #{inspect(content)}")
%ClaudeCode.Message.AssistantMessage{message: %{content: blocks}} ->
text = Enum.map_join(blocks, "", fn
%ClaudeCode.Content.TextBlock{text: t} -> t
_ -> ""
end)
IO.puts("Assistant: #{text}")
end)See ClaudeCode.History for more options.
Gets the current session ID for conversation continuity.
Returns the session ID that Claude CLI is using to maintain conversation context. This ID is automatically captured from CLI responses and used for subsequent queries to continue the conversation.
You can use this session ID with the :resume option when starting a
new session to continue the conversation later, or with :fork_session
to create a branch.
Examples
session_id = ClaudeCode.get_session_id(session)
# => "abc123-session-id"
# For a new session with no queries yet
nil = ClaudeCode.get_session_id(session)
# Resume later
{:ok, new_session} = ClaudeCode.start_link(resume: session_id)
# Or fork the conversation
{:ok, forked} = ClaudeCode.start_link(resume: session_id, fork_session: true)
@spec query( String.t(), keyword() ) :: query_response()
Sends a one-off query to Claude and returns the result.
This is a convenience function that automatically manages a temporary session.
For multi-turn conversations, use start_link/1 and stream/3 instead.
Options
See ClaudeCode.Options.session_schema/0 for all available options.
Examples
# Simple one-off query
{:ok, result} = ClaudeCode.query("What is 2 + 2?", api_key: "sk-ant-...")
IO.puts(result) # Result implements String.Chars
# => "4"
# With options
{:ok, result} = ClaudeCode.query("Complex query",
api_key: "sk-ant-...",
model: "opus",
system_prompt: "Focus on performance optimization"
)
# Handle errors
case ClaudeCode.query("Do something risky", api_key: "sk-ant-...") do
{:ok, result} -> IO.puts(result.result)
{:error, %ClaudeCode.Message.ResultMessage{is_error: true} = result} ->
IO.puts("Claude error: #{result.result}")
{:error, reason} -> IO.puts("Error: #{inspect(reason)}")
end
@spec start_link(keyword()) :: GenServer.on_start()
Starts a new Claude Code session.
The session automatically connects to a persistent CLI subprocess on startup. This enables efficient multi-turn conversations without CLI restart overhead.
Options
For complete option documentation including types, validation rules, and examples,
see ClaudeCode.Options.session_schema/0 and the ClaudeCode.Options module.
Key options:
:api_key- Anthropic API key (or set ANTHROPIC_API_KEY env var):resume- Session ID to resume a previous conversation:model- Claude model to use:system_prompt- Custom system prompt
Examples
# Start a basic session
{:ok, session} = ClaudeCode.start_link(api_key: "sk-ant-...")
# Start with application config (if api_key is configured)
{:ok, session} = ClaudeCode.start_link()
# Resume a previous conversation
{:ok, session} = ClaudeCode.start_link(
api_key: "sk-ant-...",
resume: "previous-session-id"
)
# Start with custom options
{:ok, session} = ClaudeCode.start_link(
api_key: "sk-ant-...",
model: "opus",
system_prompt: "You are an Elixir expert",
allowed_tools: ["View", "Edit", "Bash(git:*)"],
add_dir: ["/tmp", "/var/log"],
max_turns: 20,
timeout: 180_000,
name: :my_session
)
@spec stop(session()) :: :ok
Stops a Claude Code session.
This closes the CLI subprocess and cleans up resources.
Examples
:ok = ClaudeCode.stop(session)
@spec stream(session(), String.t(), keyword()) :: message_stream()
Sends a query to a session and returns a stream of messages.
This is the primary API for interacting with Claude. The stream emits messages as they arrive and automatically completes when Claude finishes responding.
Options
Query-level options override session-level options. See ClaudeCode.Options.query_schema/0
for all available query options.
Examples
# Stream all messages
session
|> ClaudeCode.stream("Write a hello world program")
|> Enum.each(&IO.inspect/1)
# Stream with option overrides
session
|> ClaudeCode.stream("Explain quantum computing",
system_prompt: "Focus on practical applications",
allowed_tools: ["View"])
|> ClaudeCode.Stream.text_content()
|> Enum.each(&IO.write/1)
# Collect all text content
text =
session
|> ClaudeCode.stream("Tell me a story")
|> ClaudeCode.Stream.text_content()
|> Enum.join()
# Multi-turn conversation
{:ok, session} = ClaudeCode.start_link(api_key: "sk-ant-...")
ClaudeCode.stream(session, "What is 5 + 3?")
|> Enum.each(&IO.inspect/1)
ClaudeCode.stream(session, "Multiply that by 2")
|> Enum.each(&IO.inspect/1)
@spec version() :: String.t()
Returns the SDK version string.
Used internally for environment variables passed to the CLI subprocess.
Examples
iex> ClaudeCode.version()
"0.16.0"