所有页面
本页内容

oar 命令

oar 是中继所在机器上的命令行。它写入配置文件,启动和停止中继,打印你在浏览器中打开的地址,安装登录时启动的服务,更新 OAR,检查安装情况,也能把它再卸载掉。它作用于启动它的那个安装,并且只在它运行的那台机器上起作用;它不会与另一台机器上的中继通信。

不带任何参数运行 oar 会显示一个菜单,运行 oar help 会显示用法说明。如何安装 OAR 见安装,首次启动见首次运行。

命令 #

命令 作用
oar 在终端中显示菜单;在其他地方显示状态和用法说明
oar setup 写入配置文件:认证令牌、访问范围(仅本机或局域网)和端口;在 Windows 上还有自启动模式
oar start 在后台启动中继
oar stop 在没有正在运行的轮次时停止中继
oar restart 重启正在运行的中继,或启动已停止的中继
oar status 报告中继是否在运行;退出代码为 0 或 3
oar url 打印带令牌的中继地址,并在手机可以使用该地址时打印二维码
oar update 安装最新版本或你指定的版本,并重启中继
oar service 安装、移除或报告登录时启动的服务
oar autostart 0.9.15 新增 切换中继自行启动的方式:登录时、开机时或关闭
oar uninstall 0.9.15 新增 移除自启动条目和软件包;数据会保留,除非你加上 --purge
oar copilot 启动中继和一个 GitHub Copilot 终端会话
oar doctor 打印安装情况、配置文件和它找到的提供商 CLI
oar help 打印用法说明
oar version 打印版本

大多数消息以 [oar] 开头。错误输出到标准错误,正常输出到标准输出。

如何解析命令行 #

  • 命令是第一个不是选项的词。选项可以出现在它前面:oar --port 3400 setup 等同于 oar setup --port 3400。
  • --port、--migrate-from、--to 和 --autostart 需要一个值,可以作为下一个词,也可以写成 --port=3400。缺少值时,oar 会打印 --port needs a value. 并以 2 退出。对于 oar update --to 和 oar copilot --migrate-from,请使用以空格分隔的写法;参见这些命令下的说明。
  • 出现在 -- 之前的 --help 或 -h 会打印用法说明并以 0 退出,无论这一行上还有什么。
  • 没有给出其他命令时,--setup、--start、--stop 和 --status 表示对应的命令:oar --setup --start 等同于 oar setup --start。
  • 没有命令时,--install-extension、--no-install-extension、--migrate-from 或 -- 部分表示 oar copilot。没有命令时,--version 或 -v 打印版本。
  • 每个命令只接受自己的选项;否则会(向标准错误)打印下列消息之一,再打印用法说明,退出代码为 2:
[oar] Unknown command: backup
[oar] Unknown option: --verbose
[oar] Unknown option for oar start: --port
[oar] Unexpected argument: extra
[oar] --lan needs a command.
[oar] oar start takes no "--" part.

只有 oar copilot 接受 -- 部分。

在终端中,oar 会显示版本、中继是否在运行、URL(不带令牌)、端口、访问范围、服务状态和任何警告,然后是以下条目:

键 条目 运行
1 Start(启动) oar start
2 Stop(停止) oar stop
3 Restart(重启) oar restart
4 Show URL and QR code(显示 URL 和二维码) oar url
5 Settings(设置) oar setup,包括它的提问
6 Install or remove the service(安装或移除服务) 未安装服务时运行 oar service install;已安装时,在 Remove the service? [y/N] 之后运行 oar service remove;在不支持服务的地方运行 oar service status
7 Update(更新) oar update。更新成功后菜单会关闭,因为它自己的文件已被替换
8 Doctor(诊断) oar doctor
9 Copilot session(Copilot 会话) oar copilot
q Quit(退出)

用方向键(或 j 和 k)移动并按 Enter,或者按数字键或 q。某个条目运行完后,按任意键返回菜单。在提问中按 Ctrl+C 会返回菜单;在菜单中按 Ctrl+C 会以退出代码 130 结束 oar。环境变量 NO_COLOR 会关闭颜色。无法读取单个按键的终端会得到同样的列表,并带有 Choose (1-9, q): 提示。

当标准输入或输出不是终端时,oar 会打印 oar status 所打印的内容、一个空行和用法说明,并以 0 退出,无论状态如何。

oar setup #

oar setup [--port <port>] [--lan | --local] [--new-token] [--autostart signin|boot|off] [--defaults] [--start] [--migrate-from <dir>]

在 OAR 的状态文件夹中写入 config.json(oar 在哪里保存它的文件;各个键见 config.json)。安装之后运行它,以后每当你想换一个端口、访问范围或令牌时也运行它。该命令不涉及的设置在现有配置文件中保持原样。

在终端中,并且你没有传入 --port、--lan、--local、--new-token、--autostart 或 --defaults 中的任何一个时,它会提出三个问题,并在方括号中显示当前值;按 Enter 保留该值。0.9.15 新增 在 Windows 上,第四个问题询问中继如何启动,默认值是当前生效的模式;无法读取开机任务时会省略这个问题。首次运行会逐一讲解这些问题。

