Aude Code

AUDE-WIRE(7) Miscellaneous Information Manual AUDE-WIRE(7)

aude-wire — the remote-control protocol of aude

This page is for a person who writes a client. Sources/AudeWire and Sources/AudeValues define the protocol.

A connection starts with the Noise handshake ‘Noise_XX_25519_ChaChaPoly_SHA256’ with an empty prologue: the client sends ‘e’, the host ‘e, ee, s, es’, and the client ‘s, se’. A message is a 2-byte big-endian length and at most 65535 bytes.

A key's fingerprint is the SHA-256 of its 32-byte X25519 public key, in base64url with no padding.

A frame is one UTF-8 JSON object on one line, with these fields:

‘version’
the version, 21
‘type’
the type
‘id’
a lowercase UUID v4, or for ‘submission’, the id of the submission
‘timestamp’
the time of the sender, RFC 3339 with milliseconds
‘reply_to’
on an answer, the ‘id’ of the frame that it answers
‘body’
the fields of the type, when it has fields

A body of several kinds has one field, which names the kind. Ignore a field that you do not know.

The first frame of a client is ‘hello’:

‘client’
‘name’
‘since’
optional: the last ‘sequence’ that the client has, or 0 for the whole transcript
‘session’
optional: the session that the client expects
‘code’
optional: the code of a pairing URL, on the first connection

The host then sends ‘welcome’ with ‘aude_version’, ‘origin’, ‘record’, the record at the last entry, as ‘aude sessions --json’ prints it, and ‘backlog_count’, the number of ‘entry’ frames that follow: the transcript after ‘since’. Then come the new entries.

An ‘origin’ has ‘connection’, an id, and ‘name’. A line from this client has the ‘connection’ of ‘welcome.origin’.

hello host see HANDSHAKE
submission host ‘text’, one line, which is one turn; optional ‘budget’, in seconds
interrupt host none
request host see REQUESTS
ping, pong both none; ‘pong’ has ‘reply_to’
welcome client see HANDSHAKE
entry client one entry of the session, see ENTRIES
presence client ‘attached’ or ‘detached’, an ‘origin’
response client see REQUESTS
failure client see PROTOCOL FAILURES

An entry has ‘sequence’, ‘timestamp’ and ‘kind’. A transcript entry is the JSON entry of aude(1). The other kinds have their fields under a key with the name of the kind:

‘settings’
‘conversation’, ‘model’, ‘alias’, ‘effort’, ‘agent’, ‘context_tokens’, ‘branch’ and ‘choices’
‘status’
‘phase’, ‘queue’ and ‘last’; ‘phase’ is ‘starting’, ‘held’, ‘idle’, ‘exiting’ or ‘busy’, which has ‘submission’, ‘deadline’ and ‘is_thinking’
‘gate’
see GATE
‘settled’
‘submission’, ‘origin’ and ‘fate’: ‘answered’, ‘dropped’ or ‘ran’
‘ended’
‘stopped’, ‘refused’, ‘instructions_file’, ‘died’ or ‘unknown_model’
‘began, ‘bound’’
the identity, the process, the endpoint and the key fingerprint of a host

‘status’ is the host process; ‘work.state’ in the record is the work. Each ‘settings’ or ‘status’ replaces the last. Each submission gets one ‘settled’; only the client whose connection is in ‘origin’ shows it. ‘ended’ is the last frame before the host closes. A client words ‘settled’ and ‘ended’ as Sources/AudeValues/SessionWords.swift does. A client that loses the socket ends the connection itself.

‘gate’ tells the gate's finding, and holds no credential. It has ‘harness’ and ‘finding’: ‘ok’, ‘not_logged_in’, ‘api_key’, ‘other_login’, ‘timed_out’, ‘not_found’, ‘silent’ or ‘unreadable’. With ‘silent’, ‘exit’ holds the probe's ‘status’ or ‘signal’. No string that the harness printed crosses the wire.

A ‘request’ is one of:

‘sessions’
the record of each session of the machine
‘pair’
a pairing window; only the key of the host can ask
‘send’
‘session’, ‘text’ and optional ‘budget’, in seconds: what aude send does

The ‘response’ has the same ‘reply_to’ and is one of ‘sessions’, ‘window’ with ‘url’ and ‘expires’, ‘session’, the new record, ‘paired’ with ‘name’ and ‘fingerprint’, or ‘refused’, a line of aude(1) DIAGNOSTICS. A ‘pair’ gets two: the window, then ‘paired’ or ‘refused’ when the window closes.

A ‘failure’ has ‘code’, ‘detail’ and ‘is_fatal’, and ‘supported’, the versions, on ‘unsupported_version’. After a fatal failure, the host closes the connection.

bad_json no a bad line, an unknown type, a second ‘hello’, or a bad submission id
bad_json yes a line not complete 30 seconds after its first byte
line_too_long yes a line over 8 MiB
unsupported_version yes a different ‘version’
unauthorised yes a refused or revoked client, or no ‘hello’
busy yes too many connections
not_found yes a ‘session’ of a different session
internal yes the host cannot write the peer list peers.json

At ‘hello’, the host uses the first rule that matches:

  1. the key of the host from a different machine: refused, ‘peer not paired’
  2. the key of the host over loopback: accepted
  3. a key in peers.json: accepted
  4. a different key with the code of the open window: paired and accepted
  5. a wrong or late code: refused, ‘pairing code rejected’
  6. no code: refused, ‘peer not paired’

A refusal is a fatal ‘unauthorised’.

  • 8 connections, with those that have not sent ‘hello’.
  • 30 seconds to send ‘hello’.
  • The host sends ‘ping’ after 15 silent seconds, and closes the connection when no ‘pong’ comes in 30 seconds.
  • The host cleans ‘client.name’ and keeps 48 characters.

A ‘hello’ on a first connection:

{"body":{"client":{"name":"my phone"},"code":"<code>",
"since":0},"id":"<uuid>","timestamp":"<time>","type":"hello","version":21}

A ‘submission’ and the ‘entry’ that the session makes of it:

{"body":{"budget":300,"text":"hi"},"id":"<id>","timestamp":"<time>",
"type":"submission","version":21}
{"body":{"kind":"user","origin":{"connection":"<id>","name":"my phone"},
"sequence":7,"text":"hi","timestamp":"<time>"},"id":"<uuid>",
"timestamp":"<time>","type":"entry","version":21}

aude(1), aude-rc(7)

October 21, 2026 aude