Skip to main content

ante serve

Server mode runs Ante as a long-lived daemon that external clients can drive through a structured message protocol. This is ideal for building editor integrations, web UIs, or any programmatic workflow that needs to control Ante over time.

Basic usage

ante serve

This starts the daemon and bridges the JSONL protocol over stdin/stdout. The process stays alive until the client sends a Shutdown operation or closes stdin.

Stdio transport (default)

ante serve --stdio

The --stdio flag is optional — stdio is the default transport. The daemon reads OpMsg JSON objects from stdin and writes EventMsg JSON objects to stdout, one per line.

WebSocket transport

ante serve --ws 127.0.0.1:8080

The --ws flag starts a WebSocket server on the given address. Each connection gets its own daemon instance. The server loops accepting new connections until a client sends a Shutdown operation.

note

--stdio and --ws are mutually exclusive — you cannot use both at the same time.

How it works

  1. The daemon starts and waits for operations on stdin
  2. Send a StartSession operation to initialize a session with your chosen model and provider
  3. Send UserInput operations to submit prompts
  4. Receive streaming events — thinking deltas, message deltas, tool calls, approvals — on stdout
  5. Respond to TurnPause events with ApprovalResponse to approve or deny tool calls
  6. Send Shutdown (or close stdin) to gracefully stop the daemon

See the Protocol Reference for the complete message catalog and wire format.

Example session

# Start the daemon, sending JSONL to its stdin via a named pipe
mkfifo /tmp/ante-pipe
ante serve < /tmp/ante-pipe &
echo '{"op":{"StartSession":{"model":"claude-sonnet-4-5","provider":"anthropic","streaming":true}},"id":"op_001"}' > /tmp/ante-pipe
echo '{"op":{"UserInput":"what is 2+2"},"id":"op_002"}' > /tmp/ante-pipe

In practice, you'd spawn the process and write to its stdin directly. Here's a minimal Node.js example:

const { spawn } = require("child_process");

const ante = spawn("ante", ["serve"]);
let buffer = "";

ante.stdout.on("data", (chunk) => {
buffer += chunk.toString();
const lines = buffer.split("\n");
buffer = lines.pop();
for (const line of lines) {
if (!line.trim()) continue;
const event = JSON.parse(line);
console.log("Event:", event.event);
}
});

ante.stdin.write(JSON.stringify({
op: { StartSession: { model: "claude-sonnet-4-5", provider: "anthropic", streaming: true } },
id: "op_001"
}) + "\n");

ante.stdin.write(JSON.stringify({
op: { UserInput: "explain what this project does" },
id: "op_002"
}) + "\n");

Differences from headless mode

HeadlessServer
LifetimeSingle prompt, then exitsLong-lived, multiple interactions
InputCLI argument or stdin pipeStructured JSONL operations
OutputFormatted text (minimal/human/json)Raw protocol events (JSONL)
TransportN/AStdio (default) or WebSocket (--ws)
SessionsImplicit — one per invocationExplicit — client sends StartSession
Tool approvalAuto-approved (yolo implied)Client must respond to TurnPause events

CLI reference

FlagDescription
--stdioUse JSONL over stdin/stdout (default)
--ws <ADDR>Serve the protocol over WebSocket
note

The --prompt flag cannot be used with ante serve. Use UserInput operations instead.