New auth token? It signs every device out. [y/N]
Access: 1 = this machine only, 2 = LAN (other devices on your network) [1]:
Port [3333]:
Autostart: 1 = at sign-in, 2 = at boot, before anyone signs in (one administrator prompt), 3 = off [3]:
选项 值 默认值 效果
--port 数字,1 到 65535 配置文件中的端口;对新配置文件,是从 3333 往上的第一个空闲端口(尝试 20 个,否则为 3333) 不经询问直接设置端口。被其他程序占用的端口会被拒绝
--lan 无 配置文件中的访问范围 允许你网络中的其他设备访问(localhostOnly: false)。不能与 --local 同时使用
--local 无 配置文件中的访问范围;新配置文件为 this machine only(仅本机) 只允许本机访问
--new-token 无 保留令牌;新配置文件会得到一个随机令牌 写入新的认证令牌。这会让所有设备退出登录
--autostart signin、boot 或 off 当前生效的模式 0.9.15 新增 不经询问直接切换自启动,与 oar autostart 相同:在 Windows 上是登录条目或开机任务(一次管理员提示),在 Linux 上是服务。仅限全局安装:git 检出会被拒绝,并且不写入任何内容
--defaults 无 关闭 什么都不问,即使在终端中也是如此,并且不经询问就重启正在运行的中继
--start 无 关闭 仅限全局安装(安装程序会使用它)。存在 systemd 用户会话时,它还会写入服务 unit;然后启动中继,有服务时通过服务启动。在 git 检出中会被忽略
--migrate-from 一个文件夹 无 把项目改名之前的 git 检出的状态(<folder>/server)复制到 OAR 的状态文件夹中。源文件夹从不会被更改。仍从该处运行的中继会阻止复制。仅限全局安装。每次你指定一个文件夹时它都会运行:已经迁移过且其数据库仍在的文件夹只会显示 <state folder> is already migrated from <folder>; nothing to do.;没有可迁移内容的文件夹会报错(Nothing to migrate from <folder>: <reason>.);数据库中已有对话的状态文件夹会拒绝迁移,且不会覆盖任何内容。参见文件与文件夹

当端口上没有任何程序应答,并且可以在本机上绑定它时,该端口即为空闲。本安装自己正在运行的中继所用的端口算作空闲。在 WSL 中,Windows 占用的端口也会被拒绝。对于端口 3333 已被占用的新配置文件,setup 会显示 Port 3333 is in use — using <port>. 全局安装还会自动从之前的托管配置文件夹接管一次状态,无需该选项。

它的执行步骤:

  1. 迁移旧状态(全局安装):自动迁移一次之前的托管配置文件夹,或迁移 --migrate-from 指定的文件夹。[oar] Migrated <folder or "earlier relay state"> into <state folder> (<n> items, sources untouched; receipt in backups/MIGRATION.md).
  2. 写入 config.json(在 Windows 以外的系统上权限为 600)并打印 [oar] Wrote <path>。新配置文件包含 authToken、port、localhostOnly、pollIntervalMs(3000)、processingTimeoutMs(600000)和 conversationSessionMode(isolated)。
  3. 0.9.15 新增 按 --autostart 或提问的回答切换自启动(全局安装)。它以该模式运行 oar autostart 并打印其输出行。
  4. 如果中继正在运行,并且令牌、端口或访问范围发生了变化,它会重启中继,并等待中继以新设置应答。在终端中,它会询问 The relay is running. Restart it now to apply the change? [Y/n];回答否时,它会打印 The running relay keeps its earlier settings until it restarts: oar restart。没有终端时,它不经询问直接重启。
  5. 打印带令牌的中继 URL,并在手机能访问该地址时打印二维码(局域网访问,且网络地址不是 WSL 内部地址)。如果自启动步骤没有成功,它随后会显示 The config is written; the autostart step did not go through (see above). 并以 1 退出。
  6. 中继未运行时,说明如何启动它:oar start(不存在服务时附带关于 oar service install 的提示);在 git 检出中则是 npm start。
退出代码 情形
0 配置文件已写入,并且所要求的重启或启动成功
1 端口被占用;中继没有重启或没有启动起来;迁移被拒绝或失败(有中继从源文件夹或在状态文件夹上运行、数据库中已有对话、你指定的文件夹中没有可迁移的内容);自启动步骤没有成功;在 git 检出中使用 --autostart
2 --port 不是 1 到 65535 之间的数字(--port expects a number from 1 to 65535.)、--autostart 不是 signin、boot 或 off(--autostart expects signin, boot or off.),或同时给出了 --lan 和 --local
130 在提问中按 Ctrl+C

oar start #

oar start

