@youdie006/swapdex 0.1.0 → 0.1.2

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 (2) hide show
  1. package/README.md +168 -0
  2. package/package.json +2 -1
package/README.md ADDED
@@ -0,0 +1,168 @@
1
+ <div align="center">
2
+
3
+ <img src="https://raw.githubusercontent.com/youdie006/swapdex/main/docs/cli-banner.png" alt="swapdex - switch Claude Code and Codex login accounts, one command, all local" width="760" />
4
+
5
+ [![CI](https://github.com/youdie006/swapdex/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/youdie006/swapdex/actions/workflows/ci.yml)
6
+ [![license](https://img.shields.io/badge/license-MIT-1e1d1a.svg)](https://github.com/youdie006/swapdex/blob/main/LICENSE)
7
+ [![local only](https://img.shields.io/badge/network-none-7a3be0.svg)](#what-it-will-not-do)
8
+
9
+ </div>
10
+
11
+ One command to flip your Claude Code or Codex CLI from your work account to your
12
+ personal one, and back. No re-login, no browser, no copying tokens around.
13
+ 100% local. Never touches the network.
14
+
15
+ ---
16
+
17
+ ## Why
18
+
19
+ If you run Claude Code or Codex under more than one account -- a work seat and a
20
+ personal subscription, a client's org and your own -- switching means logging
21
+ out and back in every time. swapdex snapshots each logged-in account once, then
22
+ swaps between them in place: the running CLI picks up the new account on your
23
+ next message.
24
+
25
+ It is a **switcher, not a rotator.** It manages accounts you already own for
26
+ distinct purposes. It has no feature for cycling accounts to get around a rate
27
+ limit -- see [What it will not do](#what-it-will-not-do).
28
+
29
+ ## Concepts
30
+
31
+ - **Profile** -- a named, point-in-time snapshot of a live login (the credential
32
+ files, captured with `add`). It is a copy, not a live link.
33
+ - **Account** -- the redacted identity a profile resolves to (email, tier,
34
+ expiry). Shown by `ls` and `status`; never a token.
35
+ - **Switch** -- `use` writes a profile's snapshot back into place atomically,
36
+ backing up the current login first. One account is active per tool at a time.
37
+
38
+ ## Install
39
+
40
+ ```sh
41
+ # crates.io (Rust)
42
+ cargo install swapdex
43
+
44
+ # Homebrew (macOS / Linux)
45
+ brew install youdie006/tap/swapdex
46
+
47
+ # npm (downloads the prebuilt binary)
48
+ npm install -g @youdie006/swapdex
49
+
50
+ # or the one-liner (prebuilt binary -> ~/.local/bin)
51
+ curl -fsSL https://raw.githubusercontent.com/youdie006/swapdex/main/install.sh | sh
52
+ ```
53
+
54
+ Linux / WSL first (macOS Keychain support is planned). Requires the Claude Code
55
+ and/or Codex CLI already installed and logged in. Full command, exit-code, and
56
+ environment reference: [docs/COMMANDS.md](https://github.com/youdie006/swapdex/blob/main/docs/COMMANDS.md).
57
+
58
+ ## Use
59
+
60
+ ```sh
61
+ # Save the account you're currently logged in as
62
+ swapdex add work # snapshots Claude + Codex, whichever is logged in
63
+ swapdex add personal --tool claude
64
+
65
+ # See what you have and who's active
66
+ swapdex ls
67
+ swapdex status
68
+
69
+ # Switch (takes effect on your next message -- no restart)
70
+ swapdex use personal
71
+ swapdex use work --tool codex
72
+ swapdex use work --dry-run # show what would change, write nothing
73
+
74
+ # Sessions grouped by the account active when they ran (needs sessionwiki)
75
+ swapdex sessions
76
+ ```
77
+
78
+ `status` shows the live account per tool, matched back to a saved profile:
79
+
80
+ ```
81
+ claude-code: you@work.com [max] (profile 'work')
82
+ codex: you@personal.com (profile 'personal')
83
+ ```
84
+
85
+ The active account is always read from the **live** login, so if you `/login`
86
+ directly in the CLI, swapdex reports the truth rather than a stale guess.
87
+
88
+ ## How it works
89
+
90
+ Each CLI keeps its login in a small on-disk file:
91
+
92
+ - Claude Code: `~/.claude/.credentials.json` plus the `oauthAccount` block inside
93
+ `~/.claude.json`
94
+ - Codex: `~/.codex/auth.json`
95
+
96
+ `add` copies the current login into a private store at
97
+ `~/.local/share/swapdex`. `use` writes a saved snapshot back into place
98
+ atomically, backing up the current login first. For Claude, only the
99
+ `oauthAccount` block of `~/.claude.json` is swapped -- your projects, MCP
100
+ servers, and settings in that file are never touched.
101
+
102
+ ## Safety
103
+
104
+ - Every credential file swapdex writes is `0600`; the store directory is `0700`.
105
+ - Writes are atomic (temp file created `0600`, then renamed) so an interrupted
106
+ switch can never leave a half-written credential that bricks the CLI.
107
+ - Symlinked credential paths and running as root are refused.
108
+ - `use` backs up the current login and verifies the backup before overwriting,
109
+ so a switch can never lose an un-saved login.
110
+ - No token, refresh token, or home path is ever printed.
111
+
112
+ **The store holds plaintext refresh tokens.** Protect `~/.local/share/swapdex`
113
+ like `~/.ssh`, and do not sync it across machines (it is single-machine,
114
+ single-user by design).
115
+
116
+ ### What it will not do
117
+
118
+ These are structural properties, not promises -- the code is built so they
119
+ cannot happen:
120
+
121
+ - **No network, ever.** The switching binary has no HTTP client in its
122
+ dependency graph (CI asserts this on every commit). swapdex cannot phone home
123
+ or exfiltrate a token.
124
+ - **No auto-rotation.** There is no `--auto`, `--next`, or
125
+ `--when-rate-limited` flag. `use` only ever switches to a name you type.
126
+ - **No token export.** There is no command that prints a saved credential.
127
+
128
+ Anthropic and OpenAI both permit multiple accounts for genuinely different
129
+ purposes but forbid using multiple accounts to get around a single workload's
130
+ rate limit, and forbid using OAuth tokens outside the official CLI. swapdex is
131
+ built for the former and structurally cannot do the latter. See
132
+ [Anthropic Usage Policy](https://www.anthropic.com/legal/usage-policy) and
133
+ [OpenAI Usage Policies](https://openai.com/policies/usage-policies/).
134
+
135
+ ## MCP (read-only)
136
+
137
+ `swapdex mcp` runs a read-only MCP server exposing `whoami` and `list_accounts`
138
+ so an agent can see which account is active. There is deliberately **no** switch
139
+ tool -- an agent can never change your account.
140
+
141
+ ```sh
142
+ claude mcp add swapdex -s user -- swapdex mcp
143
+ ```
144
+
145
+ ## Works with
146
+
147
+ swapdex is the accounts layer of a small local AI-CLI stack:
148
+
149
+ - [sessionwiki](https://github.com/youdie006/sessionwiki) -- index, search, and
150
+ resume your AI coding sessions. `swapdex sessions` groups them by account.
151
+ - [prodex](https://github.com/youdie006/prodex) -- share one logged-in ChatGPT
152
+ Pro session across agents. swapdex coexists with it without touching its auth.
153
+
154
+ ## Roadmap
155
+
156
+ Being considered, explicitly opt-in and advisory-only:
157
+
158
+ - **Per-directory hints (cross-tool).** Bind a directory to a profile and have
159
+ `swapdex resolve <dir>` *suggest* the right account ("this directory is bound
160
+ to `work` -- run `swapdex use work`"). It would cover both Claude
161
+ (`CLAUDE_CONFIG_DIR`) and Codex (`CODEX_HOME`) in one binding. It will never be
162
+ a shell wrapper, never auto-switch, and never let anything but an explicit
163
+ `swapdex use` change the active account -- that bright line is what keeps
164
+ swapdex a switcher, not a rotator.
165
+
166
+ ## License
167
+
168
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youdie006/swapdex",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Switch between multiple Claude Code and Codex login accounts, locally and safely.",
5
5
  "bin": {
6
6
  "swapdex": "bin/swapdex.js"
@@ -9,6 +9,7 @@
9
9
  "postinstall": "node install.js"
10
10
  },
11
11
  "files": [
12
+ "README.md",
12
13
  "bin/swapdex.js",
13
14
  "install.js"
14
15
  ],