Skip to content

Releases: oar-sh/oar

OAR 0.9.20

Choose a tag to compare

@materia79 materia79 released this 30 Oct 05:14

OAR 0.9.20

Every plan card gets an Approve plan button that approves the plan without starting the implementation and keeps the session in plan mode, and a session can be locked in plan mode so agents cannot take it out. Check Usage shows the tokens of every turn for every provider: input, output, cache writes and cache reads. The relay backs up its database before a new version's migrations and keeps the last two copies. A new database is oar.db; an existing install keeps running on copilot.db. Under the systemd service a restart hands the relay to systemd with its new code, waits for running turns and keeps session workers, and oar service works in a git checkout. A paired relay's approval cards in the Inbox say what they are about, and a card a turn there waits on pushes once to your devices.

Plan cards

  • "Approve plan" on every plan card. The first button of every provider's card, also on cards that were waiting when the relay was updated. It marks the plan approved and queues exactly "Plan approved by the user. Do not implement. Finish only the plan-only steps you were given, then stop." That one turn runs in agent mode (plan mode blocks writes, and the plan doc may need a commit); the session stays in plan mode, so the next message plans again.
  • Plan-only sessions (planOnly). An optional lock, set only when asked: relay_tool create_session or update_session with planOnly: true, or the owner's switch "Plan only: agents can't take this session out of plan mode" in the context modal. An agent's send or update_session that names another mode gets HTTP 409, code plan_only; the owner still changes the mode freely, and the mode select shows "Plan 🔒". On such a session the card recommends "Approve plan" and asks before "Implement in autopilot", "Implement with autopilot fleet" and "Stop here and prompt myself". list_sessions and read_session show planOnly: true.
  • No plan summary in a card's follow-up. "Implement in autopilot", "Implement with autopilot fleet" and "Stop here and prompt myself" queue only their line.
  • relay_tool send without mode leaves the target's mode alone. It used to run the target's turn in the calling session's mode. Name mode when a turn should run in a given one.
  • Switching between plan mode and a writing mode during a running turn queues the message instead of steering it in; the composer reads "Queue" for it. Messages in a mode on the same side steer in as before.
  • Relay event board_settled. A session's subscribers hear when one of its plan cards is settled, "Stop here" included. It is one of the default event types, also for subscriptions stored with the 0.9.19 default.
  • Plan cards in the Inbox. Each session's newest pending plan card, with the plan folded and the card's own buttons; cards settled in the last day show what was chosen. A paired relay's Inbox shows their title only, with "Open there".

Tokens in Check Usage

  • Tokens per turn for every provider. Every tab gets a Tokens section (today, this month, all time) and Tokens by model, this month, with fresh input, output, cache writes and cache reads apart and the share of input the cache served. A figure a provider does not report reads "—" with the reason in the section's note. Copilot turns on your own OpenAI key show as "Tokens — own OpenAI key". Both sections open expanded; two model ids with one name are one row, their tokens added up.
  • About OAR shows each provider's tokens of all time, Claude, Claude API and DeepSeek included.
  • Kept per turn and per day. Each turn's tokens are kept per run and model with the chat and go when it is deleted; the daily sums stay. The Claude API and DeepSeek days from before the upgrade are copied in once (migration 0036).
  • The DeepSeek card's "Tokens by model" is now "Priced tokens by model", and the Claude API card's "Tokens by model" is replaced by the Tokens sections every tab gets. Cache writes are no longer lost for the Claude family, Copilot, Cursor and Grok, and the Claude API spend no longer counts a turn twice when Claude Code reported a result without per-model usage.

The database file and its backups

  • The relay backs up its database before a new version's migrations. At the first start of each new version (in a git checkout: of each new commit) it copies the database into backups/ in the state root (~/.oar/backups, %APPDATA%\oar\backups; server/backups/ in a checkout), as one checked file such as oar-0.9.19-20261103-091500-pre-update.db. It keeps the last two (dbBackups.keep in config.json; dbBackups.enabled: false turns it off, dbBackups.dir moves the folder) and deletes only files it wrote itself. When the disk would keep less than max(1 GiB, 5 %) free, or the folder holds a DO_NOT_TOUCH file, the copy is skipped with a warning and the start goes on. Plain restarts take no copy.
  • oar backup [--reason <text>] copies the database while the relay runs, into the same folder with the same name and rotation.
  • About and oar doctor show the database file by its full path with its size, and the backups: the last one, how many are kept, and the folder.
  • A new database is oar.db (with oar.db-wal and oar.db-shm). An existing install keeps running on copilot.db; nothing is renamed, and oar doctor and About show which file a relay runs on.
  • oar.db and copilot.db in one data folder. The start reads both. A copilot.db that is not newer, is empty, or holds only start-up settings is set aside as copilot.db.older-<time>, never deleted, and the relay runs on oar.db. A copilot.db with newer work, or each newer somewhere, stops the start (exit code 78) with both files named and nothing changed. An oar.db-wal or oar.db-shm without oar.db stops the start too.
  • Migrations and npm run deepseek:import run by hand never create an empty database, and oar uninstall --purge says it deletes the database backups with the state root.

The systemd service

  • A restart under the service goes through systemd with the new code. 🌄 Restart web relay, the Update button, oar update and oar restart hand the restart to systemd once running turns are done, which starts a fresh supervisor and runtime from the code on disk; before, only the runtime was relaunched. oar stop and oar restart under the service wait for running turns; --now goes through systemctl --user at once. Session workers run in scopes of their own, so a stop or restart of the service no longer ends them.
  • The unit restarts a failing relay with a backoff and never gives up. The supervisor relaunches the first two crashes itself; then systemd starts it again after 2 seconds, with longer waits up to 5 minutes. The unit has KillMode=mixed.
  • oar service works in a git checkout on Linux. node bin/oar.js service install writes a unit that runs node server/server.js in the checkout, and node bin/oar.js start|stop|restart|status go through it.
  • Hand-made units are left as they are. A unit OAR did not write for this install is named and kept by oar service install, oar setup --start and oar service remove; --replace replaces or removes it, keeping a copy as oar.service.bak. oar service status says whose the unit is, lists the drop-ins in oar.service.d/, and says when lingering is off.

