Skip to content
registered2ndPublic

About

Switchy: desktop account switcher and pool for Claude Code, Codex, Gemini CLI, Kimi and OpenCode (Windows; based on cc-switch)

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

1,648 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Switchy

Switchy manages subscription accounts for coding tools — several plans per company if you like — and writes the account you pick into the program that runs it: Claude Code, Codex, Gemini CLI, Kimi Code, Cursor CLI (cursor-agent), Antigravity CLI (agy) and OpenCode. Pooling through the proxy covers Claude Code, Codex and Gemini CLI. Route a program through Switchy's local proxy and several subscription accounts serve it as one pool, moving to the next account before the current one reaches its limit.

It is a desktop app for Windows, built with Tauri; it also builds for macOS. Release history is in CHANGELOG.md.

Companies and accounts

The sidebar lists the companies you hold accounts with: Claude, OpenAI, Google, Kimi, Cursor, Z.ai GLM, MiniMax, DeepSeek, OpenCode and Command Code, then any other company once it holds an account (Alibaba Cloud, Tencent Cloud, BytePlus, StepFun). Settings → General → Homepage Display turns companies off. A company's page lists its accounts, each with its usage shown the way that company bills it, and a Used in row naming the programs the account runs in.

  • Subscription sign-ins. A Claude account runs in Claude Code, a ChatGPT account in Codex, a Cursor account in Cursor CLI, a Google AI account in Antigravity (and a Google sign-in in Gemini CLI), a Kimi membership in Kimi Code. The card shows that one program; Enable makes it the account the program runs on. Add account adds an empty card (sign in while it is in use) or imports the account signed in now.
  • Plans reached with a key (Z.ai GLM, MiniMax, Command Code, OpenCode Go, Alibaba Cloud, Tencent Cloud, BytePlus, StepFun). Add the account with its key and the plan's service (international or mainland China). Its card offers each program the plan works in — Claude Code, OpenCode — and choosing one writes the key and endpoint into that program, which then runs on the account; OpenCode holds several such accounts at once, so there the choice adds or removes it. Editing the key updates every program it is used in.
  • A Kimi membership is one card per kimi login. Its Kimi Code Console key is optional on that same card; with it, the card also offers Claude Code and OpenCode.
  • Relays and gateways serving a company's program sit with that company: relays for Claude Code (and AWS Bedrock) under Claude, relays for Codex (and Azure OpenAI) under OpenAI, relays for Gemini CLI under Google, relays and gateways set up in OpenCode under OpenCode. Add one with Add account → Relays and gateways.
  • Pay-as-you-go balances (DeepSeek, Moonshot's API under Kimi, StepFun) are a monitor only: the card shows the balance and what was spent today and this month, read with the key; it runs in no program. DeepSeek has only this. Spend is the sum of the drops between Switchy's balance readings (a rise is a top-up), counted from the first reading, since none of these companies reports spend.
  • Other appears when a program holds a pay-as-you-go key Switchy does not run (a DeepSeek or Moonshot key set up in Claude Code by an earlier version). Those cards keep working; add a balance monitor under the company to see the balance.

Settings → Programs lists each program with the account it runs on now, its proxy and failover switches, OpenCode's Oh My OpenCode profiles, and OpenClaw (off by default; turn it on there and open it to manage its providers and gateway settings).

Choosing a program from a card, or picking an account from the tray, writes it into the program's config. Claude Code picks up a switch without a restart. Codex does too while it is routed through the proxy (see Switching Codex accounts in an open session); otherwise exit and run codex resume --last, which brings the conversation back under the new account. Gemini CLI, Kimi Code, Cursor CLI and Antigravity CLI need a restart.

Upgrading to 1.0.45 files existing cards under their companies: a card on a plan's endpoint becomes that plan's account (cards with the same plan and key, in any program, become one account, and stay in use where they were), and a key on DeepSeek's, Moonshot's or StepFun's own API gets a balance monitor. Nothing is written to the programs' configs by the upgrade.

A switch changes only what the provider owns — its endpoint, credentials and model — and leaves the rest of the tool's settings file as it is: hooks, plugins, MCP servers, permissions and anything another tool writes stay. For Claude Code that is the ANTHROPIC_* variables, API_TIMEOUT_MS, the cloud credential variables, and the context-window, subagent-model and beta switches a non-Claude model needs (CLAUDE_CODE_AUTO_COMPACT_WINDOW, CLAUDE_CODE_MAX_CONTEXT_TOKENS, CLAUDE_CODE_SUBAGENT_MODEL, CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS). The common config snippet (Edit common config in the provider form) is for settings you want Switchy to put in place: saving it applies the change to the tool's settings file.

Coding plans

Model providers sell coding subscriptions that programs reach with a key. Each plan's account offers the programs below, on the international service or, where one exists, the mainland China one. Researched 2026-10-25 from each provider's documentation:

Provider Plan In Claude Code, base URL In OpenCode, base URL Key Usage on the card
Z.ai (Zhipu GLM) GLM Coding Plan Lite / Pro / Max, $18 / $80 / $168 a month Z.ai GLM Coding Plan, https://api.z.ai/api/anthropic Z.ai GLM Coding Plan, https://api.z.ai/api/coding/paas/v4 a GLM Coding Plan key (managed apart from standard API keys) 5-hour and weekly
MiniMax M Plan Go / Explore / Build, $22 / $55 / $132 a month (Token Plan is closed to new buyers) MiniMax M Plan, https://api.minimax.io/anthropic MiniMax M Plan, https://api.minimax.io/anthropic/v1 Subscription Key, sk-cp-… 5-hour and weekly
Moonshot Kimi Kimi Code membership on kimi.ai, Plus / Pro / Max / Ultra, $19 to $199 a month Kimi Code Plan, https://api.kimi.ai/coding/ Kimi Code Plan, https://api.kimi.ai/coding/v1 Kimi Code Console key, sk-kimi-…, in ANTHROPIC_API_KEY 5-hour, weekly and monthly
Alibaba Cloud (Qwen) Model Studio international (Singapore): Token Plan, $6 to $68 a month; Coding Plan Pro, $50, while slots last Alibaba Cloud Token Plan, https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic; Alibaba Cloud Coding Plan, https://coding-intl.dashscope.aliyuncs.com/apps/anthropic none plan key, sk-sp-… none: quota is shown only in the signed-in console
Tencent Cloud Token Plan Personal (Singapore), Lite / Standard / Pro / Max, $7 to $103 a month Tencent Cloud Token Plan, https://tokenhub-intl.tencentcloudmaas.com/plan/anthropic none plan key, sk-tp-… none: console only; the cloud API needs SecretId/SecretKey signing
BytePlus (ByteDance) ModelArk Coding Plan Lite / Pro, $10 / $50 a month BytePlus ModelArk Coding Plan, https://ark.ap-southeast.bytepluses.com/api/coding none ModelArk key none: needs access-key signing
DeepSeek no plan; prepaid balance a balance monitor only — key balance and spend
OpenCode Go Go / Go Plus, $10 / $40 a month OpenCode Go, https://opencode.ai/inference/go/anthropic (MiniMax M3, Qwen and Claude Haiku 5.5, the Go models that take Anthropic Messages) OpenCode Go, https://opencode.ai/inference/go/openai/v1 (its Chat Completions models) oc_sk_… 5-hour, weekly and monthly, for the whole subscription
Command Code GOAT / Pro / Max, $10 / $20 / $100–$200 a month; the $1 Go plan has no API access Command Code, https://api.commandcode.ai/provider (Claude models) Command Code, https://api.commandcode.ai/provider/v1 Command Code key month's plan credits; 5-hour and weekly on window-limited plans

To add a plan, subscribe on the provider's international site and create the key the table names. On the company's page, Add account, choose the plan and service and paste the key; then choose the programs it is used in on the card. The program gets the models the provider's own Claude Code guide gives (BytePlus picks the model in its console, through ark-code-latest). Cards of plans with a usage call show how much of each window is used and when it resets, read with the account's key: Z.ai and MiniMax their 5-hour and weekly windows, Kimi its 5-hour, weekly and monthly ones, Command Code the month's plan credits (with extra credits in the hover) and, on window-limited plans, its 5-hour and weekly meters, OpenCode Go its 5-hour, weekly and monthly windows. OpenCode Go gives each model its own monthly dollar limit, but its usage call reports one figure per window for the whole subscription, so the card shows those three figures, not one bar per model. Without a key a card shows No key.

What the plans allow:

  • Every plan is for interactive use in coding tools. Scripts, application backends, reselling and shared accounts are against their terms, and Alibaba's servers refuse requests that do not come from a coding agent.
  • Z.ai allows its plan only in the tools it lists, which include Claude Code, Codex and OpenCode.
  • OpenCode Go's and Command Code's terms forbid one person holding several accounts (OpenCode Go: to get around usage limits; Command Code: at all, on pain of a lifetime ban), so those accounts are not for pooling.
  • None needs a mainland China account or phone number. Alibaba and BytePlus require identity verification on the account.

The Kimi Code membership also signs in Kimi Code itself (see Official accounts). Command Code also has its own CLI (cmdc), which Switchy does not switch; its key works in Claude Code and OpenCode on every plan but Go.

Official accounts

An Official provider holds a subscription login instead of an API key, so switching providers switches accounts.

  • Claude Code. Sign in with claude /login while the Official provider is current, then click Capture login on its line (the button shows on the account in use). Switchy stores that login with the card and puts it back whenever the card is enabled.
  • Codex and Kimi Code. Each Official card keeps the login you signed in with while it was current; there is nothing to capture. To add a Codex account, add an OpenAI Official provider, enable it, and run codex login. A new Kimi Code card signs in on kimi.ai, the international service: enable it and run kimi login. Kimi Code keeps a kimi.ai login and a mainland kimi.com one in different files under ~/.kimi-code/credentials/, named in the card's config, and Switchy switches whichever the card's config names.
  • Cursor CLI and Antigravity CLI. Every Cursor card, and every Antigravity card under Google, is a subscription login and nothing else. Add a card, enable it and sign in (cursor-agent login, or sign in when agy starts); the login is filed with the card that is current, and Add account → Import the … account signed in now makes a card of the account signed in now. Enable writes the card's login where the CLI reads it: for Cursor, %APPDATA%\Cursor\auth.json ($XDG_CONFIG_HOME/cursor/auth.json on Linux) and the authInfo entry in ~/.cursor/cli-config.json, whose other settings stay; for Antigravity, the Windows Credential Manager entry gemini:antigravity. Before switching away, the live login is filed back into the card being left under the Codex and Claude rules: a removed or older login never replaces a stored one, and another account's login goes to the card holding that account. A card with no login signs the CLI out locally, so the next start asks for a sign-in. The Cursor editor keeps its own sign-in in its own database and is not touched. Antigravity sign-ins are separate from Gemini CLI's Google sign-in, though both are listed under Google.
  • Usage badges. An Official card shows the subscription's quota: how much of each window is used and when it resets. Cursor cards show the billing month's included usage (Included, Auto, API) from Cursor's dashboard API; Antigravity cards show the remaining quota of Gemini, Claude and GPT-OSS models from the model list agy itself reads. What Gemini and Kimi cards can show is under Known limitations.

Choosing the browser for sign-in

Settings → General → Open sign-in links manually keeps Claude Code's sign-in URL in the terminal, makes plain codex login show a link and one-time code, on Windows makes cursor-agent login print its link instead of opening a browser, and makes agy started signed out in PowerShell show its link instead of opening a browser (Switchy sets NO_OPEN_BROWSER=1 in the user environment and puts back any earlier value when the option is turned off; a terminal or app started before the change, such as Orca or Cursor, keeps its old environment until it is restarted). Copy the link into the browser profile for that account. Open a new terminal and restart existing Claude Code sessions after turning it on. Turning it off restores Claude's previous browser setting and ordinary Codex login.

Codex device-code sign-in must be enabled in your ChatGPT account's security settings or workspace permissions. If it is unavailable, login reports an error and leaves the browser closed. On Codex's initial sign-in screen, choose Device Code. The setting covers Claude Code, the Codex terminal commands in PowerShell, Bash and Zsh, and cursor-agent on Windows; the Codex desktop app, IDE extension and direct executable launches use their own sign-in controls.

Windows and native macOS/Linux installs are configured by Switchy. WSL follows the configured Claude and Codex mirror directories under Settings → Advanced → Configuration Directory. The option starts off on each installation and continues working while Switchy is closed.

The pool

Settings → Pool holds everything the pool runs on:

  • Local proxy. Routing, switching and rotation all need it running.
  • Route through the proxy. The apps whose requests go through the proxy.
  • Switch automatically. Claude tries the next account when Anthropic refuses its quota; its configured quota rotation can also move it before the limit. Connection, login and service errors stay on the account serving the request. A dropped connection, or a 502, 503 or 504, is retried once on that same account a second later. Other tools move through their switching order when requests fail. Picking an account by hand holds it for 10 minutes before automatic switching resumes.
  • Rotate accounts before the limit. For Claude and Codex, moves an account whose usage has reached the configured threshold to the back of the order until its limit resets, and serves first the account whose weekly limit resets soonest, so its quota is used before it expires. The selected account, saved login, window and tray follow an automatic switch.
  • An account's own switch-away limit. Switch away at %, under Advanced in an Official Claude or Codex account's Edit dialog, takes the place of the pool's threshold for that account alone (50–100; empty uses the pool's). Set it lower to stop using one account sooner while the others run on. Gemini CLI accounts have no such setting: Google's responses report no usage percentage, so their pool moves on only when a request is refused.
  • Keep accounts warm. Opens each account's session window in advance.
  • Lock in. The lock icon on an Official Claude or Codex card (open while unlocked, closed and highlighted while locked) enables that account and keeps it: the proxy serves it alone, with no rotation and no automatic switch, until you click it again to unlock or enable another account. Use it to spend one account's quota whatever the switching rules would pick. The lock survives a restart.
  • Global Outbound Proxy. The proxy Switchy itself uses to reach the services.
  • Require proxy. Off by default. Accounts with their own proxy always use it. Turn this on to require a global or detected local proxy, or an active local TUN route, for other accounts too; a missing route stops their requests. Leave it off when your router proxies a Wi-Fi network. This setting applies to traffic Switchy sends and does not install firewall rules.
  • An account's own proxy. A provider's advanced settings can give it a proxy of its own (HTTP or SOCKS5). While its app is routed, requests served from that account, and Switchy's renewals of its login, leave through it. For Claude, Switchy also points Claude Code's HTTPS_PROXY at the local proxy, so Claude Code's own traffic (its sign-in code exchange, its own login renewals and its telemetry, which do not use the API address) leaves through the proxy of the account in use. If that proxy cannot be reached the connection fails rather than going out directly. With the proxy off, or after Switchy quits normally, the tools connect directly again.

