@geohar/un-bien 0.8.0 → 0.14.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 (175) hide show
  1. package/README.md +258 -320
  2. package/dist/actions/handlers.js.map +1 -1
  3. package/dist/actions/registry.js.map +1 -1
  4. package/dist/bin/launcher.js +38 -0
  5. package/dist/bin/launcher.js.map +1 -0
  6. package/dist/commands/deps.d.ts +156 -0
  7. package/dist/commands/deps.js +2 -0
  8. package/dist/commands/deps.js.map +1 -0
  9. package/dist/commands/fork_link.d.ts +4 -0
  10. package/dist/commands/fork_link.js +45 -0
  11. package/dist/commands/fork_link.js.map +1 -0
  12. package/dist/commands/housekeeping.d.ts +34 -0
  13. package/dist/commands/housekeeping.js +275 -0
  14. package/dist/commands/housekeeping.js.map +1 -0
  15. package/dist/commands/info.d.ts +43 -0
  16. package/dist/commands/info.js +127 -0
  17. package/dist/commands/info.js.map +1 -0
  18. package/dist/commands/lifecycle.d.ts +45 -0
  19. package/dist/commands/lifecycle.js +708 -0
  20. package/dist/commands/lifecycle.js.map +1 -0
  21. package/dist/commands/pairing.d.ts +26 -0
  22. package/dist/commands/pairing.js +167 -0
  23. package/dist/commands/pairing.js.map +1 -0
  24. package/dist/commands/register.d.ts +12 -0
  25. package/dist/commands/register.js +255 -0
  26. package/dist/commands/register.js.map +1 -0
  27. package/dist/commands/relay.d.ts +28 -0
  28. package/dist/commands/relay.js +81 -0
  29. package/dist/commands/relay.js.map +1 -0
  30. package/dist/commands/session_ops.d.ts +52 -0
  31. package/dist/commands/session_ops.js +75 -0
  32. package/dist/commands/session_ops.js.map +1 -0
  33. package/dist/config.d.ts +30 -2
  34. package/dist/config.js.map +1 -1
  35. package/dist/daemon/install.d.ts +36 -37
  36. package/dist/daemon/install.js +49 -73
  37. package/dist/daemon/install.js.map +1 -1
  38. package/dist/enrich_tool_args.d.ts +9 -0
  39. package/dist/enrich_tool_args.js +171 -0
  40. package/dist/enrich_tool_args.js.map +1 -0
  41. package/dist/extension_ui_bridge.js.map +1 -1
  42. package/dist/image_codec.d.ts +22 -0
  43. package/dist/image_codec.js +149 -0
  44. package/dist/image_codec.js.map +1 -0
  45. package/dist/index.d.ts +32 -127
  46. package/dist/index.js +957 -4042
  47. package/dist/index.js.map +1 -1
  48. package/dist/launch.d.ts +42 -0
  49. package/dist/launch.js +206 -0
  50. package/dist/launch.js.map +1 -0
  51. package/dist/launcher/launcher.d.ts +6 -0
  52. package/dist/launcher/launcher.js +207 -0
  53. package/dist/launcher/launcher.js.map +1 -0
  54. package/dist/mcp/mesh_result.js.map +1 -1
  55. package/dist/mcp/mesh_server.js.map +1 -1
  56. package/dist/mesh/canonical.js +1 -1
  57. package/dist/mesh/canonical.js.map +1 -1
  58. package/dist/mesh/client.js.map +1 -1
  59. package/dist/mesh/encoding.js.map +1 -1
  60. package/dist/mesh/self_revoke.js.map +1 -1
  61. package/dist/mesh/siblings.js.map +1 -1
  62. package/dist/mesh/verify.js +1 -1
  63. package/dist/mesh/verify.js.map +1 -1
  64. package/dist/pairing/crypto.js +0 -1
  65. package/dist/pairing/crypto.js.map +1 -1
  66. package/dist/pairing/peer_trust.d.ts +20 -0
  67. package/dist/pairing/peer_trust.js +82 -0
  68. package/dist/pairing/peer_trust.js.map +1 -0
  69. package/dist/pairing/qr.js.map +1 -1
  70. package/dist/pairing/storage.js +4 -3
  71. package/dist/pairing/storage.js.map +1 -1
  72. package/dist/panel_bridge.d.ts +3 -1
  73. package/dist/panel_bridge.js +11 -10
  74. package/dist/panel_bridge.js.map +1 -1
  75. package/dist/paths.d.ts +22 -8
  76. package/dist/paths.js +37 -10
  77. package/dist/paths.js.map +1 -1
  78. package/dist/protocol/codec.js.map +1 -1
  79. package/dist/rooms.d.ts +16 -0
  80. package/dist/rooms.js +23 -4
  81. package/dist/rooms.js.map +1 -1
  82. package/dist/session/bridge.js.map +1 -1
  83. package/dist/session/broker.js.map +1 -1
  84. package/dist/session/broker_remote.js.map +1 -1
  85. package/dist/session/capabilities.d.ts +11 -0
  86. package/dist/session/capabilities.js +35 -0
  87. package/dist/session/capabilities.js.map +1 -0
  88. package/dist/session/cwd_lock.js +3 -3
  89. package/dist/session/cwd_lock.js.map +1 -1
  90. package/dist/session/debug_log.js +15 -5
  91. package/dist/session/debug_log.js.map +1 -1
  92. package/dist/session/envelope.js.map +1 -1
  93. package/dist/session/global_config.d.ts +1 -1
  94. package/dist/session/global_config.js +1 -1
  95. package/dist/session/global_config.js.map +1 -1
  96. package/dist/session/ipc.d.ts +2 -2
  97. package/dist/session/ipc.js.map +1 -1
  98. package/dist/session/leader_election.js.map +1 -1
  99. package/dist/session/local_config.d.ts +37 -0
  100. package/dist/session/local_config.js +47 -1
  101. package/dist/session/local_config.js.map +1 -1
  102. package/dist/session/mesh_node.d.ts +1 -1
  103. package/dist/session/mesh_node.js +1 -1
  104. package/dist/session/mesh_node.js.map +1 -1
  105. package/dist/session/peer.js.map +1 -1
  106. package/dist/session/peer_inventory.js.map +1 -1
  107. package/dist/session/peer_limits.js.map +1 -1
  108. package/dist/session/received_images.d.ts +63 -0
  109. package/dist/session/received_images.js +273 -0
  110. package/dist/session/received_images.js.map +1 -0
  111. package/dist/session/relay_lifecycle.d.ts +219 -0
  112. package/dist/session/relay_lifecycle.js +764 -0
  113. package/dist/session/relay_lifecycle.js.map +1 -0
  114. package/dist/session/rpc_envelope.d.ts +28 -0
  115. package/dist/session/rpc_envelope.js +10 -1
  116. package/dist/session/rpc_envelope.js.map +1 -1
  117. package/dist/session/rpc_handlers.d.ts +53 -0
  118. package/dist/session/rpc_handlers.js +268 -0
  119. package/dist/session/rpc_handlers.js.map +1 -0
  120. package/dist/session/rpc_inbound.d.ts +42 -7
  121. package/dist/session/rpc_inbound.js +56 -1
  122. package/dist/session/rpc_inbound.js.map +1 -1
  123. package/dist/session/setup_wizard.js.map +1 -1
  124. package/dist/session/tools.js.map +1 -1
  125. package/dist/session/wizard.js.map +1 -1
  126. package/dist/state_migration.d.ts +45 -0
  127. package/dist/state_migration.js +104 -0
  128. package/dist/state_migration.js.map +1 -0
  129. package/dist/subagent_rooms.d.ts +68 -0
  130. package/dist/subagent_rooms.js +919 -0
  131. package/dist/subagent_rooms.js.map +1 -0
  132. package/dist/test_hooks.d.ts +180 -0
  133. package/dist/test_hooks.js +98 -0
  134. package/dist/test_hooks.js.map +1 -0
  135. package/dist/transport/peer_channel.d.ts +18 -1
  136. package/dist/transport/peer_channel.js +42 -12
  137. package/dist/transport/peer_channel.js.map +1 -1
  138. package/dist/transport/pi_forward_client.js.map +1 -1
  139. package/dist/transport/relay_client.d.ts +24 -2
  140. package/dist/transport/relay_client.js +6 -3
  141. package/dist/transport/relay_client.js.map +1 -1
  142. package/dist/ui/footer.js.map +1 -1
  143. package/docs/daemon.md +170 -179
  144. package/package.json +13 -11
  145. package/service-templates/launchd.plist.template +8 -7
  146. package/service-templates/systemd.service.template +5 -4
  147. package/service-templates/task-launcher.vbs.template +5 -5
  148. package/service-templates/task-scheduler.xml.template +1 -1
  149. package/dist/bin/supervisord.js +0 -86
  150. package/dist/bin/supervisord.js.map +0 -1
  151. package/dist/daemon/client.d.ts +0 -20
  152. package/dist/daemon/client.js +0 -131
  153. package/dist/daemon/client.js.map +0 -1
  154. package/dist/daemon/control_protocol.d.ts +0 -176
  155. package/dist/daemon/control_protocol.js +0 -63
  156. package/dist/daemon/control_protocol.js.map +0 -1
  157. package/dist/daemon/cron_log.d.ts +0 -45
  158. package/dist/daemon/cron_log.js +0 -71
  159. package/dist/daemon/cron_log.js.map +0 -1
  160. package/dist/daemon/cron_registry.d.ts +0 -80
  161. package/dist/daemon/cron_registry.js +0 -198
  162. package/dist/daemon/cron_registry.js.map +0 -1
  163. package/dist/daemon/id.d.ts +0 -24
  164. package/dist/daemon/id.js +0 -36
  165. package/dist/daemon/id.js.map +0 -1
  166. package/dist/daemon/registry.d.ts +0 -63
  167. package/dist/daemon/registry.js +0 -153
  168. package/dist/daemon/registry.js.map +0 -1
  169. package/dist/daemon/rpc_child.d.ts +0 -194
  170. package/dist/daemon/rpc_child.js +0 -419
  171. package/dist/daemon/rpc_child.js.map +0 -1
  172. package/dist/daemon/supervisor.d.ts +0 -93
  173. package/dist/daemon/supervisor.js +0 -666
  174. package/dist/daemon/supervisor.js.map +0 -1
  175. /package/dist/bin/{supervisord.d.ts → launcher.d.ts} +0 -0
package/docs/daemon.md CHANGED
@@ -1,45 +1,44 @@
1
- # Daemon mode — troubleshooting
1
+ # Remote launch & launcher daemon — troubleshooting
2
2
 
3
- Companion to the README's [Daemon mode](../README.md#daemon-mode) section.
3
+ Companion to the README's [Remote launch](../README.md#remote-launch) section.
4
4
  Each scenario starts with the symptom you'd actually observe, followed by
5
- likely causes and how to fix.
5
+ likely causes and how to fix it.
6
6
 
7
7
  ---
8
8
 
9
- ## 1. `remote-pi install` fails
9
+ ## 1. `unbien install` fails
10
10
 
11
- ### "supervisor script not found"
11
+ ### "launcher script not found"
12
12
 
13
- ```
14
- [remote-pi] install failed: Error: supervisor script not found at
15
- /Users/x/dist/bin/supervisord.js. Run `pnpm build` (dev) or
16
- `npm install -g remote-pi` (prod) first.
13
+ ```text
14
+ [un-bien] install failed: Error: launcher script not found at
15
+ /Users/x/dist/bin/launcher.js. Run `pnpm build` (dev) or
16
+ `npm install -g @geohar/un-bien` (prod) first.
17
17
  ```
18
18
 
19
- You're running `remote-pi install` from a dev clone where `dist/` doesn't
19
+ You're running `unbien install` from a dev clone where `dist/` doesn't
20
20
  exist yet, or from a partial install.
21
21
 
22
22
  ```bash
23
23
  # Dev clone:
24
- cd pi-extension && pnpm build
24
+ cd extension && pnpm build
25
25
 
26
26
  # Production install:
27
- npm install -g remote-pi # or pnpm install -g remote-pi
28
- which pi-supervisord # confirm bin is on PATH
29
- remote-pi install
27
+ npm install -g @geohar/un-bien
28
+ unbien install
30
29
  ```
31
30
 
32
31
  ### "launchctl: bootstrap … already running"
33
32
 
34
33
  A previous install left a stale entry. The fix is built into `install` —
35
- re-run it and the supervisor unloads the old entry before bootstrapping
36
- the new one. If it still fails:
34
+ re-run it and the launcher unloads the old entry before bootstrapping the
35
+ new one. If it still fails:
37
36
 
38
37
  ```bash
39
- launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/dev.remotepi.supervisord.plist
40
- launchctl unload ~/Library/LaunchAgents/dev.remotepi.supervisord.plist 2>/dev/null
41
- rm ~/Library/LaunchAgents/dev.remotepi.supervisord.plist
42
- remote-pi install
38
+ launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/dev.unbien.launcher.plist
39
+ launchctl unload ~/Library/LaunchAgents/dev.unbien.launcher.plist 2>/dev/null
40
+ rm ~/Library/LaunchAgents/dev.unbien.launcher.plist
41
+ unbien install
43
42
  ```
44
43
 
45
44
  ### "systemctl --user … No such file or directory"
@@ -51,239 +50,231 @@ the unit survives logout:
51
50
  ```bash
52
51
  loginctl enable-linger $USER
53
52
  systemctl --user daemon-reload
54
- remote-pi install
53
+ unbien install
55
54
  ```
56
55
 
56
+ ### Windows: the UAC prompt fails or is declined
57
+
58
+ `unbien install` needs elevation **once** — only the `schtasks /Create`
59
+ that registers the task requires admin. Accept the prompt when it appears.
60
+ Stopping/starting the task afterwards (`/End`, `/Run`) works un-elevated.
61
+
57
62
  ---
58
63
 
59
- ## 2. Supervisor doesn't start at login
64
+ ## 2. The launcher doesn't start at login
60
65
 
61
66
  ### Check the service status
62
67
 
63
68
  ```bash
64
69
  # Linux
65
- systemctl --user status remote-pi-supervisord
66
- journalctl --user -u remote-pi-supervisord -n 50
70
+ systemctl --user status unbien-launcher
71
+ journalctl --user -u unbien-launcher -n 50
67
72
 
68
73
  # macOS
69
- launchctl list | grep remotepi
70
- tail -100 ~/.pi/remote/supervisord.log
74
+ launchctl list | grep dev.unbien
75
+ tail -100 ~/.local/state/un-bien/launcher.log
71
76
  ```
72
77
 
73
78
  ### Common failures
74
79
 
75
- - **`pi: command not found`** in the log — Pi's binary isn't on the
76
- PATH that the unit inherited. `remote-pi install` captures
77
- `process.env.PATH` at install time; if you installed Pi *after*
78
- running install, re-run `remote-pi install` to refresh.
79
- - **`Cannot find module …`** — the path baked into the unit doesn't
80
- match where `dist/bin/supervisord.js` actually lives. Happens if you
81
- uninstalled then reinstalled the package to a different location.
82
- Fix: `remote-pi uninstall && remote-pi install`.
83
- - **Permission denied on UDS** — `~/.pi/remote/` exists with wrong
84
- perms (rare; only happens if you ran `pi` as `sudo` once). Delete
85
- the dir and let it re-create: `rm -rf ~/.pi/remote && remote-pi install`.
80
+ - **`node: cannot find module …`** or immediate exit — the absolute paths
81
+ baked into the unit/plist no longer match where the package lives. This
82
+ happens when you reinstall Node via a version manager (nvm/fnm) or
83
+ uninstall/reinstall the package to a different location. Fix:
84
+ `unbien uninstall && unbien install` (install snapshots the current
85
+ node binary and paths).
86
+ - **`tmux: command not found`** (at launch time, not startup) — the PATH
87
+ captured at install time didn't include the remote-launch backend.
88
+ Install tmux (or herdr), then re-run `unbien install` to refresh PATH.
89
+ - **First connect race** — the launcher logs `initial connect failed (…)
90
+ — retrying every 3000ms` and retries on its own. This is normal when
91
+ the relay starts in the same breath; it clears once the relay is up.
86
92
 
87
- ### Run the supervisor in the foreground for debugging
93
+ ### Run the launcher in the foreground for debugging
88
94
 
89
- Bypass systemd/launchd and run it directly so you can see startup
90
- errors live:
95
+ Bypass systemd/launchd and run it directly so you can see startup errors
96
+ live:
91
97
 
92
98
  ```bash
93
- pi-supervisord
94
- # or: node /path/to/remote-pi/dist/bin/supervisord.js
99
+ unbien-launcher # from @geohar/un-bien-launcher
100
+ # or, from the extension package:
101
+ node $(npm root -g)/@geohar/un-bien/dist/bin/launcher.js
95
102
  ```
96
103
 
97
- Ctrl-C to stop. If that works but the service doesn't, the problem is
98
- in the unit/plist environment (PATH, HOME) — re-run `remote-pi install`.
104
+ If it prints `[un-bien launcher] listening on control room …` and stays
105
+ up, the daemon itself is fine — the problem is in the unit/plist
106
+ environment (PATH, node path). Re-run `unbien install`.
99
107
 
100
108
  ---
101
109
 
102
- ## 3. A specific daemon stays `crashed`
103
-
104
- `remote-pi daemon status` shows one row with `state=crashed` and a
105
- restart count near 4 (the supervisor gives up after exponential
106
- backoff: 1s, 5s, 30s, 5min).
107
-
108
- ### Step 1 — read the daemon's stderr
109
-
110
- The supervisor forwards each daemon's stderr with a `[<cwd>]` prefix:
111
-
112
- ```bash
113
- # Linux
114
- journalctl --user -u remote-pi-supervisord -f | grep '\[/Users/x/Movies\]'
115
-
116
- # macOS
117
- tail -f ~/.pi/remote/supervisord.log | grep '\[/Users/x/Movies\]'
118
- ```
119
-
120
- ### Step 2 — run that daemon manually
121
-
122
- Reproduce the failure with full visibility:
110
+ ## 3. Remotely launched pis can't read the keychain (tmux security sessions)
111
+
112
+ **Symptoms:** a remote launch opens the tmux window but pi dies silently (no
113
+ output, no stderr), or fails with `No identity could be read, but N device(s)
114
+ are already paired — refusing to generate a NEW one` (the
115
+ `PairedIdentityMissingError` guard). An `identity.json.bogus-*` file appears
116
+ in the state root. Everything works when you start pi yourself in Terminal.
117
+
118
+ **Cause — macOS security sessions:** keychain access follows the _security
119
+ session_ a process was spawned into, and every tmux pane inherits the tmux
120
+ **server's** context — not the terminal that opened the window. With
121
+ `launch.backend: "tmux"` the server is created by whichever process first
122
+ needed it: the launcher. If the launcher was started from a detached or
123
+ session-poor context (a daemon, a service manager like `sharedserver`, SSH),
124
+ the tmux server it creates carries that context and **denies keychain access
125
+ to every pane it ever hosts**. Worse, the server **outlives the launcher**:
126
+ killing/restarting the launcher just attaches new windows to the orphaned
127
+ server, so a bad creation context persists across launcher restarts.
128
+
129
+ A second wrinkle: a keychain read can require an **ACL confirmation** when
130
+ the reading binary differs from the one that created the item (e.g. after an
131
+ nvm/npm reinstall swaps the node binary). A background process has no path to
132
+ the Security Agent UI, so it gets `errSecInteractionNotAllowed` instead of a
133
+ prompt — same symptom, same fixes.
134
+
135
+ **Recovery:** kill the orphaned tmux server so the next launch recreates it
136
+ from a healthy context:
123
137
 
124
138
  ```bash
125
- cd /Users/x/Movies
126
- REMOTE_PI_DAEMON=1 pi --mode rpc -e $(npm root -g)/remote-pi/dist/index.js
139
+ tmux kill-session -t un-bien # or tmux kill-server (kills ALL sessions)
127
140
  ```
128
141
 
129
- Common reasons a daemon won't start:
142
+ **Lasting fixes (any one of these):**
130
143
 
131
- - **Local config missing.** `cd` into the daemon's folder and check
132
- `.pi/remote-pi/config.json` exists with `auto_start_relay: true`.
133
- Recreate via `remote-pi create <cwd>` (it provisions a default config
134
- when missing).
135
- - **Pi extension config drift.** Pi's own settings (model, API keys)
136
- reset → daemon fails to authenticate to the provider. Run
137
- `cd <cwd> && pi` interactively to fix.
138
- - **Port/UDS collision.** Another Pi process is already running in
139
- that cwd. The cwd-lock should reject the second one, but stale UDS
140
- sockets sometimes linger; check `lsof ~/.pi/remote/locks/<roomId>.sock`.
141
-
142
- ### Step 3 — force a re-spawn
143
-
144
- After fixing the underlying problem, kick the supervisor:
145
-
146
- ```bash
147
- remote-pi daemon restart # bounces every daemon
148
- ```
144
+ 1. **Pre-seed the tmux session from your own Terminal** — the server then
145
+ lives in your GUI login session for good, and the launcher only ever adds
146
+ windows to it:
149
147
 
150
- ---
148
+ ```bash
149
+ tmux new-session -d -s un-bien
150
+ ```
151
151
 
152
- ## 4. `daemon send` says "daemon not running"
152
+ 2. **Run the launcher as a login service** (`unbien install` — launchd
153
+ LaunchAgent / systemd `--user`), not from a detached daemon: the launcher
154
+ — and any tmux server it creates — stays inside your login session where
155
+ the keychain just works.
153
156
 
154
- The supervisor has the registry entry but no live child for that id.
155
- Most common cause: the daemon never started OR it crashed past the
156
- retry budget.
157
+ 3. **The context-proof option — seed the file identity fallback.** The
158
+ resolver reads `~/.local/state/un-bien/identity.json` automatically
159
+ whenever the keychain throws (no prompt, no re-pairing, any security
160
+ session):
157
161
 
158
- ```bash
159
- remote-pi daemon status # is state running?
160
- remote-pi daemon start # spawn any that aren't running
161
- # Then retry send.
162
- ```
162
+ ```bash
163
+ security find-generic-password -s dev.unbien.pi -a longterm-ed25519 -w \
164
+ > ~/.local/state/un-bien/identity.json
165
+ chmod 600 ~/.local/state/un-bien/identity.json
166
+ ```
163
167
 
164
- If `daemon start` shows `started=0, already_running=N`, the supervisor
165
- isn't actually spawning. Possible reasons:
166
- - Registry empty: `remote-pi daemons` to verify.
167
- - Child crashes faster than the status check: `daemon status` immediately
168
- after start may still show `running` for a few seconds before the
169
- exit event marks it crashed. Re-check 2-3 seconds later.
168
+ **Related:** the launcher needs your env (`PI_CODING_AGENT_DIR`, and
169
+ `UNBIEN_RELAY`/`UNBIEN_STATE_DIR` if you use them) in its spawn context. If
170
+ you run it under a service manager, pin them explicitly in the server
171
+ definition's env map instead of relying on ambient shell env — a daemon's
172
+ children inherit the _daemon's_ environment, not your shell's.
170
173
 
171
174
  ---
172
175
 
173
- ## 5. Mobile app doesn't connect to a daemon
176
+ ## 4. The app can't launch a session on this machine
174
177
 
175
- The daemon is up but the app doesn't see it.
178
+ The launcher is running and the app sees the machine's control room, but
179
+ launch requests do nothing.
176
180
 
177
- ### Confirm the daemon is paired
181
+ ### Remote launch is not enabled for that directory
178
182
 
179
- `pair_request` must have happened **before** the folder became a daemon
180
- (daemons don't show QRs themselves):
183
+ The launcher only honors `session_launch` where it's opted in:
181
184
 
182
- ```bash
183
- cd <daemon-cwd>
184
- pi
185
- > /remote-pi devices # confirm the device is listed
186
- > /remote-pi stop # stop interactive session — daemon takes over
187
- remote-pi daemon restart
185
+ ```jsonc
186
+ // <cwd>/.pi/un-bien/config.json — per directory
187
+ { "allow_remote_launch": true }
188
188
  ```
