@cortexkit/opencode-anthropic-auth 1.23.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +239 -195
  2. package/dist/cli-failure.d.ts +69 -0
  3. package/dist/cli.d.ts +14 -9
  4. package/dist/cli.js +98 -76
  5. package/dist/custody-dimensions.d.ts +7 -24
  6. package/dist/custody-mode.d.ts +29 -169
  7. package/dist/effort-history.d.ts +6 -1
  8. package/dist/index-1jkyhgyr.js +2 -0
  9. package/dist/{index-8y2t4mwz.js → index-2arfb1y3.js} +1 -1
  10. package/dist/{index-0jfsxyn9.js → index-4ya27n12.js} +1 -1
  11. package/dist/index-aaajxwzd.js +2 -0
  12. package/dist/index-ae3fq4n6.js +42 -0
  13. package/dist/{index-xzbhzz0a.js → index-fds0s2j4.js} +2 -2
  14. package/dist/index-nngmvczq.js +450 -0
  15. package/dist/index-pn597b6f.js +2 -0
  16. package/dist/{index-1gr8v4fn.js → index-rqync0pc.js} +1 -1
  17. package/dist/index.js +1 -38
  18. package/dist/native-command.d.ts +19 -0
  19. package/dist/rpc/notifications.d.ts +2 -1
  20. package/dist/rpc/port-file.js +1 -1
  21. package/dist/rpc/protocol.d.ts +8 -4
  22. package/dist/rpc/protocol.js +1 -1
  23. package/dist/rpc/rpc-client.d.ts +2 -0
  24. package/dist/rpc/rpc-client.js +1 -1
  25. package/dist/rpc/rpc-dir.js +1 -1
  26. package/dist/rpc/rpc-server.d.ts +5 -1
  27. package/dist/setup/command.d.ts +12 -0
  28. package/dist/setup/command.test.d.ts +1 -0
  29. package/dist/setup/native-activation.d.ts +29 -0
  30. package/dist/setup/native-enrollment.d.ts +26 -0
  31. package/dist/setup/native-enrollment.test.d.ts +1 -0
  32. package/dist/setup/native-local.d.ts +20 -0
  33. package/dist/setup/native-login.d.ts +3 -0
  34. package/dist/setup/native-paths.d.ts +15 -0
  35. package/dist/setup/native-paths.test.d.ts +1 -0
  36. package/dist/setup/pi.d.ts +13 -3
  37. package/dist/setup/process-fence.d.ts +7 -1
  38. package/dist/setup/process-fence.test.d.ts +1 -0
  39. package/dist/sidebar-state.js +1 -1
  40. package/dist/tui/command-dialogs.d.ts +5 -0
  41. package/dist/tui-preferences.js +2 -2
  42. package/dist/v2/activation.d.ts +7 -0
  43. package/dist/v2/adapter.d.ts +276 -0
  44. package/dist/v2/install.d.ts +13 -0
  45. package/dist/v2/lifecycle.d.ts +8 -0
  46. package/dist/v2/menu-contract.d.ts +8 -0
  47. package/dist/v2/menu.d.ts +10 -0
  48. package/dist/v2/models.d.ts +6 -0
  49. package/dist/v2/ownership.d.ts +11 -0
  50. package/dist/v2/prime.d.ts +12 -0
  51. package/dist/v2/rpc.d.ts +50 -0
  52. package/dist/v2/server.d.ts +8 -0
  53. package/dist/v2/server.js +4 -0
  54. package/dist/v2/setup.d.ts +58 -0
  55. package/dist/v2/source.d.ts +41 -0
  56. package/dist/v2/tui.d.ts +13 -0
  57. package/dist/v2/tui.js +2 -0
  58. package/dist/v2/wire.d.ts +36 -0
  59. package/package.json +20 -5
  60. package/src/rpc/notifications.ts +9 -2
  61. package/src/rpc/protocol.ts +8 -7
  62. package/src/rpc/rpc-client.ts +17 -0
  63. package/src/rpc/rpc-server.ts +20 -3
  64. package/src/tui/command-dialogs.tsx +264 -0
  65. package/src/tui/entry.mjs +44 -18
  66. package/src/tui-compiled/rpc/protocol.ts +8 -7
  67. package/src/tui-compiled/rpc/rpc-client.ts +17 -0
  68. package/src/tui-compiled/tui/command-dialogs.tsx +315 -76
  69. package/src/tui-compiled/tui.tsx +24 -7
  70. package/src/tui.tsx +37 -9
  71. package/dist/claustrum-enrollment-registry.d.ts +0 -4
  72. package/dist/custody-enrollment.d.ts +0 -14
  73. package/dist/custody-live.d.ts +0 -111
  74. package/dist/custody-manifest-watcher.d.ts +0 -16
  75. package/dist/index-1fq7h6yd.js +0 -430
  76. package/dist/index-797pmamn.js +0 -2
  77. package/dist/index-a5d6v3ba.js +0 -5
  78. package/dist/index-n96q8pks.js +0 -2
  79. package/dist/index-xxhyhp98.js +0 -2
  80. package/dist/index-z7gfdyv3.js +0 -1
  81. package/dist/local-login.d.ts +0 -64
  82. package/dist/logger-kk9vyem9.js +0 -1
package/README.md CHANGED
@@ -2,66 +2,91 @@
2
2
 
