Configuration Guide

View Source

ClaudeCode uses NimbleOptions for configuration validation. Options can be set at multiple levels with clear precedence rules.

Option Precedence

Options are resolved in this order (highest to lowest priority):

  1. Query-level options - Passed to query/3 or stream/3
  2. Session-level options - Passed to start_link/1
  3. Application config - Set in config/config.exs
  4. Default values - Built-in defaults
# Application config (lowest priority)
config :claude_code, timeout: 300_000

# Session-level overrides app config
{:ok, session} = ClaudeCode.start_link(timeout: 120_000)

# Query-level overrides session
ClaudeCode.stream(session, "Hello", timeout: 60_000)

Session Options

All options for ClaudeCode.start_link/1:

Authentication

OptionTypeDefaultDescription
api_keystringANTHROPIC_API_KEY envAnthropic API key
nameatom-Register session with a name

Model Configuration

OptionTypeDefaultDescription
modelstring"sonnet"Claude model to use
fallback_modelstring-Fallback if primary model fails
system_promptstring-Override system prompt
append_system_promptstring-Append to default system prompt
max_turnsinteger-Limit conversation turns
max_budget_usdnumber-Maximum dollar amount to spend on API calls
agentstring-Agent name for the session
betaslist-Beta headers for API requests

Timeouts

OptionTypeDefaultDescription
timeoutinteger300_000Query timeout in milliseconds

Tool Control

OptionTypeDefaultDescription
toolsatom/list-Available tools: :default, [], or list of names
allowed_toolslist-Tools Claude can use
disallowed_toolslist-Tools Claude cannot use
add_dirlist-Additional accessible directories
permission_modeatom:defaultPermission handling mode

Advanced

OptionTypeDefaultDescription
resumestring-Session ID to resume
fork_sessionbooleanfalseCreate new session ID when resuming
mcp_configstring-Path to MCP config file
strict_mcp_configbooleanfalseOnly use MCP servers from explicit config
agentsmap-Custom agent configurations
settingsmap/string-Team settings
setting_sourceslist-Setting source priority
tool_callbackfunction-Called after tool executions
include_partial_messagesbooleanfalseEnable character-level streaming
json_schemamap/string-JSON Schema for structured output validation

Query Options

Options that can be passed to stream/3:

OptionTypeDescription
timeoutintegerOverride session timeout
system_promptstringOverride system prompt for this query
append_system_promptstringAppend to system prompt
max_turnsintegerLimit turns for this query
max_budget_usdnumberMaximum dollar amount for this query
agentstringAgent to use for this query
betaslistBeta headers for this query
toolslistAvailable tools for this query
allowed_toolslistAllowed tools for this query
disallowed_toolslistDisallowed tools for this query
json_schemamap/stringJSON Schema for structured output
include_partial_messagesbooleanEnable deltas for this query

Note: api_key and name cannot be overridden at query time.

Application Configuration

Set defaults in config/config.exs:

config :claude_code,
  api_key: System.get_env("ANTHROPIC_API_KEY"),
  model: "sonnet",
  timeout: 180_000,
  system_prompt: "You are a helpful assistant",
  allowed_tools: ["View"]

Environment-Specific Configuration

# config/dev.exs
config :claude_code,
  timeout: 60_000,
  permission_mode: :accept_edits

# config/prod.exs
config :claude_code,
  timeout: 300_000,
  permission_mode: :default

# config/test.exs
config :claude_code,
  api_key: "test-key",
  timeout: 5_000

Model Selection

# Use a specific model
{:ok, session} = ClaudeCode.start_link(model: "opus")

# With fallback
{:ok, session} = ClaudeCode.start_link(
  model: "opus",
  fallback_model: "sonnet"
)

Available models: "sonnet", "opus", "haiku", or full model IDs.

System Prompts

# Override completely
{:ok, session} = ClaudeCode.start_link(
  system_prompt: "You are an Elixir expert. Only discuss Elixir."
)

# Append to default
{:ok, session} = ClaudeCode.start_link(
  append_system_prompt: "Always format code with proper indentation."
)

Cost Control

# Limit spending per query
session
|> ClaudeCode.stream("Complex analysis task", max_budget_usd: 5.00)
|> Stream.run()

# Set a session-wide budget limit
{:ok, session} = ClaudeCode.start_link(
  max_budget_usd: 25.00
)

Structured Outputs

Use JSON Schema to get validated structured responses:

schema = %{
  "type" => "object",
  "properties" => %{
    "name" => %{"type" => "string"},
    "age" => %{"type" => "integer"},
    "skills" => %{"type" => "array", "items" => %{"type" => "string"}}
  },
  "required" => ["name", "age"]
}

session
|> ClaudeCode.stream("Extract person info from: John is 30 and knows Elixir",
     json_schema: schema)
|> ClaudeCode.Stream.text_content()
|> Enum.join()

Tool Configuration

# Use all default tools
{:ok, session} = ClaudeCode.start_link(tools: :default)

# Specify available tools (subset of built-in)
{:ok, session} = ClaudeCode.start_link(
  tools: ["Bash", "Edit", "Read"]
)

# Disable all tools
{:ok, session} = ClaudeCode.start_link(tools: [])

# Allow specific tools with patterns
{:ok, session} = ClaudeCode.start_link(
  allowed_tools: ["View", "Edit", "Bash(git:*)"]
)

# Disallow specific tools
{:ok, session} = ClaudeCode.start_link(
  disallowed_tools: ["Bash", "Write"]
)

# Additional directories
{:ok, session} = ClaudeCode.start_link(
  add_dir: ["/app/lib", "/app/test"]
)

MCP Server Control

Claude Code can connect to MCP (Model Context Protocol) servers for additional tools. By default, it uses globally configured MCP servers. Use strict_mcp_config to control this:

# No tools at all (no built-in tools, no MCP servers)
{:ok, session} = ClaudeCode.start_link(
  tools: [],
  strict_mcp_config: true
)
# tools: [], mcp_servers: []

# Built-in tools only (ignore global MCP servers)
{:ok, session} = ClaudeCode.start_link(
  tools: :default,
  strict_mcp_config: true
)
# tools: ["Task", "Bash", "Read", "Edit", ...], mcp_servers: []

# Default behavior (built-in tools + global MCP servers)
{:ok, session} = ClaudeCode.start_link()
# tools: ["Task", "Bash", ..., "mcp__memory__*", "mcp__github__*", ...]
# mcp_servers: [%{name: "memory", ...}, %{name: "github", ...}]

# Specific MCP servers only (no global config)
{:ok, session} = ClaudeCode.start_link(
  strict_mcp_config: true,
  mcp_servers: %{
    "my-tools" => %{command: "npx", args: ["my-mcp-server"]}
  }
)

Using Hermes MCP Modules

You can use Elixir-based MCP servers built with Hermes MCP:

{:ok, session} = ClaudeCode.start_link(
  strict_mcp_config: true,
  mcp_servers: %{
    "my-tools" => MyApp.MCPServer,
    "custom" => %{module: MyApp.MCPServer, env: %{"DEBUG" => "1"}}
  }
)

Custom Agents

Configure custom agents with specialized behaviors:

agents = %{
  "code-reviewer" => %{
    "description" => "Expert code reviewer",
    "prompt" => "You review code for quality and best practices.",
    "tools" => ["View", "Grep", "Glob"],
    "model" => "sonnet"
  }
}

{:ok, session} = ClaudeCode.start_link(agents: agents)

See Agents Guide for more details.

Team Settings

# From file path
{:ok, session} = ClaudeCode.start_link(
  settings: "/path/to/settings.json"
)

# From map (auto-encoded to JSON)
{:ok, session} = ClaudeCode.start_link(
  settings: %{
    "team_name" => "My Team",
    "preferences" => %{"theme" => "dark"}
  }
)

# Control setting sources
{:ok, session} = ClaudeCode.start_link(
  setting_sources: [:user, :project, :local]
)

Validation Errors

Invalid options raise descriptive errors:

{:ok, session} = ClaudeCode.start_link(timeout: "not a number")
# => ** (NimbleOptions.ValidationError) invalid value for :timeout option:
#       expected positive integer, got: "not a number"

Next Steps