@oar-sh/oar 0.9.10 โ 0.9.12
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/CHANGELOG.md +440 -1
- package/README.md +156 -972
- package/package.json +13 -13
- package/server/README.md +112 -25
- package/server/claude-worker/claude-remote-relay-tool.mjs +2 -0
- package/server/claude-worker/claude-sdk-adapter.mjs +57 -4
- package/server/claude-worker/claude-session-process.mjs +217 -11
- package/server/claude-worker/claude-session-worker.mjs +26 -1
- package/server/claude-worker/task-output-discovery.mjs +126 -0
- package/server/copilot-worker/copilot-sdk-session-process.mjs +235 -14
- package/server/copilot-worker/copilot-sdk-session-worker.mjs +8 -0
- package/server/copilot-worker/copilot-shell-output-mirror.mjs +94 -0
- package/server/copilot-worker/copilot-task-settle.mjs +96 -0
- package/server/db-schema.mjs +68 -2
- package/server/grok-worker/acp-client.mjs +2 -1
- package/server/grok-worker/acp-host-services.mjs +46 -6
- package/server/grok-worker/grok-background-tasks.mjs +241 -0
- package/server/grok-worker/grok-sdk-adapter.mjs +3 -1
- package/server/grok-worker/grok-session-worker.mjs +33 -1
- package/server/grok-worker/grok-turn-runner.mjs +11 -0
- package/server/migrations/0013-previews.mjs +130 -0
- package/server/migrations/0014-conversation-groups.mjs +89 -0
- package/server/migrations/0015-conversation-group-position.mjs +76 -0
- package/server/migrations/0016-share-access-log.mjs +110 -0
- package/server/migrations/0017-conversation-history-indexes.mjs +89 -0
- package/server/public/app/about-ui.js +73 -0
- package/server/public/app/about-view.mjs +234 -0
- package/server/public/app/action-confirmations.js +31 -14
- package/server/public/app/agent-exchange-fold-view.mjs +40 -101
- package/server/public/app/api-client.js +264 -16
- package/server/public/app/ask-user-view.js +17 -15
- package/server/public/app/background-tasks-view.mjs +285 -16
- package/server/public/app/bootstrap.js +253 -37
- package/server/public/app/chat-actions-menu-state.mjs +20 -10
- package/server/public/app/claude-background-command-limit-options.mjs +21 -0
- package/server/public/app/context-menu.mjs +90 -6
- package/server/public/app/conversation-group-drag.mjs +191 -0
- package/server/public/app/conversation-group-order.mjs +265 -0
- package/server/public/app/conversation-group-state.mjs +100 -0
- package/server/public/app/conversation-list-drag.mjs +449 -0
- package/server/public/app/conversation-payload-cache.mjs +357 -0
- package/server/public/app/conversation-turn-state.mjs +81 -0
- package/server/public/app/conversation-view.js +567 -94
- package/server/public/app/conversation-window-retention.mjs +96 -0
- package/server/public/app/cwd-picker.js +1 -1
- package/server/public/app/hidden-messages-view.mjs +312 -0
- package/server/public/app/host-suspend-ui.js +7 -1
- package/server/public/app/journal-view.js +1033 -82
- package/server/public/app/preview-cards.mjs +117 -31
- package/server/public/app/preview-command.mjs +10 -1
- package/server/public/app/relay-board-view.js +19 -6
- package/server/public/app/relay-prompt-sanitizer.mjs +11 -4
- package/server/public/app/relay-restart-error.mjs +16 -0
- package/server/public/app/settings-modal.js +150 -10
- package/server/public/app/settings-tabs.js +1 -1
- package/server/public/app/share-format.mjs +49 -0
- package/server/public/app/share-preview-marks.mjs +167 -0
- package/server/public/app/share-state.js +109 -0
- package/server/public/app/shared-conversations-settings.js +480 -0
- package/server/public/app/socket-handlers.js +138 -20
- package/server/public/app/store.js +121 -30
- package/server/public/app/subagent-row.mjs +3 -3
- package/server/public/app/subagent-viewer.mjs +37 -7
- package/server/public/app/task-console-render.mjs +237 -0
- package/server/public/app/task-console-watch.mjs +42 -0
- package/server/public/app/task-console.mjs +630 -0
- package/server/public/app/task-output-text.mjs +234 -0
- package/server/public/app/thinking-follow.js +0 -4
- package/server/public/app/transcript-island.mjs +73 -0
- package/server/public/app/transcript-jump-bottom-view.mjs +230 -26
- package/server/public/app/transcript-jump-bottom.mjs +170 -22
- package/server/public/app/transcript-reading-anchor.mjs +256 -0
- package/server/public/app/transcript-reload-freshness.mjs +17 -1
- package/server/public/app/transcript-viewport-anchor.mjs +159 -0
- package/server/public/index.html +625 -21
- package/server/relay-tools.md +3 -1
- package/server/relay.mjs +2 -1
- package/server/repositories/conversation-group-repository.mjs +444 -0
- package/server/repositories/message-repository.mjs +9 -0
- package/server/repositories/question-repository.mjs +4 -0
- package/server/repositories/session-repository.mjs +12 -37
- package/server/repositories/share-repository.mjs +322 -0
- package/server/repositories/share-visibility-statements.mjs +10 -0
- package/server/routes/about-routes.mjs +15 -0
- package/server/routes/cache-routes.mjs +4 -0
- package/server/routes/conversation-group-routes.mjs +171 -0
- package/server/routes/messages-routes.mjs +433 -68
- package/server/routes/preview-routes.mjs +9 -1
- package/server/routes/sessions-routes.mjs +901 -253
- package/server/server-runtime.mjs +392 -99
- package/server/services/about-service.mjs +461 -0
- package/server/services/background-task-store.mjs +365 -0
- package/server/services/background-work-view.mjs +228 -0
- package/server/services/cache-rebuild-service.mjs +30 -0
- package/server/services/cli-process-runner.mjs +4 -21
- package/server/services/conversation-history-page.mjs +199 -0
- package/server/services/delete-archive-service.mjs +4 -1
- package/server/services/detached-worker-watch-service.mjs +150 -0
- package/server/services/hidden-message-list.mjs +21 -0
- package/server/services/host-suspend-command.mjs +2 -1
- package/server/services/message-pin-list.mjs +1 -1
- package/server/services/preview-health-probe.mjs +8 -1
- package/server/services/preview-proxy-server.mjs +8 -4
- package/server/services/preview-registry-service.mjs +676 -26
- package/server/services/preview-static-handler.mjs +40 -7
- package/server/services/preview-store.mjs +274 -0
- package/server/services/rate-limit-service.mjs +12 -1
- package/server/services/relay-auth.mjs +183 -0
- package/server/services/relay-cli-launcher-service.mjs +3 -1
- package/server/services/relay-event-service.mjs +17 -0
- package/server/services/relay-prompt-sanitizer.mjs +11 -4
- package/server/services/remote-relay-dispatcher.mjs +187 -7
- package/server/services/request-boundary.mjs +183 -0
- package/server/services/session-activity-tracker.mjs +231 -19
- package/server/services/session-worker-launch-service.mjs +190 -6
- package/server/services/session-worker-process-service.mjs +10 -6
- package/server/services/share-access-log-service.mjs +123 -0
- package/server/services/share-path-redaction.mjs +424 -0
- package/server/services/status-event-service.mjs +7 -3
- package/server/services/task-output-rooms.mjs +259 -0
- package/server/services/task-output-service.mjs +562 -0
- package/server/services/tunnel-worker-path-guard.mjs +24 -41
- package/server/services/windows-autostart-service.mjs +6 -1
- package/server/services/windows-boot-autostart-service.mjs +207 -23
- package/shared/claude-background-command-limit.mjs +83 -0
- package/shared/preview-tool-core.mjs +15 -5
- package/shared/remote-relay-contract.mjs +35 -3
- package/shared/share-path-privacy.mjs +30 -0
- package/shared/task-output-text.mjs +737 -0
- package/shared/windows-system-tools.mjs +106 -0
- package/shared/worker-runtime/background-task-digest.mjs +30 -0
- package/shared/worker-runtime/heartbeat.mjs +24 -0
- package/shared/worker-runtime/kept-posts.mjs +83 -0
- package/shared/worker-runtime/task-output-spool.mjs +181 -0
- package/shared/worker-runtime/worker-websocket-link.mjs +47 -15
package/README.md
CHANGED
|
@@ -7,1044 +7,228 @@
|
|
|
7
7
|
|
|
8
8
|
# OAR โ Open Agent Relay
|
|
9
9
|
|
|
10
|
-
Drive the coding agents on your machine from any browser (phone, tablet, or a second computer) through a
|
|
10
|
+
Drive the coding agents on your machine from any browser (phone, tablet, or a second computer) through a web relay you host yourself.
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
13
|
curl -fsSL oar.sh/install | sh
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
On Windows, run `irm oar.sh/install.ps1 | iex` in PowerShell. Landing page: [oar.sh](https://oar.sh)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
16
|
+
On Windows, run `irm oar.sh/install.ps1 | iex` in PowerShell. Other ways to install are under [Install](#install). Landing page: [oar.sh](https://oar.sh); the complete guide: [oar.sh/docs](https://oar.sh/docs/).
|
|
17
|
+
|
|
18
|
+
## What OAR does
|
|
19
|
+
|
|
20
|
+
Coding agents such as GitHub Copilot, Claude Code, Cursor and Grok usually live in a terminal. OAR puts them into a chat you can open anywhere: start a task at your desk, follow it from the sofa, answer the agent's question from your phone. The agents keep running on your own computer, with your files and your logins; OAR passes the conversation back and forth.
|
|
21
|
+
|
|
22
|
+
```mermaid
|
|
23
|
+
flowchart LR
|
|
24
|
+
subgraph devices["Your devices"]
|
|
25
|
+
phone["๐ฑ Phone"]
|
|
26
|
+
browser["๐ป Browser"]
|
|
27
|
+
end
|
|
28
|
+
subgraph host["Your computer"]
|
|
29
|
+
relay["OAR relay<br/>chats, queue, history, files"]
|
|
30
|
+
agents["Copilot ยท OpenAI ยท Claude<br/>Cursor ยท Grok"]
|
|
31
|
+
end
|
|
32
|
+
cloud["โ๏ธ Claude Cloud<br/>sandbox at Anthropic"]
|
|
33
|
+
phone <--> relay
|
|
34
|
+
browser <--> relay
|
|
35
|
+
relay <--> agents
|
|
36
|
+
relay <--> cloud
|
|
28
37
|
```
|
|
29
38
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
- **Seven runtimes, one chat**: you pick the agent per conversation, and all of them share the same chat, queue, history, file browser, and question cards ([Runtimes](#runtimes)).
|
|
40
|
+
- **Yours**: the relay runs on your hardware, answers only on this machine until you change that, and collects no telemetry ([Security notes](#security-notes)).
|
|
41
|
+
- **Under active development**: expect occasional rough edges, and some provider SDK features that are missing or incomplete.
|
|
33
42
|
|
|
34
43
|
## In action
|
|
35
44
|
|
|
36
45
|
<table>
|
|
37
46
|
<tr>
|
|
38
47
|
<td width="42%" rowspan="4" valign="top">
|
|
39
|
-
<a href="https://oar.sh/assets/shots/cfmail-mobile.png?v=0.9.
|
|
48
|
+
<a href="https://oar.sh/assets/shots/cfmail-mobile.png?v=0.9.12"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/cfmail-mobile.light.png?v=0.9.12"><img src="https://oar.sh/assets/shots/cfmail-mobile.png?v=0.9.12" alt="OAR on a phone: a finished agent turn in a conversation, with the composer below"></picture></a>
|
|
40
49
|
<br><sub>On a phone: the same conversations, installable as an app.</sub>
|
|
41
50
|
</td>
|
|
42
51
|
<td width="58%" valign="top">
|
|
43
|
-
<a href="https://oar.sh/assets/shots/cfmail-agents.png?v=0.9.
|
|
52
|
+
<a href="https://oar.sh/assets/shots/cfmail-agents.png?v=0.9.12"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/cfmail-agents.light.png?v=0.9.12"><img src="https://oar.sh/assets/shots/cfmail-agents.png?v=0.9.12" alt="Background subagents running in parallel in the task panel, each with live token counts, elapsed time, and its own Stop button"></picture></a>
|
|
44
53
|
<br><sub>Agents working in parallel, each with live token counts and its own Stop.</sub>
|
|
45
54
|
</td>
|
|
46
55
|
</tr>
|
|
47
56
|
<tr>
|
|
48
57
|
<td valign="top">
|
|
49
|
-
<a href="https://oar.sh/assets/shots/cfmail-question.png?v=0.9.
|
|
58
|
+
<a href="https://oar.sh/assets/shots/cfmail-question.png?v=0.9.12"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/cfmail-question.light.png?v=0.9.12"><img src="https://oar.sh/assets/shots/cfmail-question.png?v=0.9.12" alt="A question card in the middle of a turn: the agent offers several choices and a free-text reply"></picture></a>
|
|
50
59
|
<br><sub>When the agent needs a decision, it asks, and waits for your answer.</sub>
|
|
51
60
|
</td>
|
|
52
61
|
</tr>
|
|
53
62
|
<tr>
|
|
54
63
|
<td valign="top">
|
|
55
|
-
<a href="https://oar.sh/assets/shots/pingcf-thoughts.png?v=0.9.
|
|
64
|
+
<a href="https://oar.sh/assets/shots/pingcf-thoughts.png?v=0.9.12"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/pingcf-thoughts.light.png?v=0.9.12"><img src="https://oar.sh/assets/shots/pingcf-thoughts.png?v=0.9.12" alt="An expanded Thoughts block showing the agent's reasoning above its reply"></picture></a>
|
|
56
65
|
<br><sub>Read the reasoning, not just the answer.</sub>
|
|
57
66
|
</td>
|
|
58
67
|
</tr>
|
|
59
68
|
<tr>
|
|
60
69
|
<td valign="top">
|
|
61
|
-
<a href="https://oar.sh/assets/shots/pagewright-watching.png?v=0.9.
|
|
70
|
+
<a href="https://oar.sh/assets/shots/pagewright-watching.png?v=0.9.12"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/pagewright-watching.light.png?v=0.9.12"><img src="https://oar.sh/assets/shots/pagewright-watching.png?v=0.9.12" alt="A session watching two other sessions: a finished reply arrives as a compact relay-event row, the watching 2 sessions list is open with Unsubscribe, and a request to also watch a session on a paired relay waits on an Allow / Deny card"></picture></a>
|
|
62
71
|
<br><sub>Agents that watch agents: woken by events, approving nothing.</sub>
|
|
63
72
|
</td>
|
|
64
73
|
</tr>
|
|
65
74
|
</table>
|
|
66
75
|
|
|
67
76
|
<a id="quick-start"></a>
|
|
77
|
+
<a id="prerequisites"></a>
|
|
78
|
+
<a id="start-the-relay"></a>
|
|
79
|
+
<a id="the-oar-command"></a>
|
|
68
80
|
|
|
69
81
|
## Install
|
|
70
82
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
| Requirement | Needed for | Notes |
|
|
76
|
-
| ----------- | ---------- | ----- |
|
|
77
|
-
| Node.js 22.13 or newer | always | The macOS and Linux installer fetches its own copy when yours is missing or too old; the Windows installer only checks. Running the development test suite needs Node 24 (see [DEVELOPING.md](DEVELOPING.md#node-version)) |
|
|
78
|
-
| GitHub Copilot CLI (`copilot`), signed in | Copilot and OpenAI (BYOK) chats | Install it with `npm install -g @github/copilot`, then run `copilot` once on the relay host and sign in. The relay looks for the CLI's runtime when it starts, so restart the relay after installing or upgrading the CLI. Needs a GitHub Copilot plan that includes Copilot CLI |
|
|
79
|
-
| GitHub CLI (`gh`), signed in | `oar copilot`; Extension-engine sessions on Windows; the Copilot card in **Check Usage** | `gh copilot` is built into current GitHub CLI releases, so there is no extension to install. The usage card also accepts a token in `GH_TOKEN` or `GITHUB_TOKEN` |
|
|
80
|
-
| OpenAI API key | OpenAI and OpenAI Image chats | Entered in **โ๏ธ Settings**, stored in the relay database |
|
|
81
|
-
| A Claude login on the relay host | Claude chats | Log in from **โ๏ธ Settings โ Providers โ Claude โ Relogin** (the panel can install the Claude Code CLI first), or run `claude` once on the host. The relay stores no Claude key |
|
|
82
|
-
| The same Claude login, from a claude.ai account with GitHub connected | Claude Cloud chats | The Claude GitHub app must be allowed on each repository a cloud chat works on (see [Claude Cloud](#claude-cloud)) |
|
|
83
|
-
| Cursor API key | Cursor chats | Entered in **โ๏ธ Settings**, stored in the relay database |
|
|
84
|
-
| Grok CLI, signed in | Grok chats | Install it and sign in from **โ๏ธ Settings โ Providers โ Grok**, or set `XAI_API_KEY` in the relay's environment |
|
|
85
|
-
| `cloudflared` (optional) | the built-in Cloudflare tunnel | Not included; install it yourself (see [Cloudflare Tunnel](#optional-remote-internet-access-cloudflare-tunnel)) |
|
|
86
|
-
| tmux (optional) | Linux and macOS | Session workers run in detached tmux sessions you can watch from the browser (**๐ฅ๏ธ Inspect tmux console**). Without tmux they run as plain background processes |
|
|
87
|
-
|
|
88
|
-
### macOS and Linux
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
curl -fsSL oar.sh/install | sh
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
The script looks at what the machine has, prints what it is about to do, and asks once. After a yes it installs OAR, writes the config with a fresh auth token, starts the relay, and prints the relay URL with a QR code. Nothing needs root (it refuses to run as root, because OAR installs per user), and everything lands in your home directory:
|
|
95
|
-
|
|
96
|
-
| The machine has | What the installer does |
|
|
97
|
-
| --------------- | ----------------------- |
|
|
98
|
-
| Node.js 22.13 or newer whose global npm folder you can write (nvm, fnm, Homebrew, a user prefix) | `npm install -g @oar-sh/oar`, as you would by hand |
|
|
99
|
-
| Node.js 22.13 or newer whose global npm folder needs root (a distribution or NodeSource package) | Installs the package into `~/.oar/npm` with your Node.js and puts an `oar` command into `~/.local/bin`. Your npm setup is not changed |
|
|
100
|
-
| No Node.js, or an older one | Downloads the current Node.js 24 from nodejs.org into `~/.oar/runtime/node` (checksum verified, about 30 MB), installs the package into `~/.oar/npm` with it, and puts an `oar` command into `~/.local/bin`. Only OAR uses that Node.js; one of your own stays first on `PATH` |
|
|
101
|
-
|
|
102
|
-
When it puts the command into `~/.local/bin` and that folder is not on your `PATH`, it adds one line to your shell's startup file (`~/.bashrc`, `~/.zshrc`, or `~/.profile`) and says so.
|
|
103
|
-
|
|
104
|
-
The relay is started as a systemd user service where a systemd user session exists, with lingering enabled, so it is back after a reboot and keeps running while you are logged out. Elsewhere (macOS, containers, WSL without systemd) it is started in the background; after a reboot, `oar start` starts it again.
|
|
105
|
-
|
|
106
|
-
`--yes` skips the question, for scripts and CI; without a terminal to ask on, the installer stops and says so. `OAR_VERSION=x.y.z` pins a version, `OAR_CHANNEL=beta` follows the beta channel, `OAR_PORT=n` sets the relay port, `OAR_NODE=private` uses OAR's own Node.js even when yours would do, and `OAR_DRY_RUN=1` only prints the plan:
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
curl -fsSL oar.sh/install | sh -s -- --yes
|
|
110
|
-
curl -fsSL oar.sh/install | OAR_VERSION=0.9.10 OAR_PORT=3400 sh
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
The installer needs `curl` or `wget`, and `tar` when it fetches Node.js. It has no Node.js build for musl systems (Alpine) or for CPUs other than x64 and arm64; there, install Node.js yourself first. Releases before 0.9.8 are installed the same way, but their `oar setup` cannot start the relay: see [Start the relay](#start-the-relay).
|
|
114
|
-
|
|
115
|
-
Read it before you run it: [oar.sh/install](https://oar.sh/install).
|
|
116
|
-
|
|
117
|
-
### Windows
|
|
118
|
-
|
|
119
|
-
```powershell
|
|
120
|
-
irm oar.sh/install.ps1 | iex
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
The PowerShell installer (PowerShell 5 or newer) expects Node.js 22.13 or newer to be installed: it checks Node.js, runs `npm install -g @oar-sh/oar`, then `oar setup`. It reads the same `OAR_VERSION`, `OAR_CHANNEL`, and `OAR_DRY_RUN` variables, for example `$env:OAR_VERSION = '0.9.10'` before the command.
|
|
124
|
-
|
|
125
|
-
### npm
|
|
126
|
-
|
|
127
|
-
```bash
|
|
128
|
-
npm install -g --allow-scripts=better-sqlite3,koffi @oar-sh/oar
|
|
129
|
-
oar setup
|
|
130
|
-
```
|
|
83
|
+
1. **Install.** Run `curl -fsSL oar.sh/install | sh` (macOS, Linux) or `irm oar.sh/install.ps1 | iex` (Windows PowerShell). On macOS and Linux the installer says what it is about to do and asks once, then installs OAR into your home directory, writes a config with a fresh access token, starts the relay, and prints its address with a QR code. On Windows, run `oar start` afterwards.
|
|
84
|
+
2. **Open the address** it printed; `oar url` prints it again. On the relay's own machine that is `http://localhost:3333/`. For your phone, switch on LAN access with `oar setup --lan`, or use a [tunnel](#remote-access).
|
|
85
|
+
3. **Turn on an agent** under **โ๏ธ Settings โ Providers**, then start a conversation with **+ New Chat**.
|
|
131
86
|
|
|
132
|
-
|
|
87
|
+
You need Node.js 22.13 or newer (the macOS and Linux installer brings its own when yours is missing or older) and an account with the agent you want to use; see [Prerequisites](docs/install.md#prerequisites). There are also installs [with npm](docs/install.md#npm) and [from a git checkout](docs/install.md#from-a-git-checkout).
|
|
133
88
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
```bash
|
|
137
|
-
git clone https://github.com/oar-sh/oar
|
|
138
|
-
cd oar
|
|
139
|
-
npm install
|
|
140
|
-
node bin/oar.js setup # writes server/config.json with a fresh auth token
|
|
141
|
-
npm start # the same as: node server/server.js
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
A checkout keeps all of its state inside the repository (`server/config.json`, `server/data/`, `server/uploads/`, `server/logs/`) and never updates itself. `node server/server.js --port <port> --token <token>` overrides the config for one run without saving it.
|
|
145
|
-
|
|
146
|
-
You can also write `server/config.json` by hand; every key you leave out takes its default (see the [configuration reference](#configuration-reference-serverconfigjson)):
|
|
147
|
-
|
|
148
|
-
```json
|
|
149
|
-
{
|
|
150
|
-
"authToken": "change-me-to-a-long-random-secret",
|
|
151
|
-
"port": 3333,
|
|
152
|
-
"localhostOnly": true
|
|
153
|
-
}
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
Development workflows, tests, and relay internals are in [DEVELOPING.md](DEVELOPING.md).
|
|
157
|
-
|
|
158
|
-
### Start the relay
|
|
159
|
-
|
|
160
|
-
The macOS and Linux installer starts the relay itself. After a manual install, `oar setup` creates the config and prints the relay URL, but it does not start the relay unless you pass `--start`. `oar` alone, in a terminal, opens a menu with everything below.
|
|
161
|
-
|
|
162
|
-
- **Any global install:** `oar start` starts the relay in the background (through the systemd user service when one is installed) and prints the relay URL. `oar stop` stops it, `oar restart` restarts it, `oar status` says whether it runs; stop and restart wait for running turns.
|
|
163
|
-
- **At every login:** `oar service install`. On Linux that writes and enables a systemd user service and enables lingering, so the relay is back after a reboot and keeps running while you are logged out; the unit carries the `PATH` of the shell that ran the command, plus `~/.local/bin`, so the relay's sessions find the tools you have (run it again after your `PATH` changed). On Windows it switches on the same autostart as **โ๏ธ Settings โ General โ Autostart (Windows)** โ *At sign-in*; *At system startup*, which runs the relay headless before anyone signs in, is set in the web UI because it needs one admin confirmation. `oar service remove` takes it out again. Not available on macOS yet, nor on a Linux without a systemd user session (containers, WSL without systemd): use `oar start` there.
|
|
164
|
-
- **With a Copilot terminal session:** `oar copilot` starts the relay in the background if it is not already running, then opens the Copilot CLI (`gh copilot`) in the same shell. A relay that `oar copilot` started stops again when that session ends. It needs the GitHub CLI.
|
|
165
|
-
|
|
166
|
-
To run the relay of a global install in the foreground, start the server the way the systemd unit does:
|
|
167
|
-
|
|
168
|
-
```bash
|
|
169
|
-
COPILOT_WEB_RELAY_CONFIG="$HOME/.oar/config.json" \
|
|
170
|
-
COPILOT_WEB_RELAY_DATA_DIR="$HOME/.oar/data" \
|
|
171
|
-
COPILOT_WEB_RELAY_LOG_DIR="$HOME/.oar/logs" \
|
|
172
|
-
node "$(npm root -g)/@oar-sh/oar/server/server.js"
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
On Windows, point the same three variables at `%APPDATA%\oar\config.json`, `%APPDATA%\oar\data`, and `%APPDATA%\oar\logs`. The directory you start it from becomes the default working directory for new sessions.
|
|
176
|
-
|
|
177
|
-
Then open the URL that `oar setup` printed (`oar url` prints it again). With access set to this machine only (the default, `localhostOnly` in the config) that is `http://localhost:3333/` on the relay host; reach it from other devices through a [tunnel](#remote-access), or switch on LAN access with `oar setup --lan`, which also prints a QR code for your phone. The URL carries your token once (`?token=โฆ`); after that, the relay keeps the browser signed in with an HttpOnly cookie.
|
|
178
|
-
|
|
179
|
-
### The `oar` command
|
|
180
|
-
|
|
181
|
-
| Command | What it does |
|
|
182
|
-
| ------- | ------------ |
|
|
183
|
-
| `oar` | In a terminal: a menu with the relay's status (running or stopped, version, URL, port, access, service) and an entry for each command below; arrow keys or digits, Enter, `q`. Without a terminal: the status and the usage |
|
|
184
|
-
| `oar start` | Starts the relay in the background, through the systemd user service when one is installed, and prints the relay URL. A relay that is already running is left alone. Global installs only; a git checkout uses `npm start` |
|
|
185
|
-
| `oar stop` | Stops the relay: the systemd service through `systemctl --user stop oar`, any other relay through its own API, once no turn is running |
|
|
186
|
-
| `oar restart` | Restarts a running relay once no turn is running (the service through systemd, at once), or starts a stopped one |
|
|
187
|
-
| `oar status` | Says whether the relay runs, on which port and with which access, and whether the service is installed. Exit code 0 when it runs, 3 when it does not |
|
|
188
|
-
| `oar url` | Prints the relay URL. With LAN access it also prints a QR code; with access for this machine only it says how to get phone access instead. When the running relay reports a tunnel address, that address and its QR code follow |
|
|
189
|
-
| `oar setup` | Creates or updates the config. In a terminal it asks, showing the current value (Enter keeps it): a new auth token (which signs every device out), access (this machine only, or LAN), and the port. Options answer without a question: `--port <port>`, `--lan` or `--local`, `--new-token`; `--defaults` keeps everything of an existing config and gives a new one access for this machine only and the first free port from 3333 on. A port must be free, unless the install's own running relay holds it. When the token, the port or the access changed while the relay runs, setup restarts it (in a terminal it asks first) and waits until it answers with the new settings. `--start` (global installs, used by the installer) also installs the service where a systemd user session exists and starts the relay. `--migrate-from <dir>` copies the relay state of a pre-rename git checkout at `<dir>` into the OAR state root, once; the source is never changed, and a relay still running from it blocks the copy |
|
|
190
|
-
| `oar service install` \| `remove` \| `status` | Starts the relay at every login: a systemd user service on Linux, the sign-in autostart on Windows. See [Start the relay](#start-the-relay) |
|
|
191
|
-
| `oar copilot [-- <args>]` | Starts the relay in the background unless one already answers on its port, then runs `gh copilot` in the same shell, passing `<args>` through (`gh copilot -- <args>`). `--port <port>` finds or starts the relay on that port for this run without changing the config; a config this command creates saves it. `--install-extension` writes or refreshes the user-global Copilot CLI extension wrapper in `~/.copilot/extensions/web-relay/`, then exits; every run does that unless `--no-install-extension` is given. The same options without the word `copilot` (`oar -- <args>`, `oar --install-extension`) still run this command |
|
|
192
|
-
| `oar doctor` | Prints the version, Node.js, install mode, state root, config path, port, whether an auth token is set, the tunnel mode and whether the `cloudflared` it needs is installed, the database path and size, and which provider CLIs (`gh`, `claude`, `grok`) answer. It changes nothing |
|
|
193
|
-
| `oar update [--beta] [--to X.Y.Z]` | Global installs: looks up the newest release of your channel in `https://oar.sh/latest.json` (`--beta` for the beta channel), installs it with `npm install -g` (the npm of the Node.js that runs `oar`, into the folder the package is installed in), and asks a running relay to restart once no turn is running. `--to X.Y.Z` installs that version straight from npm, which works even when `OAR_NO_UPDATE_CHECK=1` blocks the lookup |
|
|
194
|
-
| `oar --version`, `oar help` | Prints the version, or the usage. An unknown command or option prints the usage and exits with code 2 |
|
|
195
|
-
|
|
196
|
-
### Where OAR keeps its files
|
|
197
|
-
|
|
198
|
-
A global install keeps its state in `~/.oar` (`%APPDATA%\oar` on Windows; `OAR_STATE_ROOT` moves it): `config.json`, `data/` (the database and uploads), and `logs/` (`server.log` when `oar` started the relay, and a `worker-<session>.log` per Node session worker). `npm install -g` updates never touch it. The macOS and Linux installer may add two folders there that are not state: `npm/` (the package, when npm's own global folder was not writable) and `runtime/node/` (OAR's own Node.js, when the machine had none new enough). A git checkout uses `server/config.json`, `server/data/`, `server/uploads/`, and `server/logs/` instead.
|
|
199
|
-
|
|
200
|
-
`COPILOT_WEB_RELAY_CONFIG`, `COPILOT_WEB_RELAY_DATA_DIR`, and `COPILOT_WEB_RELAY_LOG_DIR` override the config file, the data directory, and the log directory. `oar doctor` prints the paths in use.
|
|
201
|
-
|
|
202
|
-
### Updating
|
|
203
|
-
|
|
204
|
-
- **Global install:** **โ๏ธ Settings โ General โ Check for updates** shows a newer release with an **Update** button, which installs it with npm and restarts the relay once no turn is running. `oar update` does the same from a terminal. Automatic checks are opt-in: **Check for updates automatically** asks oar.sh about twice a day. `OAR_NO_UPDATE_CHECK=1` in the relay's environment blocks every check, manual ones included.
|
|
205
|
-
- **Git checkout:** `git pull`, `npm install`, then restart the relay (**๐ Restart web relay** in the conversation's `โฏ` menu).
|
|
89
|
+
`oar` alone opens a menu. `oar start`, `stop`, `restart` and `status` control the relay, `oar service install` starts it at every login, `oar doctor` shows what it uses, and `oar update` installs a new release (as does **โ๏ธ Settings โ General โ Check for updates**). All the details are in [Installing and running OAR](docs/install.md): [the `oar` command](docs/install.md#the-oar-command), [where OAR keeps its files](docs/install.md#where-oar-keeps-its-files), and [updating](docs/install.md#updating).
|
|
206
90
|
|
|
207
91
|
<a id="providers"></a>
|
|
92
|
+
<a id="claude-cloud"></a>
|
|
93
|
+
<a id="claude-agent-sdk"></a>
|
|
208
94
|
|
|
209
95
|
## Runtimes
|
|
210
96
|
|
|
211
|
-
The runtime (
|
|
212
|
-
|
|
213
|
-
Turning a provider **off** (or removing the OpenAI key) rebinds conversations that have not sent a message yet back to Copilot, so you are never left with a conversation pointing at a runtime that can no longer start. Conversations already in flight, and conversations belonging to a different provider, are left alone. Claude Cloud is the exception: switching it off only takes it out of **New Chat**, and its conversations stay as they are.
|
|
214
|
-
|
|
215
|
-
| Runtime | Enable via | Auth | Notes |
|
|
216
|
-
| ------- | ---------- | ---- | ----- |
|
|
217
|
-
| **Copilot** (default) | always available | the relay host's Copilot CLI login | Two engines: the headless **SDK** worker (default) or the Copilot CLI with OAR's **Extension**. The only runtime that reports Copilot usage |
|
|
218
|
-
| **OpenAI (BYOK)** | โ๏ธ Settings โ Providers โ OpenAI | your API key, stored in the relay database | Runs the Copilot runtime, on either engine, against an OpenAI-compatible endpoint |
|
|
219
|
-
| **OpenAI Image (BYOK)** | โ๏ธ Settings โ Providers โ OpenAI | the same key | The relay calls the OpenAI Images API itself; a chat whose replies are images |
|
|
220
|
-
| **Claude (Agent SDK)** | โ๏ธ Settings โ Providers โ Claude | the relay host's Claude login, **switchable from the panel** | A dedicated Node worker per conversation. The Claude Code CLI can be installed and updated from the panel |
|
|
221
|
-
| **Claude Cloud** | โ๏ธ Settings โ Providers โ Claude Cloud (off by default) | the relay host's Claude login (a claude.ai account), read from the Claude CLI | Claude Code in a sandbox at Anthropic, on a clone of a GitHub repository. Results come back as pushed branches; billed to that Claude account. Uses API endpoints that are not a documented public API (see [Claude Cloud](#claude-cloud)) |
|
|
222
|
-
| **Cursor (Agent SDK)** | โ๏ธ Settings โ Providers โ Cursor | your Cursor API key, stored in the relay database | A dedicated Node worker per conversation through the Cursor Agent SDK |
|
|
223
|
-
| **Grok (CLI ACP)** | โ๏ธ Settings โ Providers โ Grok | the relay host's Grok CLI login, **sign in and out from the panel** | Drives the Grok CLI's `grok agent stdio` over ACP. The CLI can be installed and updated from the panel |
|
|
224
|
-
|
|
225
|
-
### GitHub Copilot โ engine choice
|
|
226
|
-
|
|
227
|
-
Copilot conversations, and OpenAI (BYOK) ones, run on one of two engines, chosen in **โ๏ธ Settings โ Providers โ Copilot โ Copilot engine**. The setting is per relay and is read whenever a conversation's worker starts; sessions already running keep their engine until their worker restarts.
|
|
228
|
-
|
|
229
|
-
| Engine | What runs | Notes |
|
|
230
|
-
| ------ | --------- | ----- |
|
|
231
|
-
| **SDK** (default) | A headless Node worker per conversation, driving the Copilot CLI's bundled SDK runtime | Needs only a Copilot CLI that is installed and signed in; there is no extension to install or keep in sync. This engine has [mid-turn steering](#while-a-turn-runs), the [background task panel](#background-tasks) with a working **Stop**, **Cancel** on a steered message the runtime has not picked up yet, and multi-select question cards, for every Copilot model, hosted or BYOK. There is no TUI: the tmux console shows the worker's log |
|
|
232
|
-
| **Extension** | The Copilot CLI in a terminal session with OAR's web-relay extension loaded | The engine OAR started with. **๐ฅ๏ธ Inspect tmux console** shows the live Copilot TUI (Linux and macOS, with tmux). Messages sent during a turn queue behind it |
|
|
233
|
-
|
|
234
|
-
The SDK engine has been the default since 0.9.2. A relay where nobody has saved a choice uses it whenever it can and falls back to **Extension** when it cannot; a saved choice always wins. Saving **SDK** is refused, with the reason shown in place of the engine description, when:
|
|
235
|
-
|
|
236
|
-
- *"The Copilot SDK was not found when the relay started (COPILOT_SDK_PATH did not resolve)โฆ"*: the relay found no Copilot CLI runtime at startup. It looks in the Copilot CLI's package cache, newest version first (`~/.cache/copilot/pkg` on Linux, `~/Library/Application Support/copilot/pkg` on macOS, `%LOCALAPPDATA%\copilot\pkg` on Windows; `COPILOT_PKG_DIR` adds a location), unless `COPILOT_SDK_PATH` names the runtime's `copilot-sdk` directory directly. Install or upgrade the Copilot CLI, run it once, **and restart the relay**: the launch environment is snapshotted at startup, so a CLI installed since then is not visible yet.
|
|
237
|
-
- *"The SDK engine requires session worker routing, which is disabled on this relay (SESSION_WORKER_ROUTING_ENABLED)โฆ"*: with routing off no SDK worker is ever spawned. Turn **Session worker routing** back on in **โ๏ธ Settings โ Features** (it is on by default) and restart the relay.
|
|
238
|
-
|
|
239
|
-
A refusal never changes the stored engine; the select snaps back to the engine the relay actually runs.
|
|
240
|
-
|
|
241
|
-
SDK-engine turns report their own per-turn billing to the relay, which appears as the **Last SDK worker turn** section on the Copilot card in **Check Usage**. The card's meters come from the account-level quota API and are correct for both engines.
|
|
242
|
-
|
|
243
|
-
### OpenAI (BYOK) and OpenAI Image
|
|
244
|
-
|
|
245
|
-
Save your key in **โ๏ธ Settings โ Providers โ OpenAI**, together with the **OpenAI model ID** (default `gpt-4o`) and an optional **Base URL** (default `https://api.openai.com/v1`). **Enable OpenAI API key for New Chat model selection** is on once a key is saved, and saving discovers the endpoint's models from `/v1/models`.
|
|
246
|
-
|
|
247
|
-
- **OpenAI (BYOK)** conversations run the Copilot runtime against that endpoint with your key, on whichever Copilot engine is selected.
|
|
248
|
-
- **OpenAI Image (BYOK)** conversations are chats whose replies are images. **New Chat** asks for **Quality** and **Size** instead of reasoning effort, and **Edit this image** under a generated image iterates on it.
|
|
249
|
-
|
|
250
|
-
### Claude (Agent SDK)
|
|
251
|
-
|
|
252
|
-
Turn on **โ๏ธ Settings โ Providers โ Claude โ Enable Claude for New Chat model selection**. The relay authenticates through the Claude credentials on the host machine (`~/.claude`), so there is no key to enter.
|
|
253
|
-
|
|
254
|
-
**Commit attribution.** Commits an agent makes in a Claude session end with `Co-authored-by: Open Agent Relay (<model>) <no-reply@oar.sh>` โ the model's name in the parentheses, e.g. `Claude Fable 5.1` โ and pull request bodies with `๐ค Generated with [Open Agent Relay](https://oar.sh)`. The same tab has the choice: **OAR** (default), **vanilla** (Claude Code's own `Co-Authored-By: Claude โฆ` lines) or **off** (no attribution). A repo folder can override it for all of its Claude sessions from the **๐ง ** context modal. A change reaches a running session with its next message (a switch back to vanilla restarts the session's CLI between turns). [Claude Cloud](#claude-cloud) chats follow the same setting. Other providers are not affected: their tools have no such setting.
|
|
255
|
-
|
|
256
|
-
The same panel manages the account itself. The row at the top names the signed-in account and plan, and:
|
|
257
|
-
|
|
258
|
-
- **Relogin** runs the Claude CLI's login on the relay host and brings the flow to the browser: the authorize link appears inline with a **Copy link** button โ open it on any device, authorize on claude.ai, then paste the returned code back into the field. The relay holds no Claude secret; the CLI rewrites the host credentials, and a fresh model discovery runs straight after, so switching accounts needs no relay restart. The flow is pushed over the socket, so you can start it on one device and finish it on another, and closing the modal does not lose it.
|
|
259
|
-
- **Logout** asks for confirmation first and tells you how many Claude workers are running. Running Claude sessions keep the previous account's token until their worker exits; new sessions use the new account.
|
|
260
|
-
|
|
261
|
-
If Claude has never been logged in on the host, running `claude` there once works too.
|
|
262
|
-
|
|
263
|
-
Enabling Claude also runs model discovery against the Agent SDK and adds the discovered `claude-*` model IDs to the pickers (default model `claude-sonnet-5`). Use **๐ค Select Models โ Claude SDK** to choose which of them appear in the composer; the configured default model always stays enabled. Discovery runs the Claude Code build bundled with the Agent SDK, so `claude update` alone never surfaces a new Claude model: that arrives with an OAR update.
|
|
264
|
-
|
|
265
|
-
What Claude conversations support:
|
|
266
|
-
|
|
267
|
-
- Per-message model and reasoning effort (`none`, `low`, `medium`, `high`, `xhigh`, `max`), changeable between turns, plus **Ultracode** on models that support `xhigh` โ `xhigh` effort *and* multi-agent workflow orchestration, at a matching jump in token use
|
|
268
|
-
- All four relay modes โ `plan` maps to the SDK's plan permission mode and produces a **Plan ready** board, `ask` and `autopilot` adjust the system prompt
|
|
269
|
-
- Image and file attachments (images up to 5 MB are inlined; larger files are passed as paths for Claude to read)
|
|
270
|
-
- Question cards (including multi-select), thinking/thought streams, live reply streaming, and nested subagent bubbles
|
|
271
|
-
- **Mid-turn steering** with **Steer** / **Queue**, **Stop** on the reply bubble, and **Resend** for steered messages a Stop cut off (see [While a turn runs](#while-a-turn-runs))
|
|
272
|
-
- Background tasks that outlive the reply that started them, in the composer's task panel, including **Ultracode** workflow trees (see [Background tasks](#background-tasks))
|
|
273
|
-
- Session continuity across worker restarts โ the native Agent SDK session id is stored and resumed
|
|
274
|
-
- Real context-window metrics, reported after each turn, and a per-conversation auto-compact window (see [Usage and context](#usage-and-context))
|
|
275
|
-
|
|
276
|
-
Differences from Copilot conversations:
|
|
277
|
-
|
|
278
|
-
- Cancelling one individual subagent works only for backgrounded ones; a subagent running inside the current turn can be stopped only by stopping the whole turn
|
|
279
|
-
- Claude turns are not included in the Copilot usage line, and no usage line is attached to their replies (Claude's own plan limits appear in **Check Usage**)
|
|
280
|
-
- The browsable **Session** root points at the Agent SDK's project directory rather than a Copilot session-state folder
|
|
281
|
-
|
|
282
|
-
### Claude Cloud
|
|
283
|
-
|
|
284
|
-
**Experimental**, and off by default.
|
|
285
|
-
|
|
286
|
-
A Claude Cloud chat runs Claude Code in a sandbox at Anthropic instead of on the relay host. The sandbox works on its own clone of a GitHub repository: it sees what is pushed to GitHub and nothing on the host, and its results come back as branches the agent pushes. The chat is billed to the Claude account the relay host's Claude CLI is logged in to. In OAR it is a conversation like the others: the reply streams in, questions arrive as cards, and it works from the phone.
|
|
287
|
-
|
|
288
|
-
**What it needs.**
|
|
289
|
-
|
|
290
|
-
- The Claude CLI on the relay host, logged in with a claude.ai account (**โ๏ธ Settings โ Providers โ Claude โ Relogin**, or `claude` on the host). The same login serves Claude chats.
|
|
291
|
-
- GitHub connected to that Claude account: [claude.ai/connect-github](https://claude.ai/connect-github).
|
|
292
|
-
- The Claude GitHub app allowed on every repository a cloud chat should work on (GitHub โ Settings โ Applications โ Claude โ Configure).
|
|
293
|
-
|
|
294
|
-
**Enabling.** Turn on **โ๏ธ Settings โ Providers โ Claude Cloud โ Enable Claude Cloud for New Chat**. It is off by default, and it is refused while the host has no Claude login. The tab then shows:
|
|
295
|
-
|
|
296
|
-
- the account the chats are billed to, and where the relay reads the login from and until when it is valid. The login itself is changed on the Claude tab (**Claude login** jumps there);
|
|
297
|
-
- **Cloud environment**: the environments of the account. With none saved, the relay takes the first active one and saves it. An account without any gets its default one when you open [claude.ai/code](https://claude.ai/code) once;
|
|
298
|
-
- **Default model** for new cloud chats (`claude-sonnet-5-5` until you change it). The list is the Claude provider's models without their `[1m]` variants, plus the default.
|
|
299
|
-
|
|
300
|
-
Switching Claude Cloud off takes it out of **New Chat**. Cloud conversations that already exist keep working.
|
|
301
|
-
|
|
302
|
-
**Starting a chat.** Choose **+ New Chat โ Provider โ Claude Cloud**. The folder picker stays, but here it only fills in two fields, which you can also pick from a list or type yourself:
|
|
303
|
-
|
|
304
|
-
- **Repository**: read from the folder's `origin` remote (or the remote of its upstream branch). With the field focused, OAR lists the repositories the Claude GitHub app can reach for the account (read from Anthropic, kept for a minute; **โป** next to the label reads it again), the ones used in earlier cloud chats on this relay first and marked "used here"; typing filters the list by `owner/name`, arrow keys and Enter pick, Escape closes. `owner/repo` or a GitHub URL, https or ssh, can still be typed or pasted; only GitHub repositories are accepted.
|
|
305
|
-
- **Branch**: the folder's current branch; a repository picked from the list brings its default branch. With the field focused, OAR offers the repository's branches as the relay host's git sees them (`git ls-remote`, with the host's own GitHub login; the host's `OAR_CLAUDE_CLOUD_BRANCH_LOOKUP=off` turns this off). When the host cannot read them the field is a plain text field. Leave it empty for the repository's default branch.
|
|
306
|
-
|
|
307
|
-
Under the fields OAR warns about what the cloud clone will not have: commits that are not pushed, a branch without an upstream, uncommitted changes. It also says when the folder is no git repository or has no GitHub remote, when the Claude GitHub app has no access to the repository in the field (the cloud would refuse the first message), and when no cloud environment is set. There is no reasoning effort to choose. The cloud session itself is created by the first message.
|
|
308
|
-
|
|
309
|
-
**What works.**
|
|
310
|
-
|
|
311
|
-
- The reply streams in as the agent writes it, with thoughts, tool activity, subagent bubbles and the steps of the sandbox starting up
|
|
312
|
-
- Questions from the agent (`AskUserQuestion`) as question cards, multi-select included; a tool that asks for permission gets an **Allow** / **Deny** card. A card answered on claude.ai closes in OAR
|
|
313
|
-
- **Stop** interrupts the cloud turn. If the cloud does not confirm within 30 seconds, the turn ends in OAR with a note that the agent may still be working there
|
|
314
|
-
- Image attachments (JPEG, PNG, GIF or WebP, up to 5 MB each), sent inline
|
|
315
|
-
- Follow-up messages go into the same cloud session, also after it has been idle for a long time
|
|
316
|
-
- A restart of the worker or the relay in the middle of a turn does not send your message twice: the new worker finds the turn in the session's event log and follows it, and a turn that finished in the meantime is answered from the log. A dropped connection to the session is reopened where it broke off
|
|
317
|
-
- The **cloud line** above the composer: the repository, the branch, a link to the session on claude.ai, one **โก branch** link per branch the agent pushed (it opens GitHub's comparison with the branch the chat started from) and what the session has cost so far. The `โฏ` menu has **โ๏ธ Open on claude.ai**
|
|
318
|
-
- [Commit attribution](#claude-agent-sdk): commits and pull requests the agent makes in the sandbox end with what the Claude tab's setting says (**OAR**, **vanilla** or **off**), from the first message on, and a change reaches the sandbox with the next message. In OAR mode the `Claude-Session` link to claude.ai is left out too. A chat started from a folder follows that folder's override, and its **๐ง ** modal has the select. The commit's author is still the sandbox's git identity (`Claude`); the setting covers the lines at the end
|
|
319
|
-
- A turn the session starts by itself โ the agent's closing turn when its background work outlived the hold, or a message you sent on claude.ai โ appears in the chat as a continuation reply, with a line saying where it came from; the worker keeps the session's event stream open for that
|
|
320
|
-
- A turn the cloud refuses at the Claude usage limit is paused like a local Claude turn (a note with the reset time, the banner, and the work carries on by itself after the reset); the limit warning before it appears in the tool activity
|
|
321
|
-
- Deleting or archiving the conversation archives the cloud session at Anthropic; nothing is deleted there
|
|
322
|
-
- A **Claude Cloud** card in **Check Usage** with the account's cloud credit and the cost Anthropic reports for this relay's cloud sessions, and the **๐ง ** button for the session's context use (see [Usage and context](#usage-and-context))
|
|
323
|
-
- A failure the relay can name says what to do: log in again, connect GitHub, give the Claude GitHub app access to the repository, choose an environment
|
|
324
|
-
|
|
325
|
-
**What does not.**
|
|
326
|
-
|
|
327
|
-
- No relay modes, no reasoning effort and no context size: the three selectors are hidden. The model is chosen in **New Chat** and can be changed between turns in the composer like a local Claude chat's (the sandbox switches before the next message)
|
|
328
|
-
- No mid-turn steering: a message sent during a turn waits for the turn to end
|
|
329
|
-
- Nothing from the relay host reaches the sandbox: attachments other than images are refused, there is no working directory to change and no **Session** folder to browse
|
|
330
|
-
- No relay tools inside the sandbox: no `preview`, no `remote_relay`, no media embedded by host path
|
|
331
|
-
- No background task panel
|
|
332
|
-
|
|
333
|
-
**Started by an agent.** An agent in another session can start a cloud chat with the `remote_relay` tool, naming the repository and, if it wants one, the branch (`repo` and `branch`): an agent on a [paired relay](#remote-relays), under the rules for starting any session from there, or an agent on this relay once [agent sessions](#agent-sessions) are switched on. The same checks apply as in **New Chat** (the provider is on, an environment is set, the repository is on GitHub), and a chat without a requested model starts with the tab's default model. It can also read, prompt, wait for and stop a cloud chat you created.
|
|
334
|
-
|
|
335
|
-
**What OAR does with the Claude login.** Claude Cloud uses the login the Claude CLI keeps on the relay host (`.credentials.json` in `~/.claude`, or in `CLAUDE_CONFIG_DIR`) to call the Anthropic API endpoints the Claude CLI itself uses for cloud sessions and account usage. **These endpoints are not a documented public API.** Anthropic can change them without notice; cloud chats and the live usage figures then fail with a note until OAR is updated. If you are not comfortable with a program other than the CLI using its login this way, leave the provider off.
|
|
336
|
-
|
|
337
|
-
- The relay and its cloud workers only **read** the access token. It is sent as the bearer token to `https://api.anthropic.com` and to no other host. (OAR's own tests point the client at a fake API on the same machine; that setting accepts a loopback address and nothing else.)
|
|
338
|
-
- It is held in memory only. It is never written to the database or to a log, never sent to the browser and never put into an error message. Each cloud worker reads the credentials file itself, so nothing is passed along at launch.
|
|
339
|
-
- It is never refreshed by OAR, and the refresh token is never used. The CLI keeps its own login fresh; when the token has run out, the relay โ and a cloud chat's worker, through the relay โ reads the file again and at most once in five minutes has the CLI check its own login (`claude auth status`, which refreshes a login whose refresh token is still good), then retries. A login that is still expired ends the turn with a note to log in again.
|
|
340
|
-
- While the switch is off, the relay asks Anthropic for nothing with this login: it lists no environments and reads no account usage. Only a cloud conversation from before still talks to its session, when you write to it, delete it or archive it.
|
|
341
|
-
- The provider is off by default. Switching it on is the consent for all of the above.
|
|
342
|
-
|
|
343
|
-
`CLAUDE_CODE_OAUTH_TOKEN` in the relay's environment is used instead of the credentials file when it is set. That is the one case in which the relay passes the login on: a cloud worker started under tmux gets the variable through a file only the relay's user can read, which the worker's shell reads once and deletes; workers of other providers are not given it that way (see [Environment variables](#environment-variables)).
|
|
344
|
-
|
|
345
|
-
### Cursor (Agent SDK)
|
|
346
|
-
|
|
347
|
-
Turn on **โ๏ธ Settings โ Providers โ Cursor**, paste your Cursor API key, and enable it for New Chat model selection. Saving the key runs model discovery and also discovers each model's supported reasoning-effort tiers; use **๐ค Select Models โ Cursor SDK** to choose which models appear in the composer (the configured default model, `composer-2.5` unless you change it, always stays enabled).
|
|
348
|
-
|
|
349
|
-
What Cursor conversations support:
|
|
350
|
-
|
|
351
|
-
- Per-message model and reasoning effort โ effort tiers come from per-model discovery, and `none` means the model's default behavior
|
|
352
|
-
- All four relay modes โ `plan` uses the SDK's native plan mode and produces a **Plan ready** board; `ask` and `autopilot` ride as instructions on the message text, injected only when the mode changes
|
|
353
|
-
- Live reply streaming, question cards, and **Stop** to abort the running turn
|
|
354
|
-
- The browsable **Session** root points at the worker's per-session agent store, created on the session's first turn
|
|
355
|
-
- Expired cached agent handles are recreated and retried automatically once โ a second auth failure means the API key itself is invalid
|
|
356
|
-
|
|
357
|
-
Like Claude, Cursor turns are not included in the Copilot usage line and no usage line is attached to their replies. Cursor spend is tracked separately in **Check Usage**; set your monthly pool allowances and billing reset day under **โ๏ธ Settings โ Providers โ Cursor โ Cursor monthly plan allowance**. The optional **Dashboard session token** in the same panel unlocks live *Included in plan* bars; it is detected automatically from the host's Cursor IDE login when there is one, and headless hosts can set `CURSOR_SESSION_TOKEN` instead.
|
|
358
|
-
|
|
359
|
-
### Grok (CLI ACP)
|
|
360
|
-
|
|
361
|
-
Turn on **โ๏ธ Settings โ Providers โ Grok**. There is no key to enter: the relay drives the Grok CLI on the host and uses whatever account that CLI is signed in to (or `XAI_API_KEY` in the host environment).
|
|
362
|
-
|
|
363
|
-
The same panel manages both the CLI and the account:
|
|
364
|
-
|
|
365
|
-
- The **Grok CLI** row installs or updates the CLI itself โ see
|
|
366
|
-
[Installing a provider CLI from the relay](#installing-a-provider-cli-from-the-relay).
|
|
367
|
-
- **Sign in** starts the CLI's device-code login on the relay host and brings it to the browser: the
|
|
368
|
-
x.ai authorization link appears inline with a **Copy link** button, and the `XXXX-XXXX` code is
|
|
369
|
-
shown next to it so you can check it against what the browser displays. Open the link on any
|
|
370
|
-
device, confirm, and the panel flips to signed-in **by itself** โ nothing is pasted back through
|
|
371
|
-
the relay, because the CLI polls x.ai and finishes on its own. Model discovery re-runs straight
|
|
372
|
-
after, so switching accounts needs no relay restart. The flow is pushed over the socket: start it
|
|
373
|
-
on one device, finish it on another, and closing the modal does not lose it.
|
|
374
|
-
- **Sign out** asks for confirmation first and tells you how many Grok workers are running. Running
|
|
375
|
-
sessions keep the previous token until their worker exits.
|
|
376
|
-
|
|
377
|
-
The relay holds no Grok secret: the device code is public by design, and the token is written by the
|
|
378
|
-
CLI straight into `~/.grok/auth.json`. Running `grok login` on the host still works as before.
|
|
379
|
-
|
|
380
|
-
Grok conversations support live reply streaming, thoughts, plan boards, subagent lifecycle chips,
|
|
381
|
-
**Stop**, session resume across worker restarts, per-turn context metrics, and the live weekly quota
|
|
382
|
-
bar in **Check Usage**. The model is fixed per conversation (ACP has no mid-session switch; the default
|
|
383
|
-
is `grok-4.5`), and question cards are not available โ the protocol has no ask-user surface.
|
|
384
|
-
|
|
385
|
-
### Installing a provider CLI from the relay
|
|
386
|
-
|
|
387
|
-
Grok and Claude both run as CLIs on the relay host, and the failure mode used to be a dead end: a
|
|
388
|
-
turn fails with *"Grok CLI was not found on PATH"* and the only fix is a shell on the host โ the one
|
|
389
|
-
thing the relay exists to avoid. The Copilot, Claude, and Grok sub-tabs therefore carry a CLI row at the top:
|
|
390
|
-
|
|
391
|
-
```
|
|
392
|
-
Grok CLI not installed [ Install ]
|
|
393
|
-
Grok CLI 1.0.13 ยท ~/.grok/bin/grok ยท native ยท up to date [ Update ]
|
|
394
|
-
```
|
|
97
|
+
The runtime (the *provider* in the UI) is chosen in **New Chat** and stays fixed for that conversation.
|
|
395
98
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
-
|
|
402
|
-
|
|
403
|
-
-
|
|
404
|
-
|
|
405
|
-
keep the binary they started with.
|
|
406
|
-
- **Update** runs the CLI's own updater (`grok update`, `claude update`), not the install script again.
|
|
407
|
-
- If your Claude was installed with npm into a folder the relay user cannot write, `claude doctor`
|
|
408
|
-
says so and the button becomes **Switch to native installer** โ Anthropic's own recommended fix.
|
|
409
|
-
The npm copy stays where it is; the native build takes precedence on PATH.
|
|
410
|
-
- The **Copilot** row is read-only: that CLI is managed with npm on the host, so there is nothing
|
|
411
|
-
the relay could usefully run.
|
|
99
|
+
| Runtime | What it is | What you need |
|
|
100
|
+
| ------- | ---------- | ------------- |
|
|
101
|
+
| [**GitHub Copilot**](docs/providers.md#github-copilot--engine-choice) (default) | GitHub's coding agent, with every model your Copilot plan offers | The Copilot CLI, signed in on the relay host |
|
|
102
|
+
| [**OpenAI (BYOK)**](docs/providers.md#openai-byok-and-openai-image) | Copilot's agent against OpenAI or a compatible endpoint | Your own API key |
|
|
103
|
+
| [**OpenAI Image**](docs/providers.md#openai-byok-and-openai-image) | A chat whose replies are images | The same key |
|
|
104
|
+
| [**Claude**](docs/providers.md#claude-agent-sdk) | Claude Code on your machine | A Claude login, made from **โ๏ธ Settings** |
|
|
105
|
+
| [**Claude Cloud**](docs/providers.md#claude-cloud) (experimental) | Claude Code in a sandbox at Anthropic, on a GitHub repository | A claude.ai account with GitHub connected |
|
|
106
|
+
| [**Cursor**](docs/providers.md#cursor-agent-sdk) | Cursor's agent | A Cursor API key |
|
|
107
|
+
| [**Grok**](docs/providers.md#grok-cli-acp) | xAI's Grok CLI | A Grok sign-in, made from **โ๏ธ Settings** |
|
|
412
108
|
|
|
413
|
-
|
|
414
|
-
a button โ **Install Grok CLI**, **Sign in to Grok**, **Claude settings** โ which opens the right
|
|
415
|
-
panel and, for an install, the same confirmation sheet.
|
|
109
|
+
API keys are entered in **โ๏ธ Settings** and stay on the relay host. The Claude and Grok CLIs can be [installed and signed in to from the browser](docs/providers.md#installing-a-provider-cli-from-the-relay), so no shell on the host is needed. Each runtime discovers its own [models](docs/providers.md#models). The full picture of each runtime is in [Providers](docs/providers.md).
|
|
416
110
|
|
|
417
|
-
|
|
111
|
+
<a id="highlights"></a>
|
|
112
|
+
<a id="using-the-web-ui"></a>
|
|
418
113
|
|
|
419
|
-
|
|
114
|
+
## What you can do
|
|
420
115
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
- **Watching sessions**: an agent subscribes to other sessions, on its own relay or on a paired one, and is woken by what happens there: a question waiting for an answer, an error, a reply, a background task that finished or failed, a session gone quiet, nothing running any more. Each wake-up is a short automated message in its conversation, shown as a compact row. Subscriptions only notify; they approve nothing. The first subscribe of a conversation asks you on a card, and the header shows **watching N sessions** with an Unsubscribe per subscription. See [Watching sessions](#watching-sessions).
|
|
435
|
-
- **Notes between agents fold away**: a prompt another agent sent a session and the session's reply show as one row that opens to both.
|
|
436
|
-
- **A sub-agent's whole record**: its title in the task panel, or its row under the finished reply, opens a viewer with its thoughts, every tool call with input and result, and its reply, live while it runs. **Keep sub-agent tool output** under Settings โ General decides how long tool inputs and results are kept.
|
|
437
|
-
- **What the plans have left**: `remote_relay`'s `usage` action tells an agent what each provider's plan has left on its own relay or a paired one, before it starts work that costs; `list_sessions` and `read_session` say whether a session is running a turn, only background work, or nothing.
|
|
438
|
-
- **Folders in the file browser**: **๐+ New folder**, and a right-click (a long press on a phone) on a file or folder to rename or delete it.
|
|
439
|
-
- **Back to the latest message**: a โ button above the composer, with a count of the rows that arrived since, jumps back to the end, and the transcript follows new rows again.
|
|
440
|
-
- **Fewer surprises**: archiving a session whose process is still active asks first, Settings opens with no conversation open (so a fresh install can turn on a provider), a queued relay restart no longer waits forever on a busy relay, and waking the host from sleep no longer restarts the running turns.
|
|
441
|
-
|
|
442
|
-
### New in 0.9.7
|
|
443
|
-
|
|
444
|
-
- **Claude Cloud (experimental, off by default)**: a chat that runs Claude Code in a sandbox at Anthropic, on its own clone of a GitHub repository. Pick the repository and branch from a list, follow the turn live, answer its questions, stop it, change the model between turns; the results come back as pushed branches. See [Claude Cloud](#claude-cloud) for what it needs and what it does with the Claude login.
|
|
445
|
-
- **Archive, and a menu on every conversation**: archive a conversation instead of deleting it (๐ shows the archived ones), and right-click a row, or long-press it on a phone, to open, rename, stop, kill, archive or delete it.
|
|
446
|
-
- **Agent sessions**: an agent can start other sessions on the relay it runs on, wait for them and read their results, once you switch it on under Settings โ Relays.
|
|
447
|
-
- **Commits say Open Agent Relay**: commits and pull requests of Claude sessions carry `Co-authored-by: Open Agent Relay (<model>)`; choose OAR, Claude Code's own lines or none, per relay and per folder.
|
|
448
|
-
- **Check Usage opens at once**: the last reading shows immediately and only the open tab is read live.
|
|
449
|
-
- **Fixes**: two prices in one paragraph are no longer shown as a formula, a reply that names an error code is no longer stored as a failed turn, and on Windows the relay no longer stalls or fails to start workers while it reads the process list.
|
|
450
|
-
|
|
451
|
-
### New in 0.9.6
|
|
452
|
-
|
|
453
|
-
- **Claude pauses at the usage limit**: a turn that runs into the subscription's usage limit is paused instead of failed. A banner above the composer says when it carries on, with **Resume now** and **Cancel**; after the reset the relay sends a message of its own that quotes what was refused. The pause survives a relay restart, and a reset more than six hours away waits for you. A second banner warns when the usage passes 90 % of a limit.
|
|
454
|
-
- **A quiet command no longer fails its turn** (Copilot, Cursor, Grok): how long a turn may stay silent depends on what the agent is doing: 2 minutes with nothing in flight, 5 minutes during a model request, 30 minutes while a tool runs.
|
|
455
|
-
- **Copilot turns that fail, fail well**: the failure shows at once, what the agent had written stays above the note, Stop works on a stuck turn, a finished reply survives a relay restart, and the commands of a runtime that died are stopped. A message you send while a command runs waits for the command instead of cutting it short.
|
|
456
|
-
- **Agents on paired relays can answer each other**: a relay you mentioned stays in reach for the whole session, and an agent that was asked from another relay can answer, ask back or report later. See [Remote relays](#remote-relays).
|
|
457
|
-
- **Less scrolling in a running turn**: subagents are folded to a one-line header that says what they are doing, and a plan board sits inside the reply it belongs to; its choice also sets the session's mode.
|
|
458
|
-
- **Failure notes that help**: no more advice to restart the relay, and a Claude account problem (billing, sign-in, access) says what to check. The relay keeps its console in `relay-console.log`.
|
|
459
|
-
|
|
460
|
-
### New in 0.9.5
|
|
461
|
-
|
|
462
|
-
- **A misplaced Claude reply no longer blocks the conversation**: when a reply is published as a *background continuation* instead of under your message, the message closes after about 45 seconds of silence with a small note naming that reply, and the next message runs normally. It used to hold every later message for up to 5 minutes.
|
|
463
|
-
- **Effort for remote sessions**: an agent can set the reasoning effort of a session it starts or prompts on another relay; a new session takes the calling session's effort when the model there supports it. See [Remote relays](#remote-relays).
|
|
464
|
-
- **Waiting on another relay is steadier**: the wait no longer stops at an interim answer while the remote agent goes on in a turn of its own, for example while its subagents work.
|
|
465
|
-
- **Worker logs on Windows**: session workers now write the same `worker-<session>.log` as on Linux, in the relay's log directory, while the console window keeps showing the output.
|
|
466
|
-
|
|
467
|
-
### New in 0.9.4
|
|
468
|
-
|
|
469
|
-
- **Remote relays**: pair two OAR relays in **Settings โ Relays** by pasting the other relay's web address; the pairing works both ways. An agent in any session can then work on the other relay when you ask it to: list and read its sessions, prompt one, start a new one, wait for the reply, and pass a question the remote agent asks back to you. See [Remote relays](#remote-relays).
|
|
470
|
-
- **You decide when a relay is in reach**: a paired relay stays locked in a conversation until you mention it (`@` picks it from a list). Per relay, **Agents may** limits agents to *read only*, *read and prompt*, or *full*, and in ask and plan mode every write action asks you first. The receiving relay marks such messages with a **โ from โฆ** badge.
|
|
471
|
-
- **Every provider gets the same tools**: Grok and the Copilot extension engine now get `remote_relay` and `preview` as real tools through OAR's MCP server, instead of instruction text.
|
|
472
|
-
- **Follow the live reply**: three toggles in the running reply's header keep its thoughts, its answer, or its tool list pinned just above the composer as the reply grows. Scrolling the transcript by hand turns it off; typing in the composer does not.
|
|
473
|
-
- **Suspend host waits for the work to finish** (Windows): the relay queues the suspend and fires it after 2 minutes with no turn, background task, or GitHub Actions run active, or after a 30-second countdown when nothing was running. Every device shows a banner with what is still active and a **Cancel** button; a queued relay restart shows the same banner.
|
|
474
|
-
- **Stop** asks for confirmation before it cancels the running turn.
|
|
475
|
-
- **Fewer stuck and failed sends**: switching the Claude model mid-conversation no longer strands the next message, and the relay keeps idle connections open for 65 seconds, so a request sent after a short pause is no longer reset (behind a proxy or tunnel: an occasional 502).
|
|
476
|
-
|
|
477
|
-
### Everything else
|
|
478
|
-
|
|
479
|
-
- Remote chat UI for local coding agents, with the runtime chosen per conversation
|
|
480
|
-
- Per-message **mode** (`plan`, `ask`, `agent`, `autopilot`), **model**, and **reasoning effort** pickers, backed by live model discovery
|
|
481
|
-
- Streaming tool activity, thoughts, and live assistant reply text while a turn runs
|
|
482
|
-
- Nested **subagent bubbles**: each subagent gets its own live bubble with its own thoughts, activity, and streamed text, kept as collapsible sections after the turn finishes
|
|
483
|
-
- **Background task panel** with live per-task state, model, and token use; Claude workflow tasks fold out into a progress tree of phases and agents, and leave a *Finished background task* card in the transcript when they complete
|
|
484
|
-
- Question cards for clarification: one-click choices, multi-select checkmarks, free text, and multi-field structured forms validated against their JSON schema
|
|
485
|
-
- Mathematical and scientific notation rendering for TeX/LaTeX equations and chemical formulas, written as `$โฆ$`, `\(โฆ\)`, `$$โฆ$$` or `\[โฆ\]`. A single `$` opens a formula only when a non-space character follows it directly and the next `$` has a non-space character directly before it and no digit directly after it (a digit is allowed after something that looks like TeX, as in `$x^2$3`), so prices such as `$5 and $9` stay text
|
|
486
|
-
- **Context usage** modal with a per-category token breakdown of the model's context window, plus a per-conversation **auto-compact window** slider for Claude sessions
|
|
487
|
-
- **Transcript breaks**: day separators, a marker where a Claude session auto-compacted its context (shown while the compaction runs), and matching dots beside the scrollbar
|
|
488
|
-
- **Plan usage** modal with subscription credits, rate-limit windows, and reset countdowns for Copilot, Claude, Claude Cloud, Cursor, and Grok
|
|
489
|
-
- **Image conversations** (OpenAI Image): generate images in chat and iterate on a generated image with **Edit this image**
|
|
490
|
-
- Agents can embed **images, video, and audio** in a reply by their absolute path, on every runtime; clicking an embedded image opens the file viewer with zoom, download, and copy
|
|
491
|
-
- **Screenshot annotations**: mark up an uploaded screenshot with highlighter strokes before or after sending; the original upload is never modified
|
|
492
|
-
- **Share** a conversation by read-only link, and hide individual messages from the shared view
|
|
493
|
-
- **Pin** messages in a conversation and get back to them from a list that scrolls to each one
|
|
494
|
-
- Conversation history in local SQLite, including the Copilot sessions already stored on the host
|
|
495
|
-
- `/compact` continues in a fresh conversation seeded with a summary; `/preview` publishes a local dev server or folder on a public preview host
|
|
496
|
-
- Workspace and drive browser with file previews, **Git changes** with a diff viewer, and `@file:` / `@folder:` reference tokens
|
|
497
|
-
- **Push notifications** for questions, finished or failed turns, plan boards, and a CLI going offline
|
|
498
|
-
- Opt-in **self-update** from Settings or `oar update`
|
|
499
|
-
- Remote access through a managed **SSH** reverse tunnel or **Cloudflare Tunnel**
|
|
500
|
-
- Installable **PWA** with an installed-app fullscreen preference and browser-mode fallbacks
|
|
501
|
-
|
|
502
|
-
## Using the web UI
|
|
503
|
-
|
|
504
|
-
### Starting a conversation
|
|
505
|
-
|
|
506
|
-
- Start a chat with **+ New Chat**, which asks for the **Working directory**, **Provider**, **Model**, and **Reasoning effort** (or **Quality** and **Size**, for image chats; **Context window** where a model offers several) before the conversation exists. The working-directory list offers the known directories (current session, relay workspace, browser folder, recent roots), a **Custom pathโฆ** entry, and a ๐ folder picker; it defaults to the directory you picked last, and the chosen directory is applied before the session worker first launches. With Copilot as the only provider the provider row is hidden. For **Claude Cloud** the modal asks for a **Repository** and a **Branch** instead of a reasoning effort, filled in from the chosen folder (see [Claude Cloud](#claude-cloud)).
|
|
507
|
-
- Choose the **mode** and **model** per message in the composer.
|
|
508
|
-
- The composer knows two slash commands, with autocomplete: **`/compact`** branches to a fresh conversation seeded with summary context, and **`/preview`** publishes a local dev server or directory on the public preview host without involving the agent (`/preview 5173 [label]`, `/preview ./dist [label]`, `/preview list`, `/preview close`). Agents can do the same through the `preview` tool (Claude and Cursor) or the documented API (see [docs/preview-servers.md](docs/preview-servers.md)). Any other single-line text starting with `/` is held back once with an *Unknown command* notice; press send again to send it as text.
|
|
509
|
-
|
|
510
|
-
### Relay modes
|
|
511
|
-
|
|
512
|
-
| Mode | Behavior |
|
|
513
|
-
| ----------- | ------------------------------------------------------------ |
|
|
514
|
-
| `ask` | Clarification-first behavior before implementation |
|
|
515
|
-
| `plan` | Planning response style (no implementation unless requested) |
|
|
516
|
-
| `agent` | Interactive coding agent behavior |
|
|
517
|
-
| `autopilot` | Action-first behavior; asks only when truly blocking |
|
|
518
|
-
|
|
519
|
-
### While a turn runs
|
|
520
|
-
|
|
521
|
-
- Assistant text streams into the pending bubble as it is generated, next to the turn's tool activity and thoughts. Any subagent the turn spawns gets its own nested bubble with its own thoughts, activity, and text.
|
|
522
|
-
- **Steer or queue.** On Claude, and on Copilot's SDK engine, a message you send during a live turn is pushed into that turn; the send button reads **Steer**. A folded message keeps a compact *merged* marker in the transcript, and one the agent answers separately gets its own reply. While the turn waits on a question card or plan approval, or is compacting, the button reads **Queue** and its tooltip says why: the message waits as a pending bubble (with **Cancel**) and steers in once the card is answered or the compaction ends. On the other runtimes, and on Copilot's Extension engine, messages sent during a turn queue behind it, and the button reads **Queue**.
|
|
523
|
-
- **Stop** is on the running reply's bubble, whose header stays pinned at the top while a long reply scrolls; the send button never turns into Stop. Queued messages carry their own **Cancel** until they are picked up. A steered message that a Stop cut off is marked *Stopped with the turn โ not answered* and offers **Resend**; the button then reads **Resent** on every device.
|
|
524
|
-
- On Copilot, **Stop** ends only the reply: background agents the turn started keep running under their own **Stop** in the task panel.
|
|
525
|
-
- The transcript follows new rows while you are at its end. Once you scroll about a screen up, a round **โ** button fades in above the composer, with a badge counting the rows that arrived since; it takes you back to the end and the transcript follows again. From a search result or a pin deep in the history it loads the end first.
|
|
526
|
-
|
|
527
|
-
### Question cards
|
|
528
|
-
|
|
529
|
-
- Agents ask clarifying questions through question cards: `ask_user` on Copilot and Cursor, `AskUserQuestion` on Claude and Claude Cloud. A choice answers with one click; a question that allows several answers shows checkmarks and one **Reply with selection** button, whose reply lists every ticked choice plus anything you typed. Structured requests render as multi-field forms.
|
|
530
|
-
- On Copilot's SDK engine, the model gets OAR's own `ask_user` tool, which can mark a question as multi-select; a question worded "select all that apply" counts too, and every Copilot choice card that accepts free text has a **Select several** switch.
|
|
531
|
-
- A card waits 8 hours for an answer (2 hours on Copilot's Extension engine). After that the agent is told nobody answered and continues according to the conversation's mode. A turn that is waiting on a card is never treated as stuck.
|
|
532
|
-
- Grok has no question cards: ACP has no ask-user surface.
|
|
533
|
-
|
|
534
|
-
### Background tasks
|
|
535
|
-
|
|
536
|
-
- The composer's task panel lists background work that outlives the reply that started it: backgrounded commands, subagents, monitors, and workflows on Claude; background agents and detached shells on Copilot's SDK engine. Each row shows its state, the model it runs on, the command it is running right now, its token count, and its own **Stop**. The panel scrolls when it holds more tasks than fit.
|
|
537
|
-
- An **Ultracode** workflow folds out into a tree of its phases and agents (state, model, tokens). When it finishes, the summarizing reply keeps a collapsed *Finished background task* card holding the final tree, which survives reloads.
|
|
538
|
-
- A background task's result arrives as its own *continuation* reply.
|
|
539
|
-
- A sub-agent's title in the panel opens its whole record: its thoughts, every tool call with its full input and its result, its reply and the agents it started itself, in order and live while it runs, with its own **Stop**. The finished reply lists the turn's sub-agents as the same rows (model, type, tokens, time, how they ended), so the record stays one click away; a child agent opens in place and back returns to its parent. Claude records everything; Copilot and Cursor show what they report. A tool result is kept to its first 4 KB and a record to 2000 entries; **Keep sub-agent tool output** in Settings โ General decides how long tool inputs and results are kept.
|
|
540
|
-
- **โ๏ธ Settings โ General โ Background task timeout** (default 4 h; 0 = no limit, up to 10 h) caps how long background tasks alone may keep a Claude or Copilot session running after its reply. When the limit is reached, the tasks are stopped.
|
|
541
|
-
|
|
542
|
-
### Drafts across devices
|
|
543
|
-
|
|
544
|
-
The composer draft, attachments included, is saved per conversation on the relay and follows you to your other devices. Saves happen only on real edits and are version-checked, so an idle device never overwrites the draft you are typing on another one, and a device you are not typing on picks up the other's draft. When two devices edit at once, the newest keystroke wins and the replaced text is offered back with **Restore** (and **Undo**). A draft longer than 20,000 characters is saved up to that length, and the composer says the rest is not saved.
|
|
545
|
-
|
|
546
|
-
### The conversation list
|
|
547
|
-
|
|
548
|
-
- **Filter conversationsโฆ** above the list matches titles, ignoring case. It clears with **ร** or Escape, and while it is active it loads older pages, so it searches every conversation, not just the loaded ones.
|
|
549
|
-
- **๐** in the conversation header searches message text across all conversations.
|
|
550
|
-
- On startup, the relay imports the Copilot sessions stored on the host (through the installed Copilot runtime) into its database, so they appear in the list with their history. If the runtime is unavailable, the import is reported as failed rather than guessed from the filesystem.
|
|
551
|
-
- **Archive** (๐ on the row, or **Archive conversation** in the `โฏ` menu) takes a conversation out of the list without deleting anything: its session worker is stopped, and a Claude Cloud chat's session at Anthropic is archived with it. The ๐ toggle above the list shows the archived conversations; **Unarchive** (๐) brings one back, cloud session included. An archived chat that is opened cannot be sent to until it is unarchived; a message that reaches it anyway (an agent's through a paired relay, say) unarchives it. Archiving a conversation whose session process is still active (green in the list, idle or working) asks first, because archiving stops it. A conversation that is still working is not archived โ stop it first.
|
|
552
|
-
- A **right-click on a row** (a long press on a phone) opens a menu with Open, Edit title, Stop turn, Kill session, Archive or Unarchive, and Delete, so a session can be stopped or killed without opening it.
|
|
553
|
-
- Deleting a conversation stops its session worker and removes its CLI session too (Copilot through the runtime, Claude by deleting that session's transcript). A Claude Cloud conversation's session at Anthropic is archived, not deleted. An imported Copilot session the relay never ran is only hidden: its CLI session stays, and nothing is stopped for it. A conversation that is still working โ a running turn, one waiting on a question card or approval, or live background tasks โ is not deleted, and the sidebar says why so you can stop it first.
|
|
554
|
-
|
|
555
|
-
### Files, git, and previews
|
|
556
|
-
|
|
557
|
-
- Use **๐ Browse files** to inspect the workspace (๐ผ), drives (๐), or the session's own folder (๐ต๏ธ), and to open previews. The **Hidden** and **Heavy** toolbar filters are remembered per browser, and a refresh re-opens the folders you had expanded.
|
|
558
|
-
- **๐+ New folder** in the browser's toolbar opens a name field at the top of the folder pane; Enter creates the folder inside the open one and opens it. It works in the repository, on the drives, in the session folder, and in the folder picker of **New chat** and **Change CWD**. A right-click on a folder in the tree or a file in the folder pane (a long press on a phone) offers **Rename** and **Delete**, and on a folder **New folder here**. Delete says what goes, and a folder with content asks for its name to be typed first. Links are never followed or changed; roots (the repository root, `/`, a drive, the session folder) cannot be renamed or deleted, and the session folder is read-only apart from new folders.
|
|
559
|
-
- Click the file and folder copy controls to insert `@file:...` / `@folder:...` tokens.
|
|
560
|
-
- Workspace browsing follows the selected session's effective working directory. Running sessions keep their learned runtime directory, **๐๏ธ Change CWD** in the `โฏ` menu changes the directory for the next launch, and `cd ...` typed in chat does not retarget the browser. A Claude Cloud chat has no **Change CWD**: it works on a clone at Anthropic.
|
|
561
|
-
- Use **๐ฟ Git changes** in the conversation `โฏ` menu to review the workspace repository: the header shows the branch with ahead/behind counts and a **โฌ Pull** button, and the list shows every staged, unstaged, and untracked file (deleted files struck through). Clicking a file opens a diff viewer with **Changes** and **Full file** modes; closing it returns to the still-open list.
|
|
562
|
-
- Agents can embed images, video, and audio in a reply by absolute path; they render inline.
|
|
563
|
-
- Tap an image attachment in the composer (it carries a ๐๏ธ badge), or use **๐๏ธ Annotate** in the file viewer, to mark it up with highlighter strokes. The annotated copy is uploaded; the original stays untouched.
|
|
564
|
-
- External links in chat open in a new tab with `noopener`/`noreferrer`; workspace file mentions stay in the in-app preview.
|
|
565
|
-
|
|
566
|
-
### Usage and context
|
|
567
|
-
|
|
568
|
-
- Use **๐ Check Usage** in the conversation `โฏ` menu for plan usage across every configured provider: remaining credits, rate-limit windows, reset countdowns, and collapsible cost/token detail. Each provider gets its own tab, opening on the conversation's own provider, and the card names the signed-in account (email and plan) beneath its title. The modal opens on the reading it showed last time and reads only the open tab's provider live (its card says "updatingโฆ" until the answer is in); a tab you switch to is read live when its reading is older than a minute, **Refresh** reads the open tab, and the relay keeps the last live answer of every provider so the other cards are never empty. Sources differ per provider:
|
|
569
|
-
- **Copilot** โ live quota (AI credits or premium requests, chat, plan), plus per-model/product billed cost when your GitHub token can read personal billing. Conversations on the SDK engine add a **Last SDK worker turn** section (AI credits actually spent, tokens, model calls, overage) with the model and how long ago it was captured; it is one turn's numbers rather than a running total, and it stops being shown once it is more than seven days old.
|
|
570
|
-
- **Claude** โ subscription limit windows (5-hour, weekly, per-model), extra-usage credits, session cost, and local usage attribution. Read from the live session at the end of a turn; the relay never starts a hidden turn to refresh it, so the newest reading is from your last Claude turn. With **Claude Cloud** switched on, the limits are read live from the account each time the modal opens (kept for a minute), with no turn involved: the card then carries a **Live** badge, a limit that is getting close carries Anthropic's own warning word, and it adds **This week by product** (Claude Code, chats and the other products as shares of the week) and the organisation's **Prepaid credits** when there are any. Limit resets (full and 5-hour) are shown on claude.ai only; the card links there. When the live read fails, the card falls back to the last turn's reading and says why.
|
|
571
|
-
- **Claude Cloud** โ shown while the provider is on. A meter per dollar credit the account holds, with what is used, what is left and when it expires; **Cloud spend (OAR sessions)**, the cost Anthropic reports per cloud session, summed over the cloud conversations this relay still has, with this conversation's own cost when the modal was opened from a cloud chat; and the latest cloud session report (its cost, and cost and tokens by model). These figures are Anthropic's reported cost, not a billing statement, and sessions started elsewhere are not counted. A credit that is offered but not yet claimed is mentioned with a link to claude.ai. Cloud turns spend the cloud credit first; without a credit they count against the Claude limits above.
|
|
572
|
-
- **Cursor** โ spend from the Cursor SDK measured against the monthly allowances you enter in Settings, split into the Cursor Models and Other Models pools; these figures are estimates, and Cursor's Spending dashboard remains authoritative. With a dashboard session token, the card adds live *Included in plan* bars.
|
|
573
|
-
- **Grok** โ the live weekly subscription quota, read with the host's Grok CLI login, plus per-turn tokens and estimated cost from the agent's prompt result. An optional monthly USD allowance in Settings adds an estimated remaining meter; the card is hidden when Grok is disabled. Billing: [console.x.ai](https://console.x.ai).
|
|
574
|
-
- Per-reply usage lines are recorded only for Copilot turns โ OpenAI, Claude, Claude Cloud, Cursor, and Grok turns do not consume Copilot premium requests, and no usage line is attached to them.
|
|
575
|
-
- Use the **๐ง ** context button for a per-category breakdown of the conversation's context window (Claude sessions also show the auto-compact window, the thinking controls and the folder's commit attribution there): a usage bar, a token/percentage table, and free space. Claude sessions report exact SDK categories; Copilot sessions show the coarser system/tools + messages + buffer split, labelled as a lower-bound estimate when the runtime no longer emits full buckets. A Claude Cloud session reports how much of its window is used after each turn, without categories.
|
|
576
|
-
- Claude conversations additionally get an **auto-compact window** slider in that modal. Claude Code compacts a session once it approaches a model-tuned window (around 967k tokens on a 1M-context model), which is why long conversations rarely compact at all; setting a smaller window makes it happen sooner and keeps turns cheaper. *Auto* hands the choice back to the CLI. The smallest window is 100k, because the CLI silently ignores anything below that and falls back to its own default. The line beneath the slider reports the window actually in force and where it came from โ your setting, the model default, or the `CLAUDE_CODE_AUTO_COMPACT_WINDOW` environment override โ and fills in once the conversation's first turn completes. The slider is saved when the modal closes. Claude Code reads the window only when a session starts, so a running session restarts once, before the next message, to pick up a new one; while a turn or background work is running the change waits, and the note under the slider says for what. A window below what the conversation already uses compacts it on the next message, which the slider warns about. The modal's headline shows the tokens in use, the compaction window and, when known, the model's own limit.
|
|
577
|
-
- The transcript marks day boundaries, and marks the point where a Claude session compacted its context with the tokens before and after. While a compaction runs, the line reads *Compacting contextโฆ* and the turn's bubble says so; it turns into the final line when the compaction ends. Both kinds appear as dots beside the scrollbar for the messages currently loaded.
|
|
578
|
-
|
|
579
|
-
### Sharing
|
|
580
|
-
|
|
581
|
-
Use **โก๏ธ Share conversation** in the `โฏ` menu to publish a read-only link. Each message has a **Hide** button that keeps it out of the shared view without deleting it; hidden messages stay fully visible to you, marked *Hidden from shared viewers*, with an **Unhide** button. Anyone with the link can read the shared view, without signing in.
|
|
582
|
-
|
|
583
|
-
### Pinned messages
|
|
584
|
-
|
|
585
|
-
Each message has a **Pin** button next to **Hide**; a pinned message is marked *๐ Pinned* and offers **Unpin**. Once a conversation has pins, a **๐** button with their count appears in its header. It opens the list of pinned messages in conversation order, each with a short preview. A row closes the list and scrolls to its message, also when that message is far up in the history; **๐** in a row unpins it. Pins are kept on the relay and show on every device at once, up to 100 per conversation. They are your own bookmarks: the shared view does not show them, and a conversation continued with `/compact` starts without them.
|
|
586
|
-
|
|
587
|
-
### Notifications and the app
|
|
588
|
-
|
|
589
|
-
- **โ๏ธ Settings โ Notifications** turns on push notifications per device: for questions from the agent, completed or failed turns, plan boards, and the CLI going offline. They need a secure context (HTTPS, or `localhost`), are sent only while no device has the app in the foreground, and show generic text unless you opt in to message previews on that device.
|
|
590
|
-
- The **โฌ** button in the sidebar installs OAR as an app (PWA). **Relay name** in Settings sets its label on every device that connects to this relay, and is the name [paired relays](#remote-relays) know it by.
|
|
591
|
-
|
|
592
|
-
### The conversation menu
|
|
593
|
-
|
|
594
|
-
Besides the entries above, the `โฏ` menu holds **โ๏ธ Edit conversation title**, **๐ Archive conversation** (**๐ Unarchive** on an archived chat), **๐ฅ๏ธ Inspect tmux console** (a read-only view of the session's tmux pane), **๐ค Select Models**, **โ๏ธ Open on claude.ai** (Claude Cloud chats, once their session exists), **โ๏ธ Settings**, **๐ Restart web relay** (queued until the current turn is idle), **๐ค Suspend host** (Windows; see below), and **โ ๏ธ Kill session** (stops the conversation's worker; an active turn then needs a retry or a new message). Its header shows the queue counts with **๐ฎ Empty queue**.
|
|
595
|
-
|
|
596
|
-
**๐ค Suspend host** puts the machine the relay runs on to sleep, once the work is done. The confirmation lists what is still active. The relay then queues the suspend and fires it after 2 minutes with nothing active: no queued, running or parked turn, no background task of a live worker, and no open GitHub Actions run in the repository of a conversation that was busy since the request (read through `gh`; a repository whose state cannot be read blocks for 15 minutes, then is ignored). With nothing running when you confirm, it fires after a 30-second countdown. While a suspend is queued, every device shows a banner with the blockers or the countdown and a **Cancel** button, and a push notification reports the suspend. A relay restart drops a queued suspend and says so. **Show Suspend host action** in Settings hides the entry per browser.
|
|
597
|
-
|
|
598
|
-
## Settings and configuration reference
|
|
599
|
-
|
|
600
|
-
### Settings (โ๏ธ in the web UI)
|
|
601
|
-
|
|
602
|
-
The modal is organised into six tabs โ **General**, **Providers** (with a **Copilot**, **OpenAI**, **Claude**, **Claude Cloud**, **Grok**, and **Cursor** sub-tab), **Relays**, **Previews**, **Notifications**, and **Features** โ and reopens on the tab you used last. The `โฏ` menu opens it with no conversation open too, so a fresh install can turn on a provider before the first chat; until a provider is ready, the empty screen and **New Chat** point to Settings โ Providers. Unless noted as per browser, these settings live in the relay database rather than the config file, and apply to every browser that connects:
|
|
603
|
-
|
|
604
|
-
| Tab | Setting | Default | What it does |
|
|
605
|
-
| --- | ------- | ------- | ------------ |
|
|
606
|
-
| General | Theme, Text scaling | dark theme | Per browser |
|
|
607
|
-
| General | Show Suspend host action | on | Per browser: shows **๐ค Suspend host** in the conversation menu |
|
|
608
|
-
| General | Max turn duration | `60 min` | Hard cap on how long one turn may run before the relay requeues it (0 = no limit, up to 10 h; see below) |
|
|
609
|
-
| General | Background task timeout | `4 h` | How long background tasks alone may keep a Claude or Copilot session running after its reply; then they are stopped (0 = no limit, up to 10 h) |
|
|
610
|
-
| General | Keep sub-agent tool output | `90 days` | 7, 14, 30 or 90 days, or always: once a finished sub-agent's record is older, its tool inputs and results are removed (once a day); its thoughts, reply and the one-line summary of each tool call stay |
|
|
611
|
-
| General | Autostart (Windows) | Off | *At sign-in* (a visible terminal after you log on) or *At system startup* (headless, no logon needed, one admin confirmation) |
|
|
612
|
-
| General | Relay name | `OAR` (the hostname for paired relays) | Label of the installed PWA on every device, and this relay's name for [paired relays](#remote-relays) |
|
|
613
|
-
| General | Check for updates automatically | off | Opt-in: the relay asks oar.sh for the latest version about twice a day. **Check for updates** works regardless; `OAR_NO_UPDATE_CHECK=1` blocks both |
|
|
614
|
-
| General | Default CWD for new sessions | relay workspace root | Working directory for newly created sessions that have none of their own |
|
|
615
|
-
| Providers | Copilot engine | SDK | Extension when this relay cannot run the SDK engine (see [engine choice](#github-copilot--engine-choice)) |
|
|
616
|
-
| Providers | OpenAI API key / model / base URL | โ / `gpt-4o` / `https://api.openai.com/v1` | Enables the OpenAI and OpenAI Image providers |
|
|
617
|
-
| Providers | Claude (Agent SDK) | off | Enables Claude as a New Chat provider and runs model discovery; default model `claude-sonnet-5` |
|
|
618
|
-
| Providers | Claude account (Relogin / Logout) | host login | Switches the Claude account the relay host's CLI uses, from the browser (see [Claude (Agent SDK)](#claude-agent-sdk)) |
|
|
619
|
-
| Providers | Claude Cloud | off | Enables Claude Cloud as a New Chat provider, and the live account figures in **Check Usage**; the switch is the consent to use the Claude CLI's login (see [Claude Cloud](#claude-cloud)) |
|
|
620
|
-
| Providers | Claude Cloud environment / default model | first active environment of the account / `claude-sonnet-5-5` | The cloud environment new cloud sessions run in, and the model a new cloud chat starts with |
|
|
621
|
-
| Providers | Cursor API key / model | โ / `composer-2.5` | Enables Cursor; plus monthly plan allowances and the optional dashboard session token |
|
|
622
|
-
| Providers | Grok | off | Enables Grok; default model `grok-4.5`; **Sign in** / **Sign out**; optional monthly allowance |
|
|
623
|
-
| Relays | Public address, Accept prompts from other relays' agents | browser address / on | How paired relays reach this one, and whether their agents may prompt sessions here (see [Remote relays](#remote-relays)) |
|
|
624
|
-
| Relays | Agent sessions: Agents may start and use sessions on this relay | off | Lets agents on this relay start and use other sessions here with the `remote_relay` tool; the first session an agent starts in a conversation asks for your approval (see [Agent sessions](#agent-sessions)) |
|
|
625
|
-
| Relays | Agent sessions: Longest wait per tool call | `10 min` | How long one `remote_relay` call may wait for a reply (2 to 60 minutes), on this relay and on paired ones; adjustable whether or not the switch above is on |
|
|
626
|
-
| Relays | Remote relays | โ | Pair a relay by pasting its web address; per relay **Agents may** read only, read and prompt, or do everything |
|
|
627
|
-
| Previews | Live previews | โ | Lists the published previews, each of which you can close |
|
|
628
|
-
| Notifications | Push notifications | off | Per device: which events notify, and whether titles and message previews are included |
|
|
629
|
-
| Features | Feature flags | see below | **Session worker routing** (on), **Continuation answer routing** (on), **Generated-image continuity** (on), and a reserved **Worker fallback restart** (off, no effect yet). Changes apply after a relay restart; a `COPILOT_REMOTE_<FLAG>` environment variable pins a flag, e.g. `COPILOT_REMOTE_SESSION_WORKER_ROUTING_ENABLED=0` |
|
|
630
|
-
|
|
631
|
-
### How a stuck turn is detected
|
|
632
|
-
|
|
633
|
-
Two independent guards, both of which exempt a turn that is waiting on an unanswered question card:
|
|
634
|
-
|
|
635
|
-
1. **Inactivity** โ a turn is only considered stale after `processingTimeoutMs` with no sign of life from its worker. Worker heartbeats name the message they are working on, so a turn that legitimately runs for an hour of tool calls keeps resetting this window.
|
|
636
|
-
2. **Max turn duration** โ an absolute ceiling on elapsed time, set with the Settings slider (0 = no limit, up to 10 hours). This exists purely to catch a worker that has hung while still heartbeating.
|
|
637
|
-
|
|
638
|
-
When either trips, the turn is returned to the queue rather than lost.
|
|
639
|
-
|
|
640
|
-
### Configuration reference (`server/config.json`)
|
|
641
|
-
|
|
642
|
-
The config file is `server/config.json` in a git checkout and `~/.oar/config.json` (`%APPDATA%\oar\config.json`) for a global install; `COPILOT_WEB_RELAY_CONFIG` points the relay at another file. It holds the auth token, so the relay keeps it owner-only. The relay reads it at startup: restart the relay after editing it.
|
|
643
|
-
|
|
644
|
-
| Key | Default | Description |
|
|
645
|
-
| -------------------------- | -------------------- | ------------------------------------------------------------------------- |
|
|
646
|
-
| `authToken` | generated if empty | Required for API/UI auth. If empty, the relay generates a random token on every start and prints it to its log without saving it; `oar setup` writes a stable one |
|
|
647
|
-
| `port` | `3333` | HTTP + WebSocket port |
|
|
648
|
-
| `localhostOnly` | `true` | Bind only to loopback (`127.0.0.1`) and disable LAN/WAN access |
|
|
649
|
-
| `dataDir` | `data/` beside the server | Database and uploads; a relative path resolves against the config file's directory. `COPILOT_WEB_RELAY_DATA_DIR` wins, and global installs started by `oar` use `~/.oar/data` |
|
|
650
|
-
| `processingTimeoutMs` | `600000` | Inactivity window before a turn is treated as stale (not a cap on turn length) |
|
|
651
|
-
| `conversationSessionMode` | `isolated` | Configured strategy (`isolated` / `shared`) recorded on sessions and exposed in status |
|
|
652
|
-
| `maxRequeueRetries` | `5` | Queue retry limit for failed processing |
|
|
653
|
-
| `remotePath` | `""` | URL base path when reverse-proxied under a subpath; also drives PWA URLs and socket.io path |
|
|
654
|
-
| `trustProxy` | `"loopback"` | Which proxies may set `X-Forwarded-*` headers (Express `trust proxy`); widen it with a hop count or subnet when a proxy on another host forwards to the relay |
|
|
655
|
-
| `workspaceRootAllowList` | unset | Directories that conversations may start in (they and their subdirectories); unset allows any. `COPILOT_WORKSPACE_ROOT_ALLOW_LIST` sets it too, separated by the platform's path delimiter |
|
|
656
|
-
| `publicHostnames` | `[]` | Hostnames the relay itself answers on; the preview lane refuses to share one |
|
|
657
|
-
| `tunnelMarkerHeaders` | `[]` | Extra edge-injected headers that mark tunnel traffic (see [Session-worker path guard](#session-worker-path-guard)) |
|
|
658
|
-
| `sshTunnel.mode` | `disabled` | Tunnel mode (`disabled` or `managed`) |
|
|
659
|
-
| `sshTunnel.enabled` | `false` | Legacy alias (`true` => `managed`) |
|
|
660
|
-
| `sshTunnel.required` | `false` | Pause dequeue while managed tunnel is disconnected |
|
|
661
|
-
| `sshTunnel.remoteBind` | `loopback` | Remote bind mode for SSH `-R` (`loopback` or `public`) |
|
|
662
|
-
| `sshTunnel.command` | `ssh` | SSH executable path/command |
|
|
663
|
-
| `sshTunnel.user` | โ | SSH user |
|
|
664
|
-
| `sshTunnel.host` | โ | SSH host |
|
|
665
|
-
| `sshTunnel.remotePort` | โ | Remote forwarded port |
|
|
666
|
-
| `sshTunnel.identityFile` | optional | SSH key path (falls back to default agent/key) |
|
|
667
|
-
| `cloudflaredTunnel.mode` | `disabled` | Cloudflare tunnel mode (`disabled` or `managed`; `enabled: true` is a legacy alias for `managed`) |
|
|
668
|
-
| `cloudflaredTunnel.required` | `false` | Pause dequeue while the managed Cloudflare tunnel is disconnected |
|
|
669
|
-
| `cloudflaredTunnel.token` | โ | The tunnel token from your own Cloudflare Zero Trust tunnel |
|
|
670
|
-
| `cloudflaredTunnel.binary` | `cloudflared` | Path or command name of the `cloudflared` you installed; defaults to `cloudflared` on `PATH` |
|
|
671
|
-
| `cloudflaredTunnel.extraArgs` | `[]` | Extra arguments appended to `cloudflared tunnel run` |
|
|
672
|
-
| `previews.enabled` | `false` | Publish local dev servers on a separate listener (see [docs/preview-servers.md](docs/preview-servers.md)) |
|
|
673
|
-
| `previews.port` | `port + 1` | Loopback port for the preview listener; `0` picks an ephemeral port |
|
|
674
|
-
| `previews.bindHost` | `127.0.0.1` | Bind address; non-loopback needs `previews.allowPublicBind` |
|
|
675
|
-
| `previews.publicBaseUrl` | โ | Public base URL on a hostname **different** from the relay's |
|
|
676
|
-
| `previews.allowedTargetHosts` | `[]` | Upstreams allowed beyond loopback (container/VM IPs) |
|
|
677
|
-
| `previews.maxLive` | `8` | Maximum simultaneously published previews |
|
|
678
|
-
| `pushVapidSubject` | `mailto:copilot-remote@example.com` | Contact URI the relay sends to push services with Web Push requests |
|
|
679
|
-
| `sharedPresenceMaxPerConversation` | `200` | Most live viewers tracked per shared conversation |
|
|
680
|
-
| `sharedPresenceMaxGlobal` | `5000` | Most live shared-link viewers tracked in total |
|
|
681
|
-
| `cliBinaries` | *(written by the relay)* | Provider CLI paths resolved after an install from Settings, restored at startup |
|
|
682
|
-
| `restartGracefulTimeoutMs` | `8000` | Graceful restart wait before force fallback |
|
|
683
|
-
| `restartShutdownTimeoutMs` | `45000` | Drain timeout while waiting for active queue job completion |
|
|
684
|
-
| `restartSpawnTimeoutMs` | `18000` | Max wait for resume/restart phase per attempt |
|
|
685
|
-
| `restartRebindTimeoutMs` | `20000` | Max wait for rebind/session-sync completion per attempt |
|
|
686
|
-
| `restartMaxAttempts` | `3` | Bounded restart attempts before terminal exhaustion |
|
|
687
|
-
| `restartRetryBackoffMs` | `[1000,3000,7000]` | Deterministic retry backoff schedule in milliseconds |
|
|
688
|
-
|
|
689
|
-
### Environment variables
|
|
690
|
-
|
|
691
|
-
| Variable | Effect |
|
|
692
|
-
| -------- | ------ |
|
|
693
|
-
| `COPILOT_WEB_RELAY_CONFIG` | Config file to use |
|
|
694
|
-
| `COPILOT_WEB_RELAY_DATA_DIR` | Data directory (database and uploads) |
|
|
695
|
-
| `COPILOT_WEB_RELAY_LOG_DIR` | Log directory |
|
|
696
|
-
| `OAR_STATE_ROOT` | State root of a global install, instead of `~/.oar` / `%APPDATA%\oar` |
|
|
697
|
-
| `OAR_NO_UPDATE_CHECK=1` | Never contact oar.sh, not even for a manual update check |
|
|
698
|
-
| `OAR_HOST_SUSPEND_DRY_RUN=1` | **Suspend host** logs the suspend instead of sleeping the machine |
|
|
699
|
-
| `OAR_MCP_SERVER=0` | Do not attach OAR's MCP server to Grok and the Copilot extension engine; they get the preview instructions as text again, and no `remote_relay` tool |
|
|
700
|
-
| `COPILOT_SDK_PATH` | The Copilot CLI runtime's `copilot-sdk` directory, instead of the newest one in the CLI's package cache |
|
|
701
|
-
| `COPILOT_PKG_DIR` | An additional Copilot CLI package cache to search |
|
|
702
|
-
| `GH_TOKEN`, `GITHUB_TOKEN` | GitHub token for the Copilot usage card, instead of `gh auth token` |
|
|
703
|
-
| `XAI_API_KEY` | Grok authentication instead of the Grok CLI login |
|
|
704
|
-
| `CURSOR_SESSION_TOKEN` | Cursor dashboard session token for live plan bars |
|
|
705
|
-
| `CLAUDE_CONFIG_DIR` | Claude configuration directory, instead of `~/.claude`; Claude Cloud reads the CLI's login (`.credentials.json`) from it |
|
|
706
|
-
| `CLAUDE_CODE_OAUTH_TOKEN` | A Claude login token for Claude Cloud, used instead of the CLI's credentials file, by the relay (settings tab, **Check Usage**, archiving) and by its cloud workers. Under tmux the relay hands it to cloud workers only, through an owner-only file; a worker started without tmux inherits the relay's environment as it is |
|
|
707
|
-
| `CLAUDE_CODE_AUTO_COMPACT_WINDOW` | Overrides the Claude auto-compact window |
|
|
708
|
-
| `COPILOT_CLOUDFLARED_MODE`, `COPILOT_CLOUDFLARED_TOKEN`, `COPILOT_CLOUDFLARED_BINARY` | Override `cloudflaredTunnel.mode`, `.token`, and `.binary` |
|
|
709
|
-
| `COPILOT_WORKSPACE_ROOT_ALLOW_LIST` | Same as `workspaceRootAllowList` |
|
|
710
|
-
| `COPILOT_REMOTE_<FLAG>` | Pins a feature flag from the **Features** tab (`1`/`0`, `true`/`false`) |
|
|
711
|
-
|
|
712
|
-
Many internal names still say "copilot" (`COPILOT_WEB_RELAY_*`, `copilot.db`) from the project's earlier life; they apply to every runtime.
|
|
116
|
+
<table>
|
|
117
|
+
<tr>
|
|
118
|
+
<td width="62%" valign="top">
|
|
119
|
+
<a href="https://oar.sh/assets/shots/cfmail-steering.png?v=0.9.12"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/cfmail-steering.light.png?v=0.9.12"><img src="https://oar.sh/assets/shots/cfmail-steering.png?v=0.9.12" alt="A running Claude turn with a message steered into it mid-turn, the reply streaming with its tool calls, and the Steer button in the composer"></picture></a>
|
|
120
|
+
<br><sub>Send a message while the agent works, and it steers the running turn.</sub>
|
|
121
|
+
</td>
|
|
122
|
+
<td width="38%" valign="top">
|
|
123
|
+
<a href="https://oar.sh/assets/shots/usage-copilot-compact.png?v=0.9.12"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/usage-copilot-compact.light.png?v=0.9.12"><img src="https://oar.sh/assets/shots/usage-copilot-compact.png?v=0.9.12" alt="The GitHub Copilot card in Check Usage: premium requests and plan quota with reset dates, and the cost of the last turn"></picture></a>
|
|
124
|
+
<br><sub>What each plan has left, in one place.</sub>
|
|
125
|
+
</td>
|
|
126
|
+
</tr>
|
|
127
|
+
</table>
|
|
713
128
|
|
|
714
|
-
|
|
129
|
+
- **Watch a turn live**: the reply, the agent's thoughts and every tool call appear as they happen, and each sub-agent gets a bubble of its own. **Stop** is always one tap away ([While a turn runs](docs/web-ui.md#while-a-turn-runs)).
|
|
130
|
+
- **Steer or queue**: a message sent during a turn goes into it (Claude, Copilot) or waits behind it ([While a turn runs](docs/web-ui.md#while-a-turn-runs)).
|
|
131
|
+
- **Answer questions**: the agent asks on a card with one-click choices, checkmarks or free text, and waits for you ([Question cards](docs/web-ui.md#question-cards)).
|
|
132
|
+
- **Background work**: a task panel lists the commands and sub-agents that outlive a reply, each with its own **Stop** and its full record; a command's console shows its output live, says when it has gone quiet and counts a test run's passes and failures ([Background tasks](docs/web-ui.md#background-tasks)).
|
|
133
|
+
- **Choose how the agent works**: `ask`, `plan`, `agent` or `autopilot`, plus model and reasoning effort, per message ([Relay modes](docs/web-ui.md#relay-modes)).
|
|
134
|
+
- **Files and git**: browse the workspace, preview files, review git changes in a diff viewer, and publish a dev server as a preview link ([Files, git, and previews](docs/web-ui.md#files-git-and-previews), [preview servers](docs/preview-servers.md)).
|
|
135
|
+
- **Usage and context**: plan limits and credits of every provider, and what fills the model's context window ([Usage and context](docs/web-ui.md#usage-and-context)).
|
|
136
|
+
- **Your conversations everywhere**: the history lives on the relay, drafts follow you from device to device, and conversations can be searched, archived, grouped and pinned ([The conversation list](docs/web-ui.md#the-conversation-list), [drafts](docs/web-ui.md#drafts-across-devices), [session groups](docs/web-ui.md#session-groups), [pins](docs/web-ui.md#pinned-messages)).
|
|
137
|
+
- **Share** a conversation as a read-only link, hide single messages and the host's paths from it, and see when it was opened ([Sharing](docs/web-ui.md#sharing)).
|
|
138
|
+
- **On your phone**: install OAR as an app and get push notifications ([Notifications and the app](docs/web-ui.md#notifications-and-the-app)).
|
|
715
139
|
|
|
716
|
-
|
|
140
|
+
The full tour is in [Using the web UI](docs/web-ui.md); every setting and config key is in [Settings and configuration](docs/configuration.md). What changed in each release is in the [changelog](CHANGELOG.md), with [0.9.12](CHANGELOG.md#0912--2026-10-18) as the latest.
|
|
717
141
|
|
|
718
142
|
## Remote access
|
|
719
143
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
```
|
|
727
|
-
|
|
728
|
-
"
|
|
729
|
-
"
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
"
|
|
734
|
-
"
|
|
735
|
-
|
|
144
|
+
Out of the box the relay answers only on its own machine. There are three ways to reach it from elsewhere:
|
|
145
|
+
|
|
146
|
+
- **Same network**: `oar setup --lan` opens the relay to your LAN and prints a QR code for your phone.
|
|
147
|
+
- **Cloudflare Tunnel**: no server of your own and no open port. You need a Cloudflare account and `cloudflared` on the relay host ([how](docs/remote-access.md#optional-remote-internet-access-cloudflare-tunnel)).
|
|
148
|
+
- **SSH tunnel**: through a server you already run, behind your own HTTPS proxy ([how](docs/remote-access.md#optional-remote-internet-access-ssh-tunnel)).
|
|
149
|
+
|
|
150
|
+
```mermaid
|
|
151
|
+
flowchart LR
|
|
152
|
+
phone["๐ฑ Phone"]
|
|
153
|
+
subgraph host["Your computer"]
|
|
154
|
+
relay["OAR relay"]
|
|
155
|
+
cfd["cloudflared"]
|
|
156
|
+
end
|
|
157
|
+
cf["Cloudflare"]
|
|
158
|
+
vps["Your server<br/>HTTPS proxy"]
|
|
159
|
+
phone -- "same network<br/>oar setup --lan" --> relay
|
|
160
|
+
phone -- HTTPS --> cf --> cfd --> relay
|
|
161
|
+
phone -- HTTPS --> vps -- "SSH tunnel" --> relay
|
|
736
162
|
```
|
|
737
163
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
164
|
+
The relay keeps both tunnels running and reconnects them by itself. Beyond your own network, always go through HTTPS. Behind a reverse proxy of your own on another host, tell the relay to trust it ([how](docs/remote-access.md#behind-a-reverse-proxy)). The details are in [Remote access](docs/remote-access.md).
|
|
165
|
+
|
|
166
|
+
<a id="remote-relays"></a>
|
|
167
|
+
<a id="agent-sessions"></a>
|
|
168
|
+
<a id="watching-sessions"></a>
|
|
169
|
+
|
|
170
|
+
## Agents working together
|
|
171
|
+
|
|
172
|
+
- **Paired relays**: connect the OAR on your workstation with the OAR on a server. An agent on one can then read, prompt and start sessions on the other, once you mention that relay with `@`.
|
|
173
|
+
- **Agent sessions**: an agent hands parts of its task to new sessions on its own relay, waits for them and reads their results. It is off until you switch it on, the first session asks for your approval, and at most 4 run at once.
|
|
174
|
+
- **Watching sessions**: an agent subscribes to other sessions and is woken when a question waits, an error happens, or a reply arrives, instead of polling.
|
|
175
|
+
|
|
176
|
+
```mermaid
|
|
177
|
+
flowchart LR
|
|
178
|
+
you(("You")) --> A
|
|
179
|
+
subgraph r1["Relay on your workstation"]
|
|
180
|
+
A["Your agent's session"] -- "starts, waits for" --> B["A session it started"]
|
|
181
|
+
end
|
|
182
|
+
subgraph r2["Paired relay on a server"]
|
|
183
|
+
C["A session there"]
|
|
184
|
+
end
|
|
185
|
+
A -- "reads, prompts, waits" --> C
|
|
186
|
+
C -. "question, reply, error" .-> A
|
|
746
187
|
```
|
|
747
188
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
### Optional remote internet access (Cloudflare Tunnel)
|
|
751
|
-
|
|
752
|
-
An alternative to the SSH tunnel that needs no VPS and no inbound port: the relay
|
|
753
|
-
supervises Cloudflare's `cloudflared` binary, and Cloudflare carries your hostname down
|
|
754
|
-
to `127.0.0.1:3333`.
|
|
755
|
-
|
|
756
|
-
OAR does not include `cloudflared`; install it on the relay host first:
|
|
757
|
-
|
|
758
|
-
| System | Install |
|
|
759
|
-
| ------ | ------- |
|
|
760
|
-
| Windows | `winget install --id Cloudflare.cloudflared` |
|
|
761
|
-
| macOS | `brew install cloudflared` |
|
|
762
|
-
| Linux | Cloudflare's package repository (Debian, Ubuntu, RHEL): [pkg.cloudflare.com](https://pkg.cloudflare.com/) |
|
|
763
|
-
|
|
764
|
-
1. In your own Cloudflare Zero Trust account, create a tunnel and route a public hostname on
|
|
765
|
-
your zone to `http://localhost:3333` (or your `port`). That routing lives in Cloudflare, not
|
|
766
|
-
on this machine.
|
|
767
|
-
2. Put the tunnel's token into the config and restart the relay (`oar restart`).
|
|
768
|
-
|
|
769
|
-
```json
|
|
770
|
-
"cloudflaredTunnel": {
|
|
771
|
-
"mode": "managed",
|
|
772
|
-
"required": false,
|
|
773
|
-
"token": "<tunnel token>",
|
|
774
|
-
"binary": "",
|
|
775
|
-
"extraArgs": []
|
|
776
|
-
}
|
|
777
|
-
```
|
|
778
|
-
|
|
779
|
-
Environment overrides: `COPILOT_CLOUDFLARED_MODE`, `COPILOT_CLOUDFLARED_TOKEN`,
|
|
780
|
-
`COPILOT_CLOUDFLARED_BINARY`.
|
|
781
|
-
|
|
782
|
-
`localhostOnly` stays `true`: `cloudflared` connects outbound and nothing binds publicly.
|
|
783
|
-
The relay runs the `cloudflared` named in `cloudflaredTunnel.binary`, or else the one on
|
|
784
|
-
its `PATH`. When there is none, the relay starts as usual and the tunnel stays off: the
|
|
785
|
-
status dot's tooltip, `oar doctor` and the server log say that `cloudflared` is not
|
|
786
|
-
installed and how to install it. The relay looks again every minute and starts the tunnel
|
|
787
|
-
once `cloudflared` is there; restart the relay if it was installed into a folder that is
|
|
788
|
-
not on the relay's `PATH`. With `required: true` the queue stays paused for as long as
|
|
789
|
-
the tunnel is not connected, a missing `cloudflared` included. Connection drops reconnect with jittered exponential backoff,
|
|
790
|
-
and repeated fast exits (deleted tunnel or bad token) are reported as `auth-or-config`
|
|
791
|
-
instead of hammering Cloudflare.
|
|
792
|
-
|
|
793
|
-
The relay status dot turns **amber** while the Cloudflare tunnel is connected, so it is
|
|
794
|
-
obvious at a glance that the relay is reachable from the internet rather than only from
|
|
795
|
-
this machine. It stays green when no tunnel is configured and grey when the relay itself
|
|
796
|
-
is unreachable; a managed tunnel that has dropped, or could not start, keeps the dot green โ the relay
|
|
797
|
-
still answers locally โ and gives the reason in the tooltip.
|
|
798
|
-
|
|
799
|
-
### Session-worker path guard
|
|
800
|
-
|
|
801
|
-
Any public tunnel forwards *every* path on the bound hostname to port `3333`, including
|
|
802
|
-
the internal session-worker WebSocket endpoints. Requests to those paths that carry an
|
|
803
|
-
edge marker header (`cf-ray`, plus anything listed in `tunnelMarkerHeaders`) are rejected
|
|
804
|
-
with `403` on both the request and upgrade paths. Local workers connect over `127.0.0.1`
|
|
805
|
-
without such a header and are unaffected, and shared conversation links keep working
|
|
806
|
-
anonymously over the tunnel.
|
|
807
|
-
|
|
808
|
-
Shared links work unchanged through Cloudflare. Do not add a Cloudflare Cache Rule
|
|
809
|
-
covering `/api/shared/*` โ shared views poll for liveness and an edge-cached response
|
|
810
|
-
would pin viewers to a stale snapshot. Likewise, a Cloudflare Access application over the
|
|
811
|
-
bound hostname breaks share links unless it bypasses `/shared/*` and `/api/shared/*`.
|
|
812
|
-
|
|
813
|
-
## Remote relays
|
|
814
|
-
|
|
815
|
-
Several OAR relays can be paired, for example the one on your workstation and the one on a
|
|
816
|
-
server. An agent in any session can then work on the other relay when you ask it to: list and
|
|
817
|
-
read its sessions, prompt one, start a new one, wait for the reply, and pass a question the
|
|
818
|
-
remote agent asks back to you.
|
|
189
|
+
You stay in charge: per paired relay you decide whether agents may only read, also prompt, or do everything, and in the `ask` and `plan` modes every write asks you first. A subscription only notifies; it approves nothing.
|
|
819
190
|
|
|
820
|
-
|
|
821
|
-
open it with in the browser). OAR checks the address with its own token, or with a
|
|
822
|
-
`?token=` the pasted link carries, and asks for a token only when that fails. It reads the
|
|
823
|
-
other relay's name from its API. With **Also add this relay there** checked, it introduces
|
|
824
|
-
itself to the other relay using the address in **Public address**, so the pairing works in both
|
|
825
|
-
directions. When the two relays use different tokens, that introduction hands over this relay's
|
|
826
|
-
token, so the other relay's agents can then work here. Each side can remove the other on its own,
|
|
827
|
-
but removing a relay does not revoke a token it already holds: rotate the token for that. A relay
|
|
828
|
-
that is already paired keeps the address and token stored for it when it introduces itself again;
|
|
829
|
-
change those in **Settings โ Relays**.
|
|
191
|
+
<p><a href="https://oar.sh/assets/shots/pagewright-cross-relay.png?v=0.9.12"><picture><source media="(prefers-color-scheme: light)" srcset="https://oar.sh/assets/shots/pagewright-cross-relay.light.png?v=0.9.12"><img src="https://oar.sh/assets/shots/pagewright-cross-relay.png?v=0.9.12" alt="A session watching two sessions on a paired relay: a reply arrives as a relay-event row, and after a short outage the events the other relay kept arrive as one replayed row" width="720"></picture></a></p>
|
|
830
192
|
|
|
831
|
-
|
|
832
|
-
is empty, the machine's hostname is used.
|
|
833
|
-
|
|
834
|
-
**Mention a relay to unlock it.** Agents can see which relays are paired, but a relay stays
|
|
835
|
-
locked in a conversation until you mention it in one of your messages: type `@` and pick it
|
|
836
|
-
from the list, or write its name or its host name. An IP address or `localhost` never counts as a
|
|
837
|
-
host name; a relay whose name is itself an address is unlocked only with a leading `@`. The
|
|
838
|
-
mention unlocks that relay for the rest of
|
|
839
|
-
the conversation, whatever prompts arrive in it later.
|
|
840
|
-
|
|
841
|
-
**Agents can answer each other.** When an agent on a paired relay writes to a conversation, that
|
|
842
|
-
relay is open to the conversation from then on, within what **Agents may** allows, so the agent
|
|
843
|
-
that was asked can answer, ask back or report later. A prompt from an agent never unlocks any
|
|
844
|
-
other relay. A prompt that already crossed two relays is not passed on to a third one unless you
|
|
845
|
-
unlocked that relay yourself; reading and waiting are never limited. When the agent of a
|
|
846
|
-
conversation has sent 30 prompts to agents on other relays without a message from you, the next
|
|
847
|
-
one asks you first with a question card; **Allow** starts the count again.
|
|
848
|
-
|
|
849
|
-
**What agents can do.** Every provider gets the same `remote_relay` tool (Claude, Cursor and
|
|
850
|
-
Copilot directly; Grok and the Copilot extension engine through OAR's MCP server). Sessions get it
|
|
851
|
-
while at least one relay is paired or [agent sessions](#agent-sessions) are switched on. Per paired
|
|
852
|
-
relay, **Agents may** limits it to *read only*, *read and prompt* (existing sessions) or *full*
|
|
853
|
-
(also create sessions, answer questions, stop turns, archive). In the *ask* and *plan* relay
|
|
854
|
-
modes, every write action first asks you with a question card. For a session it starts, an agent
|
|
855
|
-
can set the provider, model, relay mode and reasoning effort; what it leaves out follows the
|
|
856
|
-
session it works in, as far as the other relay offers it. A [Claude Cloud](#claude-cloud) session
|
|
857
|
-
is started with `provider: "claude-cloud"`, a `repo` (a GitHub URL or `owner/repo`, for example
|
|
858
|
-
`example-org/sample-repo`) and an optional `branch` instead of a folder; without a model it gets
|
|
859
|
-
the default model of the other relay's Claude Cloud tab. Claude Cloud must be switched on there.
|
|
860
|
-
A cloud session that exists can be read, prompted, waited for and stopped like any other.
|
|
861
|
-
|
|
862
|
-
Two read actions help an agent plan: `usage` says what each provider's plan has left on a relay
|
|
863
|
-
(Cursor's spend against its limit, Claude's windows and whether a usage limit has paused turns,
|
|
864
|
-
Copilot and Grok where they are tracked; never account names, addresses or tokens), and
|
|
865
|
-
`list_sessions` / `read_session` give each session's `state` (`running_turn`, `background_only` or
|
|
866
|
-
`idle`) with its background agents and shell tasks.
|
|
867
|
-
|
|
868
|
-
A `send`, `create_session` or `wait` call waits for the reply for as long as the agent asks, up to
|
|
869
|
-
**Longest wait per tool call** of the relay the agent runs on (10 minutes unless you changed it,
|
|
870
|
-
see [Agent sessions](#agent-sessions)). When the time is up the agent gets what there is so far
|
|
871
|
-
and can call `wait` again.
|
|
872
|
-
|
|
873
|
-
When an agent prompts a session on another relay, that relay shows a **โ from โฆ** badge with the
|
|
874
|
-
sending relay, session and model on the message, and marks sessions an agent created in the
|
|
875
|
-
conversation list. The remote agent sees a one-line header saying that another agent is talking
|
|
876
|
-
to it. Turns started this way do not send "reply ready" notifications on the remote relay;
|
|
877
|
-
question cards still do. **Accept prompts from other relays' agents** in **Settings โ Relays**
|
|
878
|
-
switches incoming agent prompts off.
|
|
879
|
-
|
|
880
|
-
The calls go through your own relay, which holds the other relay's token: agents never see a
|
|
881
|
-
token. Remote addresses must use `https://`; plain `http://` is accepted only for loopback (an
|
|
882
|
-
SSH port forward, for example) and private network ranges.
|
|
883
|
-
|
|
884
|
-
### Agent sessions
|
|
885
|
-
|
|
886
|
-
The same `remote_relay` tool can also work on the relay the agent itself runs on. An agent can
|
|
887
|
-
then hand parts of its task to other sessions: it starts them, waits for them and reads their
|
|
888
|
-
replies. Every session it starts is an ordinary conversation in your list. No relay has to be
|
|
889
|
-
paired for this.
|
|
890
|
-
|
|
891
|
-
**Switching it on.** It is off by default. Turn on **Settings โ Relays โ Agent sessions โ
|
|
892
|
-
Agents may start and use sessions on this relay**. From then on this relay is the first entry of
|
|
893
|
-
the relay list an agent sees, marked as its own; the agent names it by its **Relay name** or as
|
|
894
|
-
`this`. It needs no mention, and **Agents may** and **Accept prompts from other relays' agents**
|
|
895
|
-
do not apply to it. On this relay an agent can do what *full* allows on a paired one: list and
|
|
896
|
-
read every session here, prompt one, start one, wait for it, answer its question, stop its turn
|
|
897
|
-
and archive it. Switching the setting off closes this relay to the tool again.
|
|
898
|
-
|
|
899
|
-
**The rules.**
|
|
900
|
-
|
|
901
|
-
- **Approval once per conversation.** The first time the agent of a conversation wants to start
|
|
902
|
-
a session here, a question card (**Agent sessions**) shows the provider, the folder or
|
|
903
|
-
repository and the prompt. **Allow** covers every session that conversation's agent starts
|
|
904
|
-
later, also after a relay restart; **Deny** refuses that one call. In the *ask* and *plan*
|
|
905
|
-
relay modes, every other write action still asks, as it does for a paired relay.
|
|
906
|
-
- **At most 4 at work.** Of the sessions one conversation's agent started, 4 may have a turn
|
|
907
|
-
queued or running at the same time. A fifth is refused until one of them has finished.
|
|
908
|
-
- **One level only.** A session that an agent created, here or from a paired relay, cannot start
|
|
909
|
-
sessions on this relay.
|
|
910
|
-
- **Not on itself.** An agent cannot prompt, stop, archive, wait for or answer the conversation
|
|
911
|
-
it runs in.
|
|
912
|
-
- The count of 30 prompts without a message from you (see above) includes prompts to sessions
|
|
913
|
-
on this relay.
|
|
914
|
-
|
|
915
|
-
**What it can start.** A session with any provider that is enabled on this relay (Copilot,
|
|
916
|
-
OpenAI, Claude, Cursor, Grok or Claude Cloud; not an OpenAI Image chat): in a folder
|
|
917
|
-
(the relay's default folder when the agent names none), or a [Claude Cloud](#claude-cloud) chat
|
|
918
|
-
with `provider: "claude-cloud"`, `repo` and an optional `branch`. A new session knows nothing of
|
|
919
|
-
the conversation it was started from. Sessions an agent starts use this relay's accounts and
|
|
920
|
-
count against their usage.
|
|
921
|
-
|
|
922
|
-
**In the conversation list.** A session an agent on this relay started carries **via agent ยท
|
|
923
|
-
โtitleโ** in the sidebar and under the title in the header, with the title of the conversation
|
|
924
|
-
the agent runs in; clicking it opens that conversation while it is still in the list. The
|
|
925
|
-
agent's prompts carry the same marker, with its model, as a badge on the message. The relay never
|
|
926
|
-
archives these sessions by itself: they stay in the list until you archive or delete them, or the
|
|
927
|
-
agent archives one with the tool.
|
|
928
|
-
|
|
929
|
-
**Longest wait per tool call.** The slider under the switch sets how long one `send`,
|
|
930
|
-
`create_session` or `wait` call may wait for a reply: 10 minutes by default, from 2 to 60 minutes
|
|
931
|
-
in steps of one minute. The agent can call `wait` again to keep waiting. The limit also applies
|
|
932
|
-
to this relay's agents when they wait for a session on a paired relay, so the slider can be moved
|
|
933
|
-
whether or not the switch above it is on. A turn that waits is still subject to **Max turn duration**
|
|
934
|
-
under **General** (60 minutes by default), which does not know about the wait.
|
|
935
|
-
|
|
936
|
-
### Watching sessions
|
|
937
|
-
|
|
938
|
-
An agent can watch other sessions instead of polling them: with `remote_relay`'s `subscribe` it
|
|
939
|
-
asks to be woken when something happens there. It works for every provider, on this relay (with
|
|
940
|
-
[agent sessions](#agent-sessions) switched on) and on a paired one.
|
|
941
|
-
|
|
942
|
-
**What wakes it.** A question waiting for an answer (with its options), an error (a failed turn,
|
|
943
|
-
the usage limit, a worker that died), a reply (with a preview), a background agent or shell task
|
|
944
|
-
that finished or failed, a session that went quiet while working (15 minutes by default), and the
|
|
945
|
-
moment nothing runs any more in the watched sessions. A subscription names sessions, or `all`
|
|
946
|
-
for every session, later ones included; the watcher's own conversation is never watched. It can
|
|
947
|
-
filter replies and task results by a regular expression, end after it fired once, and add a
|
|
948
|
-
heartbeat while work runs.
|
|
949
|
-
|
|
950
|
-
**What it looks like.** OAR writes a short message into the watcher's conversation: a new turn
|
|
951
|
-
when the watcher is idle, a steer into the running turn on Claude and Copilot's SDK engine, the
|
|
952
|
-
next turn otherwise. The message says it is automated, not from you, and that it approves
|
|
953
|
-
nothing; it shows as a compact row, never as one of your messages. Events within 30 seconds come
|
|
954
|
-
as one message; past 20 wake-ups an hour the rest comes as a digest every ten minutes, while
|
|
955
|
-
questions and errors still come at once.
|
|
956
|
-
|
|
957
|
-
**What it may do.** A subscription only notifies. It approves nothing and answers
|
|
958
|
-
nothing; what an event asks for is decided as before, by you or by the agent within what
|
|
959
|
-
it may do anyway. The first subscribe of a conversation, and any to `all`, asks you on an approval
|
|
960
|
-
card naming the sessions (and the relay); `transfer_subscriptions`, which hands every subscription
|
|
961
|
-
of an old watcher to a new one, always asks.
|
|
962
|
-
|
|
963
|
-
**Where you see it.** The watcher's header shows **watching N sessions**; the chip opens the list
|
|
964
|
-
of its subscriptions with an **Unsubscribe** button each. A watched session shows a **watched**
|
|
965
|
-
badge.
|
|
966
|
-
|
|
967
|
-
**Lifetime.** Subscriptions survive a restart and end on unsubscribe, when the watcher or the
|
|
968
|
-
watched session is archived, after firing once (`once`), or, for a paired relay, when the pairing
|
|
969
|
-
is removed.
|
|
970
|
-
|
|
971
|
-
**On a paired relay** the relay must be unlocked in the conversation and allow at least reading,
|
|
972
|
-
and the other relay must accept other relays' agents; nothing is asked there. This relay fetches
|
|
973
|
-
the events every few seconds over the pairing (a pairing in one direction is enough), and their
|
|
974
|
-
lines start with the other relay's name. If the link drops, the other relay keeps what happens
|
|
975
|
-
(up to 500 events per subscription, for 7 days) and delivers it as one row tagged **replayed** once
|
|
976
|
-
it answers again, questions and errors first, between "link lost" and "link restored". A relay
|
|
977
|
-
that runs an older OAR answers that it needs an update.
|
|
193
|
+
How pairing, permissions and limits work is in [Agents working together](docs/agents-together.md).
|
|
978
194
|
|
|
979
195
|
## Security notes
|
|
980
196
|
|
|
981
|
-
- The
|
|
982
|
-
-
|
|
983
|
-
-
|
|
984
|
-
-
|
|
985
|
-
-
|
|
986
|
-
- Files the relay serves (workspace and drive files, attachments) are never run as pages on its origin: HTML and XML go out as plain text, every file carries `nosniff` and a `Content-Security-Policy` with `sandbox`. An SVG keeps its type so it can be previewed, and the sandbox denies it script and an origin should it be opened as a page. A PDF is the one exception, served without `sandbox` (browsers refuse to show a sandboxed PDF in their built-in viewer, and PDF viewers run no document script) and framable only by the relay's own origin.
|
|
987
|
-
- A [paired relay](#remote-relays) holds a token that opens the other relay completely. The per-relay "Agents may" limit and the "Accept prompts from other relays' agents" switch are honoured by OAR's own traffic, but anyone holding the token can still use the full API: the token is the real boundary. A token entered for a paired relay is stored like the API keys below and never sent to browsers or agents.
|
|
988
|
-
- API keys you enter (OpenAI, Cursor) are stored in the relay database on the host and never sent to browsers. Claude and Grok credentials stay with their CLIs on the host.
|
|
989
|
-
- Claude Cloud, when you switch it on, reads the Claude CLI's login and uses it against Anthropic API endpoints that are not a documented public API. The token is only read and held in memory, and goes to `api.anthropic.com` only (see [Claude Cloud](#claude-cloud)). A cloud agent works in Anthropic's sandbox, not on your host.
|
|
990
|
-
- OAR has no telemetry. Its only request to oar.sh is the update check, which is off until you enable it.
|
|
991
|
-
|
|
992
|
-
## Troubleshooting
|
|
197
|
+
- **The access token is the key to everything.** Whoever holds it, or a URL carrying `?token=`, can have your agents run commands on the host. Treat it like a password; `oar setup --new-token` replaces it and signs every device out.
|
|
198
|
+
- **OAR adds reach, not a sandbox.** Agents act with the permissions of the user the relay runs as.
|
|
199
|
+
- **Local by default.** The relay answers only on its own machine until you change that. Beyond your network, use one of the [tunnels](#remote-access).
|
|
200
|
+
- **Public links are public.** Anyone with a shared-conversation or preview link can open it without signing in.
|
|
201
|
+
- **No telemetry.** The only request to oar.sh is the update check, and it is off until you turn it on.
|
|
993
202
|
|
|
994
|
-
|
|
995
|
-
| ---------------------------------- | -------------------------------------------------------------------------------- |
|
|
996
|
-
| Banner says *CLI is offline* | No session worker has reported in during the last 10 seconds, which can be normal on an idle relay. Send a message: the relay starts that conversation's worker, and the banner clears once it connects. If it stays, check `/api/status` and the worker's `worker-<session>.log` in the log directory |
|
|
997
|
-
| `oar copilot` says the GitHub CLI is missing | It runs `gh copilot` beside the relay. Install the GitHub CLI, or [run only the relay](#start-the-relay) |
|
|
998
|
-
| WSL: the browser on Windows shows another relay, or refuses the token | In WSL's default networking a port can be free in the distro while a Windows program listens on it; `localhost:<port>` in a Windows browser then reaches that program. `oar setup` picks a port that is free on both sides, and `oar status`, `oar start` and `oar doctor` warn when Windows holds the relay's port: choose another with `oar setup --port <port>` |
|
|
999
|
-
| Settings refuses the **SDK** engine | Install or upgrade the Copilot CLI, run `copilot` once, and restart the relay (see [engine choice](#github-copilot--engine-choice)) |
|
|
1000
|
-
| Messages stuck pending | Only one relay may run per data directory (a second one exits on the singleton lock), and only one process may own port `3333`. `oar doctor` shows the config and database in use |
|
|
1001
|
-
| Wrong or old model list | **๐ค Select Models โ Refresh** reruns discovery; `/api/model-variants` shows the Copilot catalog's `source` and `refreshedAt` |
|
|
1002
|
-
| Clarification card not progressing | Answer via the web card; the turn resumes once the question status becomes `answered` |
|
|
1003
|
-
| File links fail | Verify auth token/cookie and that paths are inside allowed workspace/drive roots |
|
|
1004
|
-
| Claude missing from New Chat | Enable it in **โ๏ธ Settings โ Providers โ Claude**; the toggle is off by default |
|
|
1005
|
-
| Claude reply says it cannot authenticate | Press **Claude settings** on the failed reply, then **Relogin** (or run `claude` on the relay host), and retry the turn |
|
|
1006
|
-
| Claude Cloud missing from New Chat | Enable it in **โ๏ธ Settings โ Providers โ Claude Cloud**; it is off by default and needs a Claude login on the relay host |
|
|
1007
|
-
| Claude Cloud reply says GitHub is not connected, or the Claude GitHub app has no access | Connect GitHub to the Claude account at [claude.ai/connect-github](https://claude.ai/connect-github), or add the repository to the Claude GitHub app's repository access on GitHub; then send the message again |
|
|
1008
|
-
| New Chat says *No cloud environment is set* | Choose one in **โ๏ธ Settings โ Providers โ Claude Cloud**; an account without any gets its default one when you open claude.ai/code once |
|
|
1009
|
-
| Grok reply says the CLI was not found | Press **Install Grok CLI** on the failed reply, or install it from **โ๏ธ Settings โ Providers โ Grok**; no relay restart is needed afterwards |
|
|
1010
|
-
| Grok reply says authentication failed | Press **Sign in to Grok** on the failed reply and confirm the device code in a browser |
|
|
1011
|
-
| Long turn requeued unexpectedly | Raise or clear **Max turn duration** in Settings (0 = no limit) |
|
|
1012
|
-
| Background agent or shell stopped on its own | It reached the **Background task timeout** (default 4 h); raise it or set 0 for no limit |
|
|
1013
|
-
| A conversation will not delete | It is still working: a running turn, one waiting on a question card or approval, or live background tasks. Stop it, then delete |
|
|
1014
|
-
| A conversation seems wedged | **โ ๏ธ Kill session** in the `โฏ` menu stops its worker; retry the turn or send a new message |
|
|
1015
|
-
| **๐ Restart web relay** fails with *localhost-only* | The restart endpoint accepts loopback connections only: use it on the relay host or through a tunnel, not over a direct LAN connection |
|
|
1016
|
-
| `npm install -g @oar-sh/oar` fails with `EACCES` | npm's global folder needs root (a distribution or NodeSource Node.js). Do not use `sudo`; run the installer (`curl -fsSL oar.sh/install \| sh`), which installs into `~/.oar/npm` instead |
|
|
1017
|
-
| The relay does not start after an install with npm 12 (a `better-sqlite3` error in `server-err.log`) | npm 12 skipped the install scripts of OAR's native dependencies. Reinstall with `npm install -g --allow-scripts=better-sqlite3,koffi @oar-sh/oar` |
|
|
1018
|
-
| The Cloudflare tunnel stays off and the status dot's tooltip says `cloudflared is not installed` | OAR runs the `cloudflared` on the relay host and ships none. Install it (see [Cloudflare Tunnel](#optional-remote-internet-access-cloudflare-tunnel)); the tunnel starts within a minute |
|
|
1019
|
-
| `npm install -g @oar-sh/oar` fails with node-gyp or prebuild errors | `better-sqlite3` has no prebuilt binary for your platform; install a C/C++ build toolchain and Python, then retry |
|
|
1020
|
-
| No usage line under a reply | Expected for OpenAI, Claude, Claude Cloud, Cursor, and Grok turns; only Copilot turns record plan usage |
|
|
203
|
+
How keys, cookies, served files, paired relays and Claude Cloud's use of the Claude login are handled: [Security notes](docs/security.md).
|
|
1021
204
|
|
|
1022
|
-
##
|
|
205
|
+
## Troubleshooting
|
|
1023
206
|
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
207
|
+
| Symptom | What to do |
|
|
208
|
+
| ------- | ---------- |
|
|
209
|
+
| A runtime is missing from **New Chat** | Turn it on in **โ๏ธ Settings โ Providers**; all of them except Copilot are off until you do |
|
|
210
|
+
| A reply says a CLI is missing or signed out | Press the button on the failed reply (**Install Grok CLI**, **Sign in to Grok**, **Claude settings**) |
|
|
211
|
+
| Banner says *CLI is offline* | Normal on an idle relay: send a message, and the banner clears once the conversation's worker connects |
|
|
212
|
+
| A conversation seems wedged | **โ ๏ธ Kill session** in the `โฏ` menu, then retry or send a new message |
|
|
213
|
+
| `npm install -g @oar-sh/oar` fails with `EACCES` | Do not use `sudo`; run the installer, which installs into your home directory |
|
|
214
|
+
|
|
215
|
+
`oar doctor` prints the version, paths, port and provider CLIs in use. More symptoms are in [Troubleshooting](docs/troubleshooting.md).
|
|
216
|
+
|
|
217
|
+
<a id="settings-and-configuration-reference"></a>
|
|
218
|
+
<a id="repository-layout"></a>
|
|
219
|
+
|
|
220
|
+
## Documentation
|
|
221
|
+
|
|
222
|
+
| Guide | What is in it |
|
|
223
|
+
| ----- | ------------- |
|
|
224
|
+
| [Installing and running OAR](docs/install.md) | Prerequisites, every install method, starting the relay, the `oar` command, files, updating |
|
|
225
|
+
| [Providers](docs/providers.md) | Each runtime in detail, installing provider CLIs from the relay, models |
|
|
226
|
+
| [Using the web UI](docs/web-ui.md) | Conversations, running turns, question cards, background tasks, files, usage, sharing, the menu |
|
|
227
|
+
| [Settings and configuration](docs/configuration.md) | Settings, `config.json`, environment variables, stuck-turn detection |
|
|
228
|
+
| [Remote access](docs/remote-access.md) | SSH and Cloudflare tunnels, a reverse proxy on another host, the session-worker path guard |
|
|
229
|
+
| [Agents working together](docs/agents-together.md) | Paired relays, agent sessions, watching sessions |
|
|
230
|
+
| [Security notes](docs/security.md) ยท [Troubleshooting](docs/troubleshooting.md) | The full lists |
|
|
231
|
+
| [Preview servers](docs/preview-servers.md) ยท [Copilot CLI with your own key](docs/copilot-cli-byok.md) | Publishing dev servers; BYOK notes |
|
|
232
|
+
| [DEVELOPING.md](DEVELOPING.md) ยท [server/README.md](server/README.md#api-reference) ยท [CHANGELOG.md](CHANGELOG.md) | Development, tests, relay internals and the repository layout; the HTTP API; release notes |
|
|
233
|
+
|
|
234
|
+
The most complete guide, in six languages, is [oar.sh/docs](https://oar.sh/docs/).
|