Switching Codex accounts in an open session

A running Codex session reads its ChatGPT login once, at start, and refuses to reload a login that belongs to a different account. Switching the Official provider therefore changes the account for the next session, not the open one.

Turn on the proxy for Codex (Settings → Pool → Route through the proxy) and the open session switches too. Codex keeps its own login and its built-in provider is pointed at the local proxy; on every request the proxy replaces that login with the one of the Official provider currently selected. Codex 0.160 and later send their turns over one WebSocket, which the proxy relays with the account selected when it opened; when the selection changes, the proxy closes it between turns and Codex's next turn reconnects on the new account. A turn an account refuses for usage before any of it reached Codex goes to the next account without an error: a turn carrying the whole conversation is sent there directly, and one that continues an earlier turn of the same connection makes the proxy close the connection, so Codex retries it in full on a new one. Codex stays in ChatGPT mode, so its model list and its codex resume history are unchanged. Sessions started before the proxy was turned on keep talking to OpenAI directly until they are restarted.

  • Rotation. With Switch automatically on, the app's switching order is the pool of accounts. Enable on a card still picks an account by hand: it puts that account first in the switching order, and it answers from the next request on. Rotate accounts before the limit moves an account whose usage has reached the threshold to the back of the order until its limit resets, and an account OpenAI refuses for usage is passed over until the reset it names. Among the accounts not at their limit, the one whose weekly window resets soonest is served first, so an account sent to the back for its five-hour window takes over again as soon as that window resets; accounts that have not reported a weekly window since Switchy started follow, in the switching order. When every account is spent the request still goes out, so you see OpenAI's own message.
  • Logins stay usable. The proxy renews a stored login when its access token runs out and hands the renewed login to Codex's own auth.json and to the copy restored when the proxy is turned off, under the same newest-valid-login-wins rules as One login, two installs. A login OpenAI has rejected is not retried. Enabling an account whose login was rejected signs Codex out the way codex logout does, so the next Codex started opens on its sign-in screen; sign in there, or with codex login, while that provider is current. Codex has no sign-in inside a running session. A new sign-in, on Windows or in WSL, is stored with the enabled card as soon as it appears, with the proxy on or off; the card then shows the account signed in and its failure count and circuit breaker are cleared.
  • Region warnings. In the background, Switchy asks the edge in front of the service (chatgpt.com, or api.anthropic.com for Claude) which IP and country it sees over the selected route. An exit in mainland China, a country change, or an unsuccessful lookup is logged and shown under Network warnings in Pool settings. Observations are refreshed at most once every five minutes while accounts are used. Country checks do not delay or stop requests. A configured proxy remains mandatory even when Require proxy is off.
  • /status follows the switch (experimental, on by default). A Codex window keeps the account it started with, so /status in an open window would go on showing that account. With Settings → Pool → Switch Codex's signed-in account on and Codex routed through the proxy, each Codex window started in native Windows PowerShell or WSL runs on its own Codex app-server, started from its terminal. Switchy installs a PowerShell profile function on Windows and a ~/.bashrc function in WSL; open a new terminal after installation. Permission flags (--dangerously-bypass-approvals-and-sandbox, --approve-for-me, -s, -a) are given to the window's server as settings rather than to the window, because Codex refuses them from a window that resumes a conversation on a server. Switchy signs each window's server in to the account in use on every switch, so /status shows the new account's email and limits. Codex cancels a server's requests in flight when its login changes, so a turn running at that moment would end on "Fatal error: application network permission was revoked"; Switchy therefore waits until none of the window's conversations is mid-turn. Its requests reach the new account through the proxy meanwhile. The server keeps that login in memory and asks Switchy for a new one when OpenAI refuses it; auth.json is left alone. It uses Codex's experimental chatgptAuthTokens sign-in. Switchy checks open windows on each platform against that platform's installed CLI and selected model catalog, then shows a notice and lists their terminals in Pool settings. Refresh (or refresh_codex_terminal over the control routes) waits until Codex in that terminal has finished its reply, quits it, and the terminal launches a fresh server from the installed CLI and reopens the conversation it was in, with the options it was started with. In an Orca tab Switchy quits Codex as you would (Ctrl+C, then /exit if Codex is still open); in any other terminal it ends the Codex process and the terminal's codex function restores the screen and input modes. Text typed but not sent in Codex's input box is lost. While a refresh is queued, Switchy reads the window's conversations from its server; when the window has no conversation with a message yet, or has opened more than one, the conversation picker opens instead, so another window's conversation is never taken. Codex started before 1.0.39 gets Refresh only in an Orca tab (found from its process's environment), and one started before 1.0.38 comes back on the picker; elsewhere it keeps Refresh on exit, which waits for you to exit Codex. Sessions opened before refresh support need a manual codex resume after exit. A custom model catalog still has to contain any new model entries; refreshing the server does not add them. codex exec, codex login, and other non-window commands run plain Codex, as does everything while the setting is off. A window whose terminal is killed before Codex exits leaves its session files in ~/.codex/switchy-sessions/; Switchy removes them the first time that server refuses a connection (in WSL, a socket that is missing or has nothing listening), and tries a window that fails in any other way again a minute later. A WSL window's socket link stays in that directory.
  • WSL. The Codex install in WSL is pointed at the proxy too, so its sessions switch accounts the same way. See WSL for what that needs. It must be signed in with ChatGPT. When the proxy is turned off it gets the login of the account that is current then.

Rotating Claude accounts through the proxy

Claude Code picks up a switch without a restart, so Official Claude accounts swap by hand at any time. Automatic quota switching goes through the proxy: turn on routing for Claude (Settings → Pool → Route through the proxy). An Official account whose login has not been captured cannot be served, so Switchy refuses the takeover and says so; capture it from the provider card first. The Claude install in WSL is pointed at the proxy too, under the same conditions as Codex. Claude Code sessions started while the proxy was on keep calling it after it is turned off; quit and reopen them.

With the proxy taken over for Claude, Claude Code keeps its subscription sign-in. Enabling an account by hand or after a quota refusal also puts that account's captured login into Claude Code's saved login, so /status names the account that serves the requests. The proxy presents that account's captured login and patches the account id in the request to match it. Each request leaves through the serving account's own proxy, then the global proxy if it has none, then directly if neither is configured. Claude Code's own identity calls (/api/oauth/*) pass through with the login Claude Code sent, which is the enabled account's.

With Switch automatically on, a 429 reporting exhausted account or model quota allows Claude to try another account. With Rotate accounts before the limit on, quota rotation uses the percentage configured in Pool settings. Automatic switches update the selected account, saved login, window and tray. A per-minute throttle, connection failure, refused login or service error reaches Claude from the account serving the request; those errors do not restrict its later requests or concurrency. Renewal, the exit check and the login rules follow the Codex rules above. Anthropic's rate-limit headers identify shared and model-specific quota windows, so an account spent for one model can still serve another.

Switchy then sits in the request path and renews captured logins itself, using Claude Code's own client id against Anthropic's token endpoint. Whether that fits Anthropic's terms for subscription logins is yours to weigh before turning the proxy on for Claude.

Keeping pooled accounts warm

A subscription's session window — Anthropic's five hours, ChatGPT's equivalent — opens on a real request and resets a fixed time later. An account nobody has used has no window running, so when rotation moves onto it the window starts from cold, and that account is the one holding the session with its reset furthest away.

Keep accounts warm opens those windows in advance. Each Official account is looked at on the interval you set, and one request for a single token goes out to the ones whose window has lapsed. An account whose window is still running is skipped, and so is one at its limit, so the cost stays near one request per account per window. It runs while Switchy is running and needs neither the proxy nor rotation to be on; it is off by default, because it spends quota with nobody present.

Presenting the login renews it, so a warmed account is also a signed-in one — but only as far as its refresh token reaches. That deadline is set by the last sign-in in the browser and renewing does not push it back, so keep-warm cannot hold an account open indefinitely; when the refresh token expires the account needs claude /login or codex login while it is the current provider. Everything else is as it is for a real request: the exit check runs first, a rejected refresh token is not retried, and the quota the answer reports is recorded for rotation to use — which is the other thing keep-warm buys, since an account nobody has used reports nothing at all.

The model each request uses is the test model for that tool under Settings → Advanced → Model Test Config, which defaults to the cheapest one. A Codex account signed in with ChatGPT is refused API models, so it gets the test model only when Codex lists that model for ChatGPT logins, and otherwise the model Codex lists last, at its lightest effort.

WSL

Settings → Advanced → Configuration Directory has a Claude Code Mirror Directory and a Codex Mirror Directory. Point one at the WSL install's config directory (for example \\wsl$\Ubuntu\home\<user>\.claude) and every switch is written there too, so both sides stay on the same provider and account. The Claude mirror updates only the provider fields and keeps the WSL side's own hooks, status line and plugins; docs/fork_notes_windows_wsl_claude_sync.md has the details.

While an app is routed through the proxy, its WSL install is pointed at the proxy as well. WSL reaches the proxy only with mirrored networking (networkingMode=mirrored under [wsl2] in %USERPROFILE%\.wslconfig); without it the WSL install is left alone.

Handing configs back

Routing an app through the proxy edits its config — Claude Code's settings.json, Codex's config.toml — to point at the proxy. When the proxy lets go, whether it is turned off, Switchy quits, Windows shuts down or restarts, or Switchy starts again after a crash, only what the proxy changed is put back; after a Windows restart the proxy takes the configs over again when Switchy starts. While any tool is routed through the proxy, Switchy starts at login, in the tray, so a restart, a crash or a power cut leaves the tools without a listener only until it is up again; with nothing routed, it starts at login only when Launch on startup is on. The hand-back at a Windows restart has 4 seconds and logs each step. Hooks, plugins and settings that another tool or you added in the meantime stay, such as the status hooks Orca writes. Switching the Claude account while the proxy is on keeps them too.

Control routes

The proxy's port (127.0.0.1:15721 by default) answers routes for a script or an agent to see and drive the running app. The port is open from launch, with the proxy on or off.

  • GET /switchy/accounts: for Claude and Codex, the current account, the account held after a pick by hand, the locked account, and the switching order as the pool would serve a request now, each account with its last quota reading, the usage percentage it switches away at (switchAwayAt: its own limit or the pool's) and whether it is at that limit.
  • POST /switchy/switch with {"app": "codex", "provider": "<id>"}: makes the account current as Enable on its card does, including the 10-minute hold, and updates the window and the tray.
  • GET /switchy/commands: every command the window can call, with its argument names and types.
  • POST /switchy/invoke with {"command": "<name>", "args": {...}}: runs that command as the window would and answers {"result": ...} or {"error": ...}. Anything the window does is reachable this way: providers (get_providers, add_provider, update_provider, switch_provider, …), settings (get_settings, save_settings), the proxy and routing (set_proxy_takeover_for_app, …), usage, backups and the rest. Argument names are camelCase, for example {"command": "get_providers", "args": {"app": "claude"}}. The window and tray refresh after a command that changes something. A command that opens a file dialog waits for someone at the screen.
  • Signing an account in without switching, through POST /switchy/invoke: sign_in_start {"app": "codex" | "claude", "providerId"} answers {sessionId, url, expiresAt, finish}; sign_in_finish {"sessionId", "code"} exchanges the code and answers {email, accountId, providerId}; sign_in_status {"sessionId"} answers pending, done, failed or expired. The recipe is below.

The routes cover every action in the window and the tray: each button, switch, menu item, form, reorder, import and export, sign-in, capture and refresh ends in a command POST /switchy/invoke runs, listed by GET /switchy/commands (audit). A command that opens a file or folder picker has a counterpart that takes the path. show_main_window, quit_app and set_window_appearance (theme: light, dark or system; language: zh, en or ja) do what the tray and Settings → General do, and exit_lightweight_mode works while lightweight mode has closed the window.

The two command routes return API keys and logins, so they answer only callers on this machine and refuse any request carrying an Origin header, which every browser page sends. They need the main window to exist; it does whenever Switchy is running, hidden in the tray or not.

Setting up an account from a script

Each line is {"command": ..., "args": {...}} posted to /switchy/invoke, in order. <id> is what the first call answered; a new account's id is any new UUID and createdAt the time in milliseconds.

  • Claude. add_sign_in_account {"app": "claude"} → <id>; sign it in without switching with "app": "claude". Usage: get_subscription_quota_for_provider {"tool": "claude", "providerId": "<id>"}.
  • OpenAI. add_sign_in_account {"app": "codex"} → <id>; sign it in without switching with "app": "codex"; get_codex_account_identity {"providerId": "<id>"} names it. Usage: get_subscription_quota_for_provider {"tool": "codex", "providerId": "<id>"}.
  • Google. Antigravity: add_sign_in_account {"app": "antigravity"}; switch_provider {"app": "antigravity", "id": "<id>"}; start agy and sign in; get_login_account_identity {"app": "antigravity", "providerId": "<id>"}; usage with "tool": "antigravity". Gemini CLI: the same with "app": "gemini", signing in with gemini → /auth → Login with Google.
  • Kimi. add_sign_in_account {"app": "kimi"}; switch_provider {"app": "kimi", "id": "<id>"}; run kimi login (kimi.ai). Its console key, optional: save_account {"account": {"id": "<new>", "company": "kimi", "kind": "plan", "plan": "kimi-code", "region": "intl", "name": "<email>", "secret": "<sk-kimi-…>", "loginProviderId": "<id>", "createdAt": <ms>}}; then use_account_in {"id": "<new>", "app": "claude"} or "opencode"; quota get_account_quota {"id": "<new>"}. Moonshot's API balance: save_account with "kind": "monitor", no plan, "region": "intl" or "cn"; then get_account_balance {"id": ...}.
  • Cursor. add_sign_in_account {"app": "cursor"}; switch_provider {"app": "cursor", "id": "<id>"}; run cursor-agent login; get_login_account_identity {"app": "cursor", "providerId": "<id>"}; usage with "tool": "cursor".
  • Z.ai, MiniMax, OpenCode Go, Command Code (and Alibaba Cloud, Tencent Cloud, BytePlus, StepFun). save_account {"account": {"id": "<new>", "company": "zai", "kind": "plan", "plan": "coding", "region": "intl", "name": "<name>", "secret": "<plan key>", "createdAt": <ms>}}; use_account_in {"id": "<new>", "app": "claude"} or "opencode" (remove_account_from takes it out of OpenCode); get_account_quota {"id": "<new>"}. Company and plan: zai/coding, minimax/m-plan, opencode/go, commandcode/plan, alibaba/token-plan or coding-plan, tencent/token-plan, byteplus/coding-plan, stepfun/step-plan (cn only); region is intl, or cn where the plan has a mainland service. save_account with the same id and a new key reaches every program the account is used in; delete_account {"id": ...} removes it from them.
  • DeepSeek. save_account {"account": {"id": "<new>", "company": "deepseek", "kind": "monitor", "region": "intl", "name": "<name>", "secret": "<key>", "createdAt": <ms>}}; get_account_balance {"id": "<new>"}.
  • Relays and gateways. add_provider {"app": "claude", "provider": {"id": "<new>", "name": "PackyCode", "category": "third_party", "settingsConfig": {"env": {"ANTHROPIC_BASE_URL": "https://www.packyapi.com", "ANTHROPIC_AUTH_TOKEN": "<key>"}}}}; switch_provider {"app": "claude", "id": "<new>"}. For Codex, "app": "codex" with "settingsConfig": {"auth": {"OPENAI_API_KEY": "<key>"}, "config": "model_provider = \"relay\"\nmodel = \"<model>\"\n[model_providers.relay]\nname = \"relay\"\nbase_url = \"https://…/v1\"\nwire_api = \"responses\"\nrequires_openai_auth = true"}; for Gemini CLI, "app": "gemini" with {"env": {"GOOGLE_GEMINI_BASE_URL": "…", "GEMINI_API_KEY": "<key>"}}. Each relay's own settings are its preset in src/config/*ProviderPresets.ts.

Signing an account in without switching

A Codex or Claude card, new or signed out, is signed in from that account's own browser profile while every program stays on the account it is using. Switchy runs the official CLI's OAuth flow itself: no switch, no codex login or claude /login, and the live ~/.codex/auth.json, ~/.claude/.credentials.json and their WSL copies are not written.

  1. sign_in_start {"app": "codex", "providerId": "<id>"} (or "app": "claude") → {"sessionId", "url", "expiresAt", "finish"}. Only an Official sign-in card is accepted. The sign-in waits 15 minutes (expiresAt, unix seconds); one waits per card, and a new start replaces it.
  2. Open url in the account's own browser profile (its AdsPower profile, for a pooled account) and approve.
  3. "finish": "callback" (Codex): the browser comes back to http://127.0.0.1:1455/auth/callback (1457 while a codex login holds 1455), Switchy finishes the sign-in, and the tab reads "Signed in as ". "finish": "code": Claude's page shows a code; send sign_in_finish {"sessionId": "<sessionId>", "code": "<code>#<state>"}. When both Codex ports are taken, the browser lands on a page that cannot answer; send the address it shows as code. code takes the bare code, code#state, or the whole callback address.
  4. sign_in_status {"sessionId": "<sessionId>"} → pending, done (email, accountId), failed (message, with the server's own text) or expired.

The code exchange, and for Claude the profile read after it, leave through the card's own proxy, the route its token renewals take, so the sign-in reaches OpenAI or Anthropic from the account's own exit. A card that already holds an account refuses a sign-in of another one, names both emails, and stays as it was; a card with no login takes the account signed in. The new login is filed with the card as codex login writes auth.json, or as Capture login stores a Claude login, and the card's refused-login mark, failure count and circuit breaker are cleared. Through the proxy, the card's requests carry the new login at once; it reaches Codex's auth.json once the account has answered a request, and Claude Code's credentials when the card is enabled.

Once it reads done, check it landed: for Codex, get_codex_account_identity {"providerId"} names the email with a fresh lastRefresh and get_subscription_quota_for_provider {"tool": "codex", "providerId"} reads valid; for Claude, get_captured_claude_identity {"providerId"} names the email. GET /switchy/accounts shows every program still on the account it was using.

Diagnosing a sign-out

get_request_logs (or ~/.switchy/logs/switchy.log) shows the card's refused renewals with the server's own text. token_revoked or refresh_token_invalidated right after a password reset or "log out of all devices" is expected. "Refresh token has already been used" means another holder of the same login renewed it and the result was lost, usually a login copied to a second install or machine. Either way the login only comes back through a new sign-in; retrying renewals does not restore it.

Other tools in the app

  • What an account change costs an open Claude session. Claude Code stores each turn's reasoning only as an encrypted blob signed by the organization that produced it. Anthropic drops Claude Sonnet 5.5's blobs when the conversation continues on an account of another organization, and Claude Code then shows "Claude can't use thinking from another organization": the session goes on, without its earlier reasoning and with one slower, uncached request. Opus 5.5 and Fable 5.1 reasoning carries across accounts. The proxy sends a session through another account on a switch by hand, a rotation or a failover alike.
  • Session Recovery (Settings → Advanced): finds Claude Code transcripts that fail to resume after a switch because they carry thinking blocks the new account or endpoint cannot validate. Repair strips those blocks and relinks the conversation, keeping a backup of the original file.
  • Quota history: every whole-point change in a Claude or Codex account's share of a limit window, and every new window, is recorded with its reset time in the quota_readings table of switchy.db and kept 90 days, so usage before a reset can be looked up afterwards. There is no view of it in the window yet.
  • Usage Statistics (a tab in Settings): per account, the requests, tokens and rate-limit refusals that went through the proxy and when it was last used; and a history of every account switch with its reason (picked by hand, a failed request, a usage limit, a refused login, rotation). Successful requests are recorded only while request logging is on (Settings → Pool → Proxy server).
  • Health check: the test button on a provider card sends it one request to see that it answers. The models used are set under Settings → Advanced → Model Test Config.
  • Environment variable conflicts: a banner lists environment variables whose names contain ANTHROPIC, OPENAI or GEMINI, since they can override the config Switchy writes, and can delete them after backing them up.
  • Tray: switch the account each program runs on without opening the window.
  • Backups and moving to another machine: the database is backed up on a schedule, and exported and imported as SQL, both under Settings → Switchy data. That export is how providers move to another machine. Sign each machine in to each account itself rather than copying a login across: one login on two machines races on renewal (see One login, two installs).

Setup

Windows. Download the installer from the latest release and run it; it is not code-signed, so SmartScreen asks you to confirm (More info → Run anyway). A clone has the same installers in installers/, or build from source (below).

macOS (Apple Silicon). Download the .dmg from the latest release, open it and drag Switchy into Applications. It is not signed, so macOS blocks the first launch: right-click the app and choose Open, or run xattr -dr com.apple.quarantine /Applications/Switchy.app. The .dmg is built by .github/workflows/build-macos.yml as part of each release; a clone has it in installers/.

Data lives in ~/.switchy/:

  • switchy.db — providers and app settings (SQLite)
  • settings.json — device-level preferences
  • backups/ — database backups
  • accounts/ — captured Claude logins, one directory per provider (Codex, Kimi, Cursor and Antigravity logins are stored with their providers in switchy.db)

Development

Needs Node 22 (see .node-version), pnpm and Rust 1.85 or later.

pnpm install          # dependencies
pnpm dev              # run the app with hot reload
pnpm typecheck        # TypeScript check
pnpm test:unit        # frontend tests (vitest)
cd src-tauri && cargo test   # backend tests

GitHub Actions runs both suites on Linux for every push to main and every pull request (tests.yml). Locally, a backend test that starts the proxy fails while an installed Switchy holds port 15721.

CI=true pnpm build builds the app and copies the current version's -setup.exe and .msi into installers/. CI=true stops pnpm from prompting mid-build, which fails when no terminal is attached. Under pnpm 11 a fresh checkout may also need CI=true pnpm install --force so the esbuild and msw build scripts allowed in pnpm-workspace.yaml actually run; Build and diagnosis notes has the full recipe.

After reinstalling a running copy, verify port 15721 before using routed sessions; Switchy turns the proxy back on when it starts. Check the installed switchy.exe's version too: an install started while the stopped copy is still exiting leaves the old executable in place, so wait until no switchy process is left before running the installer.

The workstation runs 1.0.49, installed on 2026-11-03 (down 6 seconds; GET /switchy/accounts answered and the running agy sessions kept going), with a Cursor and an Antigravity card each holding registered2nd@gmail.com's login; Windows holds its restart registration (--autostart, read back with GetApplicationRestartSettings). On 1.0.39 Refresh restarted Codex mid-reply only after the reply ended, in Orca tabs and in terminals outside Orca, on Windows and in WSL, each time on its own conversation with a usable terminal. Its WSL Codex CLI is 0.163.0, the same as Windows. Country observations run in the background and provide warnings. Configured proxies remain mandatory; Require proxy is off for this machine's router-proxied Wi-Fi. No Claude account is locked (checked after the 1.0.44 install); a lock holds across a restart, as observed earlier on registered2nd (ccb19499). The control routes list every command and run them, and refuse a request carrying an Origin header. The laptop runs 1.0.49 (installed 2026-11-03 over 1.0.40, which had been running since its 2026-11-02 logon; port 15721 open, GET /switchy/accounts answers). another user's PC has 1.0.49 installed (2026-11-03) and Switchy not running, as it was before. another user's Mac runs 1.0.49 (installed 2026-11-03 from the release DMG over 1.0.47, settings kept; port 15721 open, GET /switchy/accounts answers). 1.0.49 is the latest public release (2026-11-03); its Windows installers and Apple Silicon DMG are in installers/. 1.0.44 was published on 2026-10-25 and taken down the same day: its GitHub release with the installers and DMG, the v1.0.44 tag, the DMG build artifact, and its three commits on the public repo, whose main went back to the session 33 handoff. The public copy leaves 1.0.44's installer files out of every commit. Release history is in CHANGELOG.md.

The frontend is React and TypeScript (src/), the backend Tauri and Rust (src-tauri/). The SQLite database is the store; switching writes the selected provider into each tool's own config files.

Build and diagnosis notes

  • pnpm 11 build gate. Under pnpm 11.5.2 a build fails twice before compiling: with no terminal, the dependency check aborts on purging node_modules (ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY); with CI=true it proceeds and then fails on unapproved build scripts (ERR_PNPM_IGNORED_BUILDS). The allowlist pnpm 11 reads is the allowBuilds: map in pnpm-workspace.yaml (esbuild: true, msw: true); adding entries to onlyBuiltDependencies does not clear a recorded ignored state. Approved scripts run only on a reinstall, so the recipe is CI=true pnpm install --force, then CI=true pnpm tauri build.
  • The Windows window config replaces the base one. Tauri applies tauri.windows.conf.json over tauri.conf.json as a JSON merge patch, and a merge patch replaces arrays whole. app.windows is an array, so on Windows the window entry in the Windows file is the entire window config: a width, height or centring set only in the base file never applies there. Switchy opened at its 900 minimum for months while two size changes to tauri.conf.json did nothing on Windows and the browser preview looked right. Every window field that matters on Windows lives in the Windows file; confirm a size change from the running window (GetClientRect), not the preview.
  • Icon changes need a clean build. An incremental pnpm tauri build keeps the old compiled icon resource after the .ico/.png sources change; 1.0.0 shipped with the old icon that way. After changing an icon or other embedded resource, run cargo clean in src-tauri first. Check the built exe with [System.Drawing.Icon]::ExtractAssociatedIcon('<path>\switchy.exe').ToBitmap().Save('verify.png'). An icon wrong only in Explorer, the taskbar or Start is Windows' shell icon cache, not the build.
  • "NSIS directory contains mis-hashed files." The NSIS bundler checks its helper DLL in %LOCALAPPDATA%\tauri\NSIS\Plugins\x86-unicode\additional\nsis_tauri_utils.dll, a cache shared by every Tauri project on the machine, and redownloads it from GitHub on a mismatch. From this network that download times out (timeout: global, or through the port 15721 proxy protocol: http response missing version). A build of another project can overwrite the cache with its own version, as happened on 2026-10-20 before 1.0.40. Download the DLL once and copy it into the slot, then bundle again; the version in the URL must match the one Tauri prints in its "Downloading..." line. --bundles msi is unaffected.
    curl -L --max-time 300 -o /tmp/nsis_tauri_utils.dll \
      "https://github.com/tauri-apps/nsis-tauri-utils/releases/download/nsis_tauri_utils-v0.5.1/nsis_tauri_utils.dll"
    cp /tmp/nsis_tauri_utils.dll "$LOCALAPPDATA/tauri/NSIS/Plugins/x86-unicode/additional/nsis_tauri_utils.dll"
    pnpm tauri build --bundles nsis
  • Codex's auth.json no longer carries auth_mode. Codex CLI stopped writing the field, and a reader that required auth_mode == "chatgpt" treated every current install as signed out and hid its usage badges, with no error. Switchy decides from the tokens block it is about to use; a mode field counts only when it names a different mode.
  • Identify a Claude account by its token, not its name. The token in .credentials.json is the account; the oauthAccount block in .claude.json is a display label that can be stale. Two snapshots with one name and different token hashes are two accounts; one token hash under two names is one account.
  • Repairing a session by hand. strip-thinking.mjs <session.jsonl> does what Session Recovery does, from the command line: it drops thinking and redacted_thinking blocks, relinks the parentUuid chain and keeps a .bak.jsonl. Quit Claude Code first and strip in place; copying the backup over the file while a session is attached discards what that session has written since. A running Claude Code keeps the transcript it loaded in memory, so a repair takes effect only after quitting and resuming. The signature errors (Invalid signature in thinking block, Invalid data in redacted_thinking block) follow a switch back to Anthropic Official from a wrapping relay (Aiberm-style, serving GLM, Kimi or DeepSeek behind Claude names); the error can name a different block type than the culprit, so the whole family is stripped together. A passthrough relay (RightCode-style, forwarding to api.anthropic.com) signs with Anthropic's keys and swaps freely; a one-shot call showing a claude-* model field suggests passthrough, glm-* or kimi-* confirms wrapping (May 2026).

Known limitations

Claude accounts need a browser re-login every few weeks

Switchy can capture an Official Claude provider's login and swap between multiple accounts on demand, including accounts you have not touched for days.

Two deadlines govern how long a captured account stays usable. The access token expires in about 8 hours and is renewed automatically. The refresh token behind it has its own expiry, typically one to several weeks out, and that deadline is anchored to when you originally signed in through the browser — renewing does not push it back. Once it passes, that account needs claude /login again; no local state management extends it.

One login, two installs

Claude Code and Codex both rotate the refresh token on every renewal, and the server accepts each one only once. Two installs holding the same login — most commonly Windows and WSL — will therefore race, and the one that renews second is rejected and left signed out.

Switchy reconciles the two sides in the background, moving the surviving login to whichever side lost, so this heals on its own. It needs the mirror directory configured and reachable (one per tool, under Settings → Advanced → Configuration Directory); while WSL is shut down, a rotation that happens on the Windows side cannot be propagated until it comes back. For Codex, an install that is on an API key rather than a ChatGPT login is left alone.

Windows reaches a WSL distro under two names, \\wsl$\ and \\wsl.localhost\, and one can stop answering while the other still works. When the configured one does not answer, Switchy uses the other.

The proxy is a third holder of each captured Claude login, and WSL can be signed in to any captured account, not only the one in use: a switch made while WSL was out of reach leaves it on the earlier account. Before renewing an account's login, the proxy takes a newer login of that account from WSL when WSL has renewed it; a login the proxy renews is written to WSL when WSL is signed in to that account. An account whose renewal was refused comes back by itself once WSL holds a newer login of it.

What a Gemini or Kimi card can show

Usage badges and account switching both come from signing a tool in with an account. Claude Code, Codex and Kimi Code keep that login in a file Switchy stores with each provider, so switching providers switches accounts.

Gemini CLI is different. A Gemini provider holds the API key and endpoint, not the Google sign-in, so switching Gemini providers never changes which Google account is signed in. Gemini usage badges appear only while Gemini CLI is signed in with Google (/auth → Login with Google); on an API key there is nothing to show.

A Kimi Code sign-in shows no usage badge of its own. The membership's quota shows once the card holds the membership's Kimi Code Console key, which is read for it.

Coding plan usage badges read unpublished endpoints

Only MiniMax documents its quota call (/v1/token_plan/remains). Z.ai's (/api/monitor/usage/quota/limit, key without Bearer) and Kimi's (/coding/v1/usages) are documented only in their own GitHub repositories, and Kimi changed its format on 2026-09-15; Switchy reads both formats. Command Code's (/alpha/whoami, then /alpha/billing/credits for that organization) is the one its own CLI calls for /usage, read the way its CLI reads it (credits.monthlyCredits, .purchasedCredits and .freeCredits left, against the plan's monthly credits, and the top-level windowLimits). OpenCode Go's (/zen/go/v1/usage, usage.rolling, .weekly, .monthly) is the one OpenCode's own client parses; since 2026-10-11 it answers from a backend outside OpenCode's public code. The balance monitors read documented calls: DeepSeek's /user/balance, Moonshot's /v1/users/me/balance and StepFun's /v1/accounts. Any of them may change without notice; the badge then shows a failed query while the provider keeps working. The badges were checked against each endpoint's answer to a missing or invalid key, not against a subscribed account.

Cursor CLI and Antigravity CLI

  • Platforms. Antigravity accounts switch only on Windows, where agy keeps its sign-in in Credential Manager (gemini:antigravity); on macOS and Linux it uses the Keychain or Secret Service, which Switchy does not write. Cursor accounts switch on Windows and Linux; on macOS cursor-agent keeps its tokens in the Keychain, which Switchy does not write.
  • Running sessions. A running cursor-agent or agy keeps the account it started with; start it again after a switch. No proxy routing, pooling or automatic switching covers these tools.
  • A running agy writes its account back. agy reads its login once at start, renews the access token itself about hourly, and saves each renewal to the store it started on. So after a switch, an agy still running on the old account puts that account back into Credential Manager at its next renewal, and an agy started after that comes up on it, though the card shown is the new one. Switchy does not file that login under a card holding another account, but an empty card that is current then, such as one just enabled for a sign-in, takes it. Seen 2026-11-03 (agy 1.4.12): one long-running session's renewed token expiry, to the nanosecond, was the one the next short agy -p run loaded from Credential Manager, four hours running.
  • How long a login lasts. A Cursor CLI login is a session token valid for about 60 days from sign-in, with no renewal; after that the account needs cursor-agent login again while its card is current. An Antigravity sign-in is a Google refresh token, which Google does not rotate, so the copy on the card stays usable until the account is signed out or access is revoked.
  • Sign-in links for Kimi Code. Open sign-in links manually cannot keep kimi login from opening the default browser. On Windows it opens links with cmd /c start, which has no setting, flag or environment variable to stop it; on Linux and WSL it uses xdg-open, which on this workstation's WSL hands https links to Google Chrome (WSLg) before it would read BROWSER. It prints the link and code as well, so the link can be pasted into the account's own browser profile.
  • The Antigravity sign-in link needs a signed-out start in PowerShell. agy has no setting for its browser; it shows the link instead of opening one when it sees SSH_CLIENT, SSH_TTY or SSH_CONNECTION. With Open sign-in links manually on, Switchy adds an agy function to the PowerShell profile that sets SSH_CLIENT only for an agy started while it holds no saved sign-in (enabling an empty Antigravity card leaves it so). A /login inside a session that is already signed in, or an agy started from another shell, still opens the default browser. While set, agy also treats that one session as remote: its guesses about clipboard, clickable links, colors and images may be plainer, and from 1.4.12 it keeps its login in ~/.gemini/antigravity-cli/antigravity-oauth-token instead of Credential Manager (its log says "Using file-based token storage because SSH session detected"; a keyring timeout in the last hour does the same). Switchy reads that file when Credential Manager holds no login, so the sign-in is filed onto the current card, and removes it whenever it writes Credential Manager. Until the next switch writes the login to Credential Manager, an agy started outside that PowerShell function finds no sign-in.
  • Usage badges use unpublished endpoints. Cursor's comes from DashboardService/GetCurrentPeriodUsage, the call cursor-agent makes for its usage screen. Antigravity's comes from v1internal:fetchAvailableModels on daily-cloudcode-pa.googleapis.com, which answers only a client whose user agent begins with antigravity; Switchy renews the one-hour access token for it with agy's own OAuth client, read from the installed agy executable, so the badge needs agy installed on that machine. Either may change without notice, and the badge then shows a failed query while switching keeps working.

Switchy stops when Windows runs out of memory

When Windows reaches its commit limit, a memory request Switchy makes can be refused, and Switchy ends at once. If it had been running for at least a minute, Windows starts it again in the tray; tools routed through the proxy have no endpoint until it is back. Windows makes one attempt, so if memory is still exhausted then, Switchy stays down until it is started by hand or at the next sign-in. The next start restores the live configs, takes them over again and adds an entry to ~/.switchy/crash.log with the time, the exception, whether Windows was out of memory, and where Windows kept the crash dump. Analysis and options: docs/finding_low_memory_abort_2026_10_20.md.

License

MIT — Switchy began as a fork of cc-switch by Jason Young. See LICENSE.

About

Switchy: desktop account switcher and pool for Claude Code, Codex, Gemini CLI, Kimi and OpenCode (Windows; based on cc-switch)

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages