impel-cli 0.16.4 → 0.17.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 +224 -945
- package/package.json +2 -2
- package/src/apps.js +8 -2
- package/src/cli.js +38 -41
- package/src/cliProfiles.js +5 -1
- package/src/commands/apps.js +215 -0
- package/src/commands/converge.js +174 -0
- package/src/commands/sessions.js +114 -0
- package/src/commands/setup.js +312 -428
- package/src/commands/status.js +133 -83
- package/src/commands/tasks.js +1 -1
- package/src/commands/tenant.js +3 -5
- package/src/commands/update.js +39 -85
- package/src/commands/use.js +67 -238
- package/src/config.js +8 -3
- package/src/installRecovery/engine.js +9 -27
- package/src/installRecovery/redact.js +4 -0
- package/src/installRecovery/tools.js +1 -1
- package/src/provisioning.js +354 -0
- package/src/sessionCollector.js +996 -0
- package/src/sessionHooks.js +242 -0
- package/src/shellEntries.js +186 -0
- package/src/skills.js +1 -1
- package/src/tenants.js +1 -1
package/README.md
CHANGED
|
@@ -1,1031 +1,310 @@
|
|
|
1
|
-
# impel
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
## Gateway-only vendor package
|
|
29
|
-
|
|
30
|
-
White-labelled gateway launchers import the deliberately narrow
|
|
31
|
-
`impel-cli/gateway` subpath. It exports only `createGatewayCli`; the resulting
|
|
32
|
-
CLI accepts `setup`, `auth`, `claude`, `codex`, `status`, `token`, help, and
|
|
33
|
-
version. Tasks, tenants, PAT minting, apps, agents, skills, MCP, updates, and
|
|
34
|
-
other Impel control-plane commands are not part of this package surface.
|
|
35
|
-
|
|
36
|
-
```js
|
|
37
|
-
import { createGatewayCli } from "impel-cli/gateway";
|
|
38
|
-
|
|
39
|
-
const cli = createGatewayCli({ brand, entrypoint, version });
|
|
40
|
-
const exitCode = await cli.main(process.argv.slice(2));
|
|
41
|
-
if (exitCode) process.exitCode = exitCode;
|
|
42
|
-
```
|
|
1
|
+
# impel-cli
|
|
2
|
+
|
|
3
|
+
`impel-cli` prepares isolated Claude and Codex workspaces for every Impel
|
|
4
|
+
tenant you can access. It keeps tenant histories, settings, credentials, and
|
|
5
|
+
desktop app state separate from one another and from your personal Claude and
|
|
6
|
+
Codex profiles.
|
|
43
7
|
|
|
44
|
-
The
|
|
45
|
-
and its package version. Gateway profile behavior and the command allowlist
|
|
46
|
-
remain in `impel-cli`, so vendor CLIs do not copy or fork those implementations.
|
|
8
|
+
The normal lifecycle has two commands:
|
|
47
9
|
|
|
48
|
-
|
|
10
|
+
```sh
|
|
11
|
+
impel setup
|
|
12
|
+
impel update
|
|
13
|
+
```
|
|
49
14
|
|
|
50
|
-
|
|
51
|
-
computer with Node.js installed. Node.js includes the small installer tool
|
|
52
|
-
called `npm` that installs Impel for you.
|
|
15
|
+
## Install
|
|
53
16
|
|
|
54
|
-
|
|
17
|
+
Install the public npm package once per machine:
|
|
55
18
|
|
|
56
|
-
|
|
57
|
-
|
|
19
|
+
```sh
|
|
20
|
+
npm install --global impel-cli
|
|
21
|
+
```
|
|
58
22
|
|
|
59
|
-
|
|
60
|
-
choose the **LTS** installer, and accept the default installer options.
|
|
61
|
-
- **Linux:** follow Node's [official package-manager instructions](https://nodejs.org/en/download/package-manager)
|
|
62
|
-
for your distribution.
|
|
23
|
+
Node.js 18 or newer is required.
|
|
63
24
|
|
|
64
|
-
|
|
65
|
-
(Windows), then check that it worked:
|
|
25
|
+
Then run setup and paste an Impel Personal Access Token when prompted:
|
|
66
26
|
|
|
67
27
|
```sh
|
|
68
|
-
|
|
69
|
-
npm --version
|
|
28
|
+
impel setup
|
|
70
29
|
```
|
|
71
30
|
|
|
72
|
-
|
|
31
|
+
Setup discovers every tenant available to the PAT and prepares all supported
|
|
32
|
+
surfaces for each tenant. You do not need to repeat setup tenant by tenant.
|
|
73
33
|
|
|
74
|
-
|
|
34
|
+
## What setup does
|
|
75
35
|
|
|
76
|
-
|
|
36
|
+
`impel setup`:
|
|
37
|
+
|
|
38
|
+
1. Stores the PAT in the private Impel config file.
|
|
39
|
+
2. Fetches the complete live tenant list.
|
|
40
|
+
3. Preserves the current CLI tenant when it is still accessible, or selects the
|
|
41
|
+
control-plane default.
|
|
42
|
+
4. Creates isolated Claude and Codex CLI profiles for every supported tenant.
|
|
43
|
+
5. Installs or repairs supported tenant desktop apps on macOS and Windows.
|
|
44
|
+
6. Registers tenant apps with Finder/Spotlight or Windows Start/Search.
|
|
45
|
+
7. Verifies every supported tenant surface and prints a tenant-sorted summary.
|
|
46
|
+
|
|
47
|
+
Use `--tenant` only to choose the default for CLI launches. It does not limit
|
|
48
|
+
which tenants setup prepares:
|
|
77
49
|
|
|
78
50
|
```sh
|
|
79
|
-
|
|
51
|
+
impel setup --tenant acme
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Useful setup options:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
impel setup --pat <pat> # non-interactive credential input
|
|
58
|
+
impel setup --skip-apps # prepare CLI profiles only
|
|
59
|
+
impel setup --skip-clis # Windows: do not install missing vendor CLIs
|
|
60
|
+
impel setup --no-recovery # disable local and assisted recovery for this run
|
|
80
61
|
```
|
|
81
62
|
|
|
82
|
-
|
|
83
|
-
|
|
63
|
+
Putting a PAT on a command line can leave it in shell history. Prefer the
|
|
64
|
+
interactive prompt for ordinary use.
|
|
84
65
|
|
|
85
|
-
|
|
66
|
+
## Open apps
|
|
86
67
|
|
|
87
|
-
|
|
88
|
-
2. Create a Personal Access Token and copy it somewhere safe.
|
|
89
|
-
3. Back in Terminal or PowerShell, run:
|
|
68
|
+
After setup, launch the tenant-specific apps through the operating system:
|
|
90
69
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
```
|
|
70
|
+
- macOS: Finder, Spotlight, or `~/Applications`
|
|
71
|
+
- Windows: Start or Search under the Impel program group
|
|
94
72
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
73
|
+
Names include the tenant, such as `Impel Claude (Acme)` and
|
|
74
|
+
`Impel ChatGPT (Acme)`. The selected CLI tenant does not affect which tenant an
|
|
75
|
+
app opens. Tenant variants can remain installed side by side.
|
|
98
76
|
|
|
99
|
-
|
|
100
|
-
shared document.
|
|
77
|
+
Linux does not have managed desktop apps. Use the isolated CLI commands there.
|
|
101
78
|
|
|
102
|
-
|
|
79
|
+
## Use the CLI
|
|
80
|
+
|
|
81
|
+
Select the tenant used by CLI launches:
|
|
103
82
|
|
|
104
83
|
```sh
|
|
105
|
-
impel
|
|
106
|
-
impel
|
|
107
|
-
impel
|
|
108
|
-
impel update # install the latest Impel CLI later
|
|
84
|
+
impel tenant list
|
|
85
|
+
impel tenant current
|
|
86
|
+
impel tenant use acme
|
|
109
87
|
```
|
|
110
88
|
|
|
111
|
-
|
|
112
|
-
Windows it also prepares the supported isolated desktop experiences. On Windows,
|
|
113
|
-
it installs missing official vendor command-line tools with the vendors'
|
|
114
|
-
checksum-verifying native installers, so Claude Code does not inherit its newer
|
|
115
|
-
Node.js requirement from the deprecated npm package. On Linux, it prepares the
|
|
116
|
-
isolated command-line workflow.
|
|
117
|
-
|
|
118
|
-
If setup or the CLI self-update fails, Impel first runs deterministic local
|
|
119
|
-
repairs for known failure fingerprints — offline, with no upload. If the
|
|
120
|
-
failure persists, an interactive terminal offers assisted recovery (use
|
|
121
|
-
`impel setup --repair` or `impel update --repair` to opt in explicitly): a
|
|
122
|
-
bounded local loop where a gateway-hosted model selects typed diagnostic and
|
|
123
|
-
repair tools and the CLI validates, approves, and executes them on this
|
|
124
|
-
machine. Before the first upload, the CLI prints the exact sanitized payload.
|
|
125
|
-
Free-form model commands are impossible by construction; repairs limited to
|
|
126
|
-
Impel-owned files need one approval per session, while vendor installers and
|
|
127
|
-
PATH edits always confirm individually. Recovery only reports success after
|
|
128
|
-
the failed steps re-pass their local health checks, and it stops after 12
|
|
129
|
-
model turns or 10 minutes. Use `--no-recovery` or
|
|
130
|
-
`IMPEL_DISABLE_INSTALL_RECOVERY=1` to keep recovery off.
|
|
131
|
-
|
|
132
|
-
### If something does not work
|
|
133
|
-
|
|
134
|
-
- **`npm` or `node` is not recognized:** install Node.js from the link above,
|
|
135
|
-
then close and reopen Terminal or PowerShell.
|
|
136
|
-
- **`impel` is not recognized:** close and reopen the terminal, then run
|
|
137
|
-
`npm install --global impel-cli` again.
|
|
138
|
-
- **Your token is rejected:** create a fresh token in Impel gateway settings and
|
|
139
|
-
run `impel setup` again.
|
|
140
|
-
- **You need a different organization:** run `impel tenant list`, then
|
|
141
|
-
`impel tenant use <organization>`.
|
|
142
|
-
|
|
143
|
-
The npm package is public so Impel users do not need access to the private
|
|
144
|
-
GitHub repository. The package contains no account credentials or service
|
|
145
|
-
secrets; the Impel gateway and control plane still enforce your token, product
|
|
146
|
-
access, scopes, and organization membership for every protected action.
|
|
147
|
-
|
|
148
|
-
## Command reference
|
|
89
|
+
Then launch either client:
|
|
149
90
|
|
|
91
|
+
```sh
|
|
92
|
+
impel claude
|
|
93
|
+
impel codex
|
|
150
94
|
```
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
impel update [--check] [--skip-apps] [--repair|--no-recovery]
|
|
158
|
-
Update EVERYTHING: reinstall the CLI from npm, then
|
|
159
|
-
cascade to `app update all`, `skills sync all`, and
|
|
160
|
-
`agents sync all`
|
|
161
|
-
impel auth [--pat <pat>] [--gateway <url>] [--app <url>]
|
|
162
|
-
Store your Impel PAT + URLs
|
|
163
|
-
impel pat create --label <label> [options] Mint a personal PAT through the control plane
|
|
164
|
-
impel pat create --agent <agent-id> [options]
|
|
165
|
-
Mint a PAT associated with an org agent
|
|
166
|
-
impel pat revoke <token-id> --yes Irreversibly revoke one of your PATs
|
|
167
|
-
impel token [--tenant <org>] Print a selected-tenant bearer
|
|
168
|
-
impel mcp Run the local MCP bridge used by Claude/Codex
|
|
169
|
-
impel claude [claude args...] Launch isolated Impel Claude Code
|
|
170
|
-
impel codex [codex args...] Launch isolated Impel Codex
|
|
171
|
-
|
|
172
|
-
impel tasks list [--org <org>] List tickets
|
|
173
|
-
impel tasks get <id> Read one ticket
|
|
174
|
-
impel tasks create --title <title> [...] Create a ticket
|
|
175
|
-
impel tasks update <id> [...] Update a ticket
|
|
176
|
-
impel tasks delete <id> --yes Delete a ticket
|
|
177
|
-
|
|
178
|
-
impel tenant list List available organizations
|
|
179
|
-
impel tenant current Print the selected organization
|
|
180
|
-
impel tenant use <org> [--launch <target>] Select a tenant; optionally launch claude, codex, or apps
|
|
181
|
-
impel doctor [--tenant <org>|--all-tenants] Run synthetic provider, routing, and latency checks
|
|
182
|
-
|
|
183
|
-
impel use gateway [claude|codex|all] Switch to the Impel gateway (default: all)
|
|
184
|
-
impel on [claude|codex|all] Alias for `impel use gateway`
|
|
185
|
-
impel use account [claude|codex|all] Revert to your own login (default: all)
|
|
186
|
-
impel off [claude|codex|all] Alias for `impel use account`
|
|
187
|
-
|
|
188
|
-
impel skills sync [claude|codex|all] Sync Bifrost shared skills into managed clients (default: all)
|
|
189
|
-
impel agents sync [claude|codex|all] Sync explicit tenant agents into native clients
|
|
190
|
-
|
|
191
|
-
impel status Launcher readiness + native mode + gateway reachability
|
|
192
|
-
impel app install [target] [--tenant <org>] Install isolated apps for one tenant
|
|
193
|
-
impel app update [target] [--tenant <org>] [--force]
|
|
194
|
-
`all` without --tenant updates every installed tenant;
|
|
195
|
-
--force performs a clean full rebuild
|
|
196
|
-
impel app refresh [target] [--tenant <org>] Configs/catalog/skills/agents only; safe while apps run
|
|
197
|
-
(--stale-only: no-op unless 6h+ since last sync)
|
|
198
|
-
impel app status [target] [--tenant <org>] Show tenant launcher/vendor status
|
|
199
|
-
impel app open [target] [--tenant <org>] Install/configure a tenant on first use, then launch
|
|
200
|
-
it (later opens are immediate when nothing changed;
|
|
201
|
-
a detached stale-only refresh keeps things current)
|
|
202
|
-
impel app uninstall [target] [--tenant <org>] [--keep-data]
|
|
203
|
-
Remove one tenant's Impel-managed app files
|
|
204
|
-
impel help Show help
|
|
205
|
-
impel --version Show version
|
|
206
|
-
|
|
207
|
-
For app commands, `target` is `claude`, `chatgpt`/`codex`, or `all` (the
|
|
208
|
-
default). `impel app update all` without `--tenant` updates every locally
|
|
209
|
-
installed tenant. Other app commands, a specific update target, or an explicit
|
|
210
|
-
`--tenant` operate on one organization and default to the current selection.
|
|
211
|
-
|
|
212
|
-
# `impel setup` no longer takes a per-tool target and never flips native
|
|
213
|
-
# configs; flip a native tool explicitly with `impel use gateway [claude|codex]`.
|
|
95
|
+
|
|
96
|
+
Arguments after the command are passed to the vendor CLI:
|
|
97
|
+
|
|
98
|
+
```sh
|
|
99
|
+
impel claude --model opus
|
|
100
|
+
impel codex exec "review this repository"
|
|
214
101
|
```
|
|
215
102
|
|
|
216
|
-
|
|
103
|
+
Changing the selected tenant does not install, remove, or rewrite any other
|
|
104
|
+
tenant. It changes only the default used by CLI launches and selected-tenant
|
|
105
|
+
workspace commands.
|
|
217
106
|
|
|
218
|
-
|
|
219
|
-
(created with mode `0600`, directory `0700`).
|
|
107
|
+
## Update
|
|
220
108
|
|
|
221
|
-
|
|
222
|
-
- If `--gateway` isn't given, it falls back to (in order): the gateway URL you
|
|
223
|
-
already had stored, the `IMPEL_GATEWAY_URL` environment variable, then the
|
|
224
|
-
built-in default **`https://gateway.useimpel.com`**.
|
|
225
|
-
- If `--app` isn't given, it falls back to (in order): the app URL you already
|
|
226
|
-
had stored, the `IMPEL_APP_URL` environment variable, then the built-in
|
|
227
|
-
default **`https://www.useimpel.com`**.
|
|
228
|
-
- Trailing slashes on the gateway URL are stripped automatically.
|
|
109
|
+
Run one command for routine maintenance:
|
|
229
110
|
|
|
230
111
|
```sh
|
|
231
|
-
impel
|
|
112
|
+
impel update
|
|
232
113
|
```
|
|
233
114
|
|
|
234
|
-
|
|
115
|
+
Update:
|
|
235
116
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
117
|
+
1. Checks and installs the latest `impel-cli` package from npm.
|
|
118
|
+
2. Continues under the freshly installed build.
|
|
119
|
+
3. Fetches the current live tenant list.
|
|
120
|
+
4. Fully prepares tenants added since the previous run.
|
|
121
|
+
5. Repairs and upgrades existing tenants in place.
|
|
122
|
+
6. Re-registers operating-system launch entries.
|
|
123
|
+
7. Reports local tenants that are no longer accessible without deleting them.
|
|
241
124
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
125
|
+
An update preserves histories, browser state, preferences, permissions, stable
|
|
126
|
+
app identity, and user-authored settings outside Impel-managed blocks. Desktop
|
|
127
|
+
bundles are rebuilt only when missing, corrupt, or stale. An app is closed only
|
|
128
|
+
when its bundle must be replaced, and only an app closed by the update is
|
|
129
|
+
reopened afterward.
|
|
130
|
+
|
|
131
|
+
Useful update options:
|
|
246
132
|
|
|
247
133
|
```sh
|
|
248
|
-
impel
|
|
249
|
-
impel
|
|
250
|
-
impel
|
|
134
|
+
impel update --check # inspect npm availability without changing state
|
|
135
|
+
impel update --skip-apps # reconcile CLI profiles only
|
|
136
|
+
impel update --no-recovery # disable recovery for this run
|
|
251
137
|
```
|
|
252
138
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
accepts 1–365 and defaults to 90 days.
|
|
257
|
-
|
|
258
|
-
The new secret is returned once on stdout and is deliberately **not** written to
|
|
259
|
-
the config file. To rotate this CLI onto it, explicitly run
|
|
260
|
-
`impel auth --pat <new-pat>` after copying it. `--json` includes the raw secret,
|
|
261
|
-
so treat redirected output as a credential.
|
|
139
|
+
"Latest" means the latest npm CLI plus the exact vendor builds and profile
|
|
140
|
+
schema verified by that CLI. It does not mean cloning an untested moving vendor
|
|
141
|
+
release.
|
|
262
142
|
|
|
263
|
-
|
|
143
|
+
## Status and diagnosis
|
|
264
144
|
|
|
265
145
|
```sh
|
|
266
|
-
impel
|
|
267
|
-
impel
|
|
146
|
+
impel status
|
|
147
|
+
impel doctor
|
|
148
|
+
impel doctor --all-tenants
|
|
268
149
|
```
|
|
269
150
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
(`npm install -g impel-cli@latest` from npm, with no GitHub credentials),
|
|
281
|
-
then — re-executing the freshly installed build — `impel app update all`
|
|
282
|
-
(update every locally installed tenant and rebuild only stale vendored Impel apps)
|
|
283
|
-
followed by `impel skills sync all` and `impel agents sync all` across every
|
|
284
|
-
native and isolated CLI profile. Each tenant's app step syncs that tenant's app
|
|
285
|
-
profiles; the dedicated steps exclude apps, so every profile is synced once.
|
|
286
|
-
|
|
287
|
-
Most updates are in place — the desktop apps are **not** closed. A vendored
|
|
288
|
-
bundle is only rebuilt (and therefore only quit) when the bundle-building logic
|
|
289
|
-
or the pinned vendor version actually changes, not on every CLI release, so a
|
|
290
|
-
routine update just rewrites configs, skills, and agents while the apps keep
|
|
291
|
-
running. When a rebuild genuinely is required, `impel app update` closes only
|
|
292
|
-
the app whose bundle it will swap and **reopens it afterward**, so the swap
|
|
293
|
-
lands without you relaunching by hand. Apps you had already closed stay closed.
|
|
294
|
-
|
|
295
|
-
Update discovery compares the installed package version with npm's public
|
|
296
|
-
`latest` metadata, cached for 6 hours in
|
|
297
|
-
`~/.config/impel/update-check.json`. It does not invoke Git or contact GitHub.
|
|
298
|
-
|
|
299
|
-
You'll also hear about updates without asking: `impel claude`, `impel codex`,
|
|
300
|
-
`impel status`, and `impel app open` print a one-line notice when the cached
|
|
301
|
-
remote is ahead, and refresh the cache in a detached background process when
|
|
302
|
-
it's stale (TTY-only, never blocks a launch; set `IMPEL_SKIP_UPDATE_CHECK=1`
|
|
303
|
-
to silence). The Impel desktop apps keep themselves current too: their token
|
|
304
|
-
helper kicks off a detached `impel app refresh --stale-only` on use, which
|
|
305
|
-
re-syncs configs, the model catalog, skills, and native agents at most every six
|
|
306
|
-
hours — safe while the apps are running because it never swaps an app bundle.
|
|
307
|
-
|
|
308
|
-
### `impel tasks ...` (aliases `impel task`, `impel tickets`, `impel ticket`)
|
|
309
|
-
|
|
310
|
-
CRUDs Impel tickets through the app/control-plane API using the stored PAT. New
|
|
311
|
-
PATs need the `tasks` scope and the user must be a **Workspace member**. Gateway
|
|
312
|
-
members intentionally cannot access tasks or other workspace features, even if
|
|
313
|
-
an older PAT still contains the scope.
|
|
151
|
+
`impel status` is read-only. It shows authentication, the current CLI tenant,
|
|
152
|
+
and every tenant's local Claude, Codex, and desktop readiness. Its repair path
|
|
153
|
+
is `impel update`.
|
|
154
|
+
|
|
155
|
+
`impel doctor` sends explicit synthetic provider checks. Those requests may be
|
|
156
|
+
billable, so doctor never runs implicitly.
|
|
157
|
+
|
|
158
|
+
## Workspace tasks
|
|
159
|
+
|
|
160
|
+
Workspace members with a PAT carrying the `tasks` scope can use Impel tickets:
|
|
314
161
|
|
|
315
162
|
```sh
|
|
316
163
|
impel tasks list --scope visible
|
|
317
164
|
impel tasks get IMP-123
|
|
318
|
-
impel tasks create --title "
|
|
319
|
-
impel tasks update IMP-123 --progress review
|
|
320
|
-
impel tasks update IMP-123 --description-file brief.md --description-mode replace
|
|
165
|
+
impel tasks create --title "Harden setup verification"
|
|
166
|
+
impel tasks update IMP-123 --progress review
|
|
321
167
|
impel tasks delete IMP-123 --yes
|
|
322
168
|
```
|
|
323
169
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
`impel auth` discovers every organization the PAT owner currently belongs to.
|
|
331
|
-
The default is `impel` when available, otherwise the first organization slug in
|
|
332
|
-
deterministic order. Change it with `impel tenant use <org>`.
|
|
333
|
-
|
|
334
|
-
The selected tenant controls all gateway-backed surfaces together: subscription
|
|
335
|
-
accounts, usage attribution, model catalog, and specialist discovery. The
|
|
336
|
-
gateway re-verifies both the underlying PAT and current organization membership;
|
|
337
|
-
editing the local config cannot grant access to another tenant.
|
|
338
|
-
|
|
339
|
-
Isolated CLI state is kept separately under
|
|
340
|
-
`~/.config/impel/cli/tenants/<org>/`, so Claude/Codex history and MCP state do
|
|
341
|
-
not bleed between tenants. `impel tenant use <org> --launch claude|codex|apps`
|
|
342
|
-
selects and launches in one command.
|
|
343
|
-
|
|
344
|
-
On macOS, desktop app state is isolated under
|
|
345
|
-
`~/.config/impel/apps/tenants/<org>/`. Every installed tenant keeps its own app
|
|
346
|
-
bundles in `~/Applications`, with names such as `Impel Claude (Acme)` and
|
|
347
|
-
`Impel ChatGPT (Acme)`, stable tenant-specific bundle identifiers, and fixed
|
|
348
|
-
tenant profile/auth paths. Different tenants can stay open concurrently.
|
|
349
|
-
`impel app open --tenant <org>` installs and configures a missing tenant variant
|
|
350
|
-
on first use, then launches it directly without changing the globally selected
|
|
351
|
-
tenant. Later opens use the existing isolated app and profile. Switching tenants
|
|
352
|
-
never deletes local history or projects; each tenant's preserved profile reopens
|
|
353
|
-
independently. The first-use setup still requires an authenticated user PAT and
|
|
354
|
-
live membership in the requested organization; it does not create a PAT per
|
|
355
|
-
tenant.
|
|
356
|
-
Windows Claude Desktop keeps each
|
|
357
|
-
tenant under `%LOCALAPPDATA%\Claude-3p\Impel\<org>` and launches the unchanged
|
|
358
|
-
signed vendor executable with that profile selected. Windows ChatGPT keeps its
|
|
359
|
-
Codex and browser state under the same tenant-scoped Impel apps root used on
|
|
360
|
-
macOS and launches a staged copy of the unchanged signed Store payload.
|
|
361
|
-
|
|
362
|
-
### Product access
|
|
363
|
-
|
|
364
|
-
Impel has two product access levels, independent of organization membership and
|
|
365
|
-
provider-pool administration:
|
|
366
|
-
|
|
367
|
-
- **Workspace member** — the complete Impel workspace plus the gateway,
|
|
368
|
-
tenant-scoped inference, and specialist agents.
|
|
369
|
-
- **Gateway member** — the gateway setup/configuration surface, tenant selector,
|
|
370
|
-
inference, and specialist agents only. Tasks, workspace rooms, notifications,
|
|
371
|
-
and other collaboration features are unavailable.
|
|
372
|
-
|
|
373
|
-
The control plane resolves this entitlement live. The CLI caches it only for
|
|
374
|
-
display; the control plane and gateway enforce it again on every protected
|
|
375
|
-
operation. Changing the selected tenant never changes the user's product access.
|
|
376
|
-
Provider launches and `impel doctor` also preflight the PAT's live
|
|
377
|
-
`claude-code-gateway` / `codex-gateway` scopes, so an older single-provider PAT
|
|
378
|
-
gets a direct rotation instruction instead of a misleading model-capacity error.
|
|
379
|
-
|
|
380
|
-
### `impel doctor`
|
|
381
|
-
|
|
382
|
-
Runs a real streaming request through each selected provider, so it consumes a
|
|
383
|
-
small amount of provider capacity. Each request contains only a generated
|
|
384
|
-
synthetic marker and asks the model to acknowledge that marker exactly. The
|
|
385
|
-
report verifies:
|
|
386
|
-
|
|
387
|
-
- live PAT, entitlement, and tenant membership resolution,
|
|
388
|
-
- the tenant-scoped model catalog,
|
|
389
|
-
- a selected subscription account on the response,
|
|
390
|
-
- the gateway-owned request ID and echoed client correlation ID,
|
|
391
|
-
- HTTP, bounded SSE parsing, provider response ID, and successful terminal event,
|
|
392
|
-
- exact request/response acknowledgement, and
|
|
393
|
-
- headers, first-byte, time-to-first-token (TTFT), and total latency.
|
|
394
|
-
|
|
395
|
-
It never prints the PAT or any real prompt content. The default TTFT warning
|
|
396
|
-
budgets are 6 seconds for Claude and 5 seconds for Codex. A budget miss is shown
|
|
397
|
-
as a warning; add `--strict-latency` to make it fail the command. Connectivity,
|
|
398
|
-
routing, account selection, or acknowledgement errors always produce a non-zero
|
|
399
|
-
exit code.
|
|
400
|
-
|
|
401
|
-
Organizations may intentionally have only one provider pool. When the live
|
|
402
|
-
catalog reports an exact `no_seat` state for a requested provider, the doctor
|
|
403
|
-
reports that provider as skipped instead of manufacturing a failed request. The
|
|
404
|
-
tenant can pass when another requested provider completes successfully. Expired
|
|
405
|
-
credentials, exhausted capacity, rate limits, ambiguous catalog responses, and
|
|
406
|
-
tenants with no usable requested provider still fail closed.
|
|
407
|
-
|
|
408
|
-
Use `--gateway <origin>` for a one-run data-plane override. Doctor resolves the
|
|
409
|
-
gateway in this order: `--gateway`, `IMPEL_GATEWAY_URL`, the saved gateway, then
|
|
410
|
-
the canonical default. The override must be a bare HTTP or HTTPS origin and is
|
|
411
|
-
never written back to the stored authentication config.
|
|
170
|
+
Use `--json` when exact machine-readable fields matter. Gateway-only members
|
|
171
|
+
cannot use task CRUD.
|
|
172
|
+
|
|
173
|
+
## PAT lifecycle
|
|
174
|
+
|
|
175
|
+
Minting and revocation remain explicit account operations:
|
|
412
176
|
|
|
413
177
|
```sh
|
|
414
|
-
impel
|
|
415
|
-
impel
|
|
416
|
-
impel
|
|
417
|
-
impel doctor --tenant creador --providers claude
|
|
418
|
-
impel doctor --gateway https://gateway.useimpel.com
|
|
178
|
+
impel pat create --label laptop
|
|
179
|
+
impel pat create --agent <agent-id> --org acme
|
|
180
|
+
impel pat revoke <token-id> --yes
|
|
419
181
|
```
|
|
420
182
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
### Isolated CLI launchers
|
|
451
|
-
|
|
452
|
-
`impel claude [args...]` and `impel codex [args...]` launch the installed vendor
|
|
453
|
-
CLIs with every argument, the current working directory, stdin/stdout/stderr,
|
|
454
|
-
and the vendor exit code passed through unchanged. They require `impel auth`
|
|
455
|
-
and load gateway authentication plus the Impel MCP server from private,
|
|
456
|
-
Impel-only profiles:
|
|
457
|
-
|
|
458
|
-
- Claude: `~/.config/impel/cli/tenants/<org>/claude` via `CLAUDE_CONFIG_DIR`
|
|
459
|
-
- Codex: `~/.config/impel/cli/tenants/<org>/codex` via `CODEX_HOME`
|
|
460
|
-
|
|
461
|
-
The normal `claude` and `codex` commands still use `~/.claude`, `~/.claude.json`,
|
|
462
|
-
and `~/.codex`. The launchers do not read, copy, modify, or remove those native
|
|
463
|
-
profiles, their credentials, or their conversation history. Project-level
|
|
464
|
-
files and the working directory remain available exactly as they are in the
|
|
465
|
-
normal CLIs.
|
|
466
|
-
|
|
467
|
-
The isolated launchers also add an Impel-only instruction that checks the live
|
|
468
|
-
tenant specialist catalog before non-trivial work. When one available
|
|
469
|
-
specialist clearly matches, the client starts one idempotent specialist run,
|
|
470
|
-
waits for it to finish, and uses its result instead of repeating the task. It
|
|
471
|
-
continues normally when no specialist matches or delegation is unavailable.
|
|
472
|
-
Claude receives this through `--append-system-prompt`; Codex receives it through
|
|
473
|
-
the invocation-local `developer_instructions` override. Neither instruction is
|
|
474
|
-
written to or loaded by the native `claude` or `codex` commands.
|
|
475
|
-
|
|
476
|
-
The isolated Codex launcher uses Codex's embedded code-mode runtime so MCP tools
|
|
477
|
-
keep working when a vendor install does not include the optional standalone
|
|
478
|
-
`codex-code-mode-host` companion. Only the four specialist-control tools are
|
|
479
|
-
pre-approved for non-interactive delegation; other MCP tools retain Codex's
|
|
480
|
-
normal approval behavior. Its Codex-only instruction also resolves exact Impel
|
|
481
|
-
specialist tools through `tool_search` when the client defers MCP tools instead
|
|
482
|
-
of showing them directly. These settings apply only to `impel codex`.
|
|
483
|
-
|
|
484
|
-
The isolated Codex profile disables Codex shell snapshots and explicitly keeps
|
|
485
|
-
the default `KEY`/`SECRET`/`TOKEN` environment filter enabled. Before every
|
|
486
|
-
launch, `impel` removes derived `shell_snapshots`, drops inherited direct-auth
|
|
487
|
-
variables such as `CODEX_ACCESS_TOKEN`, and enforces owner-only permissions on
|
|
488
|
-
the managed profile and credential/config files. It also sweeps inactive tenant
|
|
489
|
-
and pre-tenancy Impel CLI profiles, so switching organizations cannot strand an
|
|
490
|
-
older snapshot. These safeguards apply only to Impel-owned `CODEX_HOME`
|
|
491
|
-
directories; native `~/.codex` remains untouched.
|
|
492
|
-
|
|
493
|
-
On Windows, `impel setup` installs only missing command-line tools through the
|
|
494
|
-
vendors' current native PowerShell installers. Claude Code's npm installation is
|
|
495
|
-
deprecated and its current package requires Node.js 22, while Impel itself still
|
|
496
|
-
supports Node.js 18 or newer. The native path keeps that valid Impel setup
|
|
497
|
-
working. Codex's installer is run non-interactively. Both installers download
|
|
498
|
-
platform-specific native releases and verify their published SHA-256 checksums.
|
|
499
|
-
Use `--skip-clis` to prepare the profiles without installing missing vendor
|
|
500
|
-
CLIs. Each tool is installed independently, so a failure from one vendor does
|
|
501
|
-
not prevent the other tool from being installed and configured.
|
|
502
|
-
|
|
503
|
-
The launchers and skill sync still resolve executables through `PATH`/`PATHEXT`,
|
|
504
|
-
including existing global npm `.cmd` and `.bat` shims. Windows environment
|
|
505
|
-
references such as `%NVM_SYMLINK%` are expanded during lookup, and the standard
|
|
506
|
-
npm-global, Claude native-installer, Codex standalone-installer, and Windows
|
|
507
|
-
PowerShell directories are checked even when the parent PowerShell PATH is
|
|
508
|
-
stale. Candidates must also pass a bounded `--version` probe, so a stale or
|
|
509
|
-
half-removed npm shim cannot hide a healthy native install later in the search
|
|
510
|
-
path. Existing batch-shim arguments are forwarded through an explicitly
|
|
511
|
-
escaped `cmd.exe` invocation without Node shell mode; NULs and line breaks,
|
|
512
|
-
which cannot be represented safely through a batch shim, are rejected before
|
|
513
|
-
anything is launched. Managed Codex auth and MCP subprocesses bypass batch
|
|
514
|
-
shims entirely by calling Node directly.
|
|
515
|
-
|
|
516
|
-
If a native installer fails, the wizard identifies the affected tool, preserves
|
|
517
|
-
the other tool's successful install, and prints that vendor's exact official
|
|
518
|
-
PowerShell command to retry. If an installer exits successfully but its command
|
|
519
|
-
cannot be verified, close and reopen PowerShell, retry the printed command, and
|
|
520
|
-
run `impel setup` again. Setup exits non-zero and says it is incomplete until
|
|
521
|
-
both launchers are ready—it does not print a success banner after a failed
|
|
522
|
-
installation.
|
|
523
|
-
|
|
524
|
-
Windows receives the complete CLI workflow: setup/auth, tenant selection,
|
|
525
|
-
isolated Claude and Codex launches, native profile switching, tasks, skills,
|
|
526
|
-
status, doctor, self-update, and both isolated desktop apps. `impel app install
|
|
527
|
-
claude` installs/updates Anthropic's signed per-user app through winget, writes
|
|
528
|
-
the selected tenant's 3P gateway configuration beneath Anthropic's reserved
|
|
529
|
-
`%LOCALAPPDATA%\Claude-3p\Impel\<tenant>` root, and leaves the executable and
|
|
530
|
-
normal Claude profile unchanged. `impel app install codex` installs/updates
|
|
531
|
-
OpenAI's `OpenAI.Codex` Store package, stages its unchanged signed app payload
|
|
532
|
-
inside Impel's shared app cache, and writes separate Codex and Chromium
|
|
533
|
-
profiles. `impel app open claude` and `impel app open codex` install a missing
|
|
534
|
-
official app and configure the selected tenant on first use, then launch the
|
|
535
|
-
isolated profile without changing either normal vendor profile.
|
|
536
|
-
|
|
537
|
-
For Claude, the Impel PAT is supplied only to the launched child process as an
|
|
538
|
-
authentication token and disappears when that process exits; it is never
|
|
539
|
-
written into the isolated Claude profile. The launcher also recognizes
|
|
540
|
-
Claude's standard native-installer location at `~/.local/bin/claude` when that
|
|
541
|
-
directory is not present in the parent process's `PATH`.
|
|
183
|
+
A newly minted PAT is shown once. It is not silently made active. Run
|
|
184
|
+
`impel setup` and provide the new PAT when rotating this machine. Revocation is
|
|
185
|
+
immediate and irreversible.
|
|
186
|
+
|
|
187
|
+
`impel auth --pat <pat>` remains available for existing automation that only
|
|
188
|
+
needs to store a credential. It does not provision tenants. Interactive users
|
|
189
|
+
should prefer setup because setup also reconciles the complete tenant list.
|
|
190
|
+
|
|
191
|
+
## Recovery
|
|
192
|
+
|
|
193
|
+
Setup and update include bounded installation recovery by default:
|
|
194
|
+
|
|
195
|
+
1. Known deterministic repairs run locally first.
|
|
196
|
+
2. If verification still fails, the CLI prints the exact sanitized diagnostic
|
|
197
|
+
envelope before assisted diagnosis.
|
|
198
|
+
3. The recovery model can select only strict, typed tools. It cannot run shell
|
|
199
|
+
text.
|
|
200
|
+
4. Read operations and repairs limited to Impel-owned state run automatically.
|
|
201
|
+
5. Vendor installers and user PATH edits require individual interactive
|
|
202
|
+
confirmation and are declined without a TTY.
|
|
203
|
+
6. A recovery is accepted as fixed only after fresh local health checks pass.
|
|
204
|
+
|
|
205
|
+
Tenant failures are recovered serially with a tool context and checkpoint
|
|
206
|
+
bound to the exact tenant. PATs, bearer tokens, home paths, emails, and terminal
|
|
207
|
+
control sequences are removed before any diagnostic request.
|
|
208
|
+
|
|
209
|
+
Disable all recovery for one run with `--no-recovery`, or globally for a
|
|
210
|
+
process with:
|
|
542
211
|
|
|
543
212
|
```sh
|
|
544
|
-
impel
|
|
545
|
-
impel claude -p "summarize this repository" --output-format json
|
|
546
|
-
impel codex
|
|
547
|
-
impel codex exec --json "review the current diff"
|
|
213
|
+
IMPEL_DISABLE_INSTALL_RECOVERY=1 impel update
|
|
548
214
|
```
|
|
549
215
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
default when personal and Impel sessions should coexist.
|
|
553
|
-
|
|
554
|
-
Every Impel-managed Claude configuration uses the same strict sandbox defaults
|
|
555
|
-
with unrestricted outbound network access:
|
|
556
|
-
the isolated `impel claude` profile, each tenant's Claude Desktop Code profile,
|
|
557
|
-
the native profile while `impel use gateway claude` is active, and branded
|
|
558
|
-
gateway-only CLI profiles. App config version 15 also pins managed Claude
|
|
559
|
-
Desktop profiles to third-party deployment mode, enables the 3P Chat tab so
|
|
560
|
-
Code's "Back to Claude" route has a valid destination, and removes the unusable
|
|
561
|
-
Claude.ai sign-in path. Existing tenant profiles refresh onto these policies
|
|
562
|
-
after the CLI update.
|
|
563
|
-
|
|
564
|
-
### `impel use gateway [claude|codex|all]` (alias `impel on`)
|
|
565
|
-
|
|
566
|
-
Turns **on** gateway mode for the given tool (default `all`). Requires `impel auth`
|
|
567
|
-
first.
|
|
568
|
-
|
|
569
|
-
**Claude Code** — merges into `~/.claude/settings.json` (creating it if needed,
|
|
570
|
-
leaving existing permission rules, hooks, other env vars, and custom sandbox
|
|
571
|
-
filesystem/network rules intact). Gateway mode enables Claude's strict auto-allow sandbox by
|
|
572
|
-
default: Bash runs inside the OS sandbox without routine prompts, the
|
|
573
|
-
`dangerouslyDisableSandbox` escape hatch is disabled, and supported platforms
|
|
574
|
-
fail closed if isolation cannot initialize. Native Windows keeps startup
|
|
575
|
-
available because Claude's sandbox is supported only on macOS, Linux, and WSL2.
|
|
576
|
-
A global `WebFetch(domain:*)` allow rule opens every outbound destination for Bash commands
|
|
577
|
-
while retaining filesystem isolation. Explicit deny rules remain authoritative.
|
|
578
|
-
On macOS, `enableWeakerNetworkIsolation` lets Go-based network tools reach the
|
|
579
|
-
system TLS trust service while remaining sandboxed.
|
|
580
|
-
|
|
581
|
-
```json
|
|
582
|
-
{
|
|
583
|
-
"apiKeyHelper": "impel token",
|
|
584
|
-
"env": {
|
|
585
|
-
"ANTHROPIC_BASE_URL": "https://gateway.useimpel.com/anthropic"
|
|
586
|
-
},
|
|
587
|
-
"permissions": {
|
|
588
|
-
"allow": ["WebFetch(domain:*)"]
|
|
589
|
-
},
|
|
590
|
-
"sandbox": {
|
|
591
|
-
"enabled": true,
|
|
592
|
-
"failIfUnavailable": true,
|
|
593
|
-
"autoAllowBashIfSandboxed": true,
|
|
594
|
-
"allowUnsandboxedCommands": false,
|
|
595
|
-
"excludedCommands": [],
|
|
596
|
-
"enableWeakerNetworkIsolation": true
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
```
|
|
216
|
+
See [docs/assisted-install-recovery.md](docs/assisted-install-recovery.md) for
|
|
217
|
+
the security model and tool registry.
|
|
600
218
|
|
|
601
|
-
|
|
602
|
-
`model_provider` at a custom `[model_providers.<id>]` table, plus a
|
|
603
|
-
**command-backed** bearer token via a `[model_providers.<id>.auth]` sub-table
|
|
604
|
-
(`command` + `args`, re-invoked on a timer and on auth retries — the same shape
|
|
605
|
-
as Claude Code's `apiKeyHelper`), so we reuse `impel token` there too instead of
|
|
606
|
-
writing the PAT into `config.toml` or `~/.codex/auth.json`. The block written
|
|
607
|
-
(fenced by markers, so everything else in your `config.toml` — other
|
|
608
|
-
`model_providers`, `mcp_servers`, and unrelated sandbox policy — is left alone).
|
|
609
|
-
Codex defaults to the `workspace-write` filesystem sandbox with unrestricted
|
|
610
|
-
direct outbound access; its optional network proxy stays disabled:
|
|
611
|
-
|
|
612
|
-
```toml
|
|
613
|
-
model_provider = "impel"
|
|
614
|
-
|
|
615
|
-
# >>> impel-cli managed block (model_providers.impel) >>>
|
|
616
|
-
# Generated by `impel use gateway codex`. Safe to re-run; do not hand-edit
|
|
617
|
-
# the lines between the markers above/below, they'll be overwritten.
|
|
618
|
-
sandbox_mode = "workspace-write"
|
|
619
|
-
sandbox_workspace_write.network_access = true
|
|
620
|
-
|
|
621
|
-
[model_providers.impel]
|
|
622
|
-
name = "Impel Gateway"
|
|
623
|
-
base_url = "https://gateway.useimpel.com/chatgpt_passthrough/backend-api/codex"
|
|
624
|
-
wire_api = "responses"
|
|
625
|
-
|
|
626
|
-
[model_providers.impel.auth]
|
|
627
|
-
command = "impel"
|
|
628
|
-
args = ["token"]
|
|
629
|
-
timeout_ms = 5000
|
|
630
|
-
refresh_interval_ms = 300000
|
|
631
|
-
# <<< impel-cli managed block <<<
|
|
632
|
-
```
|
|
219
|
+
## Personal profiles
|
|
633
220
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
prior Codex `model_provider`, sandbox mode, and workspace network values) into
|
|
637
|
-
`~/.config/impel/config.json`, so `impel use account`
|
|
638
|
-
can restore it exactly. If `config.toml` already has a `[model_providers.impel]` table that
|
|
639
|
-
wasn't written by this tool, `impel` refuses to touch the file and tells you to
|
|
640
|
-
resolve it manually rather than risk emitting invalid/duplicate TOML.
|
|
641
|
-
|
|
642
|
-
### `impel use account [claude|codex|all]` (alias `impel off`)
|
|
643
|
-
|
|
644
|
-
Turns gateway mode **off** and restores your normal account-based setup. It
|
|
645
|
-
removes **only** the Impel-added bits, never your own config:
|
|
646
|
-
|
|
647
|
-
- **Claude Code** — removes `apiKeyHelper` only if it's `"impel token"`, and
|
|
648
|
-
`env.ANTHROPIC_BASE_URL` only if it equals `<gateway>/anthropic`. Then restores
|
|
649
|
-
whatever those keys held before gateway mode (from the backup). If there was
|
|
650
|
-
nothing before, they're deleted (and an emptied `env` is dropped). It also
|
|
651
|
-
removes only the Impel-added global `WebFetch(domain:*)` allow rule.
|
|
652
|
-
- **Codex** — removes the marker-fenced `[model_providers.impel]` block, and
|
|
653
|
-
resets `model_provider` **only if it currently reads `"impel"`** — back to its
|
|
654
|
-
backed-up prior value, or, if there was none, removes the line entirely so
|
|
655
|
-
Codex falls back to its built-in default. The prior
|
|
656
|
-
`sandbox_mode` and `sandbox_workspace_write.network_access` values are
|
|
657
|
-
restored. All other tables are untouched.
|
|
658
|
-
|
|
659
|
-
`impel use account` doesn't require the PAT and is safe to run repeatedly (if a
|
|
660
|
-
tool is already in account mode it just says so and changes nothing).
|
|
661
|
-
|
|
662
|
-
### `impel skills sync [claude|codex|all]`
|
|
663
|
-
|
|
664
|
-
Syncs Impel's **Bifrost shared skills** into your managed Claude Code and Codex
|
|
665
|
-
clients. The gateway publishes a public, per-client plugin marketplace whose
|
|
666
|
-
bundled plugin — `bifrost-all-skills` — contains every served skill:
|
|
667
|
-
|
|
668
|
-
- Claude Code registers its manifest URL:
|
|
669
|
-
`<gateway>/api/skills/serve/claude-code/.claude-plugin/marketplace.json`
|
|
670
|
-
- Codex registers the Git source `<gateway>/api/skills/serve/codex`; its
|
|
671
|
-
marketplace manifest lives at `<source>/.agents/plugins/marketplace.json`.
|
|
672
|
-
|
|
673
|
-
The sync is idempotent: it registers the marketplace, ensures `bifrost-all-skills`
|
|
674
|
-
is installed, then runs the client's refresh commands so an already-installed
|
|
675
|
-
plugin picks up a newer bundle. It reads each marketplace's registered `name`
|
|
676
|
-
from the served `marketplace.json` to pin installs and refreshes. Codex receives
|
|
677
|
-
the Git source rather than the nested manifest URL because its CLI clones the
|
|
678
|
-
source before discovering `.agents/plugins/marketplace.json`.
|
|
679
|
-
|
|
680
|
-
You rarely need to run it by hand — it runs **automatically** at the end of every
|
|
681
|
-
install/update path:
|
|
682
|
-
|
|
683
|
-
- `impel use gateway ...` / `impel setup ...` (native `~/.claude` / `~/.codex`)
|
|
684
|
-
- `impel app install` / `impel app update` (each isolated desktop app profile)
|
|
685
|
-
|
|
686
|
-
`impel skills sync` also covers the isolated `impel claude` / `impel codex` CLI
|
|
687
|
-
profiles and installed desktop apps when they exist. Skill syncing is
|
|
688
|
-
best-effort: if a client CLI, its `plugin` subcommand, or the gateway is
|
|
689
|
-
unavailable, it logs a warning and moves on — it never fails the parent command.
|
|
690
|
-
Set `IMPEL_SKIP_SKILL_SYNC=1` to disable it entirely (offline/CI).
|
|
691
|
-
|
|
692
|
-
### `impel agents sync [claude|codex|all]`
|
|
693
|
-
|
|
694
|
-
Fetches the selected organization's explicit native-agent catalog through the
|
|
695
|
-
authenticated Impel MCP endpoint, then generates native custom-agent files for
|
|
696
|
-
every managed profile. This catalog is separate from automatic specialists: it
|
|
697
|
-
may include truthfully declared write-capable agents, but those agents require
|
|
698
|
-
explicit user selection before the server will start a run.
|
|
699
|
-
|
|
700
|
-
- Claude Code / Claude Desktop: `<CLAUDE_CONFIG_DIR>/agents/<agent-name>.md`
|
|
701
|
-
- Codex / ChatGPT Codex mode: `<CODEX_HOME>/agents/impel-<tenant>-<agent-id>.toml`
|
|
702
|
-
|
|
703
|
-
Each generated agent is bound to one exact `agentId` and
|
|
704
|
-
`scopeParam`. It verifies that the exact agent is still available, starts one
|
|
705
|
-
idempotent run, polls the durable run to a terminal state, and returns
|
|
706
|
-
`result.finalText` without repeating the work. The files include a tenant-bound
|
|
707
|
-
MCP subprocess definition so they also work in isolated desktop profiles. They
|
|
708
|
-
never contain the PAT; the subprocess reads it from Impel's owner-only config
|
|
709
|
-
when invoked.
|
|
710
|
-
|
|
711
|
-
Visible agent names come from the registry title. Codex keeps that title as the
|
|
712
|
-
custom-agent name; Claude uses the lowercase, hyphenated form required by its
|
|
713
|
-
native agent schema and Desktop's `@` picker requires the Markdown filename to
|
|
714
|
-
match that name. Codex filenames remain stable tenant-and-agent identifiers.
|
|
715
|
-
Duplicate or built-in-reserved titles receive a deterministic disambiguator.
|
|
716
|
-
|
|
717
|
-
The sync writes atomically and records a manifest beside the generated files.
|
|
718
|
-
It removes only stale filenames from that manifest, so user-authored agents are
|
|
719
|
-
never deleted. Automatic refreshes are best-effort and retain the last good
|
|
720
|
-
catalog when the gateway is unavailable; the explicit command exits non-zero
|
|
721
|
-
on failure. Set `IMPEL_SKIP_AGENT_SYNC=1` to keep the current generated catalog
|
|
722
|
-
without contacting the gateway.
|
|
723
|
-
|
|
724
|
-
Start a new task after syncing. Claude Code detects updates to an existing
|
|
725
|
-
`agents/` directory within a few seconds, but if the sync created that directory
|
|
726
|
-
for the first time while Claude was already running, restart Claude once.
|
|
727
|
-
In Claude Desktop, selecting an agent on the first turn binds that Code session
|
|
728
|
-
to the agent. Follow-up `@` menus continue to offer that same bound agent and
|
|
729
|
-
insert a normal mention chip. Other agents remain available from a new task,
|
|
730
|
-
because the running Claude session cannot safely switch agents mid-session.
|
|
731
|
-
|
|
732
|
-
Invocation uses the clients' native agent behavior:
|
|
221
|
+
Impel sessions no longer route native personal `~/.claude` or `~/.codex`
|
|
222
|
+
profiles through Impel. Setup and update use tenant-isolated profiles only.
|
|
733
223
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
224
|
+
For users of an older release, the first setup or update performs a one-time
|
|
225
|
+
cleanup migration. It removes only exact Impel-owned values and marker blocks,
|
|
226
|
+
restores stored prior values when available, and preserves user-edited or
|
|
227
|
+
unrelated settings. The old account-restore aliases remain as hidden cleanup
|
|
228
|
+
compatibility for one release, but no command can enable native routing.
|
|
737
229
|
|
|
738
|
-
|
|
739
|
-
claude --agent research-agent -p "investigate the dependency change"
|
|
230
|
+
## Platform behavior
|
|
740
231
|
|
|
741
|
-
|
|
742
|
-
Explicitly use the configured Research Agent for this request and wait for it.
|
|
743
|
-
```
|
|
232
|
+
### macOS
|
|
744
233
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
agent threads.
|
|
234
|
+
- Tenant apps live in `~/Applications`.
|
|
235
|
+
- LaunchServices registration is non-launching and idempotent.
|
|
236
|
+
- Existing bundle fingerprints and stable signing identity prevent unnecessary
|
|
237
|
+
rebuilds and permission churn.
|
|
238
|
+
- Shared vendor downloads and bundle swaps are serialized.
|
|
751
239
|
|
|
752
|
-
###
|
|
240
|
+
### Windows
|
|
753
241
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
242
|
+
- Missing official Claude Code and Codex CLIs can be installed during setup.
|
|
243
|
+
- Signed vendor desktop executables remain unchanged.
|
|
244
|
+
- Tenant profiles and Start entries are isolated per tenant.
|
|
245
|
+
- Shared package-manager/vendor preparation runs once per product.
|
|
246
|
+
- System-level installer and PATH changes require confirmation.
|
|
757
247
|
|
|
758
|
-
|
|
759
|
-
- whether a PAT is stored (masked, e.g. `impel_pat_ab12...wxyz`),
|
|
760
|
-
- the live Workspace member / Gateway member entitlement when available,
|
|
761
|
-
- a best-effort reachability check: a `POST` to `<gateway>/anthropic/v1/messages`
|
|
762
|
-
with a 5s timeout. Any HTTP response (including a 4xx) counts as "reachable" —
|
|
763
|
-
this checks the network path and gateway routing, not the request itself. A
|
|
764
|
-
`401`/`403` is called out separately since it usually just means the stored PAT
|
|
765
|
-
was rejected, not that the gateway is down.
|
|
248
|
+
### Linux
|
|
766
249
|
|
|
767
|
-
|
|
768
|
-
|
|
250
|
+
- Every tenant receives isolated CLI profiles.
|
|
251
|
+
- Managed desktop apps are unavailable.
|
|
252
|
+
- Missing vendor CLIs are reported rather than installed through an unverified
|
|
253
|
+
mechanism.
|
|
769
254
|
|
|
770
|
-
##
|
|
255
|
+
## Local state
|
|
771
256
|
|
|
772
|
-
|
|
257
|
+
Main paths:
|
|
773
258
|
|
|
774
|
-
```
|
|
775
|
-
impel
|
|
776
|
-
impel
|
|
777
|
-
impel
|
|
778
|
-
impel app status codex
|
|
259
|
+
```text
|
|
260
|
+
~/.config/impel/config.json
|
|
261
|
+
~/.config/impel/cli/tenants/<tenant>/
|
|
262
|
+
~/.config/impel/apps/tenants/<tenant>/
|
|
779
263
|
```
|
|
780
264
|
|
|
781
|
-
The
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
override. Anthropic's MSIX manifest explicitly reserves `%LOCALAPPDATA%\Claude-3p`
|
|
785
|
-
for unvirtualized third-party profiles, so each Impel tenant lives below that
|
|
786
|
-
root. The app's normal first-party profile is not read or changed. `impel setup`
|
|
787
|
-
installs this profile by default; use `--skip-apps` to omit it.
|
|
788
|
-
|
|
789
|
-
For ChatGPT/Codex Desktop, Windows installs the official Microsoft Store product
|
|
790
|
-
`9PLM9XGG6VKS` (`OpenAI.Codex`). Windows blocks other programs from directly
|
|
791
|
-
executing Electron inside `C:\Program Files\WindowsApps`, so Impel copies the
|
|
792
|
-
vendor's complete `app` payload, unchanged, into a shared managed cache. It
|
|
793
|
-
then launches that copy with a separate `CODEX_HOME` and
|
|
794
|
-
`CODEX_ELECTRON_USER_DATA_PATH` (plus Electron `--user-data-dir` as a legacy
|
|
795
|
-
fallback). The normal Store app, `%USERPROFILE%\.codex`, and the normal ChatGPT
|
|
796
|
-
browser profile are not read or changed. `chatgpt` and `codex` are equivalent
|
|
797
|
-
app-target names.
|
|
798
|
-
|
|
799
|
-
### macOS Claude and ChatGPT
|
|
800
|
-
|
|
801
|
-
The first `impel app open --tenant <org>` (or an explicit `impel app install`)
|
|
802
|
-
creates tenant-specific apps such as
|
|
803
|
-
`Impel Claude (acme).app` and `Impel ChatGPT (acme).app` in `~/Applications`.
|
|
804
|
-
Their visible bundle names use the organization display name, for example
|
|
805
|
-
`Impel Claude (Acme)` and `Impel ChatGPT (Acme)`. Each tenant/product pair has
|
|
806
|
-
a stable, unique bundle identifier and gateway configuration:
|
|
807
|
-
|
|
808
|
-
- Impel Claude is an APFS-cloned vendored copy of the official app with its own
|
|
809
|
-
bundle and helper identities. Its LaunchServices environment sets both the
|
|
810
|
-
vendor-supported `CLAUDE_USER_DATA_DIR` and Claude Code's
|
|
811
|
-
`CLAUDE_CONFIG_DIR` to the tenant-private profile. This isolates browser
|
|
812
|
-
state, sessions, plugins, MCP servers, skills, and native `@` agents from
|
|
813
|
-
`~/.claude`, while the app writes the 3P gateway
|
|
814
|
-
`configLibrary` below `~/.config/impel/apps/tenants/<org>/claude`. A new
|
|
815
|
-
isolated profile defaults to the Code app while preserving any app selection
|
|
816
|
-
the user makes afterward. A narrowly version-checked compatibility patch
|
|
817
|
-
connects Claude's native plan-usage meter to the authenticated aggregate
|
|
818
|
-
Claude subscription pool exposed by the Impel gateway.
|
|
819
|
-
- Impel ChatGPT wraps an APFS-cloned official app while preserving the nested
|
|
820
|
-
OpenAI-signed bundle and executable. A wrapper-owned startup preload pins
|
|
821
|
-
Electron's application name before the native menu is created, so macOS
|
|
822
|
-
shows `Impel ChatGPT (<org>)` without changing OpenAI's signed code. Its outer
|
|
823
|
-
resource root contains the narrowly patched renderer ASAR used at runtime.
|
|
824
|
-
The wrapper sets `CODEX_HOME`,
|
|
825
|
-
passes a separate Chromium `--user-data-dir`, and writes its provider config
|
|
826
|
-
and model catalog below `~/.config/impel/apps/tenants/<org>/chatgpt`. It also supplies a
|
|
827
|
-
process-scoped, Codex-compatible wrapper around the Impel PAT so native
|
|
828
|
-
`/status` requests can read the organization's aggregated subscription pool
|
|
829
|
-
from the gateway. Its generated Codex config uses the same snapshot and
|
|
830
|
-
subprocess-environment hardening as `impel codex`; install, update, and every
|
|
831
|
-
direct app launch also remove older snapshots for the selected profile, while
|
|
832
|
-
app install/update/open sweeps inactive tenant and legacy Impel app profiles.
|
|
833
|
-
- Neither app changes `~/.claude`, `~/.claude.json`, `~/.codex`, or the
|
|
834
|
-
normal vendor app's browser/profile data.
|
|
835
|
-
|
|
836
|
-
Open several tenants without changing the current selection. A missing variant
|
|
837
|
-
is installed and configured automatically before it opens:
|
|
265
|
+
The config directory is owner-only and the config file is written with mode
|
|
266
|
+
`0600` where supported. Generated client profiles use tenant-bound helper
|
|
267
|
+
invocations; PAT material is not embedded into shell entries.
|
|
838
268
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
269
|
+
Losing membership does not delete local tenant data. A future cleanup feature
|
|
270
|
+
must remain explicit and destructive-state aware.
|
|
271
|
+
|
|
272
|
+
## Public command surface
|
|
273
|
+
|
|
274
|
+
```text
|
|
275
|
+
impel setup
|
|
276
|
+
impel update
|
|
277
|
+
impel claude
|
|
278
|
+
impel codex
|
|
279
|
+
impel tenant list|current|use
|
|
280
|
+
impel tasks ...
|
|
281
|
+
impel pat ...
|
|
282
|
+
impel status
|
|
283
|
+
impel doctor
|
|
842
284
|
```
|
|
843
285
|
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
that have never been installed. The older global `Impel Claude.app` /
|
|
848
|
-
`Impel ChatGPT.app` launcher is removed after the first successful
|
|
849
|
-
tenant-specific rebuild.
|
|
850
|
-
|
|
851
|
-
`impel app update` compares the installed bundle's build fingerprint, signing
|
|
852
|
-
mode, pinned vendor version, identity, profile paths, and ASAR compatibility
|
|
853
|
-
hash before touching it. The build fingerprint tracks the bundle-BUILDING logic
|
|
854
|
-
(asar patches, plist rewrites, signing), not the CLI version, so a CLI release
|
|
855
|
-
that doesn't change bundle bytes leaves installed bundles — and their macOS
|
|
856
|
-
permission grants — alone. A current bundle is not closed, cloned, patched, or
|
|
857
|
-
codesigned; its config and model catalog are still refreshed. If an interrupted
|
|
858
|
-
update left a machine in a bad state, `impel app update --force` removes the
|
|
859
|
-
selected launcher and performs a clean rebuild while sweeping abandoned
|
|
860
|
-
`.tmp-*` and `.previous-*` staging directories.
|
|
861
|
-
|
|
862
|
-
Skills plugin subprocesses run asynchronously, so the TTY progress indicator
|
|
863
|
-
continues animating while Claude or Codex refreshes a marketplace. Skill status
|
|
864
|
-
lines temporarily clear and redraw the spinner instead of overwriting it.
|
|
865
|
-
|
|
866
|
-
The official Claude and ChatGPT apps remain separate installations and keep
|
|
867
|
-
their normal accounts, updater, profiles, and bundle identities. Each CLI
|
|
868
|
-
release pins exact, tested vendor builds (v0.10.0 pins Claude `1.20186.9` and
|
|
869
|
-
ChatGPT `26.707.72221`) and their archive SHA-256 digests. The installer reuses
|
|
870
|
-
an existing official app only when its version exactly matches; otherwise it
|
|
871
|
-
downloads the pinned signed archive into Impel's managed vendor cache under
|
|
872
|
-
`~/.config/impel/vendor`, verifies its digest, bundle version, layout, and code
|
|
873
|
-
signature, and only then rebuilds the isolated app. It never clones a moving
|
|
874
|
-
Homebrew or vendor “latest” release, and it never downgrades or replaces the
|
|
875
|
-
user's normal vendor app. A future app version requires a new tested CLI release
|
|
876
|
-
and pin update. Config refreshes do not download or replace apps. If the model
|
|
877
|
-
endpoint is temporarily unavailable, the installer retains functionality using
|
|
878
|
-
the CLI's bundled catalog.
|
|
879
|
-
|
|
880
|
-
For ChatGPT/Codex, the gateway controls which models and capabilities are
|
|
881
|
-
enabled while the installer merges those entries with the vendor app's native
|
|
882
|
-
catalog. The Impel copy relaxes the vendor renderer's ChatGPT-account-only Fast
|
|
883
|
-
gate because gateway auth supplies the entitlement instead. The outer wrapper
|
|
884
|
-
is then signed locally (see below) without replacing the nested OpenAI signing
|
|
885
|
-
identity. This preserves model-specific instructions and exposes
|
|
886
|
-
the same reasoning-effort and service-tier controls as the normal app, including
|
|
887
|
-
Ultra where supported and Fast only on models that advertise the `priority`
|
|
888
|
-
tier. Inference uses an explicit non-WebSocket Impel model provider so Codex
|
|
889
|
-
cannot fall back to the vendor's hard-coded `chatgpt.com` transport with an
|
|
890
|
-
Impel PAT. Config refreshes replace only the Impel-managed gateway block; plugins,
|
|
891
|
-
desktop preferences, projects, and other settings written by the isolated app
|
|
892
|
-
are kept.
|
|
893
|
-
|
|
894
|
-
Impel Claude and the outer Impel ChatGPT wrapper are signed locally after their
|
|
895
|
-
bundle identities and launch wrappers are installed. The nested ChatGPT bundle
|
|
896
|
-
retains OpenAI's signature.
|
|
897
|
-
|
|
898
|
-
By default the CLI signs each rebuild with a **stable per-machine identity** — a
|
|
899
|
-
self-signed certificate created once in a dedicated keychain under
|
|
900
|
-
`~/.config/impel/codesign` (no Apple Developer account is involved). The
|
|
901
|
-
certificate is trusted locally for the code-signing policy only; it is not a
|
|
902
|
-
TLS or document-signing authority. macOS ties
|
|
903
|
-
every privacy (TCC) grant — microphone, screen recording, folder access,
|
|
904
|
-
Automation, accessibility — to the app's code-signing designated requirement. A
|
|
905
|
-
stable identity keeps that requirement constant across rebuilds, so the grants
|
|
906
|
-
you approve survive `impel app update` the way they do for a normal app instead
|
|
907
|
-
of re-prompting after every rebuild. The one-time switch from the old ad-hoc
|
|
908
|
-
signature to the stable identity triggers a single final round of prompts. If
|
|
909
|
-
the local signing toolchain is unavailable the CLI logs a notice and falls back
|
|
910
|
-
to ad-hoc signing (the previous behavior). Two environment overrides are
|
|
911
|
-
available: `IMPEL_CODESIGN_ADHOC=1` forces ad-hoc signing, and
|
|
912
|
-
`IMPEL_CODESIGN_IDENTITY=<name>` signs with a specific existing identity (e.g. a
|
|
913
|
-
real `Developer ID Application: …`).
|
|
914
|
-
|
|
915
|
-
Older Claude profiles already encrypt browser data with the macOS login
|
|
916
|
-
Keychain item named `Claude Safe Storage`. Impel keeps that namespace immutable
|
|
917
|
-
so an update never makes existing cookies or storage unreadable. Because each
|
|
918
|
-
tenant app has a distinct bundle identity, macOS asks once before that app may
|
|
919
|
-
use the legacy item: enter the Mac login password and choose **Always Allow**.
|
|
920
|
-
Choosing **Allow** grants access for only that launch and therefore prompts
|
|
921
|
-
again next time. The stable Impel signature keeps a successful Always Allow
|
|
922
|
-
grant valid across later app updates. Clean profiles instead start with a
|
|
923
|
-
persisted tenant-specific Safe Storage namespace, so they never request access
|
|
924
|
-
to the shared vendor item. Impel does not weaken or silently rewrite Keychain
|
|
925
|
-
access lists.
|
|
926
|
-
|
|
927
|
-
The Claude 3P config necessarily contains the PAT because that app accepts a
|
|
928
|
-
gateway API key rather than a token-helper command. It is stored in the same
|
|
929
|
-
owner-only Impel config tree as the primary credential. ChatGPT/Codex uses a
|
|
930
|
-
command-backed helper and does not copy the PAT into TOML. The installable app
|
|
931
|
-
also reads that helper into its own process environment for Codex account-status
|
|
932
|
-
compatibility; the value disappears when the app exits.
|
|
933
|
-
|
|
934
|
-
## Switching back and forth
|
|
935
|
-
|
|
936
|
-
The whole point: flipping between the gateway and your own account is one
|
|
937
|
-
command, per tool, and always reversible.
|
|
286
|
+
Profile helpers, content synchronization, desktop maintenance, and transport
|
|
287
|
+
commands are internal implementation details and intentionally absent from
|
|
288
|
+
normal help.
|
|
938
289
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
290
|
+
## Library export
|
|
291
|
+
|
|
292
|
+
The package continues to expose `impel-cli/gateway` for approved branded
|
|
293
|
+
vendor integrations. Its CLI allowlist is deliberately narrow and does not
|
|
294
|
+
expose control-plane administration commands.
|
|
942
295
|
|
|
943
|
-
|
|
944
|
-
impel off claude # just Claude Code -> account
|
|
296
|
+
## Development
|
|
945
297
|
|
|
946
|
-
|
|
298
|
+
The project is dependency-free at runtime and uses Node's built-in test runner:
|
|
299
|
+
|
|
300
|
+
```sh
|
|
301
|
+
npm test
|
|
302
|
+
npm pack --dry-run
|
|
947
303
|
```
|
|
948
304
|
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
clobbers the backup with Impel's own values). `impel off` removes only keys that
|
|
956
|
-
still point at Impel and restores those backups — so a full `on` → `off`
|
|
957
|
-
round-trip leaves `settings.json` and `config.toml` byte-for-byte back to where
|
|
958
|
-
they started, with all your unrelated keys and tables intact.
|
|
959
|
-
|
|
960
|
-
If you'd rather revert by hand: delete `apiKeyHelper`, the Impel
|
|
961
|
-
`ANTHROPIC_BASE_URL`, and the Impel-managed sandbox keys from
|
|
962
|
-
`~/.claude/settings.json`, plus the Impel-added `WebFetch(domain:*)` allow rule; delete the block between the
|
|
963
|
-
`# >>> impel-cli managed block ... >>>` / `# <<< impel-cli managed block <<<`
|
|
964
|
-
markers in `~/.codex/config.toml`, reset `model_provider`, and restore or remove
|
|
965
|
-
`sandbox_mode` and `sandbox_workspace_write.network_access`; and
|
|
966
|
-
`rm -rf ~/.config/impel` to forget the PAT + gateway entirely.
|
|
967
|
-
|
|
968
|
-
## Codex compatibility route
|
|
969
|
-
|
|
970
|
-
The installable app uses an explicit Codex model provider at
|
|
971
|
-
`<gateway>/chatgpt_passthrough/backend-api/codex`, producing the request path
|
|
972
|
-
`/chatgpt_passthrough/backend-api/codex/responses`. The provider disables
|
|
973
|
-
WebSockets because the vendor's built-in ChatGPT provider derives that URL from
|
|
974
|
-
`chatgpt.com` rather than the configured account-service base. The gateway
|
|
975
|
-
preserves the request body while replacing the Impel PAT with the selected
|
|
976
|
-
ChatGPT subscription credential.
|
|
977
|
-
|
|
978
|
-
The installable Impel ChatGPT app also points Codex's account client at
|
|
979
|
-
`<gateway>/chatgpt_passthrough/backend-api`. The gateway exposes a virtual Impel
|
|
980
|
-
pool identity and `GET .../wham/usage`, aggregating each primary and secondary
|
|
981
|
-
subscription window across all active Codex seats with equal-seat weighting.
|
|
982
|
-
This lets the native `/status` surface show pool capacity without exposing any
|
|
983
|
-
provider account identity or OAuth credential.
|
|
984
|
-
|
|
985
|
-
Before every launch, the wrapper refreshes Codex's supported personal-access-token
|
|
986
|
-
login record from the tenant helper. That keeps the desktop app in native
|
|
987
|
-
ChatGPT-account mode, allowing `/status` to request the aggregate five-hour and
|
|
988
|
-
weekly windows instead of treating Impel as an API-key-only provider.
|
|
989
|
-
|
|
990
|
-
The gateway also exposes `POST /v1/responses`, but that is the conventional
|
|
991
|
-
OpenAI Responses front door for SDK/Eve traffic and may normalize the body
|
|
992
|
-
(including enforcing `store: false`). The CLI deliberately does not use it.
|
|
993
|
-
|
|
994
|
-
## Design notes
|
|
995
|
-
|
|
996
|
-
- **Zero dependencies.** Arg parsing, JSON/TOML merging, masked prompts, and the
|
|
997
|
-
reachability check are all hand-rolled against Node stdlib (`fs`, `os`,
|
|
998
|
-
`path`, `readline`, global `fetch`). No `chalk`, no `commander`, no `inquirer`.
|
|
999
|
-
- **The PAT lives in exactly one place:** `~/.config/impel/config.json` (mode
|
|
1000
|
-
`0600`). Both Claude Code and Codex fetch it on demand by shelling out to
|
|
1001
|
-
`impel token` rather than copying it into their own config files — one token,
|
|
1002
|
-
one rotation path, no stale copies.
|
|
1003
|
-
- **The `config.toml` merge is intentionally narrow**, not a general TOML
|
|
1004
|
-
parser: it touches the top-level `model_provider`, sandbox mode, the
|
|
1005
|
-
workspace-write network toggle, and its own fenced `[model_providers.impel*]` block, leaving unrelated
|
|
1006
|
-
tables (other providers, MCP servers, sandbox policy, etc.) untouched.
|
|
1007
|
-
|
|
1008
|
-
## Sources consulted for the Codex config
|
|
1009
|
-
|
|
1010
|
-
- https://developers.openai.com/codex/config-reference
|
|
1011
|
-
- https://developers.openai.com/codex/config-advanced
|
|
1012
|
-
- https://developers.openai.com/codex/auth
|
|
1013
|
-
- https://developers.openai.com/codex/ide
|
|
1014
|
-
|
|
1015
|
-
## Sources consulted for the Claude sandbox config
|
|
1016
|
-
|
|
1017
|
-
- https://code.claude.com/docs/en/settings#sandbox-settings
|
|
1018
|
-
- https://code.claude.com/docs/en/sandboxing#configure-the-sandbox-for-your-organization
|
|
1019
|
-
- https://github.com/anthropics/claude-code/blob/v2.1.214/examples/settings/settings-bash-sandbox.json
|
|
1020
|
-
|
|
1021
|
-
## Sources consulted for concurrent tenant apps
|
|
1022
|
-
|
|
1023
|
-
- Electron v43.1.0 release: https://github.com/electron/electron/releases/tag/v43.1.0
|
|
1024
|
-
- Electron applies `--user-data-dir` before app JavaScript:
|
|
1025
|
-
https://github.com/electron/electron/blob/b5c102b3f0f7e9c5be064ba337a3547a83cf7d09/shell/app/electron_main_delegate.cc#L247-L256
|
|
1026
|
-
- Electron scopes its single-instance lock to the resolved user-data directory:
|
|
1027
|
-
https://github.com/electron/electron/blob/b5c102b3f0f7e9c5be064ba337a3547a83cf7d09/shell/browser/api/electron_api_app.cc#L1049-L1073
|
|
1028
|
-
- Electron macOS bundle rebranding requirements:
|
|
1029
|
-
https://github.com/electron/electron/blob/b5c102b3f0f7e9c5be064ba337a3547a83cf7d09/docs/tutorial/application-distribution.md#L79-L96
|
|
1030
|
-
- Apple `CFBundleIdentifier` reference:
|
|
1031
|
-
https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleidentifier
|
|
305
|
+
Tests use temporary homes, injected process runners, fake catalogs, and local
|
|
306
|
+
HTTP fixtures. They must not require a live PAT, launch or close a real app,
|
|
307
|
+
run a real package manager, or modify native personal profiles.
|
|
308
|
+
|
|
309
|
+
CI runs on Ubuntu, macOS, and Windows with supported Node versions. See
|
|
310
|
+
[RELEASING.md](RELEASING.md) for the npm release process.
|