在后台启动中继,并打印中继 URL(带令牌,不带二维码)。它没有选项。它需要配置文件:没有配置文件时,它会打印 No config yet — run: oar setup。git 检出会被拒绝(This is a git checkout — start the relay with: npm start)。两者都以 1 退出。

  • 已经在应答的中继不会被改动:The relay is already running. It keeps the version and settings it started with until you restart it: oar restart。
  • 如果中继仍以某次 oar setup 之前的设置运行,oar start 会说明这一点并指向 oar restart。
  • 安装了 systemd 用户服务时(Linux),会启用并启动该服务。否则中继会作为后台进程启动,该进程在终端关闭后继续存在,并把 server.log 和 server-err.log 写入日志文件夹。重启机器后,请再次运行 oar start,或设置登录时启动。
  • 它最多等待 20 秒让中继应答;如果它启动的进程结束了,就提前停止等待。随后显示:The relay did not come up — see <log folder>/server-err.log(通过服务启动时:see journalctl --user -u oar)。0.9.14 新增 当一个存活的中继持有锁时,第二行会指出该锁并说明该怎么做:The lock <path> is held by relay process <pid> (started <time>): oar stop, or end process <pid>. 当锁中记录的进程无法确认是中继时:The lock <path> names process <pid>, which cannot be told to be a relay: if no relay is running, end process <pid> or delete the lock.
  • 0.9.14 新增 仍在迁移它此前所用数据库的中继(更新到 0.9.14 后的首次启动)不算作启动失败:oar start 会显示 The relay (process <pid>) is bringing over the database it ran on until now (…) and is still running; it answers once that is done. 并指出它的日志。
  • 对于其中继仍在启动的锁,会最多等待 5 秒。旧版本留下的、其中继不应答的锁会被删除(Removing a leftover relay lock);0.9.14 新增 本版本写入的锁则留给中继处理,中继自己会识别过时的锁(参见每个数据文件夹一个中继)。
  • 被其他程序占用的端口,或使用其他令牌的中继:Port <port> is in use by another program, or by a relay with another token.,并提示用 oar setup --port <port> 换一个端口。
  • 在 WSL 中,Windows 占用该端口时它会发出警告(WSL)。

退出代码 0:中继在运行,或仍在迁移其数据库。退出代码 1:没有配置文件、git 检出、端口被占用,或中继没有启动起来。

oar stop #

oar stop

没有选项;需要配置文件(没有时以 1 退出)。

  • systemd 服务正在运行时,它会立即运行 systemctl --user stop oar 并显示 The relay service is stopped. It starts again at the next boot (without lingering: at the next login); to take it out: oar service remove。
  • 其他任何中继都会通过它自己的接口收到停止请求,并在没有正在运行的轮次时停止。如果有轮次正在运行,会打印 Waiting for the relay's running turns to finish …。oar stop 最多等待 30 秒,然后打印 The relay is stopped. 或 The relay is still busy; it stops by itself when its running turns finish. 两种情况都以 0 退出。
  • 没有中继在运行:The relay is not running.,以 0 退出。
  • 端口被其他程序占用:Port <port> is in use by another program, or by a relay with another token.,以 1 退出。如果锁文件记录的是本安装的一个存活进程,第二行会给出它的进程 id,并让你从它的网页界面用 ⋯ → Restart web relay(⋯ → 重启网页中继)重启它,或结束该进程。
  • The relay did not accept the stop request. 或 systemctl 失败:以 1 退出。

在 Windows 上,以及在服务已安装但未运行的地方,中继通过它自己的接口停止。停止对正在运行的轮次有什么影响,参见重启中继。

oar restart #

oar restart

重启正在运行的中继,使它加载新版本并重新读取配置文件,然后打印中继 URL。已停止的中继会改为启动,与 oar start 相同。没有选项;需要配置文件。

  • systemd 服务正在运行时,systemd 会立即重启它;正在运行的轮次会结束(重启中继)。
  • 其他任何中继都会收到重启请求,并等待其正在运行的轮次。该命令最多等待 60 秒,直到中继在配置文件的端口上以配置文件的令牌应答,然后打印 The relay restarted. 如果仍有轮次在运行:The relay is still busy; it restarts by itself when its running turns finish.,以 0 退出。0.9.13 新增 这次重启会像 🌄 Restart web relay 一样排队:浏览器会显示它的横幅,并在 Ask after a queued relay restart has waited(排队的中继重启等待多久后询问)之后,在那里询问是立即重启、继续等待还是取消(重启会等待)。
  • 以 1 退出并显示 The relay came back on its earlier port and token: it was started with fixed ones (oar copilot). End that session, then run: oar start:由 oar copilot 启动的中继会保留分配给它的端口和令牌。
  • 以 1 退出并显示 The relay did not accept the restart request. Restart it from the web UI (⋯ → Restart web relay).(Restart web relay)、systemctl --user restart oar failed 或 The relay did not come back — see <log folder>/server-err.log(通过服务时:see journalctl --user -u oar)。
  • 端口被其他程序占用:与 oar stop 相同的消息,以 1 退出。

oar status #

oar status

打印中继的状态,并以脚本可以检测的代码退出。

