any-switch switches local app profiles and state.
Use it when one app has several local setups and you want to move between them without hand-editing files, copying tokens, or remembering which config entries belong together.
Examples:
- switch Claude Code between a personal account and a work account;
- switch Codex between ChatGPT OAuth and an API-key provider;
- switch any supported local tool between different endpoints, models, accounts, workspaces, or other file-backed state.
The first built-in apps are Claude Code and OpenAI Codex. The tool itself is not
AI-specific: app definitions describe what local state can be captured and
restored, and any-switch handles the backup, redaction, drift checks, and
write safety around that state.
any-switch keeps named profiles on your machine. A profile is the local state
you want an app to use, such as:
- account identity and OAuth credential state;
- API keys and provider settings;
- model, endpoint, and environment settings;
- JSON, TOML, file, Keychain, or environment fragments declared by an app definition.
When you switch profiles, any-switch shows the plan, creates backups, writes
only the declared targets, and avoids printing secret values.
any-switch is distributed as a source-built CLI. The install command compiles
the Rust binary on your machine instead of downloading an unsigned macOS or
Windows binary.
The current release scope is a macOS-evidenced stage release: macOS Claude
OAuth import has real local evidence, while broader restart checks plus Linux
and Windows real-app evidence are tracked as follow-up work. This release does
not claim full docs/design.md section 13 coverage.
rustup toolchain install 1.95.0If rustup is not installed yet, install Rust from https://rustup.rs first.
For most npm-based CLI users:
npm install -g any-switch
any-switch --versionThe first npm install can take a little while because it runs Cargo once and
stores the compiled binary inside the npm package. After that, run
any-switch directly.
For Rust users:
cargo install any-switch --locked
any-switch --versionnpx any-switch --version can work for a quick trial, but it may compile on
first use and may compile again if npm's cache is cleared. Prefer a global
install for regular use.
For local development from a checkout:
cargo install --path .Check the installation:
any-switch --version
any-switch doctorSee the apps that this build knows about:
any-switch appsCapture the current login or state of an app as a profile:
any-switch import-current <app> personalList saved profiles:
any-switch listSwitch to a profile:
any-switch use <profile-id> --dry-run
any-switch use <profile-id>Check what is active:
any-switch status <app>
any-switch doctor <app>Built-in examples:
any-switch import-current codex personal
any-switch import-current claude work --kind oauth_capture
any-switch use codex-personalUse import-current after you have already logged in or configured the target
app in the normal way:
any-switch import-current <app> personalThis is the right flow for OAuth-based app state, because the app owns the real
login process. any-switch captures the local state after login; it does not log
in for you. For built-in apps this may look like
any-switch import-current codex personal or
any-switch import-current claude work --kind oauth_capture.
Use add when the profile can be described with fields such as an API key,
model, provider, or base URL. Field names are defined by the selected app
definition and profile kind:
any-switch add <app> work --kind <kind> --field key=valueBuilt-in Codex example:
any-switch add codex openai --kind file_template \
--secret-field api_key=@prompt \
--field model=gpt-5-codex \
--field model_provider=openaiSecret fields can be read from a masked interactive prompt, stdin, an environment variable, or a local file:
--secret-field api_key=@prompt
--secret-field api_key=@stdin
--secret-field api_key=@env:OPENAI_API_KEY
--secret-field api_key=@file:~/secrets/openai-api-keyUse @prompt for normal interactive setup. Use @env:NAME, @stdin, or
@file:PATH when scripting.
Use --dry-run to inspect a switch without changing local files:
any-switch use <profile-id> --dry-runBackups are created before managed targets are overwritten. Inspect them with:
any-switch backup listRestore an app from a specific backup when needed:
any-switch restore-target <app> <backup-id>restore-target restores live app state from the backup. It does not mark a
profile active, so run any-switch status <app> afterwards to inspect the
result. Confirm the restore by typing yes in an interactive terminal, or add
--yes in scripts and CI.
- Profiles are stored under
~/.any-switchby default. This directory can contain static secrets, OAuth captures, and defensive backups. Keep it out of cloud-synced folders such as iCloud Drive, Dropbox, OneDrive, and Google Drive;doctorwarns when it detects a known sync root. SetANY_SWITCH_HOMEto an absolute path under your home directory if you want a separate state directory. - Secret values are redacted from normal command output and JSON output.
- Do not commit
~/.any-switchor any generated profile/capture files. - Quit the target app before OAuth or process-sensitive operations. OAuth
credentials can rotate while the app is running, so
--allow-runningdoes not apply to those operations. - Use
--assume-app-stoppedonly when the app is actually stopped but process detection reports a false positive; confirm with--yesin scripts or by typingyesin an interactive terminal. Do not pass it preemptively: if no matching process was detected, any-switch rejects the flag and asks you to retry without it. - For static file or environment profiles,
--allow-runningis available, but stopping the app first is still safer because the app may rewrite its own config files. --yesconfirms high-risk actions non-interactively, such asuse,restore-target,remove, or--assume-app-stopped. In an interactive terminal you may omit--yesand typeyesat the prompt instead. Neither confirmation path disables identity checks, backup checks, path checks, locks, schema validation, or secret redaction.addand ordinaryimport-currentdo not accept--yesbecause they create or capture state instead of overwriting the target app.import-current --yesis valid only with--assume-app-stopped.
Start with:
any-switch doctor
any-switch doctor <app>
any-switch status <app>Useful next steps:
IdentityMissing: the app does not currently expose the identity fields that the profile kind requires. Make sure the app is logged in, then rundoctor <app>again.TargetMissing: rundoctor <app>and look fordefinition_capture_sourcerows. They show whether the current platform credential source, such as a Keychain entry or credentials file, isexists,missing, orwarningbecause existence could not be confirmed. If a warning row includeshint:, follow that source-specific next step first. For macOS Keychain checks, avoidsecurity find-generic-password -wunless you intentionally need to reveal the credential.DriftBeforeWriteback: the live app state no longer matches the active profile. Runstatus <app>to inspect it. If the live state is valuable, import it as a new profile before switching away.AppRunning: quit the target app and retry. Use--assume-app-stoppedonly for a process-detection false positive, then confirm with--yesor the interactive prompt.ImportAmbiguous: pass--kind <kind>or clean up the app's current auth files so only one import rule matches.
any-switch can be extended with app definitions under apps.d/*.yaml.
Definitions declare the local targets an app uses and which trusted handlers can
capture or write them. This lets new apps reuse the same safety model without
adding app-specific branches to the core CLI.
For the full model, see docs/design.md.
To inspect or customize app definitions:
any-switch apps show <app>
any-switch apps export <app> --source system
any-switch apps export <app> --source resolved
any-switch apps export <app> --as override --output ~/.any-switch/overrides.d/<app>.yaml
any-switch apps validate ~/.any-switch/overrides.d/<app>.yaml- docs/user-guide.md: practical user guide with common workflows, safety flags, and troubleshooting.
- README.zh-CN.md: simplified Chinese README.
- docs/user-guide.zh-CN.md: simplified Chinese user guide.
- docs/design.md: architecture and safety model.
- docs/manual-verification.md: real-app checks that cannot be fully proven in CI.
- docs/acceptance.md: acceptance coverage.
- docs/evidence-followups.md: deferred manual evidence tracking before full section 13 coverage is claimed.
- docs/release.md: release packaging and signing.
- CHANGELOG.md: user-facing release notes.
- CONTRIBUTING.md: development and contribution rules.
- .github/ISSUE_TEMPLATE/release_checklist.yml: release evidence checklist for maintainers.
- CODE_OF_CONDUCT.md: community standards.
- SECURITY.md: vulnerability reporting.
Run the local verification script before opening a pull request:
scripts/verify-local.sh
scripts/verify-packages.shMIT. See LICENSE.