multi-claude-cli 0.4.0__tar.gz → 0.6.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.
Files changed (56) hide show
  1. {multi_claude_cli-0.4.0/src/multi_claude_cli.egg-info → multi_claude_cli-0.6.0}/PKG-INFO +47 -8
  2. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/README.md +46 -7
  3. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/__init__.py +1 -1
  4. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/cli.py +285 -13
  5. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/completion.py +2 -1
  6. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/migrate.py +9 -6
  7. multi_claude_cli-0.6.0/src/multi_claude/restore.py +149 -0
  8. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0/src/multi_claude_cli.egg-info}/PKG-INFO +47 -8
  9. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude_cli.egg-info/SOURCES.txt +4 -1
  10. multi_claude_cli-0.6.0/tests/test_everyday.py +340 -0
  11. multi_claude_cli-0.6.0/tests/test_vscode.py +127 -0
  12. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/LICENSE +0 -0
  13. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/pyproject.toml +0 -0
  14. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/setup.cfg +0 -0
  15. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/__main__.py +0 -0
  16. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/accounts.py +0 -0
  17. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/actions.py +0 -0
  18. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/config.py +0 -0
  19. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/doctor.py +0 -0
  20. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/env.py +0 -0
  21. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/fsutil.py +0 -0
  22. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/hook.py +0 -0
  23. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/identity.py +0 -0
  24. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/launcher.py +0 -0
  25. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/lock.py +0 -0
  26. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/platform.py +0 -0
  27. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/routes.py +0 -0
  28. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/sessions.py +0 -0
  29. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/shared.py +0 -0
  30. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/shellpath.py +0 -0
  31. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/statusline.py +0 -0
  32. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude/usage.py +0 -0
  33. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude_cli.egg-info/dependency_links.txt +0 -0
  34. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude_cli.egg-info/entry_points.txt +0 -0
  35. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/src/multi_claude_cli.egg-info/top_level.txt +0 -0
  36. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_accounts.py +0 -0
  37. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_completion.py +0 -0
  38. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_config.py +0 -0
  39. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_doctor.py +0 -0
  40. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_fsutil.py +0 -0
  41. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_handoff.py +0 -0
  42. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_help.py +0 -0
  43. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_identity.py +0 -0
  44. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_install.py +0 -0
  45. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_mcp.py +0 -0
  46. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_migrate.py +0 -0
  47. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_onboarding.py +0 -0
  48. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_packaging.py +0 -0
  49. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_platform.py +0 -0
  50. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_rename.py +0 -0
  51. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_routes.py +0 -0
  52. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_set.py +0 -0
  53. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_shared_exclude.py +0 -0
  54. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_statusline.py +0 -0
  55. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_usability.py +0 -0
  56. {multi_claude_cli-0.4.0 → multi_claude_cli-0.6.0}/tests/test_usage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: multi-claude-cli
3
- Version: 0.4.0
3
+ Version: 0.6.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
@@ -31,6 +31,7 @@ Dynamic: license-file
31
31
 