Inbox and paired relays

  • Other relays' approval cards say what they are about: "New session · the session waits", then the relay, the kind and the title, still with "Open there" only. The agent's prompt, answer or question never leaves its relay.
  • The badge is current within about 20 s. Every relay checks its paired relays about every 20 s, even with no browser open.
  • One push for a card a turn waits on. Its own relay pushes as before; when that reached none of your devices, the first paired relay with push on that checks it pushes instead, with no answer buttons; the tap opens the session there. It follows the device's "questions" toggle and notification settings.
  • An open fold in the Inbox stays open until you close it or its item leaves the list; the same for a question's Details on its card in the session.

Fixed

  • Archiving or deleting a chat whose session worker is gone no longer fails with "Couldn't stop this conversation's session". A worker whose process has ended counts as stopped; when a stop does fail, the relay log says why.

Upgrade notes

  • No new dependencies, and the Node.js requirement is unchanged (22.13 or newer). Install and update with npm's install scripts allowed, as since 0.9.14.
  • Migrations 0035 and 0036 add conversations.plan_only and the tables turn_token_usage and token_usage_days. They run at the first start of 0.9.20, after the backup below.
  • The first 0.9.20 start backs up the database into backups/ in the state root before the migrations run. After oar update or a git pull its name carries the running version and says pre-update-from-unknown, such as oar-0.9.20-20261103-091500-pre-update-from-unknown.db, though it holds the data of the version before; after an in-app update it carries the version before. It needs free space for one more copy of the database; oar doctor shows the result.
  • Nothing to do for the new database name. A relay that ran on copilot.db goes on running on it. The CHANGELOG has the hand-rename steps for those who want the new name.
  • Under the systemd service, run oar service install after updating (node bin/oar.js service install in a checkout) to get the new unit. A hand-made unit is reported and kept; oar service install --replace puts OAR's in its place, keeping a copy as oar.service.bak. The supervisor of 0.9.19 keeps running until the service restarts once by systemd: at an idle moment, run oar restart --now. That restart ends running turns once, and session workers s...
Read more

OAR 0.9.19

Choose a tag to compare

@materia79 materia79 released this 27 Oct 06:19

OAR 0.9.19

A relay that runs out of memory is now restarted instead of staying down. It starts with a heap limit, set with heapLimitMb in config.json, and writes one heap snapshot when it nears that limit. Agent sessions can use the providers a later relay update adds, without a restart of their own, and Copilot refuses another provider's model id before it creates anything.

A relay that runs out of memory is restarted

  • It no longer stays down. A relay runtime that ran out of memory ended the relay for good: its supervisor took the out-of-memory abort for a clean stop and exited 0, which systemd does not restart. The runtime is now relaunched like any crash.
  • A heap limit. The runtime starts with a heap limit of 60 % of RAM, between 2048 and 8192 MB. Set your own with heapLimitMb in config.json.
  • One heap snapshot near the limit, written to diagnostics in the data directory. A heap snapshot holds the relay's auth token and API keys: never share one as it is.
  • The memory in the status log every 10 minutes, and when the heap passes 80 % of the limit.

