impel-cli 0.7.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.
- package/README.md +695 -0
- package/bin/impel.js +7 -0
- package/package.json +29 -0
- package/src/apps.js +1263 -0
- package/src/args.js +36 -0
- package/src/claudeSetup.js +207 -0
- package/src/cli.js +184 -0
- package/src/cliProfiles.js +216 -0
- package/src/codexSecurity.js +184 -0
- package/src/codexSetup.js +224 -0
- package/src/commands/apps.js +538 -0
- package/src/commands/auth.js +89 -0
- package/src/commands/doctor.js +215 -0
- package/src/commands/experimental.js +60 -0
- package/src/commands/launch.js +161 -0
- package/src/commands/mcp.js +94 -0
- package/src/commands/setup.js +350 -0
- package/src/commands/skills.js +108 -0
- package/src/commands/status.js +95 -0
- package/src/commands/tasks.js +359 -0
- package/src/commands/tenant.js +77 -0
- package/src/commands/token.js +25 -0
- package/src/commands/update.js +217 -0
- package/src/commands/use.js +208 -0
- package/src/config.js +98 -0
- package/src/doctor.js +546 -0
- package/src/nativeProcess.js +192 -0
- package/src/prompt.js +51 -0
- package/src/selfInvocation.js +21 -0
- package/src/skills.js +314 -0
- package/src/tenants.js +194 -0
- package/src/updates.js +181 -0
- package/src/windowsApps.js +439 -0
- package/src/windowsSetup.js +122 -0
package/README.md
ADDED
|
@@ -0,0 +1,695 @@
|
|
|
1
|
+
# impel
|
|
2
|
+
|
|
3
|
+
A tiny, dependency-free CLI for macOS, Linux, and Windows that switches your
|
|
4
|
+
local **Claude Code** and **Codex** between two modes, per tool, reversibly:
|
|
5
|
+
|
|
6
|
+
- **gateway mode** — route through Impel's custom gateway, authenticated with an
|
|
7
|
+
Impel Personal Access Token (PAT).
|
|
8
|
+
- **account mode** — your own normal Anthropic / OpenAI login.
|
|
9
|
+
|
|
10
|
+
The gateway accepts `Authorization: Bearer impel_pat_...` directly. `impel` stores
|
|
11
|
+
that PAT locally and hands it to both tools through the same mechanism they
|
|
12
|
+
already support for external auth commands (`apiKeyHelper` for Claude Code,
|
|
13
|
+
`model_providers.<id>.auth.command` for Codex) — so the token is never written
|
|
14
|
+
into either tool's own config file.
|
|
15
|
+
|
|
16
|
+
- Claude Code talks to `<gateway>/anthropic`
|
|
17
|
+
- Codex uses `<gateway>/chatgpt_passthrough/backend-api/codex` as its provider
|
|
18
|
+
base and posts to the resulting `.../responses` compatibility route.
|
|
19
|
+
|
|
20
|
+
It can also install **isolated Impel desktop experiences**. On macOS, Impel
|
|
21
|
+
Claude and Impel ChatGPT are separate vendored app copies. On Windows, Impel
|
|
22
|
+
Claude launches Anthropic's signed vendor executable with its supported 3P
|
|
23
|
+
profile root, while Impel ChatGPT stages OpenAI's signed Electron payload out
|
|
24
|
+
of the protected Store directory and launches it with tenant-specific Codex and
|
|
25
|
+
browser profiles. Each approach keeps the user's normal app profile and
|
|
26
|
+
signed-in account untouched.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
Requires Node.js 18 or newer. The same command works on macOS, Linux, and
|
|
31
|
+
Windows (PowerShell):
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
npm install --global impel-cli
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The installable package is intentionally public so Impel users do not need
|
|
38
|
+
access to the private GitHub repository. It contains only this dependency-free
|
|
39
|
+
CLI—no credentials, service secrets, or customer data. Installing it grants no
|
|
40
|
+
Impel access: every protected operation still requires an Impel PAT and the
|
|
41
|
+
gateway/control plane re-checks the user's live product access, scopes, and
|
|
42
|
+
tenant membership.
|
|
43
|
+
|
|
44
|
+
Releases are published from the private repository with npm Trusted Publishing:
|
|
45
|
+
the registry accepts a short-lived OIDC credential only from the pinned release
|
|
46
|
+
workflow, so no long-lived npm token is stored in GitHub. npm also verifies the
|
|
47
|
+
published tarball's advertised SHA-512 integrity during installation.
|
|
48
|
+
|
|
49
|
+
Maintainers can exercise the Windows-specific paths from a Linux Docker engine
|
|
50
|
+
with the real Windows Node binary and Wine's `cmd.exe` compatibility layer:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
docker build --platform linux/amd64 -f test/docker/windows-wine.Dockerfile -t impel-cli-windows-test .
|
|
54
|
+
docker run --rm --platform linux/amd64 impel-cli-windows-test
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The repository CI additionally runs the complete suite on `windows-latest`;
|
|
58
|
+
that native job owns the hostile percent/caret npm-shim case that Wine does not
|
|
59
|
+
faithfully emulate.
|
|
60
|
+
|
|
61
|
+
## Quickstart
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
impel setup # token → tenant → platform clients → verify
|
|
65
|
+
impel claude # launch Claude Code with an isolated Impel profile
|
|
66
|
+
impel codex # launch Codex with an isolated Impel profile
|
|
67
|
+
impel update # later: update the CLI, apps, and skills in one command
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`impel setup` walks through everything below in one command (create your PAT at
|
|
71
|
+
`https://www.useimpel.com/settings/gateway`, paste it at the secure prompt, and
|
|
72
|
+
the wizard does the rest). On Windows it installs either missing official vendor
|
|
73
|
+
CLI from npm, prepares both tenant-isolated CLI profiles, installs the signed
|
|
74
|
+
Claude and ChatGPT desktop apps with separate tenant profiles, and syncs skills.
|
|
75
|
+
On macOS it installs the isolated desktop apps. The individual commands remain
|
|
76
|
+
for piecemeal use:
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
impel auth # paste your PAT when prompted
|
|
80
|
+
impel tenant list # see every organization available to this user
|
|
81
|
+
impel tenant use impel # select the tenant for accounts, specialists, and history
|
|
82
|
+
impel claude # launch Claude Code with an isolated Impel profile
|
|
83
|
+
impel codex # launch Codex with an isolated Impel profile
|
|
84
|
+
impel status # isolated-launcher readiness, native mode, and reachability
|
|
85
|
+
impel doctor # make one synthetic request to each provider and measure routing/latency
|
|
86
|
+
|
|
87
|
+
impel app install # install both isolated desktop app profiles
|
|
88
|
+
impel app update # update vendor apps, configs, and supported models
|
|
89
|
+
impel app open claude # open Claude Desktop with its isolated Impel profile
|
|
90
|
+
impel app open codex # open ChatGPT/Codex Desktop with its isolated Impel profile
|
|
91
|
+
|
|
92
|
+
# The normal `claude` and `codex` commands keep using your personal profiles.
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Fresh `impel claude` profiles start on **Claude Opus 4.8 with 1M context** and
|
|
96
|
+
also register **Claude Fable 5** in `/model`. You can choose a different
|
|
97
|
+
persistent default there, or override one session with `--model`.
|
|
98
|
+
|
|
99
|
+
## Commands
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
impel setup [--pat <pat>] [--tenant <org>] [--skip-apps] [--skip-clis]
|
|
103
|
+
Guided setup: token, tenant, platform clients, verify
|
|
104
|
+
(closes running Claude/ChatGPT apps, updates the vendor
|
|
105
|
+
apps, then installs the vendored Impel apps on macOS;
|
|
106
|
+
installs missing vendor CLIs on Windows)
|
|
107
|
+
impel update [--check] [--skip-apps] Update EVERYTHING: reinstall the CLI from npm, then
|
|
108
|
+
cascade to `app update all` and `skills sync all`
|
|
109
|
+
impel auth [--pat <pat>] [--gateway <url>] [--app <url>]
|
|
110
|
+
Store your Impel PAT + URLs
|
|
111
|
+
impel token [--tenant <org>] Print a selected-tenant bearer
|
|
112
|
+
impel mcp Run the local MCP bridge used by Claude/Codex
|
|
113
|
+
impel claude [claude args...] Launch isolated Impel Claude Code
|
|
114
|
+
impel codex [codex args...] Launch isolated Impel Codex
|
|
115
|
+
|
|
116
|
+
impel tasks list [--org <org>] List tickets
|
|
117
|
+
impel tasks get <id> Read one ticket
|
|
118
|
+
impel tasks create --title <title> [...] Create a ticket
|
|
119
|
+
impel tasks update <id> [...] Update a ticket
|
|
120
|
+
impel tasks delete <id> --yes Delete a ticket
|
|
121
|
+
|
|
122
|
+
impel tenant list List available organizations
|
|
123
|
+
impel tenant current Print the selected organization
|
|
124
|
+
impel tenant use <org> [--launch <target>] Select a tenant; optionally launch claude, codex, or apps
|
|
125
|
+
impel doctor [--tenant <org>|--all-tenants] Run synthetic provider, routing, and latency checks
|
|
126
|
+
|
|
127
|
+
impel use gateway [claude|codex|all] Switch to the Impel gateway (default: all)
|
|
128
|
+
impel on [claude|codex|all] Alias for `impel use gateway`
|
|
129
|
+
impel use account [claude|codex|all] Revert to your own login (default: all)
|
|
130
|
+
impel off [claude|codex|all] Alias for `impel use account`
|
|
131
|
+
|
|
132
|
+
impel skills sync [claude|codex|all] Sync Bifrost shared skills into managed clients (default: all)
|
|
133
|
+
|
|
134
|
+
impel status Launcher readiness + native mode + gateway reachability
|
|
135
|
+
impel app install [claude|chatgpt|codex|all] Install isolated apps
|
|
136
|
+
impel app update [claude|chatgpt|codex|all] Refresh apps, configs, and models
|
|
137
|
+
impel app refresh [claude|chatgpt|codex|all] Configs/catalog/skills only; safe while apps run
|
|
138
|
+
(--stale-only: no-op unless 6h+ since last sync)
|
|
139
|
+
impel app status [claude|chatgpt|codex|all] Show launcher/vendor status
|
|
140
|
+
impel app open [claude|chatgpt|codex|all] Launch isolated instances (fast path: opens
|
|
141
|
+
immediately when nothing changed since last open;
|
|
142
|
+
a detached stale-only refresh keeps things current)
|
|
143
|
+
impel app uninstall [target] [--keep-data] Remove Impel-managed app files
|
|
144
|
+
impel help Show help
|
|
145
|
+
impel --version Show version
|
|
146
|
+
|
|
147
|
+
# `impel setup` no longer takes a per-tool target and never flips native
|
|
148
|
+
# configs; flip a native tool explicitly with `impel use gateway [claude|codex]`.
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### `impel auth [--pat <pat>] [--gateway <url>] [--app <url>]`
|
|
152
|
+
|
|
153
|
+
Stores your PAT, gateway base URL, and app/control-plane URL in `~/.config/impel/config.json`
|
|
154
|
+
(created with mode `0600`, directory `0700`).
|
|
155
|
+
|
|
156
|
+
- If `--pat` isn't given, you're prompted for it (input is masked).
|
|
157
|
+
- If `--gateway` isn't given, it falls back to (in order): the gateway URL you
|
|
158
|
+
already had stored, the `IMPEL_GATEWAY_URL` environment variable, then the
|
|
159
|
+
built-in default **`https://gateway.useimpel.com`**.
|
|
160
|
+
- If `--app` isn't given, it falls back to (in order): the app URL you already
|
|
161
|
+
had stored, the `IMPEL_APP_URL` environment variable, then the built-in
|
|
162
|
+
default **`https://www.useimpel.com`**.
|
|
163
|
+
- Trailing slashes on the gateway URL are stripped automatically.
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
impel auth --pat impel_pat_xxxxxxxxxxxx --gateway https://gateway.useimpel.com --app https://www.useimpel.com
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### `impel update`
|
|
170
|
+
|
|
171
|
+
One command brings everything current, in dependency order: the CLI itself
|
|
172
|
+
(`npm install -g impel-cli@latest` from npm, with no GitHub credentials),
|
|
173
|
+
then — re-executing the freshly installed build — `impel app update all`
|
|
174
|
+
(close running apps, update the vendor apps, rebuild the vendored Impel apps)
|
|
175
|
+
and `impel skills sync all` across every managed profile.
|
|
176
|
+
|
|
177
|
+
Update discovery compares the installed package version with npm's public
|
|
178
|
+
`latest` metadata, cached for 6 hours in
|
|
179
|
+
`~/.config/impel/update-check.json`. It does not invoke Git or contact GitHub.
|
|
180
|
+
|
|
181
|
+
You'll also hear about updates without asking: `impel claude`, `impel codex`,
|
|
182
|
+
`impel status`, and `impel app open` print a one-line notice when the cached
|
|
183
|
+
remote is ahead, and refresh the cache in a detached background process when
|
|
184
|
+
it's stale (TTY-only, never blocks a launch; set `IMPEL_SKIP_UPDATE_CHECK=1`
|
|
185
|
+
to silence). The Impel desktop apps keep themselves current too: their token
|
|
186
|
+
helper kicks off a detached `impel app refresh --stale-only` on use, which
|
|
187
|
+
re-syncs configs, the model catalog, and skills at most every 6 hours — safe
|
|
188
|
+
while the apps are running because it never swaps an app bundle.
|
|
189
|
+
|
|
190
|
+
### `impel tasks ...` (aliases `impel task`, `impel tickets`, `impel ticket`)
|
|
191
|
+
|
|
192
|
+
CRUDs Impel tickets through the app/control-plane API using the stored PAT. New
|
|
193
|
+
PATs need the `tasks` scope and the user must be a **Workspace member**. Gateway
|
|
194
|
+
members intentionally cannot access tasks or other workspace features, even if
|
|
195
|
+
an older PAT still contains the scope.
|
|
196
|
+
|
|
197
|
+
```sh
|
|
198
|
+
impel tasks list --scope visible
|
|
199
|
+
impel tasks get IMP-123
|
|
200
|
+
impel tasks create --title "Fix flaky login test" --priority high --labels bug,engineering
|
|
201
|
+
impel tasks update IMP-123 --progress review --assignee rahulvbrahmal@gmail.com
|
|
202
|
+
impel tasks update IMP-123 --description-file brief.md --description-mode replace
|
|
203
|
+
impel tasks delete IMP-123 --yes
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Common options: `--org <org>` targets a specific org (default: the PAT's org),
|
|
207
|
+
`--json` prints the raw API response, and `--app <url>` overrides the app URL for
|
|
208
|
+
one command.
|
|
209
|
+
|
|
210
|
+
### Tenant selection
|
|
211
|
+
|
|
212
|
+
`impel auth` discovers every organization the PAT owner currently belongs to.
|
|
213
|
+
The default is `impel` when available, otherwise the first organization slug in
|
|
214
|
+
deterministic order. Change it with `impel tenant use <org>`.
|
|
215
|
+
|
|
216
|
+
The selected tenant controls all gateway-backed surfaces together: subscription
|
|
217
|
+
accounts, usage attribution, model catalog, and specialist discovery. The
|
|
218
|
+
gateway re-verifies both the underlying PAT and current organization membership;
|
|
219
|
+
editing the local config cannot grant access to another tenant.
|
|
220
|
+
|
|
221
|
+
Isolated CLI state is kept separately under
|
|
222
|
+
`~/.config/impel/cli/tenants/<org>/`, so Claude/Codex history and MCP state do
|
|
223
|
+
not bleed between tenants. `impel tenant use <org> --launch claude|codex|apps`
|
|
224
|
+
selects and launches in one command.
|
|
225
|
+
|
|
226
|
+
On macOS, desktop app state is isolated under
|
|
227
|
+
`~/.config/impel/apps/tenants/<org>/`. The app bundle in `~/Applications` is a
|
|
228
|
+
launcher for the currently opened tenant; `impel app open` refreshes that
|
|
229
|
+
launcher, the tenant-scoped bearer, model catalog, and specialist MCP arguments
|
|
230
|
+
before starting a new isolated instance. Windows Claude Desktop keeps each
|
|
231
|
+
tenant under `%LOCALAPPDATA%\Claude-3p\Impel\<org>` and launches the unchanged
|
|
232
|
+
signed vendor executable with that profile selected. Windows ChatGPT keeps its
|
|
233
|
+
Codex and browser state under the same tenant-scoped Impel apps root used on
|
|
234
|
+
macOS and launches a staged copy of the unchanged signed Store payload.
|
|
235
|
+
|
|
236
|
+
### Product access
|
|
237
|
+
|
|
238
|
+
Impel has two product access levels, independent of organization membership and
|
|
239
|
+
provider-pool administration:
|
|
240
|
+
|
|
241
|
+
- **Workspace member** — the complete Impel workspace plus the gateway,
|
|
242
|
+
tenant-scoped inference, and specialist agents.
|
|
243
|
+
- **Gateway member** — the gateway setup/configuration surface, tenant selector,
|
|
244
|
+
inference, and specialist agents only. Tasks, workspace rooms, notifications,
|
|
245
|
+
and other collaboration features are unavailable.
|
|
246
|
+
|
|
247
|
+
The control plane resolves this entitlement live. The CLI caches it only for
|
|
248
|
+
display; the control plane and gateway enforce it again on every protected
|
|
249
|
+
operation. Changing the selected tenant never changes the user's product access.
|
|
250
|
+
Provider launches and `impel doctor` also preflight the PAT's live
|
|
251
|
+
`claude-code-gateway` / `codex-gateway` scopes, so an older single-provider PAT
|
|
252
|
+
gets a direct rotation instruction instead of a misleading model-capacity error.
|
|
253
|
+
|
|
254
|
+
### `impel doctor`
|
|
255
|
+
|
|
256
|
+
Runs a real streaming request through each selected provider, so it consumes a
|
|
257
|
+
small amount of provider capacity. Each request contains only a generated
|
|
258
|
+
synthetic marker and asks the model to acknowledge that marker exactly. The
|
|
259
|
+
report verifies:
|
|
260
|
+
|
|
261
|
+
- live PAT, entitlement, and tenant membership resolution,
|
|
262
|
+
- the tenant-scoped model catalog,
|
|
263
|
+
- a selected subscription account on the response,
|
|
264
|
+
- the gateway-owned request ID and echoed client correlation ID,
|
|
265
|
+
- HTTP, bounded SSE parsing, provider response ID, and successful terminal event,
|
|
266
|
+
- exact request/response acknowledgement, and
|
|
267
|
+
- headers, first-byte, time-to-first-token (TTFT), and total latency.
|
|
268
|
+
|
|
269
|
+
It never prints the PAT or any real prompt content. The default TTFT warning
|
|
270
|
+
budgets are 6 seconds for Claude and 5 seconds for Codex. A budget miss is shown
|
|
271
|
+
as a warning; add `--strict-latency` to make it fail the command. Connectivity,
|
|
272
|
+
routing, account selection, or acknowledgement errors always produce a non-zero
|
|
273
|
+
exit code.
|
|
274
|
+
|
|
275
|
+
Organizations may intentionally have only one provider pool. When the live
|
|
276
|
+
catalog reports an exact `no_seat` state for a requested provider, the doctor
|
|
277
|
+
reports that provider as skipped instead of manufacturing a failed request. The
|
|
278
|
+
tenant can pass when another requested provider completes successfully. Expired
|
|
279
|
+
credentials, exhausted capacity, rate limits, ambiguous catalog responses, and
|
|
280
|
+
tenants with no usable requested provider still fail closed.
|
|
281
|
+
|
|
282
|
+
Use `--gateway <origin>` for a one-run data-plane override. Doctor resolves the
|
|
283
|
+
gateway in this order: `--gateway`, `IMPEL_GATEWAY_URL`, the saved gateway, then
|
|
284
|
+
the canonical default. The override must be a bare HTTP or HTTPS origin and is
|
|
285
|
+
never written back to the stored authentication config.
|
|
286
|
+
|
|
287
|
+
```sh
|
|
288
|
+
impel doctor
|
|
289
|
+
impel doctor --attempts 2 --strict-latency
|
|
290
|
+
impel doctor --all-tenants --attempts 2 --json > readiness.json
|
|
291
|
+
impel doctor --tenant creador --providers claude
|
|
292
|
+
impel doctor --gateway https://gateway.useimpel.com
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
`--attempts` is capped at five per provider and a single invocation is capped at
|
|
296
|
+
50 total probes to prevent an accidental high-volume run. JSON output is one
|
|
297
|
+
sanitized report suitable for CI or a rollout checklist.
|
|
298
|
+
|
|
299
|
+
### `impel token`
|
|
300
|
+
|
|
301
|
+
Prints **only** a bearer derived from the stored PAT and selected tenant to
|
|
302
|
+
stdout, nothing else. Non-zero exit and a
|
|
303
|
+
stderr message if you haven't run `impel auth` yet.
|
|
304
|
+
|
|
305
|
+
This is the contract both Claude Code's `apiKeyHelper` and Codex's
|
|
306
|
+
command-backed provider auth expect: a command that is invoked on demand and
|
|
307
|
+
whose stdout is the bearer token. Managed Codex auth and MCP entries call the
|
|
308
|
+
current Node executable plus Impel entry point directly, avoiding npm `.cmd`
|
|
309
|
+
resolution on Windows. Rotating your PAT is still one command
|
|
310
|
+
(`impel auth --pat ...`) and every tool picks it up on its next call/refresh.
|
|
311
|
+
|
|
312
|
+
### Specialist delegation over MCP
|
|
313
|
+
|
|
314
|
+
Gateway mode also installs an `impel` stdio MCP server in Claude Code and
|
|
315
|
+
Codex, including the isolated Impel ChatGPT profile. The server runs the Impel
|
|
316
|
+
MCP entry point, reads the PAT from the owner-only Impel
|
|
317
|
+
config, and proxies JSON-RPC to `<gateway>/mcp`; the PAT is never written into
|
|
318
|
+
either client's MCP configuration. Available specialists are discovered at
|
|
319
|
+
runtime, so publishing a new opted-in specialist does not require another CLI
|
|
320
|
+
release.
|
|
321
|
+
|
|
322
|
+
### Isolated CLI launchers
|
|
323
|
+
|
|
324
|
+
`impel claude [args...]` and `impel codex [args...]` launch the installed vendor
|
|
325
|
+
CLIs with every argument, the current working directory, stdin/stdout/stderr,
|
|
326
|
+
and the vendor exit code passed through unchanged. They require `impel auth`
|
|
327
|
+
and load gateway authentication plus the Impel MCP server from private,
|
|
328
|
+
Impel-only profiles:
|
|
329
|
+
|
|
330
|
+
- Claude: `~/.config/impel/cli/tenants/<org>/claude` via `CLAUDE_CONFIG_DIR`
|
|
331
|
+
- Codex: `~/.config/impel/cli/tenants/<org>/codex` via `CODEX_HOME`
|
|
332
|
+
|
|
333
|
+
The normal `claude` and `codex` commands still use `~/.claude`, `~/.claude.json`,
|
|
334
|
+
and `~/.codex`. The launchers do not read, copy, modify, or remove those native
|
|
335
|
+
profiles, their credentials, or their conversation history. Project-level
|
|
336
|
+
files and the working directory remain available exactly as they are in the
|
|
337
|
+
normal CLIs.
|
|
338
|
+
|
|
339
|
+
The isolated launchers also add an Impel-only instruction that checks the live
|
|
340
|
+
tenant specialist catalog before non-trivial work. When one available
|
|
341
|
+
specialist clearly matches, the client starts one idempotent specialist run,
|
|
342
|
+
waits for it to finish, and uses its result instead of repeating the task. It
|
|
343
|
+
continues normally when no specialist matches or delegation is unavailable.
|
|
344
|
+
Claude receives this through `--append-system-prompt`; Codex receives it through
|
|
345
|
+
the invocation-local `developer_instructions` override. Neither instruction is
|
|
346
|
+
written to or loaded by the native `claude` or `codex` commands.
|
|
347
|
+
|
|
348
|
+
The isolated Codex launcher uses Codex's embedded code-mode runtime so MCP tools
|
|
349
|
+
keep working when a vendor install does not include the optional standalone
|
|
350
|
+
`codex-code-mode-host` companion. Only the four specialist-control tools are
|
|
351
|
+
pre-approved for non-interactive delegation; other MCP tools retain Codex's
|
|
352
|
+
normal approval behavior. Its Codex-only instruction also resolves exact Impel
|
|
353
|
+
specialist tools through `tool_search` when the client defers MCP tools instead
|
|
354
|
+
of showing them directly. These settings apply only to `impel codex`.
|
|
355
|
+
|
|
356
|
+
The isolated Codex profile disables Codex shell snapshots and explicitly keeps
|
|
357
|
+
the default `KEY`/`SECRET`/`TOKEN` environment filter enabled. Before every
|
|
358
|
+
launch, `impel` removes derived `shell_snapshots`, drops inherited direct-auth
|
|
359
|
+
variables such as `CODEX_ACCESS_TOKEN`, and enforces owner-only permissions on
|
|
360
|
+
the managed profile and credential/config files. It also sweeps inactive tenant
|
|
361
|
+
and pre-tenancy Impel CLI profiles, so switching organizations cannot strand an
|
|
362
|
+
older snapshot. These safeguards apply only to Impel-owned `CODEX_HOME`
|
|
363
|
+
directories; native `~/.codex` remains untouched.
|
|
364
|
+
|
|
365
|
+
On Windows, `impel setup` ensures the official `@anthropic-ai/claude-code` and
|
|
366
|
+
`@openai/codex` packages are available, installing only the missing package(s)
|
|
367
|
+
with the same npm installation that supplies Impel. Use `--skip-clis` to prepare
|
|
368
|
+
the profiles without installing missing vendor CLIs. The launchers and skill
|
|
369
|
+
sync resolve native executables through `PATH`/`PATHEXT`, including global npm
|
|
370
|
+
`.cmd` and `.bat` shims. Windows environment references such as `%NVM_SYMLINK%`
|
|
371
|
+
are expanded during lookup, and the standard npm-global, Claude native-installer,
|
|
372
|
+
and Codex standalone-installer directories are checked even when the parent
|
|
373
|
+
PowerShell PATH is stale. Arguments are forwarded through an explicitly escaped
|
|
374
|
+
`cmd.exe` invocation without Node shell mode; NULs and line breaks, which cannot
|
|
375
|
+
be represented safely through a batch shim, are rejected before anything is
|
|
376
|
+
launched. Managed Codex auth and MCP subprocesses bypass batch shims entirely by
|
|
377
|
+
calling Node directly.
|
|
378
|
+
|
|
379
|
+
If npm itself fails during setup, the wizard prints the native spawn error and
|
|
380
|
+
the exact vendor-package command to retry in PowerShell. If npm succeeds but the
|
|
381
|
+
new commands remain undiscoverable, close and reopen PowerShell; then use
|
|
382
|
+
`npm prefix --global` to identify the directory that must be on the user PATH.
|
|
383
|
+
Setup exits non-zero and says it is incomplete until both launchers are ready—it
|
|
384
|
+
does not print a success banner after a failed installation.
|
|
385
|
+
|
|
386
|
+
Windows receives the complete CLI workflow: setup/auth, tenant selection,
|
|
387
|
+
isolated Claude and Codex launches, native profile switching, tasks, skills,
|
|
388
|
+
status, doctor, self-update, and both isolated desktop apps. `impel app install
|
|
389
|
+
claude` installs/updates Anthropic's signed per-user app through winget, writes
|
|
390
|
+
the selected tenant's 3P gateway configuration beneath Anthropic's reserved
|
|
391
|
+
`%LOCALAPPDATA%\Claude-3p\Impel\<tenant>` root, and leaves the executable and
|
|
392
|
+
normal Claude profile unchanged. `impel app install codex` installs/updates
|
|
393
|
+
OpenAI's `OpenAI.Codex` Store package, stages its unchanged signed app payload
|
|
394
|
+
inside Impel's shared app cache, and writes separate Codex and Chromium
|
|
395
|
+
profiles. `impel app open claude` and `impel app open codex` launch those
|
|
396
|
+
isolated profiles without changing either normal vendor profile.
|
|
397
|
+
|
|
398
|
+
For Claude, the Impel PAT is supplied only to the launched child process as an
|
|
399
|
+
authentication token and disappears when that process exits; it is never
|
|
400
|
+
written into the isolated Claude profile. The launcher also recognizes
|
|
401
|
+
Claude's standard native-installer location at `~/.local/bin/claude` when that
|
|
402
|
+
directory is not present in the parent process's `PATH`.
|
|
403
|
+
|
|
404
|
+
```sh
|
|
405
|
+
impel claude
|
|
406
|
+
impel claude -p "summarize this repository" --output-format json
|
|
407
|
+
impel codex
|
|
408
|
+
impel codex exec --json "review the current diff"
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
`impel use gateway` remains available for users who intentionally want to
|
|
412
|
+
switch their native profiles in place; the isolated launchers are the safer
|
|
413
|
+
default when personal and Impel sessions should coexist.
|
|
414
|
+
|
|
415
|
+
### `impel use gateway [claude|codex|all]` (alias `impel on`)
|
|
416
|
+
|
|
417
|
+
Turns **on** gateway mode for the given tool (default `all`). Requires `impel auth`
|
|
418
|
+
first.
|
|
419
|
+
|
|
420
|
+
**Claude Code** — merges into `~/.claude/settings.json` (creating it if needed,
|
|
421
|
+
leaving every other key — permissions, hooks, other env vars — untouched):
|
|
422
|
+
|
|
423
|
+
```json
|
|
424
|
+
{
|
|
425
|
+
"apiKeyHelper": "impel token",
|
|
426
|
+
"env": {
|
|
427
|
+
"ANTHROPIC_BASE_URL": "https://gateway.useimpel.com/anthropic"
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
**Codex** — merges into `~/.codex/config.toml`. Codex supports pointing
|
|
433
|
+
`model_provider` at a custom `[model_providers.<id>]` table, plus a
|
|
434
|
+
**command-backed** bearer token via a `[model_providers.<id>.auth]` sub-table
|
|
435
|
+
(`command` + `args`, re-invoked on a timer and on auth retries — the same shape
|
|
436
|
+
as Claude Code's `apiKeyHelper`), so we reuse `impel token` there too instead of
|
|
437
|
+
writing the PAT into `config.toml` or `~/.codex/auth.json`. The block written
|
|
438
|
+
(fenced by markers, so everything else in your `config.toml` — other
|
|
439
|
+
`model_providers`, `mcp_servers`, sandbox policy — is left alone):
|
|
440
|
+
|
|
441
|
+
```toml
|
|
442
|
+
model_provider = "impel"
|
|
443
|
+
|
|
444
|
+
# >>> impel-cli managed block (model_providers.impel) >>>
|
|
445
|
+
# Generated by `impel use gateway codex`. Safe to re-run; do not hand-edit
|
|
446
|
+
# the lines between the markers above/below, they'll be overwritten.
|
|
447
|
+
[model_providers.impel]
|
|
448
|
+
name = "Impel Gateway"
|
|
449
|
+
base_url = "https://gateway.useimpel.com/chatgpt_passthrough/backend-api/codex"
|
|
450
|
+
wire_api = "responses"
|
|
451
|
+
|
|
452
|
+
[model_providers.impel.auth]
|
|
453
|
+
command = "impel"
|
|
454
|
+
args = ["token"]
|
|
455
|
+
timeout_ms = 5000
|
|
456
|
+
refresh_interval_ms = 300000
|
|
457
|
+
# <<< impel-cli managed block <<<
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
Before overwriting anything, `impel` **backs up** what was there (any prior
|
|
461
|
+
`apiKeyHelper` / `ANTHROPIC_BASE_URL`, and the prior Codex `model_provider`
|
|
462
|
+
value) into `~/.config/impel/config.json`, so `impel use account` can restore it
|
|
463
|
+
exactly. If `config.toml` already has a `[model_providers.impel]` table that
|
|
464
|
+
wasn't written by this tool, `impel` refuses to touch the file and tells you to
|
|
465
|
+
resolve it manually rather than risk emitting invalid/duplicate TOML.
|
|
466
|
+
|
|
467
|
+
### `impel use account [claude|codex|all]` (alias `impel off`)
|
|
468
|
+
|
|
469
|
+
Turns gateway mode **off** and restores your normal account-based setup. It
|
|
470
|
+
removes **only** the Impel-added bits, never your own config:
|
|
471
|
+
|
|
472
|
+
- **Claude Code** — removes `apiKeyHelper` only if it's `"impel token"`, and
|
|
473
|
+
`env.ANTHROPIC_BASE_URL` only if it equals `<gateway>/anthropic`. Then restores
|
|
474
|
+
whatever those keys held before gateway mode (from the backup). If there was
|
|
475
|
+
nothing before, they're deleted (and an emptied `env` is dropped).
|
|
476
|
+
- **Codex** — removes the marker-fenced `[model_providers.impel]` block, and
|
|
477
|
+
resets `model_provider` **only if it currently reads `"impel"`** — back to its
|
|
478
|
+
backed-up prior value, or, if there was none, removes the line entirely so
|
|
479
|
+
Codex falls back to its built-in default. All other tables are untouched.
|
|
480
|
+
|
|
481
|
+
`impel use account` doesn't require the PAT and is safe to run repeatedly (if a
|
|
482
|
+
tool is already in account mode it just says so and changes nothing).
|
|
483
|
+
|
|
484
|
+
### `impel skills sync [claude|codex|all]`
|
|
485
|
+
|
|
486
|
+
Syncs Impel's **Bifrost shared skills** into your managed Claude Code and Codex
|
|
487
|
+
clients. The gateway publishes a public, per-client plugin marketplace whose
|
|
488
|
+
bundled plugin — `bifrost-all-skills` — contains every served skill:
|
|
489
|
+
|
|
490
|
+
- Claude Code registers its manifest URL:
|
|
491
|
+
`<gateway>/api/skills/serve/claude-code/.claude-plugin/marketplace.json`
|
|
492
|
+
- Codex registers the Git source `<gateway>/api/skills/serve/codex`; its
|
|
493
|
+
marketplace manifest lives at `<source>/.agents/plugins/marketplace.json`.
|
|
494
|
+
|
|
495
|
+
The sync is idempotent: it registers the marketplace, ensures `bifrost-all-skills`
|
|
496
|
+
is installed, then runs the client's refresh commands so an already-installed
|
|
497
|
+
plugin picks up a newer bundle. It reads each marketplace's registered `name`
|
|
498
|
+
from the served `marketplace.json` to pin installs and refreshes. Codex receives
|
|
499
|
+
the Git source rather than the nested manifest URL because its CLI clones the
|
|
500
|
+
source before discovering `.agents/plugins/marketplace.json`.
|
|
501
|
+
|
|
502
|
+
You rarely need to run it by hand — it runs **automatically** at the end of every
|
|
503
|
+
install/update path:
|
|
504
|
+
|
|
505
|
+
- `impel use gateway ...` / `impel setup ...` (native `~/.claude` / `~/.codex`)
|
|
506
|
+
- `impel app install` / `impel app update` (each isolated desktop app profile)
|
|
507
|
+
|
|
508
|
+
`impel skills sync` also covers the isolated `impel claude` / `impel codex` CLI
|
|
509
|
+
profiles and installed desktop apps when they exist. Skill syncing is
|
|
510
|
+
best-effort: if a client CLI, its `plugin` subcommand, or the gateway is
|
|
511
|
+
unavailable, it logs a warning and moves on — it never fails the parent command.
|
|
512
|
+
Set `IMPEL_SKIP_SKILL_SYNC=1` to disable it entirely (offline/CI).
|
|
513
|
+
|
|
514
|
+
### `impel status`
|
|
515
|
+
|
|
516
|
+
Shows whether the isolated CLI launchers are ready, and whether each native
|
|
517
|
+
tool profile is currently in **GATEWAY** or **ACCOUNT** mode (detected from
|
|
518
|
+
whether the Impel markers / base URL are present), plus:
|
|
519
|
+
|
|
520
|
+
- the configured gateway URL,
|
|
521
|
+
- whether a PAT is stored (masked, e.g. `impel_pat_ab12...wxyz`),
|
|
522
|
+
- the live Workspace member / Gateway member entitlement when available,
|
|
523
|
+
- a best-effort reachability check: a `POST` to `<gateway>/anthropic/v1/messages`
|
|
524
|
+
with a 5s timeout. Any HTTP response (including a 4xx) counts as "reachable" —
|
|
525
|
+
this checks the network path and gateway routing, not the request itself. A
|
|
526
|
+
`401`/`403` is called out separately since it usually just means the stored PAT
|
|
527
|
+
was rejected, not that the gateway is down.
|
|
528
|
+
|
|
529
|
+
Codex CLI and the Codex IDE extension / desktop app share the same
|
|
530
|
+
`~/.codex/config.toml`, so they always report the same mode.
|
|
531
|
+
|
|
532
|
+
## Isolated Impel desktop apps
|
|
533
|
+
|
|
534
|
+
### Windows Claude and ChatGPT Desktop
|
|
535
|
+
|
|
536
|
+
```powershell
|
|
537
|
+
impel app install claude
|
|
538
|
+
impel app open claude
|
|
539
|
+
impel app status claude
|
|
540
|
+
impel app install codex
|
|
541
|
+
impel app open codex
|
|
542
|
+
impel app status codex
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
The Windows path does not clone, patch, or re-sign Claude. It locates either
|
|
546
|
+
Anthropic's standard Squirrel installation or its signed MSIX package, then
|
|
547
|
+
launches the vendor executable with the supported `CLAUDE_USER_DATA_DIR`
|
|
548
|
+
override. Anthropic's MSIX manifest explicitly reserves `%LOCALAPPDATA%\Claude-3p`
|
|
549
|
+
for unvirtualized third-party profiles, so each Impel tenant lives below that
|
|
550
|
+
root. The app's normal first-party profile is not read or changed. `impel setup`
|
|
551
|
+
installs this profile by default; use `--skip-apps` to omit it.
|
|
552
|
+
|
|
553
|
+
For ChatGPT/Codex Desktop, Windows installs the official Microsoft Store product
|
|
554
|
+
`9PLM9XGG6VKS` (`OpenAI.Codex`). Windows blocks other programs from directly
|
|
555
|
+
executing Electron inside `C:\Program Files\WindowsApps`, so Impel copies the
|
|
556
|
+
vendor's complete `app` payload, unchanged, into a shared managed cache. It
|
|
557
|
+
then launches that copy with a separate `CODEX_HOME` and
|
|
558
|
+
`CODEX_ELECTRON_USER_DATA_PATH` (plus Electron `--user-data-dir` as a legacy
|
|
559
|
+
fallback). The normal Store app, `%USERPROFILE%\.codex`, and the normal ChatGPT
|
|
560
|
+
browser profile are not read or changed. `chatgpt` and `codex` are equivalent
|
|
561
|
+
app-target names.
|
|
562
|
+
|
|
563
|
+
### macOS Claude and ChatGPT
|
|
564
|
+
|
|
565
|
+
`impel app install` creates `Impel Claude.app` and `Impel ChatGPT.app` in
|
|
566
|
+
`~/Applications`. They have separate bundle identities and gateway
|
|
567
|
+
configuration:
|
|
568
|
+
|
|
569
|
+
- Impel Claude is an APFS-cloned vendored copy of the official app with its own
|
|
570
|
+
bundle and helper identities. Its LaunchServices environment sets the
|
|
571
|
+
vendor-supported `CLAUDE_USER_DATA_DIR` and writes the 3P gateway `configLibrary` below
|
|
572
|
+
`~/.config/impel/apps/claude`. A narrowly version-checked compatibility patch
|
|
573
|
+
connects Claude's native plan-usage meter to the authenticated aggregate
|
|
574
|
+
Claude subscription pool exposed by the Impel gateway.
|
|
575
|
+
- Impel ChatGPT is an APFS-cloned vendored copy of the official app. Its wrapper
|
|
576
|
+
sets `CODEX_HOME`, passes a separate Chromium `--user-data-dir`, and writes its
|
|
577
|
+
provider config and model catalog below `~/.config/impel/apps/chatgpt`. It also
|
|
578
|
+
supplies a process-scoped, Codex-compatible wrapper around the Impel PAT so
|
|
579
|
+
native `/status` requests can read the organization's aggregated subscription
|
|
580
|
+
pool from the gateway. Its generated Codex config uses the same snapshot and
|
|
581
|
+
subprocess-environment hardening as `impel codex`; install, update, and every
|
|
582
|
+
direct app launch also remove older snapshots for the selected profile, while
|
|
583
|
+
app install/update/open sweeps inactive tenant and legacy Impel app profiles.
|
|
584
|
+
- Neither app changes `~/.claude`, `~/.claude.json`, `~/.codex`, or the
|
|
585
|
+
normal vendor app's browser/profile data.
|
|
586
|
+
|
|
587
|
+
The official Claude and ChatGPT apps remain separate installations and keep
|
|
588
|
+
their normal accounts, updater, profiles, and bundle identities. The installer
|
|
589
|
+
uses an existing official app when found. If one is missing and
|
|
590
|
+
Homebrew is available, it installs the corresponding cask into
|
|
591
|
+
`~/Applications`. `impel app update` upgrades Homebrew-managed vendor apps,
|
|
592
|
+
rebuilds the isolated apps, reapplies version-checked compatibility patches,
|
|
593
|
+
rewrites versioned configs, and fetches the PAT-scoped model catalog from
|
|
594
|
+
`<gateway>/v1/models`. If a vendor update changes a required renderer contract,
|
|
595
|
+
the update fails without replacing the working Impel copy. If the model endpoint
|
|
596
|
+
is temporarily unavailable, the installer retains functionality using the CLI's
|
|
597
|
+
bundled catalog.
|
|
598
|
+
|
|
599
|
+
For ChatGPT/Codex, the gateway controls which models and capabilities are
|
|
600
|
+
enabled while the installer merges those entries with the vendor app's native
|
|
601
|
+
catalog. The Impel copy relaxes the vendor renderer's ChatGPT-account-only Fast
|
|
602
|
+
gate because gateway auth supplies the entitlement instead. The copy is then
|
|
603
|
+
ad-hoc signed locally. This preserves model-specific instructions and exposes
|
|
604
|
+
the same reasoning-effort and service-tier controls as the normal app, including
|
|
605
|
+
Ultra where supported and Fast only on models that advertise the `priority`
|
|
606
|
+
tier. Inference uses an explicit non-WebSocket Impel model provider so Codex
|
|
607
|
+
cannot fall back to the vendor's hard-coded `chatgpt.com` transport with an
|
|
608
|
+
Impel PAT. Config refreshes replace only the Impel-managed gateway block; plugins,
|
|
609
|
+
desktop preferences, projects, and other settings written by the isolated app
|
|
610
|
+
are kept.
|
|
611
|
+
|
|
612
|
+
Both vendored copies are ad-hoc signed locally after their bundle identities and
|
|
613
|
+
launch wrappers are installed. The Claude 3P config necessarily contains the PAT because that app accepts a
|
|
614
|
+
gateway API key rather than a token-helper command. It is stored in the same
|
|
615
|
+
owner-only Impel config tree as the primary credential. ChatGPT/Codex uses a
|
|
616
|
+
command-backed helper and does not copy the PAT into TOML. The installable app
|
|
617
|
+
also reads that helper into its own process environment for Codex account-status
|
|
618
|
+
compatibility; the value disappears when the app exits.
|
|
619
|
+
|
|
620
|
+
## Switching back and forth
|
|
621
|
+
|
|
622
|
+
The whole point: flipping between the gateway and your own account is one
|
|
623
|
+
command, per tool, and always reversible.
|
|
624
|
+
|
|
625
|
+
```sh
|
|
626
|
+
impel on # both tools -> gateway
|
|
627
|
+
impel off # both tools -> your own account (restores prior config exactly)
|
|
628
|
+
|
|
629
|
+
impel on codex # just Codex -> gateway, leave Claude Code alone
|
|
630
|
+
impel off claude # just Claude Code -> account
|
|
631
|
+
|
|
632
|
+
impel status # see where each tool stands right now
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
How the clean revert is guaranteed: `impel on` records the pre-existing values
|
|
636
|
+
(your own `apiKeyHelper` / `ANTHROPIC_BASE_URL`, and Codex's prior
|
|
637
|
+
`model_provider`) into `~/.config/impel/config.json` **before** overwriting them,
|
|
638
|
+
and only ever captures a real *account-mode* value (re-running `impel on` never
|
|
639
|
+
clobbers the backup with Impel's own values). `impel off` removes only keys that
|
|
640
|
+
still point at Impel and restores those backups — so a full `on` → `off`
|
|
641
|
+
round-trip leaves `settings.json` and `config.toml` byte-for-byte back to where
|
|
642
|
+
they started, with all your unrelated keys and tables intact.
|
|
643
|
+
|
|
644
|
+
If you'd rather revert by hand: delete `apiKeyHelper` + the Impel
|
|
645
|
+
`ANTHROPIC_BASE_URL` from `~/.claude/settings.json`; delete the block between the
|
|
646
|
+
`# >>> impel-cli managed block ... >>>` / `# <<< impel-cli managed block <<<`
|
|
647
|
+
markers in `~/.codex/config.toml` and reset `model_provider`; and
|
|
648
|
+
`rm -rf ~/.config/impel` to forget the PAT + gateway entirely.
|
|
649
|
+
|
|
650
|
+
## Codex compatibility route
|
|
651
|
+
|
|
652
|
+
The installable app uses an explicit Codex model provider at
|
|
653
|
+
`<gateway>/chatgpt_passthrough/backend-api/codex`, producing the request path
|
|
654
|
+
`/chatgpt_passthrough/backend-api/codex/responses`. The provider disables
|
|
655
|
+
WebSockets because the vendor's built-in ChatGPT provider derives that URL from
|
|
656
|
+
`chatgpt.com` rather than the configured account-service base. The gateway
|
|
657
|
+
preserves the request body while replacing the Impel PAT with the selected
|
|
658
|
+
ChatGPT subscription credential.
|
|
659
|
+
|
|
660
|
+
The installable Impel ChatGPT app also points Codex's account client at
|
|
661
|
+
`<gateway>/chatgpt_passthrough/backend-api`. The gateway exposes a virtual Impel
|
|
662
|
+
pool identity and `GET .../wham/usage`, aggregating each primary and secondary
|
|
663
|
+
subscription window across all active Codex seats with equal-seat weighting.
|
|
664
|
+
This lets the native `/status` surface show pool capacity without exposing any
|
|
665
|
+
provider account identity or OAuth credential.
|
|
666
|
+
|
|
667
|
+
Before every launch, the wrapper refreshes Codex's supported personal-access-token
|
|
668
|
+
login record from the tenant helper. That keeps the desktop app in native
|
|
669
|
+
ChatGPT-account mode, allowing `/status` to request the aggregate five-hour and
|
|
670
|
+
weekly windows instead of treating Impel as an API-key-only provider.
|
|
671
|
+
|
|
672
|
+
The gateway also exposes `POST /v1/responses`, but that is the conventional
|
|
673
|
+
OpenAI Responses front door for SDK/Eve traffic and may normalize the body
|
|
674
|
+
(including enforcing `store: false`). The CLI deliberately does not use it.
|
|
675
|
+
|
|
676
|
+
## Design notes
|
|
677
|
+
|
|
678
|
+
- **Zero dependencies.** Arg parsing, JSON/TOML merging, masked prompts, and the
|
|
679
|
+
reachability check are all hand-rolled against Node stdlib (`fs`, `os`,
|
|
680
|
+
`path`, `readline`, global `fetch`). No `chalk`, no `commander`, no `inquirer`.
|
|
681
|
+
- **The PAT lives in exactly one place:** `~/.config/impel/config.json` (mode
|
|
682
|
+
`0600`). Both Claude Code and Codex fetch it on demand by shelling out to
|
|
683
|
+
`impel token` rather than copying it into their own config files — one token,
|
|
684
|
+
one rotation path, no stale copies.
|
|
685
|
+
- **The `config.toml` merge is intentionally narrow**, not a general TOML
|
|
686
|
+
parser: it only ever touches a single top-level `model_provider` line and its
|
|
687
|
+
own fenced `[model_providers.impel*]` block, leaving unrelated tables (other
|
|
688
|
+
providers, MCP servers, sandbox policy, etc.) untouched.
|
|
689
|
+
|
|
690
|
+
## Sources consulted for the Codex config
|
|
691
|
+
|
|
692
|
+
- https://developers.openai.com/codex/config-reference
|
|
693
|
+
- https://developers.openai.com/codex/config-advanced
|
|
694
|
+
- https://developers.openai.com/codex/auth
|
|
695
|
+
- https://developers.openai.com/codex/ide
|