multi-claude-cli 0.7.0__tar.gz → 0.9.0__tar.gz
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.
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/PKG-INFO +75 -11
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/README.md +74 -10
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/__init__.py +1 -1
- multi_claude_cli-0.9.0/src/multi_claude/bundle.py +508 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/cli.py +89 -23
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/completion.py +1 -0
- multi_claude_cli-0.9.0/src/multi_claude/identity.py +189 -0
- multi_claude_cli-0.9.0/src/multi_claude/plan.py +317 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude_cli.egg-info/PKG-INFO +75 -11
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude_cli.egg-info/SOURCES.txt +4 -0
- multi_claude_cli-0.9.0/tests/test_bundle.py +305 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_help.py +3 -3
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_migrate.py +1 -1
- multi_claude_cli-0.9.0/tests/test_plan.py +478 -0
- multi_claude_cli-0.7.0/src/multi_claude/identity.py +0 -94
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/LICENSE +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/pyproject.toml +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/setup.cfg +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/__main__.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/accounts.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/actions.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/config.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/doctor.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/env.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/fsutil.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/history.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/hook.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/launcher.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/lock.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/migrate.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/platform.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/restore.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/routes.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/sessions.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/shared.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/shellpath.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/statusline.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude/usage.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude_cli.egg-info/dependency_links.txt +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude_cli.egg-info/entry_points.txt +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/src/multi_claude_cli.egg-info/top_level.txt +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_accounts.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_completion.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_config.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_doctor.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_everyday.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_fsutil.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_handoff.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_history.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_identity.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_install.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_mcp.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_onboarding.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_packaging.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_platform.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_rename.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_routes.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_set.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_shared_exclude.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_statusline.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_usability.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_usage.py +0 -0
- {multi_claude_cli-0.7.0 → multi_claude_cli-0.9.0}/tests/test_vscode.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: multi-claude-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: Run several Claude Code accounts side by side: separate CLAUDE_CONFIG_DIR directories, launchers, proxies, environment variables and arguments.
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/jakoes-wu/multi-claude
|
|
@@ -37,7 +37,7 @@ Dynamic: license-file
|
|
|
37
37
|
|
|
38
38
|
Use several [Claude Code](https://code.claude.com/docs) accounts on one machine, at the same time. Each account keeps its own login, settings and history and, if you like, its own proxy. No more logging out and in again.
|
|
39
39
|
|
|
40
|
-
It never
|
|
40
|
+
It never changes or copies your login and never edits your shell startup files. Only `list` reads an account's access token and goes online, to ask Anthropic for the current plan; `list --offline` skips that.
|
|
41
41
|
|
|
42
42
|
```sh
|
|
43
43
|
claude-work # Claude Code with your work account
|
|
@@ -64,8 +64,8 @@ The launchers are plain shell scripts. They keep working even if you uninstall m
|
|
|
64
64
|
|
|
65
65
|
## Features
|
|
66
66
|
|
|
67
|
-
- **
|
|
68
|
-
- **
|
|
67
|
+
- **Your login stays yours** — logins are never written, copied, exported or refreshed. One command reads one: `list` takes each account's access token (from the keychain, or `.credentials.json` on Linux) to ask Anthropic which plan the account is on. The token stays in memory and goes only to `api.anthropic.com`, through that account's proxy. `list --offline` reads nothing. Every other command only checks whether a login exists. `migrate-default` and `restore` move whole account directories, and on Linux the credentials file moves with its directory without being opened.
|
|
68
|
+
- **One kind of network request, nothing else** — the plan lookup of `list` (one request per account) is the only connection multi-claude makes: no telemetry, no usage reporting, no update checks. `list --offline` makes none. Only the installer, pipx or Homebrew download the package.
|
|
69
69
|
- **Leaves your shell alone** — when `PATH` needs a change, it prints the line to add instead of editing `~/.zshrc` or `~/.bashrc`.
|
|
70
70
|
- **Changes only what you ask** — it writes its own configuration and state, the launchers, account directories (including the VS Code data that `code` keeps in `<root>/.apps`) and shared links. A Claude Code settings file is changed only by `statusline install` (the file you name, with a backup) and `add --config-from` (the new account's `settings.json`).
|
|
71
71
|
- **Migrate the default account** — move your existing `~/.claude` into the account root without logging out. `claude` keeps working exactly as before.
|
|
@@ -76,11 +76,31 @@ The launchers are plain shell scripts. They keep working even if you uninstall m
|
|
|
76
76
|
- **Idempotent** — every command can be re-run safely. Write commands print only what changes (`--verbose` lists everything); conflicts with files multi-claude does not own are reported without changing anything; an interrupted migration resumes where it stopped.
|
|
77
77
|
- **Optional shared resources** — link `CLAUDE.md`, `skills`, `agents` and `commands` from one shared directory into selected accounts.
|
|
78
78
|
|
|
79
|
-
##
|
|
79
|
+
## Prerequisites
|
|
80
80
|
|
|
81
|
-
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
**Servers.** None. multi-claude runs only on your own computer; its only network requests are the plan lookups of `list`, sent to Anthropic.
|
|
82
|
+
|
|
83
|
+
**Your computer.**
|
|
84
|
+
|
|
85
|
+
| | Needed | Optional |
|
|
86
|
+
| ---- | ---- | ---- |
|
|
87
|
+
| Operating system | macOS or Linux (WSL counts as Linux) | — |
|
|
88
|
+
| Tools | Python 3.8+ (`python3`, standard library only); Claude Code (`claude`); `curl` or `wget`, and `tar`, for the installer | `pipx` or Homebrew, to install from PyPI or the tap; `lsof`, so that `migrate-default` and `restore` can find processes using `~/.claude` (Linux falls back to `/proc`); VS Code's `code` command, for `multi-claude code` |
|
|
89
|
+
|
|
90
|
+
Install what is missing:
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
# macOS (with Homebrew, https://brew.sh); curl, tar and lsof come with macOS
|
|
94
|
+
brew install python
|
|
95
|
+
curl -fsSL https://claude.ai/install.sh | bash # Claude Code, if you do not have it yet
|
|
96
|
+
|
|
97
|
+
# Debian / Ubuntu / WSL
|
|
98
|
+
sudo apt update
|
|
99
|
+
sudo apt install -y python3 curl tar lsof
|
|
100
|
+
curl -fsSL https://claude.ai/install.sh | bash # Claude Code, if you do not have it yet
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Windows itself is not supported yet; use WSL. Other ways to install Claude Code: https://code.claude.com/docs/en/setup
|
|
84
104
|
|
|
85
105
|
## Installation
|
|
86
106
|
|
|
@@ -207,6 +227,32 @@ Items that hold one account's own state cannot be shared: `.credentials.json`, `
|
|
|
207
227
|
|
|
208
228
|
**`skills/synced/`.** Claude Code stores skills synced from claude.ai in `skills/synced/`, one bucket per organization and account. If an account's `skills` is a real directory, turning sharing on is a conflict and multi-claude does not move anything. You may move the account's `skills/synced/<bucket>` into the shared directory's `skills/synced/` yourself: buckets of different accounts have different names and do not collide, but from then on that account's synced skills are written to the shared directory.
|
|
209
229
|
|
|
230
|
+
### Exporting and importing settings
|
|
231
|
+
|
|
232
|
+
```sh
|
|
233
|
+
multi-claude export work ~/work-settings.tar.gz # on this machine
|
|
234
|
+
multi-claude import ~/work-settings.tar.gz client # into another (existing) account, here or elsewhere
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
`export` writes `settings.json`, `CLAUDE.md`, `agents`, `commands`, `skills` and `output-styles` of the account, plus the MCP servers from its `.claude.json` (only the `mcpServers` entry), to a `.tar.gz` that only you can read. Logins, the rest of `.claude.json`, sessions, history and the plugin cache are never included. Items that are links (shared items) are skipped. If `settings.json` or the MCP servers contain values under names such as `API_KEY` or `Authorization`, `export` lists those names (not the values): treat the file like a password.
|
|
238
|
+
|
|
239
|
+
`import` copies the items into an account you created with `add`, and adds the MCP servers to its `.claude.json`. An item or MCP server that already exists with different content is a conflict: nothing is changed and the conflicts are listed. With `--force`, each one is first renamed to `<name>.multi-claude-bak.<timestamp>` and then replaced. An item that is a shared link is never replaced; turn sharing off for it first. `--dry-run` shows the plan. Restart running Claude sessions of the account after importing MCP servers; they keep their own copy of `.claude.json` and may overwrite the change.
|
|
240
|
+
|
|
241
|
+
Plugin choices travel in `settings.json` (`enabledPlugins`, `extraKnownMarketplaces`); Claude Code downloads the plugins again in the new account.
|
|
242
|
+
|
|
243
|
+
### Sharing MCP servers, plugins and settings
|
|
244
|
+
|
|
245
|
+
Shared links cover files and directories. For settings and MCP servers that every account should have, pass them on the command line of every launcher instead:
|
|
246
|
+
|
|
247
|
+
```sh
|
|
248
|
+
multi-claude args --defaults -- --mcp-config ~/.claude-shared/mcp.json --settings ~/.claude-shared/settings.json
|
|
249
|
+
multi-claude env --defaults CLAUDE_CODE_PLUGIN_CACHE_DIR=~/.claude-shared/plugins
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
- `--settings` is merged with each account's own `settings.json`: keys in the shared file win, other keys stay. Put `enabledPlugins`, `extraKnownMarketplaces`, `permissions` or `env` there.
|
|
253
|
+
- `--mcp-config` loads MCP servers from a JSON file (`{"mcpServers": {...}}`) in addition to each account's own. It takes several values, so keep another option after it (as `--settings` above); multi-claude warns otherwise.
|
|
254
|
+
- `CLAUDE_CODE_PLUGIN_CACHE_DIR` moves the plugins directory (marketplaces and the plugin cache), so plugins are downloaded once for all accounts.
|
|
255
|
+
|
|
210
256
|
### Choosing an account by directory
|
|
211
257
|
|
|
212
258
|
```sh
|
|
@@ -235,7 +281,7 @@ work 23% 14:00 41% Fri 12m ago
|
|
|
235
281
|
home - - no data (start claude-home once)
|
|
236
282
|
```
|
|
237
283
|
|
|
238
|
-
The numbers are the last values Claude Code itself cached in the account's `.claude.json` (for the default identity, `~/.claude.json`).
|
|
284
|
+
The numbers are the last values Claude Code itself cached in the account's `.claude.json` (for the default identity, `~/.claude.json`). `usage` never reads credentials and never calls the network, so the data can be old: `UPDATED` shows its age, and values older than an hour are marked `stale`. Claude Code writes this cache itself; when it refreshes it is not documented. A window whose reset time has passed shows `reset`.
|
|
239
285
|
|
|
240
286
|
For fresher numbers, let your status line record them. Claude Code passes the 5-hour and 7-day usage to the `statusLine` command each time it redraws the status line (Pro and Max plans, after the first response of a session). Wrap the `statusLine` command of the settings file that is actually in effect:
|
|
241
287
|
|
|
@@ -267,6 +313,22 @@ work:
|
|
|
267
313
|
|
|
268
314
|
`list` shows when each account was last used (`LAST USED`), from the newest session file or prompt history in its directory; a `handoff` into an account counts as use.
|
|
269
315
|
|
|
316
|
+
#### Plan and billing
|
|
317
|
+
|
|
318
|
+
```text
|
|
319
|
+
NAME LOGIN PLAN BILLING PROXY SHARED 5H 7D LAST USED STATUS
|
|
320
|
+
work keychain max (5x) stripe http://127.0.0.1:7890 no 23% 14:00 41% Fri 5m ago ok
|
|
321
|
+
home keychain pro apple inherit no - - 2d ago ok
|
|
322
|
+
old keychain expired - inherit no - - 9d ago ok
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
`PLAN` and `BILLING` are not cached values: every `list` asks Anthropic (`GET https://api.anthropic.com/api/oauth/profile`, the request Claude Code itself makes) with the account's own access token. `PLAN` is the subscription — `pro`, `max (5x)`, `max (20x)`, `team`, `enterprise`. `BILLING` is where the subscription is paid: `stripe` (claude.ai), `apple` (App Store), `google-play`, `aws-marketplace` and so on.
|
|
326
|
+
|
|
327
|
+
- The request uses the account's proxy setting, exactly like its launcher: the configured proxy, the proxy variables of your shell for `inherit`, none for `off`. If a proxy is configured and fails, the lookup fails; it never falls back to a direct connection. Only `http://` proxies work for the lookup.
|
|
328
|
+
- `expired` means the access token has run out. Tokens last a few hours and multi-claude never refreshes them (refreshing would compete with running sessions): start `claude-NAME` once and run `list` again. `-` means the account has no OAuth login, and `rejected` that the server refused the token.
|
|
329
|
+
- `error` comes with a reason on stderr, for example `plan lookup failed for work: timeout (via 127.0.0.1:7890, 10.01s)`. `tls_failed` usually means the Python that runs multi-claude has no root certificates (python.org installers ship an `Install Certificates.command`).
|
|
330
|
+
- `list --offline` skips the lookup — no token is read, nothing is sent — and prints the table without the two columns. `list --json` carries the same data in each account's `plan` object; scripts should use it instead of parsing the table. The lookup adds about a second, at most 15.
|
|
331
|
+
|
|
270
332
|
### Handing a session over to another account
|
|
271
333
|
|
|
272
334
|
Each account keeps its own sessions, so `claude --resume` in one account cannot see the sessions of another. `handoff` copies one session (its `.jsonl` file and the folder next to it with subagent transcripts and saved tool output) into the same project folder of another account:
|
|
@@ -401,7 +463,7 @@ By default the numbers come from the cache that Claude Code writes in `.claude.j
|
|
|
401
463
|
|
|
402
464
|
### Does multi-claude read or copy my login?
|
|
403
465
|
|
|
404
|
-
It never reads
|
|
466
|
+
It never writes, copies, exports, uploads, refreshes or backs up a login. One command reads one: `list` takes each account's access token to ask Anthropic for the account's plan (see [Plan and billing](#plan-and-billing)); the token stays in memory and is sent only to `api.anthropic.com`. `list --offline` does not read it. All other commands only check whether a login exists. `migrate-default` and `restore` move a whole account directory; on Linux the credentials file is inside it and moves with it (in copy mode it is copied as part of the directory, verified, and the original directory is then removed unless you pass `--keep-backup`), still without being opened. On macOS a login is tied to the account directory's path, which is why `rename` keeps the directory.
|
|
405
467
|
|
|
406
468
|
## Reference
|
|
407
469
|
|
|
@@ -412,6 +474,8 @@ It never reads it: its only keychain call checks whether an item exists, and it
|
|
|
412
474
|
| `multi-claude init [--root DIR] [--bin-dir DIR] [--shared-dir DIR] [--shared-items A,B]` | Create or change global settings. |
|
|
413
475
|
| `multi-claude migrate-default [NAME] [--copy] [--keep-backup] [--proxy P] [--skip-process-check]` | Turn `~/.claude` into an account. Without NAME, the email address of its login is used. |
|
|
414
476
|
| `multi-claude restore NAME [--skip-process-check] [--dry-run]` | Undo `migrate-default`: move the account back to `~/.claude` and unregister it. The login is kept. |
|
|
477
|
+
| `multi-claude export NAME FILE` | Write the account's settings, `CLAUDE.md`, agents, commands, skills, output styles and MCP servers to FILE. No logins or sessions. |
|
|
478
|
+
| `multi-claude import FILE NAME [--force] [--dry-run]` | Import such a file into an existing account; conflicts are refused unless `--force` (which backs up first). |
|
|
415
479
|
| `multi-claude add NAME [--proxy P] [--shared [DIR] \| --no-shared] [--adopt] [--shared-exclude ITEM] [--shared-include ITEM] [--config-from OTHER]` | Add an account, adopt an existing directory, or change its options. `--config-from` copies `settings.json` from OTHER once. `--shared DIR` also makes DIR the shared directory for every account (default `~/.claude-shared`). `--shared-exclude` keeps one shared item out of this account; `--shared-include` undoes it. |
|
|
416
480
|
| `multi-claude set NAME [--proxy P] [--shared [DIR] \| --no-shared] [--shared-exclude ITEM] [--shared-include ITEM]` | Change an existing account; same options as `add` without `--adopt`. Returns 1 for an account that is not registered. |
|
|
417
481
|
| `multi-claude proxy NAME PORT\|URL\|off\|inherit` | Set an account's proxy. |
|
|
@@ -419,7 +483,7 @@ It never reads it: its only keychain call checks whether an item exists, and it
|
|
|
419
483
|
| `multi-claude args (NAME \| --defaults) -- [ARG ...]` | Replace the fixed arguments; `--` with nothing after it clears them. |
|
|
420
484
|
| `multi-claude remove NAME` | Unregister an account and delete its launcher. **The directory and the login are kept.** |
|
|
421
485
|
| `multi-claude apply [-f FILE]` | Converge everything to the configuration (or to `FILE`). |
|
|
422
|
-
| `multi-claude list [--verbose \| --json \| --names]` | Show accounts, launchers and
|
|
486
|
+
| `multi-claude list [--verbose \| --json \| --names] [--offline]` | Show accounts, launchers, login state and the plan and billing channel looked up from Anthropic. `--json` adds usage and is meant for scripts; `--names` prints only the names; `--offline` skips the plan lookup (no token read, no network). |
|
|
423
487
|
| `multi-claude usage [NAME] [--json]` | Show the last known 5-hour and 7-day usage of each account. |
|
|
424
488
|
| `multi-claude usage --history [NAME] [--days N] [--by day\|model] [--json]` | Token usage per day or model, counted from the session files on this machine (default: 7 days). |
|
|
425
489
|
| `multi-claude doctor [--json] [--verbose]` | Check the configuration, launchers, account directories, shared links, logins and environment. |
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
Use several [Claude Code](https://code.claude.com/docs) accounts on one machine, at the same time. Each account keeps its own login, settings and history and, if you like, its own proxy. No more logging out and in again.
|
|
12
12
|
|
|
13
|
-
It never
|
|
13
|
+
It never changes or copies your login and never edits your shell startup files. Only `list` reads an account's access token and goes online, to ask Anthropic for the current plan; `list --offline` skips that.
|
|
14
14
|
|
|
15
15
|
```sh
|
|
16
16
|
claude-work # Claude Code with your work account
|
|
@@ -37,8 +37,8 @@ The launchers are plain shell scripts. They keep working even if you uninstall m
|
|
|
37
37
|
|
|
38
38
|
## Features
|
|
39
39
|
|
|
40
|
-
- **
|
|
41
|
-
- **
|
|
40
|
+
- **Your login stays yours** — logins are never written, copied, exported or refreshed. One command reads one: `list` takes each account's access token (from the keychain, or `.credentials.json` on Linux) to ask Anthropic which plan the account is on. The token stays in memory and goes only to `api.anthropic.com`, through that account's proxy. `list --offline` reads nothing. Every other command only checks whether a login exists. `migrate-default` and `restore` move whole account directories, and on Linux the credentials file moves with its directory without being opened.
|
|
41
|
+
- **One kind of network request, nothing else** — the plan lookup of `list` (one request per account) is the only connection multi-claude makes: no telemetry, no usage reporting, no update checks. `list --offline` makes none. Only the installer, pipx or Homebrew download the package.
|
|
42
42
|
- **Leaves your shell alone** — when `PATH` needs a change, it prints the line to add instead of editing `~/.zshrc` or `~/.bashrc`.
|
|
43
43
|
- **Changes only what you ask** — it writes its own configuration and state, the launchers, account directories (including the VS Code data that `code` keeps in `<root>/.apps`) and shared links. A Claude Code settings file is changed only by `statusline install` (the file you name, with a backup) and `add --config-from` (the new account's `settings.json`).
|
|
44
44
|
- **Migrate the default account** — move your existing `~/.claude` into the account root without logging out. `claude` keeps working exactly as before.
|
|
@@ -49,11 +49,31 @@ The launchers are plain shell scripts. They keep working even if you uninstall m
|
|
|
49
49
|
- **Idempotent** — every command can be re-run safely. Write commands print only what changes (`--verbose` lists everything); conflicts with files multi-claude does not own are reported without changing anything; an interrupted migration resumes where it stopped.
|
|
50
50
|
- **Optional shared resources** — link `CLAUDE.md`, `skills`, `agents` and `commands` from one shared directory into selected accounts.
|
|
51
51
|
|
|
52
|
-
##
|
|
52
|
+
## Prerequisites
|
|
53
53
|
|
|
54
|
-
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
**Servers.** None. multi-claude runs only on your own computer; its only network requests are the plan lookups of `list`, sent to Anthropic.
|
|
55
|
+
|
|
56
|
+
**Your computer.**
|
|
57
|
+
|
|
58
|
+
| | Needed | Optional |
|
|
59
|
+
| ---- | ---- | ---- |
|
|
60
|
+
| Operating system | macOS or Linux (WSL counts as Linux) | — |
|
|
61
|
+
| Tools | Python 3.8+ (`python3`, standard library only); Claude Code (`claude`); `curl` or `wget`, and `tar`, for the installer | `pipx` or Homebrew, to install from PyPI or the tap; `lsof`, so that `migrate-default` and `restore` can find processes using `~/.claude` (Linux falls back to `/proc`); VS Code's `code` command, for `multi-claude code` |
|
|
62
|
+
|
|
63
|
+
Install what is missing:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
# macOS (with Homebrew, https://brew.sh); curl, tar and lsof come with macOS
|
|
67
|
+
brew install python
|
|
68
|
+
curl -fsSL https://claude.ai/install.sh | bash # Claude Code, if you do not have it yet
|
|
69
|
+
|
|
70
|
+
# Debian / Ubuntu / WSL
|
|
71
|
+
sudo apt update
|
|
72
|
+
sudo apt install -y python3 curl tar lsof
|
|
73
|
+
curl -fsSL https://claude.ai/install.sh | bash # Claude Code, if you do not have it yet
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Windows itself is not supported yet; use WSL. Other ways to install Claude Code: https://code.claude.com/docs/en/setup
|
|
57
77
|
|
|
58
78
|
## Installation
|
|
59
79
|
|
|
@@ -180,6 +200,32 @@ Items that hold one account's own state cannot be shared: `.credentials.json`, `
|
|
|
180
200
|
|
|
181
201
|
**`skills/synced/`.** Claude Code stores skills synced from claude.ai in `skills/synced/`, one bucket per organization and account. If an account's `skills` is a real directory, turning sharing on is a conflict and multi-claude does not move anything. You may move the account's `skills/synced/<bucket>` into the shared directory's `skills/synced/` yourself: buckets of different accounts have different names and do not collide, but from then on that account's synced skills are written to the shared directory.
|
|
182
202
|
|
|
203
|
+
### Exporting and importing settings
|
|
204
|
+
|
|
205
|
+
```sh
|
|
206
|
+
multi-claude export work ~/work-settings.tar.gz # on this machine
|
|
207
|
+
multi-claude import ~/work-settings.tar.gz client # into another (existing) account, here or elsewhere
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
`export` writes `settings.json`, `CLAUDE.md`, `agents`, `commands`, `skills` and `output-styles` of the account, plus the MCP servers from its `.claude.json` (only the `mcpServers` entry), to a `.tar.gz` that only you can read. Logins, the rest of `.claude.json`, sessions, history and the plugin cache are never included. Items that are links (shared items) are skipped. If `settings.json` or the MCP servers contain values under names such as `API_KEY` or `Authorization`, `export` lists those names (not the values): treat the file like a password.
|
|
211
|
+
|
|
212
|
+
`import` copies the items into an account you created with `add`, and adds the MCP servers to its `.claude.json`. An item or MCP server that already exists with different content is a conflict: nothing is changed and the conflicts are listed. With `--force`, each one is first renamed to `<name>.multi-claude-bak.<timestamp>` and then replaced. An item that is a shared link is never replaced; turn sharing off for it first. `--dry-run` shows the plan. Restart running Claude sessions of the account after importing MCP servers; they keep their own copy of `.claude.json` and may overwrite the change.
|
|
213
|
+
|
|
214
|
+
Plugin choices travel in `settings.json` (`enabledPlugins`, `extraKnownMarketplaces`); Claude Code downloads the plugins again in the new account.
|
|
215
|
+
|
|
216
|
+
### Sharing MCP servers, plugins and settings
|
|
217
|
+
|
|
218
|
+
Shared links cover files and directories. For settings and MCP servers that every account should have, pass them on the command line of every launcher instead:
|
|
219
|
+
|
|
220
|
+
```sh
|
|
221
|
+
multi-claude args --defaults -- --mcp-config ~/.claude-shared/mcp.json --settings ~/.claude-shared/settings.json
|
|
222
|
+
multi-claude env --defaults CLAUDE_CODE_PLUGIN_CACHE_DIR=~/.claude-shared/plugins
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
- `--settings` is merged with each account's own `settings.json`: keys in the shared file win, other keys stay. Put `enabledPlugins`, `extraKnownMarketplaces`, `permissions` or `env` there.
|
|
226
|
+
- `--mcp-config` loads MCP servers from a JSON file (`{"mcpServers": {...}}`) in addition to each account's own. It takes several values, so keep another option after it (as `--settings` above); multi-claude warns otherwise.
|
|
227
|
+
- `CLAUDE_CODE_PLUGIN_CACHE_DIR` moves the plugins directory (marketplaces and the plugin cache), so plugins are downloaded once for all accounts.
|
|
228
|
+
|
|
183
229
|
### Choosing an account by directory
|
|
184
230
|
|
|
185
231
|
```sh
|
|
@@ -208,7 +254,7 @@ work 23% 14:00 41% Fri 12m ago
|
|
|
208
254
|
home - - no data (start claude-home once)
|
|
209
255
|
```
|
|
210
256
|
|
|
211
|
-
The numbers are the last values Claude Code itself cached in the account's `.claude.json` (for the default identity, `~/.claude.json`).
|
|
257
|
+
The numbers are the last values Claude Code itself cached in the account's `.claude.json` (for the default identity, `~/.claude.json`). `usage` never reads credentials and never calls the network, so the data can be old: `UPDATED` shows its age, and values older than an hour are marked `stale`. Claude Code writes this cache itself; when it refreshes it is not documented. A window whose reset time has passed shows `reset`.
|
|
212
258
|
|
|
213
259
|
For fresher numbers, let your status line record them. Claude Code passes the 5-hour and 7-day usage to the `statusLine` command each time it redraws the status line (Pro and Max plans, after the first response of a session). Wrap the `statusLine` command of the settings file that is actually in effect:
|
|
214
260
|
|
|
@@ -240,6 +286,22 @@ work:
|
|
|
240
286
|
|
|
241
287
|
`list` shows when each account was last used (`LAST USED`), from the newest session file or prompt history in its directory; a `handoff` into an account counts as use.
|
|
242
288
|
|
|
289
|
+
#### Plan and billing
|
|
290
|
+
|
|
291
|
+
```text
|
|
292
|
+
NAME LOGIN PLAN BILLING PROXY SHARED 5H 7D LAST USED STATUS
|
|
293
|
+
work keychain max (5x) stripe http://127.0.0.1:7890 no 23% 14:00 41% Fri 5m ago ok
|
|
294
|
+
home keychain pro apple inherit no - - 2d ago ok
|
|
295
|
+
old keychain expired - inherit no - - 9d ago ok
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
`PLAN` and `BILLING` are not cached values: every `list` asks Anthropic (`GET https://api.anthropic.com/api/oauth/profile`, the request Claude Code itself makes) with the account's own access token. `PLAN` is the subscription — `pro`, `max (5x)`, `max (20x)`, `team`, `enterprise`. `BILLING` is where the subscription is paid: `stripe` (claude.ai), `apple` (App Store), `google-play`, `aws-marketplace` and so on.
|
|
299
|
+
|
|
300
|
+
- The request uses the account's proxy setting, exactly like its launcher: the configured proxy, the proxy variables of your shell for `inherit`, none for `off`. If a proxy is configured and fails, the lookup fails; it never falls back to a direct connection. Only `http://` proxies work for the lookup.
|
|
301
|
+
- `expired` means the access token has run out. Tokens last a few hours and multi-claude never refreshes them (refreshing would compete with running sessions): start `claude-NAME` once and run `list` again. `-` means the account has no OAuth login, and `rejected` that the server refused the token.
|
|
302
|
+
- `error` comes with a reason on stderr, for example `plan lookup failed for work: timeout (via 127.0.0.1:7890, 10.01s)`. `tls_failed` usually means the Python that runs multi-claude has no root certificates (python.org installers ship an `Install Certificates.command`).
|
|
303
|
+
- `list --offline` skips the lookup — no token is read, nothing is sent — and prints the table without the two columns. `list --json` carries the same data in each account's `plan` object; scripts should use it instead of parsing the table. The lookup adds about a second, at most 15.
|
|
304
|
+
|
|
243
305
|
### Handing a session over to another account
|
|
244
306
|
|
|
245
307
|
Each account keeps its own sessions, so `claude --resume` in one account cannot see the sessions of another. `handoff` copies one session (its `.jsonl` file and the folder next to it with subagent transcripts and saved tool output) into the same project folder of another account:
|
|
@@ -374,7 +436,7 @@ By default the numbers come from the cache that Claude Code writes in `.claude.j
|
|
|
374
436
|
|
|
375
437
|
### Does multi-claude read or copy my login?
|
|
376
438
|
|
|
377
|
-
It never reads
|
|
439
|
+
It never writes, copies, exports, uploads, refreshes or backs up a login. One command reads one: `list` takes each account's access token to ask Anthropic for the account's plan (see [Plan and billing](#plan-and-billing)); the token stays in memory and is sent only to `api.anthropic.com`. `list --offline` does not read it. All other commands only check whether a login exists. `migrate-default` and `restore` move a whole account directory; on Linux the credentials file is inside it and moves with it (in copy mode it is copied as part of the directory, verified, and the original directory is then removed unless you pass `--keep-backup`), still without being opened. On macOS a login is tied to the account directory's path, which is why `rename` keeps the directory.
|
|
378
440
|
|
|
379
441
|
## Reference
|
|
380
442
|
|
|
@@ -385,6 +447,8 @@ It never reads it: its only keychain call checks whether an item exists, and it
|
|
|
385
447
|
| `multi-claude init [--root DIR] [--bin-dir DIR] [--shared-dir DIR] [--shared-items A,B]` | Create or change global settings. |
|
|
386
448
|
| `multi-claude migrate-default [NAME] [--copy] [--keep-backup] [--proxy P] [--skip-process-check]` | Turn `~/.claude` into an account. Without NAME, the email address of its login is used. |
|
|
387
449
|
| `multi-claude restore NAME [--skip-process-check] [--dry-run]` | Undo `migrate-default`: move the account back to `~/.claude` and unregister it. The login is kept. |
|
|
450
|
+
| `multi-claude export NAME FILE` | Write the account's settings, `CLAUDE.md`, agents, commands, skills, output styles and MCP servers to FILE. No logins or sessions. |
|
|
451
|
+
| `multi-claude import FILE NAME [--force] [--dry-run]` | Import such a file into an existing account; conflicts are refused unless `--force` (which backs up first). |
|
|
388
452
|
| `multi-claude add NAME [--proxy P] [--shared [DIR] \| --no-shared] [--adopt] [--shared-exclude ITEM] [--shared-include ITEM] [--config-from OTHER]` | Add an account, adopt an existing directory, or change its options. `--config-from` copies `settings.json` from OTHER once. `--shared DIR` also makes DIR the shared directory for every account (default `~/.claude-shared`). `--shared-exclude` keeps one shared item out of this account; `--shared-include` undoes it. |
|
|
389
453
|
| `multi-claude set NAME [--proxy P] [--shared [DIR] \| --no-shared] [--shared-exclude ITEM] [--shared-include ITEM]` | Change an existing account; same options as `add` without `--adopt`. Returns 1 for an account that is not registered. |
|
|
390
454
|
| `multi-claude proxy NAME PORT\|URL\|off\|inherit` | Set an account's proxy. |
|
|
@@ -392,7 +456,7 @@ It never reads it: its only keychain call checks whether an item exists, and it
|
|
|
392
456
|
| `multi-claude args (NAME \| --defaults) -- [ARG ...]` | Replace the fixed arguments; `--` with nothing after it clears them. |
|
|
393
457
|
| `multi-claude remove NAME` | Unregister an account and delete its launcher. **The directory and the login are kept.** |
|
|
394
458
|
| `multi-claude apply [-f FILE]` | Converge everything to the configuration (or to `FILE`). |
|
|
395
|
-
| `multi-claude list [--verbose \| --json \| --names]` | Show accounts, launchers and
|
|
459
|
+
| `multi-claude list [--verbose \| --json \| --names] [--offline]` | Show accounts, launchers, login state and the plan and billing channel looked up from Anthropic. `--json` adds usage and is meant for scripts; `--names` prints only the names; `--offline` skips the plan lookup (no token read, no network). |
|
|
396
460
|
| `multi-claude usage [NAME] [--json]` | Show the last known 5-hour and 7-day usage of each account. |
|
|
397
461
|
| `multi-claude usage --history [NAME] [--days N] [--by day\|model] [--json]` | Token usage per day or model, counted from the session files on this machine (default: 7 days). |
|
|
398
462
|
| `multi-claude doctor [--json] [--verbose]` | Check the configuration, launchers, account directories, shared links, logins and environment. |
|