protocol

package
v0.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 10, 2026 License: GPL-3.0 Imports: 22 Imported by: 0

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

View Source
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

type ContextAttachmentBreakdown struct {
	Name   string `json:"name"`
	Tokens int    `json:"tokens"`
}

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

type ContextPromptSection struct {
	Name   string `json:"name"`
	Tokens int    `json:"tokens"`
}

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

type ContextSystemTool struct {
	Name   string `json:"name"`
	Tokens int    `json:"tokens"`
}

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

type FastModeState = fastmode.State

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

type RequestHandler func(ctx context.Context, req *ControlRequest) (map[string]any, error)

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

func NewSession(
	log *slog.Logger,
	controller *Controller,
	options *config.Options,
) *Session

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

func (s *Session) GetSDKMCPServerNames() []string

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

func (s *Session) Initialize(ctx context.Context) error

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

func (s *Session) NeedsInitialization() bool

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL