@yefengr/remote-pi 0.7.4 → 0.7.6
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 +81 -586
- package/dist/bin/supervisord.js +4 -5
- package/dist/bin/supervisord.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -2
- package/dist/daemon/cli-links.d.ts +30 -0
- package/dist/daemon/cli-links.js +134 -0
- package/dist/daemon/cli-links.js.map +1 -0
- package/dist/daemon/commands.d.ts +27 -0
- package/dist/daemon/commands.js +295 -0
- package/dist/daemon/commands.js.map +1 -0
- package/dist/daemon/control_protocol.d.ts +53 -31
- package/dist/daemon/control_protocol.js +8 -31
- package/dist/daemon/control_protocol.js.map +1 -1
- package/dist/daemon/cron_log.d.ts +2 -23
- package/dist/daemon/cron_log.js +10 -25
- package/dist/daemon/cron_log.js.map +1 -1
- package/dist/daemon/cron_registry.d.ts +3 -40
- package/dist/daemon/cron_registry.js +58 -103
- package/dist/daemon/cron_registry.js.map +1 -1
- package/dist/daemon/install-runtime.d.ts +10 -0
- package/dist/daemon/install-runtime.js +81 -0
- package/dist/daemon/install-runtime.js.map +1 -0
- package/dist/daemon/install.d.ts +3 -63
- package/dist/daemon/install.js +5 -289
- package/dist/daemon/install.js.map +1 -1
- package/dist/daemon/preflight.d.ts +51 -0
- package/dist/daemon/preflight.js +136 -0
- package/dist/daemon/preflight.js.map +1 -0
- package/dist/daemon/registry.d.ts +33 -45
- package/dist/daemon/registry.js +171 -117
- package/dist/daemon/registry.js.map +1 -1
- package/dist/daemon/rpc_child.d.ts +92 -146
- package/dist/daemon/rpc_child.js +336 -263
- package/dist/daemon/rpc_child.js.map +1 -1
- package/dist/daemon/status.d.ts +45 -0
- package/dist/daemon/status.js +87 -0
- package/dist/daemon/status.js.map +1 -0
- package/dist/daemon/supervisor-ipc.d.ts +2 -0
- package/dist/daemon/supervisor-ipc.js +20 -0
- package/dist/daemon/supervisor-ipc.js.map +1 -0
- package/dist/daemon/supervisor.d.ts +48 -71
- package/dist/daemon/supervisor.js +430 -420
- package/dist/daemon/supervisor.js.map +1 -1
- package/dist/extension_ui_bridge.d.ts +4 -3
- package/dist/extension_ui_bridge.js +10 -0
- package/dist/extension_ui_bridge.js.map +1 -1
- package/dist/index.d.ts +25 -230
- package/dist/index.js +515 -5553
- package/dist/index.js.map +1 -1
- package/dist/pairing/crypto.d.ts +8 -1
- package/dist/pairing/crypto.js +56 -6
- package/dist/pairing/crypto.js.map +1 -1
- package/dist/pairing/owner_storage.d.ts +42 -0
- package/dist/pairing/owner_storage.js +207 -0
- package/dist/pairing/owner_storage.js.map +1 -0
- package/dist/pairing/qr.d.ts +3 -42
- package/dist/pairing/qr.js +9 -59
- package/dist/pairing/qr.js.map +1 -1
- package/dist/pairing/storage.d.ts +3 -45
- package/dist/pairing/storage.js +10 -223
- package/dist/pairing/storage.js.map +1 -1
- package/dist/protocol/types.d.ts +1 -1
- package/dist/protocol/v2/schemas.d.ts +1 -1
- package/dist/protocol/v2/schemas.js +1 -1
- package/dist/protocol/v2/schemas.js.map +1 -1
- package/dist/runtime/owner_router.d.ts +16 -0
- package/dist/runtime/owner_router.js +37 -0
- package/dist/runtime/owner_router.js.map +1 -0
- package/dist/session/ipc.d.ts +1 -22
- package/dist/session/ipc.js +4 -11
- package/dist/session/ipc.js.map +1 -1
- package/dist/session/local_config.d.ts +4 -47
- package/dist/session/local_config.js +19 -101
- package/dist/session/local_config.js.map +1 -1
- package/dist/transport/peer_channel.d.ts +25 -39
- package/dist/transport/peer_channel.js +74 -131
- package/dist/transport/peer_channel.js.map +1 -1
- package/dist/transport/relay_client.d.ts +26 -70
- package/dist/transport/relay_client.js +37 -106
- package/dist/transport/relay_client.js.map +1 -1
- package/docs/daemon.md +91 -207
- package/package.json +21 -17
- package/dist/daemon/id.d.ts +0 -24
- package/dist/daemon/id.js +0 -36
- package/dist/daemon/id.js.map +0 -1
- package/dist/mcp/mesh_result.d.ts +0 -10
- package/dist/mcp/mesh_result.js +0 -42
- package/dist/mcp/mesh_result.js.map +0 -1
- package/dist/mcp/mesh_server.d.ts +0 -16
- package/dist/mcp/mesh_server.js +0 -327
- package/dist/mcp/mesh_server.js.map +0 -1
- package/dist/mesh/canonical.d.ts +0 -30
- package/dist/mesh/canonical.js +0 -61
- package/dist/mesh/canonical.js.map +0 -1
- package/dist/mesh/client.d.ts +0 -18
- package/dist/mesh/client.js +0 -125
- package/dist/mesh/client.js.map +0 -1
- package/dist/mesh/encoding.d.ts +0 -38
- package/dist/mesh/encoding.js +0 -216
- package/dist/mesh/encoding.js.map +0 -1
- package/dist/mesh/self_revoke.d.ts +0 -73
- package/dist/mesh/self_revoke.js +0 -401
- package/dist/mesh/self_revoke.js.map +0 -1
- package/dist/mesh/siblings.d.ts +0 -49
- package/dist/mesh/siblings.js +0 -159
- package/dist/mesh/siblings.js.map +0 -1
- package/dist/mesh/types.d.ts +0 -34
- package/dist/mesh/types.js +0 -11
- package/dist/mesh/types.js.map +0 -1
- package/dist/mesh/verify.d.ts +0 -17
- package/dist/mesh/verify.js +0 -86
- package/dist/mesh/verify.js.map +0 -1
- package/dist/rooms.d.ts +0 -29
- package/dist/rooms.js +0 -57
- package/dist/rooms.js.map +0 -1
- package/dist/session/bridge.d.ts +0 -37
- package/dist/session/bridge.js +0 -130
- package/dist/session/bridge.js.map +0 -1
- package/dist/session/broker.d.ts +0 -189
- package/dist/session/broker.js +0 -507
- package/dist/session/broker.js.map +0 -1
- package/dist/session/broker_remote.d.ts +0 -74
- package/dist/session/broker_remote.js +0 -583
- package/dist/session/broker_remote.js.map +0 -1
- package/dist/session/cwd_lock.d.ts +0 -33
- package/dist/session/cwd_lock.js +0 -126
- package/dist/session/cwd_lock.js.map +0 -1
- package/dist/session/envelope.d.ts +0 -33
- package/dist/session/envelope.js +0 -117
- package/dist/session/envelope.js.map +0 -1
- package/dist/session/global_config.d.ts +0 -33
- package/dist/session/global_config.js +0 -73
- package/dist/session/global_config.js.map +0 -1
- package/dist/session/leader_election.d.ts +0 -32
- package/dist/session/leader_election.js +0 -106
- package/dist/session/leader_election.js.map +0 -1
- package/dist/session/mesh_node.d.ts +0 -116
- package/dist/session/mesh_node.js +0 -573
- package/dist/session/mesh_node.js.map +0 -1
- package/dist/session/peer.d.ts +0 -139
- package/dist/session/peer.js +0 -451
- package/dist/session/peer.js.map +0 -1
- package/dist/session/peer_inventory.d.ts +0 -13
- package/dist/session/peer_inventory.js +0 -48
- package/dist/session/peer_inventory.js.map +0 -1
- package/dist/session/peer_limits.d.ts +0 -9
- package/dist/session/peer_limits.js +0 -21
- package/dist/session/peer_limits.js.map +0 -1
- package/dist/session/setup_wizard.d.ts +0 -39
- package/dist/session/setup_wizard.js +0 -63
- package/dist/session/setup_wizard.js.map +0 -1
- package/dist/session/tools.d.ts +0 -24
- package/dist/session/tools.js +0 -252
- package/dist/session/tools.js.map +0 -1
- package/dist/session/wizard.d.ts +0 -13
- package/dist/session/wizard.js +0 -20
- package/dist/session/wizard.js.map +0 -1
- package/dist/transport/pi_forward_client.d.ts +0 -29
- package/dist/transport/pi_forward_client.js +0 -62
- package/dist/transport/pi_forward_client.js.map +0 -1
- package/dist/ui/footer.d.ts +0 -32
- package/dist/ui/footer.js +0 -34
- package/dist/ui/footer.js.map +0 -1
- package/skills/agent-network/SKILL.md +0 -310
package/README.md
CHANGED
|
@@ -4,670 +4,165 @@
|
|
|
4
4
|
|
|
5
5
|
<h1 align="center">Remote Pi</h1>
|
|
6
6
|
|
|
7
|
-
>
|
|
8
|
-
> superpowers: agents that talk to each other on the same machine, and a browser
|
|
9
|
-
> PWA that drives Pi remotely.
|
|
7
|
+
> A Pi extension for browser control of local Pi endpoints, with an optional supervised daemon lifecycle.
|
|
10
8
|
|
|
11
9
|
**Homepage:** <https://remote-pi.jacobmoura.work>
|
|
12
10
|
|
|
13
|
-
`/remote-pi`
|
|
14
|
-
first time it asks a couple of questions and you are done.
|
|
11
|
+
`/remote-pi` connects the current Pi endpoint to a Relay and provides pairing for the Remote Pi PWA. The browser selects endpoint cards, sends prompts, receives a live timeline, and can request a small set of typed session actions.
|
|
15
12
|
|
|
16
|
-
##
|
|
13
|
+
## Endpoint model
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
membership, and the trust model (what the relay sees and doesn't see),
|
|
20
|
-
read [`PROTOCOL.md`](../PROTOCOL.md) at the repo root. It is the canonical
|
|
21
|
-
document — this README only covers user-facing setup.
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## Quick start
|
|
26
|
-
|
|
27
|
-
Install the extension (one-time):
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
pi install npm:@yefengr/remote-pi
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Then in any Pi terminal:
|
|
34
|
-
|
|
35
|
-
```text
|
|
36
|
-
/remote-pi
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
The first run shows a short interactive wizard (agent name, default session,
|
|
40
|
-
whether to auto-start the relay). On every following run, `/remote-pi` joins
|
|
41
|
-
the local agent session and starts the relay automatically — no extra typing.
|
|
42
|
-
|
|
43
|
-
### Try the agent network in 30 seconds
|
|
44
|
-
|
|
45
|
-
Open **two** Pi terminals in the same directory and run `/remote-pi` in each.
|
|
46
|
-
Both join the same session. Now just talk to the LLM — it has the tools.
|
|
47
|
-
|
|
48
|
-
In terminal A (say it ended up named `agent-A`):
|
|
49
|
-
|
|
50
|
-
```text
|
|
51
|
-
Who else is connected in our agent session? List them.
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
The LLM calls `list_peers` and reports the complete routing addresses it sees.
|
|
55
|
-
|
|
56
|
-
Then, still in terminal A:
|
|
15
|
+
Remote Pi addresses process state as:
|
|
57
16
|
|
|
58
17
|
```text
|
|
59
|
-
|
|
18
|
+
device → endpoint → runtime → session / history generation
|
|
60
19
|
```
|
|
61
20
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
terminal A's inbox or a later turn. It does not block terminal A waiting for
|
|
67
|
-
agent-B's content reply.
|
|
68
|
-
|
|
69
|
-
Copy the complete address exactly as listed. Do not build, parse, decode, or
|
|
70
|
-
normalize it.
|
|
71
|
-
|
|
72
|
-
---
|
|
73
|
-
|
|
74
|
-
## What it does
|
|
75
|
-
|
|
76
|
-
Remote Pi adds two independent layers on top of Pi. You can use either, or
|
|
77
|
-
both:
|
|
78
|
-
|
|
79
|
-
### 1) Agent network (local broker, optional cross-PC relay)
|
|
80
|
-
|
|
81
|
-
Several Pi instances running side-by-side in different terminals can discover
|
|
82
|
-
each other and exchange messages. Each instance is a peer in a named
|
|
83
|
-
*session*. The LLM uses:
|
|
84
|
-
|
|
85
|
-
- `list_peers` — discover current peer routing addresses
|
|
86
|
-
- `agent_send` — unicast waits for the broker delivery ACK; broadcast is
|
|
87
|
-
fire-and-forget
|
|
88
|
-
|
|
89
|
-
The legacy Pi-only `agent_request` tool is deprecated because it blocks while
|
|
90
|
-
waiting for another agent's content reply. Use `agent_send`, continue the
|
|
91
|
-
current turn, and receive any later reply through the inbox/turn flow with
|
|
92
|
-
`re` correlating it to the original message id.
|
|
93
|
-
|
|
94
|
-
Peers on the same machine talk over a Unix domain socket at
|
|
95
|
-
`~/.pi/remote/sessions/<session-name>/broker.sock`. When sibling PCs are paired,
|
|
96
|
-
a leader-capable Extension or MCP participant bridges the opaque cross-PC
|
|
97
|
-
addresses over the relay; local-only use stays on UDS when relay access is off.
|
|
98
|
-
Useful for splitting work across roles (`backend`, `frontend`, `tests`,
|
|
99
|
-
`orchestrator`, …) and letting them coordinate.
|
|
100
|
-
|
|
101
|
-
The first agent to enter a session becomes the *leader* (hosts the broker);
|
|
102
|
-
the rest are *followers*. If the leader exits, a follower automatically takes
|
|
103
|
-
over — the failover is invisible to the LLMs.
|
|
21
|
+
- **Device**: a computer identity.
|
|
22
|
+
- **Endpoint**: a stable interactive or daemon target. A working directory may host more than one endpoint.
|
|
23
|
+
- **Runtime**: the current process instance for an endpoint. A daemon restart keeps the endpoint and starts a new runtime.
|
|
24
|
+
- **Session / generation**: the currently live Pi conversation and its history branch. The PWA does not list or resume historical Pi sessions.
|
|
104
25
|
|
|
105
|
-
|
|
26
|
+
The pairing QR is endpoint- and runtime-aware. Pair every computer independently, and revoke pairings independently on each computer. The PWA can retain multiple devices and multiple endpoint cards for each device.
|
|
106
27
|
|
|
107
|
-
|
|
108
|
-
from any modern browser. The browser and the Pi process find each other through
|
|
109
|
-
a **relay**: a small WebSocket server that ferries messages between them.
|
|
110
|
-
Pairing is one-time per browser profile, via QR code.
|
|
111
|
-
|
|
112
|
-
Communication uses WebSocket over TLS to the relay. Fields such as `ct` are
|
|
113
|
-
wire containers, not a systemwide end-to-end confidentiality guarantee: current
|
|
114
|
-
Pi-forward, cross-PC, app, and control envelopes visible to the relay are not
|
|
115
|
-
fully opaque or E2E encrypted. A relay operator can see routed plaintext
|
|
116
|
-
protocol content and metadata; see [`PROTOCOL.md`](../PROTOCOL.md) for the exact
|
|
117
|
-
trust boundaries.
|
|
118
|
-
|
|
119
|
-
**Open the PWA** — use the browser workspace at:
|
|
120
|
-
|
|
121
|
-
<https://remote-pi.jacobmoura.work/app>
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## PWA actions
|
|
126
|
-
|
|
127
|
-
Beyond the chat, the PWA surfaces a small set of typed actions you can run
|
|
128
|
-
on the paired Pi session. Open the actions control next to the message input
|
|
129
|
-
when the input is empty to open the Quick Actions sheet:
|
|
130
|
-
|
|
131
|
-
| Action | What it does |
|
|
132
|
-
|---|---|
|
|
133
|
-
| **Compact context** | Runs `ctx.compact()` — same as `/compact` in the TUI. |
|
|
134
|
-
| **New session** | Runs `ctx.newSession()` — equivalent to `/new`, asks for confirmation first. |
|
|
135
|
-
| **Model** | Opens a model picker fed by your authenticated providers (same source the TUI uses) and switches via `pi.setModel(model)`. |
|
|
136
|
-
| **Thinking** | Segmented control with the 6 SDK levels (`off` · `minimal` · `low` · `medium` · `high` · `xhigh`). Changes via `pi.setThinkingLevel(level)`. |
|
|
137
|
-
|
|
138
|
-
Each action gets a structured `action_ok` / `action_error` reply so the PWA
|
|
139
|
-
can show an inline error on failure. Visible side-effects (chat output, model
|
|
140
|
-
change broadcasts, compaction notice) still flow through the normal chat
|
|
141
|
-
channels. The wire schema is documented in [`PROTOCOL.md`](../PROTOCOL.md)
|
|
142
|
-
under "App actions".
|
|
143
|
-
|
|
144
|
-
It is **not** a generic slash-command picker. The Pi SDK does not expose
|
|
145
|
-
programmatic invocation for most builtins (those live in the TUI's
|
|
146
|
-
interactive loop), so the PWA exposes only the actions that have a clean
|
|
147
|
-
SDK call. The [`pi-telegram`](https://github.com/llblab/pi-telegram) adapter
|
|
148
|
-
follows the same pattern.
|
|
149
|
-
|
|
150
|
-
### Images
|
|
151
|
-
|
|
152
|
-
The PWA can attach **one image** from the browser to a message. It's
|
|
153
|
-
compressed client-side and rides **inline** in the `user_message` — the
|
|
154
|
-
optional `images` field carries `{ data: <base64>, mime }`. The pi-extension
|
|
155
|
-
turns it into the SDK's multimodal content (an `ImageContent` followed by the
|
|
156
|
-
caption `TextContent`) and calls `sendUserMessage(content)`, so the model sees
|
|
157
|
-
the picture plus your text.
|
|
158
|
-
|
|
159
|
-
Whether a model accepts images is surfaced as a `vision` flag on each
|
|
160
|
-
`WireModel` (derived from the SDK's `Model.input` including `"image"`); the PWA
|
|
161
|
-
disables the attach button when the active model is text-only.
|
|
162
|
-
|
|
163
|
-
The **relay is unchanged** — the image travels inside the same application
|
|
164
|
-
message container as the text, so there's no binary channel (large files are a
|
|
165
|
-
future track). Base64 or a field named `ct` is not an E2E confidentiality
|
|
166
|
-
boundary; the current Relay visibility follows the trust model above. Text-only
|
|
167
|
-
messages are unaffected.
|
|
168
|
-
|
|
169
|
-
---
|
|
170
|
-
|
|
171
|
-
## Install
|
|
28
|
+
## Quick start
|
|
172
29
|
|
|
173
|
-
|
|
30
|
+
Install once in any project where Pi runs:
|
|
174
31
|
|
|
175
32
|
```bash
|
|
176
33
|
pi install npm:@yefengr/remote-pi
|
|
177
34
|
```
|
|
178
35
|
|
|
179
|
-
|
|
180
|
-
agent skill that teaches the LLM how to use `list_peers`, `agent_send`, and the
|
|
181
|
-
event-driven inbox/reply flow.
|
|
182
|
-
|
|
183
|
-
To verify:
|
|
184
|
-
|
|
185
|
-
```text
|
|
186
|
-
/remote-pi config
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
It should print the effective relay URL and where it came from
|
|
190
|
-
(`env` / `config` / `default`).
|
|
191
|
-
|
|
192
|
-
---
|
|
193
|
-
|
|
194
|
-
## Using `/remote-pi`
|
|
195
|
-
|
|
196
|
-
The bare command is the everyday entry point:
|
|
36
|
+
Then in Pi:
|
|
197
37
|
|
|
198
38
|
```text
|
|
199
39
|
/remote-pi
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
Behavior depends on whether there's a local config for this directory:
|
|
203
|
-
|
|
204
|
-
| State | What happens |
|
|
205
|
-
|---|---|
|
|
206
|
-
| First run (no `.pi/remote-pi/config.json`) | Interactive wizard → saves config → joins agent session → starts relay (if you opted in) |
|
|
207
|
-
| Returning user, auto-start enabled | Joins agent session + starts relay automatically, then prints status |
|
|
208
|
-
| Returning user, auto-start disabled | Prints status only; join/relay must be run manually |
|
|
209
|
-
|
|
210
|
-
The wizard asks three questions:
|
|
211
|
-
|
|
212
|
-
1. **Agent name** — the presentation leaf name for this agent. Senders still
|
|
213
|
-
copy the complete opaque address returned by `list_peers`; they never build
|
|
214
|
-
an address from this name. Defaults to the directory name.
|
|
215
|
-
2. **Default session** — the name of the agent-network room for this
|
|
216
|
-
directory. Multiple terminals in the same directory join the same session.
|
|
217
|
-
3. **Auto-start relay (for PWA access)?** — `Yes` if you want
|
|
218
|
-
`/remote-pi` to also connect to the relay so the browser PWA can reach this
|
|
219
|
-
Pi. `No` for local-only use (agent network without remote access).
|
|
220
|
-
|
|
221
|
-
Re-run the wizard later with `/remote-pi setup`.
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
## Pairing the browser PWA
|
|
226
|
-
|
|
227
|
-
Once the relay is up (`/remote-pi relay status` shows `started` or `paired`):
|
|
228
|
-
|
|
229
|
-
```text
|
|
230
40
|
/remote-pi pair
|
|
231
41
|
```
|
|
232
42
|
|
|
233
|
-
|
|
234
|
-
Pairing is **per machine** — once a browser profile is paired, every Pi process
|
|
235
|
-
on this machine accepts it (the host record lives in `~/.pi/remote/peers.json`).
|
|
43
|
+
The first run creates a per-folder endpoint configuration and connects to the configured Relay. The QR command prints a one-time URI. Scan it in the [Remote Pi PWA](https://remote-pi.jacobmoura.work/app), select the endpoint card, and send a prompt.
|
|
236
44
|
|
|
237
|
-
|
|
45
|
+
Pairings are local to the computer that creates them:
|
|
238
46
|
|
|
239
47
|
```text
|
|
240
48
|
/remote-pi devices
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
To remove one:
|
|
244
|
-
|
|
245
|
-
```text
|
|
246
49
|
/remote-pi revoke <shortid>
|
|
247
50
|
```
|
|
248
51
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
---
|
|
252
|
-
|
|
253
|
-
## The relay
|
|
254
|
-
|
|
255
|
-
The relay is the network boundary. TLS protects transit, but the Relay can see
|
|
256
|
-
routed plaintext protocol content and metadata; use a relay you trust or
|
|
257
|
-
self-host. There is no systemwide or PC-mesh E2E guarantee. For Pi-to-Pi
|
|
258
|
-
forwarding, the Relay currently permits a route when any correctly signed Owner
|
|
259
|
-
blob lists both canonical Pi keys. That does not prove the Owner paired with or
|
|
260
|
-
controls either Pi.
|
|
261
|
-
|
|
262
|
-
### Upgrade order (Relay 0.3 first, then Extension 0.6)
|
|
263
|
-
|
|
264
|
-
Upgrade the **Relay to 0.3 first**: an old Extension can consume the new
|
|
265
|
-
Relay's UUID errors. Extension 0.6 carries a one-release legacy wire-label
|
|
266
|
-
shim, so mixed new/old Extensions interoperate when both select the same unique
|
|
267
|
-
colon-free signed nickname label, or when neither has one and both use the
|
|
268
|
-
canonical standard-padded key prefix. Delimiter or collision cases, like
|
|
269
|
-
divergent nickname views, are unsupported and may be silently dropped by the
|
|
270
|
-
old receiver. Upgrade all Extension/MCP participants in one maintenance window.
|
|
271
|
-
The shim does not replace the receiver-local aliases returned by `list_peers`;
|
|
272
|
-
addresses remain opaque.
|
|
273
|
-
|
|
274
|
-
Extension 0.6 accepts an old Relay's lowercase 32-hex trusted error ID only as
|
|
275
|
-
a narrow shim for an old Relay or Relay rollback; that shim is not why
|
|
276
|
-
Relay-first is safe.
|
|
52
|
+
## Browser session actions
|
|
277
53
|
|
|
278
|
-
|
|
54
|
+
The PWA supports normal chat plus typed actions that Pi can apply directly:
|
|
279
55
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
Caveats:
|
|
288
|
-
|
|
289
|
-
- Shared infrastructure — availability is best-effort.
|
|
290
|
-
- **There is no IP allow-listing or VPN gating**.
|
|
291
|
-
|
|
292
|
-
### Option B — Self-host (recommended for privacy)
|
|
56
|
+
| Action | Effect |
|
|
57
|
+
|---|---|
|
|
58
|
+
| Compact context | Calls `ctx.compact()` |
|
|
59
|
+
| New session | Calls `ctx.newSession()` after confirmation |
|
|
60
|
+
| Model | Uses `pi.setModel(model)` |
|
|
61
|
+
| Thinking | Uses `pi.setThinkingLevel(level)` |
|
|
293
62
|
|
|
294
|
-
|
|
295
|
-
[Tailscale](https://tailscale.com), [WireGuard](https://www.wireguard.com),
|
|
296
|
-
or your own VPC. Because the relay's network-level protection is just TLS +
|
|
297
|
-
keypair authentication, layering a VPN on top means **only your devices** can
|
|
298
|
-
even reach the WebSocket port — defense in depth.
|
|
63
|
+
The model picker reflects the providers configured on the host. Pi settings are the only extension source used by the supervisor and interactive Pi; Remote Pi does not inject an additional extension argument when starting Pi.
|
|
299
64
|
|
|
300
|
-
|
|
301
|
-
[relay README](https://github.com/jacobaraujo7/remote_pi/blob/main/relay/README.md#self-hosted-relay-recommended-for-privacy)
|
|
302
|
-
for the full setup, environment variables, and reverse-proxy guidance):
|
|
65
|
+
An optional companion adds rich remote clarification prompts:
|
|
303
66
|
|
|
304
67
|
```bash
|
|
305
|
-
|
|
306
|
-
--name remote-pi-relay \
|
|
307
|
-
-p 3000:3000 \
|
|
308
|
-
--restart unless-stopped \
|
|
309
|
-
ghcr.io/jacobaraujo7/remote-pi-relay:latest
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
Bind the container to your VPN interface, terminate TLS in a reverse proxy,
|
|
313
|
-
and point both your Pi and the browser PWA at the resulting `https://…` URL.
|
|
314
|
-
|
|
315
|
-
### Pointing Pi at your own relay
|
|
316
|
-
|
|
317
|
-
Once your relay is reachable, tell the extension:
|
|
318
|
-
|
|
319
|
-
```text
|
|
320
|
-
/remote-pi relay url https://relay.yourdomain.tld
|
|
68
|
+
pi install npm:@eko24ive/pi-ask
|
|
321
69
|
```
|
|
322
70
|
|
|
323
|
-
|
|
324
|
-
rejected at validation. The extension converts to WebSocket internally when
|
|
325
|
-
it opens the connection. Use the same canonical URL in the PWA and any
|
|
326
|
-
self-hosting docs: paste the URL your reverse proxy exposes.
|
|
71
|
+
## Relay configuration
|
|
327
72
|
|
|
328
|
-
|
|
329
|
-
order (highest precedence first):
|
|
73
|
+
The effective Relay URL resolves in this order:
|
|
330
74
|
|
|
331
|
-
1. `REMOTE_PI_RELAY`
|
|
75
|
+
1. `REMOTE_PI_RELAY`
|
|
332
76
|
2. `~/.pi/remote/config.json`
|
|
333
|
-
3.
|
|
77
|
+
3. `https://relay-pi.yefengr.cn`
|
|
334
78
|
|
|
335
|
-
|
|
79
|
+
Set and inspect it from Pi:
|
|
336
80
|
|
|
337
81
|
```text
|
|
82
|
+
/remote-pi set-relay https://relay.example.com
|
|
338
83
|
/remote-pi config
|
|
339
84
|
```
|
|
340
85
|
|
|
341
|
-
|
|
342
|
-
`/remote-pi relay start` (or `/remote-pi relay` to toggle).
|
|
343
|
-
|
|
344
|
-
The PWA has its own relay-URL setting in the workspace preferences — keep
|
|
345
|
-
both pointing at the same relay.
|
|
346
|
-
|
|
347
|
-
---
|
|
348
|
-
|
|
349
|
-
## Agent network: deeper look
|
|
350
|
-
|
|
351
|
-
Each session is one Unix-domain-socket broker plus N peers. The broker
|
|
352
|
-
multiplexes messages by opaque `to` address and broadcasts system events
|
|
353
|
-
(`peer_joined`, `peer_left`).
|
|
354
|
-
|
|
355
|
-
Inside the LLM, the agent skill uses `list_peers` for discovery and
|
|
356
|
-
`agent_send` for delivery:
|
|
357
|
-
|
|
358
|
-
```jsonc
|
|
359
|
-
list_peers() // copy a complete address from this result
|
|
360
|
-
|
|
361
|
-
agent_send({
|
|
362
|
-
to: "/repo/api@backend", // exact opaque address returned by list_peers
|
|
363
|
-
body: { task: "add /healthz endpoint" },
|
|
364
|
-
re: "<id>" // set to the received message id when replying
|
|
365
|
-
})
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
A unicast `agent_send` waits for the broker delivery ACK and returns the public
|
|
369
|
-
status `received`, `denied`, or `timeout`; broadcast is fire-and-forget. A
|
|
370
|
-
trusted Relay's closed transport reason is returned in `details` without
|
|
371
|
-
changing those statuses: `offline` maps to `timeout`, while `not_authorized`
|
|
372
|
-
and `bad_envelope` map to `denied`. Genuine silence is a reasonless `timeout`.
|
|
373
|
-
Do not blindly retry authorization or envelope failures. Trusted Relay errors
|
|
374
|
-
are consumed internally to settle pending sends; forged or invalid reserved
|
|
375
|
-
bodies do not gain that authority.
|
|
376
|
-
|
|
377
|
-
Mesh addresses are opaque routing values: echo them verbatim, including
|
|
378
|
-
receiver-local PC aliases with percent-encoded bytes (such as `%3A` or `%25`)
|
|
379
|
-
or collision suffixes containing `~`. Never parse, build, decode, or normalize
|
|
380
|
-
an address for routing or security. A PC alias is receiver-local presentation
|
|
381
|
-
and routing only, so different PCs may list the same sibling under different
|
|
382
|
-
aliases. The canonical 32-byte Ed25519 Pi public key is the PC's technical
|
|
383
|
-
identity; never use an alias as proof of identity.
|
|
384
|
-
|
|
385
|
-
`agent_request` remains available only as a deprecated legacy Pi tool. Prefer
|
|
386
|
-
`agent_send`, then handle any later inbox/turn reply whose `re` matches the
|
|
387
|
-
original message id.
|
|
388
|
-
|
|
389
|
-
The wire format is a 5-field envelope `{ from, to, id, re, body }` serialized
|
|
390
|
-
as one JSON line per message. The leader's broker writes an `audit.jsonl`
|
|
391
|
-
log at `~/.pi/remote/sessions/<name>/audit.jsonl` for postmortem inspection.
|
|
392
|
-
|
|
393
|
-
Useful commands:
|
|
394
|
-
|
|
395
|
-
| Command | What it does |
|
|
396
|
-
|---|---|
|
|
397
|
-
| `/remote-pi` | Join the local mesh (and start the relay, if enabled) |
|
|
398
|
-
| `/remote-pi peers` | List local + cross-PC mesh peers, grouped by PC |
|
|
399
|
-
| `/remote-pi rename <new>` | Rename this agent in the current session |
|
|
400
|
-
| `/remote-pi stop` | Leave the local mesh and disconnect the relay |
|
|
401
|
-
|
|
402
|
-
Name collisions inside a session get a numeric suffix automatically
|
|
403
|
-
(`backend`, `backend#2`, `backend#3`). The broker assigns it and returns the
|
|
404
|
-
real name to the peer.
|
|
405
|
-
|
|
406
|
-
---
|
|
407
|
-
|
|
408
|
-
## Command reference
|
|
86
|
+
Only `http://` and `https://` are accepted at the command boundary; WebSocket conversion happens internally. The Relay keeps endpoint routing state in memory and forwards opaque `ct` payloads. See [`../relay/README.md`](../relay/README.md) for its operational and security boundary.
|
|
409
87
|
|
|
410
|
-
|
|
88
|
+
## Commands
|
|
411
89
|
|
|
412
90
|
| Command | Description |
|
|
413
91
|
|---|---|
|
|
414
|
-
| `/remote-pi` | Connect
|
|
415
|
-
| `/remote-pi
|
|
416
|
-
| `/remote-pi status` | Show
|
|
417
|
-
| `/remote-pi
|
|
418
|
-
| `/remote-pi
|
|
419
|
-
| `/remote-pi
|
|
420
|
-
| `/remote-pi
|
|
421
|
-
| `/remote-pi
|
|
422
|
-
| `/remote-pi
|
|
423
|
-
| `/remote-pi
|
|
424
|
-
| `/remote-pi
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
| `/remote-pi remove <id>` | Unregister a daemon (local config preserved) |
|
|
432
|
-
| `/remote-pi daemons` | List registered daemons + state |
|
|
433
|
-
| `/remote-pi daemon start` | Start every registered daemon |
|
|
434
|
-
| `/remote-pi daemon stop` | Stop every running daemon (`/remote-pi stop` stops only the local terminal) |
|
|
435
|
-
| `/remote-pi daemon restart` | Stop + start all daemons |
|
|
436
|
-
| `/remote-pi daemon status` | Detailed runtime status (pid, uptime, restart count) |
|
|
437
|
-
| `/remote-pi daemon send <id> "<text>"` | Send a prompt to a specific daemon |
|
|
438
|
-
| `/remote-pi cron add <id> "<expr>" "<prompt>"` | Schedule a recurring prompt (`--tz`, `--wake`, `--no-skip-busy`, `--catchup`) |
|
|
439
|
-
| `/remote-pi cron list` | List scheduled jobs (schedule, enabled, next run, last status) |
|
|
440
|
-
| `/remote-pi cron run <jobId>` | Fire a job now (ignores its schedule) |
|
|
441
|
-
| `/remote-pi cron enable\|disable <jobId>` | Toggle a job on/off |
|
|
442
|
-
| `/remote-pi cron remove <jobId>` | Delete a job |
|
|
443
|
-
| `/remote-pi cron log [<jobId>] [--tail N]` | Read the fire/skip audit log |
|
|
444
|
-
| `/remote-pi install` | Install `pi-supervisord` as a system service |
|
|
445
|
-
| `/remote-pi uninstall` | Remove the system service (registry preserved) |
|
|
446
|
-
|
|
447
|
-
All commands above work both as Pi slash commands (interactive) and as
|
|
448
|
-
shell-level `remote-pi <subcommand>` when the package is installed
|
|
449
|
-
globally (`npm install -g @yefengr/remote-pi`).
|
|
450
|
-
|
|
451
|
-
### Scheduled prompts (`cron`)
|
|
452
|
-
|
|
453
|
-
`remote-pi cron` schedules **recurring prompts** to daemons through the
|
|
454
|
-
supervisor — e.g. a daily "summarise new PRs". Output flows fire-and-forget to
|
|
455
|
-
the mesh/PWA like any prompt; the cron layer only audits the dispatch.
|
|
456
|
-
|
|
457
|
-
- **Schedule** is a cron expression (croner syntax; an optional 6th *seconds*
|
|
458
|
-
field is supported), with an optional IANA timezone via `--tz`:
|
|
459
|
-
|
|
460
|
-
```sh
|
|
461
|
-
remote-pi cron add a1b2c3d4 "0 9 * * *" "Summarise new PRs" --tz America/Sao_Paulo
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
- **Minimum interval is 60s** — more frequent schedules are rejected (guards
|
|
465
|
-
token cost + pileup). A fire is **skipped when the daemon is mid-turn**
|
|
466
|
-
(`--no-skip-busy` to override); `--wake` starts a stopped daemon first;
|
|
467
|
-
`--catchup` runs once on supervisor start if the previous run was missed.
|
|
468
|
-
- **Prerequisite**: the supervisor must run as a service (`remote-pi install`).
|
|
469
|
-
Without it there is no scheduler, and `cron` commands say so instead of
|
|
470
|
-
silently pretending to schedule.
|
|
471
|
-
- **Audit**: every fire **and** every skip appends one line to
|
|
472
|
-
`~/.pi/remote/cron.jsonl` with a `result` of `delivered`,
|
|
473
|
-
`woke_and_delivered`, `deliver_failed`, `skipped_busy`, `skipped_down`, or
|
|
474
|
-
`skipped_disabled` — read it with `remote-pi cron log`.
|
|
475
|
-
|
|
476
|
-
Step-by-step walkthrough: the [daemon tutorial](https://remote-pi.jacobmoura.work/tutorials/daemon).
|
|
477
|
-
|
|
478
|
-
### Footer + title
|
|
479
|
-
|
|
480
|
-
- `📡 local (N)` — current agent session and peer count (local mesh)
|
|
481
|
-
- `🟢 relay` — relay connected, at least one device paired (globally)
|
|
482
|
-
- `🟡 relay waiting for pairing` — relay connected, no device paired yet
|
|
483
|
-
- `📱 <shortid>` — a browser PWA profile is actively connected right now
|
|
484
|
-
|
|
485
|
-
Window title: `<agent-name> · On` when relay is up, `<agent-name> · Off`
|
|
486
|
-
otherwise. Tells your terminals apart at a glance in `cmux`/`tmux`/iTerm
|
|
487
|
-
tabs.
|
|
488
|
-
|
|
489
|
-
---
|
|
92
|
+
| `/remote-pi` | Connect the current endpoint; first use creates local configuration |
|
|
93
|
+
| `/remote-pi start` / `/remote-pi stop` | Connect or disconnect this endpoint |
|
|
94
|
+
| `/remote-pi status` | Show Relay, endpoint, and runtime state |
|
|
95
|
+
| `/remote-pi pair` | Show an endpoint- and runtime-aware pairing QR |
|
|
96
|
+
| `/remote-pi devices` | List pairings stored on this computer |
|
|
97
|
+
| `/remote-pi revoke <shortid>` | Revoke one locally stored pairing |
|
|
98
|
+
| `/remote-pi set-relay <url>` | Persist the Relay URL |
|
|
99
|
+
| `/remote-pi config` | Show the resolved Relay URL |
|
|
100
|
+
| `/remote-pi create <cwd>` | Explicitly register a daemon with desired state `running` |
|
|
101
|
+
| `/remote-pi remove <id>` | Unregister a daemon by identifier |
|
|
102
|
+
| `/remote-pi remove-cwd <cwd>` | Idempotently unregister a daemon by working directory |
|
|
103
|
+
| `/remote-pi daemons` | List registered daemons |
|
|
104
|
+
| `/remote-pi daemon start\|stop\|restart [id]` | Change the desired lifecycle for one daemon or the fleet |
|
|
105
|
+
| `/remote-pi daemon status` | Show orthogonal daemon lifecycle state |
|
|
106
|
+
| `/remote-pi install` / `/remote-pi uninstall` | Install or remove the user-level supervisor service |
|
|
107
|
+
|
|
108
|
+
The global `remote-pi` CLI exposes the same lifecycle commands after installation. The cwd-based removal command is intended for external worktree managers as well as manual cleanup.
|
|
490
109
|
|
|
491
110
|
## Daemon mode
|
|
492
111
|
|
|
493
|
-
|
|
494
|
-
PWA prompts at 3am, processing cron jobs, monitoring a folder while
|
|
495
|
-
you're not at the keyboard), promote it to a **daemon** managed by a
|
|
496
|
-
single OS-level supervisor.
|
|
497
|
-
|
|
498
|
-
See [`docs/daemon.md`](./docs/daemon.md) for troubleshooting.
|
|
499
|
-
|
|
500
|
-
### One-time setup
|
|
112
|
+
Daemon mode is an explicit opt-in:
|
|
501
113
|
|
|
502
114
|
```bash
|
|
503
|
-
# Install the package globally so `remote-pi` and `pi-supervisord`
|
|
504
|
-
# are on your PATH (`pi install npm:@yefengr/remote-pi` alone makes the Pi
|
|
505
|
-
# extension available but does NOT expose the CLI binaries — see
|
|
506
|
-
# https://docs.npmjs.com/cli/v10/configuring-npm/package-json#bin).
|
|
507
115
|
npm install -g @yefengr/remote-pi
|
|
508
|
-
|
|
509
|
-
# Install the supervisor as a user-level system service. Linux uses
|
|
510
|
-
# systemd --user; macOS uses launchd LaunchAgent. Both auto-start at
|
|
511
|
-
# login and survive reboots.
|
|
512
116
|
remote-pi install
|
|
117
|
+
remote-pi create ~/Projects/backend
|
|
118
|
+
remote-pi daemon status
|
|
513
119
|
```
|
|
514
120
|
|
|
515
|
-
The `
|
|
516
|
-
- Writes `~/.config/systemd/user/remote-pi-supervisord.service` (Linux)
|
|
517
|
-
or `~/Library/LaunchAgents/dev.remotepi.supervisord.plist` (macOS)
|
|
518
|
-
- Activates it via `systemctl --user enable --now` or `launchctl bootstrap`
|
|
519
|
-
- The supervisor starts immediately and re-starts on every login
|
|
520
|
-
|
|
521
|
-
### Per-folder workflow
|
|
522
|
-
|
|
523
|
-
For each agent you want to keep alive 24/7:
|
|
121
|
+
The v2 registry at `~/.pi/remote/daemons.json` stores an opaque daemon identifier, canonical cwd, display name, creation time, and desired lifecycle (`running` or `stopped`). Registration starts in `running`; a live supervisor starts it immediately. On supervisor startup, only registrations whose desired lifecycle is `running` are restored.
|
|
524
122
|
|
|
525
|
-
|
|
526
|
-
# 1. Configure the agent interactively first (one time).
|
|
527
|
-
cd ~/Movies
|
|
528
|
-
pi # /remote-pi → setup wizard, /remote-pi pair, etc
|
|
123
|
+
The supervisor starts Pi in RPC mode without an extra extension argument. Pi's own settings determine extension loading and model/provider configuration. A daemon runtime inherits its registered endpoint identity, while every spawn receives a fresh runtime identity.
|
|
529
124
|
|
|
530
|
-
|
|
531
|
-
# (sha256(realpath)[:8]), stable across machines.
|
|
532
|
-
remote-pi create ~/Movies --name "Video Editor"
|
|
533
|
-
# → Daemon registered: id=4e39152d name="Video Editor" cwd=/Users/x/Movies
|
|
125
|
+
### Lifecycle and health
|
|
534
126
|
|
|
535
|
-
|
|
536
|
-
remote-pi daemon start
|
|
537
|
-
```
|
|
127
|
+
`daemon status` keeps these dimensions separate:
|
|
538
128
|
|
|
539
|
-
|
|
129
|
+
| Dimension | Meaning |
|
|
130
|
+
|---|---|
|
|
131
|
+
| registration | Registered or missing working directory |
|
|
132
|
+
| desired | Persisted `running` or `stopped` intent |
|
|
133
|
+
| process | OS child absent, spawning, running, or exited |
|
|
134
|
+
| runtime | RPC pending, ready, or failed |
|
|
135
|
+
| relay | Disconnected, connecting, connected, or reconnecting |
|
|
136
|
+
| health | Stopped, starting, healthy, degraded, failed, or blocked |
|
|
540
137
|
|
|
541
|
-
|
|
542
|
-
remote-pi daemons # list + state
|
|
543
|
-
remote-pi daemon status # uptime, pid, restart count
|
|
544
|
-
remote-pi daemon send 4e39152d "Cut the first 30 seconds of latest clip"
|
|
545
|
-
remote-pi daemon stop # stop all
|
|
546
|
-
remote-pi daemon restart # restart all
|
|
547
|
-
```
|
|
138
|
+
A ready daemon reconnecting to the Relay is **degraded**, not restarted. Non-retryable configuration and startup failures become deterministic **blocked** errors. If a cwd disappears, dispatch is denied immediately and the supervisor reconciles the stale registration after confirmation.
|
|
548
139
|
|
|
549
|
-
|
|
550
|
-
back through the relay/mesh you configured during interactive setup —
|
|
551
|
-
PWA sees it live, other agents on the same machine can see it via the local
|
|
552
|
-
UDS mesh.
|
|
140
|
+
### Scheduled prompts
|
|
553
141
|
|
|
554
|
-
|
|
142
|
+
Cron owns no daemon lifecycle. A scheduled prompt is sent only when its daemon is desired `running` and its runtime is ready; otherwise it is skipped and audited. There is no wake behavior.
|
|
555
143
|
|
|
556
144
|
```bash
|
|
557
|
-
remote-pi
|
|
558
|
-
remote-pi
|
|
145
|
+
remote-pi cron add <daemon-id> "0 9 * * 1-5" "Summarize the new PRs" --tz America/Sao_Paulo
|
|
146
|
+
remote-pi cron list
|
|
147
|
+
remote-pi cron log --tail 20
|
|
559
148
|
```
|
|
560
149
|
|
|
561
|
-
`
|
|
562
|
-
registered daemon back. To wipe the registry entirely, `rm
|
|
563
|
-
~/.pi/remote/daemons.json`.
|
|
564
|
-
|
|
565
|
-
### Where to find logs
|
|
566
|
-
|
|
567
|
-
| Platform | Command |
|
|
568
|
-
|---|---|
|
|
569
|
-
| Linux | `journalctl --user -u remote-pi-supervisord -f` |
|
|
570
|
-
| macOS | `tail -f ~/.pi/remote/supervisord.log` |
|
|
571
|
-
|
|
572
|
-
Each spawned daemon's stderr is forwarded into the supervisor's log
|
|
573
|
-
with a `[<cwd>]` prefix, so a single log stream shows every agent.
|
|
574
|
-
|
|
575
|
-
### Caveats (plan/26 trade-offs)
|
|
576
|
-
|
|
577
|
-
- **Tool approval is not gated.** Daemons inherit the same Pi config
|
|
578
|
-
the interactive run uses — Bash, Edit, Write etc. all execute without
|
|
579
|
-
prompting. Configure Pi's tool permissions to taste before promoting
|
|
580
|
-
a folder to daemon.
|
|
581
|
-
- **Pairing still happens interactively.** Daemons don't show a QR
|
|
582
|
-
themselves; the keypair + paired devices come from the prior `pi`
|
|
583
|
-
session in the same folder.
|
|
584
|
-
- **Single supervisor.** If `pi-supervisord` crashes all daemons go
|
|
585
|
-
down with it. systemd/launchd restarts it within seconds; daemons
|
|
586
|
-
come back automatically.
|
|
587
|
-
- **One daemon per cwd.** The `roomIdForCwd` derivation makes daemons
|
|
588
|
-
by-path; two daemons in the same folder is rejected at `create` time.
|
|
589
|
-
|
|
590
|
-
---
|
|
150
|
+
Runs are at least 60 seconds apart. `--no-skip-busy` permits dispatch during a running turn; `--catchup` permits one missed run after supervisor startup. Audits distinguish accepted, rejected, busy, desired-stopped, starting, retrying, failed, blocked, missing, and disabled outcomes.
|
|
591
151
|
|
|
592
|
-
##
|
|
152
|
+
## Troubleshooting
|
|
593
153
|
|
|
594
|
-
|
|
595
|
-
|---|---|---|
|
|
596
|
-
| `<cwd>/.pi/remote-pi/config.json` | Per-directory | `agent_name`, `session_name`, `auto_start_relay` |
|
|
597
|
-
| `~/.pi/remote/config.json` | Per-user | `relay` URL |
|
|
598
|
-
| `~/.pi/remote/peers.json` | Per-machine | Paired PWA browser profiles |
|
|
599
|
-
| `~/.pi/remote/sessions/<name>/` | Per-session | Broker socket + `audit.jsonl` |
|
|
600
|
-
| `~/.pi/remote/skills/agent-network/SKILL.md` | Per-user | Agent skill the LLM reads |
|
|
154
|
+
For daemon service installation, status interpretation, stale cwd cleanup, and recovery steps, see [`docs/daemon.md`](./docs/daemon.md).
|
|
601
155
|
|
|
602
|
-
|
|
156
|
+
## Development
|
|
603
157
|
|
|
604
158
|
```bash
|
|
605
|
-
|
|
159
|
+
pnpm install
|
|
160
|
+
pnpm typecheck
|
|
161
|
+
pnpm test
|
|
162
|
+
pnpm build
|
|
606
163
|
```
|
|
607
164
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
## Troubleshooting
|
|
611
|
-
|
|
612
|
-
**Footer says `🟡 relay waiting for pairing` even though I paired a device.**
|
|
613
|
-
The icon reflects whether *any* device has been paired on this machine, not
|
|
614
|
-
whether one is connected right now. If you really have a paired device in
|
|
615
|
-
`/remote-pi devices`, restart Pi — the cache may be stale (fixed in current
|
|
616
|
-
release; report a bug if it recurs).
|
|
617
|
-
|
|
618
|
-
**PWA times out connecting.** Verify the same relay URL is configured
|
|
619
|
-
on both sides. If you self-host behind a VPN, the browser must also be on the
|
|
620
|
-
VPN.
|
|
621
|
-
|
|
622
|
-
**`agent_request` keeps timing out.** It is deprecated because it blocks the
|
|
623
|
-
turn while waiting for another agent's content reply. Migrate to `agent_send`;
|
|
624
|
-
a unicast waits only for the delivery ACK, and the receiver can reply later
|
|
625
|
-
with `agent_send` including `re: "<original-id>"` for correlation.
|
|
626
|
-
|
|
627
|
-
**Multiple terminals in the same directory.** Supported. They share the same
|
|
628
|
-
agent-network session (UDS broker) and the relay handles each Pi process
|
|
629
|
-
independently. If the relay refuses with `RoomAlreadyOpenError`, stop the
|
|
630
|
-
other terminal first.
|
|
631
|
-
|
|
632
|
-
---
|
|
633
|
-
|
|
634
|
-
## Branding
|
|
635
|
-
|
|
636
|
-
Official brand assets live in
|
|
637
|
-
[`/branding`](https://github.com/jacobaraujo7/remote_pi/tree/main/branding) —
|
|
638
|
-
SVG sources for the logo (full, foreground, background, monochrome) plus a
|
|
639
|
-
banner. See the
|
|
640
|
-
[branding README](https://github.com/jacobaraujo7/remote_pi/blob/main/branding/README.md)
|
|
641
|
-
for palette and export sizes.
|
|
642
|
-
|
|
643
|
-
<table>
|
|
644
|
-
<tr>
|
|
645
|
-
<td align="center">
|
|
646
|
-
<img src="https://raw.githubusercontent.com/jacobaraujo7/remote_pi/main/branding/logo-full.svg" width="96" alt="logo-full" /><br/>
|
|
647
|
-
<sub><code>logo-full</code></sub>
|
|
648
|
-
</td>
|
|
649
|
-
<td align="center">
|
|
650
|
-
<img src="https://raw.githubusercontent.com/jacobaraujo7/remote_pi/main/branding/logo-foreground.svg" width="96" alt="logo-foreground" /><br/>
|
|
651
|
-
<sub><code>logo-foreground</code></sub>
|
|
652
|
-
</td>
|
|
653
|
-
<td align="center">
|
|
654
|
-
<img src="https://raw.githubusercontent.com/jacobaraujo7/remote_pi/main/branding/logo-monochrome.svg" width="96" alt="logo-monochrome" /><br/>
|
|
655
|
-
<sub><code>logo-monochrome</code></sub>
|
|
656
|
-
</td>
|
|
657
|
-
</tr>
|
|
658
|
-
</table>
|
|
659
|
-
|
|
660
|
-
---
|
|
661
|
-
|
|
662
|
-
## Links
|
|
663
|
-
|
|
664
|
-
- Homepage: <https://remote-pi.jacobmoura.work>
|
|
665
|
-
- Source: <https://github.com/jacobaraujo7/remote_pi>
|
|
666
|
-
- Pi coding agent: <https://github.com/earendil-works/pi>
|
|
667
|
-
- Relay (self-hosting guide): <https://github.com/jacobaraujo7/remote_pi/blob/main/relay/README.md>
|
|
668
|
-
- Issues / bugs: <https://github.com/jacobaraujo7/remote_pi/issues>
|
|
669
|
-
|
|
670
|
-
---
|
|
165
|
+
Node 20+ and TypeScript ESM are required. Use `.js` extensions in TypeScript imports.
|
|
671
166
|
|
|
672
167
|
## License
|
|
673
168
|
|