189
189
 
190
- ### Confirm the relay URL matches
190
+ or machine-wide, in `~/.pi/extensions/un-bien.json`:
191
191
 
192
- The daemon uses the cwd's local config (`<cwd>/.pi/remote-pi/config.json`
193
- agent_name + `~/.pi/remote/config.json` relay). Verify with:
194
-
195
- ```bash
196
- cd <daemon-cwd>
197
- pi
198
- > /remote-pi status
192
+ ```jsonc
193
+ { "defaults": { "allow_remote_launch": true } }
199
194
  ```
200
195
 
201
- The relay line should match what the mobile app is connecting to. If
202
- not, update the relay URL and bounce the daemon:
196
+ ### Turn on the diagnostic log
203
197
 
204
- ```bash
205
- remote-pi set-relay https://relay.example.tld
206
- remote-pi daemon restart
198
+ The launcher writes its decisions to the envelope debug log. Enable it in
199
+ `~/.pi/extensions/un-bien.json`:
200
+
201
+ ```jsonc
202
+ { "debug": { "envelope": true } }
207
203
  ```
208
204
 
209
- ---
205
+ then reproduce and read
206
+ `~/.local/state/un-bien/envelope-debug.log` — look for
207
+ `remote launch disabled on this machine` (the opt-in above) or
208
+ `session_launch error: …` (the backend failing to spawn).
210
209
 
211
- ## 6. Registry corrupted / partial
210
+ ### The backend is missing or misconfigured
212
211
 
213
- Symptom: `remote-pi daemons` errors out or shows nothing despite
214
- having created entries.
212
+ `launch.backend` in the global config picks the spawn mechanism — `tmux`
213
+ (default) or `herdr`. The chosen binary must be on the PATH the service
214
+ inherited (see §2). Verify what the launcher will use from any Pi
215
+ session: `/unbien config`.
215
216
 
216
- ```bash
217
- cat ~/.pi/remote/daemons.json # inspect
218
- ```
217
+ ### "Peer not paired — re-scan QR"
219
218
 
220
- The file should be:
219
+ The app's device key isn't in this machine's `peers.json` (never paired
220
+ here, or revoked). Pairing is interactive: run `/unbien pair` in any Pi
221
+ session on the machine and scan the QR from the app.
221
222
 
222
- ```json
223
- {
224
- "daemons": [
225
- { "cwd": "/Users/x/Movies" },
226
- { "cwd": "/Users/x/Projects/backend" }
227
- ]
228
- }
229
- ```
223
+ ---
230
224
 
