All pages
On this page

Updating OAR Added in 0.9.2

OAR does not update itself in the background. A relay can look for a newer release, tell you in Settings, and install it when you press Update or run oar update. Nothing is installed without you, and the check that finds a release is off until you switch it on.

The update check #

The check is off by default. A relay that has never been told otherwise sends nothing to oar.sh.

  1. Open Settings → General.
  2. Turn on Check for updates automatically.

With it on, the relay asks oar.sh for the newest version about twice a day: every 12 hours, give or take up to an hour so that many relays do not ask at once. It also asks once when you turn the switch on and once each time the relay starts with the switch on. Turning the switch off stops the asking.

The button Check for updates checks once, whatever the switch says. The line next to it reads Last checked <date and time>, or Never checked.

What the check asks for #

The relay requests one file, the manifest https://oar.sh/latest.json: a plain GET with an Accept: application/json header, and an If-None-Match header holding the tag of the last answer once there is one, so that an unchanged manifest costs no download. The request carries no version, token, account or machine information. It waits at most 5 seconds. There is no other contact with oar.sh. Installing an update talks to the npm registry, not to oar.sh.

The manifest has an entry per channel with the newest version, its release date, a link to its release notes and a flag critical:

{
  "schemaVersion": 1,
  "channels": {
    "stable": {
      "version": "0.9.19",
      "publishedAt": "2026-10-27T06:23:15.940Z",
      "notesUrl": "https://github.com/oar-sh/oar/releases/tag/v0.9.19",
      "minNode": "22.13",
      "critical": false
    }
  }
}

The relay reads the entry of its own channel (see Channels), or the stable entry when its channel has none. minNode names the oldest Node.js the release runs on; neither the relay nor the installers read it.

An automatic check that fails (no network, a timeout, a bad answer) says nothing and tries again at the next interval. A click on Check for updates that gets no usable answer shows the notice Update check failed — the update server could not be reached. A manifest with another schemaVersion than 1 stops the checking until the relay restarts and adds The relay could not read the update feed — try updating manually. to the line next to the button.

When a version is found #

A newer version shows as a row under Check for updates in Settings → General:

OAR 0.9.19 available

with a release notes link, and the buttons Update and Dismiss. There is no banner and no badge elsewhere, and with the check off nothing shows, because no newer version is known. Dismiss hides that version until a still newer one appears. A release marked critical reads OAR 0.9.19 available — critical update, cannot be dismissed, and still never installs by itself. On a git checkout the row has no Update button; it says This relay runs from a git checkout — pull and restart to update.

Turning the check off for good #

Set OAR_NO_UPDATE_CHECK=1 in the relay's environment. The relay then makes no request at all, not even when you press Check for updates: the switch and the button are disabled and a line says Update checks are disabled by OAR_NO_UPDATE_CHECK in this relay's environment. oar update without --to refuses as well. OAR_UPDATE_MANIFEST_URL points the relay and oar update at another manifest. See Environment variables.

Updating from the web UI #

Press Update in Settings → General. It works on a global install, the kind the installer and npm install -g make.

  1. The relay runs npm install -g --allow-scripts=@oar-sh/oar,better-sqlite3,koffi @oar-sh/oar@<version> (Added in 0.9.14 with @oar-sh/oar in the list; see Install with npm). On macOS and Linux it uses the npm that sits beside the Node.js running the relay, and installs into the folder the package already sits in. That covers all three layouts of the installer: your own global npm folder, ~/.oar/npm when your npm folder needed root, and ~/.oar/npm with OAR's own Node.js. On Windows it runs npm.cmd from the PATH. npm gets 10 minutes.
  2. The status line reads Updating to <version>…, and an Update log folds out with npm's output. Cancel update stops npm.
  3. When npm has finished, the line reads npm finished — the relay restarts once the running turns finish. The relay asks itself to restart. It waits for turns that are running; messages you send meanwhile wait in the queue and run after the restart. A banner on every connected device shows the wait, with Restart now and Cancel restart. Added in 0.9.13 After Ask after a queued relay restart has waited (30 minutes by default) it asks whether to restart now, keep waiting or cancel. See Restarts and resuming.
  4. The relay restarts and the page reconnects by itself. The restart does not go through systemd or any other service manager; see Autostart.

If npm fails, the line reads Update failed: <reason> and the log shows why. The relay keeps running the old version.

If you cancel the restart