3
3
  Claude Pro/Max OAuth support for both [OpenCode](https://opencode.ai) and [Pi](https://pi.dev), maintained by CortexKit.
4
4
 
5
- This repo is a Bun workspace monorepo with two user-facing integrations and one shared core package. The OpenCode package is a CortexKit-maintained fork of the original `@ex-machina/opencode-anthropic-auth` plugin. The Pi package is a native Pi provider extension that overrides Pi's built-in Anthropic provider. Both integrations share the same Anthropic OAuth, fallback-account, quota, prompt-cache, relay, dump, and request-signing logic through `@cortexkit/anthropic-auth-core`.
5
+ This repo is a Bun workspace monorepo with two user-facing integrations and one shared core package. The OpenCode package is a CortexKit-maintained fork of the original `@ex-machina/opencode-anthropic-auth` plugin. The Pi package is a native Pi extension that replaces the implementation of Pi's built-in Anthropic provider while keeping its `anthropic` provider ID and model IDs. Both integrations share the same Anthropic OAuth, account-pool, quota, prompt-cache, relay, dump, and request-signing logic through `@cortexkit/anthropic-auth-core`.
6
+
7
+ > [!IMPORTANT]
8
+ > These instructions describe the upcoming native release, which is not yet published.
6
9
 
7
10
  ## Packages
8
11
 
9
12
  | Package | Agent | Purpose |
10
13
  | --- | --- | --- |
11
14
  | `@cortexkit/opencode-anthropic-auth` | OpenCode | OpenCode plugin and CLI for Claude OAuth, request rewriting, fallback accounts, quotas, cache controls, dumps, and relay setup. |
12
- | `@cortexkit/pi-anthropic-auth` | Pi | Pi package/extension that registers a CortexKit Anthropic provider under Pi's built-in `anthropic` provider ID. |
15
+ | `@cortexkit/pi-anthropic-auth` | Pi | Pi extension that replaces the implementation of Pi's built-in Anthropic provider, keeping the `anthropic` provider ID and model IDs. |
13
16
  | `@cortexkit/anthropic-auth-core` | Shared | Reusable OAuth, account, quota, cache, relay, dump, SSE, and request-signing logic used by both integrations. |
14
17
 
15
18
  ## Support matrix
16
19
 
17
20
  | Capability | OpenCode | Pi |
18
21
  | --- | --- | --- |
19
- | Primary Claude Pro/Max OAuth | OpenCode `/connect anthropic` | Pi `/login anthropic` |
20
- | Provider integration point | OpenCode plugin fetch/request transform | Pi `registerProvider("anthropic")` provider override |
21
- | Sidecar config | `~/.config/opencode/anthropic-auth.json` | `~/.pi/agent/anthropic-auth.json` |
22
- | Runtime state | `~/.config/opencode/anthropic-auth-state.json` | next to the Pi sidecar as `anthropic-auth-state.json` |
23
- | Commands | `/claude-cache`, `/claude-cachekeep`, `/claude-prime`, `/claude-start`, `/claude-routing`, `/claude-fast`, `/claude-quota`, `/claude-dump`, `/claude-killswitch` | `/claude-cache`, `/claude-cachekeep`, `/claude-prime` (status only), `/claude-routing`, `/claude-fast`, `/claude-quota`, `/claude-dump` |
24
- | Fallback accounts, quota routing, killswitch, relay, dumps, fast mode | Supported | Supported through the same shared core and Pi sidecar |
22
+ | Claude Pro/Max OAuth (local) | Local account pool, filled by `setup` migration, `setup --login`, or `/connect anthropic` | Local account pool, filled by `setup` migration, `setup --login`, or the `/claude` menu |
23
+ | Claude accounts from the Claustrum vault | Optional, enrolled separately through `setup` | Optional, enrolled separately through `setup` |
24
+ | Provider integration point | OpenCode plugin fetch/request transform (OpenCode 1 and OpenCode 2) | Pi `registerProvider("anthropic")`, replacing the built-in implementation |
25
+ | Local account pool | `~/.config/opencode/anthropic-auth-pool.json` | `~/.pi/agent/anthropic-auth-pool.json` |
26
+ | Old sidecar (migration source only) | `~/.config/opencode/anthropic-auth.json` | `~/.pi/agent/anthropic-auth.json` |
27
+ | Slash command | `/claude` menu | `/claude` menu |
28
+ | Menu actions not available in Pi | — | Refresh quota, killswitch, Prime on/off, lane start |
29
+ | Quota sidebar widget | OpenCode TUI plugin via `tui.json` | Not available |
30
+ | Fallback accounts, quota routing, relay, dumps, fast mode | Supported | Supported through the same shared core |
25
31
 
26
32
  ## What CortexKit adds over the original plugin
27
33
 
28
- - **Fallback Claude accounts**: keep each agent's normal Anthropic login as the primary account, then route to ordered fallback OAuth accounts on auth/quota/rate-limit failures.
29
- - **Routing modes**: use `/claude-routing sticky-balanced` to distribute cold sessions by current OAuth quota headroom while keeping each session on one account, or choose `main-first` / `fallback-first` ordering.
34
+ - **Fallback Claude accounts**: keep a main Claude account and route to ordered fallback OAuth accounts or API-key routes on auth/quota/rate-limit failures.
35
+ - **Routing modes**: choose **Routing mode** → `sticky-balanced` in the `/claude` menu to spread new sessions across OAuth accounts by current quota headroom while keeping each session on one account, or choose `main-first` / `fallback-first` ordering.
30
36
  - **Quota-aware routing**: skip main or fallback accounts when their 5-hour or 7-day Claude quota falls below your configured minimum.
31
- - **Persistent Claude cache controls**: manage Anthropic 1-hour prompt caching from `/claude-cache` with explicit, automatic, or hybrid modes.
32
- - **Cache keepalive**: use `/claude-cachekeep always` or `/claude-cachekeep HH-HH` to pre-warm hybrid cache anchors for active sessions before the 1-hour TTL expires.
33
- - **Quota window priming**: opt in with `/claude-prime on` to start each 5-hour quota window about one minute after it resets instead of waiting for the next normal prompt.
34
- - **Lane start (OpenCode only)**: use `/claude-start` to fire one synthetic, one-token turn through the current session's normal model, agent, variant, quota, routing, cache, and request pipeline.
35
- - **Fast mode toggle**: use `/claude-fast on|off` to request Anthropic fast mode for supported Opus models (`claude-opus-4-6`, `claude-opus-4-7`, `claude-opus-4-8`, `claude-opus-5`, and `claude-opus-5-5`).
36
- - **Adaptive reasoning visibility**: request summarized adaptive thinking for Claude Fable 5/5.1, Mythos 5/5.1, Opus 5, and Opus 5.5. OpenCode exposes native `low`, `medium`, `high`, `xhigh`, and `max` effort variants for Fable 5.1, Opus 5, and Opus 5.5. On Opus 5.5, thinking is always on (adaptive summarized) per the model specification. OAuth Fable 5.1 sessions can change effort between turns without rewriting the cached prefix.
37
- - **Fable/Opus 5 and 5.5 safety fallback**: eligible OAuth requests try Anthropic's server-side safety fallback first. The plugin preserves Anthropic's fallback conversation boundary across OpenCode history and automatically starts its deterministic 10-response Opus 4.8 recovery if the response still ends in refusal. The TUI sidebar and OpenCode Desktop report the active target model and restoration. Set `OPENCODE_ANTHROPIC_AUTH_FALLBACK_MODE=legacy` to bypass the server policy and use client-side recovery exclusively.
38
- - **Live quota visibility**: use `/claude-quota` to see main and fallback quota state, reset times, and refresh errors.
39
- - **Host-local quota feed**: optionally publish sanitized response-header quota observations so another local CortexKit process can reuse fresh account state without polling Anthropic's rate-limited usage endpoint.
40
- - **Killswitch**: per-account hard-block thresholds that stop requests before hitting Anthropic's rate limits, with synthetic 429 retry-after when all accounts are exhausted.
37
+ - **Persistent Claude cache controls**: manage Anthropic 1-hour prompt caching from the `/claude` menu's Cache group with explicit, automatic, or hybrid modes.
38
+ - **Cache keepalive**: use **Keep cache warm always** or **Cache keep window** to pre-warm hybrid cache anchors for active sessions before the 1-hour TTL expires.
39
+ - **Quota window priming**: opt in with **Enable Prime** to start each 5-hour quota window about one minute after it resets instead of waiting for the next normal prompt.
40
+ - **Lane start (OpenCode only)**: use **Fire lane start** to send one synthetic, one-token turn through the current session's normal model, agent, variant, quota, routing, cache, and request pipeline.
41
+ - **Fast mode toggle**: use **Enable fast mode** / **Disable fast mode** to request Anthropic fast mode for supported Opus models (`claude-opus-4-8`, `claude-opus-5`, and `claude-opus-5-5`).
42
+ - **Adaptive reasoning visibility**: request summarized adaptive thinking for Claude Fable 5/5.1, Mythos 5/5.1, Opus 5/5.5, and Sonnet 5.5. OpenCode exposes native `low`, `medium`, `high`, `xhigh`, and `max` effort variants for Fable 5.1, Opus 5/5.5, and Sonnet 5.5. On Opus 5.5, thinking is always on (adaptive summarized) per the model specification. OAuth Fable 5.1 sessions can change effort between turns without rewriting the cached prefix.
43
+ - **Claude Haiku 5.5**: `claude-haiku-5-5` supports a 1M context, 128K output and native `low` through `max` adaptive effort. Forced tool choice remains supported. Configured `error` or `drop_block` behavior handles replayed thinking after earlier conversation content changes. Explicit disabled thinking is preserved, with incompatible `xhigh`/`max` effort capped to `high`; manual budgets and sampling parameters are removed. Standard input/output rates are $0.10/$0.50 per million tokens, with fivefold request-wide rates above 100K total input including cache. OAuth model costs are zeroed by default. Opt-in quota-window priming uses Haiku 4.5 to start a new quota window.
44
+ - **Fable/Opus 5 and 5.5 safety fallback (OpenCode)**: eligible OAuth requests try Anthropic's server-side safety fallback first. The plugin preserves Anthropic's fallback conversation boundary across OpenCode history and automatically starts its deterministic 10-response Opus 4.8 recovery if the response still ends in refusal. The TUI sidebar and OpenCode Desktop report the active target model and restoration. Set `OPENCODE_ANTHROPIC_AUTH_FALLBACK_MODE=legacy` to bypass the server policy and use client-side recovery exclusively.
45
+ - **Live quota visibility**: the `/claude` menu's Quota group shows main and fallback quota state, reset times, and refresh errors.
46
+ - **Host-local quota feed (OpenCode)**: optionally publish sanitized response-header quota observations so another local CortexKit process can reuse fresh account state without polling Anthropic's rate-limited usage endpoint.
47
+ - **Quota sidebar widget**: register the OpenCode TUI plugin in `tui.json` to render a live sidebar with per-account quota, routing, cache, and health state.
48
+ - **Killswitch (OpenCode menu)**: per-account hard-block thresholds that stop requests before hitting Anthropic's rate limits, with synthetic 429 retry-after when all accounts are exhausted.
41
49
  - **User-owned Cloudflare relay**: optionally provision your own Worker relay to reduce repeated client upload bytes for large OpenCode or Pi requests.
42
- - **Claude-compatible request hardening**: Claude Code 2.1.258 identity and final-body billing signing, user-turn prompt and request lineage across tool loops, live-session-stable billing suffixes, Fable 5.1 thinking-prefix recovery, safer token refresh persistence, replay-safe fallback retries, and subagent cache isolation.
50
+ - **Optional Claustrum vault custody**: enroll OpenCode or Pi with setup so it serves Claude accounts from the vault instead of its local account pool.
51
+ - **Claude-compatible request hardening**: Claude Code 2.1.280 identity and final-body billing signing, user-turn prompt and request lineage across OpenCode tool loops, live-session-stable billing suffixes, Fable 5.1 thinking-prefix recovery, safer token refresh persistence, replay-safe fallback retries, and subagent cache isolation.
43
52
 
44
53
  ## What these integrations do
45
54
 
46
55
  - Let OpenCode and Pi use Claude Pro/Max OAuth credentials instead of an Anthropic API key.
47
56
  - In OpenCode, intercept the final Anthropic request and rewrite it into the Claude-compatible shape expected by Anthropic OAuth access.
48
- - In Pi, replace Pi's built-in Anthropic provider with a CortexKit provider override that uses the same Claude-compatible request path.
49
- - Add Claude billing headers with stable `cc_version`, user-turn `cc_prompt_id`/`cc_prev_req` lineage, and body-derived `cch` signing.
50
- - Support fallback Claude accounts stored in a local per-agent sidecar file.
51
- - Keep fallback OAuth tokens fresh in the background.
57
+ - In Pi, replace the implementation of Pi's built-in Anthropic provider, keeping its provider and model IDs, with one that uses the same Claude-compatible request path.
58
+ - Add Claude billing headers with stable `cc_version`, OpenCode user-turn `cc_prompt_id`/`cc_prev_req` lineage, and body-derived `cch` signing.
59
+ - Keep Claude OAuth accounts and API-key routes in a per-host local account pool, or serve accounts from an enrolled Claustrum vault.
60
+ - Keep local OAuth tokens fresh in the background.
52
61
  - Apply quota thresholds before routing to main or fallback accounts.
53
- - Add `/claude-cache`, `/claude-cachekeep`, `/claude-prime`, `/claude-start`, `/claude-fast`, `/claude-quota`, and `/claude-dump` commands.
62
+ - Add one `/claude` menu for accounts, quota, routing, limits, cache, diagnostics, fast mode, Prime, and lane start.
54
63
  - Optionally relay large requests through a Cloudflare Worker owned by the user.
55
64
 
56
- ## Setup wizard (recommended)
65
+ ## Quick setup (recommended)
57
66
 
58
- Run the interactive setup wizard:
67
+ In this guide, a *host* is OpenCode or Pi. Setup is an *offline* step: every OpenCode, LiteCode, and Pi process must be closed while it runs. Offline does not mean without network; setup still uses the network, for example to install packages and to sign in to Claude. Quit those processes, then run:
59
68
 
60
69
  ```bash
61
70
  bunx @cortexkit/opencode-anthropic-auth setup
62
71
  ```
63
72
 
64
- The wizard detects OpenCode, Pi, and Claustrum, configures plugin entries, and optionally activates Claustrum custody.
73
+ What setup does:
74
+
75
+ - detects OpenCode, Pi, `ck`, and a running Claustrum daemon (Claustrum is a local credential-vault service; `ck` is its command-line tool), and lets you select which hosts to configure;
76
+ - adds `@cortexkit/opencode-anthropic-auth` to `opencode.jsonc` (or `opencode.json`) and `tui.jsonc` (or `tui.json`), and installs `@cortexkit/pi-anthropic-auth` with `pi install`;
77
+ - migrates each selected host to its local account pool, unless you choose Claustrum vault custody;
78
+ - enrolls each selected host in the vault when you choose vault custody (it asks, and defaults to no).
79
+
80
+ Setup refuses to change anything while an OpenCode, LiteCode, or Pi process is running.
81
+
82
+ | Flag | Effect |
83
+ | --- | --- |
84
+ | `--yes`, `-y` | Do not prompt. Selects every detected host and keeps local custody unless `--claustrum` is also given. |
85
+ | `--dry-run` | Print the planned actions and change nothing. |
86
+ | `--login` | Sign in to Claude during setup and store that account as the main account in the local pool. |
87
+ | `--claustrum` | Choose vault custody. Takes effect only when the Claustrum daemon is running and `ck` is installed; otherwise setup keeps local custody. Cannot be combined with `--login`. |
88
+ | `--no-claustrum` | Keep local custody without asking. |
89
+ | `--remove-pi-auth` | With `--yes`, consent to moving a stored Pi Anthropic login (see [Pi stored logins](#pi-stored-logins)). Plain `--yes` is not consent. |
65
90
 
66
91
  ---
67
92
 
@@ -77,15 +102,15 @@ Add the OpenCode plugin to your OpenCode configuration:
77
102
  }
78
103
  ```
79
104
 
80
- Pinning is strongly recommended for any OpenCode plugin:
105
+ Pinning is strongly recommended for any OpenCode plugin. Replace `VERSION` with the release you install:
81
106
 
82
107
  ```json
83
108
  {
84
- "plugin": ["@cortexkit/opencode-anthropic-auth@1.0.0"]
109
+ "plugin": ["@cortexkit/opencode-anthropic-auth@VERSION"]
85
110
  }
86
111
  ```
87
112
 
88
- After changing plugin config, restart OpenCode.
113
+ OpenCode 1 and OpenCode 2 load the same package. After changing plugin config, restart OpenCode.
89
114
 
90
115
  > [!TIP]
91
116
  > If OpenCode keeps using an old build, clear OpenCode's plugin cache with `rm -rf ~/.cache/opencode` and restart.
@@ -94,81 +119,122 @@ After changing plugin config, restart OpenCode.
94
119
 
95
120
  Install the Pi package with Pi's package manager:
96
121
 
97
- ```bash
98
- pi install npm:@cortexkit/pi-anthropic-auth@1.0.0
99
- ```
100
-
101
- For an unpinned install:
102
-
103
122
  ```bash
104
123
  pi install npm:@cortexkit/pi-anthropic-auth
105
124
  ```
106
125
 
126
+ To pin a release, replace `VERSION` with its version number and keep the quotes: `pi install "npm:@cortexkit/pi-anthropic-auth@VERSION"`.
127
+
107
128
  To try it for one run without adding it to Pi settings:
108
129
 
109
130
  ```bash
110
131
  pi -e npm:@cortexkit/pi-anthropic-auth
111
132
  ```
112
133
 
113
- The Pi package registers a CortexKit Anthropic provider extension under Pi's built-in `anthropic` provider ID. After installation, start or restart Pi and authenticate with Pi's normal login command:
134
+ The Pi package replaces the implementation of Pi's built-in Anthropic provider; the `anthropic` provider ID and model IDs stay the same. It authenticates from the local account pool or the vault, not from Pi's `/login anthropic` credential. Run [setup](#quick-setup-recommended) before starting Pi.
114
135
 
115
- ```text
116
- /login anthropic
117
- ```
136
+ Pi's files live in `~/.pi/agent/` by default. `PI_CODING_AGENT_DIR` or `PI_AGENT_DIR` changes that directory, and `PI_ANTHROPIC_AUTH_FILE` changes the old sidecar path from which the pool's location is derived.
118
137
 
119
- Pi package state lives separately from OpenCode in:
138
+ ## Accounts and credential custody
120
139
 
121
- ```text
122
- ~/.pi/agent/anthropic-auth.json
123
- ```
140
+ OpenCode and Pi each take Claude credentials from exactly one source:
124
141
 
125
- Override the path with `PI_ANTHROPIC_AUTH_FILE`. The package also respects `PI_AGENT_DIR` when deriving the default sidecar path.
142
+ - **Local custody** (default): the host's local account pool.
143
+ - **Vault custody**: the Claustrum vault, after the host is enrolled through setup.
126
144
 
127
- ## Primary account authentication
145
+ The host's Claustrum enrollment record decides which credential source requests use; settings files do not. An approved enrollment keeps the host on the vault even if its token file is missing, so the host refuses rather than falling back to local accounts. If the enrollment record cannot be read, requests the plugin would serve refuse until it is repaired or disconnected; ordinary API-key authentication is unaffected. See [the custody contract](https://github.com/cortexkit/anthropic-auth/blob/main/docs/custody-state-machine.md) for the full contract.
128
146
 
129
- Each integration keeps the host agent's normal Anthropic login as the primary account.
147
+ ### Local account pool
130
148
 
131
- For OpenCode, use OpenCode's Anthropic auth flow:
149
+ The pool holds the host's Claude OAuth accounts and Anthropic-compatible API-key fallback routes, plus plugin settings. One OAuth account is the main account, tried first by default; the others are fallbacks, tried in order when the main account is unusable. The pool's location follows the host's old sidecar path: its files are created in the same directory, so `OPENCODE_ANTHROPIC_AUTH_FILE` and `PI_ANTHROPIC_AUTH_FILE` move the pool too.
132
150
 
133
- ```text
134
- /connect anthropic
135
- ```
151
+ | Host | Pool | Old sidecar (migration source) |
152
+ | --- | --- | --- |
153
+ | OpenCode | `~/.config/opencode/anthropic-auth-pool.json` | `~/.config/opencode/anthropic-auth.json` |
154
+ | Pi | `~/.pi/agent/anthropic-auth-pool.json` | `~/.pi/agent/anthropic-auth.json` |
136
155
 
137
- The primary account remains OpenCode's built-in `anthropic` auth entry. The OpenCode plugin intercepts final Anthropic requests and supplies the OAuth headers and request transforms needed for Claude Pro/Max access.
156
+ Private credential state is kept beside the pool in `anthropic-auth-pool-state.json`. Every process of a host shares that host's pool. OpenCode and Pi keep separate pools.
138
157
 
139
- OpenCode's upstream authentication options are still supported:
158
+ Setup migrates each host once, while OpenCode, LiteCode, and Pi are closed:
140
159
 
141
- - Claude Pro/Max OAuth through `claude.ai`.
142
- - Anthropic Console OAuth that creates an API key.
143
- - Manually entered Anthropic API key.
160
+ - Fallback accounts, API-key routes, and settings from the old sidecar files are imported into the pool. The old sidecar files are not read afterwards.
161
+ - OpenCode's stored Claude OAuth login becomes the main account in OpenCode's pool. OpenCode keeps only an inert placeholder: a fixed, non-secret marker that is not a usable credential and only tells OpenCode to route Claude requests through the plugin. A stored OpenCode API key is left unchanged.
162
+ - Pi's stored Anthropic OAuth login is moved into the pool only with your consent.
144
163
 
145
- For Pi, install the Pi package, restart Pi, then use Pi's Anthropic login flow:
164
+ Requests refuse until migration has completed; they never fall back to credentials still stored in OpenCode's or Pi's own auth file. Before importing a stored main OAuth login, migration checks the Claude account UUID in the legacy main profile. That profile's recorded access-token fingerprint must match the host login; migration does not query Anthropic for identity. If it cannot, it changes nothing and tells you to run:
146
165
 
147
- ```text
148
- /login anthropic
166
+ ```bash
167
+ bunx @cortexkit/opencode-anthropic-auth setup --login --no-claustrum
149
168
  ```
150
169
 
151
- The Pi package registers under Pi's built-in `anthropic` provider ID and stores primary OAuth credentials through Pi's normal credential flow. CortexKit package state, fallback accounts, cache mode, dump mode, and relay config live in the Pi sidecar file.
170
+ `--login` opens a Claude sign-in during setup and stores the account as the main account.
152
171
 
153
- ## Sidecar config
172
+ ### Signing in
154
173
 
155
- OpenCode package state lives in:
174
+ In local custody, after running setup (see [Local account pool](#local-account-pool)), add the main account in any of these ways:
156
175
 
157
- ```text
158
- ~/.config/opencode/anthropic-auth.json
176
+ - **OpenCode 1**: run `/connect anthropic` and choose **Claude Pro/Max**. The account is saved in the local pool; OpenCode stores only the inert placeholder.
177
+ - **OpenCode 2**: connect Anthropic and choose **Claude Pro / Max (native account pool)**.
178
+ - **Pi**: after setup completes, open `/claude`, then use **Start OAuth sign-in** and **Finish OAuth sign-in**. The first account becomes the main account; later accounts are fallbacks, tried when the main account cannot serve.
179
+ - **Any host**: `setup --login`, while the host is stopped.
180
+
181
+ OpenCode's stock API-key options (**Create an API Key** and **Manually enter API Key** in OpenCode 1) remain ordinary OpenCode API-key authentication. The plugin passes those requests through unchanged.
182
+
183
+ Local sign-in refuses while the host is enrolled in the vault (see [Claustrum vault custody](#claustrum-vault-custody)), with `Disconnect from the vault first.`
184
+
185
+ ### Claustrum vault custody
186
+
187
+ Vault custody is optional and chosen per host. Quit every OpenCode, LiteCode, and Pi process, make sure the Claustrum daemon is running and `ck` is installed, then run:
188
+
189
+ ```bash
190
+ bunx @cortexkit/opencode-anthropic-auth setup --claustrum
159
191
  ```
160
192
 
161
- Override the OpenCode path with `OPENCODE_ANTHROPIC_AUTH_FILE`.
193
+ For each selected host, setup proposes the `anthropic-auth-opencode` or `anthropic-auth-pi` enrollment, approves it with `ck auth enroll approve`, and grants that enrollment read access to the `anthropic-native` credential category (`ck auth grant --principal enrolled:anthropic-auth-<host> --selector-kind category --selector anthropic-native --operation read`). It then refreshes the vault inventory and requires its default Anthropic credential (`oauth:anthropic`) to have a vault-reported account identity; otherwise it stops with `The vault has no verified default Claude account. Sign in through the vault and rerun setup.`
194
+
195
+ Vault setup writes the selected host's enrollment and, for Pi with your consent, Pi's auth file (see [Pi stored logins](#pi-stored-logins)). It does not read, import, change, or delete the local pool, migration journal, local runtime metadata, or routing assignments, it never imports local OAuth accounts into the vault, and it does not write OpenCode's auth file. If the vault reports that an earlier enrollment request was replaced by a newer one, already used, or no longer exists, setup clears that request and stops; run setup again.
196
+
197
+ After setup, select the vault in the host:
198
+
199
+ - **OpenCode 1**: run `/connect anthropic` and choose **Claude via credential vault**. This option appears only while OpenCode holds a vault enrollment, and it checks OpenCode's Anthropic login slot without changing it. If OpenCode already holds an Anthropic login, or the slot cannot be read, it refuses: remove that login with OpenCode's own tools, then choose the vault login, or disconnect from the vault. An OpenCode OAuth login other than the vault placeholder is never used while enrolled; requests refuse with `This host uses the credential vault, but OpenCode holds a separate Anthropic login. Remove it and choose the vault login, or disconnect from the vault.`
200
+ - **OpenCode 2**: connect Anthropic and choose **Claude vault accounts**. It refuses unless OpenCode is enrolled.
201
+ - **Pi**: no extra step; see [Pi stored logins](#pi-stored-logins).
202
+
203
+ API keys stored in OpenCode are never changed and keep working as stock OpenCode authentication in every custody state, including an unreadable enrollment. OpenCode 2 serves a request only when it carries the plugin's placeholder; API keys from OpenCode's login, configuration, or environment, and any other connection, pass through unchanged.
204
+
205
+ While a host is enrolled:
206
+
207
+ - Claude accounts come only from the vault's scoped inventory. The vault's default account is the main account. Accounts added with `ck auth login --provider anthropic` are discovered without a restart and receive an initial quota check.
208
+ - Every model request, quota or profile query, quota-window priming request, and cache keepalive request obtains fresh vault authorization. A vault refusal never falls back to a local credential.
209
+ - Local pool accounts, including API-key routes, are not used, refreshed, quota-polled, kept warm, or shown. They stay unchanged and return after disconnect.
210
+ - If the vault's default account changes to a different Claude account, sessions pinned to the old default are assigned afresh; other session pins are kept.
211
+ - If the vault has no usable Claude account, requests refuse. Add accounts with `ck auth login --provider anthropic`, or disconnect from the vault.
212
+ - The `/claude` menu still enables and disables vault accounts and resets recorded retry waits, but hides local sign-in, API-key additions, account removal and reordering, and enrollment reset.
213
+
214
+ ### Pi stored logins
162
215
 
163
- Pi package state uses the same JSON shape but a separate file:
216
+ Pi prefers its stored login over the extension's credentials. Setup asks before moving or stashing that login; with `--yes`, pass `--remove-pi-auth` to consent.
217
+
218
+ - **Local custody**: setup moves Pi's stored Anthropic OAuth login into the local pool and removes Pi's copy. Until that happens, Pi refuses to serve with `Pi still has a host Anthropic OAuth credential. Run offline setup to migrate it and approve its removal before using the native pool.`
219
+ - **Vault custody**: setup moves Pi's stored Anthropic login (OAuth or API key) into a private stash and leaves a fixed, non-secret API-key marker in Pi's auth file so Pi does not refresh the stashed OAuth login. Disconnecting restores the original login byte-for-byte before the enrollment is removed.
220
+
221
+ ### Disconnecting from the vault
222
+
223
+ Open `/claude` and choose **Disconnect from the vault** in the Accounts group. The action is offered while the host is enrolled, and also when the enrollment record cannot be read, so a damaged record can always be cleared. It asks for confirmation:
164
224
 
165
225
  ```text
166
- ~/.pi/agent/anthropic-auth.json
226
+ Disconnect this host from the vault and return to local accounts? The vault keeps this host's enrollment approved until an operator revokes it there.
167
227
  ```
168
228
 
169
- Override the Pi path with `PI_ANTHROPIC_AUTH_FILE`.
229
+ Disconnect never reads or changes OpenCode's stored sign-ins. For Pi, it restores the stashed login first. If Pi's auth file already holds a different login, disconnect stops, keeps both logins and the enrollment, and asks you to resolve them with setup. After a successful disconnect, the host returns to its local pool. If that pool has never been migrated, stop the hosts and run `setup --no-claustrum`; disconnect does not perform migration.
170
230
 
171
- Example:
231
+ Only the setup command creates or polls enrollment requests. In local custody, **Reset host enrollment** clears a denied or blocked enrollment request without proposing a new one; run setup afterwards. It never resets a pending request or an approved enrollment.
232
+
233
+ ## Settings
234
+
235
+ Plugin settings live in the host's local account pool (and, while the host is enrolled in the vault, in a separate `anthropic-auth-vault-settings.json`). Change the settings that have a `/claude` menu action from the menu; see [The /claude menu](#the-claude-menu).
236
+
237
+ During migration, setup imports these settings from the old sidecar file (`~/.config/opencode/anthropic-auth.json` or `~/.pi/agent/anthropic-auth.json`, or the paths set by `OPENCODE_ANTHROPIC_AUTH_FILE` and `PI_ANTHROPIC_AUTH_FILE`). The old file is not read after migration. The imported shape is:
172
238
 
173
239
  ```json
174
240
  {
@@ -196,9 +262,6 @@ Example:
196
262
  "quotaHeaderFeed": {
197
263
  "enabled": false
198
264
  },
199
- "claustrum": {
200
- "accounts": {}
201
- },
202
265
  "killswitch": {
203
266
  "enabled": false,
204
267
  "main": { "five_hour": 5, "seven_day": 10, "scoped": 0 },
@@ -237,28 +300,23 @@ Example:
237
300
  }
238
301
  ```
239
302
 
240
- The `routing` block controls `/claude-routing`, `claudeCache` controls `/claude-cache`, `cacheKeep` controls `/claude-cachekeep`, and `claudeFast` controls `/claude-fast`. OpenCode zeroes Anthropic OAuth model costs by default because OAuth usage is quota-based; set `costZeroing.enabled` to `false` only if you want OpenCode to display the provider's model pricing instead. Set `quota.showToasts` to `true` to opt into OpenCode quota toast notifications after quota refreshes. The `main` field identifies OpenCode's primary auth entry; Pi keeps primary OAuth credentials in Pi's own credential store, but uses the same sidecar shape for CortexKit settings and fallback account labels.
303
+ The `routing` block holds the routing mode, `claudeCache` the cache mode, `cacheKeep` the cache keepalive schedule, and `claudeFast` the fast-mode switch; the `/claude` menu changes all of them. Killswitch `scoped` thresholds apply to model-specific quota windows, such as a separate weekly limit for Claude Fable models (`claude-fable-*`). OpenCode zeroes Anthropic OAuth model costs by default because OAuth usage is quota-based; set `costZeroing.enabled` to `false` only if you want OpenCode to display the provider's model pricing instead. Set `quota.showToasts` to `true` to opt into OpenCode quota toast notifications after quota refreshes.
241
304
 
242
305
  `thinkingBinding.prefixMismatchBehavior` controls replayed signed/redacted thinking on OAuth Fable 5.1 requests. `account-default` (the default) sends no explicit prefix-mismatch override. Use `error` to make prefix changes fail deterministically during compaction testing, or `drop_block` to ask Anthropic to discard mismatched thinking blocks. The beta header is added only when an explicit behavior is configured and replayable thinking is present.
243
306
 
244
307
  `quotaHeaderFeed.enabled` is an OpenCode-only, restart-required opt-in. It publishes only allowlisted quota-window values, an opaque account reference, an observation timestamp, and the configured OAuth-account count; it never publishes tokens, raw headers, request bodies, model IDs, or refresh errors. Per-process lease files use owner-only permissions under `$TMPDIR/opencode-anthropic-auth/quota-header-feed`, expire after three minutes, and can be redirected with `OPENCODE_ANTHROPIC_AUTH_QUOTA_FEED_DIR`.
245
308
 
246
- `claustrum.accounts` remains loadable only so configurations can safely downgrade to older releases; it does not gate custody per account. Capability handles are bearer credentials and must not be copied into the public config file.
247
-
248
- Runtime data is stored separately in `anthropic-auth-state.json`: fallback OAuth tokens, API-route keys, token refresh backoff, quota snapshots, and quota API backoff. Sticky session assignments use `anthropic-auth-routing-state.json` and store only SHA-256 hashes of session IDs. Background refresh and quota checks write only runtime state, so editing `anthropic-auth.json` does not get overwritten by another running plugin instance.
249
-
250
- ## OpenCode lane-start setting
251
-
309
+ Private runtime data (OAuth tokens, API-route keys, token refresh backoff, quota snapshots, and quota API backoff) is kept in `anthropic-auth-pool-state.json`, separate from settings. `sticky-balanced` session assignments use `anthropic-auth-pool-routing-state.json` in local custody and `anthropic-auth-vault-routing-state.json` in vault custody; session IDs are SHA-256 hashed in both.
252
310
 
253
311
  ## Fallback accounts
254
312
 
255
- Fallback accounts are separate Claude OAuth accounts or Anthropic-compatible API-key routes managed by this plugin. By default, the main account is tried first unless quota policy says it is currently unusable. Fallbacks are then tried in sidecar order when the primary request returns a configured fallback status.
313
+ Fallback accounts are separate Claude OAuth accounts or Anthropic-compatible API-key routes in the local pool, or additional accounts in the vault while the host is enrolled. By default, the main account is tried first unless quota policy says it is currently unusable. Fallbacks are then tried in account order when the primary request returns a configured fallback status.
256
314
 
257
- Use `/claude-routing fallback-first` to prefer usable fallback accounts before the main account, `/claude-routing main-first` to restore the default, or `/claude-routing sticky-balanced` to allocate each new session according to spendable 5-hour, 7-day, and matching model-scoped OAuth quota headroom. The command persists `routing.mode` and takes effect on the next request without restarting. `/claude-routing reset` clears only the current session's assignment so its next request is allocated again.
315
+ In the `/claude` menu, choose **Routing mode** → `fallback-first` to prefer usable fallback accounts before the main account, `main-first` to restore the default, or `sticky-balanced` to allocate each new session to an OAuth account according to its remaining quota above your configured minimums in the 5-hour, 7-day, and any model-specific window. The choice persists and takes effect on the next request without restarting. **Reset routing session** clears only the current session's assignment so its next request is allocated again.
258
316
 
259
- `sticky-balanced` normalizes quota headroom by time until reset and tracks weighted initial-prompt deficit until the next quota refresh. Assignments are persisted by hashed session ID in `anthropic-auth-routing-state.json`, shared safely across OpenCode plugin instances and restarts. Active hybrid CacheKeep sessions seed their current route when the mode is first enabled. Changing the user-selected model discards the old assignment and its model-specific CacheKeep preference before quota-based reselection; transparent safety-recovery model changes retain the original account.
317
+ `sticky-balanced` normalizes quota headroom by time until reset and accounts for prompt bytes assigned since the last quota refresh, so new sessions do not crowd the same account before fresh quota arrives. Assignments are persisted by hashed session ID in `anthropic-auth-pool-routing-state.json` (`anthropic-auth-vault-routing-state.json` while enrolled in the vault), shared safely across OpenCode plugin instances and restarts. Sessions whose 1-hour prompt cache is already kept warm by background requests keep their current route when the mode is first enabled, avoiding a cache-losing account switch. Changing the user-selected model discards the old assignment and its model-specific CacheKeep preference before quota-based reselection; transparent safety-recovery model changes retain the original account.
260
318
 
261
- Affinity survives network/relay failures, 5xx responses, unconfirmed 429s, quota-probe failures, and relative quota changes. Confirmed 7-day or matching model-scoped exhaustion migrates a session. Confirmed 5-hour exhaustion migrates only when more than 15 minutes remain; otherwise the plugin retains the route and returns `Retry-After`. Fable content-filter recovery keeps Fable, Opus 4.8, and Fable prewarms on the same sticky account. Direct Opus sessions first prefer an otherwise usable account whose Fable quota is exhausted.
319
+ Session affinity, keeping a session on the same account, survives network/relay failures, 5xx responses, unconfirmed 429s, quota-probe failures, and relative quota changes. Confirmed 7-day or matching model-scoped exhaustion migrates a session. Confirmed 5-hour exhaustion migrates only when more than 15 minutes remain; otherwise the plugin retains the route and returns `Retry-After`. When a Claude Fable model returns a content-filter refusal and OpenCode temporarily switches the session to Opus 4.8 (see [Safety fallback](#safety-fallback)), the Fable request, the Opus 4.8 turns, and the cache prewarm sent before returning to Fable stay on the same assigned account. Direct Opus sessions first prefer an otherwise usable account whose Fable quota is exhausted.
262
320
 
263
321
  Default fallback statuses:
264
322
 
@@ -266,7 +324,7 @@ Default fallback statuses:
266
324
  [401, 403, 429]
267
325
  ```
268
326
 
269
- Add and inspect OpenCode fallback accounts with the CLI:
327
+ Add and inspect OpenCode fallback accounts with the CLI (local custody only, after running setup for OpenCode):
270
328
 
271
329
  ```bash
272
330
  bunx @cortexkit/opencode-anthropic-auth login personal-alt
@@ -274,38 +332,23 @@ bunx @cortexkit/opencode-anthropic-auth api add kie-opus
274
332
  bunx @cortexkit/opencode-anthropic-auth list
275
333
  ```
276
334
 
277
- Prefer npm? Use `npx -y @cortexkit/opencode-anthropic-auth ...` with the same subcommands.
335
+ Prefer npm? Use `npx -y @cortexkit/opencode-anthropic-auth ...` with the same subcommands. `login` and `api add` save to OpenCode's local pool and never change OpenCode's auth file; both refuse with `Disconnect from the vault first.` while OpenCode is enrolled in the vault, because vault accounts then replace the local pool. `api add` reads `OPENCODE_ANTHROPIC_AUTH_API_BASE_URL`, `OPENCODE_ANTHROPIC_AUTH_API_KEY`, and `OPENCODE_ANTHROPIC_AUTH_API_AUTH_HEADER` instead of prompting when they are set.
278
336
 
279
- API fallback routes use `Authorization: Bearer <key>` by default and rewrite requests to the configured Anthropic-compatible base URL. For Kie, use `https://api.kie.ai/claude` as the base URL; the plugin appends `/v1/messages` automatically. API-key routes are only eligible after direct evidence that the main OAuth quota is exhausted: a fresh token-bound quota snapshot at 0% remaining, or an actual main OAuth model response with HTTP 429 / streaming rate-limit error followed by a live quota check that confirms 0% remaining. Low-but-nonzero quota, stale cached quota, unconfirmed 429s, 401, or 403 do not trigger API-key routes. API-route keys are stored in `anthropic-auth-state.json`, while `anthropic-auth.json` keeps the route label, type, enabled flag, base URL, and auth-header mode.
337
+ In both hosts, the `/claude` menu's Accounts group offers the same local changes: **Start OAuth sign-in** / **Finish OAuth sign-in**, **Add API-key fallback**, **Enable account**, **Disable account**, **Remove account**, **Move account up**, and **Move account down**. Account actions ask for the complete account ID shown in the account status.
280
338
 
281
- OpenCode cost accounting stays simple: when the native Anthropic auth entry is OAuth, OpenCode sees zero-cost Claude OAuth models by default. If a request falls through to an API-key route, token accounting is still recorded, but OpenCode's built-in dollar cost is not route-aware. Advanced users can set `costZeroing.enabled` to `false` to show Anthropic model pricing for OAuth sessions too.
339
+ API fallback routes use `Authorization: Bearer <key>` by default and rewrite requests to the configured Anthropic-compatible base URL. For Kie, use `https://api.kie.ai/claude` as the base URL; the plugin appends `/v1/messages` automatically. API-key routes are only eligible after direct evidence that the main OAuth quota is exhausted: a fresh quota reading for the current Claude account showing 0% remaining, or an actual main OAuth model response with HTTP 429 / streaming rate-limit error followed by a live quota check that confirms 0% remaining. Low-but-nonzero quota, stale cached quota, unconfirmed 429s, 401, or 403 do not trigger API-key routes. API-route keys are stored with the pool's private state, separate from public route settings. **Add API-key fallback** selects either `authorization-bearer` or `x-api-key` for the authentication header.
282
340
 
283
- For Pi fallback accounts, write the same account JSON shape to `~/.pi/agent/anthropic-auth.json`. The CLI helper currently lives in the OpenCode package, so you can also point it at Pi's sidecar path when logging in a fallback account:
341
+ OpenCode cost accounting stays simple: when the native Anthropic auth entry is OAuth, OpenCode sees zero-cost Claude OAuth models by default. If a request falls through to an API-key route, token accounting is still recorded, but OpenCode's built-in dollar cost is not route-aware. To retain Anthropic model pricing for OAuth sessions during migration, set `costZeroing.enabled` to `false` in the old `anthropic-auth.json` before the first local setup. Setup imports that setting; the menu does not expose it.
284
342
 
285
- ```bash
286
- OPENCODE_ANTHROPIC_AUTH_FILE="$HOME/.pi/agent/anthropic-auth.json" \
287
- bunx @cortexkit/opencode-anthropic-auth login personal-alt
288
- ```
343
+ The CLI manages only OpenCode's locally stored Claude accounts and API-key fallbacks. Add Pi fallback accounts from Pi's `/claude` menu.
289
344
 
290
345
  Fallback retries are only attempted when the request body is safely replayable. If the original body is non-replayable or already consumed, the plugin returns the primary response unchanged.
291
346
 
292
347
  ### Token refresh
293
348
 
294
- Fallback OAuth tokens refresh in the background so idle accounts do not expire before they are needed. Refresh token rotation is persisted immediately. The plugin also re-reads the latest sidecar account before refreshing, which avoids using stale refresh-token snapshots when multiple background paths run close together. Persisted refresh backoffs are bound to the refresh token that produced them, so replacing a rejected credential immediately clears its stale latch.
295
-
296
- If Anthropic reports `invalid_grant`, that account must be logged in again. `/claude-account reset-backoff` manually clears the main account's refresh backoff and its matching quota backoff.
297
-
298
- ### Claustrum manifest service
299
-
300
- In global Claustrum mode, `/claude-account claustrum` serves OAuth routes that have a binding present in the Claustrum handle manifest; `/claude-account local` returns authority to local OAuth refresh. The vault serves credentials, and the plugin discovers only its own provider block.
349
+ Local OAuth tokens refresh in the background so idle accounts do not expire before they are needed. Refresh token rotation is persisted immediately. The plugin also re-reads the latest stored account before refreshing, which avoids using stale refresh-token snapshots when multiple background paths run close together. Persisted refresh backoffs are bound to the refresh token that produced them, so replacing a rejected credential immediately clears the backoff left by the old refresh token. In vault custody, the vault alone refreshes credentials.
301
350
 
302
- The request path reads only a resident in-memory credential. Startup warming and periodic reconciliation perform vault I/O and keep idle credentials refreshed. In Claustrum mode, a cold or unavailable vault must return a typed provider-unavailable response; it does not fall back to the sidecar credential path. That cold-route behavior lands with the dedicated cold-route task. Vault-served 401 reports carry the exact record version and response provenance, including relay-stream 401s, so a sidecar-served failure cannot invalidate a healthy vault credential. `/claude-account` and the account modal show manifest-binding presence, current vault service, and vault reauthentication state without exposing capability handles.
303
-
304
- After a new Anthropic credential is explicitly bound to `anthropic-auth`, a running plugin watches the manifest and automatically creates its secret-free routing row; the same reconciliation runs during startup. Enrollment requires an exact live `credential.get` match for both the manifest credential ID and provider account UUID, persists only a custody tombstone plus identity metadata, and immediately refreshes the new route's quota so sticky-balanced routing does not wait for the next background interval. Existing disabled rows remain disabled. To stop routing without changing the manifest, disable the account; removing a manifest-bound row is refused until its binding is removed.
305
-
306
- Claustrum mode also starts the future scoped-discovery enrollment ceremony under the host identity `anthropic-auth-opencode`. The plugin writes the request secret before proposing, shares one locked ceremony across every OpenCode project process, and displays the pending request ID and exact approval command in `/claude-account`. Approval is persisted atomically as an owner-only token at `$XDG_STATE_HOME/cortexkit/anthropic-auth/opencode-enrollment.json` (default `~/.local/state/cortexkit/anthropic-auth/opencode-enrollment.json`). Grant that identity only `category:anthropic-native`; never grant the broader `llm-provider` category. This release does not spend the enrollment token yet: model requests continue through the existing capability-handle manifest until the scoped-discovery cutover lands. `/claude-account enrollment-reset` retries only a denied or locally blocked ceremony and refuses to discard pending or approved authority.
307
-
308
- If Claustrum has replaced the main host credential with its provider-bound tombstone, the plugin rejects refresh locally without contacting Anthropic or persisting a permanent `invalid_grant` state. API-key routes are unaffected.
351
+ If Anthropic reports `invalid_grant`, that account must be signed in again. **Reset account backoff** in the `/claude` menu's Accounts group manually clears the main account's refresh backoff and its matching quota backoff.
309
352
 
310
353
  ## Quota-aware routing
311
354
 
@@ -324,15 +367,17 @@ With this config, an account is skipped when it has less than 10% remaining in t
324
367
 
325
368
  Main-account quota is cached. If the main account is known to be exhausted, the plugin skips it until the relevant reset time. If the cached main quota is stale but usable, the request proceeds and quota refresh happens in the background.
326
369
 
327
- Show current quota state:
370
+ Open `/claude` to see current quota state in the Quota group (**Quota summary**). It covers the main account and every fallback from the local pool, or from the vault while enrolled. In OpenCode, **Refresh quota** requests fresh quota; Pi shows the summary without that action.
328
371
 
329
- ```text
330
- /claude-quota
331
- ```
372
+ Reset times are rendered as relative durations, such as `resets in 10m` or `resets in 1h 15m`.
332
373
 
333
- In OpenCode, this includes the main Anthropic account and sidecar fallback accounts. In Pi, the command reports sidecar fallback account quota state from `~/.pi/agent/anthropic-auth.json`.
374
+ ### Quota header feed
334
375
 
335
- Reset times are rendered as relative durations, such as `resets in 10m` or `resets in 1h 15m`.
376
+ The optional quota header feed writes one lease file per process under `${TMPDIR:-/tmp}/opencode-anthropic-auth/quota-header-feed/`. Set `OPENCODE_ANTHROPIC_AUTH_QUOTA_FEED_DIR` to override the directory. Each file contains only quota headers observed by the process that wrote it. Each file records `lease_horizon_ms` (default 180000, three minutes). Consumers must discard entries whose `observed_at_ms` is in the future or at least that old, then combine fresh entries from every file and deduplicate by account. "Newest file wins" drops accounts seen by other processes.
377
+
378
+ For each account, use the entry with the greatest `observed_at_ms` for quota values. Resolve `anthropic_account_uuid` from any entry in that account's group that carries it. During an upgrade, an older plugin process that is still running can write the newest entry without that field while an updated process writes entries that have it.
379
+
380
+ Each entry always includes `anthropic_account_uuid`; an absent key identifies an older producer. Its value is provider-derived or `null`, never a local substitute. A consumer that sees `null` must count a gap, not fall back to `account_ref`: that field is a row ID local to one account store, not a global account identifier, so it must never be used to match accounts across stores.
336
381
 
337
382
  ## Safety fallback
338
383
 
@@ -354,7 +399,7 @@ Legacy mode routes a refused Fable 5/5.1 or Opus 5 session through Opus 4.8 for
354
399
 
355
400
  The killswitch is a per-account hard-block that stops requests when remaining quota drops below configured thresholds, even if Anthropic's API would still accept them. Unlike `minimumRemaining` (which routes to fallback accounts), the killswitch removes accounts from the routing pool entirely.
356
401
 
357
- Add a `killswitch` block to the sidecar config:
402
+ Killswitch settings have this shape; setup imports an existing `killswitch` block from the old sidecar file (`anthropic-auth.json`):
358
403
 
359
404
  ```json
360
405
  "killswitch": {
@@ -374,42 +419,58 @@ Add a `killswitch` block to the sidecar config:
374
419
  }
375
420
  ```
376
421
 
377
- Thresholds are remaining-percent values. With `five_hour: 5`, the account is killed when less than 5% of the 5-hour quota window remains. The optional `scoped` threshold applies to matching model-scoped quota windows (for example Fable weekly quota) and blocks when the scoped remaining percent is at or below the threshold. Accounts without an entry in `accounts` fall back to the `main` thresholds. The aliases `5h` and `1w` are also accepted.
422
+ Thresholds are remaining-percent values. With `five_hour: 5`, the account is killed when less than 5% of the 5-hour quota window remains. The optional `scoped` threshold applies to model-specific quota windows (for example a separate weekly limit for Claude Fable models, `claude-fable-*`) and blocks when the scoped remaining percent is at or below the threshold. Accounts without an entry in `accounts` fall back to the `main` thresholds. The aliases `5h` and `1w` are also accepted.
423
+
424
+ Missing quota readings:
425
+
426
+ - A positive 5-hour or 7-day floor requires a finite quota reading for that window. If the reading is missing or not a number, the account is blocked, whatever `quota.failClosedOnUnknownQuota` says.
427
+ - With no positive floor, missing readings follow `quota.failClosedOnUnknownQuota`.
428
+ - An explicit positive `scoped` floor requires scoped-window information for the account. If that information is missing, the account is blocked. A reported empty list of scoped windows shows the model has no separate window, so the scoped floor does not apply.
378
429
 
379
430
  Behavior:
380
431
 
381
432
  - When an account is killed, it is skipped during routing. Surviving accounts are tried instead.
382
433
  - When all accounts (main and all enabled fallbacks) are killed, the plugin returns a synthetic 429 response with a `retry-after` header set to the earliest quota reset time across all accounts.
383
434
  - On the first request after restart, the plugin eagerly fetches main quota so the killswitch evaluates immediately.
384
- - `/claude-quota` shows killswitch status and per-account killed/active state.
435
+ - **Killswitch status** in the `/claude` menu's Limits group shows killswitch status and per-account killed/active state.
385
436
 
386
- Manage the killswitch from inside OpenCode:
437
+ Manage the killswitch from the `/claude` menu's Limits group: **Enable killswitch**, **Disable killswitch**, and **Set killswitch thresholds**. Enter thresholds as a JSON array of objects with `account` (the account ID shown in account status, or `main`), `fh` (5-hour), `sd` (7-day), and optional `scoped` values, for example:
387
438
 
388
- ```text
389
- /claude-killswitch — show status and command cheatsheet
390
- /claude-killswitch on — enable with current or default thresholds
391
- /claude-killswitch off — disable
392
- /claude-killswitch set all:5,10 — set all accounts to 5h≥5%, 1w≥10%
393
- /claude-killswitch set main:3,8,0 — set main to 5h≥3%, 1w≥8%, scoped≤0%
394
- /claude-killswitch set main:3,8,0 work-alt:5,10,0 — per-account thresholds
439
+ ```json
440
+ [{"account":"main","fh":3,"sd":8,"scoped":0},{"account":"<account-id>","fh":5,"sd":10,"scoped":0}]
395
441
  ```
396
442
 
397
- Changes made with `/claude-killswitch` are persisted to the sidecar config.
443
+ Killswitch changes are persisted with the host's other plugin settings. Pi does not offer killswitch enable, disable, or threshold editing.
398
444
 
399
- ## Claude prompt cache control
445
+ ## The /claude menu
400
446
 
401
- Both OpenCode and Pi packages add a slash command for Anthropic's 1-hour ephemeral prompt-cache TTL:
447
+ Both hosts register one slash command, `/claude`. It opens a menu grouped by area; each action collects its own parameters, so typed arguments are not used (Pi rejects them and points you to the menu). Earlier separate `/claude-*` commands are no longer registered.
402
448
 
403
- ```text
404
- /claude-cache
405
- /claude-cache on
406
- /claude-cache off
407
- /claude-cache mode explicit
408
- /claude-cache mode automatic
409
- /claude-cache mode hybrid
410
- ```
449
+ | Group | Status shown | Actions | Pi |
450
+ | --- | --- | --- | --- |
451
+ | Accounts | Account status and usage | Enable account, Disable account, Remove account, Move account up, Move account down, Reset account backoff, Reset host enrollment, Add API-key fallback, Start OAuth sign-in, Finish OAuth sign-in, Custody setup guidance, Disconnect from the vault | All |
452
+ | Quota | Quota summary | Refresh quota | Summary only |
453
+ | Routing | Routing status | Routing mode (`main-first`, `fallback-first`, `sticky-balanced`), Reset routing session | All |
454
+ | Limits | Killswitch status | Enable killswitch, Disable killswitch, Set killswitch thresholds | Not available |
455
+ | Cache | Cache status, Cache keep status | Enable cache, Disable cache, Cache mode (`explicit`, `automatic`, `hybrid`), Keep cache warm always, Disable cache keep, Cache keep window, Cache keep for subagents (`on`/`off`) | All |
456
+ | Diagnostics | Dump status, Logging status | Enable request dumps, Disable request dumps, Logging level (`error`, `warn`, `info`, `debug`, `trace`) | All |
457
+ | Extras | Fast mode status, Prime quota window status | Enable fast mode, Disable fast mode, Enable Prime, Disable Prime, Fire lane start | Fast mode actions; Prime status without on/off |
411
458
 
412
- Without arguments, `/claude-cache` shows the current setting.
459
+ The Accounts actions shown depend on custody:
460
+
461
+ - **Local custody**: every Accounts action except **Disconnect from the vault**.
462
+ - **Vault custody**: the Accounts group shows `Accounts are managed in the vault. Disconnect from the vault to use local accounts.` Enable, disable, **Reset account backoff**, and **Disconnect from the vault** remain. Local sign-in, API-key additions, removal, reordering, **Reset host enrollment**, and **Custody setup guidance** are hidden and refused.
463
+ - **Unreadable enrollment**: the Accounts group shows the same actions as vault custody, so **Disconnect from the vault** stays available.
464
+
465
+ **Custody setup guidance** changes nothing; it explains that custody changes require stopping every OpenCode, LiteCode, and Pi process and running [setup](#quick-setup-recommended). **Remove account**, **Reset host enrollment**, and **Disconnect from the vault** ask for confirmation. Sign-in, API-key, guidance, and disconnect actions need an interactive session.
466
+
467
+ In the OpenCode TUI, `/claude` opens an interactive dialog. Outside the TUI (OpenCode Desktop or headless), it posts a text summary of the menu. In Pi without a UI, it prints the status sections only.
468
+
469
+ Command dialogs use a loopback-only RPC server (bound to `127.0.0.1`, bearer-authenticated) so the OpenCode server process can signal the separate TUI process. Its runtime directory defaults to a per-project path under the OpenCode state directory; override it with `OPENCODE_ANTHROPIC_AUTH_RPC_DIR`.
470
+
471
+ ## Claude prompt cache control
472
+
473
+ Both OpenCode and Pi control Anthropic's 1-hour ephemeral prompt-cache lifetime from the `/claude` menu's Cache group: **Enable cache**, **Disable cache**, and **Cache mode** (`explicit`, `automatic`, or `hybrid`). **Cache status** shows the current setting.
413
474
 
414
475
  Modes:
415
476
 
@@ -421,18 +482,11 @@ In OpenCode, subagent requests do not receive 1-hour TTL caching. The plugin det
421
482
 
422
483
  ### Cache keepalive
423
484
 
424
- `/claude-cachekeep` keeps recently used hybrid-mode session caches warm while the agent process is running:
485
+ Cache keepalive keeps recently used hybrid-mode session caches warm while the agent process is running. Control it from the Cache group: **Keep cache warm always**, **Cache keep window** (start and end hour), **Disable cache keep**, and **Cache keep for subagents** (`on`/`off`).
425
486
 
426
- ```text
427
- /claude-cachekeep
428
- /claude-cachekeep always
429
- /claude-cachekeep 09-23
430
- /claude-cachekeep off
431
- ```
487
+ **Keep cache warm always** keeps tracked sessions warm continuously for as long as the agent process remains open. Windows use local 24-hour time and are start-inclusive/end-exclusive: start `9`, end `23` runs from 09:00 until 22:59, and overnight windows such as start `23`, end `9` are accepted.
432
488
 
433
- `always` keeps tracked sessions warm continuously for as long as the OpenCode process remains open. Hour ranges use local 24-hour time and are start-inclusive/end-exclusive: `09-23` runs from 09:00 until 22:59, and overnight windows such as `23-09` are accepted.
434
-
435
- Cache keepalive only tracks requests when `/claude-cache` is enabled in `hybrid` mode. For each active session seen in the configured schedule, the package keeps an in-memory clone of the latest rewritten Anthropic request and sends a non-streaming `max_tokens: 0` pre-warm request about five minutes before the 1-hour cache entry would expire. Running `/claude-cachekeep` without arguments lists every live tracked session across OpenCode projects and plugin processes.
489
+ Cache keepalive only tracks requests when the cache is enabled in `hybrid` mode. For each active session seen in the configured schedule, the package keeps an in-memory clone of the latest rewritten Anthropic request and sends a non-streaming `max_tokens: 0` pre-warm request about five minutes before the 1-hour cache entry would expire. **Cache keep status** lists every live tracked session across OpenCode projects and plugin processes; Pi reports its own separately scoped live sessions.
436
490
 
437
491
  Request bodies, headers, and tokens remain in memory. A lease-backed file under the system temporary directory shares only session IDs and cache timing for cross-instance status; records from stopped processes disappear from status after about three minutes.
438
492
 
@@ -440,42 +494,32 @@ Pre-warm requests preserve explicit cache anchors but remove response-only field
440
494
 
441
495
  ## Claude quota window priming
442
496
 
443
- Quota-window priming is off by default. OpenCode controls it with:
444
-
445
- ```text
446
- /claude-prime
447
- /claude-prime on
448
- /claude-prime off
449
- ```
497
+ Quota-window priming is off by default. In OpenCode, turn it on or off with **Enable Prime** and **Disable Prime** in the `/claude` menu's Extras group; **Prime quota window status** shows its state and usage.
450
498
 
451
499
  When enabled, the plugin watches each OAuth account's 5-hour quota reset. About one minute after a confirmed reset, it sends one minimal `claude-haiku-4-5` request so the next window starts without waiting for a normal prompt. Usage is measured from response accounting.
452
500
 
453
- Scheduled fires happen only after the quota window has reset. If an idle account has no cached reset time, the plugin sends one bootstrap request to establish its first observed window. Atomic temporary-file claims ensure that multiple OpenCode processes sharing the same account config send only one request per account and reset.
501
+ Scheduled fires happen only after the quota window has reset. If an idle account has no cached reset time, the plugin sends one bootstrap request to establish its first observed window. When several processes share an account store, each tries to create a claim file for that account and reset; creating the file is atomic, so exactly one process succeeds and sends the request.
454
502
 
455
- Prime marker identities live in `anthropic-auth-state.json`. Plugin-owned refresh rotations preserve the main account's lineage, while a host credential replacement creates a new lineage. An existing main lineage without a refresh-token binding attaches to the current credential on its first check without changing identity. On upgrade, an existing fallback account receives an identity during its first prime check; that one-time marker change can send one extra request in the current window.
503
+ Claim files live in a temporary directory, separated by account store and credential lineage. Cleanup removes files older than six hours. Ordinary token refresh keeps the lineage; a new sign-in starts a new one. Private runtime state stores cumulative priming usage counters, not a history of primed windows. Legacy claim files are not migrated. Without the old claim, the new scheduler can treat an already primed window as unclaimed and send one extra request.
456
504
 
457
- Pi exposes `/claude-prime` as a status-only command. Its `on` and `off` arguments are ignored; enable or disable priming from OpenCode.
505
+ Pi shows **Prime quota window status** but has no Prime on/off actions; enable or disable priming from OpenCode.
458
506
 
459
507
  ## OpenCode lane start
460
508
 
461
- `/claude-start` is an OpenCode-only command. It queues one synthetic turn for the current session:
462
-
463
- ```text
464
- /claude-start
465
- ```
509
+ **Fire lane start** in the `/claude` menu's Extras group is OpenCode-only. It queues one synthetic turn for the current session.
466
510
 
467
- The bare command fires immediately. The synthetic prompt uses the session's current model, agent, and variant, then travels through the ordinary quota, routing, cache, relay, signing, and response pipeline. OpenCode shapes that OAuth request to `max_tokens: 1` while keeping streaming enabled, and correlates the request by its synthetic message ID. A queued modal is a request to start the turn, not a provider-success claim.
511
+ The action fires immediately. The synthetic prompt, a turn generated by the plugin rather than typed by you, uses the session's current model, agent, and variant, then travels through the ordinary quota, routing, cache, relay, signing, and response pipeline. OpenCode shapes that OAuth request to `max_tokens: 1` while keeping streaming enabled, and correlates the request by its synthetic message ID. A queued turn means OpenCode accepted it into the session's queue; it does not mean Anthropic has completed the request.
468
512
 
469
513
  > [!IMPORTANT]
470
514
  > This is a real billed request. The one-token limit reduces generated output only; Anthropic still charges for prompt-cache reads and any new cache writes. Use it when you plan to resume the session before the refreshed cache expires.
471
515
 
472
- Pi does not expose this command.
516
+ Pi does not offer **Fire lane start**, the command that warms the session's prompt cache.
473
517
 
474
518
  ### Cache diagnostics (beta)
475
519
 
476
520
  The `cache-diagnosis-2026-04-07` beta is measure-only. It asks Anthropic to report prompt-cache diagnostics; it does not change cache controls or routing. OpenCode captures the provider's top-level response ID as an opaque string and sends it as `diagnostics.previous_message_id` on the next request in the same session. The first request sends `null`.
477
521
 
478
- The `MC-CACHE-DIAG ` line is a versioned, one-line JSON record. Records and their beta side-channel are emitted only at debug level; use `/claude-logging debug` to capture them. Because emission is gated on the runtime log level, an empty record stream is ambiguous between a quiet system and a level below debug — liveness checks must cross-reference an independent activity witness (billing, usage rows, or dumps) instead of reading silence as absence of cache traffic. Version `2` contains these fields:
522
+ The `MC-CACHE-DIAG ` line is a versioned, one-line JSON record. Records and their beta side-channel are emitted only at debug level; choose **Logging level** → `debug` in the `/claude` menu's Diagnostics group to capture them. Because emission is gated on the runtime log level, an empty record stream is ambiguous between a quiet system and a level below debug — liveness checks must cross-reference an independent activity witness (billing, usage rows, or dumps) instead of reading silence as absence of cache traffic. Version `2` contains these fields:
479
523
 
480
524
  | Field | Type | Source |
481
525
  | --- | --- | --- |
@@ -515,7 +559,7 @@ Known sources map to `synthetic` as follows:
515
559
  | `start` | `true` |
516
560
  | `prewarm_cachekeep` | `true` |
517
561
 
518
- Lane-start cache observations therefore appear as ordinary `MC-CACHE-DIAG ` records with `source: "start"`; the row above is the diagnostics-side companion to the `/claude-start` pipeline described earlier.
562
+ Cache observations for the plugin-generated turn queued by **Fire lane start** appear as ordinary `MC-CACHE-DIAG ` records with `source: "start"`.
519
563
 
520
564
  `synthetic` wins on conflict. A disagreement for a known source is an emitter defect: OpenCode writes one warning and still emits the record with the supplied `synthetic` value. Unknown future sources have no mapping and must not be rejected by consumers.
521
565
 
@@ -546,15 +590,9 @@ When request dumps are enabled, each response gets a `.response.json` artifact c
546
590
 
547
591
  ## Claude fast mode
548
592
 
549
- Both OpenCode and Pi packages can persistently request Anthropic fast mode for supported Opus models:
593
+ Both OpenCode and Pi can save a fast-mode setting that applies to later requests and survives process restarts. It requests Anthropic fast mode for supported Opus models with **Enable fast mode** and **Disable fast mode** in the `/claude` menu's Extras group. **Fast mode status** shows the current setting.
550
594
 
551
- ```text
552
- /claude-fast
553
- /claude-fast on
554
- /claude-fast off
555
- ```
556
-
557
- When enabled, supported requests add `speed: "fast"` to the Anthropic JSON body and include the `fast-mode-2026-02-01` beta header. Unsupported models are left at standard speed. Anthropic currently documents fast mode for `claude-opus-4-6`, `claude-opus-4-7`, `claude-opus-4-8`, and `claude-opus-5`; Claude Fable and Mythos 5/5.1 are not fast-mode models.
595
+ When enabled, supported requests add `speed: "fast"` to the Anthropic JSON body and include the `fast-mode-2026-02-01` beta header. Unsupported models are left at standard speed. Anthropic supports fast mode for `claude-opus-4-8`, `claude-opus-5`, and `claude-opus-5-5`. Opus 4.7 rejects `speed: "fast"`, while Opus 4.6 runs at standard speed; Claude Fable and Mythos 5/5.1 are not fast-mode models.
558
596
 
559
597
  Fast and standard speeds do not share prompt-cache prefixes, so switching this setting can cause cache misses.
560
598
 
@@ -591,21 +629,21 @@ The relay is opt-in and user-owned. CortexKit does not run shared relay infrastr
591
629
 
592
630
  When enabled, the package sends large Anthropic request bodies to a Cloudflare Worker that you own. The first request for a session sends a full body; later requests send compact patches keyed by session affinity (`x-session-affinity` in OpenCode, Pi's stream `sessionId` in Pi). The Worker reconstructs the full Anthropic `/v1/messages` request and streams Anthropic's SSE response back to the client.
593
631
 
594
- New relay setups default to HTTP transport:
632
+ `relay setup` saves HTTP transport:
595
633
 
596
634
  ```json
597
635
  "transport": "http"
598
636
  ```
599
637
 
600
- HTTP is the safest release default and still sends compact full-sync/patch payloads through your Worker. WebSocket is available as an opt-in persistent session transport:
638
+ HTTP is the default because it also works with relay Workers deployed by older releases. It still sends compact payloads through your Worker: the full request body for a session's first request, then only the changes for later requests. WebSocket is an opt-in persistent session transport for OpenCode 1 and Pi:
601
639
 
602
640
  ```json
603
641
  "transport": "websocket"
604
642
  ```
605
643
 
606
- WebSocket mode uses protocol v2 on `/ws`, keeps one connection per OpenCode `x-session-affinity`, and serializes same-session requests until the previous stream finishes. Existing deployed Workers must be redeployed with this package's current Worker script before `"transport": "websocket"` will work; older relay Workers only understand the legacy protocol.
644
+ WebSocket mode uses protocol v2 on `/ws`, keeps one connection per session (OpenCode `x-session-affinity`, Pi stream `sessionId`), and serializes same-session requests until the previous stream finishes. Existing deployed Workers must be redeployed with this package's current Worker script before `"transport": "websocket"` will work; older relay Workers only understand the legacy protocol. OpenCode 2 supports direct and HTTP relay transport only; with WebSocket selected, it refuses requests before sending them with `request refused: WebSocket relay is not supported on OpenCode 2; select HTTP relay or direct transport`.
607
645
 
608
- Set up a relay in your Cloudflare account with the OpenCode package CLI:
646
+ Set up a relay in your Cloudflare account with the OpenCode package CLI. The CLI saves relay settings in OpenCode's local account pool, so run [setup](#quick-setup-recommended) for OpenCode first to prepare the local account pool before the CLI saves settings:
609
647
 
610
648
  ```bash
611
649
  CLOUDFLARE_API_TOKEN=... CLOUDFLARE_ACCOUNT_ID=... bunx @cortexkit/opencode-anthropic-auth relay setup
@@ -623,9 +661,9 @@ The setup command:
623
661
  2. Uploads the relay Worker module.
624
662
  3. Generates a relay shared secret.
625
663
  4. Enables the Worker.
626
- 5. Writes the local `relay` block to `~/.config/opencode/anthropic-auth.json`.
664
+ 5. Saves the relay URL, shared secret, and HTTP transport in OpenCode's local account pool.
627
665
 
628
- For Pi, copy the generated `relay` block into `~/.pi/agent/anthropic-auth.json` if you want the Pi package to use the same user-owned Worker.
666
+ `relay setup` configures OpenCode's relay settings, not Pi's. During the first local setup, existing relay settings (including `transport`) are copied from `anthropic-auth.json` into that application's pool; the `/claude` menu has no relay actions.
629
667
 
630
668
  The Cloudflare API token is used only during setup and is not stored by the plugin. Re-running setup with the same Worker name uploads the current Worker script again; this is how existing relay Workers are upgraded for protocol changes such as WebSocket v2.
631
669
 
@@ -654,13 +692,7 @@ Direct fallback logs `falling back direct`.
654
692
 
655
693
  ### Request dumps
656
694
 
657
- For relay/cache debugging, enable exact request dumps from inside OpenCode or Pi:
658
-
659
- ```text
660
- /claude-dump on
661
- /claude-dump off
662
- /claude-dump
663
- ```
695
+ For relay/cache debugging, enable exact request dumps from inside OpenCode or Pi with **Enable request dumps** and **Disable request dumps** in the `/claude` menu's Diagnostics group. **Dump status** shows the current setting.
664
696
 
665
697
  When enabled, the plugin writes artifacts under the OS temp directory:
666
698
 
@@ -675,7 +707,7 @@ Each filename includes a sanitized session/affinity segment so dumps from differ
675
707
  - `*.relay.json` — redacted relay payload/frame metadata for relay requests.
676
708
  - `*.request.json` — redacted direct request URL, method, and headers for direct requests.
677
709
 
678
- Dump state is persisted in the active sidecar config as `dump.enabled` (`~/.config/opencode/anthropic-auth.json` for OpenCode, `~/.pi/agent/anthropic-auth.json` for Pi). Dumps may contain prompt content and should be treated as sensitive local debugging artifacts.
710
+ The dump setting is saved with the host's other plugin settings. Dumps may contain prompt content and should be treated as sensitive local debugging artifacts.
679
711
 
680
712
  ## Environment variables
681
713
 
@@ -689,11 +721,21 @@ Dump state is persisted in the active sidecar config as `dump.enabled` (`~/.conf
689
721
  | `ANTHROPIC_DEFAULT_HAIKU_MODEL` | Proxy alias for `claude-haiku-*` models. |
690
722
  | `ANTHROPIC_DEFAULT_FABLE_MODEL` | Proxy alias for `claude-fable-*` and `claude-mythos-*` models. |
691
723
  | `ANTHROPIC_INSECURE` | Set to `1` or `true` to skip TLS verification when `ANTHROPIC_BASE_URL` is set. |
692
- | `OPENCODE_ANTHROPIC_AUTH_FILE` | Override the OpenCode sidecar config path. |
724
+ | `OPENCODE_ANTHROPIC_AUTH_FILE` | Override OpenCode's old sidecar path. The local account pool and its related files are created next to it. |
725
+ | `OPENCODE_ANTHROPIC_AUTH_STATE_FILE` | Override the old sidecar state file that setup reads during migration. |
693
726
  | `OPENCODE_ANTHROPIC_AUTH_CLAUSTRUM_ENROLLMENT_FILE` | Override the owner-only OpenCode Claustrum enrollment-token path. |
727
+ | `OPENCODE_ANTHROPIC_AUTH_CLAUSTRUM_CONNECTION_FILE` | Override the Claustrum connection file OpenCode uses. |
694
728
  | `OPENCODE_ANTHROPIC_AUTH_FALLBACK_MODE` | Set to `legacy` to bypass Anthropic's server policy and use deterministic 10-response client recovery exclusively. The default tries server-side safety fallback first and uses client recovery as a backstop. |
695
- | `PI_ANTHROPIC_AUTH_FILE` | Override the Pi sidecar config path. |
696
- | `PI_AGENT_DIR` | Override Pi's agent directory when deriving the default sidecar path. |
729
+ | `OPENCODE_ANTHROPIC_AUTH_ROUTING_STATE_FILE` | Override the persistent sticky-balanced session assignment file. |
730
+ | `OPENCODE_ANTHROPIC_AUTH_CACHEKEEP_REGISTRY_DIR` | Override the temporary OpenCode CacheKeep session lease directory. |
731
+ | `OPENCODE_ANTHROPIC_AUTH_RPC_DIR` | Override the directory for the OpenCode TUI menu RPC bridge (port file + token). Defaults to a per-project path under the OpenCode state directory. |
732
+ | `PI_ANTHROPIC_AUTH_FILE` | Override Pi's old sidecar path. The local account pool and its related files are created next to it. |
733
+ | `PI_ANTHROPIC_AUTH_CLAUSTRUM_ENROLLMENT_FILE` | Override the owner-only Pi Claustrum enrollment-token path. |
734
+ | `PI_ANTHROPIC_AUTH_CLAUSTRUM_CONNECTION_FILE` | Override the Claustrum connection file Pi uses. |
735
+ | `PI_ANTHROPIC_AUTH_ROUTING_STATE_FILE` | Override the persistent Pi sticky-balanced session assignment file. |
736
+ | `PI_ANTHROPIC_AUTH_CACHEKEEP_REGISTRY_DIR` | Override the temporary Pi CacheKeep session lease directory. |
737
+ | `PI_CODING_AGENT_DIR`, `PI_AGENT_DIR` | Override Pi's agent directory when deriving default paths. |
738
+ | `XDG_STATE_HOME` | Base directory for the default enrollment files (`cortexkit/anthropic-auth/<host>-enrollment.json`). Defaults to `~/.local/state`. |
697
739
  | `CLOUDFLARE_API_TOKEN` | Cloudflare token used by `bunx @cortexkit/opencode-anthropic-auth relay setup`. Not stored. |
698
740
  | `CLOUDFLARE_ACCOUNT_ID` | Cloudflare account ID used by relay setup. |
699
741
 
@@ -709,7 +751,7 @@ For Claude Pro/Max OAuth requests, the plugin works at the final Anthropic wire-
709
751
  2. Normalizes Claude-compatible OAuth headers and beta flags.
710
752
  3. Removes OpenCode-specific identity text from system blocks.
711
753
  4. Prepends Claude Code identity and billing-header blocks.
712
- 5. Rewrites cache controls according to `/claude-cache` mode.
754
+ 5. Rewrites cache controls according to the configured cache mode.
713
755
  6. Renames MCP tool names into Claude-compatible PascalCase form.
714
756
  7. Opts eligible Fable 5/5.1 and Opus 5 OAuth requests into Anthropic's server-side safety fallback, restores stored fallback boundaries, and activates replay-safe client recovery if the response still refuses.
715
757
  8. Computes final-body `cch` over the fully serialized request body.
@@ -810,10 +852,12 @@ The release workflow runs checks, publishes the core, OpenCode, and Pi packages
810
852
  ## Troubleshooting
811
853
 
812
854
  - Clear OpenCode's plugin cache after plugin config changes: `rm -rf ~/.cache/opencode`.
813
- - Restart OpenCode or Pi after changing sidecar config; some settings are loaded at startup.
814
- - If an OpenCode fallback account shows `invalid_grant`, run `bunx @cortexkit/opencode-anthropic-auth login <label>` again for that account.
855
+ - Start OpenCode or Pi again only after setup finishes; setup requires every host process to be stopped.
856
+ - If an OpenCode fallback account shows `invalid_grant`, run `bunx @cortexkit/opencode-anthropic-auth login <label>` again for that account. For the main account, sign in again from the host (see [Signing in](#signing-in)) or stop the hosts and run `setup --login --no-claustrum`.
857
+ - If requests refuse because the enrollment record cannot be read, repair the enrollment files or use **Disconnect from the vault** in `/claude`, which removes them and returns the host to local accounts.
858
+ - If requests refuse because OpenCode holds a separate Anthropic login while enrolled in the vault, remove that login, then choose **Claude via credential vault** (OpenCode 1) or **Claude vault accounts** (OpenCode 2); or disconnect from the vault.
815
859
  - Tail relay diagnostics when debugging relay setup: `tail -f "$(node -p 'require("node:os").tmpdir()')/opencode-anthropic-auth.log"`.
816
- - Use `/claude-quota` to inspect quota and refresh errors surfaced by the plugin.
860
+ - Open `/claude` to inspect account status, quota, and refresh errors surfaced by the plugin.
817
861
 
818
862
  ## License
819
863