Agent Protocol¶
Both agents share the same transport and baseline command flow.
Socket paths¶
By default, agent sockets are derived from [app].runtime_dir:
- calendar agent:
<runtime_dir>/calendar-agent.sock - network agent:
<runtime_dir>/network-agent.sock
The default runtime directory is ~/.local/state/easybar/runtime. EASYBAR_RUNTIME_DIR can override it for all EasyBar processes.
EasyBar connects to those sockets directly.
Other local clients can also connect when they speak the same protocol.
Transport format¶
- newline-delimited JSON
- one request per line
- one response per line
Example:
{ "command": "ping" }
Common commands¶
Common commands include:
pingversionfetchsubscriberestart
version returns the running binary version and the shared EasyBar IPC protocol version:
{
"kind": "version",
"version": {
"appVersion": "0.4.0",
"protocolVersion": "1"
}
}
appVersion identifies the installed EasyBar build. protocolVersion identifies the internal JSON socket contract shared by the app and helper agents.
The calendar agent additionally supports:
create_eventupdate_eventdelete_event
Every response includes a kind field.
Common kinds include:
pongversionsubscribedrestartingerror
Error responses may include a stable errorCode in addition to the human-readable message. The
calendar agent uses invalid_request when a decoded request violates protocol limits, including its
maximum 366-day date range.
Request correlation¶
Calendar requests may include an optional requestID. The calendar agent echoes that identifier in
every direct response produced by the request, including subscribed, snapshot, success, and
error messages. Broadcast snapshots caused by EventKit changes are unsolicited and omit it.
EasyBar uses the identifier to reject delayed errors or snapshots from an older subscription. The client retains a FIFO fallback for older agents that do not yet echo request identifiers.
Typical behavior¶
pingreturns onepong, then closesversionreturns one version payload, then closesfetchreturns one data payload, then closessubscribereturns onesubscribed, returns one immediate data payload, then keeps the socket open for later pushesrestartreturns onerestartingacknowledgement, closes the request socket, then exits the agent process cleanly
Reconnect behavior¶
Transport failures such as an unavailable socket or an unexpected disconnect are transient. EasyBar reconnects long-lived subscriptions with bounded backoff.
A structured calendar invalid_request response is different: the connection worked, but retrying
the same subscription cannot succeed. EasyBar therefore:
- logs the rejection once;
- suspends reconnects for that exact request;
- retains the last valid snapshot; and
- resumes immediately when the request or socket configuration changes.
Other calendar errors follow their normal response handling and do not redefine the shared transport contract.
Agent restart flow¶
Both the calendar and network agents accept the following one-shot request:
{ "command": "restart" }
The agent confirms that it accepted the request before terminating:
{ "kind": "restarting" }
The full restart sequence is:
- The client sends
restartover the agent's Unix socket. - The agent sends
restartingso the client knows the request was accepted. - The agent exits through its normal AppKit shutdown path.
- The service supervisor starts a fresh agent process.
- EasyBar reconnects when the agent socket becomes available again.
Homebrew Services runs the separately installed agents through launchd with keep_alive, so an acknowledged exit leads to a fresh process. A manually launched standalone agent has no supervisor and therefore stays stopped after it exits.
Restart is available only while the agent socket is responsive. If the agent has already crashed or cannot answer requests, its service supervisor remains responsible for recovery.
The CLI exposes this operation as easybar agent restart calendar, easybar agent restart network, and easybar agent restart all. The combined command attempts both agents before reporting a partial failure with a nonzero exit status.
EasyBar command behavior¶
EasyBar keeps long-lived subscriptions open to the agents for normal runtime updates.
A manual refresh:
easybar refresh
- does not reload config
- does not restart agents
- triggers fresh reads and UI updates
A Lua restart:
easybar runtime restart
- restarts only Lua
- does not restart agents
A config reload:
easybar config reload
- reloads
config.toml - rebuilds runtime state
- recreates agent-backed subscriptions