Cancel restart in the banner stops only the restart. The new version is installed but the relay keeps running the old one, and the status line still reads npm finished — the relay restarts once the running turns finish. Restart the relay yourself to load it.

How the relay checks the result #

Before it restarts, the relay writes down which version it tried to install. On the next start it compares that with the version it runs. A match shows Updated to <version>. A mismatch, for example because npm did not replace the package, shows Update to <version> did not apply. with the end of the npm log. A note older than 7 days is dropped without a message. Dismiss next to the line clears it.

Updating from a terminal #

oar update

It looks up the newest version of your channel in the manifest, installs it with npm install -g, and asks a running relay to restart once its queue is idle. It prints Already up to date (<version>). when there is nothing newer. Options and exit codes are in oar update.

To install one exact version, also an older one, name it with a space after the flag:

oar update --to 0.9.9

--to reads the npm registry and skips the manifest, so it works with OAR_NO_UPDATE_CHECK=1 too. Write --to 0.9.9, not --to=0.9.9: the second form is ignored and installs the newest release of your channel.

The installer is another way. It installs the package again, so running it again updates; see Install.

Channels #

There are two channels, stable and beta. A beta version looks like 0.9.19-beta.1 and sorts below the stable release with the same number.

A relay has no channel setting. It follows the channel of the version it runs: a beta version follows beta, any other follows stable. That holds for its own check and for oar update.

You want Do this
Beta from the start Install with OAR_CHANNEL=beta; see Install
To move a stable install to beta oar update --beta once
To stay on beta Nothing
To go back to stable oar update --to <stable version>, for example oar update --to 0.9.10. A relay on a stable version follows stable again

A beta relay is offered whatever version the manifest lists under beta, as long as it is newer than the running one. When the beta entry lists a stable release, as both entries do for 0.9.19, a beta relay moves to it and follows stable from then on. Going to an older version needs --to.

What an update leaves alone #

After an update
State folder, config, uploads, logs Untouched. See Files and folders
Data an earlier version kept inside the package Added in 0.9.14 Copied to data/rescued-package-data/<time>/ while the update installs, before npm removes the old version, and taken over at the next start. See Upgrade notes for 0.9.14
Database Kept. Migrations that a release needs run by themselves on the first start
Installed app The web UI comes from the relay, so it changes with it. The installed app switches to the new version when it starts; you do not reinstall. See Install as an app
Running sessions See below
Provider CLIs Not updated. See below

Sessions that were running #

The restart waits until no turn is running, then the relay starts again with the new code. Agent processes that were started before the update have the old code until they start again. A session's agent learns its tools when it starts. The 0.9.10 release is an example: a session that was already running before the update offers neither subscribe nor usage of remote_relay (now relay_tool) until its agent restarts. In 0.9.11, a worker started before the update cannot report its background tasks to the restarted relay. In 0.9.12, the console of a command needs an agent started after the update, and so do Grok's terminals in the task panel. In 0.9.13, the mark for a command piped into tail needs an agent started after the update, because the agent reports the command line. Kill session on an idle session restarts it, and the next message starts a new agent. See Restarts and resuming.

Provider CLIs #

OAR updates only itself. The Claude, Grok and GitHub Copilot command-line tools are separate programs; see Installing or updating a provider's CLI.

Good to know #

  • Cursor on a global install. Added in 0.9.14 The Cursor agent stores live in cursor-agents in the relay's data folder, so an update no longer replaces them. Before 0.9.14 they sat inside the package folder by default, and a conversation whose store an update removed got a new agent. See Files and folders and Cursor.
  • Windows. A global install runs the relay from the OAR state folder (%APPDATA%\oar), not from the package folder, so an update can replace the package while the relay runs. The autostart entries start the installed package; see Autostart.

A git checkout #

A checkout never updates itself, and neither Update nor oar update work on it. Pull, install, then restart the relay with 🌄 Restart web relay in a conversation's ⋯ menu:

git pull
npm install

See Install.

Upgrade notes #

Steps an update needs from you, newest release first. Releases not listed need none.

