@youdie006/swapdex 0.160.0 → 0.162.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 +83 -66
- package/man/swapdex.1 +5 -2
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -38,21 +38,21 @@ account -- a work seat and a personal subscription, a client's org and your own
|
|
|
38
38
|
-- switching means logging out and back in every time.
|
|
39
39
|
|
|
40
40
|
swapdex gives each account its **own permanent space** -- its own
|
|
41
|
-
`CLAUDE_CONFIG_DIR` slot -- and
|
|
41
|
+
`CLAUDE_CONFIG_DIR` or `CODEX_HOME` slot -- and switches the default pointer.
|
|
42
42
|
`swapdex use work` points your default account there and a plain `claude`
|
|
43
43
|
follows it; `swapdex run work` launches straight into that account (each terminal
|
|
44
|
-
can be a different one).
|
|
45
|
-
|
|
44
|
+
can be a different one). Existing native sessions keep their own slot when the
|
|
45
|
+
default changes.
|
|
46
46
|
`swapdex onboard` sets this up in a few prompts.
|
|
47
47
|
|
|
48
|
-
It
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
It manages accounts you already own, with separate launch defaults, proxy
|
|
49
|
+
selection and configurable failover. See [How it works](#how-it-works) for the
|
|
50
|
+
difference between permanent slots and legacy saved snapshots.
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
Each account signs in within its own slot. The optional local proxy uses the
|
|
53
|
+
selected account's credential for requests and can renew idle slots in place.
|
|
54
|
+
When an actual native session owns the same login, Swapdex leaves renewal to
|
|
55
|
+
that application and uses a verified, read-only access snapshot when available.
|
|
56
56
|
|
|
57
57
|
## Concepts
|
|
58
58
|
|
|
@@ -224,10 +224,9 @@ personal you@personal.com
|
|
|
224
224
|
|
|
225
225
|
It reads each account's remaining quota from Anthropic's official OAuth usage
|
|
226
226
|
endpoint using that account's **own** token -- read-only, and it spends zero
|
|
227
|
-
message quota.
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
also in `swapdex ui` under the `%` key.
|
|
227
|
+
message quota. It uses the slot or a verified current native login for that
|
|
228
|
+
account. An unavailable or expired credential reports its state rather than
|
|
229
|
+
inventing current quota. It is also in `swapdex ui` under the `%` key.
|
|
231
230
|
|
|
232
231
|
### The dashboard
|
|
233
232
|
|
|
@@ -240,12 +239,33 @@ setup is one keystroke and a name.
|
|
|
240
239
|
<img src="https://raw.githubusercontent.com/youdie006/swapdex/main/docs/ui-demo.gif" alt="swapdex ui on a fresh machine: it finds the Claude Code and Codex logins already present, saves them as a profile named main, and shows the account with its 5h and 7d usage bars" width="760" />
|
|
241
240
|
</div>
|
|
242
241
|
|
|
242
|
+
## Resuming Codex conversations
|
|
243
|
+
|
|
244
|
+
Use `codex resume` normally, or `codex resume --all` to include other working
|
|
245
|
+
directories. Swapdex keeps one stable OpenAI provider across account changes.
|
|
246
|
+
The paying account is shown by `swapdex serve --tool codex --quiet`.
|
|
247
|
+
If the proxy cannot start, the launcher warns that Codex will use its own login
|
|
248
|
+
directly.
|
|
249
|
+
|
|
250
|
+
After updating from a version that created `swapdex` provider IDs, run
|
|
251
|
+
`swapdex shim` to refresh the launcher. It automatically repairs those legacy
|
|
252
|
+
session labels before launching Codex. To inspect or retry the repair directly:
|
|
253
|
+
|
|
254
|
+
```sh
|
|
255
|
+
swapdex repair-codex-sessions --dry-run
|
|
256
|
+
swapdex repair-codex-sessions
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
The repair preserves conversation contents and keeps a private recovery journal.
|
|
260
|
+
Open sessions are deferred until they close. Unsupported compressed rollouts
|
|
261
|
+
and unsuccessful repairs are reported rather than silently hidden.
|
|
262
|
+
|
|
243
263
|
## Keeping accounts from expiring
|
|
244
264
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
265
|
+
Access tokens expire by design. An idle slot can renew while its refresh token
|
|
266
|
+
remains valid, but provider expiry, revocation or renewal by another credential
|
|
267
|
+
holder can make a new browser sign-in necessary. Keep-alive reduces avoidable
|
|
268
|
+
idle expiry; it cannot guarantee that a login never expires.
|
|
249
269
|
|
|
250
270
|
swapdex renews idle accounts for you, but **only while its proxy is running**,
|
|
251
271
|
because that is the process holding the timer:
|
|
@@ -280,9 +300,9 @@ own slot*. swapdex never copies a token between slots: `swapdex run <name>`
|
|
|
280
300
|
`exec`s `claude` with that slot's `CLAUDE_CONFIG_DIR`, and `swapdex use <name>`
|
|
281
301
|
writes a one-line pointer that a small `claude` shim on your PATH reads. Shared
|
|
282
302
|
config (`settings.json`, global `CLAUDE.md`) is symlinked into each new slot;
|
|
283
|
-
the token and history stay per-slot.
|
|
284
|
-
|
|
285
|
-
|
|
303
|
+
the token and history stay per-slot. Independently signed-in slots avoid sharing
|
|
304
|
+
a rotating refresh chain. Copies of one login remain coupled even if they live
|
|
305
|
+
in different directories; the warning below applies to those copies.
|
|
286
306
|
|
|
287
307
|
**Classic snapshots (still supported).** Each CLI also keeps its login in a
|
|
288
308
|
small on-disk file:
|
|
@@ -340,49 +360,48 @@ Already-current accounts and successful or empty runs return 0. Missing or
|
|
|
340
360
|
unreadable logins produce a sign-in remedy without an OAuth request.
|
|
341
361
|
|
|
342
362
|
`swapdex refresh --keep-alive` runs the same check without a proxy. If a local
|
|
343
|
-
session holds a due account,
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
363
|
+
session holds a due account, Swapdex leaves its refresh token alone. A verified
|
|
364
|
+
usable native login is shown as managed by Claude or Codex, including
|
|
365
|
+
`renewal_owner` in `ls --json`; this is not an OAuth renewal by Swapdex. When
|
|
366
|
+
that native login cannot be verified, renewal remains deferred and unverified.
|
|
367
|
+
Actual access expiry and recorded refresh rejection are separate warnings.
|
|
368
|
+
An inaccessible macOS Keychain is a read-access problem, not proof that the
|
|
369
|
+
login expired.
|
|
370
|
+
|
|
371
|
+
For an HTTP request rejected with 401, the managed proxy first attempts bounded
|
|
372
|
+
recovery of the same selected account: reread a changed usable native access
|
|
373
|
+
token, or await a coordinated Swapdex renewal for an idle login. It retries
|
|
374
|
+
only with a changed usable token, before any explicitly configured failover.
|
|
375
|
+
An unavailable selected login produces an error instead of silently using the
|
|
376
|
+
client's different account.
|
|
377
|
+
|
|
378
|
+
The launch default and proxy selection control different operations: the first
|
|
379
|
+
affects new native launches, and the second affects subsequent managed HTTP
|
|
380
|
+
requests. Changing a file or default does not switch every existing native
|
|
381
|
+
process, in-flight request or WebSocket conversation. Explicit account pins
|
|
382
|
+
retain their selected account.
|
|
348
383
|
|
|
349
384
|
An external copy can renew without changing any local file. Neither the local
|
|
350
385
|
access token's issue time nor `last_refresh` reveals that remote event. These
|
|
351
386
|
checks therefore cannot certify refresh validity after unseen remote activity;
|
|
352
387
|
external consumers need their own login instead of a copy of a managed slot.
|
|
353
388
|
|
|
354
|
-
###
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
- **No wrapper, no client spoofing.** swapdex swaps the credential file that the
|
|
371
|
-
official `claude` / `codex` binary already reads, then gets out of the way. It
|
|
372
|
-
never sits between the CLI and the API, never proxies requests, and never
|
|
373
|
-
presents itself as the official client. Your traffic is the real CLI's traffic.
|
|
374
|
-
(Launching the official tool once, on your explicit pick - `login`'s sign-in
|
|
375
|
-
flow, `ui`'s session resume - is a hand-off, not a wrapper: swapdex `exec`s
|
|
376
|
-
and is gone.)
|
|
377
|
-
|
|
378
|
-
Anthropic and OpenAI both permit multiple accounts for genuinely different
|
|
379
|
-
purposes but forbid using multiple accounts to get around a single workload's
|
|
380
|
-
rate limit, and forbid routing subscription OAuth tokens through third-party
|
|
381
|
-
tools or spoofing the official client. swapdex is built for the former and
|
|
382
|
-
structurally cannot do the latter -- it only ever hands the real CLI its own
|
|
383
|
-
credentials. See
|
|
384
|
-
[Anthropic Usage Policy](https://www.anthropic.com/legal/usage-policy) and
|
|
385
|
-
[OpenAI Usage Policies](https://openai.com/policies/usage-policies/).
|
|
389
|
+
### Network and credential behavior
|
|
390
|
+
|
|
391
|
+
Account selection and listing read local state. Opt-in quota lookups contact
|
|
392
|
+
provider usage endpoints. The optional proxy relays API requests with the
|
|
393
|
+
selected credential, and its scheduled renewal work contacts OAuth endpoints
|
|
394
|
+
for idle logins. It uses `ureq` with rustls and bundled roots; CI excludes heavy
|
|
395
|
+
async runtimes and system-TLS dependencies.
|
|
396
|
+
|
|
397
|
+
Explicit account selection, launch defaults and configured proxy failover are
|
|
398
|
+
separate controls. A local file lock coordinates participating Swapdex callers;
|
|
399
|
+
it cannot lock an independent native CLI or another machine. Native renewal
|
|
400
|
+
ownership and access availability are therefore reported separately.
|
|
401
|
+
|
|
402
|
+
There is no command that prints a saved credential. OAuth request secrets are
|
|
403
|
+
passed to curl on stdin, and diagnostics redact credentials. Native launches
|
|
404
|
+
execute the installed official CLI with the chosen account's configuration.
|
|
386
405
|
|
|
387
406
|
## MCP (read-only)
|
|
388
407
|
|
|
@@ -412,18 +431,16 @@ that project's README, July 2026):
|
|
|
412
431
|
|
|
413
432
|
- [claude-swap](https://github.com/realiti4/claude-swap) -- Claude Code only,
|
|
414
433
|
a TUI with live usage bars, and *optional auto-switching* near your limit.
|
|
415
|
-
|
|
416
|
-
that feature.
|
|
434
|
+
This older comparison should be read alongside the current source review below.
|
|
417
435
|
- [aisw](https://github.com/burakdede/aisw) -- cross-tool including Gemini,
|
|
418
436
|
OS-keyring storage, Windows support. More features, bigger surface.
|
|
419
437
|
- [caam](https://github.com/Dicklesworthstone/coding_agent_account_manager) --
|
|
420
|
-
cross-tool with a shell wrapper and automatic rotation on rate limits
|
|
421
|
-
philosophical opposite of swapdex.
|
|
438
|
+
cross-tool with a shell wrapper and automatic rotation on rate limits.
|
|
422
439
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
440
|
+
For current Codex switching and renewal mechanisms, see the
|
|
441
|
+
[2026-09-15 source survey](docs/research/2026-09-15-codex-switcher-survey.md):
|
|
442
|
+
pinned implementations, regression-test coverage and the limits of file-based
|
|
443
|
+
switching while native sessions keep running.
|
|
427
444
|
|
|
428
445
|
## Roadmap
|
|
429
446
|
|
package/man/swapdex.1
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
.ie \n(.g .ds Aq \(aq
|
|
2
2
|
.el .ds Aq '
|
|
3
|
-
.TH swapdex 1 "swapdex 0.
|
|
3
|
+
.TH swapdex 1 "swapdex 0.162.0"
|
|
4
4
|
.SH NAME
|
|
5
5
|
swapdex \- Switch Claude Code / Codex / Gemini / Antigravity login accounts, locally and safely.
|
|
6
6
|
.SH SYNOPSIS
|
|
@@ -16,6 +16,9 @@ Print help
|
|
|
16
16
|
Print version
|
|
17
17
|
.SH SUBCOMMANDS
|
|
18
18
|
.TP
|
|
19
|
+
swapdex\-repair\-codex\-sessions(1)
|
|
20
|
+
Repair provider metadata written by older Swapdex Codex shims
|
|
21
|
+
.TP
|
|
19
22
|
swapdex\-add(1)
|
|
20
23
|
Save the current live login as a named profile
|
|
21
24
|
.TP
|
|
@@ -136,4 +139,4 @@ Print the man page (roff) to stdout
|
|
|
136
139
|
swapdex\-help(1)
|
|
137
140
|
Print this message or the help of the given subcommand(s)
|
|
138
141
|
.SH VERSION
|
|
139
|
-
v0.
|
|
142
|
+
v0.162.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@youdie006/swapdex",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.162.0",
|
|
4
4
|
"description": "Switch between multiple Claude Code, Codex, Gemini, and Antigravity login accounts, locally and safely.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"swapdex": "bin/swapdex.js"
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
"man/swapdex.1"
|
|
13
13
|
],
|
|
14
14
|
"optionalDependencies": {
|
|
15
|
-
"@youdie006/swapdex-darwin-arm64": "0.
|
|
16
|
-
"@youdie006/swapdex-darwin-x64": "0.
|
|
17
|
-
"@youdie006/swapdex-linux-x64": "0.
|
|
18
|
-
"@youdie006/swapdex-linux-arm64": "0.
|
|
15
|
+
"@youdie006/swapdex-darwin-arm64": "0.162.0",
|
|
16
|
+
"@youdie006/swapdex-darwin-x64": "0.162.0",
|
|
17
|
+
"@youdie006/swapdex-linux-x64": "0.162.0",
|
|
18
|
+
"@youdie006/swapdex-linux-arm64": "0.162.0"
|
|
19
19
|
},
|
|
20
20
|
"keywords": [
|
|
21
21
|
"cli",
|