Transport
Overview
The transport layer handles the low-level communication between the client and the agent process. All transports implement the abstract ACP::Transport base class using newline-delimited JSON over stdio.
ACP::Transport (Abstract Base)
#send
transport.send(message : Hash) : Nil
Sends a JSON-RPC message to the agent.
#receive
transport.receive : JSON::Any?
Receives the next message from the agent. Blocks until a message is available. Returns nil if the transport is closed.
#close
transport.close : Nil
Closes the transport.
#closed?
transport.closed? : Bool
Returns whether the transport is closed.
ACP::StdioTransport
Communicates over existing IO pairs using newline-delimited JSON.
Constructor
ACP::StdioTransport.new(
reader : IO,
writer : IO,
buffer_size : Int32 = 256
)
| Parameter | Type | Default | Description |
|---|---|---|---|
reader |
IO |
-- | IO to read agent messages from |
writer |
IO |
-- | IO to write client messages to |
buffer_size |
Int32 |
256 |
Internal channel buffer size |
#receive(timeout)
transport.receive(timeout : Time::Span) : JSON::Any?
Receives a message with a timeout. Returns nil if no message arrives within the specified duration.
The
StdioTransportspawns a background reader fiber that continuously reads from the IO and pushes parsed JSON messages to a buffered channel.
ACP::ProcessTransport
Spawns a child process and communicates over its stdin/stdout.
Constructor
ACP::ProcessTransport.new(
command : String,
args : Array(String) = [] of String,
env : Hash(String, String)? = nil,
chdir : String? = nil,
stderr : IO? = nil,
buffer_size : Int32 = 256
)
| Parameter | Type | Default | Description |
|---|---|---|---|
command |
String |
-- | Command to spawn |
args |
Array(String) |
[] |
Command arguments |
env |
Hash(String, String)? |
nil |
Environment variables |
chdir |
String? |
nil |
Working directory for the process |
stderr |
IO? |
nil |
IO for stderr output (e.g., STDERR) |
buffer_size |
Int32 |
256 |
Internal channel buffer size |
Process Management
transport.process # => Process (the spawned process)
transport.terminated? # => Bool (has the process exited?)
transport.wait # => Process::Status (blocks until process exits)
ACP.connect
Convenience function that creates a ProcessTransport, wraps it in a Client, and calls initialize_connection:
client = ACP.connect(
command : String,
args : Array(String) = [] of String,
client_name : String = "acp-crystal",
client_version : String = ACP::VERSION,
capabilities : ACP::Protocol::ClientCapabilities = ACP::Protocol::ClientCapabilities.new,
env : Hash(String, String)? = nil,
chdir : String? = nil
) : ACP::Client
Example:
client = ACP.connect(
"npx",
args: ["-y", "@anthropic-ai/claude-code", "--agent"],
client_name: "my-editor",
client_version: "1.0"
)