0.9.19 Added in 0.9.19 #

  • No migrations. Going back to 0.9.18 needs no step: 0.9.18 ignores heapLimitMb, and the diagnostics folder stays as it is.
  • The relay now has a heap limit and writes a heap snapshot to diagnostics in the data folder when it nears it. A snapshot holds the access token and the API keys: never share one as it is.
  • Stop oar and start it again once after the update. The process that starts and watches the relay keeps the code it started with: a restart by the update, from the web UI, or by oar restart without the systemd service only starts the relay inside it again. Until that process starts on 0.9.19, the relay runs without the heap limit, heapLimitMb and the heap snapshot, and a relay that runs out of memory still stays down. Under the Linux systemd service, run oar restart; otherwise run oar stop, then oar start. For a relay that oar copilot started, end that session and start it again.
  • 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.
  • Node.js 22.13 or newer is still enough.

0.9.18 Added in 0.9.18 #

  • Migrations 0031 to 0034 run by themselves on the first start: 0031 stamps each queued message with its provider, 0032 adds the columns of the billing switch, and 0033 and 0034 add the tables of the Claude API usage card. An older version ignores the new columns and tables. The two triggers 0031 puts on the queue table keep stamping its new column there, which does no harm.
  • The agent tool is now called relay_tool. If your own instructions, permission rules or hooks name remote_relay or mcp__relay__remote_relay, change them to relay_tool or mcp__relay__relay_tool. See The name.
  • Before you go back to 0.9.17, switch Claude chats on the Claude API key back to Subscription. 0.9.17 does not know Claude API: it binds a chat of a provider it does not know to Copilot, so a chat left on the key runs as a Copilot chat there. That includes a chat that started on the subscription and was switched to the key.
  • Going back to 0.9.17 turns hooks back on in DeepSeek chats. They run the hooks and status line of their settings folders again; see Folder settings cannot reroute DeepSeek.
  • Node.js 22.13 or newer is still enough.

0.9.17 Added in 0.9.17 #

  • Migrations 0024 to 0030 add the tables of the DeepSeek usage card: the spend by model and by day, the balance it measures against and, in 0030, the figures of an imported usage export. They run by themselves on the first start, also on a relay that never uses DeepSeek, and touch no table an older version uses. An older version ignores them.
  • A Claude login token in the relay's environment (CLAUDE_CODE_OAUTH_TOKEN) reaches only Claude and Claude Cloud workers. Copilot, OpenAI, Cursor, Grok and DeepSeek workers are started without it, with or without tmux. See Which variables reach the agents.
  • ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN in the relay's environment reach no worker. Claude chats that ran on such a key now run on the host's Claude login. If the host has none, sign in with Relogin under Settings → Providers → Claude. See Environment variables.
  • A relay started from inside a Claude Code session no longer hands that session to its workers. Its variables are dropped for every worker, also under a tmux server that still carries them. Your own CLAUDE_CODE_* settings stay. See Which variables reach the agents.
  • A session that joins a group you ordered by hand comes first in the group, no longer last. See Session groups.
  • Node.js 22.13 or newer is still enough, and no setting or config.json key needs changing.