[oar] OAR 0.9.19
[oar] The relay is running on port 3333 (this machine only): http://localhost:3333/
[oar] Service: installed, running
行 含义
Not set up yet — run: oar setup 没有配置文件;它前面只有版本行
The relay is running on port <port> (<access>): <url> 中继以配置文件的令牌应答。访问范围为 LAN access(局域网访问)或 this machine only。URL 不带令牌;oar url 会打印带令牌的 URL
The relay is stopped (port <port>, <access>). Start it with: oar start 端口上没有任何程序应答
Port <port> is in use by another program, or by a relay with another token. 有程序应答,但不是使用此令牌的本中继
Service: <state> installed, running(已安装,运行中)、installed 或 not installed(未安装)。没有可报告的内容时会省略:git 检出、macOS、没有 systemd 用户会话的 Linux
Tunnel: <state> 仅当配置文件中开启了内置的 Cloudflare 隧道时显示。对于正在运行的中继:running、not connected、not connected (<reason>) 或 off: <reason>。否则为 managed (cloudflared: <path>) 或 managed, cannot start: <reason>
一条警告 在更改了端口或令牌的 oar setup 之后显示 The relay runs with its earlier settings; restart it to apply the new ones.;在 WSL 中,警告 Windows 占用了该端口

退出代码 0:中继在运行。退出代码 3:中继已停止、端口被其他程序占用,或没有配置文件。

oar url #

oar url

打印要在浏览器中打开的地址,带认证令牌,与 oar setup 结束时的方式相同。没有选项;需要配置文件(没有时以 1 退出)。其他情况以 0 退出。

[oar] Relay URL: http://localhost:3333/?token=...
[oar] This machine only. For a phone, switch on LAN access (oar setup --lan) or use a tunnel (README: Remote access).
  • 启用局域网访问时,地址是本机第一个非内部 IPv4 地址,第一行之后会跟着它的二维码。
  • 启用了局域网访问但没有网络地址时:LAN access is on, but this machine has no network address. 在 WSL 默认的(NAT)网络模式下,地址是 WSL 内部地址;输出会说明这一点,并给出隧道或镜像网络模式作为解决办法。这些情况下没有二维码。
  • 当正在运行的中继报告了隧道地址时,后面会跟一行加上了令牌的 Tunnel URL:,以及它的二维码。
  • 最后一行显示 The relay is not running. Start it with: oar start,或者在设置更改之后,说明中继在 oar restart 之前仍以之前的设置运行。

oar update #

oar update [--beta] [--to <version>]

从 npm 安装更新的 OAR 版本,并请求正在运行的中继重启。它是 Settings → General(设置 → 常规)中 Update 按钮在终端里的对应物(更新 OAR)。git 检出会打印 This install runs from a git checkout — update with git pull, then restart the relay. 并以 1 退出。

选项 值 默认值 效果
--beta 无 关闭 从更新清单中取 beta 通道的版本(通道)。不加该选项时,beta 版本跟随 beta 通道,其他版本跟随 stable。没有版本的通道会回退到 stable
--to X.Y.Z,可以带预发布后缀(X.Y.Z-beta.N) 该通道的最新版本 不经清单,直接从 npm 安装这个确切的版本。较旧的版本也可以;它不会与正在运行的版本比较

--to 后面要用空格

--to 0.9.2 可以。--to=0.9.2 能通过命令行检查,但会被忽略:oar update 随后会安装该通道的最新版本。

它的执行步骤:

  1. 不带 --to 时,每次运行都会获取 https://oar.sh/latest.json(5 秒),无论网页界面中的自动检查是否开启。
  2. 如果该通道的版本不比正在运行的版本新:Already up to date (<version>).,以 0 退出。
  3. 打印 Updating @oar-sh/oar <old> -> <new> ... 并运行 npm install -g @oar-sh/oar@<version>,带上允许 OAR 及其原生依赖运行安装脚本的标志。在 Windows 以外,它运行与运行 oar 的 Node.js 位于同一处的 npm,安装到软件包所在的前缀中;在 Windows 上则运行 npm.cmd。npm 会打印它自己的输出;然后显示 Installed @oar-sh/oar@<version>.
  4. 如果有中继在运行,请求它在队列空闲后重启(Relay restart requested — it restarts once the queue is idle.);没有中继时显示 No running relay detected — the update loads on the next start. 请求被拒绝时会打印 Could not request a relay restart; restart it manually to load the update.

退出代码 0:已安装,或已是最新版本。退出代码 1:git 检出;--to 不是 0.9.2 这样的版本;无法获取清单(Could not fetch <url>.)、清单的 schemaVersion 不是 1,或其中没有可用的版本;npm install 失败(the running install is unchanged)。

变量 效果
OAR_NO_UPDATE_CHECK=1 阻止清单请求。oar update 随后会以 1 退出并指向 oar update --to X.Y.Z,后者仍然可用
OAR_UPDATE_MANIFEST_URL 改为从这个 URL 读取清单

oar service #

oar service [install | remove | status]

在每次登录时启动中继。单独的 oar service 等同于 oar service status。git 检出会被拒绝(以 1 退出)。登录时启动页面从所有者的角度说明这项服务。

Linux #

