Packages
claude_code
0.13.2
0.36.5
0.36.4
0.36.3
0.36.2
0.36.1
0.36.0
0.35.0
0.34.0
0.33.1
0.32.2
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.1
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Claude Agent SDK for Elixir – Build AI agents with Claude Code
Current section
Files
Jump to
Current section
Files
lib/claude_code/message/system_message.ex
defmodule ClaudeCode.Message.SystemMessage do
@moduledoc """
Represents a system initialization message from the Claude CLI.
System messages provide session setup information including available tools,
MCP servers, model, and permission mode.
For conversation compaction boundaries, use `ClaudeCode.Message.CompactBoundaryMessage`.
Matches the official SDK schema:
```
{
type: "system",
subtype: "init",
uuid: string,
apiKeySource: string,
cwd: string,
session_id: string,
tools: string[],
mcp_servers: { name: string, status: string }[],
model: string,
permissionMode: "default" | "acceptEdits" | "bypassPermissions" | "plan",
slashCommands: string[],
outputStyle: string
}
```
"""
alias ClaudeCode.Types
@enforce_keys [
:type,
:subtype,
:cwd,
:session_id,
:tools,
:mcp_servers,
:model,
:permission_mode,
:api_key_source
]
defstruct [
:type,
:subtype,
:uuid,
:cwd,
:session_id,
:tools,
:mcp_servers,
:model,
:permission_mode,
:api_key_source,
slash_commands: [],
output_style: "default"
]
@type t :: %__MODULE__{
type: :system,
subtype: :init,
uuid: String.t(),
cwd: String.t(),
session_id: Types.session_id(),
tools: [String.t()],
mcp_servers: [Types.mcp_server()],
model: String.t(),
permission_mode: Types.permission_mode(),
api_key_source: String.t(),
slash_commands: [String.t()],
output_style: String.t()
}
@doc """
Creates a new SystemMessage from JSON data.
## Examples
iex> SystemMessage.new(%{"type" => "system", "subtype" => "init", ...})
{:ok, %SystemMessage{...}}
iex> SystemMessage.new(%{"type" => "assistant"})
{:error, :invalid_message_type}
"""
@spec new(map()) :: {:ok, t()} | {:error, :invalid_message_type | {:missing_fields, [atom()]}}
def new(%{"type" => "system", "subtype" => "init"} = json) do
required_fields = [
"subtype",
"cwd",
"session_id",
"tools",
"mcp_servers",
"model",
"permissionMode",
"apiKeySource"
]
missing = Enum.filter(required_fields, &(not Map.has_key?(json, &1)))
if Enum.empty?(missing) do
message = %__MODULE__{
type: :system,
subtype: :init,
uuid: json["uuid"],
cwd: json["cwd"],
session_id: json["session_id"],
tools: json["tools"],
mcp_servers: parse_mcp_servers(json["mcp_servers"]),
model: json["model"],
permission_mode: parse_permission_mode(json["permissionMode"]),
api_key_source: json["apiKeySource"],
slash_commands: json["slashCommands"] || [],
output_style: json["outputStyle"] || "default"
}
{:ok, message}
else
{:error, {:missing_fields, Enum.map(missing, &String.to_atom/1)}}
end
end
def new(_), do: {:error, :invalid_message_type}
@doc """
Type guard to check if a value is a SystemMessage.
"""
@spec system_message?(any()) :: boolean()
def system_message?(%__MODULE__{type: :system}), do: true
def system_message?(_), do: false
defp parse_mcp_servers(servers) when is_list(servers) do
Enum.map(servers, fn server ->
%{
name: server["name"],
status: server["status"]
}
end)
end
defp parse_permission_mode("default"), do: :default
defp parse_permission_mode("acceptEdits"), do: :accept_edits
defp parse_permission_mode("bypassPermissions"), do: :bypass_permissions
defp parse_permission_mode("plan"), do: :plan
defp parse_permission_mode(_), do: :default
end