@youdie006/swapdex 0.164.1 → 0.165.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +162 -97
  2. package/man/swapdex.1 +2 -2
  3. package/package.json +5 -5
package/README.md CHANGED
@@ -6,19 +6,15 @@
6
6
  [![crates.io](https://img.shields.io/crates/v/swapdex?logo=rust&color=7a3be0)](https://crates.io/crates/swapdex)
7
7
  [![npm](https://img.shields.io/npm/v/%40youdie006%2Fswapdex?logo=npm&color=7a3be0)](https://www.npmjs.com/package/@youdie006/swapdex)
8
8
  [![license](https://img.shields.io/badge/license-MIT-1e1d1a.svg)](LICENSE)
9
- [![switcher: no network](https://img.shields.io/badge/switcher-no%20network-7a3be0.svg)](#what-it-will-not-do)
9
+ [![selection: local](https://img.shields.io/badge/selection-local-7a3be0.svg)](#network-and-credential-behavior)
10
10
 
11
11
  </div>
12
12
 
13
- One command to flip your Claude Code, Codex, Gemini CLI, or Antigravity from
14
- your work account to your personal one, and back. No re-login, no browser, no copying
15
- tokens around -- and the switch itself never touches the network. (One opt-in
16
- command, `swapdex quota`, reads your remaining balance from Anthropic; nothing
17
- else does.)
18
-
19
- <div align="center">
20
- <img src="https://raw.githubusercontent.com/youdie006/swapdex/main/docs/demo.gif" alt="swapdex demo: ls lists two saved accounts, use personal switches Claude Code and Codex together, status confirms both, restore puts the previous login back" width="760" />
21
- </div>
13
+ Keep your Claude Code and Codex accounts in separate login directories, then
14
+ choose which account handles the next request in a managed conversation.
15
+ Sign each account in once; subsequent account selections do not require a new
16
+ login while its credentials remain usable. Gemini CLI and Antigravity use the
17
+ supported snapshot-switching workflow.
22
18
 
23
19
  ```sh
24
20
  brew install youdie006/tap/swapdex # macOS / Linux
@@ -26,8 +22,9 @@ npm i -g @youdie006/swapdex # or, if you have node
26
22
  cargo install swapdex # or, if you have rust
27
23
  ```
28
24
 
29
- Then `swapdex add work`, `swapdex add personal`, and `swapdex use personal`.
30
- [Full install notes](#install) &middot; [what it will not do](#what-it-will-not-do).
25
+ Start with the [Claude/Codex quickstart](#quick-start).
26
+ [Install notes](#install) &middot; [existing logins](#existing-logins-and-folders)
27
+ &middot; [network behavior](#network-and-credential-behavior).
31
28
 
32
29
  ---
33
30
 
@@ -37,13 +34,11 @@ If you run Claude Code, Codex, Gemini CLI, or Antigravity under more than one
37
34
  account -- a work seat and a personal subscription, a client's org and your own
38
35
  -- switching means logging out and back in every time.
39
36
 
40
- swapdex gives each account its **own permanent space** -- its own
41
- `CLAUDE_CONFIG_DIR` or `CODEX_HOME` slot -- and switches the default pointer.
42
- `swapdex use work` points your default account there and a plain `claude`
43
- follows it; `swapdex run work` launches straight into that account (each terminal
44
- can be a different one). Existing native sessions keep their own slot when the
45
- default changes.
46
- `swapdex onboard` sets this up in a few prompts.
37
+ swapdex gives each Claude or Codex account its **own permanent space** -- its
38
+ own `CLAUDE_CONFIG_DIR` or `CODEX_HOME` slot. A small launcher called a **shim**
39
+ makes plain `claude` or `codex` commands use the selected space and local proxy.
40
+ The proxy chooses an account for each managed request, so changing the serving
41
+ account keeps the conversation and its working directory in place.
47
42
 
48
43
  It manages accounts you already own, with separate launch defaults, proxy
49
44
  selection and configurable failover. See [How it works](#how-it-works) for the
@@ -59,12 +54,15 @@ that application and uses a verified, read-only access snapshot when available.
59
54
  - **Account** -- one login you own (a work seat, a personal subscription). Its
60
55
  redacted identity (email, tier) is shown by `slots`, `status`, and `doctor`;
61
56
  never a token.
62
- - **Slot** -- an account's own permanent `CLAUDE_CONFIG_DIR`, where its login
63
- lives and refreshes in place. swapdex creates one per account (or adopts a
64
- `~/.claude-*` dir you already use) and never copies tokens between them.
65
- - **Default account** -- the one a plain `claude` uses, via a tiny shim on your
66
- PATH. `swapdex use <name>` repoints it; `swapdex run <name>` ignores it and
67
- launches a specific account directly.
57
+ - **Slot** -- an account's permanent Claude or Codex directory, where its login
58
+ lives and refreshes in place. Swapdex creates it, or registers a separate
59
+ directory you already use. Each new slot needs its own native sign-in.
60
+ - **Launch default** -- the slot a plain `claude` or `codex` starts in through
61
+ the shim. `swapdex use <name> --tool codex` selects a Codex default.
62
+ - **Serving account** -- the account the proxy uses for subsequent managed
63
+ requests. `swapdex serve <name> --tool codex` changes it without moving the
64
+ conversation's home. `swapdex run` launches the named slot directly, so it
65
+ is useful for login and for sessions that should use their own account.
68
66
 
69
67
  <sub>swapdex still keeps the classic snapshot commands (`add` copies a live login
70
68
  into a profile, `use` on that profile swaps it back, guarded against the
@@ -75,7 +73,7 @@ slots.</sub>
75
73
  ## Install
76
74
 
77
75
  ```sh
78
- # npm - you already have it, since Claude Code and Codex ship this way
76
+ # npm (requires Node.js and npm)
79
77
  npm install -g @youdie006/swapdex
80
78
 
81
79
  # Homebrew (macOS / Linux)
@@ -93,60 +91,120 @@ with two of them the shims keep calling whichever copy wrote them - so updating
93
91
  the other one changes nothing, silently. `swapdex doctor` reports this, along
94
92
  with whether the version you are running is the one that is published.
95
93
 
96
- Linux, WSL, and macOS (Claude's macOS login lives in the Keychain; swapdex
97
- swaps it there, via `/usr/bin/security`). Requires at least one supported CLI
98
- (Claude Code, Codex, Gemini, Antigravity) already installed and logged in. Full command, exit-code, and environment
99
- reference: [docs/COMMANDS.md](docs/COMMANDS.md).
94
+ Linux, WSL, and macOS are supported. Install the native CLI you want to use
95
+ first; Swapdex does not install it. Codex-only and Claude-only machines are both
96
+ supported. Claude's macOS login uses the Keychain through `/usr/bin/security`.
97
+ For WSL, install and run Swapdex and the native CLI inside the same WSL
98
+ distribution. [Full command reference](docs/COMMANDS.md).
100
99
 
101
- ## Use
100
+ ## Quick start
101
+
102
+ Choose the tool you have. `work` and `personal` are example names; sign into
103
+ the intended account in each login flow. The second account is optional.
104
+
105
+ ### Codex
102
106
 
103
107
  ```sh
104
- # First run: guided setup -- registers ~/.claude-* dirs you already use,
105
- # moves old profiles onto slots, offers the shim. A bare `swapdex` runs this
106
- # automatically the first time there is something to set up.
107
- swapdex onboard
108
+ swapdex run work --tool codex -- login --device-auth
109
+ swapdex run personal --tool codex -- login --device-auth
110
+ swapdex shim
111
+ ```
112
+
113
+ Activate the PATH change printed by `swapdex shim`: open a new terminal, source
114
+ the shell file it names, or apply its printed `export PATH=...` command. Then:
115
+
116
+ ```sh
117
+ swapdex use work --tool codex
118
+ codex
119
+ ```
120
+
121
+ While that conversation stays open, use another terminal to select the account
122
+ for its next request:
108
123
 
109
- # Launch an account in its own slot (first time = sign in; concurrent-safe,
110
- # so each terminal can be a different account)
111
- swapdex run work
112
- swapdex run personal
124
+ ```sh
125
+ swapdex serve personal --tool codex
126
+ swapdex serve --tool codex --quiet
127
+ ```
128
+
129
+ The last command shows the selected serving account. It is a routing status,
130
+ not an independent billing statement. A request already in progress finishes
131
+ with the account it started with.
132
+
133
+ ### Claude Code
134
+
135
+ ```sh
136
+ swapdex run work --tool claude -- auth login
137
+ swapdex run personal --tool claude -- auth login
138
+ swapdex shim
139
+ ```
140
+
141
+ Activate the printed PATH change, then start a managed conversation:
113
142
 
114
- # Make a plain `claude` follow a default account
115
- swapdex shim # installs the claude shim once (prints a PATH line)
116
- swapdex use personal # a plain `claude` now runs as personal
117
- swapdex use work # switch the default -- no re-login, never logs out
143
+ ```sh
144
+ swapdex use work --tool claude
145
+ claude
146
+ ```
118
147
 
119
- # See your accounts and who's active
120
- swapdex slots
121
- swapdex status
148
+ In another terminal, `swapdex serve personal --tool claude` selects the account
149
+ for the next managed request. `swapdex serve --tool claude --quiet` shows it.
122
150
 
123
- # Register a config dir you already run by hand; move old profiles to slots
124
- swapdex adopt company ~/.claude-company
125
- swapdex migrate
151
+ **Existing conversations:** a native process started before the shim was
152
+ installed, or started directly with `swapdex run`, keeps its direct routing.
153
+ Resume it once through plain `codex resume` or `claude --resume` after activating
154
+ the shim. Subsequent serving-account changes apply without restarting that
155
+ managed session. Explicit custom-provider options can also bypass managed
156
+ routing. If proxy startup fails, the managed launcher stops with an error.
126
157
 
127
- # Sessions grouped by the account active when they ran (needs sessionwiki)
128
- swapdex sessions
158
+ `swapdex slash` installs an in-chat `/swap` command. `swapdex ui` offers the
159
+ account picker and conversation menu. Run `swapdex doctor` if the plain CLI
160
+ still uses a different executable or account than expected.
129
161
 
130
- # Recent local token usage per tool (5h/7d) -- tells you when to switch
131
- swapdex usage
162
+ ## Existing logins and folders
132
163
 
133
- # Remaining quota per Claude account -- the one opt-in network read
134
- swapdex quota
164
+ Already signed in through a default native directory? The quickstart creates
165
+ separate slots and leaves that login in place. It requires one sign-in in each
166
+ new slot; it does not import the existing credential into those slots.
135
167
 
136
- # Set up a second machine with the same accounts (never carries a login)
137
- swapdex export setup.json # on the machine you already use
138
- swapdex import setup.json # on the new one, then sign each account in
168
+ If you already keep accounts in separate directories, register them in place:
139
169
 
140
- # Anything off? Every finding comes with its fix
141
- swapdex doctor
170
+ ```sh
171
+ swapdex adopt work ~/.codex-work --tool codex
172
+ swapdex adopt work ~/.claude-work --tool claude
173
+ swapdex onboard
142
174
  ```
143
175
 
144
- The classic snapshot commands still work for the shared-slot workflow: `swapdex
145
- add <name>` snapshots the current login, `swapdex use <name>` swaps it back
146
- (backed up first, and refused while a `claude` session is running on that login
147
- so it can't be logged out), `swapdex restore` undoes the last swap, and `swapdex
148
- ui` is the full-screen picker. `swapdex migrate` matches Claude and Codex
149
- profiles to slots by account and creates spaces only for accounts without one.
176
+ Run only the `adopt` command for a directory you actually have. `onboard` can
177
+ discover `~/.claude-*` directories, offer migration of saved Claude/Codex
178
+ profiles, and install available shims. Migration creates missing slots; each
179
+ new slot still needs its native sign-in.
180
+
181
+ ### Saved snapshots and other tools
182
+
183
+ `swapdex setup` guides saving current logins as profiles and adding more.
184
+ `swapdex add work --tool codex` saves the Codex login that is already present;
185
+ calling `add` again under another name does not sign into a different account.
186
+ `swapdex login personal --tool codex` runs the legacy add-another-login flow,
187
+ preserving the old login and restoring it if sign-in fails.
188
+
189
+ `swapdex use <name>` applies a saved snapshot when no matching slot exists,
190
+ with backups and running-session guards. `swapdex restore` restores the last
191
+ snapshot switch. Gemini and Antigravity use this workflow; the live proxy and
192
+ slot quickstart above support Claude and Codex. Snapshot switching does not
193
+ reconfigure an already running native process.
194
+
195
+ ## Everyday commands
196
+
197
+ | Task | Command |
198
+ | --- | --- |
199
+ | List accounts and their state | `swapdex ls` |
200
+ | Show launch defaults | `swapdex status` |
201
+ | Show the Codex serving account | `swapdex serve --tool codex --quiet` |
202
+ | Find a conversation by project | `swapdex whereis <project>` |
203
+ | Group indexed sessions by account | `swapdex sessions` (needs sessionwiki) |
204
+ | Read local session activity | `swapdex usage` |
205
+ | Fetch Claude/Codex account quota | `swapdex quota` |
206
+ | Check paths, accounts and services | `swapdex doctor` |
207
+ | Transfer setup without credentials | `swapdex export setup.json`, then `swapdex import setup.json` on the other machine and sign in there |
150
208
 
151
209
  `status` shows the active account per tool, matched back to a saved profile:
152
210
 
@@ -206,8 +264,8 @@ each event's timestamp (the same honest join `sessions` uses); anything before
206
264
  your first switch stays untagged. Still deliberately a hint, not a
207
265
  quota-dodging auto-rotator.
208
266
 
209
- Where `usage` is your local activity, `quota` is the vendor's actual remaining
210
- balance -- the one command that reaches the network, and only when you run it:
267
+ Where `usage` is local activity, `quota` fetches the provider's reported usage
268
+ windows for Claude and Codex accounts:
211
269
 
212
270
  ```
213
271
  $ swapdex quota
@@ -219,14 +277,14 @@ work (active) you@work.com
219
277
  7d ▓▓▓▓▓▓░░░░ 57% left resets in 3d 4h
220
278
 
221
279
  personal you@personal.com
222
- snapshot token expired - `swapdex use personal` to refresh, then `swapdex quota`
280
+ usage endpoint rejected this credential - check `swapdex doctor`
223
281
  ```
224
282
 
225
- It reads each account's remaining quota from Anthropic's official OAuth usage
226
- endpoint using that account's **own** token -- read-only, and it spends zero
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.
283
+ It reads usage endpoints using each account's **own** token and does not submit
284
+ a model request. It uses the slot or a verified current native login for that
285
+ account. An unavailable credential or failed lookup reports its state rather
286
+ than inventing current quota. The dashboard also fetches quota for its account
287
+ rows; `%` opens the detailed panel.
230
288
 
231
289
  ### The dashboard
232
290
 
@@ -244,8 +302,8 @@ setup is one keystroke and a name.
244
302
  Use `codex resume` normally, or `codex resume --all` to include other working
245
303
  directories. Swapdex keeps one stable OpenAI provider across account changes.
246
304
  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.
305
+ If the proxy cannot start, the managed launcher exits with an error before
306
+ starting Codex. It does not send the request through a different native login.
249
307
 
250
308
  After updating from a version that created `swapdex` provider IDs, run
251
309
  `swapdex shim` to refresh the launcher. It automatically repairs those legacy
@@ -267,7 +325,7 @@ remains valid, but provider expiry, revocation or renewal by another credential
267
325
  holder can make a new browser sign-in necessary. Keep-alive reduces avoidable
268
326
  idle expiry; it cannot guarantee that a login never expires.
269
327
 
270
- swapdex renews idle accounts for you, but **only while its proxy is running**,
328
+ Swapdex can renew idle accounts **while its proxy is running**,
271
329
  because that is the process holding the timer:
272
330
 
273
331
  ```sh
@@ -281,7 +339,9 @@ nobody has opened. A slot the tool is running in is never touched: its own
281
339
  session holds the refresh token, and renewing from outside would retire the one
282
340
  that session is about to use.
283
341
 
284
- Without the service, nothing is on a timer. You can sweep by hand:
342
+ The service keeps that timer available after the launching terminal closes.
343
+ A foreground or automatically started proxy also sweeps while it remains
344
+ running. You can run a sweep by hand:
285
345
 
286
346
  ```sh
287
347
  swapdex refresh --keep-alive # renew every account heading for expiry
@@ -292,17 +352,16 @@ swapdex refresh <name> # renew one that has already lapsed
292
352
 
293
353
  ## How it works
294
354
 
295
- **Slots (the model swapdex uses now).** Each account gets its own
296
- `CLAUDE_CONFIG_DIR` -- a directory under `~/.local/share/swapdex/slots/`, or a
297
- `~/.claude-*` dir you adopt. Claude keys its login to that dir (a file on Linux,
298
- a Keychain item on macOS), so each account's token lives and refreshes *in its
299
- own slot*. swapdex never copies a token between slots: `swapdex run <name>`
300
- `exec`s `claude` with that slot's `CLAUDE_CONFIG_DIR`, and `swapdex use <name>`
301
- writes a one-line pointer that a small `claude` shim on your PATH reads. Shared
302
- config (`settings.json`, global `CLAUDE.md`) is symlinked into each new slot;
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.
355
+ **Slots.** Each Claude or Codex account gets its own `CLAUDE_CONFIG_DIR` or
356
+ `CODEX_HOME`, under Swapdex's data directory or in a directory you adopt.
357
+ Claude keys its login to that directory (a file on Linux, a Keychain item on
358
+ macOS); Codex stores its own auth file there. Each token refreshes in its own
359
+ slot. `swapdex run` invokes the native CLI directly with the named slot's home.
360
+ `swapdex use` selects the home for plain shimmed launches. Shared configuration
361
+ and conversation stores are linked where supported, so selecting a different
362
+ serving account does not require copying conversations. Independently signed-in
363
+ slots avoid sharing a rotating refresh chain. Copies of one login remain
364
+ coupled even when stored in different directories.
306
365
 
307
366
  **Classic snapshots (still supported).** Each CLI also keeps its login in a
308
367
  small on-disk file:
@@ -320,8 +379,8 @@ your projects, MCP servers, and settings are untouched. That switch is refused
320
379
  while a `claude` session is running on the same login slot, since the session's
321
380
  next token refresh would otherwise revoke the saved copy. On macOS the Claude
322
381
  token lives in the login Keychain, one item per `CLAUDE_CONFIG_DIR`. `swapdex
323
- migrate [--tool claude|codex]` moves unslotted Claude and Codex profiles onto
324
- their own slots, retiring the shared homes.
382
+ migrate [--tool claude|codex]` creates missing slots for saved Claude and Codex
383
+ accounts. It does not copy their credentials; sign in to each new slot once.
325
384
 
326
385
  ## Safety
327
386
 
@@ -336,7 +395,8 @@ their own slots, retiring the shared homes.
336
395
  command if the switch was a mistake. The store keeps the last 2 backups per
337
396
  tool, and `use` warns when the outgoing login is not saved as a profile --
338
397
  so save accounts you care about with `add`.
339
- - No token, refresh token, or home path is ever printed.
398
+ - Diagnostics do not print tokens or refresh tokens. Setup commands may show
399
+ the local paths that need to be configured.
340
400
 
341
401
  **The store holds plaintext refresh tokens.** Protect `~/.local/share/swapdex`
342
402
  like `~/.ssh`, and do not sync it across machines (it is single-machine,
@@ -388,11 +448,16 @@ external consumers need their own login instead of a copy of a managed slot.
388
448
 
389
449
  ### Network and credential behavior
390
450
 
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.
451
+ Account selection and listing use local state. Managed launches and `serve`
452
+ can start a local proxy; its scheduled renewal work contacts OAuth endpoints
453
+ for idle logins. `quota` and the dashboard contact provider usage endpoints;
454
+ `quota` can first renew eligible expired Claude slot credentials through the
455
+ same coordinated path. Saved snapshots remain read-only, and running native
456
+ sessions keep renewal ownership. `doctor` checks the published version online. Login commands invoke the
457
+ native tool's sign-in flow. The proxy relays model requests with the selected
458
+ credential using `ureq`, rustls and bundled roots; CI excludes heavy async
459
+ runtimes and system-TLS dependencies. An ordinary account selection does not
460
+ submit a model request.
396
461
 
397
462
  Explicit account selection, launch defaults and configured proxy failover are
398
463
  separate controls. A local file lock coordinates participating Swapdex callers;
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.164.1"
3
+ .TH swapdex 1 "swapdex 0.165.1"
4
4
  .SH NAME
5
5
  swapdex \- Switch Claude Code / Codex / Gemini / Antigravity login accounts, locally and safely.
6
6
  .SH SYNOPSIS
@@ -139,4 +139,4 @@ Print the man page (roff) to stdout
139
139
  swapdex\-help(1)
140
140
  Print this message or the help of the given subcommand(s)
141
141
  .SH VERSION
142
- v0.164.1
142
+ v0.165.1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youdie006/swapdex",
3
- "version": "0.164.1",
3
+ "version": "0.165.1",
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.164.1",
16
- "@youdie006/swapdex-darwin-x64": "0.164.1",
17
- "@youdie006/swapdex-linux-x64": "0.164.1",
18
- "@youdie006/swapdex-linux-arm64": "0.164.1"
15
+ "@youdie006/swapdex-darwin-arm64": "0.165.1",
16
+ "@youdie006/swapdex-darwin-x64": "0.165.1",
17
+ "@youdie006/swapdex-linux-x64": "0.165.1",
18
+ "@youdie006/swapdex-linux-arm64": "0.165.1"
19
19
  },
20
20
  "keywords": [
21
21
  "cli",