231
- Fix manually if needed (it's a JSON list of `{cwd}` entries), or wipe
232
- and re-create:
225
+ ## 5. The app can't see the machine at all
233
226
 
234
- ```bash
235
- rm ~/.pi/remote/daemons.json
236
- remote-pi create ~/Movies --name "Video Editor"
237
- remote-pi create ~/Projects/backend --name "Backend"
238
- remote-pi daemon restart
239
- ```
227
+ - **Relay mismatch.** The launcher uses the same global relay config as
228
+ the extension — check `/unbien config` and make sure the app is pointed
229
+ at the same URL.
230
+ - **Launcher not running.** Check §2; the control room only exists while
231
+ the launcher is connected.
240
232
 
241
233
  ---
242
234
 
243
- ## 7. Uninstall cleanly + re-install from scratch
235
+ ## 6. Uninstall cleanly + re-install from scratch
244
236
 
245
237
  When you suspect everything is misconfigured:
246
238
 
247
239
  ```bash
248
- remote-pi uninstall # removes service, keeps registry
249
- rm -rf ~/.pi/remote # nukes registry + paired devices + keys
250
- npm uninstall -g remote-pi
251
- npm install -g remote-pi
252
- remote-pi install
253
- # Then re-pair + re-create daemons from scratch.
240
+ unbien uninstall # removes the service, keeps config + pairing
241
+ rm -rf ~/.local/state/un-bien # nukes pairing + identity (re-pair after this)
242
+ npm uninstall -g @geohar/un-bien
243
+ npm install -g @geohar/un-bien
244
+ unbien install
245
+ # Then re-pair from scratch: pi → /unbien pair
254
246
  ```
255
247
 
256
- This is the "nuke everything" path. After this, the only state left is
257
- each cwd's `<cwd>/.pi/remote-pi/config.json` — which you can either
258
- keep (re-create restores the daemon) or delete (full reset).
248
+ This is the "nuke everything" path. After it, the only state left is each
249
+ cwd's `<cwd>/.pi/un-bien/config.json`, which you can keep or delete for a
250
+ full reset.
259
251
 
260
252
  ---
261
253
 
262
- ## 8. Diagnostic commands cheat-sheet
254
+ ## 7. Diagnostic commands cheat-sheet
263
255
 
264
256
  ```bash
265
- # Where is the supervisor's UDS?
266
- ls -la ~/.pi/remote/supervisor.sock
267
-
268
- # Talk to the supervisor manually (raw JSONL):
269
- echo '{"op":"list"}' | nc -U ~/.pi/remote/supervisor.sock
270
-
271
- # Where are the daemon configs?
272
- find ~/Projects -name "config.json" -path "*/.pi/remote-pi/*" 2>/dev/null
257
+ # Service status
258
+ systemctl --user status unbien-launcher # Linux
259
+ launchctl list | grep dev.unbien # macOS
260
+ schtasks /Query /TN RemotePiLauncher # Windows
273
261
 
274
- # Where are the cwd locks?
275
- ls ~/.pi/remote/locks/
262
+ # Logs
263
+ journalctl --user -u unbien-launcher -f # Linux
264
+ tail -f ~/.local/state/un-bien/launcher.log # macOS / Windows
276
265
 
277
- # Where are the paired devices?
278
- cat ~/.pi/remote/peers.json
266
+ # Global config the launcher reads (relay, launch backend, defaults)
267
+ cat ~/.pi/extensions/un-bien.json
279
268
 
280
- # What Pi binary is the supervisor about to spawn?
281
- remote-pi install --dry-run # (not implemented; check ~/Library/LaunchAgents or systemd unit manually)
269
+ # Paired devices (per machine)
270
+ cat ~/.local/state/un-bien/peers.json
282
271
 
283
- # Quick liveness check
284
- remote-pi daemon status
272
+ # What the extension thinks (from any Pi session, in pi):
273
+ # /unbien config
274
+ # /unbien status
275
+ # /unbien devices
285
276
  ```
286
277
 
287
278
  If after walking the list you're still stuck, file an issue with the
288
- output of `remote-pi daemon status`, the recent supervisor log, and
289
- the contents of `~/.pi/remote/daemons.json`.
279
+ output of the service status, the launcher log, and the contents of
280
+ `~/.pi/extensions/un-bien.json`.
package/package.json CHANGED
@@ -1,13 +1,23 @@
1
1
  {
2
2
  "name": "@geohar/un-bien",
3
- "version": "0.8.0",
3
+ "version": "0.14.0",
4
4
  "description": "Mobile remote control and local agent mesh for the Pi coding agent. Pair your phone via QR over a relay, watch tool calls in real time, run multi-Pi sessions over a local Unix Domain Socket broker, and let agents talk to each other through structured request/reply. Derived from remote-pi by Jacob Moura (https://github.com/jacobaraujo7/remote_pi), MIT.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "bin": {
9
- "unbien": "dist/index.js",
10
- "pi-supervisord": "dist/bin/supervisord.js"
9
+ "unbien": "dist/index.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./launcher": {
17
+ "types": "./dist/bin/launcher.d.ts",
18
+ "default": "./dist/bin/launcher.js"
19
+ },
20
+ "./package.json": "./package.json"
11
21
  },
12
22
  "scripts": {
13
23
  "build": "tsc -p tsconfig.build.json",
@@ -61,14 +71,6 @@
61
71
  "engines": {
62
72
  "node": ">=20.0.0"
63
73
  },
64
- "pnpm": {
65
- "onlyBuiltDependencies": [
66
- "@google/genai",
67
- "esbuild",
68
- "koffi",
69
- "protobufjs"
70
- ]
71
- },
72
74
  "devDependencies": {
73
75
  "@types/node": "^25.8.0",
74
76
  "@types/ws": "^8.18.1",
@@ -1,15 +1,15 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <!-- un-bien daemon supervisor (plan/26). Generated by `unbien install`. -->
3
+ <!-- un-bien launcher daemon. Generated by `unbien install`. -->
4
4
  <plist version="1.0">
5
5
  <dict>
6
6
  <key>Label</key>
7
- <string>dev.unbien.supervisord</string>
7
+ <string>dev.unbien.launcher</string>
8
8
 
9
9
  <key>ProgramArguments</key>
10
10
  <array>
11
11
  <string>{NODE}</string>
12
- <string>{SUPERVISOR}</string>
12
+ <string>{PRESENCE}</string>
13
13
  </array>
14
14
 
15
15
  <key>RunAtLoad</key>
@@ -18,14 +18,15 @@
18
18
  <true/>
19
19
 
20
20
  <key>StandardOutPath</key>
21
- <string>{HOME}/.pi/un-bien/supervisord.log</string>
21
+ <string>{LOG}</string>
22
22
  <key>StandardErrorPath</key>
23
- <string>{HOME}/.pi/un-bien/supervisord.log</string>
23
+ <string>{LOG}</string>
24
24
 
25
25
  <key>EnvironmentVariables</key>
26
26
  <dict>
27
- <!-- Inherit the user's shell PATH so `pi --mode rpc` resolves to the
28
- same binary it would in Terminal.app (Homebrew / npm-global / etc.). -->
27
+ <!-- Inherit the user's shell PATH so `tmux`/`herdr` (the remote-launch
28
+ backends) and `pi` resolve the same way they would in Terminal.app
29
+ (Homebrew / npm-global / etc.). -->
29
30
  <key>PATH</key>
30
31
  <string>{PATH}</string>
31
32
  <key>HOME</key>
@@ -1,17 +1,18 @@
1
1
  [Unit]
2
- Description=Remote Pi daemon supervisor (plan/26)
2
+ Description=un-bien launcher daemon
3
3
  Documentation=https://docs.georgeharker.com/un-bien
4
4
  After=default.target
5
5
 
6
6
  [Service]
7
7
  Type=simple
8
- ExecStart={NODE} {SUPERVISOR}
8
+ ExecStart={NODE} {PRESENCE}
9
9
  Restart=on-failure
10
10
  RestartSec=5s
11
11
  StandardOutput=journal
12
12
  StandardError=journal
13
- # Inherit the user's shell PATH so `pi --mode rpc` resolves to the same
14
- # binary it would in an interactive shell (npm-global / Homebrew / etc.).
13
+ # Inherit the user's shell PATH so `tmux`/`herdr` (remote-launch backends)
14
+ # and `pi` resolve to the same binaries they would in an interactive shell
15
+ # (npm-global / Homebrew / etc.).
15
16
  Environment="PATH={PATH}"
16
17
  Environment="HOME={HOME}"
17
18
 
@@ -1,10 +1,10 @@
1
- ' Remote Pi supervisor launcher — runs node hidden (no console window) and tees
2
- ' stdout+stderr to {LOG} so crashes are diagnosable (Task Scheduler gives the
3
- ' hidden process no console, mirroring launchd/systemd log redirection).
1
+ ' un-bien launcher daemon launcher — runs node hidden (no console window) and
2
+ ' tees stdout+stderr to {LOG} so crashes are diagnosable (Task Scheduler gives
3
+ ' the hidden process no console, mirroring launchd/systemd log redirection).
4
4
  ' `cmd /c` is required for the `>>` redirection. Run(cmd, 0, True): window
5
5
  ' style 0 = hidden, wait = True so wscript stays alive for node's lifetime →
6
- ' Task Scheduler's RestartOnFailure still monitors the supervisor.
6
+ ' Task Scheduler's RestartOnFailure still monitors the launcher daemon.
7
7
  ' WScript.Quit propagates node's exit code.
8
8
  Dim rc
9
- rc = CreateObject("Wscript.Shell").Run("cmd /c """"{NODE}"" ""{SUPERVISOR}"" >> ""{LOG}"" 2>&1""", 0, True)
9
+ rc = CreateObject("Wscript.Shell").Run("cmd /c """"{NODE}"" ""{PRESENCE}"" >> ""{LOG}"" 2>&1""", 0, True)
10
10
  WScript.Quit rc
@@ -1,7 +1,7 @@
1
1
  <?xml version="1.0" encoding="UTF-16"?>
2
2
  <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
3
3
  <RegistrationInfo>
4
- <Description>Remote Pi daemon supervisor (pi-supervisord) — keeps background Pi agents running.</Description>
4
+ <Description>un-bien launcher daemon — keeps the machine reachable on the mesh.</Description>
5
5
  </RegistrationInfo>
6
6
  <Triggers>
7
7
  <LogonTrigger>