rollbridge 0.1.2 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kaspernj
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -37,6 +37,7 @@ export default {
37
37
  proxy: {
38
38
  host: "127.0.0.1",
39
39
  port: 8182,
40
+ upstreamHost: "127.0.0.1",
40
41
  healthPath: "/ping",
41
42
  healthTimeoutMs: 30000,
42
43
  drainTimeoutMs: 60000,
@@ -85,6 +86,34 @@ chmod the control socket after it binds. This restricts which users can send
85
86
  control commands — useful when several deploy users share a group. When unset,
86
87
  the socket keeps the default permissions from the daemon's umask.
87
88
 
89
+ Set the proxied process's `health.startDelayMs` (default `0`) to wait that long
90
+ after the process starts before the first health probe — like a readiness
91
+ probe's initial delay, useful for apps with a known boot time. The delay runs
92
+ before the `health.timeoutMs` window begins.
93
+
94
+ Set a process's `restart` policy to control automatic restarts after a crash.
95
+ `restart.maxRestarts` caps how many restarts are allowed within `restart.windowMs`
96
+ before Rollbridge gives up and leaves the process `failed` (`maxRestarts: 0`
97
+ disables restarts entirely), while `restart.backoffFactor` — with an optional
98
+ `restart.maxDelayMs` cap — backs off the `restartDelayMs` delay on each successive
99
+ restart. With no `restart` block, a crashed process keeps restarting after
100
+ `restartDelayMs`, as before. See [`docs/config.md`](docs/config.md#processesrestart).
101
+
102
+ ```js
103
+ restart: {maxRestarts: 5, windowMs: 60000, backoffFactor: 2, maxDelayMs: 30000}
104
+ ```
105
+
106
+ Set `releaseRetention` to bound how many stopped (drained) releases the daemon
107
+ keeps in memory and reports in `status`. `keep` (default `10`) retains the most
108
+ recent stopped releases; `maxAgeMs` (default `0`, disabled) also prunes stopped
109
+ releases older than that many milliseconds. The active and draining releases are
110
+ never pruned. This is Rollbridge's own release records — your deploy tool still
111
+ owns cleaning up on-disk release directories.
112
+
113
+ ```js
114
+ releaseRetention: {keep: 5, maxAgeMs: 86400000}
115
+ ```
116
+
88
117
  A function export receives no arguments and lets you build the config at load
89
118
  time:
90
119
 
@@ -107,7 +136,7 @@ rendered when the process starts:
107
136
 
108
137
  - `{{releasePath}}`, `{{releaseId}}`, `{{revision}}`, `{{application}}`, `{{processId}}`
109
138
  - `{{port}}` — the port allocated to this process; `{{ports.<id>}}` — another process's allocated port
110
- - `{{proxy.host}}`, `{{proxy.port}}`
139
+ - `{{proxy.host}}`, `{{proxy.port}}`, `{{proxy.upstreamHost}}`
111
140
  - `{{env.<NAME>}}` — a variable from the daemon's own environment, e.g. `{{env.HOME}}`
112
141
 
113
142
  Referencing a placeholder with no value (including an unset `{{env.<NAME>}}`)
@@ -116,12 +145,115 @@ fails the process start with a clear error, so typos surface immediately.
116
145
  Production-ready examples live in `examples/`, including
117
146
  `examples/tensorbuzz.com.js` for the current TensorBuzz backend deployment.
118
147
 
148
+ See [`docs/velocious.md`](docs/velocious.md) for a Velocious deployment guide —
149
+ how Beacon, background-jobs-main, background-jobs-worker, and the web process map
150
+ to Rollbridge policies, with startup ordering and deploy behavior.
151
+
152
+ See [`docs/config.md`](docs/config.md) for the full config reference — every
153
+ field, its default, validation rules, template variables, and the environment
154
+ variables Rollbridge injects.
155
+
119
156
  ## Process Policies
120
157
 
121
- - `proxied`: the web/API process. Rollbridge forwards HTTP and WebSocket traffic to the active release and tracks connections for draining.
122
- - `companion`: a release-scoped support process. It starts with the release and stops after that release drains.
123
- - `singleton`: a one-at-a-time support process. Rollbridge stops the old singleton before starting the new one, so duplicate-unsafe schedulers or job dispatchers do not overlap.
124
- - `service`: a daemon-wide support process. Rollbridge starts it before release processes need it, leaves it running across deploys, and updates its restart template after a successful deploy.
158
+ Every process declares a `policy` that controls its lifecycle. Pick one per
159
+ process:
160
+
161
+ | You need | Use |
162
+ | --- | --- |
163
+ | The process that receives external HTTP/WebSocket traffic | `proxied` |
164
+ | A per-release helper tied to the release lifecycle | `companion` |
165
+ | Exactly one instance, never overlapping across deploys | `singleton` |
166
+ | A long-lived shared broker that survives deploys | `service` |
167
+
168
+ ### `proxied`
169
+
170
+ The web/API process — exactly one per config. Rollbridge forwards HTTP and
171
+ WebSocket traffic to the active release's proxied process and tracks open
172
+ connections so they can be drained on the next deploy. It must define a `port`
173
+ range, is health-checked before traffic switches to a new release, and is
174
+ auto-restarted while its release is active.
175
+
176
+ ```js
177
+ {
178
+ id: "web",
179
+ policy: "proxied",
180
+ cwd: "{{releasePath}}",
181
+ command: "npx velocious server --host 127.0.0.1 --port {{port}}",
182
+ port: {from: 18182, to: 18299},
183
+ health: {path: "/ping", timeoutMs: 30000}
184
+ }
185
+ ```
186
+
187
+ ### `companion`
188
+
189
+ A release-scoped helper (for example a background worker bound to one release).
190
+ It starts **before** the proxied process in the same release, so release-local
191
+ dependencies are ready before the health check, and it is auto-restarted while
192
+ its release is active. Each release gets its own companions; a release's
193
+ companions stop when that release is drained and retired after a newer release
194
+ takes over.
195
+
196
+ ```js
197
+ {
198
+ id: "background-jobs-worker",
199
+ policy: "companion",
200
+ cwd: "{{releasePath}}",
201
+ command: "npx velocious background-jobs-worker",
202
+ gracefulStopMs: 60000
203
+ }
204
+ ```
205
+
206
+ ### `singleton`
207
+
208
+ A one-at-a-time helper for duplicate-unsafe schedulers or job dispatchers. After
209
+ a new release becomes active, Rollbridge stops the old singleton and then starts
210
+ the new one, so two copies never run at once. Use it when running the old and
211
+ new copies simultaneously during a deploy would be unsafe.
212
+
213
+ ```js
214
+ {
215
+ id: "scheduler",
216
+ policy: "singleton",
217
+ cwd: "{{releasePath}}",
218
+ command: "npx velocious scheduler"
219
+ }
220
+ ```
221
+
222
+ ### `service`
223
+
224
+ A daemon-wide broker that should outlive individual releases — for example
225
+ Velocious Beacon or `background-jobs-main`. Rollbridge starts it once (before
226
+ release processes that depend on it), keeps it running across deploys, and gives
227
+ it a stable port that does not change between releases. After each successful
228
+ deploy its restart template is refreshed to the latest release, so if it crashes
229
+ it restarts from the newest good release. It keeps restarting until the daemon
230
+ shuts down.
231
+
232
+ ```js
233
+ {
234
+ id: "background-jobs-main",
235
+ policy: "service",
236
+ cwd: "{{releasePath}}",
237
+ command: "npx velocious background-jobs-main",
238
+ port: 7331
239
+ }
240
+ ```
241
+
242
+ ### Deploy ordering
243
+
244
+ On `rollbridge deploy`, Rollbridge:
245
+
246
+ 1. starts any `service` that is not already running;
247
+ 2. starts the new release's `companion`s, then its `proxied` process, and
248
+ health-checks the proxied process;
249
+ 3. switches new traffic to the new release;
250
+ 4. refreshes each `service`'s restart template to the new release;
251
+ 5. replaces `singleton`s (stops the old one, then starts the new one);
252
+ 6. drains the previous release's connections, then stops its `proxied` and
253
+ `companion` processes.
254
+
255
+ If the new release fails to start or health-check, the previous release stays
256
+ active and any service started during this deploy is rolled back.
125
257
 
126
258
  ## Commands
127
259
 
@@ -130,6 +262,14 @@ Production-ready examples live in `examples/`, including
130
262
  explicitly, but `rollbridge validate` (or any command) works with no flag when a
131
263
  `rollbridge.js` is present.
132
264
 
265
+ For machine-readable output, `deploy`, `status`, `stop`, `shutdown`, and
266
+ `ensure-daemon` already print JSON, and `validate`, `doctor`, and `logs` accept
267
+ a `--json` flag that switches their output to JSON (with the same exit codes),
268
+ so deploy tooling can parse results.
269
+
270
+ See [`docs/cli.md`](docs/cli.md) for the full per-command reference (every
271
+ option, default, output shape, and exit code).
272
+
133
273
  Validate a config without starting the daemon:
134
274
 
135
275
  ```bash
@@ -152,6 +292,30 @@ Found 2 configuration issues in rollbridge.js:
152
292
  Fix: Give each process a unique id; "web" is used more than once.
153
293
  ```
154
294
 
295
+ Check the environment before starting the daemon:
296
+
297
+ ```bash
298
+ rollbridge doctor --config rollbridge.js
299
+ ```
300
+
301
+ `doctor` validates the config and then probes the runtime environment, exiting
302
+ non-zero if any check fails (so deploy tooling can gate on it):
303
+
304
+ ```text
305
+ ✓ config: valid: 4 processes, proxy on 127.0.0.1:8182
306
+ ✓ control socket: no daemon running; /tmp/rollbridge-ticket-server.sock is free to bind
307
+ ✓ control socket directory: /tmp is writable
308
+ ✓ proxy port: 127.0.0.1:8182 is available
309
+
310
+ All checks passed.
311
+ ```
312
+
313
+ A free control socket, a writable socket directory, and a bindable proxy port
314
+ pass. Because `rollbridge daemon` cannot bind a socket or port that is already
315
+ taken, doctor fails the relevant check when a Rollbridge daemon (or any other
316
+ process) is already listening on the control socket or holding the proxy port —
317
+ so a green `doctor` means a fresh daemon can actually start.
318
+
155
319
  Start the daemon:
156
320
 
157
321
  ```bash
@@ -182,12 +346,34 @@ Inspect state:
182
346
  rollbridge status --config rollbridge.js
183
347
  ```
184
348
 
349
+ `status` reports each managed process's `state`, `pid`, recent `logs`, last
350
+ `exitCode`/`exitSignal`, and — per process — its automatic-restart count
351
+ (`restarts`), last start time (`startedAt`), and current `uptimeMs` while
352
+ running.
353
+
354
+ Print the recent captured stdout/stderr per process (a one-shot snapshot of the
355
+ retained `outputLines`, not a live stream):
356
+
357
+ ```bash
358
+ rollbridge logs --config rollbridge.js
359
+ rollbridge logs --config rollbridge.js --process web
360
+ ```
361
+
185
362
  Stop the active release:
186
363
 
187
364
  ```bash
188
365
  rollbridge stop --config rollbridge.js
189
366
  ```
190
367
 
368
+ Restart non-proxied processes in place — all of them, one by id, or a policy
369
+ group (the proxied process is never restarted; use `deploy` for that):
370
+
371
+ ```bash
372
+ rollbridge restart --config rollbridge.js # all non-proxied processes
373
+ rollbridge restart --config rollbridge.js --process background-jobs-worker
374
+ rollbridge restart --config rollbridge.js --policy companion
375
+ ```
376
+
191
377
  Shut down the daemon and managed processes:
192
378
 
193
379
  ```bash
@@ -210,6 +396,10 @@ location / {
210
396
  }
211
397
  ```
212
398
 
399
+ See [`docs/nginx.md`](docs/nginx.md) for the full guide — WebSocket upgrade
400
+ headers, timeouts for long-lived connections, forwarded headers, and common
401
+ failure modes (502/503, dropped WebSockets).
402
+
213
403
  ## Running under systemd
214
404
 
215
405
  Run the long-lived daemon as a systemd service so it starts on boot and is
@@ -246,6 +436,8 @@ absolute CLI path for `ExecStart`.
246
436
 
247
437
  Run migrations before `rollbridge deploy`, and keep migrations backwards-compatible while old and new web releases overlap. For stable local brokers such as Velocious Beacon or `background-jobs-main`, use `service` when the process should survive deploys and restart from the latest successful release if it crashes.
248
438
 
439
+ See [`docs/deploy-recipes.md`](docs/deploy-recipes.md) for ready-to-use shell, CI, and Capistrano recipes that drive Rollbridge through its CLI, and [`docs/troubleshooting.md`](docs/troubleshooting.md) for diagnosing health-check failures, port conflicts, stale sockets, crash loops, and stuck draining releases.
440
+
249
441
  ## Releasing
250
442
 
251
443
  Maintainers can publish a patch release from the latest default branch:
@@ -253,3 +445,11 @@ Maintainers can publish a patch release from the latest default branch:
253
445
  ```bash
254
446
  npm run release:patch
255
447
  ```
448
+
449
+ The release script owns the package version bump, lockfile update, default-branch
450
+ commit, push, and npm publish. Do not run `npm version` manually before running
451
+ it.
452
+
453
+ ## License
454
+
455
+ Rollbridge is released under the [MIT License](LICENSE).
package/TODO.md CHANGED
@@ -26,9 +26,9 @@ This roadmap tracks planned Rollbridge features and documentation. Rollbridge sh
26
26
  - [ ] Restart memory-heavy workers gracefully when possible, with a forced stop timeout.
27
27
  - [ ] Add tests with a fixture process that allocates memory above the configured limit.
28
28
  - [ ] Worker auto-restart and restart policy controls.
29
- - [ ] Add config for max restarts, restart window, exponential backoff, and disabled restart behavior.
29
+ - [x] Add config for max restarts, restart window, exponential backoff, and disabled restart behavior (per-process `restart` policy).
30
30
  - [ ] Distinguish crash restarts, deploy replacements, manual restarts, and memory restarts in status/events.
31
- - [ ] Add a `restart` CLI command for a single process, a policy group, or all non-proxied workers.
31
+ - [x] Add a `restart` CLI command for a single process, a policy group, or all non-proxied workers.
32
32
  - [ ] Keep restart behavior safe for job workers by using lifecycle hooks before termination.
33
33
  - [ ] Graceful job-worker lifecycle.
34
34
  - [ ] Add generic lifecycle hooks such as `quietCommand`, `drainCommand`, `drainTimeoutMs`, and `stopCommand`.
@@ -52,13 +52,16 @@ This roadmap tracks planned Rollbridge features and documentation. Rollbridge sh
52
52
  - [ ] Document migration constraints for rollback.
53
53
  - [ ] Observability and diagnostics.
54
54
  - [ ] Add structured event history for deploys, switches, stops, crashes, memory restarts, and failed commands.
55
- - [ ] Add restart counters, uptime, exit reasons, memory stats, and child-process-tree details to status.
56
- - [ ] Add `logs` and `events` CLI commands.
55
+ - [x] Add restart counters and uptime to status (exit reasons already reported via `exitCode`/`exitSignal`/`state`).
56
+ - [ ] Add memory stats and child-process-tree details to status (with memory supervision).
57
+ - [x] Add a `logs` CLI command (recent per-process output from status).
58
+ - [ ] Add an `events` CLI command (after structured event history lands).
57
59
  - [ ] Add optional file logging with rotation guidance.
58
- - [ ] Add machine-readable JSON output flags for all CLI commands.
60
+ - [x] Add machine-readable JSON output for all CLI commands (data commands print JSON; `validate`/`doctor`/`logs` take `--json`).
59
61
  - [ ] Config validation and doctoring.
60
62
  - [x] Add `validate` to parse config and report all config errors without starting the daemon.
61
- - [ ] Add `doctor` to check control socket reachability, proxy port availability, process commands, release path, and writable log/state paths.
63
+ - [x] Add `doctor` to check config validity, control socket reachability, proxy port availability, and control-socket directory writability.
64
+ - [ ] Extend `doctor` with process-command, release-path, and log/state-path checks once those are resolvable (rendered templates, persisted state).
62
65
  - [x] Validate duplicate process IDs, missing ports on proxied processes, invalid ranges, and the single-proxied-process policy rule.
63
66
  - [ ] Validate unsupported lifecycle-hook combinations once worker lifecycle hooks land.
64
67
  - [x] Include example fixes in validation output.
@@ -68,30 +71,30 @@ This roadmap tracks planned Rollbridge features and documentation. Rollbridge sh
68
71
  - [x] Add a control-socket permission option (`control.mode`) for shared deploy users.
69
72
  - [ ] Add control-socket owner/group options for shared deploy users (needs name-to-id resolution).
70
73
  - [x] Make stale control socket diagnostics clearer when another daemon is still alive.
71
- - [ ] Add old-release cleanup policies by age, count, and stopped state.
74
+ - [x] Add old-release cleanup policies by age, count, and stopped state (`releaseRetention`).
72
75
  - [x] Add port allocation diagnostics when a range is exhausted.
73
- - [ ] Add optional startup command timeout before health checks begin.
76
+ - [x] Add an optional startup delay (`health.startDelayMs`) before health checks begin.
74
77
  - [x] Add process output retention config instead of a fixed recent-log count.
75
78
  - [x] Add environment variable interpolation from the daemon environment.
76
79
  - [x] Add `--config` default lookup resolving to `rollbridge.js` when no path is given.
77
80
  - [ ] Add shell completion generation for common shells.
78
- - [ ] Add npm package metadata such as repository, license, bugs, and homepage.
81
+ - [x] Add npm package metadata such as repository, license, bugs, and homepage.
79
82
  - [x] Add systemd service examples for the Rollbridge daemon.
80
83
  - [x] Add tests for malformed control socket JSON and unknown control commands.
81
- - [ ] Add tests for duplicate IDs and singleton replacement failure behavior.
84
+ - [x] Add tests for duplicate IDs and singleton replacement failure behavior.
82
85
  - [x] Add tests for proxy behavior when the active release exits unexpectedly.
83
86
 
84
87
  ## Documentation TODO
85
88
 
86
- - [ ] Write a full config reference covering every field, default, and template variable.
87
- - [ ] Write a CLI reference for `daemon`, `ensure-daemon`, `deploy`, `status`, `stop`, `shutdown`, and future commands.
88
- - [ ] Expand process policy docs with deployment examples for `proxied`, `companion`, `singleton`, and `service`.
89
+ - [x] Write a full config reference covering every field, default, and template variable (`docs/config.md`).
90
+ - [x] Write a CLI reference for `daemon`, `ensure-daemon`, `deploy`, `status`, `stop`, `shutdown`, and future commands (`docs/cli.md`).
91
+ - [x] Expand process policy docs with deployment examples for `proxied`, `companion`, `singleton`, and `service`.
89
92
  - [ ] Document memory checks and auto-restart behavior after the feature lands.
90
93
  - [ ] Document worker lifecycle hooks and safe background-job deployment patterns after the feature lands.
91
- - [ ] Add a Velocious deployment guide with Beacon, background-jobs-main, background-jobs-worker, and web process examples.
92
- - [ ] Add an Nginx guide with WebSocket headers, timeouts, and common failure modes.
93
- - [ ] Add deploy-tool recipes that call Rollbridge CLI commands directly.
94
- - [ ] Add a Capistrano recipe showing shell commands only; do not add a Capistrano plugin or Rollbridge-specific Capistrano tasks.
94
+ - [x] Add a Velocious deployment guide with Beacon, background-jobs-main, background-jobs-worker, and web process examples (`docs/velocious.md`).
95
+ - [x] Add an Nginx guide with WebSocket headers, timeouts, and common failure modes (`docs/nginx.md`).
96
+ - [x] Add deploy-tool recipes that call Rollbridge CLI commands directly (`docs/deploy-recipes.md`).
97
+ - [x] Add a Capistrano recipe showing shell commands only; do not add a Capistrano plugin or Rollbridge-specific Capistrano tasks (`docs/deploy-recipes.md`).
95
98
  - [ ] Add a TensorBuzz-specific runbook for current production ports, external services, deploy ordering, and rollback constraints.
96
- - [ ] Add troubleshooting docs for health-check failures, port conflicts, stale sockets, crash loops, and stuck draining releases.
99
+ - [x] Add troubleshooting docs for health-check failures, port conflicts, stale sockets, crash loops, and stuck draining releases (`docs/troubleshooting.md`).
97
100
  - [ ] Add a release checklist for maintainers using `npm run release:patch`.
package/docs/cli.md ADDED
@@ -0,0 +1,174 @@
1
+ # Rollbridge CLI reference
2
+
3
+ ```
4
+ rollbridge <command> [options]
5
+ ```
6
+
7
+ This reference covers every current command. See the README for config and
8
+ process-policy details.
9
+
10
+ ## Global behavior
11
+
12
+ - **`-c, --config <path>`** is accepted by every command and is optional. When
13
+ omitted, Rollbridge loads `rollbridge.js` from the current directory (a
14
+ JavaScript module that `export default`s the config object or a function
15
+ returning it).
16
+ - Commands that talk to a running daemon — `deploy`, `status`, `stop`,
17
+ `shutdown`, and `logs` — connect to the control socket (`control.path`). They
18
+ fail with an error if no daemon is listening; start one first with
19
+ `rollbridge daemon` or `rollbridge deploy --ensure-daemon`.
20
+ - `validate`, `doctor`, and `logs` accept `--json` for machine-readable output.
21
+ `deploy`, `status`, `stop`, `shutdown`, and `ensure-daemon` always print JSON.
22
+
23
+ ## `daemon`
24
+
25
+ ```
26
+ rollbridge daemon [--config <path>]
27
+ ```
28
+
29
+ Runs the supervisor in the foreground: binds the stable proxy port and the
30
+ control socket and stays running. On `SIGINT`/`SIGTERM` it stops its managed
31
+ processes, closes the servers, removes the control socket, and exits `0`.
32
+ Structured JSON log lines are written to stdout. Run it under a process manager
33
+ such as systemd (see `examples/rollbridge.service`).
34
+
35
+ ## `ensure-daemon`
36
+
37
+ ```
38
+ rollbridge ensure-daemon [--config <path>]
39
+ [--daemon-log-path <path>]
40
+ [--daemon-pid-path <path>]
41
+ [--daemon-start-timeout-ms <ms>]
42
+ ```
43
+
44
+ Starts the daemon as a detached process **only if** the control socket is not
45
+ already accepting commands, waits until it responds, then prints the daemon
46
+ status JSON. Idempotent — safe to call before every deploy.
47
+
48
+ - `--daemon-log-path <path>` — file the detached daemon's stdout/stderr is
49
+ appended to. Default: `/tmp/rollbridge-<application>.log`.
50
+ - `--daemon-pid-path <path>` — file the detached daemon's PID is written to.
51
+ Default: `/tmp/rollbridge-<application>.pid`.
52
+ - `--daemon-start-timeout-ms <ms>` — how long to wait for the daemon to accept
53
+ control commands before failing. Default: `10000`.
54
+
55
+ ## `deploy`
56
+
57
+ ```
58
+ rollbridge deploy --release-path <path>
59
+ [--config <path>]
60
+ [--release-id <id>]
61
+ [--revision <sha>]
62
+ [--ensure-daemon]
63
+ [--daemon-log-path <path>]
64
+ [--daemon-pid-path <path>]
65
+ [--daemon-start-timeout-ms <ms>]
66
+ ```
67
+
68
+ Starts the prepared release, health-checks the proxied process, switches new
69
+ traffic to it, then drains and stops the previous release. Prints
70
+ `{"status": "success", "activeReleaseId": "...", "previousReleaseId": "..."}`.
71
+ If the new release fails to start or health-check, the previous release stays
72
+ active and the command errors.
73
+
74
+ - `--release-path <path>` (**required**) — path to the prepared release
75
+ directory; available to process templates as `{{releasePath}}`.
76
+ - `--release-id <id>` — identifier for the release. Defaults to `--revision`,
77
+ or a timestamp when neither is given.
78
+ - `--revision <sha>` — VCS revision; available as `{{revision}}`.
79
+ - `--ensure-daemon` — start the daemon first if it isn't running (honors the
80
+ same `--daemon-*` options as `ensure-daemon`).
81
+
82
+ ## `status`
83
+
84
+ ```
85
+ rollbridge status [--config <path>]
86
+ ```
87
+
88
+ Prints the daemon status JSON: the active release id, the proxy address, and —
89
+ per release, service, and singleton process — its `state`, `pid`, automatic
90
+ `restarts`, `startedAt`, `uptimeMs`, last `exitCode`/`exitSignal`, and recent
91
+ `logs`.
92
+
93
+ ## `stop`
94
+
95
+ ```
96
+ rollbridge stop [--config <path>] [--release-id <id>]
97
+ ```
98
+
99
+ Stops the active release (or the release named by `--release-id`) and prints the
100
+ updated status JSON. With no active release, the proxy answers `503` until the
101
+ next deploy.
102
+
103
+ ## `restart`
104
+
105
+ ```
106
+ rollbridge restart [--config <path>] [--process <id>] [--policy <policy>]
107
+ ```
108
+
109
+ Restarts **non-proxied** processes and prints `{"restarted": [<ids>]}`. Like
110
+ `systemctl restart`, a running process is bounced (stop, then start) and a
111
+ crashed or stopped one is revived — so this is also how you bring back a process
112
+ that exhausted its `restart` budget (see [`config.md`](config.md#processesrestart)).
113
+ Selectors:
114
+
115
+ - no selector — restart every non-proxied process (companions, singletons, and services);
116
+ - `--process <id>` — restart only that process;
117
+ - `--policy <companion|singleton|service>` — restart only processes with that policy.
118
+
119
+ The proxied process is never restarted in place — that would drop traffic.
120
+ Targeting it (by id or `--policy proxied`) is an error; use `rollbridge deploy`
121
+ for a zero-downtime replacement. `--process <id>` with an id that is not a
122
+ managed process (unknown, or a companion with no active release) is also an
123
+ error. Restarting a `service` bounces a shared broker (for example Velocious
124
+ Beacon), which briefly disrupts every process that depends on it.
125
+
126
+ ## `shutdown`
127
+
128
+ ```
129
+ rollbridge shutdown [--config <path>]
130
+ ```
131
+
132
+ Stops all managed processes (services, singletons, and releases), closes the
133
+ proxy and control socket, removes the socket file, and prints
134
+ `{"status": "success", "message": "shutdown"}`.
135
+
136
+ ## `validate`
137
+
138
+ ```
139
+ rollbridge validate [--config <path>] [--json]
140
+ ```
141
+
142
+ Parses and validates the config without starting the daemon, reporting every
143
+ issue with an example fix. Exits `1` when issues are found. With `--json`, prints
144
+ `{"config": {...} | null, "issues": [{"message", "fix"}], "path", "valid"}`.
145
+
146
+ ## `doctor`
147
+
148
+ ```
149
+ rollbridge doctor [--config <path>] [--json]
150
+ ```
151
+
152
+ Validates the config, then probes the environment: whether a daemon already
153
+ holds the control socket, whether the control socket's directory is writable,
154
+ and whether the proxy port can be bound. Exits `1` when any check fails (so a
155
+ green `doctor` means a fresh daemon can start). With `--json`, prints
156
+ `{"checks": [{"name", "ok", "detail"}], "ok"}`.
157
+
158
+ ## `logs`
159
+
160
+ ```
161
+ rollbridge logs [--config <path>] [--process <id>] [--json]
162
+ ```
163
+
164
+ Prints the recent stdout/stderr retained per managed process — a one-shot
165
+ snapshot of each process's `outputLines`, not a live stream. `--process <id>`
166
+ limits output to one process. With `--json`, prints
167
+ `[{"id", "source", "logs": [{"at", "line", "stream"}]}]`.
168
+
169
+ ## Exit codes
170
+
171
+ - `0` — success.
172
+ - `1` — `validate`/`doctor` found problems, or `--config` could not be resolved.
173
+ - non-zero (with an error message) — a daemon command could not reach the daemon,
174
+ or the daemon returned an error.