Back to Cc Switch

CC Switch v3.19.2

docs/release-notes/v3.19.2-en.md

3.19.232.7 KB
Original Source

CC Switch v3.19.2

The through-line of this release is getting the numbers right and pinning down the boundaries: Codex usage accounting fixes a defect that could count an interleaved-counter file several times over — new data is correct immediately after upgrading, and inflated history can be corrected with a one-time manual rebuild (see "Upgrade Notes"); a six-part security hardening pass caps every unbounded read across usage scripts, session logs, catalog files, and buffered proxy response bodies. The everyday conveniences are filled in too: the MCP / prompt / Skills panels can be searched, and MCP and Skills gain one-click per-app bulk toggles; the Auth Center shows each ChatGPT account's subscription usage; OMO users get a working integration back. With two write paths batched, backup imports, automatic sync, and usage re-imports no longer stall at every turn on large databases. This release has no database migration.

中文版 → | 日本語版 →


Highlights: What You Can Do Now

  • Get correct Codex usage numbers: real-world logs contain files with interleaved counters — the same snapshot replayed by a gateway under changing rate-limit buckets, or two cumulative counters alternating — and the old algorithm treated both as new increments; files from the field measured six to eight times their true usage. The fix is validated by replaying nearly 1,900 real session files, landing within 0.001% of an independently recomputed ideal. Historical data is not rewritten automatically — see Upgrade Notes for how to correct it.
  • Search directly inside the MCP, prompt, and Skills panels: all three panels now have a search box; the per-app badges on the MCP and Skills lists also become three-state toggles that enable or disable an app across the whole list in one click (#5954 and #5935 both came straight from user requests).
  • Let current Claude Code releases enter a Copilot-takeover session directly: current Claude Code shows a confirmation dialog for an unrecognized API key, with "No (recommended)" preselected — and the placeholder takeover used to write ran straight into it, leaving users looking at a signed-out session. Takeover now writes the ANTHROPIC_AUTH_TOKEN placeholder instead and enters with no dialog at all.
  • Keep managing OMO with CC Switch: since OMO 4.19.3, configuration is unified into ~/.omo/omo.jsonc and the legacy file is no longer read, so provider switches used to look successful while landing nowhere. CC Switch now detects the unified file (omo.jsonc or omo.json) and writes into its "[opencode]" section. The OMO form's model pickers also merge in the runtime models opencode models actually reports.
  • See each ChatGPT account's subscription usage in the Auth Center: no more switching accounts one by one to check.
  • Stop hitting stalls on large databases: backup exports move to batched INSERTs and sync restores to a single transaction — the per-row fsync was exactly what made automatic sync stall periodically; a full Codex usage re-import on a real corpus drops from 36.3 to 11.1 seconds (macOS), with a larger win on Windows.
  • See the tool calls a gateway swallowed instead of being silently left hanging: when a third-party Chat gateway returned tool calls with missing function names, the transform layer used to drop them and still report the turn complete, so Codex quietly ended its loop. That case now fails loudly, and every drop site carries structured logging — problems like #4341 can finally be diagnosed from real traffic.
  • Make Hermes prompts actually take effect: they are written to ~/.hermes/SOUL.md, the file Hermes actually loads, instead of the AGENTS.md it never reads there.
  • Install Skills that used to fail: repositories like ast-grep's, with a same-name wrapper directory, now install; skills.sh nested Skills no longer get 404 README links (existing records need a one-time reinstall, see Upgrade Notes).

Usage Guides

The changes in this release center on usage statistics and the extension-management panels. The following docs are worth reading alongside it:

  • Usage Statistics: the usage dashboard's data sources and how the statistics are counted — useful for understanding how the interleaved-counter over-count happened and when a manual rebuild is needed.
  • MCP Management and Skills Management: the two panels that gained search and bulk toggles.

[!WARNING]

Only Official Channels (Please Read)

CC Switch is a fully free and open-source desktop app, and we do not charge users any fees. Please only obtain the software through the official channels listed below:

ChannelOnly Official
Websiteccswitch.io
Sourcegithub.com/farion1231/cc-switch
DownloadsGitHub Releases
Author@farion1231
Report an ImposterGitHub Issues

Any "CC Switch" website or client that asks you for payment, top-ups, or login credentials is fake. If you have been tricked into paying, stop the transaction immediately and file a report through GitHub Issues.


Overview

CC Switch v3.19.2 is a correctness-focused maintenance release along three lines. The first is getting the numbers right: the Codex session importer could over-count usage several times over on files with interleaved counters (#3011); this release switches to an algorithm that prefers each turn's explicit delta and recognizes replays by their full signature, closed out by replaying nearly 1,900 real session files; the backup and usage-import write paths are batched at the same time, markedly easing import stalls on large databases (#2100 will likely benefit).

The second is pinning down the boundaries: an externally contributed security hardening pass caps every unbounded read across the usage-script runtime, Grok session logs, Codex catalog files, and buffered proxy response bodies, and the deep-link import confirmation gains two credential fields it used to collect without displaying. The third is filling in the everyday conveniences: search across the MCP / prompt / Skills panels, bulk per-app toggles for MCP and Skills, per-account subscription usage in the Auth Center, and two OMO adaptations — the unified config and runtime models. On top of that come seven specific fixes covering Copilot sign-in, Hermes prompts, Skill installs, and more. This release has no database schema migration (the version stays at v16), so upgrading is light.

Release date: 2026-08-06

Change size: 24 commits | 109 files changed | +12,340 / -1,897 lines


Added

Management Panels: Search and Bulk Per-App Toggles

The MCP, prompt, and Skills panels share a new search box — Esc clears it, and it only intercepts the global back shortcut while it has content, so your usual habits are unaffected. The per-app count badges atop the MCP and Skills lists become three-state toggle buttons: one click enables or disables an app across the whole list — the days of flipping switches row by row are over (#5954, #5935).

Bulk operations deliberately run serially rather than concurrently — each app's live config is a single file, and concurrent writes would overwrite each other; failed entries are collected and reported in one go. A bulk toggle acts on the whole list, not the search-filtered subset, avoiding the ambiguity of "thought I only toggled the filtered results, actual state unclear".

Two long-standing data-layer problems get fixed along the way: MCP toggles move from read-whole-row / modify in memory / write-whole-row to a single-column atomic UPDATE, so two apps toggled at nearly the same time no longer lose each other's updates; Skill updates re-confirm before writing that the record still exists with its install generation unchanged, so a slow update task can no longer resurrect a Skill that was just uninstalled. The search index is an explicit whitelist — environment variables and request headers never enter the searchable text.

Auth Center: Per-Account Subscription Usage

Settings → Auth Center now shows each ChatGPT (Codex OAuth) account's subscription usage inline, reusing the query the provider card footer already runs — deduplicated by account, cached for five minutes, fetched once on mount with no polling. Multi-account users no longer have to switch around to check their quota. (#4887)

OMO Model Pickers Merge In Runtime Models

The OMO form's model pickers used to offer only a static list; they now also run opencode models and merge in the models the locally installed OpenCode actually reports. The helper process is deliberately sandboxed: project-level config discovery is disabled and the working directory is pinned to the OpenCode config directory — opening a form can never execute some project's .opencode/ plugins; the whole run has a 20-second deadline, after which the entire process tree is killed (process groups on macOS / Linux, taskkill /T on Windows, and an in-distro timeout for WSL installs). Any failure falls back to the static list with a toast. (#5522)

Built-In Pricing for Qwen3.8 Max

qwen3.8-max is seeded at the official list price: $2 input / $6 output per million tokens, $0.25 cache read, $2.50 cache write (125% of input, the official explicit context-cache rate). Seeding is insert-if-absent, so a price you edited yourself is untouched. (#6053)


Changed

Partner Roster Maintenance

The NekoCode and Unity2.ai partner presets are removed from every app, the READMEs, and all locale files; the Qiniu preset's position in the ordering is adjusted.


Fixed

Codex Usage Over-Counted (Up to Several Times) When Counters Interleaved

The session importer used to derive deltas from a single high-water mark over cumulative totals — correct when a file carries one monotonic counter, but real-world logs contain two interleaved shapes: a gateway replaying the same unchanged snapshot under changing rate-limit buckets, and two genuinely distinct cumulative counters alternating. The old algorithm treated both replays and alternation as new increments; files from the field measured six to eight times their true usage.

The importer now prefers the explicit last-turn usage each event carries, and recognizes replays by their full token signature. Deduplication is deliberately narrow: a snapshot is compared only against the same source's own previous signature or the immediately preceding token event — never against other sources' older signatures, because a legitimate counter reset reproduces old values and a full-table scan would swallow it. The totals-only legacy format falls back to a single global baseline, with the same semantics as before.

The fix is validated by replaying nearly 1,900 real session files totalling 1.7 GB: within 0.001% of an independently recomputed ideal, with every residual difference being a legitimate recovery of a counter reset the old algorithm clamped away. Historical data is deliberately not rewritten — see "Upgrade Notes" for how to correct it. (#3011, #3015)

Dropped Tool Calls No Longer Masquerade as a Completed Turn

Third-party Chat gateways occasionally return tool calls with missing function names; the Chat → Responses transform used to drop them silently and still report the turn completed — Codex saw a "successful turn with nothing left to do" and quietly ended its agent loop, turning a diagnosable upstream failure into a silent stall.

Now, when every tool call in a turn has been dropped and none remains usable, the streaming path emits response.failed and the non-streaming path reports a transform error; the check is gated on status == "completed", so finish_reason: length truncation keeps its own incomplete semantics. All three drop sites log structured, content-free fields — call-id presence, argument byte counts, finish reason — so problems like #4341 can finally be diagnosed from real traffic. Turns with a valid tool call, text-only turns, and truncated turns behave as before.

OMO's Configuration Was Written to a File It No Longer Reads

OMO 4.19.3 unified its configuration into ~/.omo/omo.jsonc (then omo.json), and its migration renames the legacy per-app file out of the way. From then on CC Switch — which only knew the legacy path — kept writing a file outside OMO's config chain, so provider switches looked successful while landing nowhere (#5945).

When the unified file is detected, the OpenCode configuration is now written into OMO's "[opencode]" section — and only there, because OMO validates its root schema strictly and discards the whole file over any unknown root key. Writes treat the document as JSON5: comments, key order, and line endings survive, and nothing is written when nothing changed; before every write, the result is re-parsed and compared semantically against the intent — if serialization would corrupt the document, the write is refused and the original file left untouched rather than saving a broken one (see "Upgrade Notes" for the known trigger). The same change also moves atomic file writes on Windows to ReplaceFileW for every managed app, closing the brief window in the old delete-then-rename sequence where the target file did not exist.

Copilot Takeover Left Current Claude Code Signed Out

Current Claude Code releases show a confirmation dialog for an unrecognized API key, with "No (recommended)" preselected — and the ANTHROPIC_API_KEY placeholder Copilot takeover used to write ran straight into it: follow the recommendation and the key is ignored, leaving a signed-out session. Takeover now writes the ANTHROPIC_AUTH_TOKEN placeholder, entering with no dialog; a provider that explicitly selected the ANTHROPIC_API_KEY field in the form's advanced section keeps the old behavior. The Copilot forwarding path also gains the [1M] context-marker strip the other paths already had, so a claude-*[1M] model ID no longer reaches GitHub's API verbatim. (#5832)

Hermes Prompts Were Written Under the Wrong File Name

The identity file Hermes loads from ~/.hermes/ is SOUL.md; it never looks for AGENTS.md there — that name is project-level context, discovered upward from the working directory. CC Switch's prompt management had written ~/.hermes/AGENTS.md since the day Hermes support was added, so enabling a Hermes prompt produced a dead file. It now reads and writes ~/.hermes/SOUL.md, and the existing back-fill still applies: a SOUL.md you wrote yourself is imported into the database before being replaced. (#5777)

Skill Repositories With a Same-Name Wrapper Directory Would Not Install

Installing ast-grep's official Skill failed with "SKILL.md missing": that repository keeps a wrapper directory named after the Skill at its root, with the real Skill nested deeper, and the resolver returned the first directory whose name matched. Source resolution is now anchored on SKILL.md itself — a directory without one is never selected — which also fixes the phantom "update available" that update checks kept reporting against such repositories. (#4141)

The skills.sh discovery flow reports only a Skill's basename; installation resolved the real nested directory, but the stored README link was still built from the basename guess — a 404 on click. The link is now generated from the directory the installer actually resolved. The fix applies to the install path only — records written by earlier versions need a one-time reinstall, see "Upgrade Notes". (#6111)

Header Actions Were Clipped With Every App Enabled

With every app tab, the profile switcher, and the takeover toggles visible at once, the header overflowed and the add-provider button was clipped. Primary actions now live in a non-shrinking cluster, and the app switcher is width-aware: apps that no longer fit collapse into a "more" popover, with the active app always visible.

The Route Status Animation Burned GPU in the Background

The route status indicator's pulse animation kept running while the window was unfocused, occupying the GPU for a purely decorative effect. Window focus now gates the heartbeat through a data attribute and CSS — an unfocused window freezes the animation at full opacity, and the system's reduced-motion preference disables it entirely. Data polling is unaffected; only the decoration pauses. (#5767)


Security Hardening

Every Unbounded Read Capped, No More Hidden Fields in the Confirmation

A six-part externally contributed hardening pass (#5919):

  • Usage scripts get resource and time limits: usage scripts can reach a machine via deep link or a synced database, and used to run on an unrestricted JS runtime — a single while(true) could hang the backend thread forever. The runtime now enforces a 5-second interrupt, a 16 MiB memory cap, and a 256 KiB stack cap.
  • Grok session-log reads get bounds: files over 50 MiB are skipped, directory recursion is capped at 16 levels, and symlinks are no longer followed — a symlink cycle under ~/.grok/sessions could previously overflow the stack.
  • The Codex model-catalog path is tightened: model_catalog_json used to trust any absolute path on the file name alone; it must now resolve inside the Codex config directory — re-checked after canonicalize, so a symlink cannot escape — with a 32 MiB per-read cap.
  • Buffered proxy response bodies are capped: bodies collected in full — non-streaming responses, error bodies, and whole-body validation paths — are capped at 128 MiB, accumulated as chunks arrive so the connection is dropped the moment the limit is crossed rather than after collection; streaming paths (passthrough and streamed transforms) are never buffered in full and carry no total cap.
  • Decompression is budgeted up front: the quota sits on the decoder's read side, covering gzip, deflate, zstd, and brotli, so a compression bomb cannot expand unchecked; an over-limit response maps to a distinct 502 instead of being mistaken for a retryable network error.
  • The deep-link confirmation gains two fields: the provider import confirmation used to parse and persist usageAccessToken and usageUserId without ever showing them; both now display before you approve, the token masked as usual.

Performance

Backups: Batched Exports, Single-Transaction Restores

Each direction had its own independent cost. On the export side, every row used to be its own INSERT, so importing a large backup had SQLite parsing, preparing, and destroying tens of thousands of statements one by one; exports now generate multi-row INSERTs in batches of 200 rows / 1 MB, cutting the statement count by two orders of magnitude and shrinking the backup file itself by roughly 4x. On the restore side, every WebDAV / S3 sync import ends by writing back the locally retained tables, and each row used to be its own implicit transaction — one full journal write and one fsync per row, exactly what made automatic sync stall the app periodically on large databases; the whole restore now runs in a single transaction.

Old single-row backups still import as before, and the new format is within what every SQLite shipped with the app supports — compatible in both directions across versions. The cross-machine import freeze reported in #2100 will likely ease — real-world results on that issue are welcome. (#6122)

Full Codex Usage Re-Imports Are Roughly 3x Faster, More on Windows

A full re-import — triggered by importing a pre-v16 SQL backup, by cursor mismatches after a cross-machine restore, or by a manual rebuild — could pin a CPU core for minutes on a large corpus: every token event formed its own auto-commit transaction, paying a full journal create / fsync / delete cycle per row, and every archived file ran a cursor-inheritance query that could not use an index.

Events now commit in batches of 1,000, with the connection lock released between batches so UI queries can slip in; the cursor advances in the same transaction as the final batch, so a crash can never leave it ahead of the data; cursors and model pricing are preloaded once per pass, and hot statements use the prepared-statement cache. A real corpus of 1,920 files / 1.7 GB drops from 36.3 to 11.1 seconds on macOS (release build); on Windows, where each per-row fsync costs milliseconds, the absolute win is an order of magnitude larger. Replaying the same corpus before and after verifies equivalence: 82,000 imported rows are byte-identical across all exported columns, with identical import / skip counts.


Upgrade Notes

No Database Migration in This Release

v3.19.2 contains no schema migration (the version stays at v16), triggers no pre-upgrade backup, and is ready to use immediately.

Inflated Historical Codex Usage Needs a One-Time Manual Rebuild

The interleaved-counter fix only guarantees correctness going forward: historical rows are deliberately not rewritten, and there is no automatic rebuild. If your dashboard's Codex numbers look impossibly high and your session files carry the interleaved shape, go to Usage page → Codex usage maintenance → "Rebuild Codex usage" once after upgrading — the database is backed up automatically before the rebuild; history whose session logs were already deleted cannot be re-imported. This release's import speedup makes the rebuild roughly 3x faster than before.

Most installations are unaffected: on data without the interleaved shape, the old and new algorithms differ by less than one part in a thousand.

Existing Nested-Skill Records Need a One-Time Reinstall

An existing Skill installed through skills.sh whose README link 404s recovers the correct link after an uninstall and reinstall; an in-place "update" will not rewrite it.

The First Sync After Upgrading Re-Uploads the Backup File Once

The backup dump format changed, and the sync protocol treats it as an opaque artifact hashed as a whole, so the first WebDAV / S3 sync after upgrading re-transfers db.sql in full — one-time and harmless.

The Copilot Placeholder Takes Effect on the Next Takeover Write

The AUTH_TOKEN placeholder takes effect the next time takeover rewrites the live config — switch providers or restart takeover. Providers that explicitly selected the ANTHROPIC_API_KEY field in the form's advanced section are unaffected; your choice is preserved as is.

OMO Unified Config Is Detected by File Presence

The decision is based on whether the file exists, not on the OMO version: when ~/.omo/omo.jsonc (or omo.json) exists, it is edited in place; when neither exists, the legacy OpenCode-layer file is written as before. Known limitation: if the unified file contains block comments (/* … */), writes fail with an error to protect the document — line comments (//) are unaffected. Until the upstream JSON5 writer is fixed, remove block comments before switching providers.

Bulk Toggles Act on the Whole List

The management panels' bulk per-app toggles act on every entry, not the search-filtered subset.

Buffered Proxy Response Bodies Are Capped at 128 MiB

Proxy responses that must be buffered in full — non-streaming responses and error bodies — fail with a 502 above 128 MiB instead of being forwarded; streamed passthrough responses are unaffected. A normal LLM response is a few MB at most, so the cap only triggers on upstream anomalies; such a failure terminates the request and does not trigger failover to the next address.


Risk Notice

Carried-Over Notices

xAI Grok OAuth sign-in: reuses the public OAuth client identity of the official Grok CLI; using it could lead to account restriction or suspension — see the v3.18.0 release notes for details.

Codex OAuth reverse proxy: using a ChatGPT subscription's Codex OAuth through a reverse proxy may violate OpenAI's terms of service. See the v3.13.0 release notes for details.

SuperGrok quota queries: the quota display on provider cards depends on a non-public billing endpoint at grok.com and may stop working once xAI changes the interface — see the v3.19.0 release notes for details.

Third-party provider routing: when the CC Switch local proxy converts and forwards Codex, Claude Desktop, or Grok Build requests to a third-party provider, each provider has different constraints on billing, compliance, and data retention. Please read the target provider's terms of service before use.

By enabling these features, users accept the associated risks. CC Switch is not responsible for any account restriction, warning, or service suspension resulting from their use.


Thanks

Thirteen of this release's 24 commits are PRs from outside contributors — nine of them, covering nearly every main line from the headline usage fix to the security hardening.

Code Contributions

  • #5854: the Codex interleaved-counter usage fix — this release's headline. Thanks to @MJYKIM99, who arrived with real-file evidence and polished the fix through three review rounds until the full replay converged; thanks also to @ayanamislover for independently replaying their own interleaved files, corroborating our validation.
  • #5919, #6122, #6119: the six-part security hardening, the backup performance overhaul, and the skills.sh README fix. Thanks to @zayokami — the "Security Hardening" and "Performance" chapters of this release are largely these three pieces of work.
  • #6011, #5522, #5767: the OMO unified-config adaptation, runtime model discovery, and the route-status GPU fix. Thanks to @allenxu09.
  • #5967: the management panels' search and bulk toggles, fixing two long-standing data-layer concurrency problems along the way. Thanks to @YUZHEthefool — who also collaborated on #6119 to converge that fix to its minimal shape.
  • #4887: per-account subscription usage in the Auth Center. Thanks to @SaladDay.
  • #5832: Copilot takeover compatibility with current Claude Code. Thanks to @Suaig.
  • #5779: the Hermes prompt file-name fix. Thanks to @mmm-05610 — from the report #5777 to the submitted fix, one person end to end.
  • #4153: anchoring Skill source-directory resolution on SKILL.md. Thanks to @makoMakoGo.
  • #6053: built-in pricing for Qwen3.8 Max. Thanks to @mhy1227.

Issue Reports

  • Thanks to @KeShih for pinpointing in #3011 that total_token_usage is non-monotonic and that replays were being counted as new increments — the problem definition behind this release's headline fix comes straight from that report; @KeShih also proposed the repair direction early in #3015.
  • Thanks to @Syuryuuki for reporting the missing OMO unified-config adaptation (#5945), @abcfy2 for the ast-grep Skill install failure (#4141), and @mortalBibo for the skills.sh nested-Skill 404 links (#6111).
  • Thanks to @kith13 (#5954) and @Getianyu1998 (#5935) — the management panels' search and bulk toggles came straight from these two suggestions.

Download & Install

Visit Releases and download the build for your system, or get it from the official site ccswitch.io (downloads are distributed through Cloudflare edge nodes and do not depend on GitHub being reachable).

System Requirements

SystemMinimum VersionArchitecture
WindowsWindows 10 and laterx64 / ARM64
macOSmacOS 12 (Monterey)+Intel (x64) / Apple Silicon (arm64)
LinuxSee table belowx64 / ARM64

Windows

FileDescription
CC-Switch-v3.19.2-Windows.msiRecommended - MSI installer with auto-update
CC-Switch-v3.19.2-Windows-Portable.zipPortable build, unzip and run

Windows ARM64 devices should pick the artifact whose file name carries the arm64 tag.

macOS

FileDescription
CC-Switch-v3.19.2-macOS.dmgRecommended - DMG installer, drag to Applications
CC-Switch-v3.19.2-macOS.zipUnzip and drag to Applications, Universal Binary
CC-Switch-v3.19.2-macOS.tar.gzFor Homebrew install and auto-update

Homebrew install:

bash
brew install --cask cc-switch

Upgrade:

bash
brew upgrade --cask cc-switch

Linux

Linux assets are available for both x86_64 and ARM64 (aarch64). Choose the file whose architecture tag matches your machine's uname -m output:

  • CC-Switch-v3.19.2-Linux-x86_64.AppImage / .deb / .rpm
  • CC-Switch-v3.19.2-Linux-arm64.AppImage / .deb / .rpm
DistributionRecommended FormatInstall Command
Ubuntu / Debian / Linux Mint / Pop!_OS.debsudo dpkg -i CC-Switch-*.deb or sudo apt install ./CC-Switch-*.deb
Fedora / RHEL / CentOS / Rocky Linux.rpmsudo rpm -i CC-Switch-*.rpm or sudo dnf install ./CC-Switch-*.rpm
openSUSE.rpmsudo zypper install ./CC-Switch-*.rpm
Arch Linux / Manjaro.AppImageMake executable and run directly, or use AUR
Other distributions / unsure.AppImagechmod +x CC-Switch-*.AppImage && ./CC-Switch-*.AppImage