Agents and providers

  • relay_tool takes any provider id. Agent sessions started before a relay update refused the providers the update added (such as deepseek and claude-api) in create_session and send. The tool now takes any provider id; the relay checks it against its current list and names that list when it refuses one.
  • Copilot refuses another provider's model id before creating anything. A Copilot session given another provider's model id (such as claude-opus-5-5 for Copilot's claude-opus-5.5) was created and then refused with CURSOR_MODEL_REQUIRES_NEW_CONVERSATION. Copilot now refuses such an id with COPILOT_MODEL_UNAVAILABLE and the close match before anything is created, and a first prompt refused after create_session made the session names that session.

Upgrade notes

  • No new dependencies, no migrations, and the Node.js requirement is unchanged (22.13 or newer). Install and update with npm's install scripts allowed, as since 0.9.14.
  • Restart oar once after updating. The heap limit, the heap snapshot and the relaunch after an out-of-memory abort start only when the oar process itself starts on 0.9.19; the in-app update and a restart from the web UI only relaunch the runtime. Under systemd run oar restart, otherwise oar stop and then oar start.
  • Agent sessions started before 0.9.19 keep their provider list: their workers keep running through the update, with the relay_tool they started with. That list is the one 0.9.19 has, so nothing changes now; it lacks the providers a later update adds until the session's worker restarts, for example after ☠️ Kill session in the ⋯ menu.

All the details are in the CHANGELOG.

Install / update: curl -fsSL oar.sh/install | sh · irm oar.sh/install.ps1 | iex · npm i -g @oar-sh/oar --allow-scripts=@oar-sh/oar,better-sqlite3,koffi · Docs: https://oar.sh

OAR 0.9.18

Choose a tag to compare

@materia79 materia79 released this 26 Oct 04:41

OAR 0.9.18

Claude chats can now run on a Claude Console API key. Claude API is a provider beside your subscription, with an optional monthly spend cap and a card in Check Usage with the estimated spend. A Claude chat can switch between the subscription and the key and keep its Claude Code session, also when it is paused at the usage limit. The relay's agent tool is now called relay_tool. And DeepSeek and Claude API chats now start with all hooks off.

Claude API: Claude chats on your API key

  • Add a key, start a chat. ⚙️ Settings → Providers → Claude API holds a Claude Console API key, the switch, the default model and an optional monthly cap in US dollars. Usage is billed to the Console organisation the key belongs to. New Chat offers Claude API, Select Models has a Claude API tab, and its chats show a gold Claude API pill.
  • The key stays on the relay host. It is never shown again: the tab only says that one is saved. Any sk-ant- Console key is taken; Claude login and session tokens and Admin keys are refused when you save. A key Anthropic itself refuses stays saved, and the tab's status line says so.
  • The key's own models. The relay lists them from Anthropic when you save the key, when you switch Claude API on again, and on Refresh models. Until then it offers the Claude tab's models.
  • One set of Claude settings. Commit attribution, the background command limit, the effort levels and the compaction window stay on the Claude tab, shared by both.
  • Clear failures. A turn that Claude API refuses or could not run ends with the buttons that fit the reason: Claude API settings, Switch to subscription, Add funds, Console billing or Console limits. When the relay refuses to start a Claude API chat (the monthly cap, no key, switched off), New Chat stays open with the reason and Start on subscription.

Switch between your subscription and the key

  • A Subscription | API key toggle under a Claude chat's lock note, while Claude API is on with a saved key. The chat keeps its Claude Code session. The toggle says what a pending switch waits for, and why a side cannot be chosen.
  • The switch applies from the next turn. A running turn finishes on the billing it started on; messages already queued run on the new one. The relay restarts the chat's Claude Code between turns, and waits while a turn, a question, a compaction or a background task is still running. The transcript notes each switch, and the first turn on the key has no prompt cache, so it costs more.
  • At the usage limit, the banner of a paused subscription chat offers Switch this chat to API key, and the paused turn carries on on the key at once. Nothing switches by itself.
  • Agents can switch too. relay_tool send takes provider (claude or claude-api) for a Claude session, and switches together with the message, in one call: a refused switch sends nothing, and a refused message switches nothing. The approval card says "Switches billing to API key".
  • The switch is refused, with the reason, when the key is missing or Claude API is off, when the monthly cap is reached, or when the chat's model is not on the other side's model list.

What the key costs you

  • A Claude API card in 📊 Check Usage: what this relay's turns on the key are estimated to have cost today and this month, per model, with the tokens, and the monthly cap as a bar. The figures are Claude Code's own estimate, so sub-agents, compaction and web search are in them; the Console's billing page, linked from the card, has the real figures and the balance. Tokens without a known price show as "no price known", never as $0.
  • A monthly cap. Once this month's estimate reaches it, a new turn on the key does not run, a switch to the key is refused, and a new Claude API chat or an agent's send to one gets CLAUDE_API_CAP_REACHED. A running turn finishes, and its cost is booked when it ends, so running turns can take the month past the cap. Days and the month follow the relay's time zone. Console spend limits still apply on top.
  • Turns paid from a Max or Team plan's subscriber API credit are counted too; OAR cannot see that credit.

Hooks and keys

  • No hooks or status line run in DeepSeek and Claude API chats. In 0.9.17, a DeepSeek chat ran the hooks and status line of DeepSeek's settings folder, of the chat folder's .claude/settings*.json and of plugins, as the relay's user with the DeepSeek key in their environment. Those chats now start with all hooks off, set on Claude Code's command line, so a folder's settings cannot turn them back on. Hooks in managed settings still run, and chats on your Claude login keep their hooks and status line.
  • A subscription chat never runs on an API key. An env.ANTHROPIC_API_KEY in Claude Code's settings, an apiKeyHelper or a Console login used to make such a chat run on that key and bill its owner. Now the turn stops at Claude Code's start, with a note naming the source and the setting to remove; at most one model request, sent a moment after that start, can go out first.

The agent tool is now relay_tool

  • The relay's agent tool was remote_relay and is now relay_tool on every provider (mcp__relay__relay_tool on Claude), with the same actions and fields. The docs and the agents' instructions use the new name, and tool lines written under the old name still show as this tool.
  • If your own instructions, permission rules or hooks name remote_relay or mcp__relay__remote_relay, change them to the new name: outside OAR's own MCP server the old name is refused.

Docs

  • The providers guide has a Claude API section, and the web UI, configuration, security, agents-together and troubleshooting pages cover it too. Troubleshooting lists two known gaps: a key not tied to a workspace gets HTTP 400 from Anthropic, and a model Claude Code has no price for (currently Claude Haiku 5.5) is left out of the estimate.
  • Corrections to the 0.9.17 notes: DeepSeek's budget bar changes colour at 50 % and 75 % of the budget and turns red at 90 %; the composer's context chip shows DeepSeek's 1M window as 1.05M; and the preview tool's hint reaches only the sessions that have the tool.

Upgrade notes

  • No new dependencies, and the Node.js requirement is unchanged (22.13 or newer). Install and update with npm's install scripts allowed, as since 0.9.14.
  • Rename remote_relay to relay_tool in your own instructions, permission rules and hooks.
  • Downgrading to 0.9.17: first switch Claude chats on the Claude API key back to Subscription, since 0.9.17 runs a chat left on the key as a Copilot chat.
  • Downgrading to 0.9.17 turns hooks back on in DeepSeek chats: they run the hooks and status line of their settings folders again.

All the details are in the CHANGELOG.

Install / update: curl -fsSL oar.sh/install | sh · irm oar.sh/install.ps1 | iex · npm i -g @oar-sh/oar --allow-scripts=@oar-sh/oar,better-sqlite3,koffi · Docs: https://oar.sh

OAR 0.9.17

Choose a tag to compare

@materia79 materia79 released this 25 Oct 18:04

OAR 0.9.17

DeepSeek is now a provider of its own. Paste a DeepSeek API key, and New Chat offers DeepSeek's models with what a Claude chat has: the four modes, tools, question cards, sub-agents and reasoning effort, plus the 1M context window, a usage card with your balance and spend, and an import of your earlier usage. New sessions in a group now show at the top, and the relay's own Anthropic credentials no longer reach the agents it starts.

DeepSeek, a provider of its own

  • Paste a key, start a chat. Add your DeepSeek API key in ⚙️ Settings → Providers → DeepSeek, and New Chat offers the models DeepSeek lists (deepseek-flash by default, deepseek-v4-pro). A DeepSeek chat runs Claude Code on the relay host against DeepSeek's Anthropic-compatible API, so it has all four modes, tools, question cards, sub-agents, steering, Stop and background tasks.
  • Reasoning effort is low, high or max (high by default), and you can switch models between turns. A switch to a model without image input is refused once the chat holds images.
  • The 1M context window shows in the context panel. The chat compacts at 400K unless you set another window there.
  • Sub-agents stay on the chat's model. A sub-agent asked for as "opus" or "sonnet" runs on the chat's model, one asked for as "haiku" on DeepSeek Flash, and its badge names the DeepSeek model.
  • Commits carry Open Agent Relay (DeepSeek Flash) (the model in use), or no attribution, as set on the DeepSeek tab.
  • Clear failures. A used-up balance or a refused key ends the turn with a note and Top up DeepSeek and DeepSeek settings buttons.

Your key and your folders

  • The key is stored on the relay host, is never sent to browsers, and reaches only DeepSeek's workers. Their Claude Code keeps its state in a folder of its own, without your Claude login. The relay replaces the key with [redacted] in what the agent's replies, thoughts, tool activity and task output carry before it stores or shows them. This is hygiene for what the relay keeps, not a barrier against the agent: the agent's own commands can read the key from their environment, as with any key a CLI holds.
  • The relay pins DeepSeek's routing over a folder's settings. A chat folder's Claude Code settings could send the key to another endpoint or replace it. The relay now pins DeepSeek's endpoint and key, and with them the proxy, TLS trust, provider and credential settings, over the folder's settings. This covers routing, not commands: hooks and a status line in a folder's settings still run as the relay's user, as in any Claude Code chat, so use DeepSeek chats only in folders you trust.
  • The tab's Advanced section takes another base URL, for a proxy for example (https, or http on the same machine).

What DeepSeek costs you

  • A DeepSeek card in 📊 Check Usage: the account balance, read with your key, and the estimated spend of DeepSeek turns on this relay, by model, from DeepSeek's published prices with peak and off-peak hours. Web searches are counted on a row of their own.
  • Charts without a chart library: a balance bar against your last top-up, or a starting balance you set; the daily spend of the last 30 days, stacked by model; where the money goes per model, with what the cache saved; and a monthly budget bar, in USD or CNY, amber near the budget and red over it. Every chart has a table, in both themes and on a phone.
  • Import your earlier usage. Import usage export on the DeepSeek tab takes the two CSV files from DeepSeek's usage page (amount and cost). On the days the export covers, the card then shows DeepSeek's own figures instead of the estimate, and says through when. npm run deepseek:import does the same from the shell.
  • The estimate does not know Chinese public holidays, when DeepSeek charges off-peak prices all day, so peak-hour turns on those days are counted at double the real price.

Sessions and groups

  • A new session in a group shows at the top of the group, right under its first session: one an agent creates there, one started with the group chosen, or one moved in by its menu. The order you set stays.

Credentials stay with the relay

  • The relay's own ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN no longer reach any worker. A relay started with either in its environment handed it to every agent it started, and Claude Code prefers either to your Claude login. Now no worker gets them, also under tmux. Claude chats that ran on such a key now run on the host's Claude login.
  • The Claude login token (CLAUDE_CODE_OAUTH_TOKEN) reaches only Claude's workers, no longer Copilot, OpenAI, Cursor or Grok.
  • A relay started from inside a Claude Code session no longer hands that session to its workers.

Fixed

  • The Inbox opens at the top, or where you last left it, instead of somewhere in the middle of the list.
  • The session header on a phone comes in two rows, so the title gets the width the buttons leave and the chips no longer break inside their text.
  • OpenAI image models work on the SDK engine again, and a refused image request fails its turn instead of staying in progress.

Upgrade notes

  • No new dependencies, and the Node.js requirement is unchanged (22.13 or newer). Install and update with npm's install scripts allowed, as since 0.9.14.

All the details are in the CHANGELOG.

Install / update: curl -fsSL oar.sh/install | sh · irm oar.sh/install.ps1 | iex · npm i -g @oar-sh/oar --allow-scripts=@oar-sh/oar,better-sqlite3,koffi · Docs: https://oar.sh

OAR 0.9.16

Choose a tag to compare

@materia79 materia79 released this 24 Oct 02:26

OAR 0.9.16

Agents get more done with less of your attention: they can file the sessions they start into your groups, change another session's settings, watch other sessions with fewer wake-ups, and schedule prompts that survive a restart. They can ask you a question without stopping their work, and the new Inbox shows every open question from this relay and its paired relays in one place.

Agents that organise their own work

  • New sessions land in your groups. An agent that starts a session can put it into one of your existing session groups, here or on a paired relay. The approval card names the group, and an unknown group is refused before anything is created. Renaming and arranging groups stays yours.
  • Agents can change another session's settings: its model, reasoning effort, mode, auto-compact window, title, group, thinking or working folder, for its next turns. A session the agent's own conversation started can be changed freely; any other session, yours or another agent's, needs your Allow once per conversation. An open page shows the change at once.
  • "Agents in this conversation may start sessions." A new switch in the 🧠 settings of a session an agent started lets its agents start sessions themselves. The limit of four at work and your first Allow still apply, and only you can turn it on.

Watching with fewer wake-ups

  • Digests: a watching agent can get a subscription's events as one message every few minutes instead of one by one.
  • Quiet hours: a daily window in a time zone you choose (across midnight and clock changes too) whose events arrive as one message when it ends.
  • Exclusions: a subscription to all sessions can leave some out.
  • Questions and errors still arrive at once, held events survive a restart, and an agent is no longer woken a second time for a reply it was already waiting for. The watching chip shows a small digest or quiet-hours hint.

Scheduled prompts

  • An agent can schedule a prompt for a set time or every N minutes (5 minutes to a week), into its own conversation or, with your approval, another session on this relay.
  • Schedules survive a restart or an update. A time missed while the relay was down fires once when it is back, and a repeat waits while the one before is still queued.
  • The message says it is automated and approves nothing. The sidebar marks a scheduled session, and its header lists the schedules with a Cancel button each. Archiving a session ends its schedules.

Questions that don't block, and the Inbox

  • Agents can ask without stopping. A question card appears in the agent's session (up to eight options, a recommendation, folded detail, and a push for urgent ones) while the agent goes on with work that does not depend on it. Your answer, or a dismissal, reaches the agent as soon as you give it.
  • The Inbox in the sidebar, with its count, lists every pending question across this relay and the paired relays, grouped by relay, with a filter for your own sessions or the agents'. What you answered in the last day stays below a divider. Answer an agent's question there or in its session, also one on a paired relay; a paired relay's approval cards open on that relay.
  • On a phone the Inbox is one column with full-width buttons.

Fixed

  • The agents' loop guard counts only your own messages. Before, a relay event, the usage-limit follow-up or the note after a restart could reset it, so two agents watching each other could go on without you.

Upgrade notes

  • Group filing, settings changes and questions on a paired relay need that relay on 0.9.16 too; with an older one, the agent is told what did not apply.
  • No new dependencies, and the Node.js requirement is unchanged (22.13 or newer). Install and update with npm's install scripts allowed, as since 0.9.14.

All the details are in the CHANGELOG.

Install / update: curl -fsSL oar.sh/install | sh · irm oar.sh/install.ps1 | iex · npm i -g @oar-sh/oar --allow-scripts=@oar-sh/oar,better-sqlite3,koffi · Docs: https://oar.sh

OAR 0.9.15

Choose a tag to compare

@materia79 materia79 released this 21 Oct 22:32

OAR 0.9.15

oar setup now asks how your relay should start on Windows, oar autostart switches it later, and oar uninstall takes OAR off a machine without taking your conversations with it. Autostart changes are safe: a declined administrator prompt changes nothing, and a task you made yourself is never deleted without a copy.

Note

From 0.9.14 with a hand-made autostart task: switching to boot mode in 0.9.14 could delete an existing task of the same name (oar-relay, or the older copilot-remote-relay) without a copy. 0.9.15 keeps such a task and asks for --replace, which saves a copy before it replaces anything.

Start the relay your way on Windows

  • oar setup asks how the relay starts: when you sign in, at boot before anyone signs in (one administrator prompt), or not at all. Your current mode is the default, and --autostart signin|boot|off answers without a question.
  • oar autostart signin|boot|off|status switches later. Only boot mode needs an administrator, and only for the one step that registers or removes the task. status lists each entry, whether OAR made it, and which other OAR install an old entry would start.
  • Boot mode works in any profile folder: with a space, an apostrophe or non-ASCII letters (such as ü) in the path, switching on and off now works, and OAR recognises its own task again.

Your tasks and entries stay yours

  • A declined administrator prompt changes nothing. Before, Windows PowerShell could report a declined prompt in a way that read as confirmed, so a switch went halfway.
  • A hand-made autostart entry is never deleted or written over, in the web UI as in oar autostart: OAR stops and names it. --replace replaces it with OAR's own and keeps a copy (<name>.bak).
  • A boot task only an administrator can read is never deleted. OAR reports that it cannot check it and leaves it alone.
  • A switch that fails puts back what it removed and keeps the copies.

Uninstall without losing your data

  • oar uninstall stops the relay, takes out the autostart entries and the Copilot extension wrapper OAR made, then has npm remove the package. Your config, conversations, uploads and logs stay, and it tells you where.
  • oar uninstall --purge deletes them too, after you type delete. A data folder elsewhere, or inside a git checkout, gets a question of its own; a drive root, your home folder, a system folder, or a folder without OAR's data in it is refused whatever you type.
  • If a step fails, the command stops and says what is done and what is left.

Smaller package

  • The two developer READMEs (the relay's HTTP API and the web-relay extension's) are no longer in the npm package; they are on GitHub.

Upgrade notes

  • Read the note above if you made an autostart task yourself and use 0.9.14.
  • On Linux, oar autostart uses the systemd user service (oar service); on other systems it says it is not supported.
  • The Node.js requirement is unchanged (22.13 or newer). Install and update with npm's install scripts allowed, as since 0.9.14.

All the details are in the CHANGELOG.

Install / update: curl -fsSL oar.sh/install | sh · irm oar.sh/install.ps1 | iex · npm i -g @oar-sh/oar --allow-scripts=@oar-sh/oar,better-sqlite3,koffi · Docs: https://oar.sh

OAR 0.9.14

Choose a tag to compare

@materia79 materia79 released this 21 Oct 16:49

OAR 0.9.14

Warning

Windows autostart users, and anyone whose relay a plain gh copilot started: save your data before you update.
Up to 0.9.13 those relays kept their database and uploads inside the installed package, and npm i -g deletes them together with the old version. 0.9.14 copies them first, while it installs, and the relay takes the copy over at its next start, but only when npm runs OAR's install script. npm 12 skips it unless @oar-sh/oar is allowed, and the Update button and oar update of 0.9.13 don't allow it. So do this update by hand:

  1. Close every gh copilot session (its extension starts the relay again), then run oar stop and wait until oar status says the relay is not running. If 0.9.13's oar stop does not stop a relay the system-startup launcher started, end the relay before installing: end the relay's processes in Task Manager (node.exe running OAR).
  2. Run npm root -g and open <that folder>/@oar-sh/oar/server (usually %APPDATA%\npm\node_modules\@oar-sh\oar\server). Copy both the data and the uploads folders, with everything in them, to a safe place.
  3. Update with npm's install scripts allowed:
    npm i -g @oar-sh/oar --allow-scripts=@oar-sh/oar,better-sqlite3,koffi
    
    Never update OAR with --ignore-scripts: it skips the copy and the native modules (better-sqlite3, koffi), and the relay can't start afterwards.
  4. Before starting the relay, copy both folders back into the same server folder.
  5. oar start. In relay-console.log in the OAR logs folder, look for [data] Brought over the database …: your conversations should be back.

If the relay stops with [data] Not starting: each database has changes newer than the other's, both hold work: pick the one to keep and move the other one's copilot.db, copilot.db-wal and copilot.db-shm into a folder of your own (don't delete them), then oar start again. All the details are in the CHANGELOG.

A relay you only ever started with oar start already ran on the OAR data folder and needs none of this.

Your relay now keeps its data in one place however it's started, and an update no longer takes your conversations with it. Locks an unclean shutdown left behind no longer block the next start, autostart waits for late drives, and agents can ask to be woken when the relay is back after a restart.

Your data, safe across updates

  • Windows autostart and gh copilot relays run on the same data as oar start: the config, database, uploads and logs in the OAR folder (%APPDATA%\oar, ~/.oar), outside the installed package. The relay brings an autostart entry or launcher that an earlier version generated up to date at its first start; one you edited by hand is left alone.
  • An update copies the data an earlier version kept in the package to rescued-package-data/<time>/ in the OAR data folder before npm removes it, on every platform. If that copy fails, npm 10 and 11 stop the update and put the old version back with its data.
  • The relay never moves to another database unannounced. At its start it looks once at each database it may have run on until now: a newer one is checked and copied in, the one it replaces is kept in backups/<time>/, and nothing is ever deleted. When it can't tell which one to keep, it stops with one line naming both, and its supervisors don't restart it in a loop (exit code 78).
  • Cursor conversations keep their agent across updates (its stores now live in the data folder), uploads follow the config's dataDir, and every attachment an earlier version stored elsewhere still opens.
  • oar setup --migrate-from works after the installer has run, says what it copied or why it copied nothing, and never overwrites a config or a database with conversations.

Starting reliably

  • A relay lock left by a crash or a power loss no longer blocks the next start, and two starts recovering the same lock no longer both run. Locks no longer go by the clock, so a clock step can't make a live relay look gone.
  • Windows autostart waits for a late drive: both the sign-in entry and the system-startup launcher wait up to 5 minutes for %TEMP% and the data folder's drive (a RAM disk, a drive a script mounts later), then log what was still missing. A TEMP set with quotes no longer stops the launcher.
  • A relay whose data folder can't be created stops with one line naming it instead of an error trace.

Agents

  • Woken when the relay runs again: an agent can subscribe to relay_restarted with remote_relay and gets one relay event after each start, with how the relay stopped. Opt-in, never part of the default events, and it can't chain restarts into a loop.
  • An agent's preview tool lists and closes only its own conversation's previews; Settings › Previews and /preview list still show all of them.
  • Approval cards take a choice, not typed text: OAR's Allow/Deny cards and Claude Cloud's permission cards no longer have a reply box where a typed "yes" counted as a denial, and a card's header shows above its question.
  • Reasoning effort reaches every Cursor model that takes one (after Refresh in Select Models).

Fixes

  • A conversation whose working folder was deleted or renamed now says so, with what to do, instead of blaming the CLI, libc or a missing node.
  • Answering a question no longer gets a long turn requeued by Max turn duration.
  • A resumed sub-agent opens its record and is listed as running again.
  • Help texts and oar messages say what the relay actually does; the docs match the code.
  • Claude Agent SDK 0.3.304 (Claude Code 2.1.304), Cursor SDK 1.0.38, Copilot SDK 1.0.23.

Upgrade notes

  • Read the warning above first if you use Windows autostart or a plain gh copilot.
  • npm 12 runs no install script it wasn't told to allow: install and update OAR with --allow-scripts=@oar-sh/oar,better-sqlite3,koffi. The oar.sh installers, and oar update and the Update button from 0.9.14 on, pass it themselves. An allow-scripts entry in .npmrc doesn't help 0.9.13's Update button or oar update: their own --allow-scripts replaces it.
  • A relay that finds its lock held, or can't decide between two databases, now exits with code 78, which a systemd unit written by this version's oar service install doesn't retry.
  • The Node.js requirement is unchanged (22.13 or newer).

Install / update: curl -fsSL oar.sh/install | sh · irm oar.sh/install.ps1 | iex · npm i -g @oar-sh/oar --allow-scripts=@oar-sh/oar,better-sqlite3,koffi · Docs: https://oar.sh

OAR 0.9.13

Choose a tag to compare

@materia79 materia79 released this 20 Oct 07:30

OAR 0.9.13

A relay restart is now something you can see and steer: a queued restart shows what it waits for and asks instead of waiting forever, the task console survives it, and sessions a restart cut off can be told to carry on. Agents get fewer needless wakeups and a clear refusal for a model that doesn't exist, and a message sent without a model keeps the conversation's own.

Relay restarts

  • 🌄 Restart web relay first lists the sessions with a running turn it would wait for, the messages it would hold, and the sessions with background tasks (commands, monitors, sub-agents), each with whether it keeps running. Restart when idle queues the restart; Restart now doesn't wait.
  • While a restart is queued, every page shows a banner: Relay restart queued — waiting for N sessions, with the sessions as links, how long it has waited, that new messages are held until then, the background tasks, Restart now and Cancel restart.
  • Settings › General › Ask after a queued relay restart has waited (30 minutes by default, 5 minutes to 4 hours or no limit): after that time the banner, and a push notification, ask restart now, keep waiting or cancel?. A queued restart never restarts while turns run, and still goes ahead as soon as they end.
  • After a relay restart, tell interrupted sessions to carry on (Settings › General, off by default): a session whose turn a restart cut off for good gets one compact relay note when the relay is back, saying when it restarted and asking the agent to check what it was doing. The user's message is never sent again.
  • Workers reconnect after a restart even when their connect hangs, a socket is accepted but never greeted, or the old relay hangs in its shutdown.

Task console

  • It survives a relay restart: finished rows come back with their ✓ or ✘ for the rest of their hour, and a running command's console reads its output at once. The command counts as running again only when its worker says so; one whose worker didn't survive ends with a neutral ? (result unknown), its output still readable.
  • A | tail no longer looks stuck: when a command pipes into tail, the console marks where the output stops and suggests logging to a file instead. The Claude, Copilot and Grok workers now report each shell task's command line.
  • The task's row stays in view beside the open console on wide screens, so its ✓/✘ chip, clock and Stop stay live; Load earlier is also in the console header.
  • Test counts cover the whole log of a long run, not just its last 64 KB, and vitest's RUN/PASS/FAIL badges render filled.
  • Credentials in task rows are blanked (descriptions, summaries, commands), and the scrubber knows more shapes: curl -u, --password/--token/--secret, mysql -p…, docker login -p, sshpass -p, redis-cli -a, AWS secret keys, Slack webhook paths, ?key=/&sig=/&token= and Authorization headers in any case.

Agents

  • remote_relay refuses a model the provider doesn't list, in create_session and send, before any approval card, with the close matches ("Unknown model 'gpt-5-4' for Copilot on relay …; did you mean 'gpt-5.4'?"). Claude also takes opus, sonnet and haiku, and a Copilot id with its effort (gpt-5.4-high) runs as that model with that effort.
  • Fewer watcher wakeups: a subscription that names no events no longer wakes the watcher for every shell command that ended well (subagent_finished replaces task_finished in the default). Failures and finished sub-agents still wake it. Existing subscriptions without their own event list switch by themselves; name task_finished to get every task end.

Fixes

  • A message sent without a model keeps the conversation's model, effort and mode and saves nothing it didn't name. Before, a script's or agent's message to a Copilot conversation ran on the catalog's first model with effort none and saved that as the conversation's own. If the conversation's model has left the catalog, the send is refused with a message saying so.
  • A scroll right after older messages load is no longer undone; the jump-to-bottom badge counts a message that arrives just as you scroll up; the background-task panel no longer shrinks back for a moment.
  • A preview's websocket is dropped when the browser hangs up before the dev server answers, and stopping the preview lane no longer waits for it.
  • The unit test suite passes and finishes on Windows again.

Upgrade notes

  • Migration 0018 (stored task-console rows) runs by itself on the first start. The Node.js requirement is unchanged (22.13 or newer).
  • New settings: Ask after a queued relay restart has waited (30 minutes) and After a relay restart, tell interrupted sessions to carry on (off); a new push notification, Queued relay restart waited its maximum time in Settings › Notifications, is on by default.
  • Scripts that post /api/message without a model to an existing conversation now get the conversation's own model, effort and mode (or 409 CONVERSATION_MODEL_UNAVAILABLE), instead of the relay's first model.

Install / update: curl -fsSL oar.sh/install | sh · npm i -g @oar-sh/oar · oar update · or from a running relay: Settings → General → Updates · Docs: https://oar.sh

OAR 0.9.12

Choose a tag to compare

@materia79 materia79 released this 18 Oct 20:08

OAR 0.9.12

Background commands get a console: open one from the task panel and read its output live, see when it has gone quiet and how its tests are doing. Long conversations open and page back fast, and you come back to the message you were reading.

Task console

  • Click a background command or monitor in the task panel to open its console: the last 2,000 lines, following live, with Load earlier paging back through the whole log (about 5 MB at most). Progress-bar redraws collapse to their last state, a line repeated many times folds into one with ×N, colours are kept (a red failure stays red), other control codes are dropped, and credentials are blanked. The console has its own Stop.
  • A finished command keeps a dimmed ✓ or ✘ row for about an hour, so a failed run can still be read after it ended.
  • Claude reads the file its CLI writes for the command, Copilot a detached shell's log or an attached shell's recent output, and Grok now lists its terminals as background tasks. A session started before this release names no output file for its commands; its console says so and that restarting the session helps.

Quiet tasks and test runs

  • A shell or monitor row that has written nothing for a minute or more says no output for N min, in amber after Settings › General › Mark a background task as quiet after (10 minutes by default, 1 to 120).
  • When the output is a test run (vitest, Playwright, node:test, jest, pytest, or turbo, also through pnpm), the row and the console header show a ✓ 412 ✘ 2 chip; the header's chip jumps to the first failure.
  • Sub-agent rows in the task panel show their step count, as the rows in the reply already did.

Claude background commands

  • Settings › Providers › Claude › Claude background command limit (30 minutes to 8 hours, 2 hours by default) sets how long a command Claude runs in the background may take before Claude Code stops it, when Claude gives it no timeout of its own; Claude may still ask for up to 8 hours for one command. A foreground command moves to the background after 2 minutes, so the turn goes on while it runs.
  • Claude is also told to write the output of long runs to a log file instead of piping it into tail, and to start runs that must survive a session restart with nohup.
  • A change applies to Claude sessions started afterwards; Claude Cloud is not affected.

Agents

  • remote_relay gains read_task_output: the tail of a shell or monitor task's output on a relay the agent may read (up to 500 lines), how long it has been quiet, and the pass/fail counts of a known test runner, scrubbed of credentials as in the console. read_session lists each task's id, whether it has output, and that health. Share links never expose it.

Long conversations

  • History pages are selected in the database, so a conversation with thousands of messages opens, pages back and refreshes live in well under a tenth of a second instead of about two seconds per page (migration 0017 adds the indexes).
  • Switching back to a conversation you viewed in this tab draws it at once from what the page kept; the relay's fresh answer is merged in when it arrives.

Reading position

  • Switching away and back keeps your place, older pages included: the page remembers the message you were reading, keeps the loaded messages, and adds what was written meanwhile. After a reload it opens at that message, with the messages around it. Settings › General › Messages kept per conversation for switching back (200 by default, 100 to 1,000 or no limit, per browser) sets how many each of the last eight conversations keeps.
  • New messages no longer skip the ones in between while you read far up. Opened at a pin, a search result or the place read after a reload, a conversation used to put a new message right under the loaded window and never load the ones between. Now new messages wait: the ⌄ button counts them, and scrolling down loads everything in between, in order. A message you send from there takes you to the end.
  • Images that load late no longer push the text you are reading down in browsers without scroll anchoring (Safari, for one); the transcript holds your place while they load and lets go as soon as you scroll.

Conversation list

  • Activity shows in the title's colour. The three animated dots after a working session's title are gone: a ready session that runs a turn or background work keeps the bright green title, an idle one turns a darker green (a muted green in the light theme), and the chat header follows the same rule. Question, error, offline and archived titles keep their colours.

Fixes

  • Copilot background tasks report how they ended. Finished shells and sub-agents on Copilot's SDK engine showed the status unknown without an exit code. The worker now reports completed, failed or cancelled, a shell's exit code, and a sub-agent's result (or error) as its summary; a passing status line such as Thinking… is no longer kept as the final summary.
  • A test run that ends shows its final pass/fail counts within a moment, instead of the counts from mid-run.
  • Cancel on a usage-limit pause removes the relay's held Automatic message from OAR row from the open conversation at once, and from what the page keeps for switching back.

Known limits

  • Commands that start with sleep, and sub-agents' commands, are not moved to the background after 2 minutes, so they can block a Claude turn in the foreground up to the background command limit.

Upgrade notes

  • OAR now sets BASH_DEFAULT_TIMEOUT_MS, BASH_MAX_TIMEOUT_MS and CLAUDE_CODE_AUTO_BACKGROUND_TIMEOUT_MS for the Claude sessions it starts, from the new limit: values of these in the relay's environment no longer apply.
  • Migration 0017 (two indexes for the history of long conversations) runs by itself on the first start. The Node.js requirement is unchanged (22.13 or newer), and no setting or config key needs changing.

Install / update: curl -fsSL oar.sh/install | sh · npm i -g @oar-sh/oar · oar update · or from a running relay: Settings → General → Updates · Docs: https://oar.sh

OAR 0.9.11

Choose a tag to compare

@materia79 materia79 released this 17 Oct 01:43

OAR 0.9.11

Sessions an agent starts gather in groups you can fold, name and rearrange by drag and drop; shared links get a management page with an access log and keep the host's paths to themselves; and the relay is harder to reach from outside.

Session groups

  • A session an agent starts with remote_relay sits under the session that started it. The head row has a fold button and a pill that sums up the members ("3 · 1 waiting for you, 2 running"); a group folds away once everything in it has finished, unless you folded or unfolded it yourself.
  • A question or approval waiting in a folded member shows on the head row, and a tap opens that member. Activity anywhere in a group lifts the whole group to the top of the list.
  • The head row's menu has Archive group (members still working are kept and named), Stop all running, Rename group and Dissolve group; any row's menu has Add to group…, Move to another group… and Remove from group.
  • list_sessions and read_session tell an agent which group a session is in.

Drag and drop

  • Drag a session into a group, out of it, or to another place inside it; the order you set stays, and later arrivals join at the end. Drop one loose session onto the middle of another and the two become a new group.
  • On a phone, a long press lifts the row and a move drags it; a long press without moving opens the row's menu when the finger lifts. With the keyboard, a member's menu has Move up and Move down.

Sharing

  • Settings › Sharing lists every shared conversation with when it was shared and last opened, how often and by how many viewers, and Copy link, Renew link (the old link stops at once) and Stop sharing. The ⋯ menu has Stop sharing too while the open conversation is shared.
  • Each row unfolds into an access log: one entry per open of the page, with time, IP address, country and browser. It carries over to a renewed link and is deleted when you stop sharing or delete the conversation. Switch off Store viewer IP addresses to log new opens without the address; switching it off also offers to remove the addresses already stored.
  • A share link no longer carries the host's paths. Paths and file names in Settings › Sharing: show every path, hide the path and show the file name (the default), or hide both. Tool lines, thoughts, replies, attachments and sub-agent records all pass through the filter; free text is filtered on a best-effort basis.
  • 🔍 Preview as shared in the ⋯ menu shows the conversation as a viewer sees it, without creating a link: replaced paths are marked green, whatever still looks like a path amber.
  • A 🙈 button next to 📍 counts the messages hidden from the shared link and opens their list, with Unhide per row and Unhide all.
  • A sub-agent's row in a shared view opens its record, read-only. A stopped or renewed link answers a plain 404, and a shared page still open stops at its next refresh. Shared views no longer mark every reply "ran on" its own provider.

Security

  • Ten wrong tokens from one address within a minute lock it out: 429 with Retry-After until the minute is over, and the sign-in page says how long to wait. A stale cookie repeated counts once; requests from the relay host itself are never locked out.
  • The live Socket.IO channel accepts the relay's own origin only, plus the origins listed in the new allowedOrigins setting.
  • X-Forwarded-For, X-Forwarded-Host and the other forwarded headers count only from a proxy trusted through trustProxy, for rate limits, the sign-in lockout, the access log and share links alike.
  • ?token= signs in the page only; API, file and asset URLs take the token in the Authorization header or the cookie.
  • Restart web relay, cancelling a queued restart and Empty queue now work from every signed-in device with the token. The session-worker socket and the image-operation run answer only the relay host itself, never a request a tunnel or proxy forwarded. A refused restart says why instead of reporting success.

Web UI

  • ℹ️ About OAR in the ⋯ menu: version, commit and start time, each provider that is on with its CLI and SDK version and whether it is online, conversations, turns and messages, the usage the providers report, uptime, database size and running workers. Backed by the new GET /api/about.
  • Day/Night is back in the ⋯ menu on every screen size; since 0.9.10 it showed only in a shared view.
  • A conversation no longer scrolls by itself while you read further up; the ⌄ button turns blue with a count when something new arrived below and amber with "?" when a question or approval waits. Settings → General → Jump to the end when I send a message (on by default) decides what your own send does.
  • A reply to another agent's note is no longer folded away; only the note folds into its row.
  • A wide table in the file reader scrolls in its own box instead of turning the page.

Relay and workers

  • Preview links survive a relay restart: previews are kept in the database and checked again at start, and publishing the same port or folder again returns the same link. Settings → Previews shows when each was published and last opened.
  • A worker no longer stops reconnecting after a relay restart, and a worker left without a connection for 60 seconds while a message waits is replaced (never while its session is working).
  • A relay restart no longer forgets running background tasks: workers report them again, with their original start time.
  • Workers run on the relay's own Node by its full path, so they start when no node is on the PATH (e.g. a Windows system-startup task), and a launch that fails says why. The Windows startup launcher waits for an early-boot %TEMP%.
  • The direct dependencies (the Claude, Copilot and Cursor SDKs among them) are pinned to the versions the release was tested with.

Upgrade notes

  • Behind a reverse proxy on another host or origin, set trustProxy and allowedOrigins in the config file (~/.oar/config.json, or server/config.json in a git checkout), then restart the relay:
    "trustProxy": "192.0.2.10",
    "allowedOrigins": ["https://relay.example.com"]
    trustProxy takes the proxy's address, a subnet such as "10.0.0.0/8" or a hop count such as 1 (it defaults to "loopback", so a proxy on the relay host needs nothing). allowedOrigins lists the public origins as the browser shows them. Without them the page's live connection is refused (the relay logs Refused a handshake from origin …), and every client shares the proxy's address for the sign-in lockout.
  • Scripts that used ?token= on API, file or asset URLs must send Authorization: Bearer <token> instead; a Socket.IO client passes the token as auth.token.
  • Four database migrations (previews, session groups, the place in a group, the share access log) are applied on start. The Node.js requirement is unchanged (22.13 or newer).

Known issues

  • On Windows, one phone-layout check in the browser test suite (transcript-stays-put, the reader's place while a reply finishes) misses its tolerance of under 1 px by 0.14 px. The same happened on 0.9.10.
  • In the browser test suite, one check that a reader following a streaming reply stays at the end while background tasks grow (transcript-jump-to-bottom) fails intermittently, on 0.9.10 as well. It is a timing race we are still looking into.

Install / update: curl -fsSL oar.sh/install | sh · npm i -g @oar-sh/oar · oar update · or from a running relay: Settings → General → Updates · Docs: https://oar.sh