32
32
  [![Release](https://img.shields.io/github/v/release/jakoes-wu/multi-claude)](https://github.com/jakoes-wu/multi-claude/releases)
33
33
  [![CI](https://github.com/jakoes-wu/multi-claude/actions/workflows/ci.yml/badge.svg)](https://github.com/jakoes-wu/multi-claude/actions/workflows/ci.yml)
34
+ [![PyPI](https://img.shields.io/pypi/v/multi-claude-cli)](https://pypi.org/project/multi-claude-cli/)
34
35
  ![Python](https://img.shields.io/badge/python-3.8%2B-blue)
35
36
  [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
36
37
 
@@ -96,7 +97,9 @@ The tool goes to `~/.local/share/multi-claude` and the `multi-claude` command to
96
97
 
97
98
  The `multi-claude` command runs with the `python3` found on `PATH` at install time. If that is a version-manager shim (pyenv, asdf, mise), the installer writes the interpreter behind it instead: a shim adds tens of milliseconds to every start, and with the statusline hook installed that happens on every status-line redraw. Run the installer again after removing that Python version.
98
99
 
99
- Alternatively: `pipx install git+https://github.com/jakoes-wu/multi-claude`.
100
+ Alternatively, from PyPI: `pipx install multi-claude-cli` (upgrade with `pipx upgrade multi-claude-cli`). The command is still `multi-claude`. Use either pipx or the installer, not both: they put the same command in `~/.local/bin`.
101
+
102
+ With Homebrew: `brew install jakoes-wu/tap/multi-claude` (upgrade with `brew upgrade multi-claude`). It installs into Homebrew's own prefix, so remove other installations first to avoid two `multi-claude` commands on your `PATH`.
100
103
 
101
104
  **Verified downloads.** From v0.4.0 on, every release publishes `multi-claude-<tag>.tar.gz` and `SHA256SUMS`. The remote installer downloads that archive and checks its SHA-256 before installing anything; a mismatch stops the installation. Branches and older releases are installed unverified (the installer says so); set `MULTI_CLAUDE_REQUIRE_CHECKSUM=1` to refuse them. The checksum is published next to the archive, so it protects against a damaged or altered download, not against a compromised GitHub account.
102
105
 
@@ -269,6 +272,36 @@ multi-claude mcp client-a list
269
272
 
270
273
  `mcp` runs `claude mcp ...` with the account's configuration directory, proxy and extra environment variables, but without its fixed arguments (options such as `--allowedTools` would otherwise swallow the `mcp` subcommand). Claude Code itself writes the server configuration. Use `--scope user` for a server that should be available in every project of that account.
271
274
 
275
+ ### Running other commands as an account
276
+
277
+ ```sh
278
+ multi-claude run work -- claude --version # any command, with exactly the environment of claude-work
279
+ multi-claude run work # same as claude-work
280
+ multi-claude run -- env # without NAME: the account claude-auto would use here
281
+ cd "$(multi-claude path work)" # the account's directory
282
+ multi-claude add client-b --config-from work # start client-b with a copy of work's settings.json
283
+ ```
284
+
285
+ `run` sets the same `CLAUDE_CONFIG_DIR`, proxy and extra variables as the launcher; everything after the first `--` is run unchanged and its exit code is returned. Without a command it runs `claude` with the account's fixed arguments. Without NAME it follows the routes of `claude-auto` and prints the chosen account on stderr; with no route and no default it asks for NAME. `path` exits with 1 if the directory is missing.
286
+
287
+ `--config-from` copies `settings.json` once; afterwards the two files are independent. A different existing `settings.json` in the new account, or a `settings.json` that the account shares, is a conflict and nothing is changed. Use [shared resources](#shared-resources) for settings that should stay the same in every account.
288
+
289
+ ### Opening VS Code for an account (experimental)
290
+
291
+ ```sh
292
+ multi-claude code work ~/projects/app # a separate VS Code window for work
293
+ multi-claude code personal . -- --disable-gpu # arguments after -- go to VS Code
294
+ ```
295
+
296
+ The Claude Code extension uses the `CLAUDE_CONFIG_DIR` of the environment VS Code was started with, so a VS Code opened from the Dock always uses `~/.claude`. `code` starts VS Code with the account's environment (the same as `run`) and a separate user data directory, `<root>/.apps/<account directory>/vscode`. A separate user data directory is required: otherwise VS Code hands the request to the instance that is already running, with its own environment. Each account's instance starts with default VS Code settings; extensions are shared because they live in `~/.vscode/extensions`.
297
+
298
+ Notes:
299
+
300
+ - If an instance for the account is already running, the request goes to it; changes to the proxy or environment variables apply after that instance quits.
301
+ - Setting `CLAUDE_CONFIG_DIR` in the extension's `claudeCode.environmentVariables` inside that instance overrides the account.
302
+ - On macOS the `code` command passes the whole environment to `open --env`, so the values are briefly visible in the process list.
303
+ - Verified with VS Code 1.139.1 and Claude Code extension 2.1.286 on macOS; `code` prints a warning because it relies on undocumented behaviour. It needs the `code` command on `PATH` (in VS Code: "Shell Command: Install 'code' command in PATH").
304
+
272
305
  ### Diagnostics and completion
273
306
 
274
307
  `multi-claude doctor` checks, without changing anything: the configuration and any unfinished migration, whether `claude` and the launcher directory are on `PATH`, whether each launcher is up to date and not hidden by another file of the same name, whether each account directory exists and is private (`0700`), the default account's link, broken shared links, whether a login exists, and variables such as `ANTHROPIC_API_KEY` that override the accounts' logins. Every problem comes with the command that fixes it. It exits with 1 when there is an error; `--json` prints the results for scripts.
@@ -283,7 +316,7 @@ multi-claude completion fish > ~/.config/fish/completions/multi-claude.fish
283
316
 
284
317
  The default account is made of three parts that Claude Code finds only when `CLAUDE_CONFIG_DIR` is **not** set: the directory `~/.claude`, the file `~/.claude.json`, and (on macOS) the keychain item `Claude Code-credentials`. On macOS, the keychain item of every other account is tied to the exact path string in `CLAUDE_CONFIG_DIR`, so the default account cannot simply be pointed at a new path.
285
318
 
286
- `multi-claude migrate-default main` therefore:
319
+ `multi-claude migrate-default main` therefore (without a name it uses the email address of the login in `~/.claude.json`):
287
320
 
288
321
  1. moves `~/.claude` to `~/.cc/main` (rename on the same file system; otherwise copy, verify every file by SHA-256, and park the original as `~/.claude.multi-claude-bak.<timestamp>`);
289
322
  2. leaves the link `~/.claude -> ~/.cc/main`;
@@ -308,6 +341,8 @@ Sockets and FIFOs are not copied in copy mode. On macOS, copy mode does not pres
308
341
 
309
342
  ### Undoing a migration by hand
310
343
 
344
+ `multi-claude restore main` undoes the migration: it removes the link, moves `~/.cc/main` back to `~/.claude` and unregisters the account (its launcher is deleted; shared links inside the directory stay). It checks for running Claude Code sessions like `migrate-default` (`--skip-process-check` skips that) and can be run again if it is interrupted. It refuses, without changing anything, when a route still uses the account, when `~/.claude` points elsewhere, or when the two directories are on different file systems. By hand, the same steps are:
345
+
311
346
  ```sh
312
347
  rm ~/.claude # remove the link (only the link)
313
348
  mv ~/.cc/main ~/.claude # move the data back
@@ -322,7 +357,7 @@ If a migration stops with an error and you want to abandon it: the error message
322
357
 
323
358
  ### How do I upgrade multi-claude?
324
359
 
325
- Run the installer again: `curl -fsSL https://raw.githubusercontent.com/jakoes-wu/multi-claude/main/install.sh | sh`, or `./install.sh` from an updated clone. It replaces only the tool; your configuration, accounts and launchers stay. When a release changes what launchers contain, `multi-claude doctor` reports them as stale and `multi-claude apply` rewrites them.
360
+ With pipx, run `pipx upgrade multi-claude-cli`; with Homebrew, `brew upgrade multi-claude`. Otherwise run the installer again: `curl -fsSL https://raw.githubusercontent.com/jakoes-wu/multi-claude/main/install.sh | sh`, or `./install.sh` from an updated clone. It replaces only the tool; your configuration, accounts and launchers stay. When a release changes what launchers contain, `multi-claude doctor` reports them as stale and `multi-claude apply` rewrites them.
326
361
 
327
362
  ### Which account does plain `claude` use?
328
363
 
@@ -351,8 +386,9 @@ No. It never reads, copies or deletes credentials; its only keychain call checks
351
386
  | Command | What it does |
352
387
  | ---- | ---- |
353
388
  | `multi-claude init [--root DIR] [--bin-dir DIR] [--shared-dir DIR] [--shared-items A,B]` | Create or change global settings. |
354
- | `multi-claude migrate-default NAME [--copy] [--keep-backup] [--proxy P] [--skip-process-check]` | Turn `~/.claude` into an account. |
355
- | `multi-claude add NAME [--proxy P] [--shared [DIR] \| --no-shared] [--adopt] [--shared-exclude ITEM] [--shared-include ITEM]` | Add an account, adopt an existing directory, or change its options. `--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
+ | `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. |
390
+ | `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. |
391
+ | `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. |
356
392
  | `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. |
357
393
  | `multi-claude proxy NAME PORT\|URL\|off\|inherit` | Set an account's proxy. |
358
394
  | `multi-claude env (NAME \| --defaults) [K=V ...] [--unset K ...]` | Set or remove extra environment variables. |
@@ -367,6 +403,9 @@ No. It never reads, copies or deletes credentials; its only keychain call checks
367
403
  | `multi-claude rename OLD NEW` | Rename an account and its launcher. The directory and the login stay. |
368
404
  | `multi-claude login NAME [ARG ...]` | Sign in to that account (runs `claude auth login ARG ...` as it; an e-mail-like name is pre-filled with `--email`). |
369
405
  | `multi-claude mcp NAME [ARG ...]` | Run `claude mcp ARG ...` as that account. |
406
+ | `multi-claude run [NAME] [-- COMMAND ...]` | Run a command (default: `claude` with the fixed arguments) with the environment of the account's launcher. Without NAME, the account `claude-auto` would use. |
407
+ | `multi-claude path NAME` | Print the account's directory. |
408
+ | `multi-claude code NAME [PATH] [-- ARGS ...]` | Open a separate VS Code instance with the account's environment (experimental). |
370
409
  | `multi-claude handoff TARGET [--from NAME] [--session ID] [--force]` | Copy a session to another account and print the command that resumes it there. |
371
410
  | `multi-claude statusline install\|uninstall FILE` | Wrap the statusLine command in a settings file so that `usage` gets fresh numbers, or restore it. |
372
411
  | `multi-claude completion bash\|zsh\|fish` | Print a shell completion script. |
@@ -434,7 +473,7 @@ If you move an account directory yourself, its launcher reports that the directo
434
473
  | 1 | Runtime error (I/O, invalid configuration file, failed verification, lock held by another command, account not registered) |
435
474
  | 2 | Invalid command-line arguments |
436
475
  | 3 | Conflict with files multi-claude does not own, or a change that would break a login; nothing was changed |
437
- | 4 | The migration source is in use |
476
+ | 4 | The directory to migrate or restore is in use |
438
477
 
439
478
  ## Uninstalling
440
479
 
@@ -442,7 +481,7 @@ If you move an account directory yourself, its launcher reports that the directo
442
481
  ./install.sh --uninstall
443
482
  ```
444
483
 
445
- This removes the tool only. Your configuration, account directories, logins and `claude-<name>` launchers stay; the launchers keep working because they do not depend on multi-claude. Run `multi-claude statusline uninstall FILE` first if you wrapped a status line.
484
+ This removes the tool only. Your configuration, account directories (including the VS Code data in `<root>/.apps` created by `code`), logins and `claude-<name>` launchers stay; the launchers keep working because they do not depend on multi-claude. Run `multi-claude statusline uninstall FILE` first if you wrapped a status line.
446
485
 
447
486
  ## Contributing
448
487
 
@@ -4,6 +4,7 @@
4
4
 
5
5
  [![Release](https://img.shields.io/github/v/release/jakoes-wu/multi-claude)](https://github.com/jakoes-wu/multi-claude/releases)
6
6
  [![CI](https://github.com/jakoes-wu/multi-claude/actions/workflows/ci.yml/badge.svg)](https://github.com/jakoes-wu/multi-claude/actions/workflows/ci.yml)
7
+ [![PyPI](https://img.shields.io/pypi/v/multi-claude-cli)](https://pypi.org/project/multi-claude-cli/)
7
8
  ![Python](https://img.shields.io/badge/python-3.8%2B-blue)
8
9
  [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
9
10
 
@@ -69,7 +70,9 @@ The tool goes to `~/.local/share/multi-claude` and the `multi-claude` command to
69
70
 
70
71
  The `multi-claude` command runs with the `python3` found on `PATH` at install time. If that is a version-manager shim (pyenv, asdf, mise), the installer writes the interpreter behind it instead: a shim adds tens of milliseconds to every start, and with the statusline hook installed that happens on every status-line redraw. Run the installer again after removing that Python version.
71
72
 
72
- Alternatively: `pipx install git+https://github.com/jakoes-wu/multi-claude`.
73
+ Alternatively, from PyPI: `pipx install multi-claude-cli` (upgrade with `pipx upgrade multi-claude-cli`). The command is still `multi-claude`. Use either pipx or the installer, not both: they put the same command in `~/.local/bin`.
74
+
75
+ With Homebrew: `brew install jakoes-wu/tap/multi-claude` (upgrade with `brew upgrade multi-claude`). It installs into Homebrew's own prefix, so remove other installations first to avoid two `multi-claude` commands on your `PATH`.
73
76
 
74
77
  **Verified downloads.** From v0.4.0 on, every release publishes `multi-claude-<tag>.tar.gz` and `SHA256SUMS`. The remote installer downloads that archive and checks its SHA-256 before installing anything; a mismatch stops the installation. Branches and older releases are installed unverified (the installer says so); set `MULTI_CLAUDE_REQUIRE_CHECKSUM=1` to refuse them. The checksum is published next to the archive, so it protects against a damaged or altered download, not against a compromised GitHub account.
75
78
 
@@ -242,6 +245,36 @@ multi-claude mcp client-a list
242
245
 
243
246
  `mcp` runs `claude mcp ...` with the account's configuration directory, proxy and extra environment variables, but without its fixed arguments (options such as `--allowedTools` would otherwise swallow the `mcp` subcommand). Claude Code itself writes the server configuration. Use `--scope user` for a server that should be available in every project of that account.
244
247
 
248
+ ### Running other commands as an account
249
+
250
+ ```sh
251
+ multi-claude run work -- claude --version # any command, with exactly the environment of claude-work
252
+ multi-claude run work # same as claude-work
253
+ multi-claude run -- env # without NAME: the account claude-auto would use here
254
+ cd "$(multi-claude path work)" # the account's directory
255
+ multi-claude add client-b --config-from work # start client-b with a copy of work's settings.json
256
+ ```
257
+
258
+ `run` sets the same `CLAUDE_CONFIG_DIR`, proxy and extra variables as the launcher; everything after the first `--` is run unchanged and its exit code is returned. Without a command it runs `claude` with the account's fixed arguments. Without NAME it follows the routes of `claude-auto` and prints the chosen account on stderr; with no route and no default it asks for NAME. `path` exits with 1 if the directory is missing.
259
+
260
+ `--config-from` copies `settings.json` once; afterwards the two files are independent. A different existing `settings.json` in the new account, or a `settings.json` that the account shares, is a conflict and nothing is changed. Use [shared resources](#shared-resources) for settings that should stay the same in every account.
261
+
262
+ ### Opening VS Code for an account (experimental)
263
+
264
+ ```sh
265
+ multi-claude code work ~/projects/app # a separate VS Code window for work
266
+ multi-claude code personal . -- --disable-gpu # arguments after -- go to VS Code
267
+ ```
268
+
269
+ The Claude Code extension uses the `CLAUDE_CONFIG_DIR` of the environment VS Code was started with, so a VS Code opened from the Dock always uses `~/.claude`. `code` starts VS Code with the account's environment (the same as `run`) and a separate user data directory, `<root>/.apps/<account directory>/vscode`. A separate user data directory is required: otherwise VS Code hands the request to the instance that is already running, with its own environment. Each account's instance starts with default VS Code settings; extensions are shared because they live in `~/.vscode/extensions`.
270
+
271
+ Notes:
272
+
273
+ - If an instance for the account is already running, the request goes to it; changes to the proxy or environment variables apply after that instance quits.
274
+ - Setting `CLAUDE_CONFIG_DIR` in the extension's `claudeCode.environmentVariables` inside that instance overrides the account.
275
+ - On macOS the `code` command passes the whole environment to `open --env`, so the values are briefly visible in the process list.
276
+ - Verified with VS Code 1.139.1 and Claude Code extension 2.1.286 on macOS; `code` prints a warning because it relies on undocumented behaviour. It needs the `code` command on `PATH` (in VS Code: "Shell Command: Install 'code' command in PATH").
277
+
245
278
  ### Diagnostics and completion
246
279
 
247
280
  `multi-claude doctor` checks, without changing anything: the configuration and any unfinished migration, whether `claude` and the launcher directory are on `PATH`, whether each launcher is up to date and not hidden by another file of the same name, whether each account directory exists and is private (`0700`), the default account's link, broken shared links, whether a login exists, and variables such as `ANTHROPIC_API_KEY` that override the accounts' logins. Every problem comes with the command that fixes it. It exits with 1 when there is an error; `--json` prints the results for scripts.
@@ -256,7 +289,7 @@ multi-claude completion fish > ~/.config/fish/completions/multi-claude.fish
256
289
 
257
290
  The default account is made of three parts that Claude Code finds only when `CLAUDE_CONFIG_DIR` is **not** set: the directory `~/.claude`, the file `~/.claude.json`, and (on macOS) the keychain item `Claude Code-credentials`. On macOS, the keychain item of every other account is tied to the exact path string in `CLAUDE_CONFIG_DIR`, so the default account cannot simply be pointed at a new path.
258
291
 
259
- `multi-claude migrate-default main` therefore:
292
+ `multi-claude migrate-default main` therefore (without a name it uses the email address of the login in `~/.claude.json`):
260
293
 
261
294
  1. moves `~/.claude` to `~/.cc/main` (rename on the same file system; otherwise copy, verify every file by SHA-256, and park the original as `~/.claude.multi-claude-bak.<timestamp>`);
262
295
  2. leaves the link `~/.claude -> ~/.cc/main`;
@@ -281,6 +314,8 @@ Sockets and FIFOs are not copied in copy mode. On macOS, copy mode does not pres
281
314
 
282
315
  ### Undoing a migration by hand
283
316
 
317
+ `multi-claude restore main` undoes the migration: it removes the link, moves `~/.cc/main` back to `~/.claude` and unregisters the account (its launcher is deleted; shared links inside the directory stay). It checks for running Claude Code sessions like `migrate-default` (`--skip-process-check` skips that) and can be run again if it is interrupted. It refuses, without changing anything, when a route still uses the account, when `~/.claude` points elsewhere, or when the two directories are on different file systems. By hand, the same steps are:
318
+
284
319
  ```sh
285
320
  rm ~/.claude # remove the link (only the link)
286
321
  mv ~/.cc/main ~/.claude # move the data back
@@ -295,7 +330,7 @@ If a migration stops with an error and you want to abandon it: the error message
295
330
 
296
331
  ### How do I upgrade multi-claude?
297
332
 
298
- Run the installer again: `curl -fsSL https://raw.githubusercontent.com/jakoes-wu/multi-claude/main/install.sh | sh`, or `./install.sh` from an updated clone. It replaces only the tool; your configuration, accounts and launchers stay. When a release changes what launchers contain, `multi-claude doctor` reports them as stale and `multi-claude apply` rewrites them.
333
+ With pipx, run `pipx upgrade multi-claude-cli`; with Homebrew, `brew upgrade multi-claude`. Otherwise run the installer again: `curl -fsSL https://raw.githubusercontent.com/jakoes-wu/multi-claude/main/install.sh | sh`, or `./install.sh` from an updated clone. It replaces only the tool; your configuration, accounts and launchers stay. When a release changes what launchers contain, `multi-claude doctor` reports them as stale and `multi-claude apply` rewrites them.
299
334
 
300
335
  ### Which account does plain `claude` use?
301
336
 
@@ -324,8 +359,9 @@ No. It never reads, copies or deletes credentials; its only keychain call checks
324
359
  | Command | What it does |
325
360
  | ---- | ---- |
326
361
  | `multi-claude init [--root DIR] [--bin-dir DIR] [--shared-dir DIR] [--shared-items A,B]` | Create or change global settings. |
327
- | `multi-claude migrate-default NAME [--copy] [--keep-backup] [--proxy P] [--skip-process-check]` | Turn `~/.claude` into an account. |
328
- | `multi-claude add NAME [--proxy P] [--shared [DIR] \| --no-shared] [--adopt] [--shared-exclude ITEM] [--shared-include ITEM]` | Add an account, adopt an existing directory, or change its options. `--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. |
362
+ | `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. |
363
+ | `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. |
364
+ | `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. |
329
365
  | `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. |
330
366
  | `multi-claude proxy NAME PORT\|URL\|off\|inherit` | Set an account's proxy. |
331
367
  | `multi-claude env (NAME \| --defaults) [K=V ...] [--unset K ...]` | Set or remove extra environment variables. |
@@ -340,6 +376,9 @@ No. It never reads, copies or deletes credentials; its only keychain call checks
340
376
  | `multi-claude rename OLD NEW` | Rename an account and its launcher. The directory and the login stay. |
341
377
  | `multi-claude login NAME [ARG ...]` | Sign in to that account (runs `claude auth login ARG ...` as it; an e-mail-like name is pre-filled with `--email`). |
342
378
  | `multi-claude mcp NAME [ARG ...]` | Run `claude mcp ARG ...` as that account. |
379
+ | `multi-claude run [NAME] [-- COMMAND ...]` | Run a command (default: `claude` with the fixed arguments) with the environment of the account's launcher. Without NAME, the account `claude-auto` would use. |
380
+ | `multi-claude path NAME` | Print the account's directory. |
381
+ | `multi-claude code NAME [PATH] [-- ARGS ...]` | Open a separate VS Code instance with the account's environment (experimental). |
343
382
  | `multi-claude handoff TARGET [--from NAME] [--session ID] [--force]` | Copy a session to another account and print the command that resumes it there. |
344
383
  | `multi-claude statusline install\|uninstall FILE` | Wrap the statusLine command in a settings file so that `usage` gets fresh numbers, or restore it. |
345
384
  | `multi-claude completion bash\|zsh\|fish` | Print a shell completion script. |
@@ -407,7 +446,7 @@ If you move an account directory yourself, its launcher reports that the directo
407
446
  | 1 | Runtime error (I/O, invalid configuration file, failed verification, lock held by another command, account not registered) |
408
447
  | 2 | Invalid command-line arguments |
409
448
  | 3 | Conflict with files multi-claude does not own, or a change that would break a login; nothing was changed |
410
- | 4 | The migration source is in use |
449
+ | 4 | The directory to migrate or restore is in use |
411
450
 
412
451
  ## Uninstalling
413
452
 
@@ -415,7 +454,7 @@ If you move an account directory yourself, its launcher reports that the directo
415
454
  ./install.sh --uninstall
416
455
  ```
417
456
 
418
- This removes the tool only. Your configuration, account directories, logins and `claude-<name>` launchers stay; the launchers keep working because they do not depend on multi-claude. Run `multi-claude statusline uninstall FILE` first if you wrapped a status line.
457
+ This removes the tool only. Your configuration, account directories (including the VS Code data in `<root>/.apps` created by `code`), logins and `claude-<name>` launchers stay; the launchers keep working because they do not depend on multi-claude. Run `multi-claude statusline uninstall FILE` first if you wrapped a status line.
419
458
 
420
459
  ## Contributing
421
460
 
@@ -1,3 +1,3 @@
1
1
  """multi-claude:管理多个 Claude Code 账号的配置目录、启动命令、代理与启动参数。"""
2
2
 
3
- __version__ = "0.4.0"
3
+ __version__ = "0.6.0"