@sailorbridge/client 0.1.1

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,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,411 @@
1
+ # SailorBridge Client
2
+
3
+ Standalone Node/TypeScript client for SailorBridge: a relay HTTP client, a debug
4
+ CLI, a worker host runtime, and a tmux supervisor that owns one local Claude or
5
+ Codex agent process and reports monitor state to the relay. Host pairing login
6
+ stores a host-scoped relay key for subsequent local host commands.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install -g @sailorbridge/client
12
+ sailorbridge --help
13
+ ```
14
+
15
+ When installing globally on Linux or macOS, make sure your npm global prefix is
16
+ writable and its `bin` directory is on `PATH`. Prefer a user-owned Node install
17
+ from tools such as nvm/asdf over `sudo npm install -g`. Linux and macOS are the
18
+ supported targets; Windows packaging support is deferred.
19
+
20
+ For a managed host daemon, use the compiled single-binary path instead of a
21
+ Node-based global install. Build or download the native `sailorbridge` binary,
22
+ then log in once — `login` installs and starts the user service itself:
23
+
24
+ ```bash
25
+ bun run build:binary
26
+ ./bin/sailorbridge login
27
+ ./bin/sailorbridge host service status
28
+ ```
29
+
30
+ The service runs `sailorbridge host run` from the binary and reads the
31
+ host-scoped credential file. The unit/plist never embeds bearer tokens. After
32
+ the binary is built or installed, the managed host runtime does not require
33
+ Node, Bun, or Python on `PATH`.
34
+
35
+ ## Quickstart
36
+
37
+ Configure relay credentials:
38
+
39
+ ```bash
40
+ export SAILORBRIDGE_RELAY_URL=http://127.0.0.1:8765
41
+ export SAILORBRIDGE_TOKEN=...
42
+ export SAILORBRIDGE_AGENT_NAME=session_agent
43
+ export SAILORBRIDGE_CAPTAIN_ID=100
44
+ export SAILORBRIDGE_SESSION=session
45
+ export SAILORBRIDGE_HOST_ID="$(hostname)"
46
+ export SAILORBRIDGE_HOST_DISPLAY_NAME="$(hostname)"
47
+ ```
48
+
49
+ Or pair this machine through the product API:
50
+
51
+ ```bash
52
+ sailorbridge login
53
+ ```
54
+
55
+ `login` connects to `https://www.sailorbridge.com`. The command prints a short
56
+ host pairing code, waits for console/mobile approval, writes a 0600 credentials
57
+ file at `~/.sailorbridge/credentials.json`, and then installs and starts the
58
+ host service so the console can start workers and agents on this machine without
59
+ a second command.
60
+
61
+ Common commands:
62
+
63
+ ```bash
64
+ sailorbridge --help
65
+ sailorbridge login
66
+ sailorbridge workflow
67
+ sailorbridge mailbox peek "$SAILORBRIDGE_AGENT_NAME"
68
+ sailorbridge mailbox ack MESSAGE_ID --lease-token LEASE_TOKEN
69
+ printf '%s\n' 'hello $USER `date` $(pwd)' | sailorbridge mailbox send --to-agents ab_hand --tag BTW
70
+ sailorbridge mailbox send --to-roles reviewer --session ab --tag PLAN-REVIEW --body-file ./plan.txt
71
+ sailorbridge enrollment --session ab --agent ab_hand --roles operator
72
+ sailorbridge host register
73
+ sailorbridge host consume --once --dry-run-start
74
+ sailorbridge host service install --binary /opt/sailorbridge/bin/sailorbridge
75
+ sailorbridge host service status
76
+ sailorbridge worker serve --worker dev-1 --workdir "$PWD"
77
+ sailorbridge supervise --agent ab_hand --cli codex --cwd "$PWD" --i-own-this-agent
78
+ ```
79
+
80
+ The package ships only the built CLI/runtime files under `dist/src/` plus this
81
+ README. It deliberately does not publish `src/`, `tests/`, or `dist/tests/`.
82
+ Create a release tarball with `npm run pack:staged`; it stages the current build without
83
+ mutating the live `dist/` symlink.
84
+ Publish that staged tarball with `npm publish sailorbridge-client-<version>.tgz`;
85
+ do not run `npm publish` directly from this package.
86
+
87
+ ## Development
88
+
89
+ ```bash
90
+ bun install
91
+ bun run check
92
+ ```
93
+
94
+ Building requires Perl with `Fcntl::flock` (available on supported Linux and macOS hosts).
95
+ Builds retain immutable releases for at least one hour so in-flight readers remain
96
+ loadable; older non-current releases are reclaimed.
97
+
98
+ The package installs a `sailorbridge` bin after build:
99
+
100
+ ```bash
101
+ bun run build
102
+ node dist/src/cli.js workflow
103
+ node dist/src/cli.js mailbox peek "$SAILORBRIDGE_AGENT_NAME"
104
+ ```
105
+
106
+ Build a native standalone binary for the current host:
107
+
108
+ ```bash
109
+ bun run build:binary
110
+ ./bin/sailorbridge --help
111
+ ```
112
+
113
+ `build:binary` defaults to the native Bun compile target. Release automation can
114
+ pass `--target` through `scripts/build-binary.mjs` for the supported matrix:
115
+
116
+ ```text
117
+ linux-x64 -> bun-linux-x64
118
+ linux-arm64 -> bun-linux-arm64
119
+ darwin-x64 -> bun-darwin-x64
120
+ darwin-arm64 -> bun-darwin-arm64
121
+ ```
122
+
123
+ ## Configuration
124
+
125
+ Preferred environment:
126
+
127
+ ```bash
128
+ SAILORBRIDGE_RELAY_URL=http://127.0.0.1:8765
129
+ SAILORBRIDGE_TOKEN=...
130
+ SAILORBRIDGE_AGENT_NAME=session_agent
131
+ SAILORBRIDGE_CAPTAIN_ID=100
132
+ SAILORBRIDGE_SESSION=session
133
+ SAILORBRIDGE_HOST_ID=mac
134
+ SAILORBRIDGE_HOST_DISPLAY_NAME="Mac"
135
+ SAILORBRIDGE_HOST_WORKSPACES=~/project-a:~/project-b
136
+ SAILORBRIDGE_API_URL=https://www.sailorbridge.com
137
+ SAILORBRIDGE_CREDENTIALS_FILE=~/.sailorbridge/credentials.json
138
+ SAILORBRIDGE_WORKER_NAME=dev-1
139
+ SAILORBRIDGE_WORKDIR=~/sailorbridge-workdir
140
+ SAILORBRIDGE_MAX_CONCURRENCY=1
141
+ ```
142
+
143
+ `SAILORBRIDGE_CAPTAIN_ID` is optional for current descriptors but, when present,
144
+ must be a numeric string. It is diagnostic identity metadata; routing still uses
145
+ the short `SAILORBRIDGE_AGENT_NAME`.
146
+
147
+ `SAILORBRIDGE_HOST_ID` and `SAILORBRIDGE_HOST_DISPLAY_NAME` identify the
148
+ captain-scoped local host for Tier 6 console start-request polling. When omitted,
149
+ host commands default both values from the OS hostname.
150
+ `SAILORBRIDGE_HOST_WORKSPACES` is an explicit opt-in inventory list for host
151
+ daemon reporting, split by the platform path delimiter (`:` on Linux/macOS). The
152
+ daemon reports only those declared git workspaces, including `remote.origin.url`
153
+ and the current branch, so the console can queue an isolated clone from that
154
+ origin. It does not scan home directories.
155
+
156
+ Every 6 hours the host daemon also runs a scratch sweep over each declared
157
+ workspace, reaping `<root>/.agent/tmp/` (a git-ignored scratch directory): it
158
+ deletes git-untracked files older than 7 days, then evicts oldest-first until the
159
+ directory total is under 512 MiB. It only ever touches untracked files inside that
160
+ directory, never follows symlinks, and skips (with a log) any workspace whose
161
+ `.agent/tmp/` resolves out of bounds or is not a git repository. Set
162
+ `SAILORBRIDGE_SCRATCH_SWEEP_ENABLED=0` (or `false`/`no`/`off`) to disable it;
163
+ it is on by default.
164
+
165
+ `sailorbridge worker serve` runs the TypeScript host worker against the relay
166
+ without importing the Python worker package. It registers the configured worker
167
+ name, long-polls `/pull`, executes jobs inside `SAILORBRIDGE_WORKDIR`, posts
168
+ results with the relay lease token, and streams stdout/stderr for stream jobs.
169
+ Use `--worker`, `--workdir`, and `--max-concurrency` or the matching
170
+ `SAILORBRIDGE_WORKER_NAME`, `SAILORBRIDGE_WORKDIR`, and
171
+ `SAILORBRIDGE_MAX_CONCURRENCY` environment variables. `SAILORBRIDGE_MODE=readonly`
172
+ blocks mutating job kinds locally.
173
+
174
+ `sailorbridge login` creates a host pairing against
175
+ `https://www.sailorbridge.com`. The command displays the one-time code and
176
+ polls until approval. The stored credential contains a host-scoped relay key
177
+ (`key_scope: "host"` plus `host_id`) and is used as a fallback when
178
+ `SAILORBRIDGE_RELAY_URL` or `SAILORBRIDGE_TOKEN` are not set. Raw host keys are
179
+ written to the credentials file only. Data commands default to
180
+ `--format plain`; login's plain success output prints the host id, credential
181
+ path, and service status. Explicit `--format json` prints key id and host
182
+ metadata, not the token.
183
+
184
+ `sailorbridge login` installs this service automatically; it exits 3 when
185
+ pairing succeeded but the install did not, and states that the host remains
186
+ offline and cannot receive console tasks before naming the command to run by hand.
187
+ Pass `--no-service` (or set `SAILORBRIDGE_NO_SERVICE=1`) to pair only — the
188
+ opt-out for containers, WSL, and CI images without a service manager.
189
+ Re-running `login` refreshes the definition and restarts the daemon so it always
190
+ runs with the arguments on disk. A markerless legacy definition is taken over
191
+ only when its parsed executable and arguments identify `sailorbridge host run`:
192
+ the old daemon is stopped/unloaded and the definition is renamed to a
193
+ `.sb-legacy-<UTC timestamp>` archive before reinstall. Foreign definitions,
194
+ symlinks, and definitions serving another host remain rejected; move a foreign
195
+ file aside or pass `--service-name` to install a scoped
196
+ `sailorbridge-host-<suffix>` unit.
197
+ `sailorbridge host service install|uninstall|status` manages the long-running
198
+ host daemon as a per-user service afterwards. Linux uses user systemd with
199
+ `Restart=on-failure`; macOS uses a user LaunchAgent with `KeepAlive`. The service
200
+ definition points at a credentials file and a binary path; it does not inline
201
+ tokens. Linux `status` detects whether linger is enabled. If boot persistence is
202
+ not active, `install` and `status` print the exact
203
+ `sudo loginctl enable-linger <user>` command for the user to run, but never run
204
+ sudo automatically. macOS LaunchAgents have no linger equivalent.
205
+
206
+ ## Relay Contract
207
+
208
+ This client reimplements the relay HTTP contract in TypeScript. It does not
209
+ import the Python SailorBridge engine, SailorBridge Site, or SailorAgent code. Key creation uses
210
+ the observed relay contract `roles: string[]`; the legacy singular `role` field
211
+ is deprecated and intentionally not sent.
212
+
213
+ Client host commands implement the P5a relay contract from `engine/PROTOCOL.md`:
214
+ registering or heartbeating a host, listing captain-scoped hosts, and claiming a
215
+ single `agent_start_request`. Host-paired credentials are limited to their bound
216
+ host id and cannot list sibling hosts. In P5a, `sailorbridge host consume` requires
217
+ `--once --dry-run-start`; it validates and transitions a claimed request but does
218
+ not launch an engine process. `sailorbridge host run` is the real long-running
219
+ host daemon: it claims console start requests, redeems an agent credential,
220
+ prepares the workspace, and starts the supervised agent.
221
+ On daemon restart it asks the product API for every still-active member owned by
222
+ the host, rotates the agent credential, and rebuilds the exact relay-reported
223
+ tmux target before it resumes polling new start requests. Workers started by the
224
+ same daemon are restored from the same durable ledger. Console **Relaunch** also
225
+ queues a new host start, so it does not depend on the old supervisor still polling.
226
+ Host-started Claude and Codex agents get terse-output defaults and Claude output
227
+ hygiene hooks to reduce routine token spend without lowering reasoning effort or
228
+ verification requirements.
229
+ Before launching an agent, the host must already be logged in to that engine:
230
+ Codex uses `$CODEX_HOME/auth.json` when set, otherwise `~/.codex/auth.json`;
231
+ Claude uses `$CLAUDE_CONFIG_DIR/.credentials.json` when set, otherwise
232
+ `~/.claude/.credentials.json`.
233
+ The per-agent sandbox links to that single host auth file; missing engine auth
234
+ fails fast instead of starting a CLI that will prompt for credentials.
235
+
236
+ Worker commands implement the relay worker contract from `engine/PROTOCOL.md`:
237
+ register, heartbeat, pull, stream upload, and result posting. Worker HTTP uses
238
+ bounded connect/read-idle timeouts for liveness and leaves result uploads without
239
+ a total timeout cap.
240
+
241
+ Mailbox claim is a destructive operation on the relay; `mailbox peek` is the
242
+ non-destructive command. Add `--lease` to a claim only to include rows already
243
+ leased by this client. A supervisor peek leaves workflow-obligation messages
244
+ queued and claimable after it surfaces the body-free doorbell. The bound agent's
245
+ first `mailbox claim` leases them, then the agent completes the required action.
246
+ Direct workflow messages are acknowledged with the lease token returned by the
247
+ claim. Durable task sources are acknowledged by their successful task
248
+ transition, while task terminal replies and `UNPARKED` are auto-acked after
249
+ delivery. Ordinary and control messages keep their existing acknowledgement
250
+ behavior.
251
+
252
+ Mailbox send is footgun-free by construction: message bodies are read only from
253
+ piped stdin or `--body-file`, never from positional argv. Every `--body-file` and
254
+ `--description-file` flag treats `-` as stdin; `task create --description -` is the
255
+ same stdin shorthand, as is positional `reply` body `-`. Non-empty piped input
256
+ that another selected source would discard is rejected instead of silently
257
+ ignored; commands without a stdin contract reject it before any relay request.
258
+ This prevents the local
259
+ shell from expanding `$VARS`, backticks, or `$()` before the client starts. A
260
+ single `--to-agents A` sends directly to that agent even when `--session` is also
261
+ present. Multiple explicit agents use the session mailbox endpoint. `--to-agents`
262
+ is mutually exclusive with `--to-roles` and `--to-host`; combine roles and host
263
+ when filtering registered agents. An empty pipe sends an empty string body; an
264
+ interactive TTY with no pipe fails fast instead of waiting for typed input.
265
+
266
+ Plaintext bearer tokens are never printed by default. Enrollment descriptors
267
+ contain a plaintext token and are printed only when the caller explicitly runs
268
+ the enrollment command.
269
+
270
+ ## Driver Contract
271
+
272
+ Phase 1 exposes only the tmux transport for Claude and Codex agents. SDK,
273
+ headless, and PTY driver code remains in the package for a later release, but
274
+ the public CLI and host-start surfaces fail fast if callers request those
275
+ transports or request postponed engines such as opencode, copilot, or a custom
276
+ CLI id. There is no silent downgrade to tmux or PTY.
277
+
278
+ The client provides a shared `AgentDriver` interface. The public Phase 1 path is
279
+ the tmux backend; all drivers share the same transport-level contract: `start`,
280
+ `send`, `on`, `resume`, `isAlive`, and `stop`.
281
+
282
+ The tmux driver creates a dedicated tmux session by default and only destroys
283
+ sessions it created. Existing-session mode can send or interrupt, but it does
284
+ not launch a process because environment secrets must not be typed into an
285
+ interactive pane. Host-started agents use readable session names such as
286
+ `sb-<team>-<role>` and append the captain number only when that default already
287
+ exists on the host.
288
+
289
+ Tmux launch environment is passed through tmux process mechanisms (`-e` and the
290
+ child process environment), never as `KEY=value command` text typed into the
291
+ pane. That still has the normal short-lived process-list exposure of command
292
+ arguments; cleaner secret delivery belongs to a later transport release.
293
+
294
+ SDK drivers are optional implementation code and are release-gated from the
295
+ public Phase 1 CLI. A base install or tmux-only caller does not need to
296
+ instantiate them. The pinned SDK versions are:
297
+
298
+ - `@anthropic-ai/claude-agent-sdk@0.3.168`
299
+ - `@openai/codex-sdk@0.137.0`
300
+
301
+ Anthropic's public Claude Code SDK docs still reference
302
+ `@anthropic-ai/claude-code` in some places; the implementation is grounded in
303
+ the `@anthropic-ai/claude-agent-sdk@0.3.168` npm package declarations. Unit
304
+ tests use injected fake SDK facades to verify our event mapping and option
305
+ assembly; they do not prove live provider behavior. Real SDK smoke tests exist
306
+ but are skipped by default. Set `SAILORBRIDGE_REAL_SDK_SMOKE=1` to run them.
307
+
308
+ Productized supervisors default to unattended execution so a BYO agent does not
309
+ stop on local permission prompts: Claude uses `bypassPermissions` and Codex uses
310
+ `danger-full-access` plus `approvalPolicy: "never"` / `yolo`. Explicit
311
+ `--permission-mode`, `--sandbox-mode`, `--approval-policy`, or `--yolo false`
312
+ opt back into a more interactive or constrained launch; the tmux transport
313
+ translates those flags into first-party CLI argv. An explicit `-- COMMAND...`
314
+ is always used verbatim; combining it with safety flags fails fast because those
315
+ flags would not be applied to the verbatim argv. `--yolo true` is also mutually
316
+ exclusive with explicit Codex sandbox or approval-policy constraints.
317
+
318
+ SDK capabilities, PTY support, opencode/copilot adapters, and custom CLI ids are
319
+ deferred to the next release. Their implementation files may exist in this
320
+ package, but Phase 1 help, docs, and validation do not expose them as supported
321
+ product surface.
322
+
323
+ Mailbox consumption, `CLEAR`, and `WORKFLOW-REFRESH` handling are supervisor
324
+ responsibilities (see Supervisor Contract). The driver only manages transport
325
+ lifecycle, liveness inspection, and text delivery.
326
+
327
+ ## Supervisor Contract
328
+
329
+ The TypeScript supervisor owns one local agent process,
330
+ chooses a transport, leases that agent's mailbox, and reports only real
331
+ session/profile changes back to the relay.
332
+
333
+ Ownership is exclusive: do not run this supervisor and the Python SailorBridge
334
+ listener against the same `agent_name`. A single agent inbox and runtime control
335
+ channel must have one owner, otherwise mailbox leases can be stolen. Use
336
+ `sailorbridge supervise` only for agents not already driven by another
337
+ listener/supervisor.
338
+
339
+ Default transport selection:
340
+
341
+ | CLI | Default transport | Default command |
342
+ | --- | --- | --- |
343
+ | `claude` | `tmux` | `claude` |
344
+ | `codex` | `tmux` | `codex` |
345
+
346
+ `claude`/`codex` default to `tmux` so the agent runs the real first-party CLI
347
+ (covered by the captain's Claude/Codex subscription and attachable). When `tmux`
348
+ is the resolved transport and no `--tmux-session` is given, host-started agents
349
+ use readable names such as `sb-<team>-<role>`; same-host collisions try the
350
+ default name, then the captain number, then the agent name, followed by numeric
351
+ suffixes `-1` through `-100`. If every candidate is occupied, startup fails
352
+ explicitly. Direct `sailorbridge supervise` has no team/role context, so it
353
+ falls back to a readable `sb-<agent>` name.
354
+ `--tmux-session` overrides all derived names.
355
+
356
+ When `tmux` is the resolved transport but no `tmux` binary is found, the client
357
+ fails fast or asks before installing it:
358
+
359
+ - **default path** (no `--transport`) → resolves to tmux and fails
360
+ fast with a platform install hint.
361
+ - **explicit `--transport tmux`** on an interactive TTY → prompts: `[1]` install
362
+ tmux (macOS `brew` / Linux `apt-get`/`dnf`/`pacman`, asking for confirmation
363
+ and showing the exact command — including `sudo` — before running it),
364
+ or `[2]` cancel.
365
+ - **explicit `--transport tmux`** without a TTY (e.g. CI) → fails fast with the
366
+ platform install hint. It never installs silently or downgrades the transport.
367
+
368
+ `--transport tmux` launches through the tmux driver, using an explicit
369
+ `--tmux-session` when given or otherwise deriving the readable default described
370
+ above; pass `--tmux-session` for direct-supervise collision control. It is the
371
+ attach/mirror option because tmux reports `attach: true`. Explicit
372
+ `--transport auto` is rejected so the public surface stays tmux-only; `sdk`,
373
+ `headless`, and `pty` fail fast as next-release transports.
374
+
375
+ Supervisor relaunch decisions are based only on local process liveness:
376
+ `driver.on("exit")` or `isAlive().processAlive === false`. Reply liveness is
377
+ not reported as relay presence and never triggers relaunch by itself.
378
+
379
+ `CLEAR` and `WORKFLOW-REFRESH` are monitor-handled control messages. They are
380
+ claimed and acknowledged by the supervisor after successful control cue delivery;
381
+ they are not normal work prompts. For the current tmux transport, `CLEAR` sends
382
+ `/clear`. Future SDK transports must expose a real session reset or document
383
+ their best-effort semantics before they become public.
384
+
385
+ The supervisor owns mailbox leases for its agent and long-polls with
386
+ `wait=true` and `peek=false`. Delivery is serial and control-first. If driver
387
+ delivery fails, the message is not acknowledged so the relay lease can expire and
388
+ requeue it. Surface telemetry is observability-only;
389
+ acknowledgement and driver delivery failures remain real errors. Shutdown
390
+ aborts the in-flight long poll and never acknowledges a partially delivered
391
+ message. Persistent relay errors back off instead of spinning.
392
+
393
+ The CLI entrypoint is explicit about ownership:
394
+
395
+ ```bash
396
+ sailorbridge supervise --agent A --cli codex --cwd /repo --i-own-this-agent
397
+ ```
398
+
399
+ `--i-own-this-agent` is required as a runtime collision guard. For tmux launches,
400
+ the built-in Claude/Codex default commands include the matching no-prompt flags
401
+ unless explicit safety flags request a constrained command. Explicit command argv
402
+ is used verbatim and cannot be combined with safety flags.
403
+ The runtime fetches the relay monitor record before start/relaunch and uses
404
+ `session_handle` only when `should_resume` is true and the selected driver
405
+ reports `resume: true`. After every successful start/rebuild it patches the
406
+ driver's live handle back to the relay; for tmux this is the final
407
+ collision-resolved session name consumed by roster `tmux_session_name`.
408
+
409
+ The liveness loop no longer patches relay presence. Relaunch is attempted only from `driver.on("exit")` or
410
+ `isAlive().processAlive === false`, with capped exponential backoff and a
411
+ give-up state after repeated failures. `replyAlive` never causes a relaunch by itself.