@bivy/bivy 0.10.1-staging.372 → 0.10.1-staging.374
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/README.md +150 -93
- package/bin/bivy.mjs +19 -5
- package/dist/agents/claude-code/runtime.js +31 -0
- package/dist/attach.js +59 -1
- package/dist/relay-attach.js +2 -0
- package/dist/server.js +29 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,59 +1,108 @@
|
|
|
1
1
|
# Bivy
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@bivy/bivy)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
|
|
7
|
+
**Run coding agents on the machines you already own — then reach them from your
|
|
8
|
+
phone, browser, or another terminal.**
|
|
9
|
+
|
|
10
|
+
Start Claude Code on your workstation, right where the repo, the running dev
|
|
11
|
+
server, and the staging database already live. Walk away. On the train, open
|
|
12
|
+
your phone: read what the agent did, answer its question, approve the migration
|
|
13
|
+
— over a link only your devices can decrypt. The work never left your machine.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
curl -fsSL https://bivy.sh/install.sh | bash # install + guided setup
|
|
17
|
+
bivy run claude # start an agent in your repo
|
|
18
|
+
bivy open # pick it up from your phone or browser
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**[Quickstart](docs/quickstart.md)** ·
|
|
22
|
+
**[Docs](docs/README.md)** ·
|
|
23
|
+
**[Why Bivy](docs/why-bivy.md)** ·
|
|
24
|
+
**[Security model](docs/security-model.md)** ·
|
|
25
|
+
**[bivy.sh](https://bivy.sh)**
|
|
26
|
+
|
|
27
|
+
> **0.x software.** The core loop is solid and used daily. Interfaces and
|
|
28
|
+
> cross-runtime fidelity still change between releases — check the
|
|
29
|
+
> [runtime support matrix](docs/runtime-support-matrix.md) before you depend on
|
|
30
|
+
> a specific agent capability.
|
|
31
|
+
|
|
32
|
+
## Why not just a cloud sandbox?
|
|
33
|
+
|
|
34
|
+
A hosted sandbox starts from an *approximation* of your environment. A Bivy
|
|
35
|
+
Machine **is** your environment — the actual working tree, the services already
|
|
36
|
+
running, the caches already warm.
|
|
37
|
+
|
|
38
|
+
| | Cloud sandbox | Bivy Machine |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| Your repository | a cloned copy | the real working tree, uncommitted changes and all |
|
|
41
|
+
| Dev server & database | mocked, or absent | already running, right beside the agent |
|
|
42
|
+
| Private networks & internal APIs | out of reach | reachable |
|
|
43
|
+
| Toolchains, package caches | cold, reinstalled each time | warm, already installed |
|
|
44
|
+
| GPUs / local inference | rented separately | the ones on your box |
|
|
45
|
+
| Where your code sits | someone else's infrastructure | the machine you already trust |
|
|
46
|
+
|
|
47
|
+
You keep the environment. Bivy adds the part that was missing: **reaching that
|
|
48
|
+
environment from anywhere, and leaving it working while you're gone.**
|
|
49
|
+
|
|
50
|
+
## What you can do
|
|
51
|
+
|
|
52
|
+
Bivy gives you two ways to put an agent to work.
|
|
53
|
+
|
|
54
|
+
### Sessions — interactive, and portable
|
|
55
|
+
|
|
56
|
+
Start an agent, watch it work, jump in to steer, stop, or approve. Then leave
|
|
57
|
+
your desk and keep going:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
bivy run claude # or codex, pi, gemini, and a dozen more
|
|
61
|
+
bivy open # continue the same session in the browser or PWA
|
|
62
|
+
bivy resume # pick it back up in the terminal
|
|
63
|
+
bivy run claude --no-follow # start it in the background instead of attaching
|
|
64
|
+
bivy run claude --chat # start the governed app session and open it in the browser
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- **Reconnect from anywhere** — phone, browser, or another terminal — to the
|
|
68
|
+
same live Session. The PWA adds voice input, read-aloud, phone-to-agent
|
|
69
|
+
file/image uploads, and agent-to-phone attachments.
|
|
21
70
|
- **Move work without starting over.** Import existing Claude Code and Codex
|
|
22
|
-
Sessions, or fork
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- **Operate more than one Machine.** Keep a workstation, private-network server,
|
|
27
|
-
and GPU box on one account; select the environment a Session or Run needs.
|
|
28
|
-
Optional warm Session replication is Beta, off by default, and manually
|
|
29
|
-
promoted rather than automatic failover.
|
|
30
|
-
- **Let events start checked work.** Create Runs manually or from failed CI,
|
|
31
|
-
GitHub/Linear issues, Slack, schedules, and signed webhooks. Automations can
|
|
32
|
-
pin a Machine, agent, model, sandbox, approval mode, and attempt ceiling, then
|
|
33
|
-
report bounded check and outcome evidence in a Receipt.
|
|
34
|
-
- **Bring your own stack.** Use provider subscriptions through supported native
|
|
35
|
-
agent logins, API keys in Bivy's vault, or local/OpenAI-compatible inference.
|
|
36
|
-
Add an existing ACP or headless process agent with `bivy agent add`; declarative
|
|
37
|
-
agent plugins are Experimental (`v1alpha1`) and run out of process.
|
|
38
|
-
|
|
39
|
-
Start with the [five-minute quickstart](docs/quickstart.md), then try the
|
|
40
|
-
[capability recipes](docs/capability-recipes.md) or check the exact
|
|
41
|
-
[runtime support matrix](docs/runtime-support-matrix.md).
|
|
71
|
+
Sessions, or fork, copy, and move a Bivy Session to another agent, model, or
|
|
72
|
+
Machine.
|
|
73
|
+
- **Run more than one Machine** — a workstation, a private-network server, a GPU
|
|
74
|
+
box — on one account, and pick the environment each Session needs.
|
|
42
75
|
|
|
43
|
-
|
|
44
|
-
paired devices, so the relay cannot decrypt it. The seatbelt has a precise edge:
|
|
45
|
-
explicitly enabled hosted provisioning may give the control plane technical
|
|
46
|
-
access to encrypted cloud, repository, or key-escrow material, while Slack and
|
|
47
|
-
generic webhook instructions reach it in plaintext. See [Why Bivy](docs/why-bivy.md)
|
|
48
|
-
and the [security model](docs/security-model.md) for the complete trust model.
|
|
76
|
+
### Runs — unattended, and accountable
|
|
49
77
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
- **License:** [AGPL-3.0-only](LICENSE)
|
|
78
|
+
Queue one on demand, or let an event kick it off — either way it returns
|
|
79
|
+
immediately and reports back:
|
|
53
80
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
81
|
+
```bash
|
|
82
|
+
bivy runs start "..." # queue a one-off unattended Run, then `bivy runs wait <id>`
|
|
83
|
+
bivy automation init # or define governed jobs in .bivy/automations.yaml
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- **Trigger from real events** — a failed CI job, a GitHub or Linear issue,
|
|
87
|
+
Slack, a schedule, or a signed webhook.
|
|
88
|
+
- **Pin the guardrails** — Machine, agent, model, sandbox, approval mode, and a
|
|
89
|
+
hard attempt ceiling — right next to the job.
|
|
90
|
+
- **Get a Receipt** — every Run reports the checks it ran and how it turned out,
|
|
91
|
+
not just a wall of output.
|
|
92
|
+
|
|
93
|
+
Try the [capability recipes](docs/capability-recipes.md) to see each of these
|
|
94
|
+
end to end, or the [runtime support matrix](docs/runtime-support-matrix.md) for
|
|
95
|
+
exactly what each agent supports.
|
|
96
|
+
|
|
97
|
+
## Bring your own stack
|
|
98
|
+
|
|
99
|
+
Use provider subscriptions through native agent logins, API keys stored in
|
|
100
|
+
Bivy's vault, or local / OpenAI-compatible inference. Add any ACP or headless
|
|
101
|
+
agent with a single command — no per-agent adapter to write:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
bivy agent add # register an existing ACP or process agent
|
|
105
|
+
```
|
|
57
106
|
|
|
58
107
|
## Install
|
|
59
108
|
|
|
@@ -72,18 +121,26 @@ has Bivy just applies the latest build and restarts the service.
|
|
|
72
121
|
Already have Node.js 22.19+? The installer is optional:
|
|
73
122
|
|
|
74
123
|
```bash
|
|
75
|
-
npm install -g @bivy/bivy
|
|
76
|
-
bivy setup
|
|
124
|
+
npm install -g @bivy/bivy && bivy setup # install globally
|
|
125
|
+
npx @bivy/bivy setup # or try it once, no install
|
|
77
126
|
```
|
|
78
127
|
|
|
79
|
-
|
|
128
|
+
Releases are published from CI with provenance attestations; verify a build's
|
|
129
|
+
origin with `npm audit signatures`. See [`docs/releasing.md`](docs/releasing.md).
|
|
130
|
+
|
|
131
|
+
### Your first session
|
|
132
|
+
|
|
133
|
+
Once `bivy setup` finishes, the whole loop is three commands — start local,
|
|
134
|
+
reconnect remote:
|
|
80
135
|
|
|
81
136
|
```bash
|
|
82
|
-
|
|
137
|
+
bivy run claude # start an agent as a durable session in the current repo
|
|
138
|
+
bivy open # open that same session in the web app (needs relay setup)
|
|
139
|
+
bivy resume # or pick it back up here in the terminal
|
|
83
140
|
```
|
|
84
141
|
|
|
85
|
-
|
|
86
|
-
|
|
142
|
+
From here the [quickstart](docs/quickstart.md) walks through Runs, multiple
|
|
143
|
+
Machines, and automations.
|
|
87
144
|
|
|
88
145
|
### Install options
|
|
89
146
|
|
|
@@ -141,7 +198,7 @@ when a newer build is available.
|
|
|
141
198
|
|
|
142
199
|
## Architecture
|
|
143
200
|
|
|
144
|
-
Bivy has three parts. Only the first one holds your data
|
|
201
|
+
Bivy has three parts. **Only the first one holds your data.**
|
|
145
202
|
|
|
146
203
|
```text
|
|
147
204
|
your machine hosted or self-hosted
|
|
@@ -166,6 +223,8 @@ Bivy has three parts. Only the first one holds your data.
|
|
|
166
223
|
|
|
167
224
|
Because the node serves no UI, a browser or phone needs a control plane — hosted
|
|
168
225
|
at `app.bivy.sh`, or one you deploy yourself. The terminal CLI needs neither.
|
|
226
|
+
Interactive Session traffic is end-to-end encrypted between a Machine and its
|
|
227
|
+
paired devices, so the relay cannot decrypt it.
|
|
169
228
|
|
|
170
229
|
See [`docs/remote-access.md`](docs/remote-access.md) and
|
|
171
230
|
[`docs/security-model.md`](docs/security-model.md).
|
|
@@ -173,14 +232,14 @@ See [`docs/remote-access.md`](docs/remote-access.md) and
|
|
|
173
232
|
## Supported agents
|
|
174
233
|
|
|
175
234
|
**Claude Code and Codex are the recommended, release-certified paths.** The
|
|
176
|
-
broader catalog
|
|
177
|
-
|
|
235
|
+
broader catalog stays available under **More agents**; capabilities and fidelity
|
|
236
|
+
vary by runtime.
|
|
178
237
|
|
|
179
238
|
| Agent | Command | Notes |
|
|
180
239
|
|---|---|---|
|
|
181
|
-
| Pi | `bivy run pi` | Uses the operator-installed `pi` command and Pi auth/config |
|
|
182
240
|
| Claude Code | `bivy run claude` | Uses the operator-installed `claude` command through an SDK bridge |
|
|
183
241
|
| Codex | `bivy run codex` | Installs `@openai/codex` |
|
|
242
|
+
| Pi | `bivy run pi` | Uses the operator-installed `pi` command and Pi auth/config |
|
|
184
243
|
| OpenCode | `bivy run opencode` | Installs `opencode-ai` |
|
|
185
244
|
| Gemini CLI | `bivy run gemini` | Installs `@google/gemini-cli` |
|
|
186
245
|
| Qwen Code | `bivy run qwen` | Installs `@qwen-code/qwen-code` |
|
|
@@ -202,9 +261,8 @@ Any other command works via `bivy run -- ./your-agent --flags`. ACP-capable
|
|
|
202
261
|
agents can be promoted to Bivy's governed protocol path for per-tool approvals
|
|
203
262
|
and native resume. To add a reusable process or ACP agent to both the CLI and web
|
|
204
263
|
picker without changing Bivy, run `bivy agent add`, or scaffold and install a
|
|
205
|
-
declarative [plugin manifest](docs/plugins.md) with `bivy plugin init
|
|
206
|
-
|
|
207
|
-
support distributable or custom protocol bridges.
|
|
264
|
+
declarative [plugin manifest](docs/plugins.md) with `bivy plugin init`
|
|
265
|
+
(declarative plugins are Experimental, `v1alpha1`, and run out of process).
|
|
208
266
|
|
|
209
267
|
[`docs/runtime-support-matrix.md`](docs/runtime-support-matrix.md) lists exactly
|
|
210
268
|
what each agent supports — resume, model selection, approvals, sandboxing.
|
|
@@ -213,8 +271,8 @@ what each agent supports — resume, model selection, approvals, sandboxing.
|
|
|
213
271
|
|
|
214
272
|
```bash
|
|
215
273
|
bivy # show the command overview
|
|
216
|
-
bivy run
|
|
217
|
-
bivy run
|
|
274
|
+
bivy run claude # launch Claude Code as a durable session
|
|
275
|
+
bivy run codex # run a different agent
|
|
218
276
|
bivy sessions # list live and saved sessions
|
|
219
277
|
bivy resume # resume the most recent session
|
|
220
278
|
bivy open # open the web app (requires relay setup)
|
|
@@ -250,24 +308,24 @@ bivy config init --project # .bivy/policy.yaml
|
|
|
250
308
|
```
|
|
251
309
|
|
|
252
310
|
See [`docs/config-as-code.md`](docs/config-as-code.md). Every environment
|
|
253
|
-
variable and precedence rule
|
|
311
|
+
variable and precedence rule lives in
|
|
254
312
|
[`docs/configuration.md`](docs/configuration.md).
|
|
255
313
|
|
|
256
314
|
## Approvals and sandboxing
|
|
257
315
|
|
|
258
316
|
The default approval mode is **`autonomous`**: agents act without per-action
|
|
259
|
-
prompts.
|
|
317
|
+
prompts. How much that actually protects you depends on the runtime. Native-sandbox
|
|
260
318
|
agents enforce the chosen access tier; structured runtimes also pass tool calls
|
|
261
319
|
through Bivy's policy and approval layer. Process agents that Bivy cannot
|
|
262
|
-
intercept run with your OS user permissions
|
|
263
|
-
|
|
320
|
+
intercept run with your OS user permissions — the picker flags this and requires
|
|
321
|
+
confirmation before you pick that path.
|
|
264
322
|
|
|
265
323
|
Where Bivy receives structured shell/file calls, a heuristic floor blocks known
|
|
266
324
|
catastrophic commands and structured writes outside the workspace, and a
|
|
267
325
|
backstop set (force-push, publish, deploy, sudo) pauses for a human. This catches
|
|
268
|
-
accidents; it is not an adversarial isolation boundary
|
|
326
|
+
accidents; **it is not an adversarial isolation boundary.**
|
|
269
327
|
|
|
270
|
-
|
|
328
|
+
Want to be asked about more? Set the mode explicitly:
|
|
271
329
|
|
|
272
330
|
```bash
|
|
273
331
|
BIVY_APPROVAL_MODE=risky # prompt on risky shell commands and file edits
|
|
@@ -280,19 +338,14 @@ Approve from the terminal, browser, or phone.
|
|
|
280
338
|
Sandbox tiers (`read-only`, `workspace-write`, `danger-full-access`) are enforced
|
|
281
339
|
natively by agents that support them — Codex, Claude Code, Gemini CLI, Qwen Code.
|
|
282
340
|
Agents without a native sandbox may expose structured tool or MCP controls, but
|
|
283
|
-
those
|
|
284
|
-
|
|
285
|
-
|
|
341
|
+
those don't cover activity the agent performs outside those channels; some
|
|
342
|
+
process adapters run entirely with your user permissions. Check the picker's
|
|
343
|
+
Protection label. **Bivy does not currently ship its own OS-level jail.**
|
|
286
344
|
|
|
287
345
|
## Credentials
|
|
288
346
|
|
|
289
347
|
Interactive prompts, transcripts, and workspace files stay encrypted across the
|
|
290
|
-
relay. Credentials can remain on a Machine or in a vault you control
|
|
291
|
-
explicitly enable hosted unattended provisioning, Bivy Cloud may instead store
|
|
292
|
-
encrypted cloud, repository, model, or key-escrow material that the service can
|
|
293
|
-
technically access. Treat this as an explicit hosted-custody mode, not as relay
|
|
294
|
-
blindness. See the
|
|
295
|
-
[security model](docs/security-model.md#what-the-control-plane-sees).
|
|
348
|
+
relay. Credentials can remain on a Machine or in a vault you control:
|
|
296
349
|
|
|
297
350
|
```bash
|
|
298
351
|
bivy secrets list
|
|
@@ -301,9 +354,15 @@ bivy secrets ref github.repo-token op://Bivy/GitHub/repo-token
|
|
|
301
354
|
bivy secrets doctor
|
|
302
355
|
```
|
|
303
356
|
|
|
304
|
-
`secret://`, `env://`, and `op://` (1Password) references
|
|
305
|
-
|
|
306
|
-
|
|
357
|
+
`secret://`, `env://`, and `op://` (1Password) references resolve on demand when
|
|
358
|
+
the daemon provisions an agent run, so raw values never sit in your config.
|
|
359
|
+
|
|
360
|
+
**One deliberate exception to relay blindness:** if you explicitly enable hosted
|
|
361
|
+
unattended provisioning, Bivy Cloud may store encrypted cloud, repository,
|
|
362
|
+
model, or key-escrow material that the service can technically access. Treat this
|
|
363
|
+
as an explicit hosted-custody mode. See the
|
|
364
|
+
[security model](docs/security-model.md#what-the-control-plane-sees) and
|
|
365
|
+
[`docs/key-management.md`](docs/key-management.md).
|
|
307
366
|
|
|
308
367
|
## Automations as code
|
|
309
368
|
|
|
@@ -318,7 +377,7 @@ bivy automation apply
|
|
|
318
377
|
```
|
|
319
378
|
|
|
320
379
|
Instructions are encrypted on the applying node before upload. Safety policy
|
|
321
|
-
lives beside the job—sandbox, approval mode, and a hard attempt ceiling that
|
|
380
|
+
lives beside the job — sandbox, approval mode, and a hard attempt ceiling that
|
|
322
381
|
retry/fallback rules cannot exceed. See
|
|
323
382
|
[`docs/automations-as-code.md`](docs/automations-as-code.md).
|
|
324
383
|
|
|
@@ -399,8 +458,8 @@ Each URL has a flag and an environment-variable equivalent (the flag wins):
|
|
|
399
458
|
|
|
400
459
|
Sign-in defaults to GitHub device login (`--github`); pass
|
|
401
460
|
`--email you@example.com` for an email magic-link, or `--session-token <token>`
|
|
402
|
-
to skip interactive sign-in. `relay:setup` checks the control plane is reachable,
|
|
403
|
-
this node, and writes the endpoints to `.bivy/relay.json`, so `bivy open`,
|
|
461
|
+
to skip interactive sign-in. `relay:setup` checks the control plane is reachable,
|
|
462
|
+
enrolls this node, and writes the endpoints to `.bivy/relay.json`, so `bivy open`,
|
|
404
463
|
`bivy link`, and `bivy update` all keep using your deployment afterwards.
|
|
405
464
|
|
|
406
465
|
**Self-hosting is unsupported** — no SLA, community best-effort via GitHub
|
|
@@ -410,16 +469,14 @@ issues. You own TLS, backups, upgrades, and hardening. See
|
|
|
410
469
|
## Security
|
|
411
470
|
|
|
412
471
|
Report vulnerabilities through [GitHub private vulnerability reporting](https://github.com/bivysh/bivy/security/advisories/new).
|
|
413
|
-
Please
|
|
472
|
+
Please don't open a public issue. See [`SECURITY.md`](SECURITY.md) for scope,
|
|
414
473
|
response times, and safe harbour, and [`docs/security-model.md`](docs/security-model.md)
|
|
415
474
|
for the trust model and known limitations.
|
|
416
475
|
|
|
417
476
|
## License
|
|
418
477
|
|
|
419
|
-
Bivy Core is free and open-source software
|
|
420
|
-
|
|
478
|
+
Bivy Core is free and open-source software under the GNU Affero General Public
|
|
479
|
+
License, version 3.0 only (AGPL-3.0-only). You may use, study, modify, and
|
|
421
480
|
self-host it under that license. If you modify Bivy and let users interact with
|
|
422
|
-
it over a network, section 13 requires you to offer
|
|
423
|
-
source code.
|
|
424
|
-
|
|
425
|
-
See [`LICENSE`](LICENSE).
|
|
481
|
+
it over a network, section 13 requires you to offer them the corresponding
|
|
482
|
+
source code. See [`LICENSE`](LICENSE).
|
package/bin/bivy.mjs
CHANGED
|
@@ -939,12 +939,14 @@ function extractRunFlags(args) {
|
|
|
939
939
|
let name, model, node, workspace;
|
|
940
940
|
let chat = false;
|
|
941
941
|
let noOpen = false;
|
|
942
|
+
let noFollow = false;
|
|
942
943
|
let clone; // undefined = no clone; true = current repo; string = explicit remote
|
|
943
944
|
for (let i = 0; i < args.length; i++) {
|
|
944
945
|
const a = args[i];
|
|
945
946
|
if (a === "--") { rest.push(...args.slice(i)); break; }
|
|
946
947
|
if (a === "--chat") { chat = true; continue; }
|
|
947
948
|
if (a === "--no-open") { noOpen = true; continue; }
|
|
949
|
+
if (a === "--no-follow") { noFollow = true; continue; }
|
|
948
950
|
if (a === "--name" && args[i + 1] !== undefined) { name = args[++i]; continue; }
|
|
949
951
|
if (a.startsWith("--name=")) { name = a.slice("--name=".length); continue; }
|
|
950
952
|
if (a === "--model" && args[i + 1] !== undefined) { model = args[++i]; continue; }
|
|
@@ -957,7 +959,7 @@ function extractRunFlags(args) {
|
|
|
957
959
|
if (a === "--clone") { clone = looksLikeRemote(args[i + 1]) ? args[++i] : true; continue; }
|
|
958
960
|
rest.push(a);
|
|
959
961
|
}
|
|
960
|
-
return { name: name?.trim() || undefined, model: model?.trim() || undefined, node: node?.trim() || undefined, workspace: workspace?.trim() || undefined, chat, noOpen, clone, rest };
|
|
962
|
+
return { name: name?.trim() || undefined, model: model?.trim() || undefined, node: node?.trim() || undefined, workspace: workspace?.trim() || undefined, chat, noOpen, noFollow, clone, rest };
|
|
961
963
|
}
|
|
962
964
|
|
|
963
965
|
// A safe-ish workspace dir name from a remote or path (basename minus .git).
|
|
@@ -1813,12 +1815,20 @@ function governedChatAgentId(id) {
|
|
|
1813
1815
|
|
|
1814
1816
|
async function cmdRun(args = []) {
|
|
1815
1817
|
if (!(await ensureDeps())) process.exit(1);
|
|
1816
|
-
const { name, model, node, workspace, chat, noOpen, clone, rest } = extractRunFlags(args);
|
|
1818
|
+
const { name, model, node, workspace, chat, noOpen, noFollow, clone, rest } = extractRunFlags(args);
|
|
1817
1819
|
// Bare `bivy` (empty rest) resolves to the configured default agent; an
|
|
1818
1820
|
// explicit `bivy run <agent>` keeps that agent verbatim.
|
|
1819
1821
|
const [agentIdArg, ...extraArgs] = rest;
|
|
1820
1822
|
const agentId = agentIdArg || resolveDefaultAgent();
|
|
1821
1823
|
|
|
1824
|
+
// --chat already returns immediately, so --no-follow adds nothing there; keep
|
|
1825
|
+
// the two paths distinct rather than silently ignoring the flag.
|
|
1826
|
+
if (chat && noFollow) {
|
|
1827
|
+
console.error(c.red("--no-follow applies to native runs; a --chat session already starts in the background (use --no-open to skip opening the browser)."));
|
|
1828
|
+
process.exit(1);
|
|
1829
|
+
return;
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1822
1832
|
if (chat) {
|
|
1823
1833
|
if (node) {
|
|
1824
1834
|
console.error(c.red("--chat currently starts a governed session on this node; it can't be combined with --node."));
|
|
@@ -1923,6 +1933,9 @@ async function cmdRun(args = []) {
|
|
|
1923
1933
|
"--relay-config", relayConfigPath,
|
|
1924
1934
|
"--attach-cmd", JSON.stringify(nodeScriptArgs(attachEntry)),
|
|
1925
1935
|
"--run", JSON.stringify(spec),
|
|
1936
|
+
// The remote run-terminal is daemon-owned there too, so once it is open
|
|
1937
|
+
// the relay bridge can drop and the session keeps running on the target.
|
|
1938
|
+
...(noFollow ? ["--no-follow"] : []),
|
|
1926
1939
|
], { cwd: repoRoot, env: process.env });
|
|
1927
1940
|
return;
|
|
1928
1941
|
}
|
|
@@ -1935,7 +1948,7 @@ async function cmdRun(args = []) {
|
|
|
1935
1948
|
}
|
|
1936
1949
|
const spec = { ...resolved.spec, name, model, workspace: undefined }; // workspace is the remote node's, not ours
|
|
1937
1950
|
console.log(c.dim(`Starting on ${c.cyan(node)} (${target.url})…`));
|
|
1938
|
-
await run(nodeBin, [...nodeScriptArgs(attachEntry), "--url", target.url, ...(target.token ? ["--token", target.token] : []), "--run", JSON.stringify(spec)], {
|
|
1951
|
+
await run(nodeBin, [...nodeScriptArgs(attachEntry), "--url", target.url, ...(target.token ? ["--token", target.token] : []), "--run", JSON.stringify(spec), ...(noFollow ? ["--no-follow"] : [])], {
|
|
1939
1952
|
cwd: repoRoot,
|
|
1940
1953
|
env: process.env,
|
|
1941
1954
|
});
|
|
@@ -1961,7 +1974,7 @@ async function cmdRun(args = []) {
|
|
|
1961
1974
|
try { token = await localDeviceToken(config); }
|
|
1962
1975
|
catch (error) { console.error(c.red(error?.message || String(error))); process.exit(1); return; }
|
|
1963
1976
|
|
|
1964
|
-
process.exit(await run(nodeBin, [...nodeScriptArgs(attachEntry), "--url", url(config), "--token", token, "--run", JSON.stringify(spec)], {
|
|
1977
|
+
process.exit(await run(nodeBin, [...nodeScriptArgs(attachEntry), "--url", url(config), "--token", token, "--run", JSON.stringify(spec), ...(noFollow ? ["--no-follow"] : [])], {
|
|
1965
1978
|
cwd: repoRoot,
|
|
1966
1979
|
env: startEnv(config),
|
|
1967
1980
|
}));
|
|
@@ -4769,10 +4782,11 @@ async function main() {
|
|
|
4769
4782
|
// args (including its own --help) pass straight through to it — e.g.
|
|
4770
4783
|
// 'bivy run claude --help' must show Claude's help, not bivy's.
|
|
4771
4784
|
if (args[0] === "-h" || args[0] === "--help") {
|
|
4772
|
-
console.log(`Usage: bivy run <agent> [--chat [--no-open]] [--name <label>] [--model <model>] [--node <name>] [--clone [remote]] [--workspace <dir>] | -- <command>
|
|
4785
|
+
console.log(`Usage: bivy run <agent> [--chat [--no-open] | --no-follow] [--name <label>] [--model <model>] [--node <name>] [--clone [remote]] [--workspace <dir>] | -- <command>
|
|
4773
4786
|
|
|
4774
4787
|
Run a native agent (real CLI/TUI) as a relay-visible session.
|
|
4775
4788
|
Use --chat to start the governed session used by the app instead; --no-open prints its URL without launching a browser.
|
|
4789
|
+
Use --no-follow to start the native session in the background without attaching your terminal; rejoin it with 'bivy resume' or open it in the app.
|
|
4776
4790
|
Agents: ${[...AGENT_INTEGRATIONS.keys()].join(", ")}, or -- <command> for anything else.
|
|
4777
4791
|
An agent's own --help passes through, e.g. 'bivy run claude --help'.`);
|
|
4778
4792
|
break;
|
|
@@ -67,10 +67,18 @@ const SDK_PACKAGE = "@anthropic-ai/claude-agent-sdk";
|
|
|
67
67
|
// the first prompt. Until then this.models is empty and the picker would show
|
|
68
68
|
// nothing. These are the models a Claude Pro/Max subscription exposes; once
|
|
69
69
|
// the query is up, supportedModels() replaces them with the authoritative set.
|
|
70
|
+
// Placeholder catalog shown before a live agent can answer (see getModels() and
|
|
71
|
+
// warmModels()). A not-yet-started session has no subprocess to query, so the
|
|
72
|
+
// picker shows this until warmModels() spawns one and supportedModels() replaces
|
|
73
|
+
// it with the account's real, current lineup. Keep it roughly current so the
|
|
74
|
+
// pre-warm placeholder isn't jarringly stale, but it is only a placeholder — the
|
|
75
|
+
// live list is the source of truth.
|
|
70
76
|
const FALLBACK_MODELS = [
|
|
77
|
+
{ provider: "anthropic", id: "claude-opus-5", name: "Claude Opus 5", reasoning: true },
|
|
71
78
|
{ provider: "anthropic", id: "claude-opus-4-8", name: "Claude Opus 4.8", reasoning: true },
|
|
72
79
|
{ provider: "anthropic", id: "claude-sonnet-5", name: "Claude Sonnet 5", reasoning: true },
|
|
73
80
|
{ provider: "anthropic", id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5", reasoning: true },
|
|
81
|
+
{ provider: "anthropic", id: "claude-fable-5", name: "Claude Fable 5", reasoning: true },
|
|
74
82
|
];
|
|
75
83
|
// The SDK's supportedModels() labels each row with a bare family+version
|
|
76
84
|
// ("Opus 4.8") or a family alias ("Sonnet", "Haiku") — while a not-yet-started
|
|
@@ -927,6 +935,29 @@ class ClaudeSession {
|
|
|
927
935
|
clearTimeout(timer);
|
|
928
936
|
}
|
|
929
937
|
}
|
|
938
|
+
/**
|
|
939
|
+
* Spin up the agent subprocess *without* sending a prompt, purely so
|
|
940
|
+
* supportedModels() can resolve and the picker shows the account's real,
|
|
941
|
+
* current lineup instead of FALLBACK_MODELS. Used to warm a not-yet-started
|
|
942
|
+
* (e.g. draft/new-session) catalog. Gated on credentials — mirroring prompt()'s
|
|
943
|
+
* preflight — so we never spawn a subprocess that would only fail; without a
|
|
944
|
+
* credential the picker simply keeps the placeholder list. Best-effort and
|
|
945
|
+
* idempotent: once the query is up it just re-reads the list.
|
|
946
|
+
*/
|
|
947
|
+
async warmModels() {
|
|
948
|
+
if (this.query)
|
|
949
|
+
return this.refreshSupportedModels();
|
|
950
|
+
try {
|
|
951
|
+
const env = { ...process.env, ...depCacheEnv(this.cwd), ...this.runtimeOptions.env, ...(await this.resolveCredentialEnv().catch(() => ({}))) };
|
|
952
|
+
if (anthropicCredentialPreflight(env))
|
|
953
|
+
return; // no credential — keep FALLBACK_MODELS
|
|
954
|
+
await this.ensureStarted();
|
|
955
|
+
await this.refreshSupportedModels();
|
|
956
|
+
}
|
|
957
|
+
catch {
|
|
958
|
+
// Spawn/credential failure — the picker keeps FALLBACK_MODELS.
|
|
959
|
+
}
|
|
960
|
+
}
|
|
930
961
|
/**
|
|
931
962
|
* Tear down the running query and re-spawn it resuming the same session, using
|
|
932
963
|
* a freshly-resolved vault credential (Pi's AuthStorage auto-refreshes an
|
package/dist/attach.js
CHANGED
|
@@ -15,6 +15,10 @@ import { WebSocket } from "ws";
|
|
|
15
15
|
* Modes:
|
|
16
16
|
* --run <specJson> open a fresh run-terminal for a resolved agent command
|
|
17
17
|
* --attach <termId> bind to an existing run-terminal (replays scrollback)
|
|
18
|
+
*
|
|
19
|
+
* With `--run --no-follow` the terminal is started but never bound to the local
|
|
20
|
+
* TTY: the daemon keeps the PTY running and this process returns immediately, so
|
|
21
|
+
* `bivy run <agent> --no-follow` launches a background session you rejoin later.
|
|
18
22
|
*/
|
|
19
23
|
const c = {
|
|
20
24
|
dim: (s) => `\x1b[2m${s}\x1b[22m`,
|
|
@@ -52,6 +56,7 @@ function parseArgs(argv) {
|
|
|
52
56
|
let mode = "attach";
|
|
53
57
|
let run;
|
|
54
58
|
let termId;
|
|
59
|
+
let noFollow = false;
|
|
55
60
|
for (let i = 0; i < argv.length; i++) {
|
|
56
61
|
const arg = argv[i];
|
|
57
62
|
if (arg === "--url" && argv[i + 1])
|
|
@@ -70,8 +75,10 @@ function parseArgs(argv) {
|
|
|
70
75
|
mode = "attach";
|
|
71
76
|
termId = argv[++i];
|
|
72
77
|
}
|
|
78
|
+
else if (arg === "--no-follow")
|
|
79
|
+
noFollow = true;
|
|
73
80
|
}
|
|
74
|
-
return { url: url.replace(/\/+$/, ""), token, mode, run, termId };
|
|
81
|
+
return { url: url.replace(/\/+$/, ""), token, mode, run, termId, noFollow };
|
|
75
82
|
}
|
|
76
83
|
function wsUrl(baseUrl, token) {
|
|
77
84
|
const u = new URL(baseUrl);
|
|
@@ -219,11 +226,62 @@ function bridge(args, open) {
|
|
|
219
226
|
});
|
|
220
227
|
});
|
|
221
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Start a run-terminal on the daemon and return immediately, WITHOUT binding the
|
|
231
|
+
* local TTY. The PTY is daemon-owned, so it keeps running once this client
|
|
232
|
+
* disconnects — the same lifecycle as a Ctrl-\ Ctrl-\ detach, except the
|
|
233
|
+
* terminal was never attached in the first place. Resolves once the daemon
|
|
234
|
+
* confirms the terminal is open (or errors trying).
|
|
235
|
+
*/
|
|
236
|
+
function openDetached(args, spec, cols, rows) {
|
|
237
|
+
return new Promise((resolve) => {
|
|
238
|
+
const socket = new WebSocket(wsUrl(args.url, args.token));
|
|
239
|
+
let settled = false;
|
|
240
|
+
const finish = (code) => {
|
|
241
|
+
if (settled)
|
|
242
|
+
return;
|
|
243
|
+
settled = true;
|
|
244
|
+
try {
|
|
245
|
+
socket.close();
|
|
246
|
+
}
|
|
247
|
+
catch { }
|
|
248
|
+
resolve(code);
|
|
249
|
+
};
|
|
250
|
+
socket.on("open", () => socket.send(JSON.stringify({ kind: "terminal.open.run", agent: spec.agent, label: spec.label, name: spec.name, model: spec.model, command: spec.command, args: spec.args ?? [], workspace: spec.workspace, sessionId: spec.sessionId, cols, rows })));
|
|
251
|
+
socket.on("error", (err) => {
|
|
252
|
+
process.stderr.write(c.red(`Connection error: ${err instanceof Error ? err.message : String(err)}\n`));
|
|
253
|
+
finish(1);
|
|
254
|
+
});
|
|
255
|
+
socket.on("close", () => finish(settled ? 0 : 1));
|
|
256
|
+
socket.on("message", (raw) => {
|
|
257
|
+
let msg;
|
|
258
|
+
try {
|
|
259
|
+
msg = JSON.parse(raw.toString());
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (msg.type === "terminal.opened") {
|
|
265
|
+
const label = spec.name || spec.label || spec.agent || spec.command;
|
|
266
|
+
process.stdout.write(c.green(`Started ${label} in the background.\n`));
|
|
267
|
+
process.stdout.write(c.dim("It keeps running — reopen it in the Bivy app, or with `bivy resume`.\n"));
|
|
268
|
+
finish(0);
|
|
269
|
+
}
|
|
270
|
+
else if (msg.type === "terminal.error") {
|
|
271
|
+
process.stderr.write(c.red(`${String(msg.error || "Terminal error")}\n`));
|
|
272
|
+
finish(1);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
}
|
|
222
277
|
async function main() {
|
|
223
278
|
const args = parseArgs(process.argv.slice(2));
|
|
224
279
|
if (args.mode === "run") {
|
|
225
280
|
const spec = args.run;
|
|
226
281
|
const { cols, rows } = termSize();
|
|
282
|
+
if (args.noFollow) {
|
|
283
|
+
process.exit(await openDetached(args, spec, cols, rows));
|
|
284
|
+
}
|
|
227
285
|
process.stdout.write(c.dim(`Starting ${c.cyan(spec.name || spec.label || spec.agent || spec.command)} — Ctrl-\\ Ctrl-\\ to detach\r\n`));
|
|
228
286
|
const code = await bridge(args, (ws) => ws.send(JSON.stringify({ kind: "terminal.open.run", agent: spec.agent, label: spec.label, name: spec.name, model: spec.model, command: spec.command, args: spec.args ?? [], workspace: spec.workspace, sessionId: spec.sessionId, cols, rows })));
|
|
229
287
|
process.exit(code);
|
package/dist/relay-attach.js
CHANGED
|
@@ -72,6 +72,7 @@ function parseArgs(argv) {
|
|
|
72
72
|
attachCmd,
|
|
73
73
|
run: get("--run"),
|
|
74
74
|
attachTermId: get("--attach"),
|
|
75
|
+
noFollow: argv.includes("--no-follow"),
|
|
75
76
|
label: get("--label") || "Bivy CLI (run --node)",
|
|
76
77
|
};
|
|
77
78
|
}
|
|
@@ -316,6 +317,7 @@ async function main() {
|
|
|
316
317
|
localUrl,
|
|
317
318
|
...(args.run ? ["--run", args.run] : []),
|
|
318
319
|
...(args.attachTermId ? ["--attach", args.attachTermId] : []),
|
|
320
|
+
...(args.noFollow ? ["--no-follow"] : []),
|
|
319
321
|
];
|
|
320
322
|
note(c.dim(`Paired ✓ starting session on ${c.cyan(args.nodeName)}\n`));
|
|
321
323
|
const child = spawn(process.execPath, childArgs, { stdio: "inherit", env: process.env });
|
package/dist/server.js
CHANGED
|
@@ -2411,16 +2411,12 @@ const RELAY_COMMANDS = {
|
|
|
2411
2411
|
if (!requestedSessionId && wantedRuntimeId && record?.runtimeId !== wantedRuntimeId)
|
|
2412
2412
|
record = null;
|
|
2413
2413
|
record ??= await sessionForModelQuery(wantedRuntimeId);
|
|
2414
|
-
const session = record.session;
|
|
2415
|
-
const current = session.getCurrentModel();
|
|
2416
|
-
const models = await publicModelsList(session, current);
|
|
2417
|
-
const thinking = publicThinkingInfo(session);
|
|
2418
2414
|
// Tag the list with the runtime it was resolved for so the client can
|
|
2419
2415
|
// tell whether it belongs to the agent it currently has selected. Without
|
|
2420
2416
|
// this a models.list answered for one agent (e.g. Codex's models) could
|
|
2421
2417
|
// linger on the composer/picker after the user switched to another agent
|
|
2422
2418
|
// (e.g. Claude) — the "Claude shows Codex models" bug.
|
|
2423
|
-
relay?.sendEvent(
|
|
2419
|
+
relay?.sendEvent(await modelsListEventFor(record));
|
|
2424
2420
|
},
|
|
2425
2421
|
"models.prefetch"(msg) {
|
|
2426
2422
|
// The composer's agent picker opened: warm the scratch session for each
|
|
@@ -8105,11 +8101,28 @@ async function sessionForModelQuery(runtimeId) {
|
|
|
8105
8101
|
if (inflight)
|
|
8106
8102
|
return inflight;
|
|
8107
8103
|
const build = createSession(defaultWorkspace, undefined, { makeActive: false, ephemeral: true, runtimeId: wanted })
|
|
8108
|
-
.then((rec) => { modelQueryScratch.set(wanted, rec); return rec; })
|
|
8104
|
+
.then((rec) => { modelQueryScratch.set(wanted, rec); void warmScratchModels(rec); return rec; })
|
|
8109
8105
|
.finally(() => { modelQueryScratchPending.delete(wanted); });
|
|
8110
8106
|
modelQueryScratchPending.set(wanted, build);
|
|
8111
8107
|
return build;
|
|
8112
8108
|
}
|
|
8109
|
+
// A fresh scratch answers its first models.list from the runtime's placeholder
|
|
8110
|
+
// list (no live agent yet). Warm the real catalog in the background — for Claude
|
|
8111
|
+
// Code this spins up the agent subprocess just far enough for supportedModels()
|
|
8112
|
+
// to resolve — then push an updated models.list so a picker opened on the
|
|
8113
|
+
// placeholder repaints with the account's actual, current lineup. Best-effort:
|
|
8114
|
+
// a runtime without warmModels() (static catalog) or a warm failure is a no-op.
|
|
8115
|
+
async function warmScratchModels(rec) {
|
|
8116
|
+
if (typeof rec.session.warmModels !== "function")
|
|
8117
|
+
return;
|
|
8118
|
+
try {
|
|
8119
|
+
await rec.session.warmModels();
|
|
8120
|
+
relay?.sendEvent(await modelsListEventFor(rec));
|
|
8121
|
+
}
|
|
8122
|
+
catch {
|
|
8123
|
+
// Keep the placeholder list; the on-demand models.list path surfaces real errors.
|
|
8124
|
+
}
|
|
8125
|
+
}
|
|
8113
8126
|
/**
|
|
8114
8127
|
* Warm the model-query scratch for one or more runtimes in the background so the
|
|
8115
8128
|
* first agent switch to any of them answers instantly instead of paying the
|
|
@@ -8974,6 +8987,16 @@ async function publicModelsList(session, current) {
|
|
|
8974
8987
|
}));
|
|
8975
8988
|
return [...connected, ...other];
|
|
8976
8989
|
}
|
|
8990
|
+
// Build the models.list event for a session/scratch record — the single shape
|
|
8991
|
+
// both the on-demand handler and the background warm-push send, so an open
|
|
8992
|
+
// picker updates identically however the list was produced.
|
|
8993
|
+
async function modelsListEventFor(record) {
|
|
8994
|
+
const session = record.session;
|
|
8995
|
+
const current = session.getCurrentModel();
|
|
8996
|
+
const models = await publicModelsList(session, current);
|
|
8997
|
+
const thinking = publicThinkingInfo(session);
|
|
8998
|
+
return { type: "models.list", sessionId: record.id, runtimeId: record.runtimeId, current: current ? publicModel(current, current) : null, models, thinking };
|
|
8999
|
+
}
|
|
8977
9000
|
function publicThinkingInfo(session) {
|
|
8978
9001
|
const supports = typeof session.supportsThinking === "function" ? session.supportsThinking() : false;
|
|
8979
9002
|
const level = typeof session.getThinkingLevel === "function" ? session.getThinkingLevel() : undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bivy/bivy",
|
|
3
|
-
"version": "0.10.1-staging.
|
|
3
|
+
"version": "0.10.1-staging.374",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"description": "Run coding agents on machines you own. Open-source, self-hostable agent workspace.",
|
|
@@ -63,6 +63,6 @@
|
|
|
63
63
|
"brace-expansion": "5.0.9",
|
|
64
64
|
"undici": "8.10.0"
|
|
65
65
|
},
|
|
66
|
-
"readme": "# Bivy\n\n**Give coding agents your real environment, then reach them from anywhere.**\n\nA provider sandbox starts from an approximation. A Bivy Machine can use the\nrepository, local services and databases, private networks, existing tools and\ncaches, and GPUs or local inference already available on your workstation or\nserver. Bivy turns that local capability into Sessions you can continue remotely\nand Runs you can leave working unattended.\n\n## What Bivy lets you do\n\n- **Work where the full environment lives.** Run Claude Code, Codex, Pi, or\n another agent beside real repos, dev servers, databases, internal APIs,\n toolchains, package caches, and specialized compute.\n- **Continue from a phone, browser, or terminal.** Reconnect to the same Session,\n steer or stop it, answer questions, and approve supported tool calls. The PWA\n supports voice input and read-aloud, phone-to-agent file/image uploads, and\n agent-to-phone attachments. Native terminal Sessions can stay remote-visible;\n supported runtimes can hand work between terminal and structured chat.\n- **Move work without starting over.** Import existing Claude Code and Codex\n Sessions, or fork/copy/move a Bivy Session to another agent, model, or Machine.\n Fidelity is runtime-dependent: a fork may use a native transcript, replayed\n history, or a bounded seeded continuation, and cross-Machine moves require the\n destination's repo access, agent, and credentials.\n- **Operate more than one Machine.** Keep a workstation, private-network server,\n and GPU box on one account; select the environment a Session or Run needs.\n Optional warm Session replication is Beta, off by default, and manually\n promoted rather than automatic failover.\n- **Let events start checked work.** Create Runs manually or from failed CI,\n GitHub/Linear issues, Slack, schedules, and signed webhooks. Automations can\n pin a Machine, agent, model, sandbox, approval mode, and attempt ceiling, then\n report bounded check and outcome evidence in a Receipt.\n- **Bring your own stack.** Use provider subscriptions through supported native\n agent logins, API keys in Bivy's vault, or local/OpenAI-compatible inference.\n Add an existing ACP or headless process agent with `bivy agent add`; declarative\n agent plugins are Experimental (`v1alpha1`) and run out of process.\n\nStart with the [five-minute quickstart](docs/quickstart.md), then try the\n[capability recipes](docs/capability-recipes.md) or check the exact\n[runtime support matrix](docs/runtime-support-matrix.md).\n\nInteractive Session traffic is end-to-end encrypted between a Machine and its\npaired devices, so the relay cannot decrypt it. The seatbelt has a precise edge:\nexplicitly enabled hosted provisioning may give the control plane technical\naccess to encrypted cloud, repository, or key-escrow material, while Slack and\ngeneric webhook instructions reach it in plaintext. See [Why Bivy](docs/why-bivy.md)\nand the [security model](docs/security-model.md) for the complete trust model.\n\n- **Website:** [bivy.sh](https://bivy.sh)\n- **Documentation:** [`docs/`](docs/README.md)\n- **License:** [AGPL-3.0-only](LICENSE)\n\n> Bivy is 0.x software. The core loop is solid and used daily, but interfaces,\n> cross-runtime fidelity, and behaviour can change between releases. Check the\n> support matrix before depending on a particular agent capability.\n\n## Install\n\n```bash\ncurl -fsSL https://bivy.sh/install.sh | bash\n```\n\nmacOS and Linux. Requires Node.js 22.19 or newer; the installer installs it for\nyou on Debian/Ubuntu and otherwise points you at nodejs.org. It installs the\n[`@bivy/bivy`](https://www.npmjs.com/package/@bivy/bivy) package from npm, puts\nthe `bivy` command on your `PATH`, then runs the guided `bivy setup` wizard —\nagent choice, relay/control-plane sign-in, and an auto-start background service\n(launchd on macOS, systemd on Linux). Re-running it on a machine that already\nhas Bivy just applies the latest build and restarts the service.\n\nAlready have Node.js 22.19+? The installer is optional:\n\n```bash\nnpm install -g @bivy/bivy\nbivy setup\n```\n\nOr try it once without installing anything (`npx` always fetches the latest):\n\n```bash\nnpx @bivy/bivy setup\n```\n\nReleases are published from CI with provenance attestations; verify a build's\norigin with `npm audit signatures`. See [`docs/releasing.md`](docs/releasing.md).\n\n### Install options\n\nEnvironment variables passed to the one-line installer change what it does:\n\n| Goal | Variable |\n|---|---|\n| Track the dev channel (new build on every merge to `main`) | `BIVY_CHANNEL=staging` |\n| Pin an exact version | `BIVY_VERSION=0.1.0` |\n| Install without sudo, into a user-owned prefix | `BIVY_NPM_PREFIX=~/.local` |\n| Preinstall every known upstream agent | `BIVY_INSTALL_ALL_AGENTS=1` |\n\nFor example: `BIVY_CHANNEL=staging curl -fsSL https://bivy.sh/install.sh | bash`.\n\nWorking from a checkout of this repository instead:\n\n```bash\npnpm install\npnpm run setup\n```\n\nSee [`docs/install.md`](docs/install.md) for where data lives, service\nmanagement, and uninstall.\n\n## Updating\n\n```bash\nbivy update\n```\n\n`bivy update` detects how Bivy was installed and does the right thing, then\nwaits for any active session to finish its current turn and restarts the\nbackground service so the node reconnects on the new build:\n\n| Install kind | What `bivy update` does |\n|---|---|\n| npm global (`npm i -g`) | `npm install -g @bivy/bivy@<channel>`, then restart the service |\n| installer / packaged | re-runs `install.sh` (migrating to npm if needed), then restart |\n| git checkout | `git pull --ff-only` + `pnpm install --frozen-lockfile`, then restart |\n| `npx` run | nothing to update — each run already fetches the latest |\n\nUpdates follow the release **channel** recorded at install time — `latest`\n(production) by default, or `staging` if you installed with\n`BIVY_CHANNEL=staging`. Switch channels (the choice is remembered for next\ntime), or skip the wait for a busy session:\n\n```bash\nbivy update --staging # move to the dev channel\nbivy update --stable # move back to production (latest)\nbivy update --force # don't wait for an in-flight turn to finish\n```\n\nThe daemon also checks the registry periodically and posts an in-session notice\nwhen a newer build is available.\n\n## Architecture\n\nBivy has three parts. Only the first one holds your data.\n\n```text\n your machine hosted or self-hosted\n\n ┌──────────────┐ ┌─────────┐ ┌───────────────┐\n │ node daemon │ ──dials──▶ │ relay │ ◀────▶ │ control plane │\n │ agents, keys │ outbound │ opaque │ │ accounts, web │\n │ repo, tools │ │ frames │ │ app, metadata │\n └──────────────┘ └─────────┘ └───────────────┘\n ▲ ▲\n └────────── end-to-end encrypted session ───────────┘\n phone · browser · another terminal\n```\n\n- **Node** — a daemon on your machine. Owns the workspace, credentials, and agent\n processes. Serves an API and WebSocket on `http://localhost:4317` plus a\n `/healthz` probe. **It hosts no web UI.**\n- **Relay** — forwards encrypted frames between your node and your devices. Your\n node dials out, so no inbound port is opened. The relay cannot read the frames.\n- **Control plane** — holds your account, node registry, and session index, and\n serves the web/PWA client. Use the hosted one or run your own.\n\nBecause the node serves no UI, a browser or phone needs a control plane — hosted\nat `app.bivy.sh`, or one you deploy yourself. The terminal CLI needs neither.\n\nSee [`docs/remote-access.md`](docs/remote-access.md) and\n[`docs/security-model.md`](docs/security-model.md).\n\n## Supported agents\n\n**Claude Code and Codex are the recommended, release-certified paths.** The\nbroader catalog remains available under **More agents** for users who need it;\ncapabilities and fidelity vary by runtime:\n\n| Agent | Command | Notes |\n|---|---|---|\n| Pi | `bivy run pi` | Uses the operator-installed `pi` command and Pi auth/config |\n| Claude Code | `bivy run claude` | Uses the operator-installed `claude` command through an SDK bridge |\n| Codex | `bivy run codex` | Installs `@openai/codex` |\n| OpenCode | `bivy run opencode` | Installs `opencode-ai` |\n| Gemini CLI | `bivy run gemini` | Installs `@google/gemini-cli` |\n| Qwen Code | `bivy run qwen` | Installs `@qwen-code/qwen-code` |\n| Goose | `bivy run goose` | Requires `goose` on PATH |\n| Aider | `bivy run aider` | No session resume (upstream gap) |\n| Cline | `bivy run cline` | Installs `cline` |\n| Crush | `bivy run crush` | No session resume (upstream gap) |\n| Cursor | `bivy run cursor` | ACP-capable |\n| GitHub Copilot | `bivy run copilot` | ACP-capable |\n| Grok | `bivy run grok` | Model selection |\n| Amp | `bivy run amp` | Native thread resume |\n| Auggie | `bivy run auggie` | Headless CLI |\n| Droid | `bivy run droid` | Model selection |\n| Continue | `bivy run continue` | Headless CLI |\n| Kilo Code | `bivy run kilocode` | ACP-capable |\n| Rovo Dev | `bivy run rovodev` | Installed out of band |\n\nAny other command works via `bivy run -- ./your-agent --flags`. ACP-capable\nagents can be promoted to Bivy's governed protocol path for per-tool approvals\nand native resume. To add a reusable process or ACP agent to both the CLI and web\npicker without changing Bivy, run `bivy agent add`, or scaffold and install a\ndeclarative [plugin manifest](docs/plugins.md) with `bivy plugin init`. Both use\nthe same schema/store; the plugin SDK, diagnostics, and ACP conformance fixtures\nsupport distributable or custom protocol bridges.\n\n[`docs/runtime-support-matrix.md`](docs/runtime-support-matrix.md) lists exactly\nwhat each agent supports — resume, model selection, approvals, sandboxing.\n\n## Common commands\n\n```bash\nbivy # show the command overview\nbivy run pi # launch Pi as a durable session\nbivy run claude # run a different agent\nbivy sessions # list live and saved sessions\nbivy resume # resume the most recent session\nbivy open # open the web app (requires relay setup)\nbivy automation init # create .bivy/automations.yaml\nbivy agent add # connect an existing ACP or process agent\nbivy plugin list # installed declarative integration packages\nbivy status # config summary and node reachability\nbivy doctor # health check\nbivy logs -f # tail node logs\nbivy update # update Bivy and restart the service\n```\n\nFull command list, flags, and examples: [`docs/cli-reference.md`](docs/cli-reference.md).\n\n## Configuration\n\nThe common knobs:\n\n```bash\nBIVY_WORKSPACE=/path/to/repo # default workspace\nBIVY_SANDBOX=read-only # read-only | workspace-write (default) | danger-full-access\nBIVY_APPROVAL_MODE=risky # never | risky | always | autonomous (default)\n```\n\nCreate and inspect the typed node configuration, or add repository-owned\nsafety/check/retry policy:\n\n```bash\nbivy config init\nbivy config set defaults.agent codex\nbivy config explain defaults.sandbox\nbivy config init --project # .bivy/policy.yaml\n```\n\nSee [`docs/config-as-code.md`](docs/config-as-code.md). Every environment\nvariable and precedence rule remains in\n[`docs/configuration.md`](docs/configuration.md).\n\n## Approvals and sandboxing\n\nThe default approval mode is **`autonomous`**: agents act without per-action\nprompts. The actual protection depends on the selected runtime. Native-sandbox\nagents enforce the chosen access tier; structured runtimes also pass tool calls\nthrough Bivy's policy and approval layer. Process agents that Bivy cannot\nintercept run with your OS user permissions. The picker shows this distinction\nand requires confirmation before selecting that limited path.\n\nWhere Bivy receives structured shell/file calls, a heuristic floor blocks known\ncatastrophic commands and structured writes outside the workspace, and a\nbackstop set (force-push, publish, deploy, sudo) pauses for a human. This catches\naccidents; it is not an adversarial isolation boundary.\n\nIf you want to be asked about more, set the mode explicitly:\n\n```bash\nBIVY_APPROVAL_MODE=risky # prompt on risky shell commands and file edits\nBIVY_APPROVAL_MODE=always # prompt on all shell commands and file edits\nBIVY_APPROVAL_MODE=never # no prompts; structured-tool heuristic blocks still apply where available\n```\n\nApprove from the terminal, browser, or phone.\n\nSandbox tiers (`read-only`, `workspace-write`, `danger-full-access`) are enforced\nnatively by agents that support them — Codex, Claude Code, Gemini CLI, Qwen Code.\nAgents without a native sandbox may expose structured tool or MCP controls, but\nthose controls do not cover activity the agent performs outside those channels;\nsome process adapters run entirely with your user permissions. Check the\npicker's Protection label. **Bivy does not currently ship its own OS-level jail.**\n\n## Credentials\n\nInteractive prompts, transcripts, and workspace files stay encrypted across the\nrelay. Credentials can remain on a Machine or in a vault you control. If you\nexplicitly enable hosted unattended provisioning, Bivy Cloud may instead store\nencrypted cloud, repository, model, or key-escrow material that the service can\ntechnically access. Treat this as an explicit hosted-custody mode, not as relay\nblindness. See the\n[security model](docs/security-model.md#what-the-control-plane-sees).\n\n```bash\nbivy secrets list\nbivy secrets set github.repo-token\nbivy secrets ref github.repo-token op://Bivy/GitHub/repo-token\nbivy secrets doctor\n```\n\n`secret://`, `env://`, and `op://` (1Password) references are resolved on demand\nwhen the daemon provisions an agent run, so the raw values never sit in your\nconfig. See [`docs/key-management.md`](docs/key-management.md).\n\n## Automations as code\n\nDefine governed jobs in `.bivy/automations.yaml`, validate them, and simulate\ntrigger events locally before applying anything:\n\n```bash\nbivy automation init\nbivy automation validate\nbivy automation test --event .bivy/events/failed-ci.yaml\nbivy automation apply\n```\n\nInstructions are encrypted on the applying node before upload. Safety policy\nlives beside the job—sandbox, approval mode, and a hard attempt ceiling that\nretry/fallback rules cannot exceed. See\n[`docs/automations-as-code.md`](docs/automations-as-code.md).\n\n## GitHub Runs\n\nLabel an issue `bivy` (or `bivy/<machine>` to target a Machine), or mention the\nBivy GitHub App in a comment. Bivy creates a Run on the selected Machine, uses an\nisolated worktree, executes configured checks, and reports an explicit outcome.\n\nCore applies no commercial usage limits. Bivy Cloud billing and commercial\npolicy live in the separate Cloud repository.\n\nA private GitHub App only installs on the account that owns it, so connect one\napp per GitHub account — one for your personal repos, one per organization\n(`bivy github:app-create --org <org>`). A node can serve several at once, each\nwith its own key and `@`-mention handle.\n\nSee [`docs/github-work-queue.md`](docs/github-work-queue.md).\n\n## Linear Runs\n\nApply `bivy` or `bivy/<machine>` to a Linear issue to create a Run on the selected\nMachine. The Machine fetches issue content directly from Linear, works in an\nisolated GitHub worktree, and asks the agent to open a pull request. See\n[`docs/linear-work-queue.md`](docs/linear-work-queue.md).\n\n## Development\n\n```bash\npnpm install\npnpm run dev # node daemon on http://localhost:4317\npnpm run dev:web # web client dev server (proxies /api and /ws to the node)\n```\n\nChecks — all of these run in CI:\n\n```bash\npnpm run typecheck\npnpm run typecheck:web\npnpm run lint\npnpm run test:unit\npnpm run test:core\npnpm run check:licenses\npnpm run check:secrets\n```\n\nRepository layout:\n\n- `src/` — node daemon, runtime adapters, approvals, secrets, sessions\n- `bin/` — the `bivy` CLI\n- `packages/core` — shared protocol, pairing, wire format\n- `packages/web` — the React/Vite PWA client (`@bivy/web`)\n- `services/relay` — self-hostable relay\n- `services/control-plane` — self-hostable control plane\n- `deploy/` — self-host deployment examples\n\nSee [`CONTRIBUTING.md`](CONTRIBUTING.md).\n\n## Self-hosting\n\nNode, relay, and control plane are all in this repository. Point a node at your\nown deployment by passing URLs to `bivy relay:setup` — re-running it switches an\nexisting node over to the new endpoints:\n\n```bash\nbivy relay:setup \\\n --control-plane https://bivy.example.com \\\n --relay wss://relay.example.com\n```\n\nEach URL has a flag and an environment-variable equivalent (the flag wins):\n\n| Flag | Environment variable | Points at | Default |\n|---|---|---|---|\n| `--control-plane <url>` | `BIVY_CONTROL_PLANE_URL` | accounts, node registry, and the web-app API | hosted (`app.bivy.sh`) |\n| `--relay <wss-url>` | `BIVY_RELAY_URL` | the encrypted-frame relay your node dials out to | hosted |\n| `--client <url>` | `BIVY_CLIENT_BASE_URL` | base URL used when building app/PWA links | the `--control-plane` URL |\n\nSign-in defaults to GitHub device login (`--github`); pass\n`--email you@example.com` for an email magic-link, or `--session-token <token>`\nto skip interactive sign-in. `relay:setup` checks the control plane is reachable, enrolls\nthis node, and writes the endpoints to `.bivy/relay.json`, so `bivy open`,\n`bivy link`, and `bivy update` all keep using your deployment afterwards.\n\n**Self-hosting is unsupported** — no SLA, community best-effort via GitHub\nissues. You own TLS, backups, upgrades, and hardening. See\n[`docs/self-host.md`](docs/self-host.md).\n\n## Security\n\nReport vulnerabilities through [GitHub private vulnerability reporting](https://github.com/bivysh/bivy/security/advisories/new).\nPlease do not open a public issue. See [`SECURITY.md`](SECURITY.md) for scope,\nresponse times, and safe harbour, and [`docs/security-model.md`](docs/security-model.md)\nfor the trust model and known limitations.\n\n## License\n\nBivy Core is free and open-source software licensed under the GNU Affero General\nPublic License, version 3.0 only (AGPL-3.0-only). You may use, study, modify, and\nself-host it under that license. If you modify Bivy and let users interact with\nit over a network, section 13 requires you to offer those users the corresponding\nsource code.\n\nSee [`LICENSE`](LICENSE).\n",
|
|
66
|
+
"readme": "# Bivy\n\n[](https://www.npmjs.com/package/@bivy/bivy)\n[](LICENSE)\n[](https://nodejs.org)\n\n**Run coding agents on the machines you already own — then reach them from your\nphone, browser, or another terminal.**\n\nStart Claude Code on your workstation, right where the repo, the running dev\nserver, and the staging database already live. Walk away. On the train, open\nyour phone: read what the agent did, answer its question, approve the migration\n— over a link only your devices can decrypt. The work never left your machine.\n\n```bash\ncurl -fsSL https://bivy.sh/install.sh | bash # install + guided setup\nbivy run claude # start an agent in your repo\nbivy open # pick it up from your phone or browser\n```\n\n**[Quickstart](docs/quickstart.md)** ·\n**[Docs](docs/README.md)** ·\n**[Why Bivy](docs/why-bivy.md)** ·\n**[Security model](docs/security-model.md)** ·\n**[bivy.sh](https://bivy.sh)**\n\n> **0.x software.** The core loop is solid and used daily. Interfaces and\n> cross-runtime fidelity still change between releases — check the\n> [runtime support matrix](docs/runtime-support-matrix.md) before you depend on\n> a specific agent capability.\n\n## Why not just a cloud sandbox?\n\nA hosted sandbox starts from an *approximation* of your environment. A Bivy\nMachine **is** your environment — the actual working tree, the services already\nrunning, the caches already warm.\n\n| | Cloud sandbox | Bivy Machine |\n|---|---|---|\n| Your repository | a cloned copy | the real working tree, uncommitted changes and all |\n| Dev server & database | mocked, or absent | already running, right beside the agent |\n| Private networks & internal APIs | out of reach | reachable |\n| Toolchains, package caches | cold, reinstalled each time | warm, already installed |\n| GPUs / local inference | rented separately | the ones on your box |\n| Where your code sits | someone else's infrastructure | the machine you already trust |\n\nYou keep the environment. Bivy adds the part that was missing: **reaching that\nenvironment from anywhere, and leaving it working while you're gone.**\n\n## What you can do\n\nBivy gives you two ways to put an agent to work.\n\n### Sessions — interactive, and portable\n\nStart an agent, watch it work, jump in to steer, stop, or approve. Then leave\nyour desk and keep going:\n\n```bash\nbivy run claude # or codex, pi, gemini, and a dozen more\nbivy open # continue the same session in the browser or PWA\nbivy resume # pick it back up in the terminal\nbivy run claude --no-follow # start it in the background instead of attaching\nbivy run claude --chat # start the governed app session and open it in the browser\n```\n\n- **Reconnect from anywhere** — phone, browser, or another terminal — to the\n same live Session. The PWA adds voice input, read-aloud, phone-to-agent\n file/image uploads, and agent-to-phone attachments.\n- **Move work without starting over.** Import existing Claude Code and Codex\n Sessions, or fork, copy, and move a Bivy Session to another agent, model, or\n Machine.\n- **Run more than one Machine** — a workstation, a private-network server, a GPU\n box — on one account, and pick the environment each Session needs.\n\n### Runs — unattended, and accountable\n\nQueue one on demand, or let an event kick it off — either way it returns\nimmediately and reports back:\n\n```bash\nbivy runs start \"...\" # queue a one-off unattended Run, then `bivy runs wait <id>`\nbivy automation init # or define governed jobs in .bivy/automations.yaml\n```\n\n- **Trigger from real events** — a failed CI job, a GitHub or Linear issue,\n Slack, a schedule, or a signed webhook.\n- **Pin the guardrails** — Machine, agent, model, sandbox, approval mode, and a\n hard attempt ceiling — right next to the job.\n- **Get a Receipt** — every Run reports the checks it ran and how it turned out,\n not just a wall of output.\n\nTry the [capability recipes](docs/capability-recipes.md) to see each of these\nend to end, or the [runtime support matrix](docs/runtime-support-matrix.md) for\nexactly what each agent supports.\n\n## Bring your own stack\n\nUse provider subscriptions through native agent logins, API keys stored in\nBivy's vault, or local / OpenAI-compatible inference. Add any ACP or headless\nagent with a single command — no per-agent adapter to write:\n\n```bash\nbivy agent add # register an existing ACP or process agent\n```\n\n## Install\n\n```bash\ncurl -fsSL https://bivy.sh/install.sh | bash\n```\n\nmacOS and Linux. Requires Node.js 22.19 or newer; the installer installs it for\nyou on Debian/Ubuntu and otherwise points you at nodejs.org. It installs the\n[`@bivy/bivy`](https://www.npmjs.com/package/@bivy/bivy) package from npm, puts\nthe `bivy` command on your `PATH`, then runs the guided `bivy setup` wizard —\nagent choice, relay/control-plane sign-in, and an auto-start background service\n(launchd on macOS, systemd on Linux). Re-running it on a machine that already\nhas Bivy just applies the latest build and restarts the service.\n\nAlready have Node.js 22.19+? The installer is optional:\n\n```bash\nnpm install -g @bivy/bivy && bivy setup # install globally\nnpx @bivy/bivy setup # or try it once, no install\n```\n\nReleases are published from CI with provenance attestations; verify a build's\norigin with `npm audit signatures`. See [`docs/releasing.md`](docs/releasing.md).\n\n### Your first session\n\nOnce `bivy setup` finishes, the whole loop is three commands — start local,\nreconnect remote:\n\n```bash\nbivy run claude # start an agent as a durable session in the current repo\nbivy open # open that same session in the web app (needs relay setup)\nbivy resume # or pick it back up here in the terminal\n```\n\nFrom here the [quickstart](docs/quickstart.md) walks through Runs, multiple\nMachines, and automations.\n\n### Install options\n\nEnvironment variables passed to the one-line installer change what it does:\n\n| Goal | Variable |\n|---|---|\n| Track the dev channel (new build on every merge to `main`) | `BIVY_CHANNEL=staging` |\n| Pin an exact version | `BIVY_VERSION=0.1.0` |\n| Install without sudo, into a user-owned prefix | `BIVY_NPM_PREFIX=~/.local` |\n| Preinstall every known upstream agent | `BIVY_INSTALL_ALL_AGENTS=1` |\n\nFor example: `BIVY_CHANNEL=staging curl -fsSL https://bivy.sh/install.sh | bash`.\n\nWorking from a checkout of this repository instead:\n\n```bash\npnpm install\npnpm run setup\n```\n\nSee [`docs/install.md`](docs/install.md) for where data lives, service\nmanagement, and uninstall.\n\n## Updating\n\n```bash\nbivy update\n```\n\n`bivy update` detects how Bivy was installed and does the right thing, then\nwaits for any active session to finish its current turn and restarts the\nbackground service so the node reconnects on the new build:\n\n| Install kind | What `bivy update` does |\n|---|---|\n| npm global (`npm i -g`) | `npm install -g @bivy/bivy@<channel>`, then restart the service |\n| installer / packaged | re-runs `install.sh` (migrating to npm if needed), then restart |\n| git checkout | `git pull --ff-only` + `pnpm install --frozen-lockfile`, then restart |\n| `npx` run | nothing to update — each run already fetches the latest |\n\nUpdates follow the release **channel** recorded at install time — `latest`\n(production) by default, or `staging` if you installed with\n`BIVY_CHANNEL=staging`. Switch channels (the choice is remembered for next\ntime), or skip the wait for a busy session:\n\n```bash\nbivy update --staging # move to the dev channel\nbivy update --stable # move back to production (latest)\nbivy update --force # don't wait for an in-flight turn to finish\n```\n\nThe daemon also checks the registry periodically and posts an in-session notice\nwhen a newer build is available.\n\n## Architecture\n\nBivy has three parts. **Only the first one holds your data.**\n\n```text\n your machine hosted or self-hosted\n\n ┌──────────────┐ ┌─────────┐ ┌───────────────┐\n │ node daemon │ ──dials──▶ │ relay │ ◀────▶ │ control plane │\n │ agents, keys │ outbound │ opaque │ │ accounts, web │\n │ repo, tools │ │ frames │ │ app, metadata │\n └──────────────┘ └─────────┘ └───────────────┘\n ▲ ▲\n └────────── end-to-end encrypted session ───────────┘\n phone · browser · another terminal\n```\n\n- **Node** — a daemon on your machine. Owns the workspace, credentials, and agent\n processes. Serves an API and WebSocket on `http://localhost:4317` plus a\n `/healthz` probe. **It hosts no web UI.**\n- **Relay** — forwards encrypted frames between your node and your devices. Your\n node dials out, so no inbound port is opened. The relay cannot read the frames.\n- **Control plane** — holds your account, node registry, and session index, and\n serves the web/PWA client. Use the hosted one or run your own.\n\nBecause the node serves no UI, a browser or phone needs a control plane — hosted\nat `app.bivy.sh`, or one you deploy yourself. The terminal CLI needs neither.\nInteractive Session traffic is end-to-end encrypted between a Machine and its\npaired devices, so the relay cannot decrypt it.\n\nSee [`docs/remote-access.md`](docs/remote-access.md) and\n[`docs/security-model.md`](docs/security-model.md).\n\n## Supported agents\n\n**Claude Code and Codex are the recommended, release-certified paths.** The\nbroader catalog stays available under **More agents**; capabilities and fidelity\nvary by runtime.\n\n| Agent | Command | Notes |\n|---|---|---|\n| Claude Code | `bivy run claude` | Uses the operator-installed `claude` command through an SDK bridge |\n| Codex | `bivy run codex` | Installs `@openai/codex` |\n| Pi | `bivy run pi` | Uses the operator-installed `pi` command and Pi auth/config |\n| OpenCode | `bivy run opencode` | Installs `opencode-ai` |\n| Gemini CLI | `bivy run gemini` | Installs `@google/gemini-cli` |\n| Qwen Code | `bivy run qwen` | Installs `@qwen-code/qwen-code` |\n| Goose | `bivy run goose` | Requires `goose` on PATH |\n| Aider | `bivy run aider` | No session resume (upstream gap) |\n| Cline | `bivy run cline` | Installs `cline` |\n| Crush | `bivy run crush` | No session resume (upstream gap) |\n| Cursor | `bivy run cursor` | ACP-capable |\n| GitHub Copilot | `bivy run copilot` | ACP-capable |\n| Grok | `bivy run grok` | Model selection |\n| Amp | `bivy run amp` | Native thread resume |\n| Auggie | `bivy run auggie` | Headless CLI |\n| Droid | `bivy run droid` | Model selection |\n| Continue | `bivy run continue` | Headless CLI |\n| Kilo Code | `bivy run kilocode` | ACP-capable |\n| Rovo Dev | `bivy run rovodev` | Installed out of band |\n\nAny other command works via `bivy run -- ./your-agent --flags`. ACP-capable\nagents can be promoted to Bivy's governed protocol path for per-tool approvals\nand native resume. To add a reusable process or ACP agent to both the CLI and web\npicker without changing Bivy, run `bivy agent add`, or scaffold and install a\ndeclarative [plugin manifest](docs/plugins.md) with `bivy plugin init`\n(declarative plugins are Experimental, `v1alpha1`, and run out of process).\n\n[`docs/runtime-support-matrix.md`](docs/runtime-support-matrix.md) lists exactly\nwhat each agent supports — resume, model selection, approvals, sandboxing.\n\n## Common commands\n\n```bash\nbivy # show the command overview\nbivy run claude # launch Claude Code as a durable session\nbivy run codex # run a different agent\nbivy sessions # list live and saved sessions\nbivy resume # resume the most recent session\nbivy open # open the web app (requires relay setup)\nbivy automation init # create .bivy/automations.yaml\nbivy agent add # connect an existing ACP or process agent\nbivy plugin list # installed declarative integration packages\nbivy status # config summary and node reachability\nbivy doctor # health check\nbivy logs -f # tail node logs\nbivy update # update Bivy and restart the service\n```\n\nFull command list, flags, and examples: [`docs/cli-reference.md`](docs/cli-reference.md).\n\n## Configuration\n\nThe common knobs:\n\n```bash\nBIVY_WORKSPACE=/path/to/repo # default workspace\nBIVY_SANDBOX=read-only # read-only | workspace-write (default) | danger-full-access\nBIVY_APPROVAL_MODE=risky # never | risky | always | autonomous (default)\n```\n\nCreate and inspect the typed node configuration, or add repository-owned\nsafety/check/retry policy:\n\n```bash\nbivy config init\nbivy config set defaults.agent codex\nbivy config explain defaults.sandbox\nbivy config init --project # .bivy/policy.yaml\n```\n\nSee [`docs/config-as-code.md`](docs/config-as-code.md). Every environment\nvariable and precedence rule lives in\n[`docs/configuration.md`](docs/configuration.md).\n\n## Approvals and sandboxing\n\nThe default approval mode is **`autonomous`**: agents act without per-action\nprompts. How much that actually protects you depends on the runtime. Native-sandbox\nagents enforce the chosen access tier; structured runtimes also pass tool calls\nthrough Bivy's policy and approval layer. Process agents that Bivy cannot\nintercept run with your OS user permissions — the picker flags this and requires\nconfirmation before you pick that path.\n\nWhere Bivy receives structured shell/file calls, a heuristic floor blocks known\ncatastrophic commands and structured writes outside the workspace, and a\nbackstop set (force-push, publish, deploy, sudo) pauses for a human. This catches\naccidents; **it is not an adversarial isolation boundary.**\n\nWant to be asked about more? Set the mode explicitly:\n\n```bash\nBIVY_APPROVAL_MODE=risky # prompt on risky shell commands and file edits\nBIVY_APPROVAL_MODE=always # prompt on all shell commands and file edits\nBIVY_APPROVAL_MODE=never # no prompts; structured-tool heuristic blocks still apply where available\n```\n\nApprove from the terminal, browser, or phone.\n\nSandbox tiers (`read-only`, `workspace-write`, `danger-full-access`) are enforced\nnatively by agents that support them — Codex, Claude Code, Gemini CLI, Qwen Code.\nAgents without a native sandbox may expose structured tool or MCP controls, but\nthose don't cover activity the agent performs outside those channels; some\nprocess adapters run entirely with your user permissions. Check the picker's\nProtection label. **Bivy does not currently ship its own OS-level jail.**\n\n## Credentials\n\nInteractive prompts, transcripts, and workspace files stay encrypted across the\nrelay. Credentials can remain on a Machine or in a vault you control:\n\n```bash\nbivy secrets list\nbivy secrets set github.repo-token\nbivy secrets ref github.repo-token op://Bivy/GitHub/repo-token\nbivy secrets doctor\n```\n\n`secret://`, `env://`, and `op://` (1Password) references resolve on demand when\nthe daemon provisions an agent run, so raw values never sit in your config.\n\n**One deliberate exception to relay blindness:** if you explicitly enable hosted\nunattended provisioning, Bivy Cloud may store encrypted cloud, repository,\nmodel, or key-escrow material that the service can technically access. Treat this\nas an explicit hosted-custody mode. See the\n[security model](docs/security-model.md#what-the-control-plane-sees) and\n[`docs/key-management.md`](docs/key-management.md).\n\n## Automations as code\n\nDefine governed jobs in `.bivy/automations.yaml`, validate them, and simulate\ntrigger events locally before applying anything:\n\n```bash\nbivy automation init\nbivy automation validate\nbivy automation test --event .bivy/events/failed-ci.yaml\nbivy automation apply\n```\n\nInstructions are encrypted on the applying node before upload. Safety policy\nlives beside the job — sandbox, approval mode, and a hard attempt ceiling that\nretry/fallback rules cannot exceed. See\n[`docs/automations-as-code.md`](docs/automations-as-code.md).\n\n## GitHub Runs\n\nLabel an issue `bivy` (or `bivy/<machine>` to target a Machine), or mention the\nBivy GitHub App in a comment. Bivy creates a Run on the selected Machine, uses an\nisolated worktree, executes configured checks, and reports an explicit outcome.\n\nCore applies no commercial usage limits. Bivy Cloud billing and commercial\npolicy live in the separate Cloud repository.\n\nA private GitHub App only installs on the account that owns it, so connect one\napp per GitHub account — one for your personal repos, one per organization\n(`bivy github:app-create --org <org>`). A node can serve several at once, each\nwith its own key and `@`-mention handle.\n\nSee [`docs/github-work-queue.md`](docs/github-work-queue.md).\n\n## Linear Runs\n\nApply `bivy` or `bivy/<machine>` to a Linear issue to create a Run on the selected\nMachine. The Machine fetches issue content directly from Linear, works in an\nisolated GitHub worktree, and asks the agent to open a pull request. See\n[`docs/linear-work-queue.md`](docs/linear-work-queue.md).\n\n## Development\n\n```bash\npnpm install\npnpm run dev # node daemon on http://localhost:4317\npnpm run dev:web # web client dev server (proxies /api and /ws to the node)\n```\n\nChecks — all of these run in CI:\n\n```bash\npnpm run typecheck\npnpm run typecheck:web\npnpm run lint\npnpm run test:unit\npnpm run test:core\npnpm run check:licenses\npnpm run check:secrets\n```\n\nRepository layout:\n\n- `src/` — node daemon, runtime adapters, approvals, secrets, sessions\n- `bin/` — the `bivy` CLI\n- `packages/core` — shared protocol, pairing, wire format\n- `packages/web` — the React/Vite PWA client (`@bivy/web`)\n- `services/relay` — self-hostable relay\n- `services/control-plane` — self-hostable control plane\n- `deploy/` — self-host deployment examples\n\nSee [`CONTRIBUTING.md`](CONTRIBUTING.md).\n\n## Self-hosting\n\nNode, relay, and control plane are all in this repository. Point a node at your\nown deployment by passing URLs to `bivy relay:setup` — re-running it switches an\nexisting node over to the new endpoints:\n\n```bash\nbivy relay:setup \\\n --control-plane https://bivy.example.com \\\n --relay wss://relay.example.com\n```\n\nEach URL has a flag and an environment-variable equivalent (the flag wins):\n\n| Flag | Environment variable | Points at | Default |\n|---|---|---|---|\n| `--control-plane <url>` | `BIVY_CONTROL_PLANE_URL` | accounts, node registry, and the web-app API | hosted (`app.bivy.sh`) |\n| `--relay <wss-url>` | `BIVY_RELAY_URL` | the encrypted-frame relay your node dials out to | hosted |\n| `--client <url>` | `BIVY_CLIENT_BASE_URL` | base URL used when building app/PWA links | the `--control-plane` URL |\n\nSign-in defaults to GitHub device login (`--github`); pass\n`--email you@example.com` for an email magic-link, or `--session-token <token>`\nto skip interactive sign-in. `relay:setup` checks the control plane is reachable,\nenrolls this node, and writes the endpoints to `.bivy/relay.json`, so `bivy open`,\n`bivy link`, and `bivy update` all keep using your deployment afterwards.\n\n**Self-hosting is unsupported** — no SLA, community best-effort via GitHub\nissues. You own TLS, backups, upgrades, and hardening. See\n[`docs/self-host.md`](docs/self-host.md).\n\n## Security\n\nReport vulnerabilities through [GitHub private vulnerability reporting](https://github.com/bivysh/bivy/security/advisories/new).\nPlease don't open a public issue. See [`SECURITY.md`](SECURITY.md) for scope,\nresponse times, and safe harbour, and [`docs/security-model.md`](docs/security-model.md)\nfor the trust model and known limitations.\n\n## License\n\nBivy Core is free and open-source software under the GNU Affero General Public\nLicense, version 3.0 only (AGPL-3.0-only). You may use, study, modify, and\nself-host it under that license. If you modify Bivy and let users interact with\nit over a network, section 13 requires you to offer them the corresponding\nsource code. See [`LICENSE`](LICENSE).\n",
|
|
67
67
|
"readmeFilename": "README.md"
|
|
68
68
|
}
|