Skip to main content
Version: 1.2.0

ACP Drive Path

The ClaudusCode terminal is the interactive face of ClaudusBridge. The ACP drive path is its programmatic counterpart: a native C++ client, FClaudusAcpClient, that drives the very same embedded agent without a terminal, PTY, or TUI — straight C++ to agent, over the Agent Client Protocol.

Use it when you want to script the agent from your own editor tooling: kick off a prompt from a button, react to streamed assistant text and tool calls in C++, gate the agent's actions behind your own permission UI, or run the agent headless as part of an automated workflow.

How it differs from the terminal

ClaudusCode terminalACP drive path
TransportOS pseudo-terminal (ConPTY / forkpty)node cli-node.js --acp, JSON-RPC over stdio
SurfaceRendered TUI in a Slate tabDelegates + console commands; no UI
InputKeystrokes you typeSendPrompt(...) calls
OutputPainted terminal cellsOnAgentText / OnToolCall delegates
Use caseA human chatting with the agentC++ code driving the agent

Both launch the same bundled agent (see the Embedded Agent Bundle page) — the ACP path simply speaks a structured protocol instead of a terminal.

What FClaudusAcpClient does

FClaudusAcpClient (in the ClaudusCode module) spawns node "<Resources/Agent/cli-node.js>" --acp and:

  1. Speaks JSON-RPC 2.0, newline-delimited (ndjson), over the child process's stdio pipes.
  2. Performs the initialize + session/new handshake.
  3. Forwards your prompts as ACP prompt turns.
  4. Streams the agent's reply back through delegates: assistant text chunks (agent_message_chunk) and tool calls (tool_call).
  5. Answers the agent's permission requests according to the configured permission mode (or your own hook).

It is created, owned, and ticked on the game thread via the core ticker, and is not thread-safe — drive it from the game thread.

Configuration

Start() takes an FConfig:

FieldMeaningEmpty default
NodeExePathAbsolute path to the node executable.Resolve node from PATH.
AgentScriptPathAbsolute path to cli-node.js.The plugin's Resources/Agent/cli-node.js.
WorkingDirSession working directory.The Unreal project directory.
PermissionModeACP permission-mode seed (see below).The agent's own default.
ModelModel id (e.g. opus, claude-opus-4-8, gpt-5.5).The agent's default model.

Permission modes

The permission mode controls whether — and how — the agent is allowed to take actions (run tools, edit files, call MCP tools on the editor):

  • default — the safe mode. With no permission UI bound, the client denies tool-permission requests, so the agent can converse and read but cannot execute. Good for read-only exploration.
  • acceptEdits — auto-accept file edits.
  • bypassPermissions — let the agent act autonomously without prompting.
  • Additional seeds (dontAsk, plan, auto) are passed through to the agent.

For finer control, bind the PermissionRequest delegate. It receives the tool title and the offered ACP option ids (e.g. allow_always, allow, reject) and returns the chosen option id — or an empty string to cancel. If you do not bind it, the client auto-allows once. This is the hook to wire up your own in-editor "Allow / Deny" dialog.

Delegates

Subscribe to these multicast delegates on the client to react to the agent:

DelegateFires when
OnSessionReadyThe session is established and prompts run immediately.
OnAgentText(Text)A streamed chunk of assistant text arrives.
OnToolCall(Title, RawInputJson)The agent invokes a tool (human title + condensed JSON input).
OnTurnComplete(StopReason)The current prompt turn finished (end_turn, cancelled, error, …).
OnStopped(Reason)The client stopped (process exit, error, or Stop()).
PermissionRequest(Title, OptionIds)(return-value) The agent asks permission; you choose the option.

Prompts sent before OnSessionReady are queued and flushed once the session is up, so you can call SendPrompt immediately after Start without racing the handshake. CancelTurn() cancels the in-flight turn via an ACP session/cancel notification.

Console commands

The subsystem (UClaudusCodeSubsystem) exposes the ACP path through console commands, handy for trying it out from the editor's command line or for a quick test harness:

ClaudusCode.Acp.Start [permissionMode]
ClaudusCode.Acp.Prompt <your prompt text…>
ClaudusCode.Acp.Stop
  • ClaudusCode.Acp.Start — starts the agent. The optional argument is the permission mode; it defaults to default (deny tools — converse/read only). Pass bypassPermissions or acceptEdits to let it act.
  • ClaudusCode.Acp.Prompt — sends a prompt; remaining args are joined with spaces. Queued until the session is ready.
  • ClaudusCode.Acp.Stop — stops the agent and releases the process.

While running through these commands, streamed text, tool calls, turn completion, and stop events are surfaced to the Output Log (prefixed [ClaudusAcp]), so you can watch the agent work without any UI. A richer in-engine UI can subscribe to the same delegates.

Driving it from C++

UClaudusCodeSubsystem* Sub = GEditor->GetEditorSubsystem<UClaudusCodeSubsystem>();

// Start the agent with autonomous permissions.
Sub->StartAcpAgent(TEXT("bypassPermissions"));

// React to streamed output.
if (FClaudusAcpClient* Acp = Sub->GetAcpClient())
{
Acp->OnAgentText.AddLambda([](const FString& Text)
{
UE_LOG(LogTemp, Display, TEXT("Agent: %s"), *Text);
});
Acp->OnTurnComplete.AddLambda([](const FString& StopReason)
{
UE_LOG(LogTemp, Display, TEXT("Turn done: %s"), *StopReason);
});
}

// Prompt it (queued until the session is ready).
Sub->SendAcpPrompt(TEXT("List the actors in the current level and tidy up their names."));

Stop() (or StopAcpAgent()) cancels any active turn, closes the session, terminates the process, and releases resources; it is idempotent and safe to call on shutdown.

Verifying the agent responds to ACP

You can sanity-check the bundle's ACP support directly with your system Node, exactly as the plugin invokes it:

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":1,"clientCapabilities":{}}}' | node cli-node.js --acp

A successful run returns a JSON-RPC initialize result with the agent's capabilities. See the Embedded Agent Bundle page for where cli-node.js lives and what it requires.