@bivy/bivy 0.16.1-staging.2 → 0.16.1-staging.4

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 CHANGED
@@ -4,21 +4,25 @@
4
4
  [![license: AGPL-3.0-only](https://img.shields.io/badge/license-AGPL--3.0--only-2b6cb0)](LICENSE)
5
5
  [![node](https://img.shields.io/badge/node-%E2%89%A520-2b6cb0)](https://nodejs.org)
6
6
 
7
- **Run coding agents on the machines you already own — then reach them from your
8
- phone, browser, or another terminal.**
7
+ **Run coding agents on your machines and use them from anywhere — from a phone,
8
+ browser, terminal, GitHub issue, Slack message, schedule, or webhook.**
9
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.
10
+ Start Claude Code on your workstation, next to the repo, dev server, and
11
+ database you already use. Walk away. From your phone, you can see what it did,
12
+ answer a question, or approve a migration. CI or a webhook can start the next
13
+ job on the right Machine without waiting for you to return.
14
14
 
15
15
  ```bash
16
- curl -fsSL https://bivy.sh/install.sh | bash # install + guided setup
16
+ curl -fsSL https://bivy.sh/install.sh | bash # install + guided setup
17
17
  cd your-repo
18
- bivy run claude # start an agent where your work lives
19
- bivy open # pick it up from your phone or browser
18
+ bivy run claude # start an agent in this repo
19
+ bivy open # open it in a browser or on your phone
20
20
  ```
21
21
 
22
+ Bivy does not replace Claude Code, Codex, or the other agents you use. It keeps
23
+ their Sessions running, routes work to the right Machine, and gives you one place
24
+ to start, join, approve, and review work.
25
+
22
26
  First thing to try: ask the agent to explain the repository, make one small safe
23
27
  change, then open the same Session in the web app or on your phone while it runs.
24
28
 
@@ -28,16 +32,16 @@ change, then open the same Session in the web app or on your phone while it runs
28
32
  **[Security model](docs/security-model.md)** ·
29
33
  **[bivy.sh](https://bivy.sh)**
30
34
 
31
- > **0.x software.** The core loop is solid and used daily. Interfaces and
32
- > cross-runtime fidelity still change between releases — check the
33
- > [runtime support matrix](docs/runtime-support-matrix.md) before you depend on
34
- > a specific agent capability.
35
+ > **Bivy is 0.x software.** Claude Code, Codex, Pi, and OpenCode are the
36
+ > release-tested paths. Support for other agents varies; check the
37
+ > [runtime support matrix](docs/runtime-support-matrix.md) before relying on a
38
+ > specific feature.
35
39
 
36
40
  ## Why not just a cloud sandbox?
37
41
 
38
- A hosted sandbox starts from an *approximation* of your environment. A Bivy
39
- Machine **is** your environment — the actual working tree, the services already
40
- running, the caches already warm.
42
+ A hosted sandbox clones your repo into a clean environment. Bivy runs in the
43
+ environment you already use: the current working tree, running services, and
44
+ warm caches.
41
45
 
42
46
  | | Cloud sandbox | Bivy Machine |
43
47
  |---|---|---|
@@ -48,62 +52,56 @@ running, the caches already warm.
48
52
  | GPUs / local inference | rented separately | the ones on your box |
49
53
  | Where your code sits | someone else's infrastructure | the machine you already trust |
50
54
 
51
- You keep the environment. Bivy adds the part that was missing: **reaching that
52
- environment from anywhere, and leaving it working while you're gone.**
55
+ Bivy lets you leave that environment running and reach it from anywhere.
53
56
 
54
57
  ## What you can do
55
58
 
56
- Bivy gives you two ways to put an agent to work.
59
+ Every task in Bivy becomes a Session on a Machine you choose. Start it from the
60
+ terminal, browser, phone, or an external trigger. Join it while it runs, or let
61
+ it finish in the background.
57
62
 
58
- ### Sessions — interactive, and portable
63
+ ### Sessions
59
64
 
60
- Start an agent, watch it work, jump in to steer, stop, or approve. Then leave
61
- your desk and keep going:
65
+ Start an agent, watch it work, steer it, stop it, or approve a tool call. You can
66
+ leave your desk and keep the Session open:
62
67
 
63
68
  ```bash
64
69
  bivy run claude # or codex, pi, gemini, and a dozen more
65
70
  bivy open # continue the same session in the browser or PWA
66
71
  bivy resume # pick it back up in the terminal
67
72
  bivy run claude --no-follow # start it in the background instead of attaching
68
- bivy run claude --chat # start the governed app session and open it in the browser
73
+ bivy run claude --chat # start a chat session and open it in the browser
69
74
  ```
70
75
 
71
- - **Reconnect from anywhere** — phone, browser, or another terminal — to the
72
- same live Session. The PWA adds voice input, read-aloud, phone-to-agent
73
- file/image uploads, and agent-to-phone attachments.
74
- - **Move work without starting over.** Import existing Claude Code and Codex
75
- Sessions, or fork, copy, and move a Bivy Session to another agent, model, or
76
- Machine.
77
- - **Run more than one Machine** — a workstation, a private-network server, a GPU
78
- box — on one account, and pick the environment each Session needs.
76
+ - Reconnect to the same Session from a phone, browser, or terminal.
77
+ - Upload files and images from your phone, or download files the agent creates.
78
+ - Import existing Claude Code and Codex Sessions.
79
+ - Fork or move a Session to another agent, model, or Machine.
80
+ - Connect several Machines, such as a workstation, server, or GPU box.
79
81
 
80
- ### Runs — unattended, and accountable
82
+ ### Runs
81
83
 
82
- Queue one on demand, or let an event kick it off — either way it returns
83
- immediately and reports back:
84
+ A Run is a Session started as a background job. Start one yourself or trigger it
85
+ from another service; Bivy queues it and returns immediately:
84
86
 
85
87
  ```bash
86
88
  bivy runs start "..." # queue a one-off unattended Run, then `bivy runs wait <id>`
87
- bivy automation init # or define governed jobs in .bivy/automations.yaml
89
+ bivy automation init # define jobs in .bivy/automations.yaml
88
90
  ```
89
91
 
90
- - **Trigger from real events** — a failed CI job, a GitHub or Linear issue,
91
- Slack, a schedule, or a signed webhook.
92
- - **Pin the guardrails** — Machine, agent, model, sandbox, approval mode, and a
93
- hard attempt ceiling — right next to the job.
94
- - **Get a Receipt** — every Run reports the checks it ran and how it turned out,
95
- not just a wall of output.
92
+ - Trigger Runs from GitHub, Linear, Slack, a schedule, CI, or a signed webhook.
93
+ - Choose the Machine, agent, model, sandbox, approval mode, and retry limit.
94
+ - Review the changed files, checks, and final result in a Receipt.
96
95
 
97
- Try the [capability recipes](docs/capability-recipes.md) to see each of these
98
- end to end, or the [runtime support matrix](docs/runtime-support-matrix.md) for
99
- exactly what each agent supports.
96
+ See the [capability recipes](docs/capability-recipes.md) for examples and the
97
+ [runtime support matrix](docs/runtime-support-matrix.md) for per-agent support.
100
98
 
101
- ## Bring your own stack
99
+ ## Bring your own agents and models
102
100
 
103
- Use provider subscriptions through native agent logins, API keys stored in
104
- Bivy's vault, or local / OpenAI-compatible inference. Claude Code, Codex, and Pi
105
- have first-class SDK integrations; any other ACP or headless agent needs no
106
- adapter at all — it's a data row you add with one command:
101
+ Use your existing agent login, an API key in Bivy's vault, or a local
102
+ OpenAI-compatible server. Claude Code, Codex, Pi, and OpenCode have release-tested
103
+ integrations. Other agents run through ACP or a headless process adapter. Add
104
+ your own with:
107
105
 
108
106
  ```bash
109
107
  bivy agent add # register an existing ACP or process agent
@@ -115,28 +113,25 @@ bivy agent add # register an existing ACP or process agent
115
113
  curl -fsSL https://bivy.sh/install.sh | bash
116
114
  ```
117
115
 
118
- macOS and Linux. Requires Node.js 20 or newer. The installer puts the
119
- [`@bivy/bivy`](https://www.npmjs.com/package/@bivy/bivy) npm package and the
120
- `bivy` command on your `PATH` with optional bridges skipped for speed, then runs
121
- `bivy setup` — agent choice, selected-agent install if needed, remote access,
122
- and an auto-start background service (launchd on macOS, systemd on Linux).
123
-
124
- If Claude Code, Codex, OpenCode, Gemini, or another agent is already installed,
125
- setup says so and uses that existing CLI, login, and configuration. Bivy does
126
- not replace the agent or copy its native credentials; it adds remote continuity
127
- and governance around the agent you already use. Re-running the installer on a
128
- machine that already has Bivy just applies the latest build and restarts the
129
- service.
130
-
131
- **What needs an account, and what doesn't.** The CLI alone — `bivy run`,
132
- `bivy resume`, `bivy sessions` — needs no account and no server; `bivy setup`
133
- lets you pick **local only for now** and skip remote access. A browser or phone
134
- UI needs a control plane, because the node hosts none: use the hosted one at
135
- `app.bivy.sh` (sign in with GitHub or email; free tier plus a paid plan — see
136
- [bivy.sh#pricing](https://bivy.sh#pricing)) or
137
- [self-host your own](docs/self-host-quickstart.md). Switch any time with
116
+ Bivy supports macOS and Linux and requires Node.js 20 or newer. The installer
117
+ adds the [`@bivy/bivy`](https://www.npmjs.com/package/@bivy/bivy) package and
118
+ `bivy` command, then runs `bivy setup`. Setup asks which agent to use, installs
119
+ it if needed, configures remote access, and starts a launchd or systemd service.
120
+
121
+ If an agent is already installed, Bivy uses its existing command, login, and
122
+ configuration. Re-running the installer updates Bivy and restarts the service.
123
+
124
+ **Local and remote use.** `bivy run`, `bivy resume`, and `bivy sessions` work
125
+ without an account or server. During setup, choose **local only for now** to skip
126
+ remote access. The browser and phone apps need a control plane: use
127
+ [app.bivy.sh](https://app.bivy.sh) or
128
+ [self-host one](docs/self-host-quickstart.md). You can switch later with
138
129
  `bivy relay:setup`.
139
130
 
131
+ Self-hosted Bivy Core is open source and has no usage limits. Bivy Cloud offers
132
+ a managed app, relay, and hosted Machines; see
133
+ [bivy.sh#pricing](https://bivy.sh#pricing) for details.
134
+
140
135
  Prefer to inspect the installer first?
141
136
 
142
137
  ```bash
@@ -145,8 +140,7 @@ less install.sh
145
140
  bash install.sh
146
141
  ```
147
142
 
148
- **What the installer does with sudo.** It escalates only when it must, and
149
- tells you when it does:
143
+ **When the installer uses sudo:**
150
144
 
151
145
  - Debian/Ubuntu without a suitable Node.js: `sudo apt-get install curl
152
146
  ca-certificates`, then NodeSource's Node 22 setup script via `sudo`.
@@ -170,9 +164,7 @@ origin with `npm audit signatures`. See [`docs/releasing.md`](docs/releasing.md)
170
164
 
171
165
  ### Your first session
172
166
 
173
- Once `bivy setup` finishes, use Bivy from inside an existing repo. The first win
174
- is simple: start the local agent, give it a real task in that environment, then
175
- reopen the same Session from another surface.
167
+ After setup, start Bivy inside an existing repo:
176
168
 
177
169
  ```bash
178
170
  cd your-repo
@@ -216,9 +208,8 @@ management, and uninstall.
216
208
  bivy update
217
209
  ```
218
210
 
219
- `bivy update` detects how Bivy was installed and does the right thing, then
220
- waits for any active session to finish its current turn and restarts the
221
- background service so the node reconnects on the new build:
211
+ `bivy update` uses the same install method you used originally. It waits for an
212
+ active turn to finish, updates Bivy, and restarts the background service:
222
213
 
223
214
  | Install kind | What `bivy update` does |
224
215
  |---|---|
@@ -238,12 +229,12 @@ bivy update --stable # move back to production (latest)
238
229
  bivy update --force # don't wait for an in-flight turn to finish
239
230
  ```
240
231
 
241
- The daemon also checks the registry periodically and posts an in-session notice
242
- when a newer build is available.
232
+ The daemon checks for new releases and posts an update notice in the Session.
243
233
 
244
234
  ## Architecture
245
235
 
246
- Bivy has three parts. **Only the first one holds your data.**
236
+ Bivy has three parts. For normal interactive Sessions, code, credentials, and
237
+ transcripts stay on the node.
247
238
 
248
239
  ```text
249
240
  your machine hosted or self-hosted
@@ -266,24 +257,26 @@ Bivy has three parts. **Only the first one holds your data.**
266
257
  - **Control plane** — holds your account, node registry, and session index, and
267
258
  serves the web/PWA client. Use the hosted one or run your own.
268
259
 
269
- Because the node serves no UI, a browser or phone needs a control plane — hosted
270
- at `app.bivy.sh`, or one you deploy yourself. The terminal CLI needs neither.
271
- Interactive Session traffic is end-to-end encrypted between a Machine and its
272
- paired devices: the relay never sees plaintext and cannot decrypt it. Who can
273
- *authorize* a device depends on how you pair — with a QR / `bivy link` pairing,
274
- or on a self-hosted deployment, the control plane can't read your Sessions
275
- either; with hosted account sign-in you trust the control plane to authorize
276
- devices and to serve the web app that holds the keys. See
277
- [known limitations](docs/security-model.md#known-limitations-for-0x).
260
+ The node has no web UI. The browser and phone apps come from `app.bivy.sh` or
261
+ your own control plane; the terminal CLI needs neither. Session traffic is
262
+ end-to-end encrypted between the node and paired devices, so the relay cannot
263
+ read it.
264
+
265
+ QR pairing with `bivy link` lets the node authorize the device directly. Hosted
266
+ account pairing trusts the control plane to authorize devices and serve the web
267
+ app that holds the keys. Read the
268
+ [known limitations](docs/security-model.md#known-limitations-for-0x) before using
269
+ Bivy with sensitive work.
278
270
 
279
271
  See [`docs/remote-access.md`](docs/remote-access.md) and
280
272
  [`docs/security-model.md`](docs/security-model.md).
281
273
 
282
274
  ## Supported agents
283
275
 
284
- **Bivy maintains wrappers for the popular coding agents below.** Claude Code,
285
- Codex, Pi, and OpenCode have the richest release-tested capability sets today;
286
- capabilities and fidelity still vary by runtime.
276
+ **Claude Code, Codex, Pi, and OpenCode are the release-tested paths.** The other
277
+ adapters are maintained, but their features vary. Check the
278
+ [runtime support matrix](docs/runtime-support-matrix.md) for resume, models,
279
+ approvals, sandboxing, and test status.
287
280
 
288
281
  | Agent | Command | Notes |
289
282
  |---|---|---|
@@ -307,20 +300,14 @@ capabilities and fidelity still vary by runtime.
307
300
  | Kilo Code | `bivy run kilocode` | ACP-capable |
308
301
  | Rovo Dev | `bivy run rovodev` | Installed out of band |
309
302
 
310
- Also defined but hidden from the picker as *Experimental* — runnable via
311
- `BIVY_RUNTIME=<id>`: Codebuff (`codebuff`, no verified headless mode upstream
312
- yet), Hermes (`hermes`, generic process adapter), and OpenClaw (`openclaw`,
313
- CLI adapter only, no resume yet).
303
+ Codebuff, Hermes, and OpenClaw are experimental and hidden from the picker.
304
+ Run them with `BIVY_RUNTIME=<id>`.
314
305
 
315
- Any other command works via `bivy run -- ./your-agent --flags`. ACP-capable
316
- agents can be promoted to Bivy's governed protocol path for per-tool approvals
317
- and native resume. To add a reusable process or ACP agent to both the CLI and web
318
- picker without changing Bivy, run `bivy agent add`, or scaffold and install a
319
- declarative [plugin manifest](docs/plugins.md) with `bivy plugin init`
320
- (declarative plugins are Experimental, `v1alpha1`, and run out of process).
306
+ Run any command with `bivy run -- ./your-agent --flags`. For a reusable entry in
307
+ the CLI and web picker, use `bivy agent add`. You can also create an experimental
308
+ `v1alpha1` [plugin manifest](docs/plugins.md) with `bivy plugin init`.
321
309
 
322
- [`docs/runtime-support-matrix.md`](docs/runtime-support-matrix.md) lists exactly
323
- what each agent supports — resume, model selection, approvals, sandboxing.
310
+ See the [runtime support matrix](docs/runtime-support-matrix.md) for details.
324
311
 
325
312
  ## Common commands
326
313
 
@@ -352,8 +339,7 @@ BIVY_SANDBOX=read-only # read-only | workspace-write (default) | danger
352
339
  BIVY_APPROVAL_MODE=risky # never | risky | always | autonomous (default)
353
340
  ```
354
341
 
355
- Create and inspect the typed node configuration, or add repository-owned
356
- safety/check/retry policy:
342
+ Manage node settings or add repo-specific checks and safety rules:
357
343
 
358
344
  ```bash
359
345
  bivy config init
@@ -368,19 +354,18 @@ variable and precedence rule lives in
368
354
 
369
355
  ## Approvals and sandboxing
370
356
 
371
- The default approval mode is **`autonomous`**: agents act without per-action
372
- prompts. How much that actually protects you depends on the runtime. Native-sandbox
373
- agents enforce the chosen access tier; structured runtimes also pass tool calls
374
- through Bivy's policy and approval layer. Process agents that Bivy cannot
375
- intercept run with your OS user permissions — the picker flags this and requires
376
- confirmation before you pick that path.
357
+ The default approval mode is **`autonomous`**, so most actions do not prompt.
358
+ Protection depends on the agent. Some agents enforce Bivy's sandbox setting;
359
+ others expose tool calls that Bivy can approve or deny. A process agent that
360
+ Bivy cannot intercept runs with your user permissions. The picker shows which
361
+ case applies and asks for confirmation on unprotected paths.
377
362
 
378
- Where Bivy receives structured shell/file calls, a heuristic floor blocks known
379
- catastrophic commands and structured writes outside the workspace, and a
380
- backstop set (force-push, publish, deploy, sudo) pauses for a human. This catches
381
- accidents; **it is not an adversarial isolation boundary.**
363
+ For tool calls it can see, Bivy blocks destructive system commands and writes
364
+ outside the workspace. It asks before force pushes, publishing, deployments,
365
+ and `sudo`. These checks help prevent accidents. **They are not a security
366
+ sandbox.**
382
367
 
383
- Want to be asked about more? Set the mode explicitly:
368
+ To see more prompts, change the approval mode:
384
369
 
385
370
  ```bash
386
371
  BIVY_APPROVAL_MODE=risky # prompt on risky shell commands and file edits
@@ -390,12 +375,11 @@ BIVY_APPROVAL_MODE=never # no prompts; structured-tool heuristic blocks still
390
375
 
391
376
  Approve from the terminal, browser, or phone.
392
377
 
393
- Sandbox tiers (`read-only`, `workspace-write`, `danger-full-access`) are enforced
394
- natively by agents that support them — Codex, Claude Code, Gemini CLI, Qwen Code.
395
- Agents without a native sandbox may expose structured tool or MCP controls, but
396
- those don't cover activity the agent performs outside those channels; some
397
- process adapters run entirely with your user permissions. Check the picker's
398
- Protection label. **Bivy does not currently ship its own OS-level jail.**
378
+ Codex, Claude Code, Gemini CLI, and Qwen Code enforce the `read-only`,
379
+ `workspace-write`, and `danger-full-access` tiers themselves. Other agents may
380
+ run with your full user permissions even when Bivy can inspect some tool calls.
381
+ Check the Protection label in the picker. **Bivy does not provide an OS-level
382
+ sandbox.**
399
383
 
400
384
  ## Credentials
401
385
 
@@ -409,20 +393,19 @@ bivy secrets ref github.repo-token op://Bivy/GitHub/repo-token
409
393
  bivy secrets doctor
410
394
  ```
411
395
 
412
- `secret://`, `env://`, and `op://` (1Password) references resolve on demand when
413
- the daemon provisions an agent run, so raw values never sit in your config.
396
+ `secret://`, `env://`, and `op://` (1Password) references are resolved only when
397
+ an agent needs them, so the raw values do not appear in config files.
414
398
 
415
- **One deliberate exception to relay blindness:** if you explicitly enable hosted
416
- unattended provisioning, Bivy Cloud may store encrypted cloud, repository,
417
- model, or key-escrow material that the service can technically access. Treat this
418
- as an explicit hosted-custody mode. See the
399
+ Hosted unattended provisioning is different from normal interactive Sessions.
400
+ If you enable it, Bivy Cloud may hold encrypted cloud, repository, model, or
401
+ key-escrow data that the service can access. See the
419
402
  [security model](docs/security-model.md#what-the-control-plane-sees) and
420
- [`docs/key-management.md`](docs/key-management.md).
403
+ [key-management guide](docs/key-management.md).
421
404
 
422
405
  ## Automations as code
423
406
 
424
- Define governed jobs in `.bivy/automations.yaml`, validate them, and simulate
425
- trigger events locally before applying anything:
407
+ Define jobs in `.bivy/automations.yaml`, validate them, and test trigger events
408
+ locally:
426
409
 
427
410
  ```bash
428
411
  bivy automation init
@@ -431,19 +414,18 @@ bivy automation test --event .bivy/events/failed-ci.yaml
431
414
  bivy automation apply
432
415
  ```
433
416
 
434
- Instructions are encrypted on the applying node before upload. Safety policy
435
- lives beside the job — sandbox, approval mode, and a hard attempt ceiling that
436
- retry/fallback rules cannot exceed. See
417
+ Bivy encrypts instructions on the node before upload. Each job records its
418
+ sandbox, approval mode, and maximum number of attempts. See
437
419
  [`docs/automations-as-code.md`](docs/automations-as-code.md).
438
420
 
439
421
  ## GitHub Runs
440
422
 
441
423
  Label an issue `bivy` (or `bivy/<machine>` to target a Machine), or mention the
442
424
  Bivy GitHub App in a comment. Bivy creates a Run on the selected Machine, uses an
443
- isolated worktree, executes configured checks, and reports an explicit outcome.
425
+ isolated worktree, runs the configured checks, and posts the result.
444
426
 
445
- Core applies no commercial usage limits. Bivy Cloud billing and commercial
446
- policy live in the separate Cloud repository.
427
+ Core has no usage limits. Hosted pricing is managed in the separate Cloud
428
+ repository.
447
429
 
448
430
  A private GitHub App only installs on the account that owns it, so connect one
449
431
  app per GitHub account — one for your personal repos, one per organization
package/bin/bivy.mjs CHANGED
@@ -39,6 +39,8 @@ import { renderManagedBlock, upsertManagedBlock, removeManagedBlock, rcFileForSh
39
39
  import { removeInstallAndState } from "./uninstall-paths.mjs";
40
40
  import { findAvailablePort, reconcilePort } from "./port-picker.mjs";
41
41
  import { resolveAttachSessionId } from "./attach-session-id.mjs";
42
+ import { detectInstallKind as classifyInstallKind } from "./install-kind.mjs";
43
+ import { hasConfiguredService as configuredServiceExists } from "./service-state.mjs";
42
44
 
43
45
  const selfScript = fileURLToPath(import.meta.url);
44
46
  const __dirname = path.dirname(selfScript);
@@ -69,14 +71,10 @@ process.env.BIVY_DATA_DIR = appDir;
69
71
  // background service can point at repoRoot:
70
72
  // - "git" dev checkout (has .git)
71
73
  // - "npx" ephemeral `npx bivy` run (repoRoot under an npm _npx cache)
72
- // - "npm-global" `npm i -g @bivy/bivy` (repoRoot's parent dir is node_modules)
74
+ // - "npm-global" `npm i -g @bivy/bivy` (repoRoot is below node_modules/@bivy)
73
75
  // - "packaged" install.sh tarball tree (user-owned, self-preserving)
74
76
  function detectInstallKind() {
75
- if (fs.existsSync(path.join(repoRoot, ".git"))) return "git";
76
- const inNodeModules = path.basename(path.dirname(repoRoot)) === "node_modules";
77
- if (inNodeModules && /[\\/]_npx[\\/]/.test(repoRoot)) return "npx";
78
- if (inNodeModules) return "npm-global";
79
- return "packaged";
77
+ return classifyInstallKind(repoRoot);
80
78
  }
81
79
  const cliConfigPath = path.join(appDir, "cli.json");
82
80
  const canonicalConfigPath = path.join(appDir, "config.yaml");
@@ -3254,6 +3252,10 @@ async function reconcileNodePort(config) {
3254
3252
  // reloads/relaunches). Otherwise a plain restart. Returns true if the service
3255
3253
  // was (re)started. Used by `bivy restart` and `bivy update` — the paths that
3256
3254
  // previously trusted the saved port verbatim.
3255
+ function hasConfiguredService(config) {
3256
+ return configuredServiceExists(config, servicePaths().file);
3257
+ }
3258
+
3257
3259
  async function restartServiceReconciled(config) {
3258
3260
  const { kind, file } = servicePaths();
3259
3261
  if (!fs.existsSync(file)) return restartService();
@@ -4442,7 +4444,7 @@ async function runUpdate(args = []) {
4442
4444
  await ensureKnownAgents();
4443
4445
  const config = loadConfig();
4444
4446
  await waitForIdleSessions(config, { skip: skipWait });
4445
- if (config.service && (await restartServiceReconciled(config))) {
4447
+ if (hasConfiguredService(config) && (await restartServiceReconciled(config))) {
4446
4448
  if (await verifyNodeCameUp(config)) {
4447
4449
  console.log(c.green("Updated and restarted the background service."));
4448
4450
  } else {
@@ -4474,7 +4476,7 @@ async function runUpdate(args = []) {
4474
4476
  });
4475
4477
  // install.sh restarts the service itself; verify the node actually came up
4476
4478
  // rather than trusting the installer's exit code over a crash-looping node.
4477
- if (code === 0 && config.service && !(await verifyNodeCameUp(config))) {
4479
+ if (code === 0 && hasConfiguredService(config) && !(await verifyNodeCameUp(config))) {
4478
4480
  reportNodeDidNotStart();
4479
4481
  process.exit(1);
4480
4482
  }
@@ -4490,7 +4492,7 @@ async function runUpdate(args = []) {
4490
4492
  await ensureKnownAgents();
4491
4493
  const config = loadConfig();
4492
4494
  await waitForIdleSessions(config, { skip: skipWait });
4493
- if (config.service && (await restartServiceReconciled(config))) {
4495
+ if (hasConfiguredService(config) && (await restartServiceReconciled(config))) {
4494
4496
  if (await verifyNodeCameUp(config)) {
4495
4497
  console.log(c.green("Updated and restarted the background service."));
4496
4498
  } else {
@@ -0,0 +1,20 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (c) 2026 Petter André Sjulstad
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+
6
+ /** Classify a Bivy package root without assuming unscoped npm package layout. */
7
+ export function detectInstallKind(repoRoot, existsSync = fs.existsSync) {
8
+ if (existsSync(path.join(repoRoot, ".git"))) return "git";
9
+
10
+ // npm installs an unscoped package at node_modules/name and a scoped package
11
+ // at node_modules/@scope/name. Bivy uses the latter layout.
12
+ const parent = path.dirname(repoRoot);
13
+ const grandparent = path.dirname(parent);
14
+ const inNodeModules = path.basename(parent) === "node_modules"
15
+ || (path.basename(parent).startsWith("@") && path.basename(grandparent) === "node_modules");
16
+
17
+ if (inNodeModules && /[\\/]_npx[\\/]/.test(repoRoot)) return "npx";
18
+ if (inNodeModules) return "npm-global";
19
+ return "packaged";
20
+ }
@@ -0,0 +1,12 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (c) 2026 Petter André Sjulstad
3
+ import fs from "node:fs";
4
+
5
+ /**
6
+ * Whether an install has a background service that an update must restart.
7
+ * The on-disk unit/plist is authoritative; cli.json.service is only a hint and
8
+ * may be absent on migrated installs.
9
+ */
10
+ export function hasConfiguredService(config, serviceFile, existsSync = fs.existsSync) {
11
+ return Boolean(config?.service) || existsSync(serviceFile);
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.16.1-staging.2",
3
+ "version": "0.16.1-staging.4",
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.",
@@ -66,6 +66,6 @@
66
66
  "nanoid": "3.3.18",
67
67
  "undici": "8.10.0"
68
68
  },
69
- "readme": "# Bivy\n\n[![npm](https://img.shields.io/npm/v/@bivy/bivy?color=2b6cb0&label=%40bivy%2Fbivy)](https://www.npmjs.com/package/@bivy/bivy)\n[![license: AGPL-3.0-only](https://img.shields.io/badge/license-AGPL--3.0--only-2b6cb0)](LICENSE)\n[![node](https://img.shields.io/badge/node-%E2%89%A520-2b6cb0)](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\ncd your-repo\nbivy run claude # start an agent where your work lives\nbivy open # pick it up from your phone or browser\n```\n\nFirst thing to try: ask the agent to explain the repository, make one small safe\nchange, then open the same Session in the web app or on your phone while it runs.\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. Claude Code, Codex, and Pi\nhave first-class SDK integrations; any other ACP or headless agent needs no\nadapter at all — it's a data row you add with one command:\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 20 or newer. The installer puts the\n[`@bivy/bivy`](https://www.npmjs.com/package/@bivy/bivy) npm package and the\n`bivy` command on your `PATH` with optional bridges skipped for speed, then runs\n`bivy setup` — agent choice, selected-agent install if needed, remote access,\nand an auto-start background service (launchd on macOS, systemd on Linux).\n\nIf Claude Code, Codex, OpenCode, Gemini, or another agent is already installed,\nsetup says so and uses that existing CLI, login, and configuration. Bivy does\nnot replace the agent or copy its native credentials; it adds remote continuity\nand governance around the agent you already use. Re-running the installer on a\nmachine that already has Bivy just applies the latest build and restarts the\nservice.\n\n**What needs an account, and what doesn't.** The CLI alone — `bivy run`,\n`bivy resume`, `bivy sessions` — needs no account and no server; `bivy setup`\nlets you pick **local only for now** and skip remote access. A browser or phone\nUI needs a control plane, because the node hosts none: use the hosted one at\n`app.bivy.sh` (sign in with GitHub or email; free tier plus a paid plan — see\n[bivy.sh#pricing](https://bivy.sh#pricing)) or\n[self-host your own](docs/self-host-quickstart.md). Switch any time with\n`bivy relay:setup`.\n\nPrefer to inspect the installer first?\n\n```bash\ncurl -fsSL https://bivy.sh/install.sh -o install.sh\nless install.sh\nbash install.sh\n```\n\n**What the installer does with sudo.** It escalates only when it must, and\ntells you when it does:\n\n- Debian/Ubuntu without a suitable Node.js: `sudo apt-get install curl\n ca-certificates`, then NodeSource's Node 22 setup script via `sudo`.\n- Other Linux, or macOS, without a suitable Node.js: downloads the official\n Node 22 tarball from nodejs.org (sha256-checked) and installs it under\n `/usr/local` with `sudo`.\n- If npm's global prefix isn't writable it falls back to `~/.local` — it never\n runs `npm install` under `sudo`.\n- It appends a marked PATH block to `~/.bashrc` or `~/.zshrc`\n (`BIVY_NO_RC_UPDATE=1` to opt out).\n\nWant no sudo at all? Bring your own Node.js 20+ and skip the script:\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, use Bivy from inside an existing repo. The first win\nis simple: start the local agent, give it a real task in that environment, then\nreopen the same Session from another surface.\n\n```bash\ncd your-repo\nbivy run claude # start an agent as a durable session in the current repo\n# Try: \"Explain this repo and suggest one small, safe improvement.\"\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 the npm package into a user-owned prefix | `BIVY_NPM_PREFIX=~/.local` |\n| Preinstall every known upstream agent | `BIVY_INSTALL_ALL_AGENTS=1` |\n| Install optional Bivy bridges/native terminal dependency up front | `BIVY_INSTALL_OPTIONAL_DEPS=1` |\n| Don't touch `~/.bashrc` / `~/.zshrc`; print the PATH line instead | `BIVY_NO_RC_UPDATE=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: the relay never sees plaintext and cannot decrypt it. Who can\n*authorize* a device depends on how you pair — with a QR / `bivy link` pairing,\nor on a self-hosted deployment, the control plane can't read your Sessions\neither; with hosted account sign-in you trust the control plane to authorize\ndevices and to serve the web app that holds the keys. See\n[known limitations](docs/security-model.md#known-limitations-for-0x).\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**Bivy maintains wrappers for the popular coding agents below.** Claude Code,\nCodex, Pi, and OpenCode have the richest release-tested capability sets today;\ncapabilities and fidelity still vary 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\nAlso defined but hidden from the picker as *Experimental* — runnable via\n`BIVY_RUNTIME=<id>`: Codebuff (`codebuff`, no verified headless mode upstream\nyet), Hermes (`hermes`, generic process adapter), and OpenClaw (`openclaw`,\nCLI adapter only, no resume yet).\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 community-supported** — no SLA, best-effort help via GitHub\nissues. You own TLS, backups, upgrades, and hardening. Start with the\none-command VPS path in\n[`docs/self-host-quickstart.md`](docs/self-host-quickstart.md); the ops\nreference (backups, rotation, security boundary) is\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\n**Where the open-core line is.** Everything in this repository — node, CLI,\nrelay, control plane, and the web/PWA client — is AGPL Core, with no usage\nlimits. **Bivy Cloud** is the hosted operation of that stack plus billing and\nplans, and lives in a separate private repository. Contributions are accepted\nunder the [DCO](CONTRIBUTING.md#certificate-of-origin); there is no CLA.\n",
69
+ "readme": "# Bivy\n\n[![npm](https://img.shields.io/npm/v/@bivy/bivy?color=2b6cb0&label=%40bivy%2Fbivy)](https://www.npmjs.com/package/@bivy/bivy)\n[![license: AGPL-3.0-only](https://img.shields.io/badge/license-AGPL--3.0--only-2b6cb0)](LICENSE)\n[![node](https://img.shields.io/badge/node-%E2%89%A520-2b6cb0)](https://nodejs.org)\n\n**Run coding agents on your machines and use them from anywhere — from a phone,\nbrowser, terminal, GitHub issue, Slack message, schedule, or webhook.**\n\nStart Claude Code on your workstation, next to the repo, dev server, and\ndatabase you already use. Walk away. From your phone, you can see what it did,\nanswer a question, or approve a migration. CI or a webhook can start the next\njob on the right Machine without waiting for you to return.\n\n```bash\ncurl -fsSL https://bivy.sh/install.sh | bash # install + guided setup\ncd your-repo\nbivy run claude # start an agent in this repo\nbivy open # open it in a browser or on your phone\n```\n\nBivy does not replace Claude Code, Codex, or the other agents you use. It keeps\ntheir Sessions running, routes work to the right Machine, and gives you one place\nto start, join, approve, and review work.\n\nFirst thing to try: ask the agent to explain the repository, make one small safe\nchange, then open the same Session in the web app or on your phone while it runs.\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> **Bivy is 0.x software.** Claude Code, Codex, Pi, and OpenCode are the\n> release-tested paths. Support for other agents varies; check the\n> [runtime support matrix](docs/runtime-support-matrix.md) before relying on a\n> specific feature.\n\n## Why not just a cloud sandbox?\n\nA hosted sandbox clones your repo into a clean environment. Bivy runs in the\nenvironment you already use: the current working tree, running services, and\nwarm caches.\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\nBivy lets you leave that environment running and reach it from anywhere.\n\n## What you can do\n\nEvery task in Bivy becomes a Session on a Machine you choose. Start it from the\nterminal, browser, phone, or an external trigger. Join it while it runs, or let\nit finish in the background.\n\n### Sessions\n\nStart an agent, watch it work, steer it, stop it, or approve a tool call. You can\nleave your desk and keep the Session open:\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 a chat session and open it in the browser\n```\n\n- Reconnect to the same Session from a phone, browser, or terminal.\n- Upload files and images from your phone, or download files the agent creates.\n- Import existing Claude Code and Codex Sessions.\n- Fork or move a Session to another agent, model, or Machine.\n- Connect several Machines, such as a workstation, server, or GPU box.\n\n### Runs\n\nA Run is a Session started as a background job. Start one yourself or trigger it\nfrom another service; Bivy queues it and returns immediately:\n\n```bash\nbivy runs start \"...\" # queue a one-off unattended Run, then `bivy runs wait <id>`\nbivy automation init # define jobs in .bivy/automations.yaml\n```\n\n- Trigger Runs from GitHub, Linear, Slack, a schedule, CI, or a signed webhook.\n- Choose the Machine, agent, model, sandbox, approval mode, and retry limit.\n- Review the changed files, checks, and final result in a Receipt.\n\nSee the [capability recipes](docs/capability-recipes.md) for examples and the\n[runtime support matrix](docs/runtime-support-matrix.md) for per-agent support.\n\n## Bring your own agents and models\n\nUse your existing agent login, an API key in Bivy's vault, or a local\nOpenAI-compatible server. Claude Code, Codex, Pi, and OpenCode have release-tested\nintegrations. Other agents run through ACP or a headless process adapter. Add\nyour own with:\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\nBivy supports macOS and Linux and requires Node.js 20 or newer. The installer\nadds the [`@bivy/bivy`](https://www.npmjs.com/package/@bivy/bivy) package and\n`bivy` command, then runs `bivy setup`. Setup asks which agent to use, installs\nit if needed, configures remote access, and starts a launchd or systemd service.\n\nIf an agent is already installed, Bivy uses its existing command, login, and\nconfiguration. Re-running the installer updates Bivy and restarts the service.\n\n**Local and remote use.** `bivy run`, `bivy resume`, and `bivy sessions` work\nwithout an account or server. During setup, choose **local only for now** to skip\nremote access. The browser and phone apps need a control plane: use\n[app.bivy.sh](https://app.bivy.sh) or\n[self-host one](docs/self-host-quickstart.md). You can switch later with\n`bivy relay:setup`.\n\nSelf-hosted Bivy Core is open source and has no usage limits. Bivy Cloud offers\na managed app, relay, and hosted Machines; see\n[bivy.sh#pricing](https://bivy.sh#pricing) for details.\n\nPrefer to inspect the installer first?\n\n```bash\ncurl -fsSL https://bivy.sh/install.sh -o install.sh\nless install.sh\nbash install.sh\n```\n\n**When the installer uses sudo:**\n\n- Debian/Ubuntu without a suitable Node.js: `sudo apt-get install curl\n ca-certificates`, then NodeSource's Node 22 setup script via `sudo`.\n- Other Linux, or macOS, without a suitable Node.js: downloads the official\n Node 22 tarball from nodejs.org (sha256-checked) and installs it under\n `/usr/local` with `sudo`.\n- If npm's global prefix isn't writable it falls back to `~/.local` — it never\n runs `npm install` under `sudo`.\n- It appends a marked PATH block to `~/.bashrc` or `~/.zshrc`\n (`BIVY_NO_RC_UPDATE=1` to opt out).\n\nWant no sudo at all? Bring your own Node.js 20+ and skip the script:\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\nAfter setup, start Bivy inside an existing repo:\n\n```bash\ncd your-repo\nbivy run claude # start an agent as a durable session in the current repo\n# Try: \"Explain this repo and suggest one small, safe improvement.\"\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 the npm package into a user-owned prefix | `BIVY_NPM_PREFIX=~/.local` |\n| Preinstall every known upstream agent | `BIVY_INSTALL_ALL_AGENTS=1` |\n| Install optional Bivy bridges/native terminal dependency up front | `BIVY_INSTALL_OPTIONAL_DEPS=1` |\n| Don't touch `~/.bashrc` / `~/.zshrc`; print the PATH line instead | `BIVY_NO_RC_UPDATE=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` uses the same install method you used originally. It waits for an\nactive turn to finish, updates Bivy, and restarts the background service:\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 checks for new releases and posts an update notice in the Session.\n\n## Architecture\n\nBivy has three parts. For normal interactive Sessions, code, credentials, and\ntranscripts stay on the node.\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\nThe node has no web UI. The browser and phone apps come from `app.bivy.sh` or\nyour own control plane; the terminal CLI needs neither. Session traffic is\nend-to-end encrypted between the node and paired devices, so the relay cannot\nread it.\n\nQR pairing with `bivy link` lets the node authorize the device directly. Hosted\naccount pairing trusts the control plane to authorize devices and serve the web\napp that holds the keys. Read the\n[known limitations](docs/security-model.md#known-limitations-for-0x) before using\nBivy with sensitive work.\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, Codex, Pi, and OpenCode are the release-tested paths.** The other\nadapters are maintained, but their features vary. Check the\n[runtime support matrix](docs/runtime-support-matrix.md) for resume, models,\napprovals, sandboxing, and test status.\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\nCodebuff, Hermes, and OpenClaw are experimental and hidden from the picker.\nRun them with `BIVY_RUNTIME=<id>`.\n\nRun any command with `bivy run -- ./your-agent --flags`. For a reusable entry in\nthe CLI and web picker, use `bivy agent add`. You can also create an experimental\n`v1alpha1` [plugin manifest](docs/plugins.md) with `bivy plugin init`.\n\nSee the [runtime support matrix](docs/runtime-support-matrix.md) for details.\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\nManage node settings or add repo-specific checks and safety rules:\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`**, so most actions do not prompt.\nProtection depends on the agent. Some agents enforce Bivy's sandbox setting;\nothers expose tool calls that Bivy can approve or deny. A process agent that\nBivy cannot intercept runs with your user permissions. The picker shows which\ncase applies and asks for confirmation on unprotected paths.\n\nFor tool calls it can see, Bivy blocks destructive system commands and writes\noutside the workspace. It asks before force pushes, publishing, deployments,\nand `sudo`. These checks help prevent accidents. **They are not a security\nsandbox.**\n\nTo see more prompts, change the approval mode:\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\nCodex, Claude Code, Gemini CLI, and Qwen Code enforce the `read-only`,\n`workspace-write`, and `danger-full-access` tiers themselves. Other agents may\nrun with your full user permissions even when Bivy can inspect some tool calls.\nCheck the Protection label in the picker. **Bivy does not provide an OS-level\nsandbox.**\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 are resolved only when\nan agent needs them, so the raw values do not appear in config files.\n\nHosted unattended provisioning is different from normal interactive Sessions.\nIf you enable it, Bivy Cloud may hold encrypted cloud, repository, model, or\nkey-escrow data that the service can access. See the\n[security model](docs/security-model.md#what-the-control-plane-sees) and\n[key-management guide](docs/key-management.md).\n\n## Automations as code\n\nDefine jobs in `.bivy/automations.yaml`, validate them, and test trigger events\nlocally:\n\n```bash\nbivy automation init\nbivy automation validate\nbivy automation test --event .bivy/events/failed-ci.yaml\nbivy automation apply\n```\n\nBivy encrypts instructions on the node before upload. Each job records its\nsandbox, approval mode, and maximum number of attempts. 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, runs the configured checks, and posts the result.\n\nCore has no usage limits. Hosted pricing is managed in the separate Cloud\nrepository.\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 community-supported** — no SLA, best-effort help via GitHub\nissues. You own TLS, backups, upgrades, and hardening. Start with the\none-command VPS path in\n[`docs/self-host-quickstart.md`](docs/self-host-quickstart.md); the ops\nreference (backups, rotation, security boundary) is\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\n**Where the open-core line is.** Everything in this repository — node, CLI,\nrelay, control plane, and the web/PWA client — is AGPL Core, with no usage\nlimits. **Bivy Cloud** is the hosted operation of that stack plus billing and\nplans, and lives in a separate private repository. Contributions are accepted\nunder the [DCO](CONTRIBUTING.md#certificate-of-origin); there is no CLA.\n",
70
70
  "readmeFilename": "README.md"
71
71
  }