一个 systemd 用户 unit,即 ~/.config/systemd/user/ 中的 oar.service。它以本安装的配置、数据和日志文件夹,以及你的 shell 的 PATH(加上 ~/.local/bin 和所用 Node.js 的文件夹)运行中继。崩溃 5 秒后,systemd 会重启它。

词 作用
install 需要配置文件。写入 unit;运行 loginctl enable-linger,使中继在退出登录后继续运行(如果失败,会打印需要你自己运行的命令);重新加载 systemd;停止你手动启动的中继,让服务可以接管端口;启用并启动服务。如果那个中继没有停止,服务会被启用,并在下次开机时接管(没有 lingering 时则在下次登录时),或者在那个中继停止并且你运行 oar start 之后接管
remove 禁用并停止服务,删除 unit,重新加载 systemd。没有服务时显示 The service is not installed.
status Service: installed, running、installed, not running 或 not installed

没有 systemd 用户会话时,该命令会说明这一点并以 1 退出。在 WSL 中,消息还会说明如何开启 systemd:在 /etc/wsl.conf 的 [boot] 下设置 systemd=true,然后在 Windows 中运行 wsl --terminate <distro>。

Windows #

你的 Startup 文件夹中的一个条目会在你登录时启动中继。

词 作用
install 需要配置文件。开启登录时启动;它不会立即启动中继(Start it now with: oar start)
remove 关闭登录时启动:Autostart is off. A running relay keeps running; stop it with: oar stop
status Autostart: on, at sign-in、on, at boot (scheduled task) 或 off

通过计划任务实现的开机启动,可以用 oar autostart boot 设置,也可以在网页界面的 Settings → General → Autostart (Windows)(设置 → 常规 → 自启动,Windows)中设置(Windows)。只要该任务处于就绪状态,install 和 remove 就会拒绝执行(以 1 退出),并显示 The relay starts at boot through a scheduled task. Change that with oar autostart signin|off, or in the web UI: Settings → General → Autostart (Windows).;status 会报告它。

macOS #

The service is not supported on macOS yet. Start the relay with: oar start,每个词都以 1 退出。

退出代码 0:完成,或 status。退出代码 1:git 检出、macOS、没有 systemd 用户会话、install 时没有配置文件、Windows 上有计划的开机任务,或 install 之后中继没有启动起来。退出代码 2:这三个词以外的词,或第二个词。

oar autostart 0.9.15 新增 #

oar autostart [signin | boot | off | status] [--replace]

切换本安装的中继自行启动的方式。单独的 oar autostart 等同于 oar autostart status。git 检出会被拒绝(This is a git checkout — autostart is for global installs.,以 1 退出)。signin 和 boot 需要配置文件;off 和 status 不需要。自启动从所有者的角度说明各种模式。

Windows #

词 作用
signin 在你的 Startup 文件夹中写入条目;如果有开机任务,则将其删除(一次管理员提示)。打印 The relay starts when you sign in to Windows. 它不会立即启动中继
boot 注册计划任务 oar-relay 及其启动器(一次管理员提示:Confirm the administrator prompt to register the boot task …),并删除登录条目。打印 The relay starts at boot, before anyone signs in (scheduled task \oar-relay). 已处于开机模式时,它不做任何更改,也不请求提示;如果生成的启动器缺失或来自较早的版本,它会重新注册任务,需要一次管理员提示
off 删除开机任务(一次管理员提示)和登录条目。Autostart is off. A running relay keeps running; stop it with: oar stop
status 模式和每个条目,每个条目标为 (generated by OAR) 或 (hand-made);参见状态

管理员提示出现在这台电脑自己的桌面上,最多等待 2 分钟。只有 schtasks 调用以提升的权限运行。拒绝提示不会更改任何内容(Nothing changed: the administrator prompt was declined.)。使用 --replace 切换后,每份副本都会被列出:Kept a copy of <entry> as <copy>。在提示之后失败的切换会恢复它删除的任务,其错误行以 Copies kept: … 结尾。

只有 OAR 生成的条目才会被删除或覆盖。只要某个手动创建或编辑过的条目会留在新模式旁边,或会被新模式替换,就不会做任何更改,并会指出该条目;参见不是 OAR 创建的条目。

选项 效果
--replace 用 OAR 自己的条目替换手动创建的条目。它会先为每个条目保留一份副本,即 OAR 文件夹中的 <name>.bak:启动器的副本在启动器旁边,任务的副本是导出的 XML(<task>.task.xml.bak),Startup 条目也有副本。不加 --replace 时,手动创建的条目永远不会被更改

无法读取的开机任务,例如 Access is denied(拒绝访问),会阻止每一次切换,包括 --replace:Nothing changed: the boot task could not be read (<reason>).

Linux 和 macOS #

在 Linux 上,这些词对应 oar service:signin 和 boot 运行 oar service install,off 运行 oar service remove,status 运行 oar service status。有 lingering 时,服务会在开机时启动。在 macOS 上:Autostart is not supported on macOS yet. Start the relay with: oar start,以 1 退出。

