@bondsmith/bondsmithd 0.1.0

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.
Files changed (3) hide show
  1. package/README.md +139 -0
  2. package/dist/index.js +2840 -0
  3. package/package.json +52 -0
package/README.md ADDED
@@ -0,0 +1,139 @@
1
+ # bondsmithd
2
+
3
+ Local daemon that manages tmux-backed terminal sessions on your machine and exposes them to the
4
+ Bondsmith web app over a signed WebSocket protocol. Runs entirely on your own machine — no code,
5
+ terminal output, or session data is ever sent anywhere except the Bondsmith account you explicitly
6
+ pair it with.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install -g @bondsmith/bondsmithd
12
+ ```
13
+
14
+ Requires Node >=24 and `tmux` (`brew install tmux` on macOS). `node-pty`, the one native
15
+ dependency, ships prebuilt binaries for macOS (Intel and Apple Silicon) and installs without
16
+ compiling anything on supported platforms.
17
+
18
+ ## Running
19
+
20
+ ```bash
21
+ bondsmithd
22
+ ```
23
+
24
+ On first run, `bondsmithd` prints a pairing code and URL — confirm it from your Bondsmith account
25
+ to trust this machine. After that, `bondsmithd` just needs to be running for the Bondsmith web app
26
+ to see and control sessions on this machine.
27
+
28
+ Start it from a normal interactive shell, not a stripped-down context (a bare `launchd`/login-item
29
+ invocation, a minimal CI shell, etc.). The daemon passes its own `process.env` through to every
30
+ tmux session it creates, so sessions inherit your real `PATH`, version manager shims
31
+ (`mise`/`nvm`/etc.), and tools like `claude` or `pnpm` — the same environment you'd get opening a
32
+ new terminal tab. A stripped environment at daemon-start time means the same stripped environment
33
+ in every session it launches.
34
+
35
+ Environment variables (all optional):
36
+
37
+ ```
38
+ PORT=4577 # defaults to 4577
39
+ ALLOWED_ORIGINS=https://app.bondsmith.dev
40
+ BONDSMITH_RELAY_URL=wss://relay.bondsmith.dev # defaults to a local-only address; set this for a real install
41
+ ```
42
+
43
+ `BONDSMITH_DEV_TUNNEL_TOKEN` also exists but only applies to the legacy direct-connection path
44
+ (`BONDSMITH_RELAY_ENABLED=false`) — should not be set by hand for a normal install.
45
+
46
+ ## What it does
47
+
48
+ - Creates, lists, attaches to, and stops tmux sessions prefixed `bondsmith-*`.
49
+ - Never enumerates or manages tmux sessions it didn't create.
50
+ - Attaches a real PTY (`tmux attach-session`) so whatever is running inside (`claude`, `opencode`,
51
+ `bash`, anything) behaves exactly as it would in a normal terminal.
52
+ - Keeps tmux itself as the only source of truth — no database. Restarting the daemon rediscovers
53
+ running sessions from tmux.
54
+
55
+ ## Production connectivity (current status)
56
+
57
+ `bondsmithd` connects outbound to the Bondsmith relay by default (`BONDSMITH_RELAY_ENABLED=true`),
58
+ which is what a production account actually uses — no dev-tunnel token involved. Point
59
+ `BONDSMITH_RELAY_URL` at `wss://relay.bondsmith.dev` for a real install (see "Environment
60
+ variables" above); it defaults to a local-only address for monorepo development.
61
+
62
+ The dev-tunnel-token requirement only applies to the legacy direct-connection path
63
+ (`BONDSMITH_RELAY_ENABLED=false`), which still 404s the token-handoff route in production by
64
+ design — that path is for local debugging only, not a real install.
65
+
66
+ ## Security model
67
+
68
+ - Every connection is validated against the daemon's `ALLOWED_ORIGINS` and completes a
69
+ cryptographic handshake — a fresh, single-use, daemon-issued challenge signed by a controller key
70
+ the daemon has explicitly and locally trusted. See "Pairing" above for how a controller key
71
+ becomes trusted in the first place.
72
+ - Every sensitive command AND every sensitive read (session listing, workspace status, diffs, plus
73
+ every state-changing action) must arrive as part of that same authenticated, signed connection —
74
+ read access is not treated as lower-risk than write access, since a read can expose session
75
+ metadata and source code just as much as a write can change it.
76
+ - Replay protection is connection-scoped and lives entirely in the daemon's memory — nothing about
77
+ it is persisted to disk, so a browser reload or reconnect always starts a clean, independent
78
+ session.
79
+ - Revoking trust for a controller (from your Bondsmith account) closes its active connections
80
+ within a bounded time, whether or not it's mid-session.
81
+ - Only ever touches tmux sessions it created itself, named `bondsmith-<uuid>`.
82
+ - All tmux/PTY invocations use argv arrays, never shell string interpolation.
83
+ - PTY/terminal contents are never logged or persisted by the daemon itself.
84
+ - This is not a confidentiality boundary against a compromised network path between your machine
85
+ and Bondsmith Cloud — the design assumes source, protocol behavior, and the daemon binary itself
86
+ are fully observable by an attacker, and derives its guarantees from cryptographic signing and
87
+ local trust decisions, never from secrecy of the code. The dev-tunnel admission token described
88
+ under "Production connectivity" above is the one exception (a genuine shared-secret mechanism),
89
+ but it only applies to the legacy direct-connection path, not the relay path a real install uses.
90
+
91
+ Full design detail: `docs/architecture/local-sessions-auth-decision-log.md` in the
92
+ [bondsmith repository](https://github.com/ellis-river-ventures/bondsmith).
93
+
94
+ ## Contributing / developing bondsmithd itself
95
+
96
+ This section is for people working in the `bondsmith` monorepo, not for installed users of the
97
+ published package.
98
+
99
+ ```bash
100
+ pnpm --filter @bondsmith/bondsmithd dev
101
+ ```
102
+
103
+ This is deliberately **not** part of `pnpm dev` / `turbo dev` — it needs tmux and a native module
104
+ on the host, and it's opt-in tooling, not a service the rest of the stack depends on.
105
+
106
+ **node-pty is pinned to `1.2.0-beta.15`, not the `1.1.0` stable release.** `1.1.0`'s prebuilt
107
+ `darwin-arm64` binary fails immediately with `posix_spawnp failed` on Node 24 (verified on macOS
108
+ 15/Apple Silicon) — any spawn, not just tmux, crashes the whole daemon process. The `1.2.0-beta`
109
+ line has a prebuild that works correctly on Node 24. Don't downgrade to a `node-pty` stable release
110
+ without first confirming `pty.spawn(...)` actually works on your Node version.
111
+
112
+ For local development, create a `.env` file in this directory (or export the vars directly):
113
+
114
+ ```
115
+ PORT=4577
116
+ ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000,http://localhost:4000,http://127.0.0.1:4000
117
+ ```
118
+
119
+ Port 4000 is included because that's where `make dev`'s Docker Compose stack serves the web app
120
+ (`docker-compose.dev.yml` maps `4000:4000`); port 3000 covers running `apps/web` directly via
121
+ `pnpm dev:web` instead.
122
+
123
+ The web app needs `NEXT_PUBLIC_LOCAL_AGENT_DAEMON_URL=ws://127.0.0.1:4577` set wherever it reads
124
+ its env from — under `make dev` that's the repo-root `.env.local` (referenced by
125
+ `docker-compose.dev.yml`'s `env_file`), not `apps/web/.env.local`.
126
+
127
+ ### Publishing
128
+
129
+ `pnpm --filter @bondsmith/bondsmithd build` bundles `@bondsmith/local-agent-protocol` directly into
130
+ `dist/index.js` (see `tsup.config.ts`'s `noExternal`) — the published package has no `workspace:*`
131
+ dependency and no runtime dependency on that package existing on any registry. Only `dist/index.js`,
132
+ `package.json`, and this README are published (see `package.json`'s `files`); sourcemaps and every
133
+ other repo file are excluded.
134
+
135
+ ### Non-goals (current scope)
136
+
137
+ No cloud execution, no multi-machine support, no session sharing, no Claude/OpenCode API
138
+ integration, no agent-output parsing or detection, no terminal history storage or session
139
+ recording.