Repository navigation
Releases: originrouter/originrouter_cli
Release list
OriginRouter CLI v0.5.1
OriginRouter CLI 0.5.1
Release date: 2026-10-15. Supersedes 0.5.0. Twelve commits.
Summary
This release corrects a bind-address defect that prevented device pairing over
the local network, introduces a user-configurable timeout for permission
requests, and resolves several relay-routing and session-state defects
affecting remote agent control.
Action required before upgrading
The Local API bind address default changes to 0.0.0.0
| 0.5.0 | 0.5.1 | |
|---|---|---|
bindAddress |
127.0.0.1 |
0.0.0.0 |
allowLan |
off |
on |
Three Local API endpoints are unauthenticated by bearer token and exist for
devices that cannot read the 0600 credential file on the host:
/local/e2ee/session, /local/e2ee/messages, /local/pair/redeem. Under the
0.5.0 default these endpoints were bound to loopback and therefore unreachable
from any client other than the host itself.
The authentication posture is unchanged. The bearer token remains the
authorisation boundary for all other routes on the socket, which return 401;
the three endpoints listed above authenticate by device identity.
Installations that have configured neither setting adopt the new default
automatically and require no action. To retain loopback binding:
originrouter local config set --bind 127.0.0.1 --allow-lan offAn address set this way is recorded as an operator choice rather than as a
record of the last resolved default, and is therefore not overwritten by a
subsequent upgrade. --bind and ORIGINROUTER_LOCAL_BIND passed to a single
daemon invocation apply to that invocation only and are not persisted.
Changes
Pairing
-
The address advertised by
local api pairnow derives from the configured
bind address. In 0.5.0 the daemon bound loopback while the address
suggestion scanned local interfaces and returned a LAN address, because a
bind it could not read was treated as unknown. The pairing payload, the QR
code and theAddressline all advertised that LAN address, so clients
following it reached no listener; pairing succeeded only from the host. The
CLI additionally printed guidance to correct the address in the App, which
misattributed the failure.The address suggestion now follows the bind: a concrete bind is preserved, a
loopback bind yields loopback, and interface scanning applies only to the
wildcard bind, which is the one bind whose LAN address is resolvable. -
local api pairissues a single credential. The 8-character code and the
signed pairing line conveyed the same ticket. The code path performed no
signing and therefore returned a routing hint rather than a credential, while
the client maintained two input fields, two error vocabularies and a mode
switch for the associated privilege. The code,--lineand--jsonhave
been removed. The signed line is printed as a terminal QR code and as text,
wrapped asoriginrouter://pair?v=2&l=<payload>, which is the form the
shared scanner accepts.This change is paired with a client update. The pairing import is the
only remaining input on both sides; the code field has been removed from the
App. Client and CLI must be updated together. -
Output has been reduced to statements of fact. Field labels now match the
output oflocal api status(bindAddress,tokenSet) because they are the
keys used in the files they reference. Explanatory text covering credential
storage, single-use semantics and address selection has been removed. -
local api statusno longer reportsbaseUrlas
http://0.0.0.0:<port>. The value was formatted directly from the bind
address, which is not a resolvable URL under a wildcard bind.
Agents and permissions
-
Permission requests are identified consistently across repeated
deliveries. Claude Code 2.1.283 does not includetool_use_idon
PermissionRequest. The hook server read that field, found it absent, and
generated a new identifier per delivery, so each repeated delivery was
registered as an independent permission — producing multiple approval cards,
multiple expiries and multiple denials for a single tool call. Requests are
now keyed by(session_id, prompt_id, tool_name, canonical(tool_input)), and
a repeated delivery joins the open request and receives the same decision. A
payload missing any component falls back to the previous behaviour. -
Remote permission requests are no longer terminated after five seconds. The
hook forwarder's HTTP client specified no agent and therefore inherited
Node's global agent, which applies a five-second socket timeout. This
overrodepermissionRequestTimeoutMs: 0— the value denoting an indefinite
wait — with a deadline that was neither configurable nor intentional. The
forwarder now uses a dedicated agent without a socket timeout. -
agent.interactionTimeoutMsmakes the permission-request timeout
configurable. The previous bound was whichever of five hard-coded deadlines
expired first, the outermost being 315 seconds. A device that was
unreachable or inactive for that period produced an automatic denial, and the
agent was informed that the request had been declined by the user.The setting accepts a millisecond count or a duration (
5m,2h,1d),
defaults to0(wait indefinitely), and is read per request, so a change
takes effect on the next approval without restarting the daemon. All five
layers that previously imposed a deadline now derive from this value, each
outer layer receiving a fixed 15-second margin. Claude Code requires a finite
hook deadline; that layer retains an 86400-second ceiling.
Sessions and relay
-
Relay types have a single dispatch owner.
agent.workspace.browsehad two
responders. The one ordered ahead in the dispatch chain opened with a check
comparing the relay payload's target device against the local device
identifier — a field the App does not populate. An absent field yields an
empty string, which never matches, so every such frame was claimed and
discarded before any log entry, on both ends. This presented as an
unresponsive device after a 30-second timeout and was not distinguishable
from a slow device.collaboration.remote.errorcarried the same check
inverted, causing App-originated error frames to bypass error handling. -
A trailing thinking block no longer reopens a completed turn. Turns
commonly arrive asagent.task.started → task_result_ready → agent.thinking → agent.text. Reading the final event as a turn start returned a completed
turn to the running state, presenting a stop control for an idle agent.
agent.thinkingmay now raise an active turn but cannot open one. -
Device trust is evaluated at signing time. Trust was evaluated against
the present state, so revoking a device or rotating its key invalidated
signatures that device had already produced, including the admission policy
other devices vouch for. Relay operation on the CLI side would stop while the
App continued. Signatures are now accepted when the signer was trusted at the
time of signing. -
Trust events announce themselves to the sender. The sender retains the
session on which ane2ee.sessions.resetwas received; its next envelope was
interpreted as an initial message and rejected, leaving the session blocked
until the corresponding state expired. The sender is now instructed to discard
its own session state.
Upgrade procedure
npm install -g @originrouter/cli@0.5.1
originrouter service restart
originrouter local api statusVerification points after upgrade:
bindAddressreports0.0.0.0andallowLanreportson, unless both were
set explicitly.local api pairprints a QR code and a text payload.--lineand--json
are no longer accepted and no 8-character code is issued.- The
Addressline reports an address reachable from the pairing device.
OriginRouter CLI 0.5.1
发布日期:2026-10-15。取代 0.5.0,共 12 个提交。
概述
本次发布修正了导致局域网设备配对无法完成的绑定地址缺陷,新增了权限请求超时的
用户配置项,并解决了若干影响远程智能体控制的中继路由与会话状态缺陷。
升级前须知
Local API 绑定地址默认值变更为 0.0.0.0
| 0.5.0 | 0.5.1 | |
|---|---|---|
bindAddress |
127.0.0.1 |
0.0.0.0 |
allowLan |
off |
on |
Local API 中有三个端点不使用 bearer token 鉴权,其存在前提是客户端无法读取本机
0600 权限的凭据文件:/local/e2ee/session、/local/e2ee/messages、
/local/pair/redeem。在 0.5.0 的默认值下,这三个端点绑定于 loopback,除本机
之外的任何客户端均无法访问。
鉴权边界未发生变更。bearer token 仍是该 socket 上其余全部路由的鉴权边界,未授权
请求返回 401;上述三个端点通过设备身份完成认证。
未显式配置这两项的安装将自动采用新默认值,无需任何操作。如需保留 loopback 绑定:
originrouter local config set --bind 127.0.0.1 --allow-lan off以此方式设置的地址会被记录为运维人员的选择,而非上一次默认值的解析结果记录,
因此后续升级不会将其覆盖。传入单次 daemon 调用的 --bind 与
ORIGINROUTER_LOCAL_BIND 仅对本次调用生效,不会持久化。
变更内容
配对
-
local api pair公布的地址现取自实际配置的绑定地址。 0.5.0 中 daemon
绑定于 loopback,而地址建议逻辑会扫描本机网卡并返回局域网地址——因为读不到的
绑定被视为未知。配对载荷、二维码与Address行公布的均为该局域网地址,依此
连接的客户端不会命中监听套接字;配对仅在本机可用。CLI 另会输出提示要求在
App 中修正地址,导致故障归因错误。地址建议现遵循绑定地址:具体绑定地址予以保留,loopback 绑定返回 loopback,
网卡扫描仅适用于通配绑定——这是唯一可解析出局域网地址的绑定形式。 -
local api pair只签发一种凭据。 此前的 8 位字符码与签名配对行表示同一张
票据。字符码路径不执行签名,因此签发的是路由提示而非凭据,而客户端需为此
维护两个输入框、两套错误文案与一个权限模式开关。字符码、--line与--json
已移除。签名行以终端二维码与文本两种形式打印,包装为
originrouter://pair?v=2&l=<payload>,该形式为共享扫描器所接受。该项变更需与客户端同步发布。 配对导入是两端唯一保留的输入方式,App 侧的
字符码输入框已移除,客户端与 CLI 需同步升级。 -
输出内容精简为事实陈述。 字段标签现与
local api status的输出一致
(bindAddress、tokenSet),因其即为其所引用文件中的键名。有关凭据存储、
单次使用语义与地址选择的说明性文字均已移除。 -
local api status不再将baseUrl报告为http://0.0.0.0:<port>。
该值此前直接由绑定地址格式化而来,在通配绑定下并非可解析的 URL。
智能体与权限
- 权限请求在重复投递间保持一致标识。 Claude Code 2.1.283 的
`Permi...
OriginRouter CLI v0.5.0
OriginRouter CLI v0.5.0
Tag: v0.5.0 · npm: @originrouter/cli@0.5.0 · Requires: Node.js 22+
Highlights
Claude model routing: five slots, one per model family
Claude Code resolves its built-in subagents by model family — an agent
declaring model: opus looks up ANTHROPIC_DEFAULT_OPUS_MODEL, model: haiku
looks up ANTHROPIC_DEFAULT_HAIKU_MODEL, and so on. The CLI previously had only
two slots (main and small), so four of the five families had no way to be
pointed anywhere except the primary model.
Claude routing is now one primary model plus four independently-settable
auxiliary slots:
| Slot | Alias | Environment variable |
|---|---|---|
main |
originrouter-claude-model |
ANTHROPIC_MODEL |
opus |
originrouter-claude-opus |
ANTHROPIC_DEFAULT_OPUS_MODEL |
sonnet |
originrouter-claude-sonnet |
ANTHROPIC_DEFAULT_SONNET_MODEL |
haiku |
originrouter-claude-haiku |
ANTHROPIC_DEFAULT_HAIKU_MODEL |
fable |
originrouter-claude-fable |
ANTHROPIC_DEFAULT_FABLE_MODEL |
Any auxiliary slot can inherit the primary model — which is the default, and
means the family follows the primary everywhere, including when you later switch
the primary's provider. Set one explicitly with a model id, or leave it alone:
originrouter route set claude \
--provider my-provider \
--main-model claude-opus-5-5 \
--haiku claude-haiku-4-5--opus, --sonnet, --haiku and --fable each accept a model id or the
literal inherit. Omitting a flag also means inherit.
All five slots must share one provider, and that is now enforced across every
slot rather than just main-versus-small.
Two environment variables are no longer injected
ANTHROPIC_SMALL_FAST_MODEL— replaced by the per-family defaults above.CLAUDE_CODE_SUBAGENT_MODEL— removed. It collapsed every model-less
subagent onto the primary model; per-family defaults make it unnecessary.
The old originrouter-claude-fast-model alias is gone.
Sending and stopping no longer flicker
The CLI used to report "terminal activity" on a two-second timer whenever the
terminal's rendered output changed. Interactive TUIs redraw constantly, so this
produced a steady stream of terminal.activity events — in one measured session,
tens of thousands of identical rows, which crowded real turn events out of the
App's most-recent-100 window and made the send/stop button flip between states.
The reporter has been removed; turn state now comes only from actual turn events.
Sessions are valid on every device, at every scale
New sessions are identified by claude-<32 hex> instead of
claude-<millisecond timestamp>. The old id was only unique within one machine,
and the server keys sessions with UNIQUE (session_id) and no account column —
so two devices starting in the same millisecond collided and the second user's
conversation was left with no session row at all. 122 bits of randomness
removes the collision rather than narrowing its window.
Live events encrypt once, not once per viewer
When several devices are watching the same session, updates are now sealed a
single time under a per-session group key and fanned out by the relay, instead
of being re-encrypted for every recipient. Request/response traffic stays
pairwise. Group keys live in <state-dir>/session-group-keys/ (directory mode
0700, file mode 0600).
This also fixes a scale problem: subscribing to 40 sessions took roughly six
seconds and delayed the first history page by around eighteen. Subscribers now
receive every key they are missing in a single frame and report the keys they
already hold, so a re-subscribe in the steady state sends nothing at all.
Fixed
The Local API port no longer ratchets away from the default
local-api.json records the port the daemon last bound, not a port anyone
asked to keep — but it was being treated as authoritative. On a host where 7437
was taken — a second OriginRouter user on a shared Linux box, say — the daemon
moved to 7438, wrote 7438 back, and then preferred 7438 for good. Each restart
could push it one further away from the port the App and the CLI's own commands
expect.
Port selection is now precedence-ordered and fallback-aware:
- an explicit
--local-port/ORIGINROUTER_LOCAL_PORT(an instruction — never
silently substituted;0means "kernel chooses" and outranks everything below) local-api.jsonmarkedportSource: "operator"(set via
local api set-port— the only way to pick a port on a launchd/systemd
service install, where the supervisor starts the daemon with no flags)- the last recorded port
- the default, 7437
- the first free port above
When the daemon lands somewhere other than the port that was requested, it now
says so loudly, naming the command that pins a port — because under a service
manager its own stderr goes to logs/daemon.err.log where nobody will read it.
Directly related: originrouter daemon refuses to start a second instance beside
a live one, instead of drifting to the next free port and rewriting the endpoint
App pairing reads. Use originrouter daemon status|restart|stop for a managed
daemon.
A busy port no longer blocks startup
A port recorded in local-api.json was being read as if you had asked for it
explicitly, and an explicit port never falls back — so a port that happened to be
taken turned into a failure to start at all. A recorded port is now treated as a
preference, not a demand.
Ports are read strictly
A port value used to be parsed loosely, so "80abc" was read as 80, "80.5" as
80, and "0x10" as 0. A typo became a plausible wrong port instead of an error.
Ports now have to be plain decimal digits, and anything else is rejected with the
value quoted back.
--local-port 0 asks the kernel for a free port
--local-port 0 (or ORIGINROUTER_LOCAL_PORT=0) means "any free port, you
choose", which is what a throwaway or test home wants. It works as before, and it
now overrides the recorded and default ports rather than letting a leftover
local-api.json answer a question you explicitly left open.
Agent presence is a fact, not an inference
The cloud previously inferred whether an agent was still attached from its turn
status. A session that stopped while the relay was down could therefore linger as
"active" indefinitely. Presence is now reported explicitly
(agent.session.presence), and on every relay reconnect the daemon reconciles
what it has attached against what the catalog still believes is live,
detaching anything that is gone.
Conversations stop reordering, and stop getting stuck as "running"
- A conversation's activity timestamp is now a high-water mark
(MAX(last_activity_at, ?)), so a late duplicate finish event can no longer
move it backwards and flip the card to a previous run. - The "latest run" join prefers a still-open run over a finished one.
- On exit, the conversation status is synced first, before the event drain
and bridge teardown, and is bounded by a timeout. Previously the process could
be reaped before the sync ran, leaving a conversation stuck on "running"
forever — visible in neither the history nor the session list.
Provider conversation ids are recorded, and no longer split the session
The provider's own conversation id used to be written into the conversation id,
producing two keys for one run (claude:<uuid> versus claude-<timestamp>) with
no column joining them. Those conversations matched no session row and appeared
in neither the App's history nor its session list. The value now travels
separately as native_session_id, and is only overwritten by a non-empty value,
so an early empty report cannot erase an id recorded by an earlier run.
Long Claude conversations page back without re-parsing
The Claude transcript is parsed once per file revision and cached by
(path, size, mtime) instead of being re-read and re-parsed on every page.
Shell completion matches the current flags
Pressing <TAB> after route set or on a provider command offered
--small-model and --small-fast-model, which this version no longer accepts, so
the suggestion could only lead to an error. Completion now lists the flags that
actually work, including the four per-family ones.
Upgrading
Upgrading is automatic; no data migration is performed and no action is required
for most users.
One behavior change to know about. If you had set claude.small to a
cheaper, faster model, the Haiku family now uses your primary model instead,
which is more expensive. There is no automatic migration — the value is dropped.
If you were relying on that, set it back explicitly:
originrouter route set claude --provider <name> --haiku <cheap-model>The CLI warns about a leftover claude.small when you run
originrouter env print and originrouter doctor, and points at this command.
Your old setting is kept on disk, unused, so you can roll back if you need to.
The first run after upgrading restarts the routing proxy once. This is expected
and clears itself — no action needed.
OriginRouter CLI v0.5.0
标签: v0.5.0 · npm: @originrouter/cli@0.5.0 · 依赖: Node.js 22+
重点
Claude 模型路由:五个槽位,每个模型家族一个
Claude Code 是按模型家族来解析内置子智能体的 —— 声明 model: opus 的智能体去读
ANTHROPIC_DEFAULT_OPUS_MODEL,model: haiku 的去读
ANTHROPIC_DEFAULT_HAIKU_MODEL,以此类推。而 CLI 此前只有两个槽位(main 和
small),所以五个家族里有四个除了主模型之外无处可指。
现在 Claude 路由是一个主模型 + 四个可独立指定的辅助槽位:
| 槽位 | 别名 | 环境变量 |
|---|---|---|
main |
originrouter-claude-model |
ANTHROPIC_MODEL |
opus |
originrouter-claude-opus |
ANTHROPIC_DEFAULT_OPUS_MODEL |
| ... |
OriginRouter CLI v0.4.9
OriginRouter CLI v0.4.9
English
This release fixes a class of failures where a session's route or environment was correct but something else silently replaced it, and it rebuilds shell completion so that it describes the whole command surface — on Windows, including the PowerShell that plain powershell actually starts.
Session environment and settings files
- Claude Code merges its own settings files above the subprocess environment, so a stale
~/.claude/settings.jsonenv block outranked the resolved route and replaced it — with nothing reported. The route is now pinned through the--settings(flagSettings) layer, which outranks every filesystem settings layer except enterprise managed settings. The SDK launch path and the PTY launch path now pin the same key set; the SDK path previously named five env keys by hand and leftCLAUDE_CODE_SUBAGENT_MODELand the entireANTHROPIC_DEFAULT_*_MODELfamily — the keys a stale settings file is most likely to hold — unpinned. - Report settings conflicts instead of resolving them silently. A conflicting layer is named at launch and by
originrouter env print, so a correct route that a settings file was overriding no longer looks like a routing failure. - Fix
originrouter env printdescribing only the process environment. It printed "(unset)" for the very keys a settings file was forcing. It now lists the settings layers that outrank the process environment, the transport keys each one sets, and whether OriginRouter overrides them. Credential keys are named, never their values; enterprise managed settings are identified as outranking OriginRouter.
Shell completion
- Derive completion from a single command catalog instead of a hand-maintained subset, so subcommands, options, and value completions can no longer drift apart from the command tree they describe.
- Refresh completion after a successful
originrouter update. A new version can generate a different script, and on Windows an older version may have written into a profile the running PowerShell never reads. Only profiles that already carry a completion block are touched — updating the CLI is never consent to configure a shell that was never configured. A failure in the refresh cannot turn a successful upgrade into a failed command.
Windows
- Install PowerShell completion into both profiles. Windows ships two PowerShells that read different files: Windows PowerShell 5.1 (what plain
powershellstarts) readsDocuments\WindowsPowerShell\Microsoft.PowerShell_profile.ps1, and PowerShell 7+ (pwsh) readsDocuments\PowerShell\Microsoft.PowerShell_profile.ps1. Only the 7+ path was written, so completion was installed yet never loaded for 5.1 users. Uninstall now clears both. - Fix completion for an empty word. PowerShell 5.1 silently drops a trailing empty argument when it invokes a native command, so
provider <TAB>reached the CLI asprovider, and the CLI echoed that word back instead of offering its subcommands. An empty string cannot be passed at all in 5.1 — a literal, an empty variable,String.Empty, and a splat all arrive as nothing, while" "survives — so the generated script sends a sentinel that the CLI maps back to an empty word. Only the last word is translated; anything before it is complete typed input. - Fix
originrouter loginandoriginrouter run --failing to execute npm-installed commands when the CLI is installed byscripts/install.ps1.
Security
- Make the Codex app-server provider id unique per process. Codex merges its config layers by key, and a table merges field by field rather than replacing wholesale. Our
-coverrides land in the SessionFlags layer and beat a userconfig.tomlfor every field we set — but any field we do not set under the same provider id survives from the lower layer. Measured against Codex 0.156.1 with a fixed id, a[model_providers.<id>]block in the user'sconfig.tomlsmuggledenv_http_headers,http_headers, andquery_paramsonto the very request our own credential authorized, so the user's key left the machine to whatever endpoint the route pointed at. An empty-table override does not clear them — the merge walks the overlay's keys, so an empty overlay contributes nothing. Choosing an id the user cannot have written is what removes the merge partner, and it costs nothing because the id is an internal handle Codex only resolves againstmodel_provider. - Pin both Anthropic credential variables when a route is applied, not only the unused one. A route that sets
ANTHROPIC_API_KEYleftANTHROPIC_AUTH_TOKENabsent, and an absent key is supplied by a lower settings layer instead. Measured against Claude Code 2.1.283, a staleANTHROPIC_AUTH_TOKENin~/.claude/settings.jsonthen rode out as aBearertoken alongside our ownANTHROPIC_API_KEY, and Claude Code prefers that bearer token — so the proxy was handed the user's stale credential and the user's own key left the machine. Pinning both also keeps Claude Code's "both ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY set" warning from returning.
Session and App state
- Stop reporting an active turn for a session that is online but idle.
session.statusdescribes the long-lived CLI process — a healthy idle Agent sits atrunningfor hours — so treating it as turn activity opened the App with a stop button and flickered against every refresh. Turn activity is latched by turn events alone. - Make the control snapshot and the session projection agree. The snapshot published the raw turn latch while the session published a gated projection, so the App alternated between two answers on every refresh.
- Keep a waiting state alive across an approval that expires without an event. Pending interactions are now the authoritative source for the waiting states, which a turn-event latch cannot observe.
- Stop resurrecting a finished turn when an Agent reconnects. Registration is treated as a fresh attach, so a turn that ended while the App was away no longer inherits the previous
runninglatch and shows a stop button until a terminal event that never comes.
Command discovery
- Document the
local apifamily.originrouter helpomitted it entirely, includinglocal api pair, which pairs an App with this machine's Local API — so the pairing flow had no discoverable entry point. The reference now listsstatus,pair,connect,set-host, andset-port, and explains that the pairing line never carries the access key. - Stop offering a subcommand the CLI rejects.
auth logoutwas declared in the command catalog but never implemented: TAB offered it, and choosing it failed with "Unknown auth subcommand". Signing out isoriginrouter logout. - Check catalog subcommands for reachability, not just declaration. A name could be declared and offered by completion while no dispatch branch accepted it. Each entry is now resolved against the module that owns its branch, and an exemption has to state its reason. The help text stays hand-authored (its sections are grouped by concept, not tree position) but is checked in both directions, so a documented-but-absent command and an undocumented-but-present one both fail.
Validation: the full CLI test suite passed, including new tests for the command catalog, completion (the sentinel and the dual-profile install), settings overrides, Codex provider isolation, env print settings layers, and turn-state projection. The catalog check was mutation-tested — re-adding the removed auth logout entry, adding an unimplemented subcommand, deleting a help section, and un-hiding an internal command each made it fail. The refresh-on-upgrade path is covered by a test that proves a failure inside it can never turn a successful upgrade into a failed command. Shell completion was exercised end to end in real Bash, Zsh, and Windows PowerShell 5.1 sessions. git diff --check passed.
After publishing @originrouter/cli@0.4.9 to npm, existing users can check and install the update with:
originrouter update check
originrouter update installInteractive startup also checks for updates. The default mode prompts the user after a newer npm version is cached; users who selected automatic updates install it when the CLI next starts and the system is idle. update also refreshes shell completion for shells that already have it installed.
中文
本次修复了一类「线路或环境本身是对的、却被别的东西悄悄替换掉」的故障,并重建了 shell 补全,使其覆盖完整命令面 —— 在 Windows 上包括直接运行 powershell 时实际启动的那个 PowerShell。
会话环境与 settings 文件
- Claude Code 的 settings 文件合并层级高于子进程环境变量,因此
~/.claude/settings.json中陈旧的env块会压过已解析的线路并将其替换,而且没有任何提示。现在线路通过--settings(flagSettings)层固定,该层优先级高于除企业托管设置之外的所有文件系统 settings 层。SDK 启动路径与 PTY 启动路径现在固定同一组 key;此前 SDK 路径手工写了 5 个环境变量,导致CLAUDE_CODE_SUBAGENT_MODEL和整个ANTHROPIC_DEFAULT_*_MODEL家族(恰恰是陈旧 settings 文件最可能持有的 key)处于未固定状态。 - 冲突不再被静默解决,而是被报告出来。冲突的 settings 层会在启动时以及
originrouter env print中被点名,因此「线路是对的、但被 settings 文件覆盖了」不再表现为一个路由故障。 - 修复
originrouter env print只描述进程环境的问题。此前它会对被 settings 文件强行设定的 key 打印 "(unset)"。现在它会列出优先级高于进程环境的各 settings 层、每一层设置的传输类 key,以及 OriginRouter 是否覆盖了它们。凭据只报 key 名,绝不报值;企业托管设置会明确标注为优先级高于 OriginRouter。
Shell 补全
- 补全改为由单一命令目录派生,而不是手工维护的子集,因此子命令、选项和取值补全不会再与它们所描述的命令树脱节。
originrouter update成功升级后会刷新补全。新版本可能生成不同的脚本,而在 Windows 上旧版本可能写入了一个当前 PowerShell 根本不会读取的 profile。只有已经带有补全块的 profile 才会被改动 —— 升级 CLI 绝不等于同意去配置一个从未配置过的 shell。刷新过程中的失败不会把一次成功的升级变成失败。
Windows
- PowerShell 补全同时安装到两个 profile。Windows 自带两个读取不同文件的 PowerShell:Windows PowerShell 5.1(直接运行
powershell时启动的就是它)读取Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1,PowerShell 7+(pwsh)读取Documents\PowerShell\Microsoft.PowerShell_profile.ps1。此前只写了 7+ 的路径,导致 5.1 用户「补全已安装却从未加载」。卸载现在会同时清理两者。 - 修复补全空词时的行为。PowerShell 5.1 在调用原生命令时会静默丢弃末尾的空参数,于是
provider <TAB>到达 CLI 时变成provider,CLI 就把这个词回显出来,而不是给出它的子命令。在 5.1 中空字符串根本无法传递 —— 字面量、空变量、String.Empty、...
OriginRouter CLI v0.4.8
OriginRouter CLI v0.4.8
English
This patch fixes cross-device session opening (device directory caching and verification) and repairs several Windows execution paths, including one that made originrouter login unusable.
Device encryption directory
- Scope the device directory cache to the account instead of a single sign-in. Every
originrouter loginpreviously started from a cold cache, discarding the pinned key history and leaving superseded files on disk with contradictory views of the same account. An existing session-scoped cache is carried over once and the superseded files are removed. - Verify each device's key chain independently, so one unverifiable device no longer makes every other device unreachable. The device at fault is quarantined and reported with a specific reason; invalid signatures, unsigned rotations, and mutated pinned keys stay fatal for that device.
- Complete a chain the server serves starting above key version 1 using key history this installation already pinned, so a server-side omission no longer permanently prevents a session from opening. Only previously pinned key IDs are reused.
- Report the actual cause in peer errors, distinguishing a quarantined device from one that is absent or untrusted.
- Remove the superseded
legacy_hmac_v2local authentication path from the CLI and the App. The method is now always negotiated explicitly, and a client that cannot negotiate is told to update rather than falling back to the weaker path.
Windows
- Fix
originrouter loginopening a truncated URL. The launcher usedcmd /c start, and cmd splits unquoted arguments at every&, so the browser received only the first query parameter and the device code was lost. - Fix
originrouter run --and agent launches failing to execute npm-installed commands. These ship as.cmdshims, whichCreateProcesscannot run. Bare names are now resolved againstPATH/PATHEXTand shims are routed throughcmd.exe. The same fix applies to the pty executor, which reported "File not found". - Fix system proxy detection, so managed Python and uv can be downloaded from behind a proxy. The registry reader matched a single hardcoded value type and silently returned nothing for any other type.
- Terminate the whole process tree when stopping an agent. Windows has no POSIX process groups, so the previous path could not reach descendants.
- Expand both
~/pathand~\pathin workspace, approval policy, audit store, autonomy policy, and agent catalog paths. Two of these only accepted the separator that does not appear on Windows.
Security
- Restrict the state directory holding credentials and device keys by ACL on Windows, where filesystem mode bits have no effect. Access is granted only to the current user and
SYSTEM, inheritance is cleared so new secret files are covered automatically, and principals are addressed by SID so the hardening works on localized systems. Best-effort: a directory that refuses ACL edits stays usable and warns once.
Validation: the full CLI test suite passed, including a new Windows ACL test. The Windows fixes were verified on a real Windows 11 machine: the login URL arrives intact where the old path was truncated, a .cmd shim that failed with ENOENT now runs, and the state directory under a deliberately world-readable parent ends up granting only SYSTEM and the current user, with newly written key files inheriting the restriction. git diff --check passed.
After publishing @originrouter/cli@0.4.8 to npm, existing users can check and install the update with:
originrouter update check
originrouter update installInteractive startup also checks for updates. The default mode prompts the user after a newer npm version is cached; users who selected automatic updates install it when the CLI next starts and the system is idle.
中文
本次修复跨设备会话打开(设备目录缓存与校验),并修复多处 Windows 执行路径问题,其中一处会导致 originrouter login 完全无法使用。
设备加密目录
- 设备目录缓存改为按账户划分,而不是按单次登录。此前每次
originrouter login都从空缓存开始,丢弃已固定的密钥历史,并在磁盘上留下对同一账户持有矛盾视图的废弃文件。现在会一次性迁移已有的会话级缓存,并删除被取代的文件。 - 每台设备的密钥链独立校验,一台无法校验的设备不再导致其他所有设备不可用。出问题的设备被隔离并给出具体原因;签名无效、轮换未签名、已固定密钥被篡改,对该设备仍然是致命错误。
- 当服务端返回的密钥链从高于版本 1 的位置开始时,使用本机已固定的密钥历史补全该链,避免服务端的遗漏永久阻断会话打开。仅复用此前已固定的 key ID。
- 对端错误报告真实原因,区分「被隔离的设备」与「不存在或未受信的设备」。
- 从 CLI 和 App 两端移除已被取代的
legacy_hmac_v2本地认证路径。认证方式现在始终显式协商;无法协商的客户端会被要求更新,而不是静默回退到更弱的路径。
Windows
- 修复
originrouter login打开被截断的 URL。原启动方式使用cmd /c start,而 cmd 会在每个未加引号的&处拆分参数,浏览器只收到第一个查询参数,设备码丢失。 - 修复
originrouter run --和 Agent 启动无法执行 npm 安装的命令。这类命令以.cmdshim 形式安装,CreateProcess无法直接执行。现在裸命令名会按PATH/PATHEXT解析,shim 通过cmd.exe执行。同一修复也应用于 pty 执行器(此前报 "File not found")。 - 修复系统代理检测,使托管 Python 和 uv 能在代理后下载。注册表读取此前只匹配一种硬编码的值类型,其他类型会静默返回空。
- 停止 Agent 时终止整个进程树。Windows 没有 POSIX 进程组,原路径无法触及子进程。
- 在 workspace、审批策略、审计存储、自治策略和 Agent 目录路径中,同时展开
~/path和~\path。其中两处此前只接受 Windows 上不会出现的分隔符。
安全
- 在 Windows 上通过 ACL 限制存放凭据与设备密钥的状态目录(该平台文件系统权限位无效)。仅授予当前用户和
SYSTEM,并清除继承,使新写入的密钥文件自动受保护;主体按 SID 指定,因此在本地化系统上同样生效。该加固为尽力而为:无法修改 ACL 的目录仍可正常使用,并只警告一次。
验证:CLI 完整测试套件通过,包含新增的 Windows ACL 测试。Windows 修复已在真实 Windows 11 机器上验证:登录 URL 完整送达(旧路径会被截断),此前报 ENOENT 的 .cmd shim 现在可正常执行,在故意放宽权限的父目录下创建的状态目录最终只授予 SYSTEM 和当前用户,新写入的密钥文件继承该限制。git diff --check 通过。
将 @originrouter/cli@0.4.8 发布到 npm 后,已安装用户可以执行:
originrouter update check
originrouter update install交互式启动也会检查更新。默认模式会在缓存到新版 npm 包后提示用户;选择自动更新模式的用户会在下次启动且系统空闲时安装。
OriginRouter CLI v0.4.7
OriginRouter CLI v0.4.7
English
This patch fixes CLI startup and runtime errors affecting Workspace, daemon, device removal, and local API flows.
- Fix logout with device removal by signing the request with the current account epoch. Keep the installation's device identity key after sign-out.
- Record the resolved provider and model in Agent session telemetry. Preserve the original error when a session fails before provider resolution.
- Read the existing device identity in
originrouter env printwithout entering the login-specific setup flow. - Restore Workspace's active-run spinner and fix a missing provider reference in the daemon.
- Return consistent remote-share status from the dedicated and local status endpoints. Route model verification through the configured probe function.
Validation: 12 focused tests passed across Workspace, CLI login, local API, and session management. git diff --check passed. The full test suite and Windows verification were not run for this patch.
After publishing @originrouter/cli@0.4.7 to npm, existing users can check and install the update with:
originrouter update check
originrouter update installInteractive startup also checks for updates. The default mode prompts the user after a newer npm version is cached; users who selected automatic updates install it when the CLI next starts and the system is idle.
中文
本次修复 Workspace、daemon、设备移除及本地 API 流程中的 CLI 启动和运行错误。
- 退出登录并移除设备时,使用当前账户 epoch 签名移除请求;退出后保留本机安装的设备身份密钥。
- Agent 会话遥测记录实际解析出的 Provider 和模型;如果会话在 Provider 解析前失败,保留原始错误。
originrouter env print读取现有设备身份,不再进入登录专用的设备设置流程。- 恢复 Workspace 运行中的进度动画,并修复 daemon 中缺失的 Provider 引用。
- 远程共享独立状态接口与本地状态摘要返回一致的数据;模型验证使用已配置的探测函数。
验证:Workspace、CLI 登录、本地 API 和会话管理的 12 项针对性测试通过;git diff --check 通过。本次未运行完整测试套件,也未进行 Windows 真机验证。
将 @originrouter/cli@0.4.7 发布到 npm 后,已安装用户可以执行:
originrouter update check
originrouter update install交互式启动也会检查更新。默认模式会在缓存到新版 npm 包后提示用户;选择自动更新模式的用户会在下次启动且系统空闲时安装。
OriginRouter CLI v0.4.6
OriginRouter CLI v0.4.6
English
This patch fixes two Windows service regressions in v0.4.5: a persistent blank Windows Terminal window at login, and reinstall failures that incorrectly reported an exiting daemon as still running.
- Launch the scheduled daemon through the Windows Script Host GUI host, hiding PowerShell before Windows creates its console. Explicitly select JScript so custom
.jsfile associations do not affect startup. - Wait for the daemon's process handle to signal exit before completing stop, reinstall, or restart. Preserve unrelated Node processes and report a genuine termination failure.
- Stop the previous service before npm replaces loaded native modules. Apply this to the Windows installer and CLI updater; the installer can recover older broken CLI versions without calling their service commands.
- Show Windows service command errors as readable UTF-8 text, without a long encoded command or PowerShell progress XML.
- Synchronize the package and website PowerShell installers.
Validation: full macOS test suite; real Windows 11 / PowerShell 5.1 tests covering ordinary-user reinstall, repeated stop/start/restart, failed-start cleanup, delayed process termination, actual launcher exit codes and logs, npm replacement, repeat installation, and fresh CLI/task installation. All five installation checks pass. Desktop window enumeration confirms service startup adds no visible terminal window. After a real reboot and login, the daemon starts automatically, all five checks pass, and the desktop has zero visible terminal windows.
After publishing the npm package and deploying the website script, run in Windows PowerShell:
irm https://originrouter.com/install.ps1 | iexExisting tasks are replaced automatically; no manual uninstall is required.
中文
本次修复 v0.4.5 的两个 Windows 服务问题:登录后空白终端常驻任务栏,以及重装时把正在退出的 daemon 误报为仍在运行。
- 计划任务改由 Windows Script Host 的 GUI 入口启动,在创建 PowerShell 控制台前隐藏窗口;显式指定 JScript,避免
.js默认打开方式影响服务启动。 - 停止、重装和重启服务时,等待 daemon 的进程句柄确认退出;保留其他 Node 程序,无法终止时明确报错。
- Windows 安装脚本及 CLI 更新器在 npm 替换本机模块之前先停止旧服务,避免旧包目录残留。安装脚本不调用旧版 CLI 的服务命令,也能恢复旧版停止逻辑有问题的安装。
- 服务命令报错改为可读的 UTF-8 文本,不再输出很长的编码命令或 PowerShell 进度 XML。
- npm 包及官网 PowerShell 安装脚本保持同步。
验证:macOS 完整测试;Windows 11 / PowerShell 5.1 真机验证普通权限重装、重复停止/启动/重启、启动失败清理、延迟退出、启动入口日志及退出码、npm 覆盖安装、重复安装、卸载 CLI 和任务后重新安装。安装验证五项全绿,实际桌面窗口枚举确认启动服务不会增加可见终端窗口。电脑实际重启并登录后,daemon 自动启动,五项检查全绿,可见终端窗口为零。
发布 npm 包并部署官网脚本后,在 Windows PowerShell 执行:
irm https://originrouter.com/install.ps1 | iex旧计划任务会自动替换,无需手动卸载。
OriginRouter CLI v0.4.5
OriginRouter CLI 0.4.5
English
This release makes Windows installation and background service startup reliable. The Local API now locates its authentication token correctly on Windows, and service installation verifies that the registered scheduled task matches the generated configuration. The daemon runs without opening an empty terminal window. If startup fails, OriginRouter stops the task and its daemon process tree, reports the failure, and allows a clean retry.
Service reinstall, stop, and uninstall clean up managed processes without touching unrelated Node processes; Windows automatically requests elevation for registration or removal when needed. After a CLI update, OriginRouter rebuilds the service configuration from the newly installed version, preserving whether the service was running. The Windows installer now runs unattended setup correctly, cleans up timed-out child processes, and shows a final five-part verification result. Running the installer again refreshes the existing installation.
Validation: macOS regression suite and Windows PowerShell 5.1 integration checks; clean removal and installation from the 0.4.5 package; repeat installation; service failure and retry cleanup; non-admin task registration through UAC; all five setup checks passing on Windows 11, and reboot validation with automatic daemon startup and no empty terminal window.
中文
此版本修复了 Windows 安装和后台服务启动问题。Local API 现在能正确定位 Windows 上的认证令牌;安装服务后会核对已注册的计划任务与生成的配置。后台 daemon 启动时不会再弹出空白终端窗口。启动失败时,OriginRouter 会停止任务及其 daemon 进程树、报告错误,并允许干净地重试。
重新安装、停止或卸载服务时会清理受管进程,不会误伤其他 Node 进程;注册或删除计划任务需要管理员权限时,Windows 会自动请求提权。CLI 更新后会使用新版本代码重建服务配置,并保留服务原先的运行状态。Windows 安装脚本修复了无人值守 setup、超时子进程清理和最终五项验证结果显示;重复运行安装脚本会刷新已有安装。
验证:macOS 回归测试、Windows PowerShell 5.1 集成测试、从 0.4.5 安装包清理并重装、重复安装、启动失败及重试清理、普通权限下通过 UAC 注册任务,Windows 11 上全部五项安装检查通过,以及重启后 daemon 自动启动且不再弹出空白终端窗口。
OriginRouter CLI v0.4.4
OriginRouter CLI 0.4.4
English
Fixed
- Windows background service now actually launches. The scheduled task's
embedded PowerShell startup script escaped embedded quotes in the Bash
style (\"), which PowerShell does not honor. The script therefore failed
to parse, the daemon was never started, and the Local API stayed
permanently not ready — with no log output at all, since the failure
happened before any redirection. All values in the wrapper are now wrapped
in PowerShell single-quote literals. Verified on a real Windows 11 machine:
the generated script parses with zero syntax errors and node.exe receives
correctly quoted arguments.
This was the last remaining failure in the Windows install chain; originrouter setup now completes with all verification checks green.
Upgrade notes
- Re-run the standard install in a normal PowerShell:
irm https://originrouter.com/install.ps1 | iex
Click "Yes" once when the Windows permission prompt appears (UAC may be
silent if prompts are disabled on your machine). No administrator window
is needed.
中文
修复
- Windows 后台服务现在能够真正启动。 计划任务内嵌的 PowerShell 启动脚本
此前使用 Bash 风格的引号转义(\"),而 PowerShell 并不认这种转义,导致
脚本解析失败、daemon 从未被启动、Local API 永远无法就绪——而且由于失败
发生在任何重定向之前,连日志都不会留下。现在包装脚本中的所有值都改用
PowerShell 单引号字面量。已在真实 Windows 11 机器上验证:生成的脚本
语法解析零错误,node.exe 收到的参数引号正确。
这是 Windows 安装链路上最后一个遗留问题;originrouter setup 现在可以全绿通过。
升级说明
- 在普通 PowerShell 中重新执行标准安装:
irm https://originrouter.com/install.ps1 | iex
出现 Windows 权限弹窗时点一次“是”即可(如果机器关闭了 UAC 提示则静默通过)。
全程不需要管理员窗口。
OriginRouter CLI v0.4.3
OriginRouter CLI 0.4.3
English
Fixed
- Background service now starts reliably on Windows. On machines where
scheduled-task registration requires administrator approval, the installer
now raises the standard Windows UAC prompt automatically — users simply
click "Yes" in the normal (non-elevated) PowerShell window instead of
opening an administrator console themselves. A declined prompt produces a
clear, actionable message instead of a garbled error. - The daemon no longer exits immediately after starting on logged-out
installs. An internalundefinedvsnullcomparison was misread as an
account change, shutting the daemon down right after launch. On macOS and
Linux the service supervisor masked this by restarting it in a tight loop;
on Windows the scheduled task does not supervise, so the Local API never
became ready and setup verification failed with "installed but not ready". - Service status and errors are no longer mojibake on Chinese Windows.
schtasksoutput is now captured through a UTF-8 console.
Upgrade notes
- Re-run the standard install in a normal PowerShell:
irm https://originrouter.com/install.ps1 | iex
Click "Yes" once when the Windows permission prompt appears. No
administrator window is needed, and daily use never requires elevation.
中文
修复
- Windows 后台服务现在可以可靠启动。 在注册计划任务需要管理员授权的
机器上,安装器现在会自动弹出标准的 Windows UAC 授权框——用户只需在普通
(非管理员)PowerShell 窗口里点一下“是”,无需自己打开管理员控制台。
点击“否”时会得到清晰可操作的提示,而不是乱码报错。 - 未登录状态下 daemon 不再启动后立即退出。 内部一处
undefined与
null的比较被误判为账户上下文变化,导致 daemon 启动后马上自行关闭。
macOS/Linux 上由服务管理器不断重启掩盖了这个问题;Windows 的计划任务
不会自动重启进程,因此 Local API 始终无法就绪,setup 验证报
“installed but not ready”。 - 中文 Windows 上服务状态与报错不再乱码。
schtasks输出现在通过
UTF-8 控制台捕获。
升级说明
- 在普通 PowerShell 中重新执行标准安装:
irm https://originrouter.com/install.ps1 | iex
出现 Windows 权限弹窗时点一次“是”即可。全程不需要管理员窗口,
日常使用也永远不需要提权。
OriginRouter CLI v0.4.2
OriginRouter CLI 0.4.2 Release Notes
Release date: 2026-09-27
A follow-up to 0.4.1 that closes the two remaining Windows rough edges found during end-to-end installation testing: the background service failing to register, and slow Python downloads that bypassed the system proxy.
Fixed
🛠️ Windows background service now registers successfully
originrouter service installpreviously failed on Windows with
(35,25): Interval:PT30S— Task Scheduler rejects failure-restart intervals
shorter than one minute. The generated task XML now uses the schema minimum
(PT1M), so the OriginRouter daemon registers and auto-starts on logon.
🚀 Python / LiteLLM downloads now honor the system proxy
originrouter setupandoriginrouter proxy installdownload Python, uv,
and LiteLLM packages through pip/uv, which ignore the Windows system proxy.
The CLI now reads the system proxy (Windows Internet Settings) and passes it
to those tools asHTTP(S)_PROXYenvironment variables, restoring normal
download speed behind local proxies such as Clash — no manual environment
setup required.ORIGINROUTER_PROXYexplicitly overrides the detected proxy;
ORIGINROUTER_NO_PROXY=1disables detection. ExistingHTTPS_PROXY/HTTP_PROXY
values always win.
Upgrade notes
-
Upgrading from 0.4.1 or 0.4.0 requires no manual migration. If the
background service previously failed to register, simply re-run the
installer ororiginrouter service installafter upgrading:npm install --global @originrouter/cli@0.4.2or re-run the platform installer:
# Windows (PowerShell) irm https://originrouter.com/install.ps1 | iex -
Full logs of the previous release (0.4.1) are available in
CHANGELOG.md.
Quality
- Added regression coverage for proxy environment inheritance (explicit
overrides, disabling, and non-Windows no-op behavior) and for the Task
Scheduler interval constraints in the generated Windows task XML.
OriginRouter CLI 0.4.2 发布说明
发布日期:2026-09-27
0.4.1 的跟进版本,收尾在 Windows 端到端安装测试中发现的最后两个问题:后台服务注册失败,以及 Python 下载绕过系统代理导致的龟速。
修复内容
🛠️ Windows 后台服务可以正常注册了
- 此前
originrouter service install在 Windows 上报
(35,25): Interval:PT30S——任务计划程序不接受小于 1 分钟的失败重启间隔。
生成的任务 XML 现在使用 schema 允许的最小值(PT1M),OriginRouter
守护进程可以正常注册并在登录时自动启动。
🚀 Python / LiteLLM 下载现在会走系统代理
originrouter setup与originrouter proxy install通过 pip/uv 下载
Python、uv 和 LiteLLM 依赖,而这些工具不认 Windows 系统代理。CLI 现在会
读取系统代理并转成HTTP(S)_PROXY环境变量传给它们,在 Clash 等本地代理
环境下恢复正常下载速度,无需任何手动设置。ORIGINROUTER_PROXY显式覆盖检测到的代理;ORIGINROUTER_NO_PROXY=1
关闭检测;已设置的HTTPS_PROXY/HTTP_PROXY永远优先。
升级说明
-
从 0.4.1 或 0.4.0 升级无需任何手动迁移。如果之前后台服务注册失败,升级后
重跑安装器或originrouter service install即可:npm install --global @originrouter/cli@0.4.2或重跑平台安装脚本:
# Windows (PowerShell) irm https://originrouter.com/install.ps1 | iex -
上一版本(0.4.1)的完整说明见 CHANGELOG.md。
质量保障
- 新增代理环境继承的回归测试(显式覆盖、关闭检测、非 Windows 平台无副作用),
以及 Windows 任务 XML 中计划任务间隔约束的回归断言。