Documentation
¶
Overview ¶
Package protocol implements bidirectional control message handling for the Claude CLI.
The protocol package provides a Controller that manages request/response correlation for control messages sent to and received from the Claude CLI. This enables interactive features like interruption, dynamic configuration changes, and hook callbacks.
The Controller handles:
- Sending control_request messages with unique IDs
- Receiving and correlating control_response messages
- Request timeout enforcement
- Handler registration for incoming requests from the CLI
Example usage:
transport := subprocess.NewCLITransport(log, "", options) transport.Start(ctx) controller := protocol.NewController(log, transport) controller.Start(ctx) // Send a request with timeout resp, err := controller.SendRequest(ctx, "interrupt", nil, 5*time.Second)
Index ¶
- Constants
- type AccountInfo
- type AgentInfo
- type AppliedSettings
- type AvailableModelInfo
- type CancelAsyncMessageResult
- type ContextAPIUsage
- type ContextAgent
- type ContextAttachmentBreakdown
- type ContextCategory
- type ContextDeferredBuiltinTool
- type ContextGridSquare
- type ContextMCPTool
- type ContextMemoryFile
- type ContextMessageBreakdown
- type ContextPromptSection
- type ContextSkillFrontmatter
- type ContextSkills
- type ContextSlashCommands
- type ContextSystemTool
- type ContextToolCallBreakdown
- type ContextUsage
- type ControlRequest
- type ControlResponse
- type Controller
- func (c *Controller) CancelAllInFlight()
- func (c *Controller) Done() <-chan struct{}
- func (c *Controller) FatalError() error
- func (c *Controller) Messages() <-chan map[string]any
- func (c *Controller) RegisterHandler(subtype string, handler RequestHandler)
- func (c *Controller) SendRequest(ctx context.Context, subtype string, payload map[string]any, ...) (*ControlResponse, error)
- func (c *Controller) SetFatalError(err error)
- func (c *Controller) Start(ctx context.Context) error
- func (c *Controller) Stop()
- type FastModeState
- type MCPSetServersResult
- type PluginInfo
- type ReloadPluginsResult
- type RequestHandler
- type RewindFilesResult
- type ServerInfo
- type Session
- func (s *Session) GetSDKMCPServer(name string) (mcp.ServerInstance, bool)
- func (s *Session) GetSDKMCPServerNames() []string
- func (s *Session) GetServerInfo() (*ServerInfo, error)
- func (s *Session) HandleCanUseTool(ctx context.Context, req *ControlRequest) (map[string]any, error)
- func (s *Session) HandleElicitation(ctx context.Context, req *ControlRequest) (map[string]any, error)
- func (s *Session) HandleHookCallback(ctx context.Context, req *ControlRequest) (map[string]any, error)
- func (s *Session) HandleMCPMessage(ctx context.Context, req *ControlRequest) (map[string]any, error)
- func (s *Session) Initialize(ctx context.Context) error
- func (s *Session) NeedsInitialization() bool
- func (s *Session) RegisterHandlers()
- func (s *Session) RegisterMCPServers()
- type SettingsSnapshot
- type SettingsSource
- type SettingsSourceSnapshot
- type SlashCommand
- type Transport
Constants ¶
const ( // FastModeStateOff indicates fast mode is disabled. FastModeStateOff = fastmode.StateOff // FastModeStateCooldown indicates fast mode is cooling down. FastModeStateCooldown = fastmode.StateCooldown // FastModeStateOn indicates fast mode is enabled. FastModeStateOn = fastmode.StateOn )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AccountInfo ¶ added in v0.0.7
type AccountInfo struct {
Email *string `json:"email,omitempty"`
Organization *string `json:"organization,omitempty"`
SubscriptionType *string `json:"subscriptionType,omitempty"`
TokenSource *string `json:"tokenSource,omitempty"`
APIKeySource *string `json:"apiKeySource,omitempty"`
APIProvider *string `json:"apiProvider,omitempty"`
}
AccountInfo describes the authenticated CLI account.
type AgentInfo ¶ added in v0.0.7
type AgentInfo struct {
Name string `json:"name"`
Description string `json:"description"`
Model *string `json:"model,omitempty"`
}
AgentInfo describes an available agent returned by initialize or reload.
type AppliedSettings ¶ added in v0.0.7
type AppliedSettings struct {
Model string `json:"model"`
Effort *string `json:"effort,omitempty"`
}
AppliedSettings contains runtime-resolved applied settings.
type AvailableModelInfo ¶ added in v0.0.7
type AvailableModelInfo struct {
Value string `json:"value"`
DisplayName string `json:"displayName"`
Description string `json:"description"`
SupportsEffort *bool `json:"supportsEffort,omitempty"`
SupportedEffortLevels []string `json:"supportedEffortLevels,omitempty"`
SupportsAdaptiveThinking *bool `json:"supportsAdaptiveThinking,omitempty"`
SupportsFastMode *bool `json:"supportsFastMode,omitempty"`
SupportsAutoMode *bool `json:"supportsAutoMode,omitempty"`
}
AvailableModelInfo describes a model returned by the live CLI.
type CancelAsyncMessageResult ¶ added in v0.0.7
type CancelAsyncMessageResult struct {
Cancelled bool `json:"cancelled"`
}
CancelAsyncMessageResult contains the result of cancel_async_message.
type ContextAPIUsage ¶ added in v0.0.7
type ContextAPIUsage struct {
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
CacheCreationInputTokens int `json:"cache_creation_input_tokens"`
CacheReadInputTokens int `json:"cache_read_input_tokens"`
}
ContextAPIUsage describes API token usage within the current context.
type ContextAgent ¶ added in v0.0.7
type ContextAgent struct {
AgentType string `json:"agentType"`
Source string `json:"source"`
Tokens int `json:"tokens"`
}
ContextAgent describes an agent's token usage contribution.
type ContextAttachmentBreakdown ¶ added in v0.0.7
ContextAttachmentBreakdown describes token usage for one attachment type.
type ContextCategory ¶ added in v0.0.7
type ContextCategory struct {
Name string `json:"name"`
Tokens int `json:"tokens"`
Color string `json:"color"`
IsDeferred *bool `json:"isDeferred,omitempty"`
}
ContextCategory describes one context-usage category.
type ContextDeferredBuiltinTool ¶ added in v0.0.7
type ContextDeferredBuiltinTool struct {
Name string `json:"name"`
Tokens int `json:"tokens"`
IsLoaded bool `json:"isLoaded"`
}
ContextDeferredBuiltinTool describes a deferred builtin tool's token usage.
type ContextGridSquare ¶ added in v0.0.7
type ContextGridSquare struct {
Color string `json:"color"`
IsFilled bool `json:"isFilled"`
CategoryName string `json:"categoryName"`
Tokens int `json:"tokens"`
Percentage float64 `json:"percentage"`
SquareFullness float64 `json:"squareFullness"`
}
ContextGridSquare describes one cell in the rendered context grid.
type ContextMCPTool ¶ added in v0.0.7
type ContextMCPTool struct {
Name string `json:"name"`
ServerName string `json:"serverName"`
Tokens int `json:"tokens"`
IsLoaded *bool `json:"isLoaded,omitempty"`
}
ContextMCPTool describes an MCP tool's contribution to context usage.
type ContextMemoryFile ¶ added in v0.0.7
type ContextMemoryFile struct {
Path string `json:"path"`
Type string `json:"type"`
Tokens int `json:"tokens"`
}
ContextMemoryFile describes a memory file included in context usage.
type ContextMessageBreakdown ¶ added in v0.0.7
type ContextMessageBreakdown struct {
ToolCallTokens int `json:"toolCallTokens"`
ToolResultTokens int `json:"toolResultTokens"`
AttachmentTokens int `json:"attachmentTokens"`
AssistantMessageTokens int `json:"assistantMessageTokens"`
UserMessageTokens int `json:"userMessageTokens"`
ToolCallsByType []ContextToolCallBreakdown `json:"toolCallsByType"`
AttachmentsByType []ContextAttachmentBreakdown `json:"attachmentsByType"`
}
ContextMessageBreakdown describes message token usage by bucket.
type ContextPromptSection ¶ added in v0.0.7
ContextPromptSection describes a system prompt section's token usage.
type ContextSkillFrontmatter ¶ added in v0.0.7
type ContextSkillFrontmatter struct {
Name string `json:"name"`
Source string `json:"source"`
Tokens int `json:"tokens"`
}
ContextSkillFrontmatter describes one skill's token usage.
type ContextSkills ¶ added in v0.0.7
type ContextSkills struct {
TotalSkills int `json:"totalSkills"`
IncludedSkills int `json:"includedSkills"`
Tokens int `json:"tokens"`
SkillFrontmatter []ContextSkillFrontmatter `json:"skillFrontmatter"`
}
ContextSkills describes skill token usage.
type ContextSlashCommands ¶ added in v0.0.7
type ContextSlashCommands struct {
TotalCommands int `json:"totalCommands"`
IncludedCommands int `json:"includedCommands"`
Tokens int `json:"tokens"`
}
ContextSlashCommands describes slash command token usage.
type ContextSystemTool ¶ added in v0.0.7
ContextSystemTool describes a system tool's token usage.
type ContextToolCallBreakdown ¶ added in v0.0.7
type ContextToolCallBreakdown struct {
Name string `json:"name"`
CallTokens int `json:"callTokens"`
ResultTokens int `json:"resultTokens"`
}
ContextToolCallBreakdown describes token usage for one tool type.
type ContextUsage ¶ added in v0.0.7
type ContextUsage struct {
Categories []ContextCategory `json:"categories"`
TotalTokens int `json:"totalTokens"`
MaxTokens int `json:"maxTokens"`
RawMaxTokens int `json:"rawMaxTokens"`
Percentage float64 `json:"percentage"`
GridRows [][]ContextGridSquare `json:"gridRows"`
Model string `json:"model"`
MemoryFiles []ContextMemoryFile `json:"memoryFiles"`
MCPTools []ContextMCPTool `json:"mcpTools"`
DeferredBuiltinTools []ContextDeferredBuiltinTool `json:"deferredBuiltinTools,omitempty"`
SystemTools []ContextSystemTool `json:"systemTools,omitempty"`
SystemPromptSections []ContextPromptSection `json:"systemPromptSections,omitempty"`
Agents []ContextAgent `json:"agents"`
SlashCommands *ContextSlashCommands `json:"slashCommands,omitempty"`
Skills *ContextSkills `json:"skills,omitempty"`
AutoCompactThreshold *int `json:"autoCompactThreshold,omitempty"`
IsAutoCompactEnabled bool `json:"isAutoCompactEnabled"`
MessageBreakdown *ContextMessageBreakdown `json:"messageBreakdown,omitempty"`
APIUsage *ContextAPIUsage `json:"apiUsage,omitempty"`
}
ContextUsage is the typed payload returned by get_context_usage.
type ControlRequest ¶
type ControlRequest struct {
// Type is always "control_request"
Type string `json:"type"`
// RequestID uniquely identifies this request for response correlation
RequestID string `json:"request_id"` //nolint:tagliatelle // Claude CLI uses snake_case
// Request contains the nested request data including subtype and payload fields
Request map[string]any `json:"request"`
}
ControlRequest represents a control message sent to or received from the CLI.
Wire format:
{
"type": "control_request",
"request_id": "req_1_abc123",
"request": {
"subtype": "initialize",
"hooks": {...}
}
}
func (*ControlRequest) Subtype ¶
func (r *ControlRequest) Subtype() string
Subtype extracts the subtype from the nested request data.
type ControlResponse ¶
type ControlResponse struct {
// Type is always "control_response"
Type string `json:"type"`
// Response contains the nested response data including subtype, request_id,
// and either response (for success) or error (for error)
Response map[string]any `json:"response"`
}
ControlResponse represents a response to a control request.
Wire format for success:
{
"type": "control_response",
"response": {
"subtype": "success",
"request_id": "req_1_abc123",
"response": {...}
}
}
Wire format for error:
{
"type": "control_response",
"response": {
"subtype": "error",
"request_id": "req_1_abc123",
"error": "error message"
}
}
func (*ControlResponse) ErrorMessage ¶
func (r *ControlResponse) ErrorMessage() string
ErrorMessage extracts the error message from an error response.
func (*ControlResponse) IsError ¶
func (r *ControlResponse) IsError() bool
IsError checks if the response is an error response.
func (*ControlResponse) Payload ¶
func (r *ControlResponse) Payload() map[string]any
Payload extracts the response payload from a success response.
func (*ControlResponse) RequestID ¶
func (r *ControlResponse) RequestID() string
RequestID extracts the request_id from the nested response.
type Controller ¶
type Controller struct {
// contains filtered or unexported fields
}
Controller manages bidirectional control message communication with the Claude CLI.
The Controller handles:
- Sending control_request messages with unique request IDs
- Receiving and routing control_response messages to waiting requests
- Request timeout enforcement
- Handler registration for incoming control_request messages from the CLI
- Forwarding non-control messages to consumers via the Messages channel
The Controller must be started with Start() before use and manages its own goroutine for reading and routing messages.
func NewController ¶
func NewController(log *slog.Logger, transport Transport) *Controller
NewController creates a new protocol controller.
The logger will receive debug, info, warn, and error messages during protocol operations. The transport must be connected before calling Start().
func (*Controller) CancelAllInFlight ¶
func (c *Controller) CancelAllInFlight()
CancelAllInFlight cancels all in-flight operations. This is called during Stop() to ensure clean shutdown.
func (*Controller) Done ¶
func (c *Controller) Done() <-chan struct{}
Done returns a channel that is closed when the controller stops.
func (*Controller) FatalError ¶
func (c *Controller) FatalError() error
FatalError returns the fatal error if one occurred.
func (*Controller) Messages ¶
func (c *Controller) Messages() <-chan map[string]any
Messages returns a channel for receiving non-control messages.
The controller acts as a multiplexer: it reads all messages from the transport, handles control messages internally, and forwards regular messages through this channel. Consumers should read from this channel instead of calling transport.ReadMessages() directly.
The channel is closed when the controller stops or the transport closes. Use Done() and FatalError() to detect and retrieve transport errors.
func (*Controller) RegisterHandler ¶
func (c *Controller) RegisterHandler(subtype string, handler RequestHandler)
RegisterHandler registers a handler for incoming control requests.
When the CLI sends a control_request with the specified subtype, the handler will be invoked. The handler should return a payload map or an error.
Only one handler can be registered per subtype. Registering a handler for the same subtype twice will override the previous handler.
func (*Controller) SendRequest ¶
func (c *Controller) SendRequest( ctx context.Context, subtype string, payload map[string]any, timeout time.Duration, ) (*ControlResponse, error)
SendRequest sends a control request and waits for the response.
This method generates a unique request ID, sends the control_request, and blocks until a matching control_response is received or the timeout expires.
The timeout parameter specifies how long to wait for a response. Use context cancellation for overall operation timeout.
Returns an error if the request fails to send, times out, or the CLI returns an error response.
func (*Controller) SetFatalError ¶
func (c *Controller) SetFatalError(err error)
SetFatalError stores a fatal error and broadcasts to all waiters by closing done.
func (*Controller) Start ¶
func (c *Controller) Start(ctx context.Context) error
Start begins reading messages from the transport and routing control messages.
This method spawns a goroutine that reads from the transport and routes control_request and control_response messages. The goroutine stops when the context is cancelled or the transport is closed.
Start must be called before SendRequest or any handlers will work.
func (*Controller) Stop ¶
func (c *Controller) Stop()
Stop gracefully shuts down the controller.
This method signals the read loop to stop, cancels all in-flight operations, and waits for completion. It's safe to call Stop multiple times.
type FastModeState ¶ added in v0.0.7
FastModeState describes the current fast-mode state.
type MCPSetServersResult ¶ added in v0.0.7
type MCPSetServersResult struct {
Added []string `json:"added"`
Removed []string `json:"removed"`
Errors map[string]string `json:"errors"`
}
MCPSetServersResult is the typed result of mcp_set_servers.
type PluginInfo ¶ added in v0.0.7
type PluginInfo struct {
Name string `json:"name"`
Path string `json:"path"`
Source *string `json:"source,omitempty"`
}
PluginInfo describes a loaded plugin returned by reload_plugins.
type ReloadPluginsResult ¶ added in v0.0.7
type ReloadPluginsResult struct {
Commands []SlashCommand `json:"commands"`
Agents []AgentInfo `json:"agents"`
Plugins []PluginInfo `json:"plugins"`
MCPServers []mcp.ServerStatus `json:"mcpServers"`
ErrorCount int `json:"error_count"`
}
ReloadPluginsResult is the typed result of reload_plugins.
type RequestHandler ¶
RequestHandler is a function that handles incoming control requests from the CLI.
Handlers are registered for specific subtypes and are invoked when the CLI sends a control_request (e.g., for hook callbacks).
The handler should return a payload map or an error. The Controller automatically wraps the result in a ControlResponse.
type RewindFilesResult ¶ added in v0.0.7
type RewindFilesResult struct {
CanRewind bool `json:"canRewind"`
Error *string `json:"error,omitempty"`
FilesChanged []string `json:"filesChanged,omitempty"`
Insertions *int `json:"insertions,omitempty"`
Deletions *int `json:"deletions,omitempty"`
}
RewindFilesResult is the typed result of rewind_files.
type ServerInfo ¶ added in v0.0.7
type ServerInfo struct {
Commands []SlashCommand `json:"commands"`
Agents []AgentInfo `json:"agents"`
OutputStyle string `json:"output_style"`
AvailableOutputStyles []string `json:"available_output_styles"`
Models []AvailableModelInfo `json:"models"`
Account AccountInfo `json:"account"`
PID *int `json:"pid,omitempty"`
FastModeState *FastModeState `json:"fast_mode_state,omitempty"`
}
ServerInfo contains typed initialize metadata returned by the CLI.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session encapsulates protocol handling logic for hooks, MCP servers, and callbacks. It can be used by both Client and Query() to provide protocol support.
func NewSession ¶
NewSession creates a new Session for protocol handling.
func (*Session) GetSDKMCPServer ¶ added in v0.0.2
func (s *Session) GetSDKMCPServer(name string) (mcp.ServerInstance, bool)
GetSDKMCPServer returns a registered SDK MCP server by name.
func (*Session) GetSDKMCPServerNames ¶
GetSDKMCPServerNames returns the names of all registered in-process SDK MCP servers.
func (*Session) GetServerInfo ¶ added in v0.0.7
func (s *Session) GetServerInfo() (*ServerInfo, error)
GetServerInfo returns typed initialization metadata when available.
func (*Session) HandleCanUseTool ¶
func (s *Session) HandleCanUseTool( ctx context.Context, req *ControlRequest, ) (map[string]any, error)
HandleCanUseTool is called by CLI before tool use.
func (*Session) HandleElicitation ¶ added in v0.0.7
func (s *Session) HandleElicitation( ctx context.Context, req *ControlRequest, ) (map[string]any, error)
HandleElicitation handles direct CLI elicitation control requests.
func (*Session) HandleHookCallback ¶
func (s *Session) HandleHookCallback( ctx context.Context, req *ControlRequest, ) (map[string]any, error)
HandleHookCallback handles hook_callback control requests from the CLI. The CLI sends callback_id which we use to look up the registered callback.
func (*Session) HandleMCPMessage ¶
func (s *Session) HandleMCPMessage( ctx context.Context, req *ControlRequest, ) (map[string]any, error)
HandleMCPMessage handles unified mcp_message control requests from the CLI. Routes based on the JSONRPC method field: initialize, tools/list, tools/call, notifications/initialized.
func (*Session) Initialize ¶
Initialize sends the initialization control request to the CLI. It generates callback IDs for each hook and stores them for later lookup.
func (*Session) NeedsInitialization ¶
NeedsInitialization returns true if the session has callbacks that require initialization.
func (*Session) RegisterHandlers ¶
func (s *Session) RegisterHandlers()
RegisterHandlers registers protocol handlers for hooks, MCP, and tool permissions. This must be called before Initialize().
func (*Session) RegisterMCPServers ¶
func (s *Session) RegisterMCPServers()
RegisterMCPServers extracts and registers SDK MCP servers from options.
type SettingsSnapshot ¶ added in v0.0.7
type SettingsSnapshot struct {
Effective map[string]any `json:"effective"`
Sources []SettingsSourceSnapshot `json:"sources"`
Applied *AppliedSettings `json:"applied,omitempty"`
}
SettingsSnapshot contains effective and raw settings views.
type SettingsSource ¶ added in v0.0.7
type SettingsSource string
SettingsSource identifies one settings layer.
const ( // SettingsSourceUserSettings is the user settings layer. SettingsSourceUserSettings SettingsSource = "userSettings" // SettingsSourceProjectSettings is the project settings layer. SettingsSourceProjectSettings SettingsSource = "projectSettings" // SettingsSourceLocalSettings is the local settings layer. SettingsSourceLocalSettings SettingsSource = "localSettings" // SettingsSourceFlagSettings is the flag settings layer. SettingsSourceFlagSettings SettingsSource = "flagSettings" // SettingsSourcePolicySettings is the policy settings layer. SettingsSourcePolicySettings SettingsSource = "policySettings" )
type SettingsSourceSnapshot ¶ added in v0.0.7
type SettingsSourceSnapshot struct {
Source SettingsSource `json:"source"`
Settings map[string]any `json:"settings"`
}
SettingsSourceSnapshot contains one settings source and its raw settings.
type SlashCommand ¶ added in v0.0.7
type SlashCommand struct {
Name string `json:"name"`
Description string `json:"description"`
ArgumentHint string `json:"argumentHint"`
}
SlashCommand describes a slash command available to the session.
type Transport ¶
type Transport interface {
ReadMessages(ctx context.Context) (<-chan map[string]any, <-chan error)
SendMessage(ctx context.Context, data []byte) error
}
Transport defines the minimal interface needed for protocol operations.
This interface is satisfied by the CLITransport but allows for testing with mock transports.