退出代码 0:完成,或 status。退出代码 1:git 检出、macOS、signin 或 boot 时没有配置文件、有手动创建的条目挡路、管理员提示被拒绝或失败、无法读取开机任务,或无法更改登录条目;在 Linux 上,还有 oar service 的那些情形。退出代码 2:其他词、第二个词或其他选项。

oar uninstall 0.9.15 新增 #

oar uninstall [--purge]

把 OAR 从这台机器上移除,同时保留你的数据。git 检出会被拒绝(This is a git checkout — there is no global package to uninstall.,以 1 退出)。使用 --purge 时,它会先提出它的问题(见下文);然后依次:

  1. 停止中继,与 oar stop 相同:它会等待正在运行的轮次。之后仍然繁忙的中继会让命令结束(The relay finishes its running turns first; it stops by itself after them.),其他任何内容都不会被更改。持有锁却不应答的中继(正在迁移数据库或正在启动)也会让命令结束:The relay (process <pid>) is bringing over its database and does not answer yet; once oar status says it runs, run oar uninstall again.,或 A relay (process <pid>) holds <lock> without answering; stop it (oar stop, or end process <pid>).
  2. 删除 OAR 为本安装生成的自启动条目:在 Windows 上是开机任务(一次管理员提示)及其启动器和任务 XML,以及登录条目;在 Linux 上是 systemd unit,前提是它就是 oar service install 写入的那个。然后删除 OAR 为本安装写入的、位于 ~/.copilot/extensions/web-relay/ 中的 Copilot 扩展包装器。手动创建或更改过的条目或包装器,或属于另一个安装的,会保留并被指出(Left as it is: <path> (hand-made))。
  3. 使用 --purge 时,删除数据(见下文)。
  4. 在后台启动 npm uninstall -g @oar-sh/oar,使用与运行 oar 的 Node.js 位于同一处的 npm,作用于软件包所在的前缀(在 Windows 上是 npm.cmd)。npm 无法移除正在运行的软件包,因此它会等到 oar 结束(最多 2 分钟),然后把 npm 的结果写入 oar-uninstall.log:位于 OAR 的 logs 文件夹中,使用 --purge 时位于临时文件夹中。

最后它会列出它做了什么:

[oar] Done: stopped the relay.
[oar] Done: removed C:\Users\dev\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\oar-web-relay.cmd.
[oar] Your data stays in C:\Users\dev\AppData\Roaming\oar (config, database, uploads, logs). A later install picks it up again; delete the folder yourself if you no longer need it.
[oar] npm removes @oar-sh/oar once this command has ended (log: C:\Users\dev\AppData\Roaming\oar\logs\oar-uninstall.log).

当数据文件夹位于状态文件夹之外时,这一行会同时列出两者。中继停止时,会话 worker 会继续运行,而 npm 无法移除正在运行的程序所占用的文件。当仍有程序从该软件包运行时,命令会列出它们的进程 id,npm 会把它们的文件留在软件包原来位置旁边的一个隐藏 .oar-* 文件夹中;日志会指出该文件夹。等它们结束后删除它,最迟在重启机器之后。

如果某个步骤失败,命令会停止并说明原因(例如 Uninstall stopped: <reason>. 或 The relay did not stop.),然后显示 Done: … 和 Not done: the autostart entries; the package.(使用 --purge 时还有 the data),以及 Run oar uninstall again once that is sorted out.(使用 --purge 时:oar uninstall --purge)。

选项 效果
--purge 还会永久删除状态文件夹:配置文件、包含所有对话的数据库、上传的文件和日志。它会先显示 --purge deletes <folder> for good: …,然后要求你输入 delete(Type "delete" to confirm: );输入其他任何内容都会以 Not confirmed. Nothing was changed. 结束。按 Ctrl+C 或没有可读取的输入时,以退出代码 130 结束,且不更改任何内容

使用 --purge 时,有些文件夹会在输入 delete 之后单独询问一次([y/N]):位于 git 检出内的状态文件夹、rescued-package-data(较早版本保存在其软件包内的数据),以及状态文件夹之外的数据文件夹(配置文件中的 dataDir,或 COPILOT_WEB_RELAY_DATA_DIR)。无论你输入什么,对于以下状态文件夹,--purge 都不会删除其中的任何内容:驱动器或文件系统的根目录、你的主文件夹或其上级文件夹、系统文件夹或其上级文件夹、Windows 文件夹内的文件夹、git 检出,或者其中没有 OAR 配置文件或数据库的文件夹:--purge deletes nothing in <folder> (<reason>). Nothing was changed. 这样的额外文件夹不会被列为可删除项(Not deleted, and not offered: …)。

退出代码 0:已开始移除软件包。退出代码 1:git 检出;--purge 拒绝的状态文件夹;没有输入 delete;中继没有停止,或持有锁却不应答;无法删除某个自启动条目(提示被拒绝、无法读取开机任务);无法删除某个文件夹;无法启动 npm(remove it yourself: npm uninstall -g @oar-sh/oar)。退出代码 2:其他选项。退出代码 130:在提问时按 Ctrl+C。

oar copilot #

