@bivy/bivy 0.16.9-staging.2 → 0.16.9-staging.20
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 +12 -0
- package/bin/agent-manifest.json +1 -1
- package/bin/bivy.mjs +8 -2
- package/bin/install-kind.mjs +20 -0
- package/dist/agents/claude-code/integration.js +1 -1
- package/dist/agents/codex/integration.js +1 -1
- package/dist/agents/profiles.js +1 -1
- package/dist/certification/generated.js +3 -3
- package/dist/runtime/bivy-provider-catalog.js +2 -0
- package/dist/runtime/tool-call-map.js +21 -8
- package/dist/server.js +14 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -506,6 +506,18 @@ one-command VPS path in
|
|
|
506
506
|
reference (backups, rotation, security boundary) is
|
|
507
507
|
[`docs/self-host.md`](docs/self-host.md).
|
|
508
508
|
|
|
509
|
+
Prebuilt Core service images are public on GHCR:
|
|
510
|
+
|
|
511
|
+
```text
|
|
512
|
+
ghcr.io/bivysh/bivy-control-plane:<version-or-full-commit-sha>
|
|
513
|
+
ghcr.io/bivysh/bivy-relay:<version-or-full-commit-sha>
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
Use a release version for self-hosting or a full commit SHA for an immutable
|
|
517
|
+
build. `latest` moves only when a production release is promoted. Each tag
|
|
518
|
+
supports `linux/amd64` and `linux/arm64`; the images are built from this
|
|
519
|
+
repository with SBOM and provenance attestations.
|
|
520
|
+
|
|
509
521
|
## Security
|
|
510
522
|
|
|
511
523
|
Report vulnerabilities through [GitHub private vulnerability reporting](https://github.com/bivysh/bivy/security/advisories/new).
|
package/bin/agent-manifest.json
CHANGED
package/bin/bivy.mjs
CHANGED
|
@@ -41,7 +41,7 @@ import { renderManagedBlock, upsertManagedBlock, removeManagedBlock, rcFileForSh
|
|
|
41
41
|
import { removeInstallAndState } from "./uninstall-paths.mjs";
|
|
42
42
|
import { findAvailablePort, reconcilePort } from "./port-picker.mjs";
|
|
43
43
|
import { resolveAttachSessionId } from "./attach-session-id.mjs";
|
|
44
|
-
import { detectInstallKind as classifyInstallKind } from "./install-kind.mjs";
|
|
44
|
+
import { detectInstallKind as classifyInstallKind, npmGlobalPrefix } from "./install-kind.mjs";
|
|
45
45
|
import { hasConfiguredService as configuredServiceExists } from "./service-state.mjs";
|
|
46
46
|
|
|
47
47
|
const selfScript = fileURLToPath(import.meta.url);
|
|
@@ -4447,7 +4447,13 @@ async function runUpdate(args = []) {
|
|
|
4447
4447
|
|
|
4448
4448
|
if (kind === "npm-global") {
|
|
4449
4449
|
console.log(c.dim(`Updating the globally-installed bivy package (channel: ${channel})…`));
|
|
4450
|
-
|
|
4450
|
+
// npm's configured global prefix may not be the prefix that owns this
|
|
4451
|
+
// executable (for example, `npm config get prefix` can remain /usr after
|
|
4452
|
+
// installing Bivy with --prefix ~/.local). Always update the installation
|
|
4453
|
+
// that is actually running this command.
|
|
4454
|
+
const prefix = npmGlobalPrefix(repoRoot);
|
|
4455
|
+
const prefixArgs = prefix ? ["--prefix", prefix] : [];
|
|
4456
|
+
const code = await run("npm", ["install", "-g", ...prefixArgs, `@bivy/bivy@${channel}`, "--no-audit", "--no-fund"]);
|
|
4451
4457
|
if (code !== 0) {
|
|
4452
4458
|
console.log(c.yellow(`npm reported an issue (exit ${code}). Try: sudo npm i -g @bivy/bivy@${channel}`));
|
|
4453
4459
|
process.exit(code);
|
package/bin/install-kind.mjs
CHANGED
|
@@ -18,3 +18,23 @@ export function detectInstallKind(repoRoot, existsSync = fs.existsSync) {
|
|
|
18
18
|
if (inNodeModules) return "npm-global";
|
|
19
19
|
return "packaged";
|
|
20
20
|
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Return the npm prefix that owns a package installed below node_modules.
|
|
24
|
+
* npm uses <prefix>/lib/node_modules on Unix and <prefix>/node_modules on
|
|
25
|
+
* other platforms. The running npm process may have a different configured
|
|
26
|
+
* prefix, so deriving it from the package path is important for user-local
|
|
27
|
+
* installs.
|
|
28
|
+
*/
|
|
29
|
+
export function npmGlobalPrefix(repoRoot) {
|
|
30
|
+
let current = path.resolve(repoRoot);
|
|
31
|
+
while (true) {
|
|
32
|
+
if (path.basename(current) === "node_modules") {
|
|
33
|
+
const parent = path.dirname(current);
|
|
34
|
+
return path.basename(parent) === "lib" ? path.dirname(parent) : parent;
|
|
35
|
+
}
|
|
36
|
+
const parent = path.dirname(current);
|
|
37
|
+
if (parent === current) return undefined;
|
|
38
|
+
current = parent;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -4,7 +4,7 @@ import { defineAgentIntegration } from "../definition.js";
|
|
|
4
4
|
import { withExactCapabilitySurface } from "../../runtime/types.js";
|
|
5
5
|
import { createCredentialStore } from "../../runtime/credentials.js";
|
|
6
6
|
import { ClaudeCodeRuntime, claudeRuntimeFromEnv, claudeSdkInstalled, } from "./runtime.js";
|
|
7
|
-
export const CLAUDE_TESTED_VERSION = "0.3.
|
|
7
|
+
export const CLAUDE_TESTED_VERSION = "0.3.258";
|
|
8
8
|
const CLAUDE_CAPABILITIES = withExactCapabilitySurface({
|
|
9
9
|
toolInterception: true,
|
|
10
10
|
modelSelection: true,
|
|
@@ -9,7 +9,7 @@ import { codexCredentialPreflight } from "../../runtime/codex-preflight.js";
|
|
|
9
9
|
import { deleteCodexSession, discoverNativeCodexSessions, loadCodexTranscript, writeCodexRollout, exportCodexRollout, importCodexRollout, } from "../../runtime/codex-sessions.js";
|
|
10
10
|
import { ProtocolRuntime } from "../../runtime/protocol.js";
|
|
11
11
|
import { codexSlashCommands } from "../../runtime/slash-commands.js";
|
|
12
|
-
export const CODEX_TESTED_VERSION = "0.
|
|
12
|
+
export const CODEX_TESTED_VERSION = "0.152.1";
|
|
13
13
|
const CODEX_AVAILABLE_CACHE = new Map();
|
|
14
14
|
function codexCommand() {
|
|
15
15
|
return process.env.BIVY_CODEX_BIN?.trim() || "codex";
|
package/dist/agents/profiles.js
CHANGED
|
@@ -43,7 +43,7 @@ export const AGENT_PROFILES = {
|
|
|
43
43
|
// Approve/Deny + session/load resume + a real model picker), the same bar Pi,
|
|
44
44
|
// Claude Code, and Codex clear. See `acp` below for the version fallback.
|
|
45
45
|
supportTier: "supported",
|
|
46
|
-
testedVersion: "1.18.
|
|
46
|
+
testedVersion: "1.18.27",
|
|
47
47
|
blurb: "The most widely used open-source coding harness (OpenCode CLI).",
|
|
48
48
|
// `opencode run -s <id> "<prompt>"` continues a prior session by its own id
|
|
49
49
|
// (`-s, --session session id to continue`, per `opencode run --help`).
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
export const CERTIFICATION_MATRIX = {
|
|
4
4
|
schemaVersion: 1,
|
|
5
5
|
agents: [
|
|
6
|
-
{ id: "claude-code-sdk", status: "active", executionMode: "protocol", pinnedVersion: "0.3.
|
|
7
|
-
{ id: "codex-approvals", status: "active", executionMode: "protocol", pinnedVersion: "0.
|
|
6
|
+
{ id: "claude-code-sdk", status: "active", executionMode: "protocol", pinnedVersion: "0.3.258", capabilities: ["toolInterception", "modelSelection", "resume"] },
|
|
7
|
+
{ id: "codex-approvals", status: "active", executionMode: "protocol", pinnedVersion: "0.152.1", capabilities: ["toolInterception", "modelSelection", "resume"] },
|
|
8
8
|
{ id: "pi", status: "active", executionMode: "protocol", pinnedVersion: "0.84.4", capabilities: ["toolInterception", "modelSelection", "resume"] },
|
|
9
|
-
{ id: "opencode", status: "active", executionMode: "protocol", pinnedVersion: "1.18.
|
|
9
|
+
{ id: "opencode", status: "active", executionMode: "protocol", pinnedVersion: "1.18.27", capabilities: ["toolInterception", "modelSelection", "resume"] },
|
|
10
10
|
]
|
|
11
11
|
};
|
|
@@ -16,6 +16,7 @@ const reference = { kind: "reference", label: "Password manager or environment"
|
|
|
16
16
|
/** Authoritative common providers and the offline baseline models Bivy ships. */
|
|
17
17
|
export const BIVY_PROVIDER_CATALOG = [
|
|
18
18
|
{ id: "anthropic", name: "Anthropic", authMethods: [oauth("Claude Pro / Max", "anthropic"), apiKey("Anthropic API key", "https://console.anthropic.com/settings/keys"), reference], env: ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN"], compatibility: "anthropic", helpUrl: "https://docs.anthropic.com/", models: [
|
|
19
|
+
{ id: "claude-opus-4-8", name: "Claude Opus 4.8", reasoning: true },
|
|
19
20
|
{ id: "claude-opus-4-1", name: "Claude Opus 4.1", reasoning: true },
|
|
20
21
|
{ id: "claude-sonnet-4-5", name: "Claude Sonnet 4.5", reasoning: true },
|
|
21
22
|
{ id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5" },
|
|
@@ -26,6 +27,7 @@ export const BIVY_PROVIDER_CATALOG = [
|
|
|
26
27
|
{ id: "gpt-4o", name: "GPT-4o" },
|
|
27
28
|
] },
|
|
28
29
|
{ id: "openai-codex", name: "OpenAI — ChatGPT subscription", aliases: ["codex"], authMethods: [oauth("ChatGPT Plus / Pro", "openai-codex")], compatibility: "openai", models: [
|
|
30
|
+
{ id: "gpt-5.6-sol", name: "GPT-5.6 Sol", reasoning: true },
|
|
29
31
|
{ id: "gpt-5.3-codex-spark", name: "GPT-5.3 Codex Spark", reasoning: true },
|
|
30
32
|
{ id: "gpt-5-codex", name: "GPT-5 Codex", reasoning: true },
|
|
31
33
|
] },
|
|
@@ -45,6 +45,19 @@ function decorate(detail, toolName, input, context) {
|
|
|
45
45
|
function canon(name) {
|
|
46
46
|
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
47
47
|
}
|
|
48
|
+
/** Match both native names and namespaced MCP/ACP names. Providers commonly
|
|
49
|
+
* expose a tool as `mcp__server__read_file` or `functions.exec`; the final
|
|
50
|
+
* component still has the same portable meaning. Keep this exact (rather than
|
|
51
|
+
* substring) matching so `multitasker` cannot become a delegation by accident. */
|
|
52
|
+
function inToolSet(set, rawName, key) {
|
|
53
|
+
if (set.has(key))
|
|
54
|
+
return true;
|
|
55
|
+
const separator = rawName.lastIndexOf("__");
|
|
56
|
+
const dot = rawName.lastIndexOf(".");
|
|
57
|
+
const slash = rawName.lastIndexOf("/");
|
|
58
|
+
const index = Math.max(separator, dot, slash);
|
|
59
|
+
return index >= 0 && set.has(canon(rawName.slice(index + (separator === index ? 2 : 1))));
|
|
60
|
+
}
|
|
48
61
|
function asRecord(input) {
|
|
49
62
|
return input && typeof input === "object" && !Array.isArray(input)
|
|
50
63
|
? input
|
|
@@ -97,11 +110,11 @@ const PATH_KEYS = ["path", "file_path", "filePath", "filename", "fileName", "fil
|
|
|
97
110
|
export function mapToolCall(toolName, input, context = {}) {
|
|
98
111
|
const key = canon(toolName);
|
|
99
112
|
const o = asRecord(input);
|
|
100
|
-
if (SHELL
|
|
113
|
+
if (inToolSet(SHELL, toolName, key)) {
|
|
101
114
|
const command = str(o, "command", "cmd", "script", "input", "args");
|
|
102
115
|
return command ? decorate({ kind: "shell", command, ...(str(o, "cwd", "workdir", "workingDir", "directory") ? { cwd: str(o, "cwd", "workdir", "workingDir", "directory") } : {}) }, toolName, input, context) : undefined;
|
|
103
116
|
}
|
|
104
|
-
if (EDIT
|
|
117
|
+
if (inToolSet(EDIT, toolName, key)) {
|
|
105
118
|
let path = str(o, ...PATH_KEYS);
|
|
106
119
|
// Codex `apply_patch`/`file_change` carries a `changes` map keyed by path.
|
|
107
120
|
if (!path) {
|
|
@@ -118,26 +131,26 @@ export function mapToolCall(toolName, input, context = {}) {
|
|
|
118
131
|
const newText = str(o, "new_string", "newString", "new", "after", "replace", "replacement");
|
|
119
132
|
return decorate({ kind: "edit", path, ...(oldText ? { oldText } : {}), ...(newText ? { newText } : {}) }, toolName, input, context);
|
|
120
133
|
}
|
|
121
|
-
if (WRITE
|
|
134
|
+
if (inToolSet(WRITE, toolName, key)) {
|
|
122
135
|
const path = str(o, ...PATH_KEYS);
|
|
123
136
|
return path ? decorate({ kind: "write", path }, toolName, input, context) : undefined;
|
|
124
137
|
}
|
|
125
|
-
if (READ
|
|
138
|
+
if (inToolSet(READ, toolName, key)) {
|
|
126
139
|
const path = str(o, ...PATH_KEYS);
|
|
127
140
|
return path ? decorate({ kind: "read", path }, toolName, input, context) : undefined;
|
|
128
141
|
}
|
|
129
|
-
if (SEARCH
|
|
142
|
+
if (inToolSet(SEARCH, toolName, key)) {
|
|
130
143
|
const query = str(o, "pattern", "query", "q", "search", "regex", "searchTerm");
|
|
131
144
|
return query ? decorate({ kind: "search", query, ...(str(o, "path", "dir", "directory", "include") ? { path: str(o, "path", "dir", "directory", "include") } : {}) }, toolName, input, context) : undefined;
|
|
132
145
|
}
|
|
133
|
-
if (FETCH
|
|
146
|
+
if (inToolSet(FETCH, toolName, key)) {
|
|
134
147
|
const url = str(o, "url", "uri", "href", "link");
|
|
135
148
|
return url ? decorate({ kind: "fetch", url }, toolName, input, context) : undefined;
|
|
136
149
|
}
|
|
137
|
-
if (PLAN
|
|
150
|
+
if (inToolSet(PLAN, toolName, key)) {
|
|
138
151
|
return decorate({ kind: "plan", ...(str(o, "plan", "text", "content", "message") ? { text: str(o, "plan", "text", "content", "message") } : {}) }, toolName, input, context);
|
|
139
152
|
}
|
|
140
|
-
if (DELEGATE
|
|
153
|
+
if (inToolSet(DELEGATE, toolName, key)) {
|
|
141
154
|
const label = str(o, "subagent_type", "subagentType", "agent", "agentType", "role", "name");
|
|
142
155
|
const description = str(o, "description", "task", "prompt", "instructions", "goal", "message");
|
|
143
156
|
return decorate({ kind: "delegation", ...(label ? { label } : {}), ...(description ? { description } : {}) }, toolName, input, context);
|
package/dist/server.js
CHANGED
|
@@ -2144,9 +2144,21 @@ const RELAY_COMMANDS = {
|
|
|
2144
2144
|
scheduleAdvertise();
|
|
2145
2145
|
},
|
|
2146
2146
|
abort(msg, ctx) {
|
|
2147
|
-
const
|
|
2148
|
-
|
|
2147
|
+
const sessionId = String(msg.sessionId ?? "");
|
|
2148
|
+
const record = resolveSession(sessionId);
|
|
2149
|
+
// A Stop can race the turn settling (or arrive after another client already
|
|
2150
|
+
// stopped it). Always answer that race with authoritative state so a client
|
|
2151
|
+
// that still has a stale working dot does not leave the stopped session
|
|
2152
|
+
// looking active until the next minute-long list refresh.
|
|
2153
|
+
if (!record) {
|
|
2154
|
+
if (sessionId)
|
|
2155
|
+
ctx.broadcast({ type: "session.closed", sessionId });
|
|
2149
2156
|
return;
|
|
2157
|
+
}
|
|
2158
|
+
if (!sessionBusy(record)) {
|
|
2159
|
+
ctx.broadcast({ type: "session.state", sessionId: record.id, state: sessionState(record) });
|
|
2160
|
+
return;
|
|
2161
|
+
}
|
|
2150
2162
|
if (record.turnAttention)
|
|
2151
2163
|
turnWatchdog.resolveTurnAttention(record, "stop");
|
|
2152
2164
|
else
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bivy/bivy",
|
|
3
|
-
"version": "0.16.9-staging.
|
|
3
|
+
"version": "0.16.9-staging.20",
|
|
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.",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"zod": "^4.0.0"
|
|
51
51
|
},
|
|
52
52
|
"optionalDependencies": {
|
|
53
|
-
"@anthropic-ai/claude-agent-sdk": "0.3.
|
|
53
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.258",
|
|
54
54
|
"@earendil-works/pi-ai": "0.84.4",
|
|
55
55
|
"@earendil-works/pi-coding-agent": "0.84.4",
|
|
56
56
|
"node-pty": "^1.1.0"
|
|
@@ -67,6 +67,6 @@
|
|
|
67
67
|
"nanoid": "3.3.18",
|
|
68
68
|
"undici": "8.10.0"
|
|
69
69
|
},
|
|
70
|
-
"readme": "# Bivy\n\n[](https://www.npmjs.com/package/@bivy/bivy)\n[](LICENSE)\n[](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 sign in later with\n`bivy login` (or use `bivy relay:setup` for self-hosted endpoint options).\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
|
+
"readme": "# Bivy\n\n[](https://www.npmjs.com/package/@bivy/bivy)\n[](LICENSE)\n[](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 sign in later with\n`bivy login` (or use `bivy relay:setup` for self-hosted endpoint options).\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\nPrebuilt Core service images are public on GHCR:\n\n```text\nghcr.io/bivysh/bivy-control-plane:<version-or-full-commit-sha>\nghcr.io/bivysh/bivy-relay:<version-or-full-commit-sha>\n```\n\nUse a release version for self-hosting or a full commit SHA for an immutable\nbuild. `latest` moves only when a production release is promoted. Each tag\nsupports `linux/amd64` and `linux/arm64`; the images are built from this\nrepository with SBOM and provenance attestations.\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",
|
|
71
71
|
"readmeFilename": "README.md"
|
|
72
72
|
}
|