0.9.16 Added in 0.9.16 #

  • Three database migrations run by themselves on the first start: 0019 (the subscription options and the watcher's own prompts), 0020 (the switch Agents in this conversation may start sessions) and 0021 (which session groups an agent made, and your groups an agent emptied). They only add columns and a table. Going back to an older version needs no data change: it ignores them, keeps the one-level rule, and removes an empty group at its start as before.
  • Migration 0022 adds the table for scheduled prompts, with where each schedule's messages come from (origin_json, with their hops) and when a firing was held for you (held_since). It runs by itself on the first start, together with 0019 to 0021.
  • Migration 0023 adds the table for questions that don't block (relay_asks). It runs by itself on the first start as well. Going back to an older version ignores it.
  • Subscriptions that take question_asked also get question_answered, your answer to an ask, from now on.
  • The loop guard counts only your own messages as yours. Before 0.9.16 a relay event, the usage-limit follow-up or the note after a restart reset the count of prompts an agent may send other agents before you are asked, so two agents that watched each other could go on without you. Now only a message you write resets it, and agents in such a loop ask you sooner. See the rules.
  • Agents passing arguments an action does not take: create_session and update_session now refuse the call and change nothing; the other actions still run and name them in ignored. See Actions.
  • A watcher that waited for its own prompt's reply no longer gets that turn's turn_end as an event as well.
  • Node.js 22.13 or newer is still enough, and no setting or config.json key needs changing.

0.9.15 #

  • From 0.9.14 with a hand-made autostart task on Windows: switching to boot mode in 0.9.14 could delete an existing task of the same name (oar-relay, or the one from before the rename) without a copy. 0.9.15 keeps such a task and asks for --replace, which saves a copy first. If a task of yours is already gone, OAR has no copy of it.
  • Switching autostart no longer replaces anything OAR did not make. A boot task or launcher edited by hand, a task someone else made, the boot task from before the rename and a hand-made Startup entry now stop the switch, in the web UI as in oar autostart, where 0.9.14 replaced them. oar autostart <mode> --replace replaces them, keeping a copy of each. See Entries OAR did not make.
  • New commands: oar autostart and oar uninstall, and oar setup asks for the autostart mode on Windows. See The oar command.
  • The package is smaller: the developer READMEs, server/README.md with the HTTP API and the web-relay extension's, are no longer in it. They are in the repository on GitHub.
  • Node.js 22.13 or newer is still enough, and no setting or config.json key needs changing.

0.9.14 #

Windows autostart, or a relay a plain gh copilot started: save your data first

Before 0.9.14, a relay that Windows autostart started, or that a plain gh copilot started after oar copilot had installed its extension, ran on the database and uploads inside the installed package, and npm install -g deletes them with the old version. A relay you only started with oar start, oar restart or the Linux service already ran on the OAR data folder and needs none of the steps below.

0.9.14 copies that data first, while it installs, to rescued-package-data/<time>/ in the OAR data folder (%APPDATA%\oar\data, ~/.oar/data), and the relay takes the copy over at its next start. npm 10 and 11 run that copy (11.21 with a warning), and if it fails they put the old version back with its data. npm 12 skips it unless @oar-sh/oar is allowed: the install then succeeds and the old data is gone. With strict-allow-scripts, npm 11 and 12 refuse the install and change nothing. An allow-scripts entry in .npmrc does not help the Update button or oar update of 0.9.13, because their own --allow-scripts replaces it. To be safe, 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 it 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 every file in them, to a safe place.
  3. Update with npm's install scripts allowed: npm install -g --allow-scripts=@oar-sh/oar,better-sqlite3,koffi @oar-sh/oar. Never update with --ignore-scripts: it skips the copy and the native modules (better-sqlite3, koffi), so the relay cannot start afterwards.
  4. Before you start the relay, copy both folders back into the same server folder.
  5. Run oar start. In relay-console.log in the OAR logs folder, look for [data] Brought over the database …: your conversations should be back. A database that was already in the OAR data folder is kept in backups/<time>/ in the OAR folder (%APPDATA%\oar, ~/.oar). The folder brought over keeps its database as copilot.db.adopted-<time>; the others looked at keep theirs as copilot.db.older-<time>. Nothing is deleted.
  6. If the relay stops with [data] Not starting: each database has changes newer than the other's, both hold work. The line names both folders; one may be under rescued-package-data/<time>/data. Pick the one to keep, move the other one's copilot.db, copilot.db-wal and copilot.db-shm into a folder of your own (do not delete them), then run oar start again.
  7. If you already updated without saving and nothing was copied, OAR cannot recover the database from the package.

Also in 0.9.14:

  • A relay that cannot run on its data stops with exit code 78: when another relay holds its lock, when two databases both hold newer work, or when its data or upload folder cannot be created. The line before the exit says which and what to do. A systemd unit written by oar service install of 0.9.14 does not restart it; run oar service install again to get that unit. See One relay per data folder.
  • A large database takes minutes to bring over. The relay logs its size, progress at least once a minute and each step's time, and oar start says meanwhile that it is still bringing it over. Do not start a second relay.
  • Windows autostart now waits up to 5 minutes for %TEMP% and the data drive, and the first start after the update brings a generated entry or launcher up to date. See Autostart.
  • Cursor agent stores move to cursor-agents in the data folder, and uploads follow dataDir; uploads an earlier version left in server/uploads or in the state folder's uploads/ are still read where they are. See Files and folders.
  • Node.js 22.13 or newer is still enough.

0.9.13 #

  • Migration 0018 adds the table that keeps the task consoles across a relay restart, and runs by itself on the first start. The finished rows the relay before this update held in memory are lost one last time at the restart into it. Node.js 22.13 or newer is still enough.
  • New settings in Settings → General: Ask after a queued relay restart has waited (30 minutes by default) and After a relay restart, tell interrupted sessions to carry on (off by default). A new notification, Queued relay restart waited its maximum time, is on by default. See Settings and When the wait is long.
  • Watching agents: a subscription that named no events now leaves out shell commands that ended well; finished sub-agents and failures still wake it. One that named its events keeps them. Name task_finished to get every task end. See The default events.
  • Scripts that post a message without a model to an existing conversation now get the conversation's own model, effort and mode instead of the relay's first model, or a 409 with the code CONVERSATION_MODEL_UNAVAILABLE when that model has left the catalog. See Models and reasoning.
  • Agents that pass a model to relay_tool must use an id the target lists; an unknown one is now refused with REMOTE_RELAY_UNKNOWN_MODEL. See Which models are accepted.

0.9.12 #

  • Migration 0017 adds two indexes for the history of long conversations and runs by itself on the first start. Node.js 22.13 or newer is still enough, and no setting or config.json key needs changing.
  • Two new settings in Settings → General: Mark a background task as quiet after (10 minutes by default, for the relay) and Messages kept per conversation for switching back (200 by default, in each browser). See Settings.
  • Claude background commands may run for 2 hours by default and up to 8 when Claude asks: Settings → Providers → Claude → Claude background command limit. OAR now sets BASH_DEFAULT_TIMEOUT_MS, BASH_MAX_TIMEOUT_MS and CLAUDE_CODE_AUTO_BACKGROUND_TIMEOUT_MS for its Claude sessions, so values of these in the relay's environment no longer apply. See Background command limit.
  • Sessions that run while you update keep their agent until it starts again, and show no output in a command's console until then. See Sessions that were running.

0.9.11 #

  • Behind a reverse proxy on another machine, set trustProxy and allowedOrigins. 0.9.11 is the first release that checks the origin of the live connection and reads the client address, host and scheme from X-Forwarded-* headers only when the proxy is trusted. A proxy or tunnel on the relay's own machine is trusted already. For one on another machine, or one that rewrites the Host header, add the two keys to config.json and restart the relay. Without them the page loads but gets no live updates, and every client shares the proxy's address and its sign-in lockout. See A proxy on another machine.
  • Ten wrong tokens from one address within a minute answer 429 until the minute is over. Requests from the relay's own machine that nothing forwarded are never counted. See Protections on sign-in.
  • ?token= works on the page address only. Scripts that fetch API, file or asset addresses with ?token= must send Authorization: Bearer <token> instead, or the cookie; a Socket.IO client passes it as auth.token. See Ways to present it.
  • Restart web relay, cancelling a queued restart and Empty queue need only the token, from any signed-in device. The session-worker socket and the run of image operations answer only requests from the relay's machine that no tunnel or proxy forwarded. See Endpoints only the relay's machine may use.
  • Four database migrations (previews, session groups, the place in a group, the share access log) run by themselves on the first start. Node.js 22.13 or newer is still enough.
  • Dependencies are pinned. The packages OAR uses directly, the Claude, Copilot and Cursor SDKs among them, are installed in the exact versions the release was tested with; a newer one arrives with an OAR update.

What changed #

The changelog is on oar.sh and in the repository as CHANGELOG.md. Each release also has release notes on GitHub, which the release notes link in Settings → General opens. Steps an update needs from you are under Upgrade notes in a release's entry, when it has any.

If it does not work #

What you see What to do
The check finds nothing Press Check for updates and read the line next to it. Update check failed — the update server could not be reached means the relay host did not get an answer from oar.sh within 5 seconds; check its network and proxy. Never checked. after pressing it means the same
The switch and the button are disabled OAR_NO_UPDATE_CHECK=1 is set for the relay. Unset it and restart the relay, or use oar update --to <version>
Could not fetch <url>. from oar update The terminal cannot reach the manifest, or OAR_UPDATE_MANIFEST_URL is wrong. Try oar update --to <version>
The update fails with a permissions error (EACCES) npm cannot write to the folder the package is in. Do not use sudo. Run the installer on macOS or Linux, or give your user a global npm folder it owns; see Install
The update ran but the relay did not come back The restart waits for running turns; look for the banner and wait or cancel it. If the relay is down, start it with oar start and read the log in the relay's log folder
The version is unchanged after an update The line Update to <version> did not apply. and the log under it say why. Run oar update from a terminal, or oar update --to <version>, and watch npm's output
oar update says Already up to date on a beta you want to leave Use oar update --to <stable version>
Update is missing The relay runs from a git checkout, the update was dismissed, or no newer version is known yet. Press Check for updates first