oar copilot [--port <port>] [--install-extension] [--no-install-extension] [--migrate-from <dir>] [-- <gh copilot args>]

如果没有中继应答,就启动中继,然后在你的终端中运行 GitHub Copilot CLI(gh copilot)。它启动的中继会在会话结束时停止。GitHub Copilot 说明何时使用它。不带 copilot 这个词的相同选项仍会运行它:oar -- <args>、oar --install-extension、oar --port 3400 --no-install-extension。

选项 值 默认值 效果
--port 1 到 65535 配置文件中的端口,否则为 3333 本次运行在这个端口上查找或启动中继,不更改配置文件;本命令创建的配置文件会保存它。已在该端口上运行的中继会被使用。不是端口号的值会被忽略,且没有任何提示
--install-extension 无 关闭 写入或刷新 ~/.copilot/extensions/web-relay/ 中用户全局的扩展包装器(COPILOT_CONFIG_HOME 会移动 ~/.copilot),然后退出。不需要 gh
--no-install-extension 无 关闭 本次运行跳过包装器。不加该选项时,每次运行都会写入或刷新它
--migrate-from 一个文件夹 无 与 oar setup 相同。要用空格隔开:--migrate-from=dir 会被忽略
-- 该行的其余部分 无 在 gh copilot 自己的 -- 之后传给它

依次执行:检查 gh 是否存在;刷新包装器(失败会被报告,但只会让 --install-extension 停止);迁移旧状态(全局安装);在端口上查找中继;如果中继不应答就启动它,最多等待 20 秒(Relay did not become ready at <url>);然后在当前文件夹中运行 gh copilot,并连接终端。已经在运行的中继会继续运行。缺少的配置文件会被创建,访问范围为仅本机。

出现在 -- 之前的 --help 或 -h 会打印通用的用法说明,而不是 copilot 专用的说明。出现在 -- 之后的 --help 或 -h 会打印 oar copilot 的用法并以 0 退出。出现在 -- 之后的 --install-extension 和 --no-install-extension 也会被 oar 读取。它们都不会传给 gh。

Copilot 会话的中继使用启动它时给定的端口和令牌。oar restart 无法改变它们;参见 oar restart。

退出代码 情形
gh copilot 的退出代码 会话已运行(如果 gh 被信号结束则为 1)
0 --install-extension 写入了包装器
1 未安装 gh(The Copilot session needs the GitHub CLI (gh)...);使用 --install-extension 时无法写入包装器;端口被占用;中继没有就绪;中继仍在迁移其数据库;状态迁移失败(被阻止的迁移会被报告,Nothing was migrated; starting on the state root as it is.,会话仍会启动)

oar doctor #

oar doctor

打印 oar 找到的内容。没有选项,不更改任何内容,以 0 退出。

OAR 0.9.19
  node          : v22.13.0 (linux)
  mode          : global install
  state root    : /home/dev/.oar
  config        : /home/dev/.oar/config.json
  port          : 3333 (localhostOnly: yes)
  auth token    : set
  tunnel        : disabled
  database      : /home/dev/.oar/data/copilot.db (12.4 MB)
  provider CLIs :
    gh (Copilot)  : gh version 2.60.0 (2025-01-01)
    claude        : 2.1.0 (Claude Code)
    grok          : not found
    cursor        : bundled (@cursor/sdk)
行 含义
mode global install 或 git checkout
state root 状态文件夹;在 git 检出中为 (repo-local server/)
config 配置文件路径,没有配置文件时附带 (missing — run: oar setup);此时会省略 port、auth token 和 tunnel
port 配置文件中的端口;localhostOnly: yes 表示仅本机,no 表示网络
auth token set 或 MISSING
tunnel disabled、managed (cloudflared: <path>) 或 managed, cannot start: <reason>
database 路径和以 MB 为单位的大小,或 (not created yet)
provider CLIs gh (Copilot)、claude 和 grok:<cli> --version 输出的第一行(截断到 60 个字符),没有输出时为 installed,命令失败或不存在时为 not found(5 秒限制)。cursor 始终为 bundled (@cursor/sdk):Cursor 不需要 CLI
warning 在 WSL 中,Windows 占用了中继的端口时显示

oar help 和 oar version #

oar help          # also: oar --help, oar -h, oar <command> --help
oar version       # also: oar --version, oar -v

help 打印用法说明。version 打印已安装的版本,例如 0.9.19。两者都以 0 退出。--version 和 -v 只在没有命令时有效。

oar 在哪里保存它的文件 #

oar 作用于一个安装:启动它的软件包及其状态文件夹。

安装 状态文件夹 配置文件 数据 日志
全局安装,macOS 和 Linux ~/.oar 其中的 config.json data/ logs/
全局安装,Windows %APPDATA%\oar 其中的 config.json data\ logs\
git 检出 检出目录中的 server/ server/config.json server/data/ ~/.config/copilot-remote/logs(Windows:%LOCALAPPDATA%\copilot-remote\logs);npm start 写入 server/logs

