Public beta — this package is versioned at
0.x; its API may change between minor versions.
The engine-agnostic wire layer spoken by every client of the Rush daemon (rushd):
- Frame taxonomy — five frame types:
0x01control-json,0x02log-stdout,0x03log-stderr,0x04stdin,0x05event. - Length-prefixed binary codec — a streaming serializer/deserializer that is lossless for arbitrary (including non-UTF-8) payloads and tolerant of arbitrarily split or coalesced chunks.
DAEMON_PROTOCOL_VERSION— the negotiated protocol version constant.- Version negotiation — a
hello/helloAckhandshake with a typedProtocolVersionMismatchErroron major-version mismatch. - Event contract — the
0x05frame payload envelope (currently a placeholder mirroring@rushstack/reporter'sIReporterEventEnvelope; to be replaced by a direct reference when the reporter package lands) plus namespacedrushd.*extension events. - Per-subscription verbosity — a pure filter applied at event serialization so each client receives its own verbosity subset without mutating shared engine state.
- Resolved phased-request contracts — engine-agnostic request, enabled-state selection, parsed built-in/custom command origin, and client-scoped result types for integrations that have already parsed a command and resolved it against a real warm operation graph.
- Final command result contract — one typed success, warning, failure, or abort outcome with the authoritative Rush-compatible exit code, delivered after request output drains.
- Interactive request contracts — request-tagged stdin frames preserve arbitrary bytes, while acknowledged raw-mode controls and typed terminal-policy results remain scoped to one request.
- Request admission contracts — resolved no-wait and bounded-timeout options, typed admission
failure codes, and capability-gated one-based queue-position control messages. A queue position
may carry the
restartReasonfor which the daemon restarts once the requests that the position counts finish, withscriptCount, how many of those requests run a rushx script, andrestartsForAnotherRequest, set when the restart is another request's: for a rushx script that waits for another request's restart, and for a request queued behind another request that waits for the rushx scripts to exit before the daemon restarts. AscriptCountwithout arestartReasonsays that the request waits for that many running rushx scripts to exit before it runs, because it restarts the daemon once it ends (a nativeinstallorupdate). A request queued behind it is toldnativeMutationinstead, which names that command incommandName.workspaceInputsChangednames the installation files or the files of Rush and its plugins that changed since the daemon started, or the Rush version that the request selects. Older daemons omit these fields, and clients ignore reason kinds they do not know. A queue position may instead carrynativeLockHolder(IDaemonNativeLockHolder) while the request waits for a Rush process that the daemon does not run to release the repository's lock: that process'spidandcommand, such asrush install, as far as the daemon can tell. Itspositionis then 1. A queue position may also carrycontinuingOperations(IDaemonContinuingOperations) while the request waits only for operations that earlier requests left running after their result, such as the independent operations of a failed build that returned early: how many of them still wait or run (count), and the names of the first few (names). Older clients ignore it. - Request lifecycle contracts — a validated presentation-free command envelope, cancellation, typed routing rejection/fallback, and one authoritative terminal result control. Command parsing and Rush action construction remain outside the protocol.
- Daemon lifecycle controls (0.6) — after a compatible
hello, a client can sendshutdownand receiveshutdownAckbefore connection closure. Clients must negotiate at leastDAEMON_LIFECYCLE_PROTOCOL_MINORbefore sending this control.pongcan also report the daemon's PID and resident memory in bytes; older peers may omit these fields. - Input lifecycle controls (0.7) —
supportsInputLifecyclenegotiatesstdinReadyandstdinEnd. The host grants the first write credit only after the request attaches its input destination, then grants another after each write drains. The client sends one bounded chunk per credit and EOF after all chunks. Empty data is never interpreted as EOF. Peers that did not negotiate the capability receive no new controls. - Invocation kind (0.8) - optional
invocationKind: "rush" | "rushx"selects the native parser independently ofcommandOrigin. Omission retains legacy Rush routing; custom workspace commands are never inferred to be package scripts. A Rushx client must negotiate at leastDAEMON_INVOCATION_KIND_PROTOCOL_MINORbefore submitting its request. Older peers could ignore the discriminator, so the client falls back beforerequestStartor input consumption. - Graph generation fencing (0.9) - graph snapshots carry an opaque
workspaceGenerationtoken. Mutation requests must echo it inexpectedWorkspaceGeneration; the server checks it under exclusive admission before touching operations. Tokens change on session or process replacement. Clients must negotiateDAEMON_GRAPH_GENERATION_PROTOCOL_MINORbefore mutation; an older server could otherwise ignore the reference. - Workspace restart (0.10) - native
install/updaterouting is capability-gated. A failure result may includeretryAfterRestart: trueonly when no execution or request IO occurred and an available successor was selected. It cannot coexist with cancellation, admission errors or operation results. Clients may retry once after attested predecessor ownership release, never on transport loss or an error string. The ordinary mutation result has no retry flag and drains before restart. A retry result may say why inrestartReason:installationChangednames the folder that was removed or replaced, andenvironmentChangednames the environment variables that differ from the daemon's, never their values. Each control, format, line separator or paragraph separator character of a name, such as a newline, ESC, U+2028 or a bidirectional override, and each backslash, is sent as a\xHHor\u{H…}escape, so that a client prints the names on one line. Clients ignore kinds they do not know. - Read-only workspace status - optional
pong.payload.workspacereports the provider generation, installed session token, graph existence and real warm accounting. An absent token means no session is installed; an absentwarmSetmeans no controller is attached, not zero memory. Warm status includes effective configuration, maintenance state/failure, retained/protected/watched projects, measured RSS, unmeasured runners, pressure and cleanup diagnostics. Child RSS is a last-completion sample, not a process-tree ceiling. Nested records and numeric fields are validated. Older pong shapes remain valid; this additive field does not change the 0.9 request, generation-fencing or retry contracts. While the daemon runs only operations that earlier requests left running after their result, the status also carries them ascontinuingOperations, in the same shape as a queue position's. - Keepalive (0.13) - a client may
pingwhile its request runs, to learn whether the daemon still responds, and gets apongas before. A daemon that is closing the session ignores apingrather than answering it with a protocolerror, which could reach the client ahead of the request's typed result. Clients must negotiateDAEMON_KEEPALIVE_PROTOCOL_MINORbefore they ping during a request. - Request started (0.14) - a client that negotiated
DAEMON_REQUEST_STARTED_PROTOCOL_MINORmay subscribe withsupportsRequestStarted: true. The daemon then sends itrequestStartedonce per request, when the request has left every queue and before anything from it is applied, so the notice precedes the request's output, events and terminal control. A daemon that exits after aqueuePositionbut beforerequestStartedhas not run the request, unless it exited abruptly just as a build joined an executing iteration, which starts the build's work before the notice is written. A daemon answers arequestStartedthat a client sends with a protocolerror. - Usage - a failure result for a command line that native Rush rejects as invalid may carry the command's
usage, which native Rush prints to stdout before the error. Older daemons omit it and older clients ignore it, so this additive field needs no minor.
Part of the Rush 6 / rushd re-architecture: microsoft/rushstack#5894.
- CHANGELOG.md - Find out what's new in the latest version
- API Reference
@rushstack/rush-daemon-protocol is part of the Rush Stack family of projects.