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.
--stdio and --ws are mutually exclusive — you cannot use both at the same time.
How it works
- The daemon starts and waits for operations on stdin
- Send a
StartSessionoperation to initialize a session with your chosen model and provider - Send
UserInputoperations to submit prompts - Receive streaming events — thinking deltas, message deltas, tool calls, approvals — on stdout
- Respond to
TurnPauseevents withApprovalResponseto approve or deny tool calls - 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
| Headless | Server | |
|---|---|---|
| Lifetime | Single prompt, then exits | Long-lived, multiple interactions |
| Input | CLI argument or stdin pipe | Structured JSONL operations |
| Output | Formatted text (minimal/human/json) | Raw protocol events (JSONL) |
| Transport | N/A | Stdio (default) or WebSocket (--ws) |
| Sessions | Implicit — one per invocation | Explicit — client sends StartSession |
| Tool approval | Auto-approved (yolo implied) | Client must respond to TurnPause events |
CLI reference
| Flag | Description |
|---|---|
--stdio | Use JSONL over stdin/stdout (default) |
--ws <ADDR> | Serve the protocol over WebSocket |
The --prompt flag cannot be used with ante serve. Use UserInput operations instead.