The State Model Behind a Provider Switch
CC Switch's provider switch is a state-management problem: the application must preserve several provider choices, translate one of them into a client's native configuration, and report honestly when a running process has—or has not—adopted the change. This chapter follows that lifecycle so you can tell which state CC Switch owns, which state belongs to the client, and why a switch can be safely committed without being immediately visible to an already-running tool.
What belongs to CC Switch, and what belongs to the client
A provider card is a durable record of an option, not a copy of whatever a client happens to be using at this moment. In the current data model, a provider has a stable ID, a name, a settings configuration, optional metadata, endpoint information, notes, and failover membership. That record lives in CC Switch's SQLite database. The database can therefore hold several alternatives for one application even when that application itself expects only one active provider.
The client still needs a native representation. Claude Code reads a JSON settings file, Codex divides important information between JSON and TOML, and Gemini CLI uses its own environment and settings files. CC Switch projects the selected provider into the representation that the client understands. “Projection” is a useful term here because the native file is derived from managed state, but it is not disposable output. A user may edit it directly, the client may add data of its own, or another integration may write alongside the provider settings. CC Switch has to read it back when those changes matter.
That gives the system two kinds of ownership. CC Switch owns the managed alternatives and the rules for producing an effective configuration. The client owns the runtime interpretation of the native file. The boundary is not perfectly clean: CC Switch may preserve selected client-side changes through backfill, while the client may rewrite or cache parts of the file after CC Switch writes it. A useful operational question is therefore not “which file is the real source of truth?” but “which part of the state is authoritative for this decision?”
For the list of saved providers, the database is the durable authority. For a currently running Codex process, the process's in-memory state is what determines the next request. For a prompt or MCP entry that the client loads from a native file, that file is the immediate input until the client reloads it. Treating one layer as authoritative for every question is how configuration tools lose user edits or report success too early.
CC Switch's application model makes another distinction that is easy to miss. Some clients use switch semantics. Claude Code, Codex, and Gemini CLI are representative cases: a provider selection identifies the configuration that should occupy the active slot. Other clients use additive semantics. OpenCode, OpenClaw, Hermes, and Pi can manage provider entries that coexist in a native configuration and can be enabled independently. In an additive client, there is no single current-provider pointer with the same meaning. Replacing one entry would be a destructive interpretation of a choice that was meant to add or enable capability.
This difference changes the shape of a safe operation. In switch mode, CC Switch must preserve alternatives in its database while changing one live projection. In additive mode, it must decide whether a newly added provider should also be written to the client, and editing a database-only entry should not silently add it to the live configuration. The visible “provider card” is similar in both cases, but the transition behind the button is not.
Current state also has a device dimension. CC Switch validates an effective current provider from local settings when possible and falls back to the database's current marker. This allows a device to select its own active provider while retaining a database-level default for situations such as a new device or an incomplete local pointer. It also means that synchronizing a database does not necessarily mean every device should start sending requests through the same provider. Durable catalog state and local selection state are related, not identical.
The same ownership split explains why endpoints are stored separately from a provider's main settings snapshot. A user may test or retain several endpoint candidates without changing the provider identity or its other configuration. Likewise, health information and request history describe what happened around a provider; they are not necessarily provider configuration itself. CC Switch's schema keeps provider records, endpoint candidates, provider health, request logs, pricing, and session-sync state as different kinds of data because each has a different lifecycle.
A provider edit follows the same principle. When the active provider is edited, CC Switch can read the latest live configuration before opening the editor. If the user changed a setting in the client, that change can be brought back into the provider record rather than being overwritten by an older database snapshot. Saving then writes the edited effective configuration back to the live file. This is a reconciliation relationship: the application tries to converge two representations while preserving the changes that belong to the user or to the client.
Reconciliation does not mean that every field is merged indiscriminately. Some data is shared across providers and should remain shared. Some data is generated for a client and should not become a provider-specific setting merely because it appeared in the live file. Some data is sensitive and should never be copied into a general provider snapshot. The boundaries become most visible during a switch.
A provider switch is a reconciliation lifecycle
The ordinary switch begins by validating that the target provider exists for the selected application and that its settings have an acceptable shape. This first step matters because a button that changes a current pointer before checking the target can leave the interface naming a provider that the client cannot load. The current implementation gives Codex an especially explicit preflight path for this reason: a target configuration is checked before the current selection is committed when the write layer has constraints that could otherwise reject it.
If the user is leaving a different provider in an exclusive client, CC Switch first considers the live configuration as evidence. It can read the current file and save meaningful manual changes into the current provider's stored settings. This is the “backfill” step. It is not a backup of every byte. It is an attempt to preserve the user's latest provider-specific edits before the old projection is replaced.
Backfill must also remove information that would be wrong in the next provider snapshot. A shared configuration snippet is applied when producing an effective live configuration but can be stripped again when saving the provider, so a global setting does not become duplicated in every card. MCP entries projected from the central MCP store should not be smuggled into a Codex provider and later resurrect a server that the user deleted. Generated or lossy client projections, such as a model catalog, may need to be reconstructed from the stored provider data rather than trusted as a complete reverse representation.
Credentials require the strictest version of this rule. In the managed Codex OAuth path, the provider record retains the account binding and an appropriate configuration shape, while the actual managed tokens are held by the authentication manager. When CC Switch backfills the live file, it deliberately avoids persisting those real tokens in the provider snapshot. That is not merely a cleanup preference. A token copied into an ordinary provider record could be exposed through export, synchronization, or later editing as if it were ordinary configuration.
After backfill and target validation, CC Switch constructs the effective target settings. “Effective” means the settings that the client should receive after applicable shared configuration, authentication handling, model defaults, and app-specific normalization have been applied. The stored provider snapshot is not always byte-for-byte identical to this output. Keeping that distinction allows CC Switch to change shared defaults or refresh managed credentials without pretending those generated values were explicitly entered by the user.
The live write is designed to avoid a half-written file. CC Switch serializes JSON deterministically where appropriate, writes to a newly created temporary file, flushes it, and replaces the destination. Credential-bearing writes can use private Unix permissions for new and replacement files. The point is simple: a crash or interruption should not normally leave a JSON or TOML file containing only the first part of a new configuration. Atomic replacement cannot make a running client update at the same instant, but it reduces corruption at the file boundary.
The application then records the new current state locally and in the database, preserving the distinction between a device's effective selection and the database's stored marker. It synchronizes the managed projections that belong with the new state. If a switch involves a client with a distinct native layout, the write path has to understand that layout; a generic “put the key in a file” operation would be unsafe. Codex's recent changes show why: newer Codex releases changed how third-party authentication is represented, so current CC Switch switches third-party providers through their own provider configuration rather than treating the shared official-login file as a universal key slot. The release notes also describe safety gates for keyless or unloadable configurations, refusing a switch rather than reporting success for a client that cannot start.
The lifecycle looks like this:
The sequence has two important asymmetries. CC Switch can make the file replacement atomic, but it cannot control when every client rereads the file. And it can record a target as current, but that record is not proof that the upstream endpoint accepts the target's protocol, key, model, or account. The user-facing manual reflects this with different activation behavior: Claude Code can hot-reload provider data, Gemini CLI rereads its environment on each request, while Codex commonly needs a terminal restart.
A successful switch therefore has a precise meaning. The requested provider passed the application's checks, CC Switch committed the relevant managed state, and the native projection was written or the appropriate additive action was taken. It does not necessarily mean that a process already in memory has adopted the change, that an endpoint is reachable, or that an upstream will interpret the model and tool payload as expected. A short test request remains useful because it verifies the next boundary rather than repeating the database operation.
There are also failure paths that the design cannot hide. Another program may lock or rewrite the native file. A permission error may prevent projection even though the provider record is valid. A client may cache configuration until restart. A provider may have a valid-looking endpoint but require a nonstandard path or a different protocol. CC Switch can surface warnings, preflight some known invalid combinations, and preserve safety backups in related workflows; it cannot make external processes part of one transaction.
That is the practical state model. A provider card is a durable alternative. A current pointer is a selection signal. A native file is a client-facing projection that may also contain user and client state. Backfill is the attempt to preserve relevant changes at the transition, and atomic write is protection at the file boundary. Once a local proxy is introduced, provider selection moves one step later—from configuration time into request time—so the next question is no longer only how to project a provider, but how CC Switch can route a running client's request through that choice.