New
Apps 848Makers 847This week 848
Promote your app−30%
multi-claude screenshot 1
1views in
the last 30 days

multi-claude

multi-claude allows you to run multiple Claude desktop apps, use the Claude desktop app (in code...

Built with Claude Code

by webb-ventures · from AUAustralia · added Oct 29, 2026
no ratings0 comments

Small tools for running Claude Code through your own inference gateway and opening multiple Claude Desktop profiles on one Mac.

  • start-cc.sh launches the installed Claude Code CLI through a gateway.
  • claude_code_proxy.py configures Desktop's local Code sessions only to use the gateway, while Desktop keeps its normal account interface and Chat/Cowork routing.
  • claude_profiles.py builds named, colour-coded .app launchers or optional full runtime copies with separate Desktop account data and, by default, separate Claude Code configuration.

The default launcher mode opens the same, untouched /Applications/Claude.app; reopening a launcher uses the current installed version. Optional copy mode creates an independent, modified runtime app with its own running Dock icon/name. Copies are locally ad-hoc signed, not vendor signed or notarized, and need refreshing after the original is updated. Neither mode modifies the original installation.

Thanks to CLIProxyAPI. Its gateway and provider integrations make this workflow possible. Please visit the upstream project for proxy installation, supported providers, authentication, configuration, and troubleshooting.

This is an unofficial toolkit, not an Anthropic or CLIProxyAPI product. It does not include Claude Desktop, Claude Code, a proxy server, provider credentials, or subscription entitlements.

Important limits up front

  • Separate Desktop profiles mean separate browser data/cookie stores, not separate macOS users or independently isolated Keychains. Native services, hardware credentials, and browser-based SSO can remain shared.
  • In default launcher mode, names and coloured icons identify the launcher apps in Finder and pinned shortcuts; the running vendor app retains its normal Claude Dock/menu identity. Copy mode changes the copied app's running Dock icon/name, without changing the original vendor bundle.
  • Copy signing removes vendor-only team identity, protected Keychain access groups and app groups, while retaining ordinary runtime/JIT/capability entitlements. SSO, passkeys, hardware-key authentication and features needing those protected groups are not guaranteed to work. Copy mode is not a separate macOS user or an independent Keychain/security boundary. Copy builds refuse known device-managed Claude preference files rather than changing the bundle identity around them.
  • The Desktop corporate-launcher hook deliberately withholds Desktop inference credentials from the Code engine. The engine uses gateway authentication. Remote Control and other first-party-authenticated engine services are not preserved by this route; the native launcher disables fast mode.
  • The normal Desktop model picker is unchanged. A gateway must accept/map the Claude model IDs and helper-model requests Desktop sends. Arbitrary models advertised by a gateway are not automatically added to Desktop's picker.
  • Relocating Desktop's user-data directory disables its local-pairing feature in the examined build. SSH and cloud Code sessions are not configured here.
  • Complete separate-account sign-in, native OAuth/deep-link callback routing, every provider/model feature, and updater-triggered profile relaunch have not been verified. Test your own accounts before relying on this setup.

Requirements

For the CLI launcher:

  • Python 3.10+ and a POSIX shell, on macOS or Linux.
  • Claude Code installed and available as claude on PATH.
  • A gateway implementing Anthropic's Messages API, including streaming and tool use. The Desktop preflight also requires GET /v1/models.

For Desktop proxy/profile tools:

  • macOS and the normal Claude Desktop installation at /Applications/Claude.app.

  • A Desktop build supporting claudeCodeProcessWrapperEnabled in first-party mode. The hook is present but public-undocumented in the examined builds; future updates can change it.

  • Administrator access for the optional Desktop proxy installer. The profile builder runs as your normal user and needs write access to /Applications; use --apps-dir "$HOME/Applications" if that directory is not writable. Do not run the whole builder with sudo.

  • Xcode or Xcode Command Line Tools for profile icon/launcher compilation:

    xcode-select --install
    xcrun --find swiftc
    

Python uses only the standard library. The launcher builder uses the system Swift, AppKit, iconutil, and codesign tools. Generated wrappers and runtime copies are locally ad-hoc signed; the original Claude app is never re-signed.

1. Set up your proxy and private configuration

Install and configure CLIProxyAPI (or another compatible gateway) first. Obtain its client inference API key. A management/admin key is separate and is not required by these tools.

From your checkout:

mkdir -p "$HOME/.config/multi-claude"
chmod 700 "$HOME/.config/multi-claude"
cp config.example.json "$HOME/.config/multi-claude/config.json"
chmod 600 "$HOME/.config/multi-claude/config.json"

Edit that file with your gateway URL and actual client API key:

{
  "gateway_urls": [
    "http://localhost:8317/"
  ],
  "gateway_token": "REPLACE_WITH_YOUR_GATEWAY_TOKEN"
}

The placeholder is intentionally rejected until replaced. Never commit your real key. Prefer this outside-the-repository file for apps launched from Finder, which normally do not inherit terminal exports.

Optional fallback gateways are listed after the primary:

{
  "gateway_urls": [
    "https://primary.example.com/",
    "https://backup.example.com/"
  ],
  "gateway_token": "REPLACE_WITH_YOUR_GATEWAY_TOKEN"
}

Use gateways accepting the same API key. Selection tries credential-free TCP connections in order, then uses the first reachable endpoint. This is startup reachability failover, not mid-generation failover or a guarantee of switching on HTTP authentication/model errors. If none is reachable, the wrapper fails; it does not fall back to Anthropic inference.

Configuration precedence:

  1. An explicit --config /absolute/path/config.json argument where supported.
  2. MULTI_CLAUDE_CONFIG.
  3. An ignored config.local.json next to the scripts, if present.
  4. ~/.config/multi-claude/config.json.

MULTI_CLAUDE_GATEWAY_URL and MULTI_CLAUDE_GATEWAY_TOKEN override their JSON values. Environment-only configuration works for terminal use, but an installed Desktop launcher should use a persistent private JSON file. Do not put credentials in command-line arguments.

Remote gateways require HTTPS. Plain HTTP is accepted only for loopback addresses or .ts.net hosts intended for an encrypted Tailscale network. Connect your VPN or tailnet yourself; these tools do not log in to it or change its configuration. Configuration is parsed as JSON, never sourced as shell code.

2. Use the Claude Code CLI

./start-cc.sh
./start-cc.sh /path/to/project --model claude-opus-5-5
./start-cc.sh --dir "/path/with spaces" --resume
./start-cc.sh --config /absolute/path/config.json mcp list

The wrapper sets the gateway address/authentication in the child environment, not in command-line arguments or committed Claude settings. Claude flags and subcommands are otherwise forwarded. Use a model your gateway actually serves.

Your existing CLAUDE_CONFIG_DIR is retained. To choose a particular directory for this standalone CLI wrapper, optionally add:

"cli_config_dir": "/absolute/path/to/your/claude-config"

This option does not override the Desktop profile launchers' individual Code config directories.

Remote Control: this public launcher intentionally refuses --rc, --remote-control, and the Remote Control subcommand. It does not ship the private forward-proxy/certificate lane used by some custom setups, and never silently changes to direct subscription inference to make RC work.

3. Route normal Desktop's local Code sessions through the proxy

Run these commands as your normal user, from a checkout that will stay at its current location:

python3 -I claude_code_proxy.py check

The check validates the app/configuration and authenticates a Models API request. It does not generate inference or prove a live Desktop session is routed.

Finish active work and quit all Claude Desktop instances, then:

python3 -I claude_code_proxy.py install

The installer requests sudo only for the managed-policy step. Do not run the whole installer as root. It:

  1. Merges processWrapper into /Library/Application Support/ClaudeCode/managed-settings.json.
  2. Creates/selects a minimal local configuration-library entry containing only claudeCodeProcessWrapperEnabled: true, under ~/Library/Application Support/Claude-3p/configLibrary/.
  3. Records enough state to remove its own changes safely.

Despite the Claude-3p directory name, the minimal entry has no inference provider and keeps Desktop in normal first-party mode. Original configuration entries remain intact. Existing managed wrappers, incompatible authentication policy, device-managed deployments, and active local profiles with additional settings are not silently overwritten.

The managed launcher declaration is machine-wide. This installer is intended for a user-controlled Mac, not an unreviewed multi-user or corporate fleet rollout. Consult your administrator if device policy already controls your installation.

Open Claude normally, sign in, and start a new Code → Local session. Desktop launches its own selected Code executable through the wrapper; the wrapper never substitutes an unrelated claude version from PATH. Chat and Cowork are not routed by this hook. Desktop account switching does not switch the gateway key; inference continues to use your configured gateway.

Check installed state:

python3 -I claude_code_proxy.py status

status verifies installed settings, not a particular completed request. To verify actual routing, correlate a new local Code prompt with gateway request logs, or inspect that engine's gateway environment and active network connection. Do not publish keys, prompt bodies, or private request logs when sharing diagnostics.

To undo, quit all Claude instances and run:

python3 -I claude_code_proxy.py uninstall

Removal preserves unrelated policy edits and restores the prior profile selection unless you changed it yourself. It refuses to delete edited/replaced profile settings. Interrupted removals can be retried. If installation was interrupted, run uninstall to recover its recorded changes before trying install again, even if the configuration-library metadata was not created yet.

Moving an existing installation: uninstall using the script in its old location before installing from a new checkout. Do not delete or move an installed checkout, interpreter, or private config file while its launcher still refers to those paths. Merely copying this repository does not replace an existing launcher.

4. Create multiple named Desktop profile apps

Create two independently configured profile apps (lightweight launcher mode by default):

python3 -I claude_profiles.py create "Claude Work" --color blue
python3 -I claude_profiles.py create "Claude Personal" --color purple

They appear under:

/Applications/
  Claude Work.app
  Claude Personal.app

Open them in Finder, pin their launcher shortcuts to the Dock, or use:

python3 -I claude_profiles.py launch "Claude Work"
python3 -I claude_profiles.py launch "Claude Personal"
python3 -I claude_profiles.py list
python3 -I claude_profiles.py status

Each starts with fresh account data; sign in separately. No existing cookies, account tokens, or conversations are copied. Existing standard Claude accounts and app data remain untouched. The profile names are labels you choose, not verified account identities.

Available colours: blue, purple, teal, green, red, orange, pink, slate, black, or a quoted hex value such as --color '#1F8A70'. Without --icon-svg, the locally installed Claude icon is framed/badged with that colour. No vendor icon assets are distributed in this repo.

Optional full copies for distinct running Dock icons

Create a new profile with its own runtime copy:

python3 -I claude_profiles.py create "Claude Copy" --color teal --mode copy

Or quit the selected profile, then convert its existing launcher:

python3 -I claude_profiles.py set-icon "Claude Work" --mode copy

Conversion keeps the profile UUID, app path, account and Code config directories, proxy opt-in, and existing icon/embedded SVG. It changes the generated app, not those account stores. The copied bundle's metadata, icon and current Electron helper bundle/executable names are adjusted to match its new CFBundleName, as required for startup. The installed source app remains untouched. Successful CLI builds refresh the generated app's Launch Services registration without restarting Finder or the Dock.

To return to a lightweight launcher, quit that profile and run:

python3 -I claude_profiles.py set-icon "Claude Work" --mode launcher

Changing icons, converting or refreshing a profile is refused while it is running if either its current or requested mode is copy; the tool does not stop it for you. Copies have their own update/signing caveats; see Updates below.

Recolour an SVG instead of adding a frame

Supply your own static, path-only SVG to change its background colour directly, without an added frame, padding, or initials badge:

python3 -I claude_profiles.py create "Claude Purple" --color purple \
  --icon-svg /absolute/path/icon.svg
python3 -I claude_profiles.py create "Claude Black" --color black \
  --icon-svg /absolute/path/icon.svg

The first path's fill identifies the background. All paths with that same fill are recoloured; other fills and path geometry stay unchanged. The icon is rendered on a 1024-pixel square canvas, preserving the SVG viewBox aspect ratio. Input must be UTF-8, at most 1 MiB, and contain only flat paths with explicit hex fills. Scripts, styles, transforms, external resources and DTD/entity definitions are rejected.

Update an existing profile app's icon and optionally relocate it, without recreating its profile or changing its mode, account data, Code config, or proxy opt-in (quit a copy-mode profile first):

python3 -I claude_profiles.py set-icon "Claude Work" --color purple \
  --icon-svg /absolute/path/icon.svg --apps-dir /Applications
python3 -I claude_profiles.py set-icon "Claude Work" --color black

The second command reuses the sanitised SVG embedded in that app. Omitting --apps-dir keeps its current location. An unrelated existing app at the target path is never replaced. Re-add a pinned Dock shortcut if it still points to the old location; macOS can temporarily cache the previous icon.

Use artwork you have permission to use. User-supplied SVGs are stored only in your local generated app; they are not included in this repository. Confirm redistribution rights before sharing generated apps or adding third-party artwork to a fork.

Default storage:

Data Location
Registry/build cache ~/Library/Application Support/Claude-Profiles/
Desktop account data <root>/<profile UUID>/
Companion configuration <root>/<profile UUID>-3p/
Separate Code config <root>/<profile UUID>-code/

Production Claude strips CLAUDE_USER_DATA_DIR. These launchers use the supported Chromium --user-data-dir=<absolute path> argument instead, and set a distinct CLAUDE_CONFIG_DIR for Code. Do not manually launch the bare source binary without the profile argument and expect it to select the same account.

If the Desktop proxy is already installed, new profiles automatically receive a fresh, minimal companion configuration-library opt-in for that same machine-level launcher. They do not share browser auth stores or copy proxy credentials. Use --code-proxy on to require an installed proxy, or --code-proxy off to omit this local opt-in. Existing device policy always remains authoritative.

Optional shared Code configuration

To keep Desktop accounts separate but share the usual ~/.claude directory:

python3 -I claude_profiles.py create "Claude Shared Settings" \
  --color teal --shared-code-config

Sharing that directory shares Code state, plugins, settings, and potentially credentials, not just harmless preferences. Separate Code configs are the safer default. This choice does not copy or share Desktop's cookie jars.

Updates

Keep the original /Applications/Claude.app installed and update it normally. In launcher mode, reopening a profile uses the current installed version without rebuilding its launcher or moving its account data. There is no guarantee that every in-app updater restart preserves the profile argument; save your work and reopen the named launcher if an updater restarts an unexpected profile.

Copy-mode apps are independent snapshots. After updating the original, quit each copied profile and rebuild it from its current vendor source:

python3 -I claude_profiles.py refresh "Claude Work"

Refresh keeps the mode, app path, UUID, account/Code config directories, proxy opt-in, and existing icon/embedded SVG, and records the newly copied source version. Do not use a copy's own in-app updater. The runtime requests DISABLE_AUTOUPDATER=1, but not every app build is guaranteed to honour it; this is not an updater-isolation guarantee or a separate vendor-supported updater. Refresh again from the original if the copy needs rebuilding/re-signing.

A custom source location can be selected at creation with --source /path/Claude.app; refresh uses the source path already recorded for that profile.

Remove a profile app without deleting account data

Quit the selected profile first, then:

python3 -I claude_profiles.py remove "Claude Work"

This removes its generated launcher or runtime-copy app and registry entry. Desktop account data and Code config are retained, with paths printed for your records. It does not terminate a running instance, remove live locks, delete accounts, or purge history.

Troubleshooting

  • The key works for models but logs return 401: inference and management keys are different. Configure logging/admin access in CLIProxyAPI itself. This toolkit only needs the client inference key.
  • Desktop still uses a different launcher: check status, then check the machine-managed settings. Uninstall an older installation with its original script instead of overwriting managed policy manually.
  • A named launcher shows Claude's usual Dock icon/name: expected in default launcher mode. For a distinct running icon/name, quit that profile and use set-icon "NAME" --mode copy, accepting the signing/auth/update limits above. If a copy shows stale artwork, macOS may be caching its previous icon.
  • A login link opens another instance: multiple instances still share the vendor's registered URL scheme. Complete sign-in/callback behavior is an acceptance test, not an established guarantee. Do not send authentication URLs or cookies to other profiles to work around it.
  • A profile has the wrong Code config: Desktop can have its own stored config override. Check the profile's settings and status; shared-config mode is intentional only when explicitly selected.
  • No gateway is reachable: connect the required network/VPN, check the URLs, and start the gateway. There is no automatic direct-inference fallback.

Development and verification

python3 -I -B -m unittest discover -s tests -v
sh -n start-cc.sh

Tes

Description taken from the repository README.

Ratings

–
0 ratings
5 0
4 0
3 0
2 0
1 0

Rate this app

Sign in to rate

Comments 0

Sign in to comment

No comments yet.

Related apps

#claude-desktop · #multi-instance · #macos