OAR_STATE_ROOT 会移动全局安装的状态文件夹。包含 .git 的软件包文件夹算作 git 检出。数据文件夹中有数据库 copilot.db、锁文件 relay-server.lock,以及在某次 oar setup 与应用它的重启之间存在的 relay-previous.json。日志是 server.log 和 server-err.log。oar 写入的其他位置:~/.config/systemd/user/oar.service(Linux 服务)、Windows Startup 文件夹中的 oar-web-relay.cmd,以及 %APPDATA%\oar 中的 oar-web-relay-launcher.cmd、开机任务的 XML、oar-relay-elevate.ps1、oar-web-relay.log 和 oar-web-relay-launcher.log,还有 ~/.copilot/extensions/web-relay/extension.mjs。0.9.15 新增 oar autostart --replace 把它的副本作为 <name>.bak 保存在状态文件夹中,oar uninstall 把 oar-uninstall.log 写入日志文件夹(使用 --purge 时写入临时文件夹)。

环境变量 #

变量 使用者 效果
OAR_STATE_ROOT 全部 全局安装的状态文件夹
OAR_NO_UPDATE_CHECK update 1 阻止清单请求;--to 仍然可用
OAR_UPDATE_MANIFEST_URL update 清单的另一个 URL
COPILOT_WEB_RELAY_LOG_DIR 全部 另一个日志文件夹
COPILOT_WEB_RELAY_CONFIG 仅 copilot 存在时要使用的配置文件。其他命令始终使用本安装自己的 config.json
COPILOT_WEB_RELAY_DATA_DIR copilot、start、restart、setup、uninstall、Windows 自启动 这些命令启动中继时,作为数据文件夹交给中继,但由 Linux 服务启动时除外。setup 会迁移到其中,uninstall 会指出它并在 --purge 下将其列为可删除项。oar 自己在默认数据文件夹中查找锁文件
COPILOT_CLOUDFLARED_MODE、COPILOT_CLOUDFLARED_TOKEN、COPILOT_CLOUDFLARED_BINARY status、doctor 改变 status 的 Tunnel: 行和 doctor 的 tunnel 行,就像它们改变中继的隧道一样
COPILOT_CONFIG_HOME copilot 包装器所用的 Copilot 主文件夹,默认为 ~/.copilot
APPDATA、USERPROFILE、LOCALAPPDATA、XDG_CONFIG_HOME 全部 Windows 和旧版的文件夹位置
NO_COLOR 菜单 关闭颜色
PATH service install 服务会得到这个 PATH(加上 ~/.local/bin 和 Node.js 文件夹)

oar 如何找到中继 #

oar 从本安装的 config.json 读取端口和令牌,并带着令牌请求 http://localhost:<port>/api/status:

应答 oar 将其理解为
中继的状态 中继在运行
任何其他应答(令牌错误、其他程序),或 2.5 秒内没有回复 端口被其他程序占用,或被使用其他令牌的中继占用
连接被拒绝 中继已停止

锁文件不能作为证据:它可能比它的中继存在得更久。oar start 和 oar copilot 会等待持有锁但尚未应答的中继,并且只删除旧版本写入的锁。oar update 把存活的锁视为正在运行的中继。只要有存活的进程持有锁,oar uninstall 就不会继续。在更改了端口或令牌的 oar setup 与应用它的重启之间,中继仍在旧的端口和令牌上应答;oar 通过 relay-previous.json 找到它,并说明它仍以之前的设置运行。

安装了服务时,在 Linux 上 start、stop 和 restart 通过 systemd 执行(立即执行,不等待轮次);否则 start 启动一个分离的进程,stop 和 restart 使用中继自己的接口,它会等到没有轮次在运行。在 Windows 上,自启动从不参与 start;当自启动或开机任务开启时,status 显示 Service: installed。

WSL #

在 WSL 中,oar 会检测发行版(WSL_DISTRO_NAME 或 WSL_INTEROP,或内核版本),并询问 Windows 哪个程序占用了某个端口。oar setup 会拒绝 Windows 占用的端口。oar setup、start、status 和 doctor 会打印 Windows holds port <port> (<program>): a browser on Windows reaches that program, not this relay. Pick another port: oar setup --port N。在 WSL 默认网络模式下开启局域网访问时,oar url 会说明该地址是 WSL 内部地址。

退出代码 #

代码 含义 命令
0 完成;对于 stop 和 restart,中继仍然繁忙、之后会自行完成时也是 0 全部;status 仅在中继运行时
1 命令无法完成你要求的操作:没有配置文件、git 检出、端口被占用、中继没有启动起来或不接受请求、npm install 失败、缺少 gh、管理员提示被拒绝、有手动创建的自启动条目挡路、--purge 未被确认;也包括意外错误 setup、start、stop、restart、url、update、service、autostart、uninstall、copilot
2 用法错误:未知的命令或选项、缺少值、错误的 --port(copilot 除外)或 --autostart、--lan 与 --local 同时使用 全部
3 中继未运行(已停止、被其他程序占用,或尚未设置) 仅 status
130 在提问中或菜单中按 Ctrl+C setup、uninstall、菜单
gh copilot 的退出代码 Copilot 会话结束 copilot