github libnyanpasu/clash-nyanpasu v2.0.0
Clash Nyanpasu v2.0.0

2 hours ago

简体中文版本请展开页面底部的「简体中文」。

2.0 is the first stable release since the 1.6 series. It rewrites the frontend, rebuilds how the backend manages state and the core, and adds traffic analytics, Profile pipeline inspection, a standalone widget, diagnostics and crash reporting.

These notes compare against v1.6.1. Implementations that landed during the Beta and RC cycle and were later replaced are not listed separately.

Read Before Upgrading

  • Your configuration is migrated automatically. On first launch, the old verge.yaml, profiles.yaml and related files are split and migrated into new per-domain configuration files. The configuration directory and storage.db are backed up before migration; if migration fails, the startup dialog offers "Open backup directory", "Open migration log" and "Quit". Old settings keep their meaning wherever possible: for example, auto_close_connection: false becomes "Do not close connections when switching proxies", and a non-random mixed port becomes a fixed port. We still recommend backing up the configuration directory by hand before a major upgrade; afterwards, you can create a backup from Settings at any time.
  • Release targets are narrowed to six: x86_64 and aarch64 for each of Windows, Linux and macOS. i686 builds for Windows/Linux and Linux ARMv7 (armel/armhf) builds are no longer provided.
  • The CPU must support hardware AES: x86_64 needs AES-NI (Intel Westmere from 2010 or later, AMD Bulldozer from 2011 or later); aarch64 needs the ARMv8 AES extension. Some ARM devices without it, such as the Raspberry Pi 4/5, cannot run 2.0.
  • The minimum macOS version is now 12.6 (11.0 in 1.6).
  • Service mode requires nyanpasu-service 2.0.1 or later. Older services are rejected by the version check rather than falling back to the old protocol; update the service from System Settings when prompted.
  • port and socks-port in Profiles, Merge/Overlay and scripts are no longer passed to the core. Like mixed-port, both ports are now managed in Clash settings and are removed when unset. This prevents a subscription's own port: 7890 from taking over the mixed port (#5720).
  • The Profile model has changed. "Multiple selected Profiles + Chain" is split into a single current Config plus Transforms: merging several subscriptions is expressed with a Composition Config, Merge is renamed Overlay, and the global Chain becomes Global Transform. Remote / Local are no longer Profile types but a source property of each Profile (see "Profiles and the Pipeline"). Migration converts existing data automatically.
  • Clash Premium is deprecated and will be removed in a future release. It still works in this release; core management and the dashboard mark it as deprecated, and switching to it shows a notice.
  • Third-party dashboards should use the HTTP external controller settings provided by the app. The core's named pipe / Unix socket control channels are allocated and authorized per instance by the runtime and are no longer a stable, customizable interface.

New Features

Redesigned Interface

  • The main interface is redesigned in Material You, and the old interface has been removed. Components are built on our own @nyanpasu/ui (Radix primitives + Tailwind CSS) rather than re-theming the old pages.
  • The dashboard is made of freely arranged widgets; layouts can be saved and each widget configured on its own. When the window is resized, the layout for the new size is used.
  • Theming: follow the system accent color, or pick a color from the HCT palette with live preview; light / dark / follow system; custom CSS or LESS. The default theme color is #3e64a7.
  • Inter Variable is bundled and the CJK font fallback order is adjusted. The page's lang attribute follows the app language, so Han characters use the glyphs of the selected language rather than the system locale.
  • Responsive sidebar and narrow-window navigation, directional page transitions, per-platform title bars (Windows / macOS / Linux) and configurable window decorations. Linux no longer uses the native title bar by default.
  • The title bar menus (File / Settings / Help) are now a unified menu bar with keyboard navigation and switching between open menus.
  • Settings are grouped by category, and pages with many items are split into subpages.
  • The About page lists open source licenses.

Traffic Analytics

The new Traffic Analytics page lets you review historical traffic and track down anomalies:

  • View traffic by overview, connection path, location, device and process; rankings can be weighted by traffic or by connection count. After filtering on a dimension, its other candidates stay in the ranking for comparison.
  • Traffic is recorded per Profile, bucketed by time, and expired data is cleaned up automatically. Closed connections can also be browsed page by page with filters.
  • The map is shaded by traffic share. Regions are resolved with a country index bundled with the app (built from the core's geo databases), and each region shows how it was located.
  • DIRECT traffic and local sources can be located by probing the public IP. The probe requires explicit consent and is never sent while TUN is enabled.
  • The Rules, Connections and Traffic pages link to each other, carrying filters along, and you can return to the original page.
  • Data is stored in the new time-series layer nyanpasu-tsdb (see "Architecture"). Traffic recorded during Beta/RC is imported automatically on upgrade.

Profiles and the Pipeline

  • Type and source are separate: in 1.6 a Profile was one of Remote, Local, Merge or Script, and only configuration files could come from a remote subscription. 2.0 separates "what it is" from "where it comes from". Types are Config (a single configuration file, or a Composition combining several sources) and Transform (YAML Overlay, JavaScript / Lua script). The source is a separate property of each Profile and can be:

    • Remote: downloaded from a URL and synced on an interval;
    • Managed locally: the file is managed by the app and edited in the app;
    • Linked local file: references a file of your own, either as a "symlink" (references the original file directly; on Windows this needs Developer Mode or administrator rights) or a "mirror" (keeps a copy and syncs it when the original changes).

    Overlays and scripts can therefore be synced from a remote source like subscriptions, or linked to files you maintain elsewhere.

  • Pipeline: Overlay, JavaScript and Lua Transforms can be attached after a Config, and Global Transforms apply to every Config. The pipeline can be reordered by drag and drop.

  • Inspect: a full-height step browser shows how the configuration is generated. Each step has a snapshot, a diff against the previous step, a list of changed fields and the step's log, with the effective nodes and each step's highest log level marked. The final view matches the configuration the core actually loads. The open document tab and step filters are remembered.

  • Profile folders: create folders and organize Profiles by drag and drop or a "Move to" menu; deletion can be undone.

  • Preview before importing from a URL: the content is downloaded first, classified as a Config, Overlay or script from its response headers and content, and imported after you confirm the type and source.

  • Redesigned Profile cards and detail pages; subscriptions show their remaining traffic quota. All subscriptions can be updated at once, with sync status and run history; the update interval is hidden when auto-update is off.

  • clash://install-config deep links can specify a name and share the quick-import flow. Links are queued in the backend and imported in order once the main window has loaded, so links arriving during a page reload or before the window loads are not lost.

  • Subscriptions: Remnawave HWID, syncing the Profile name from response headers, hidden proxy groups from subscription metadata, and IP hostnames in subscription URLs.

  • include-all in proxy groups is expanded the way Mihomo does it and can be toggled in Clash settings.

  • The generated configuration keeps the key order of the source files. 1.6 reordered top-level keys by a fixed field table, so the generated configuration did not match the layout of the source. Nested maps keep their order too, which matters to the core for fields such as dns.nameserver-policy.

  • Scripts: JavaScript can import JSON/plain-text modules and built-in helper modules, runs in memory and keeps stack traces; both JavaScript and Lua have console output, and Lua keeps the original key order after processing.

  • When saving fails, the error names the Profile and the file.

Proxies, Connections and Rules

  • Proxies: proxy groups are listed in the sidebar, can be put in folders and reordered by drag and drop, and the layout is saved per Profile; frequently used groups can be pinned. Nodes within a group can be searched, sorted and filtered. Latency tests use each group's own test URL with a configurable timeout; node cards show recent latency history; group headers show the number of available nodes and the current selection chain (e.g. A › B › node). Health checks can be triggered for Providers. "Close connections when switching proxies" now has three levels: off / this group only / all.
  • Connections: a Closed tab, configurable columns, filtering by traffic dimension and value range, connection details and totals; sorting and scrolling through large lists are faster.
  • Rules: the rule list is virtualized, can be filtered by proxy, and shows each rule's current connection count and traffic.
  • Providers: a new dedicated Providers page.

Core

  • Adds the Meow (meow-rs) core with its own Meow Alpha channel, and Clash Rust Alpha, including Windows ARM64.
  • Alpha cores read the build currently in the upstream rolling release on every update check, so the version manifest no longer points at a deleted file after an upstream update, which caused 404 downloads.
  • Core updates verify the archive's SHA-256 and the binary's version; "Reinstall" is offered when an installed core cannot report its version.
  • A new core management view shows the core status, the control channel (HTTP / named pipe / Unix socket) and the service mode status. The control channel can be chosen in Settings, and the view also shows the channel actually in effect.
  • With the Meow core, core updates also install its bundled meow-cli and agent skill. A new AI page in Settings provides a one-line prompt you can give to an agent such as Claude Code or Codex to install the skill.
  • On macOS with TUN enabled, taking over and restoring the system DNS is part of the core transaction. The original DNS is persisted before any change, so it can be restored even after the app exits abnormally.
  • When several instances run at once (for example a development build and a release build), one instance no longer stops a core that another instance started through the service.
  • Service mode is now a preference: the service runs the core when it is ready; when the service is not installed, stopped or incompatible, the core runs locally and Settings shows a notice. Neither startup nor saving settings installs or starts the service automatically, so no unexpected UAC prompt appears; once the service is ready again, the next startup or an explicit action uses it again.
  • Local mode and service mode share the same app-managed core data directory owned by the current user, so caches stay writable after switching modes.
  • On Windows the service is controlled over a named pipe. Stopping the core first sends Ctrl+C through the service, so a force-killed Meow no longer leaves adapter DNS behind. Toggling Meow's TUN alone first tries a hot update and reads it back to confirm, restarting the core only if that fails.
  • TUN auto-route can be managed separately; on Unix, TUN permissions are checked and granted automatically when needed.

System Proxy and Network Settings

  • Adds a PAC mode with download, validation and fallback on failure.
  • The mixed, SOCKS5 and HTTP ports can each be enabled with a strategy: fixed, random, or fall back to a free port when occupied. When the port actually bound at runtime differs from the configuration, both are shown. A non-random mixed port from 1.6 stays "fixed" after migration.
  • The system proxy bypass list falls back to the default when empty.
  • In 1.6, "Auto close connections" was a single switch. 2.0 splits it into three settings that each decide whether existing connections are closed: when switching proxies (off / current proxy group only / all connections), when switching Profiles, and when switching routing modes. The old setting is migrated automatically.
  • New DNS cache management and external controller settings pages; fields such as unified-delay and tcp-concurrent can be handed over to the Profile when needed. Fields handed over to the Profile keep the Profile's values even when Clash field filtering is on.

Logs, Diagnostics and Crash Reports

  • The log viewer combines app, service and core logs, with search highlighting, date filtering, JSON highlighting, loading history on scroll and live follow.
  • App logs rotate by file size and local date. Core log rotation and compression can be changed in Settings and take effect immediately; session logs rotate within a disk budget and are compressed with preset and trained dictionaries.
  • Frontend warnings and errors are also written to the app log.
  • Diagnostics: "Report an issue" collects environment information (system, CPU/GPU, WebView, current core) along with recent app and core logs, and shows its progress. The logs are redacted and packed into a ZIP (the latest 5 are kept) that can be revealed in the file manager and dragged into an issue. Redaction removes user info and query parameter values from URLs, credential-like fields, Bearer tokens and home directory paths.
  • Crash reports: on a fatal panic, a separate native window (built with Slint, independent of the main WebView) shows the full report, scrollable and copyable, and can open a prefilled issue in one click. Crashes include the diagnostics as well. Stack frames are recorded as module offsets, and Windows releases archive the symbol files so they can be symbolized afterwards. The report window follows the app language.

Standalone Widget, Tray and Windows

  • Standalone network widget: a lightweight native window (Slint) running as a child process of the app, without loading the main WebView. It comes in large and small styles and shows upload/download speeds and cumulative traffic. Like the tray icon, its logo can switch with the proxy state (no proxy / TUN / system proxy), using either the tray icons or a separate icon set. Measured on a Windows release build: about 24 MiB working set and 3 threads.

Tray

  • WebView tray menu: a new Material You tray panel that can open the main window, toggle the system proxy and TUN, switch between Rule / Global / Direct / Script modes, pick proxy groups and nodes level by level, copy Shell / Cmd / PowerShell environment variables, open the data / config / core / log directories, restart the app or the core, and quit. The native menu is still available and can be selected in Settings; Windows defaults to the WebView menu, other platforms to the native menu.
  • Icons: Windows offers two presets, "Minimal cat" and "Mascot", plus a custom editor: drag built-in icons onto the no proxy / TUN / system proxy states (keyboard operation is supported), or upload an image for each state. macOS keeps using monochrome template icons.
  • The tray can show text and live upload/download speeds; macOS supports colored icons.
  • Proxy nodes in the native tray menu are identified by "group + node", so duplicate group names or renamed nodes no longer check or click the wrong node.
  • The tray menu no longer steals focus when it opens.

Windows

  • A new window manager handles creating, showing, hiding and destroying windows. Every window is created hidden and shown only once its page is ready, so editors and the tray menu no longer flash a blank window; a window not ready within 10 seconds is shown as a fallback. Rapidly opening/closing from the tray or a hotkey no longer depends on the order in which events arrive.
  • Closing can be set to "destroy" or "hide": set a global value, then let the main window, editors and tray menu each inherit it, destroy or hide. The old tray menu close setting is migrated automatically.
  • The Windows main window is no longer created as a transparent window. A transparent window allocates a window-sized bitmap on every repaint; without it, an open window uses one window-sized allocation less (about 30 MB for a 3840×2064 window).
  • The Profile editor and the custom CSS editor open in separate windows.
  • When a window is hidden to the tray or minimized, its WebView is marked invisible and asked to reduce memory usage, and animations stop rendering in the background.

Updates and Distribution

  • Switch between the Stable, Beta and Nightly update channels. Switching from Beta back to Stable keeps the current version until a newer stable release appears.
  • The update dialog lists the release notes of every version skipped since the current one, rendered as GitHub-flavored Markdown.
  • The priority of download sources is configurable (with new mirrors such as ghfast), and download speed tests sample over a fixed time window. The app and the core shut down in order before the installer starts.
  • The Windows installer and the portable build each come in two variants: a standard one using the system WebView2, and one bundling a fixed-version WebView2.
  • Release artifacts are also uploaded to SourceForge and the Internet Archive as mirrors.
  • The NSIS installer gains a sidebar image, and the macOS DMG a background and icon layout.

Windows Loopback Exemption Tool

  • The old UWP loopback tool (enableLoopback.exe, a .NET Framework 4 WinForms program downloaded as latest from a third-party repository, with no source, version or checksum) is replaced by our own enable-loopback, written in Rust and WinUI 3.
  • It fully reproduces the original tool: list AppContainers with search, sorting, multi-select and copy, save exemptions for checked entries, and a command-line mode (-all, -none, -allow, -deny). It fixes the original tool's saving defect: when a write fails, unsaved changes are kept and can be retried directly.
  • The interface follows the app language and supports English, Simplified Chinese, Traditional Chinese, Japanese, Korean and Russian.
  • The tool's version is pinned with the submodule and verified against the GitHub release's SHA-256 after download. On launch it checks for the Windows App Runtime and offers to install it from the Microsoft Store when missing; systems without the Store (such as LTSC) use the official download instead.
  • The app list builds rows only for the visible area, cutting the private working set at startup from about 107 MiB to 71 MiB (v0.1.4).

Languages

  • Adds Japanese, Korean and Traditional Chinese (including the NSIS installer). Supported languages are now English, Simplified Chinese, Traditional Chinese, Japanese, Korean and Russian.
  • The interface language is chosen from the system language on first launch.
  • The Simplified Chinese, Traditional Chinese, English and Korean translations have been reviewed string by string.

Architecture

This section is mainly for contributors, and it also explains where many of the stability improvements come from.

From Global Singletons to Explicit Composition

  • Process-wide global singletons such as Config, CoreManager, Handle and Logger are all gone. Dependencies are injected through constructors, builders, function parameters or actor startup arguments, and the object graph is assembled in a composition root at startup. The few remaining process-wide statics are registered and checked by CI.
  • Long-lived mutable state (configuration, Profiles, the core, the service, WebSocket streams, the tray, hotkeys, update downloads, traffic recording and more) is owned serially by actors. Deterministic logic such as configuration generation, validation and runtime configuration building stays as pure functions independent of Tauri.
  • The application layer exposes domain operations through NyanpasuClient. It is not a service locator and does not expose actor references. Windows, the tray, dialogs, the file system, the network and so on are reached through ports and adapters, and business logic does not use Tauri types directly. UI-independent path resolution, runtime and platform capabilities have moved into neutral crates such as nyanpasu-core and nyanpasu-platform, preparing for non-GUI frontends such as a CLI.

Configuration Layer

  • Configuration is split by domain into the typed nyanpasu-config: application settings (Application), window and session state (SessionState), Clash settings (ClashConfig) and Profiles are persisted separately and each managed by its own actor, instead of sharing one global object that anything could read and write. Every configuration file carries a schema revision; old data is converted by a one-time migration, backed up automatically beforehand and checked for state consistency afterwards.
  • The runtime configuration is generated by pure functions from typed snapshots: Profile sources → pipeline → guarding and filtering of managed fields → post-processing → final configuration, with a snapshot and changes recorded at each step. "What was saved", "what was generated" and "what the core actually loaded" are recorded separately.
  • nyanpasu-state uses TCC-like, inversion-of-control state transactions: configuration actors only build candidate values, and the state layer orchestrates prepare, persistence, CAS commit and notification. Participants that affect the running state (the running configuration, switching cores, switching service mode, etc.) join the same transaction through Try / Confirm / Cancel: if Try fails, the source configuration is not committed; if persistence fails, Cancel restores the previous state. Peripheral effects such as the tray, the UI and the system proxy are reconciled after the commit, and their failures are shown separately as "committed but not converged" rather than as "configuration not saved".
  • Every commit produces a receipt and a state event, so the UI can show whether the configuration has converged and which operations have unconfirmed results, with retry. Commit events are pushed to every window and HTTP client, and the frontend re-reads only the data that actually changed.

Core Management (nyanpasu-runtime)

  • The core lifecycle is owned by the new Core Manager. Each core instance has a monotonically increasing epoch and counts as started only after passing a health probe; a supervisor restarts it with backoff after crashes; the runtime configuration is held privately by the manager with revision-based optimistic concurrency control. Configuration changes are classified as Noop / Patch / Reload / Restart / Switch and rolled back on failure.
  • When the core and configuration support it, switching cores first starts the new core with a configuration that listens on no inbound ports and probes it, then stops the old core and restores the listeners. This moves the seconds-long startup out of the downtime window; the port handover still causes a brief interruption. When the conditions are not met (e.g. an HTTP controller or listener conflicts), it falls back to a direct switch. When the old process cannot be confirmed to have exited, the manager enters quarantine instead of starting a conflicting instance.
  • CoreControl unifies the semantics of local and service mode: validation, revision CAS, classification, execution, verification, rollback and publication happen in one Reconcile transaction; operations run through a bounded serial queue and are idempotent by OperationId. A caller disconnecting or giving up on waiting does not interrupt an operation that has started. The service hosts the same complete CoreControl, not a reduced backend.
  • The in-app CoreActor only selects the local or service endpoint, forwards operations and projects state; it no longer keeps a second copy of the lifecycle state. ServiceActor handles installing the service, version compatibility, probing, reconnecting and uninstalling. Switching between local and service is an explicit handover of control guarded by a generation.
  • The service protocol is upgraded to v2: errors are returned as structured CoreErrorKinds, state is pushed as full snapshots, and the event stream resynchronizes automatically after falling behind (Lagged). Configuration is transferred as content and digest instead of a path local to the service. The Windows core named pipe gains access authorization, and service logs no longer record environment variable values.
  • Clash API access is bound to a specific core instance; old handles become invalid when the instance is replaced, so requests never reach a core that has already been replaced.

Unified RPC

  • App commands are declared with #[nyanpasu_macro::rpc], and Tauri IPC and the optional local HTTP server share the same application layer. Frontend types are generated by Specta, and the frontend calls the backend only through @nyanpasu/rpc and @nyanpasu/query.
  • Commands are classified as queries or mutations by their actual side effects; errors cross the transport as structured data and their details can be copied. Connection details are sent only to pages that subscribe to them.
  • The local HTTP server is off by default, binds only to loopback, generates new access credentials on every start and checks Host/Origin.

New Building Blocks

  • nyanpasu-tsdb: a columnar time-series layer written for traffic analytics. Data is bucketed by time, labels are dictionary-encoded and stored in column chunks; queries run on snapshots; retention cleanup, compaction and space reclamation run as background maintenance tasks; all memory allocated in proportion to data volume counts against a memory budget; redb is the persistence backend.
  • nyanpasu-local-channel: a typed, bidirectional local channel between parent and child processes, with access tokens, type fingerprint checks, a frame size limit and platform ACLs. The standalone widget talks to the main app through it.
  • Background jobs (subscription updates and others) are scheduled by actors in the runtime; run records are written to a transactional redb journal, and logs are captured per job.

Frontend Engineering

  • The frontend is split into source packages such as constants, utils, hooks, platform, rpc, query, theme and ui, with the dependency direction between packages enforced by a check script.
  • Main stack: React 19, TanStack Router / Query / Table, Tailwind CSS 4 (replacing Sass), Paraglide JS (replacing the previous i18n solution), Monaco 0.56 (loaded on demand, kept out of the main bundle), es-toolkit (replacing lodash-es), Oxlint (replacing ESLint); repository scripts moved to Deno.
  • UI state storage: in 1.6, UI state such as the dashboard, proxy group order and theme was stored by jotai atoms in each window's own localStorage. 2.0 writes it to a KV store in the backend's storage.db (redb), read and written by the frontend through useKvStorage, which works much like useState: within a window, each key is read from the backend once and then kept up to date by change events; writes show up immediately in every component using the key and are committed in call order; every read, write and change event carries a revision, and a backlog of events triggers a resync. localStorage serves only as a first-frame cache. This state is therefore shared across windows and HTTP clients and included in configuration backups.
  • Backend events: events are exported as tauri-specta types, generated into bindings together with the commands, and can be bridged to HTTP. After a configuration commit, the state change event says what kind of data changed (application settings, Clash settings, Profiles, and which Profiles), so the frontend refreshes only the affected queries.

Development and Verification

  • Architecture constraints are checked by scripts: lint:architecture-ledger forbids new global service singletons and requires every process-wide static to be registered with its purpose; lint:backend-boundaries checks the dependency direction of backend crates (neutral crates must not depend on Tauri, egui or Slint); lint:frontend-boundaries checks the dependency direction between frontend packages.
  • Testing: actors are tested through typed clients with fake adapters; a new fake-core can stand in for a real core, and the runtime also has integration tests against real cores; the frontend uses Vitest unit and browser tests.
  • Performance: page benchmarks can count renders and the longest main-thread busy time and emit profiles and traces; deno task bench:ab runs A/B comparisons alternating between two commits. The backend provides trace-chrome and dhat-heap profiling features.
  • In-process requests and replies always wait for the real result; timeouts exist only at network and IPC boundaries, and a caller giving up on waiting does not cancel work that has started.
  • Incompatible change for API callers: clash_api_get_providers_proxies returns only Provider summaries (with proxyCount), no longer the full node list, testUrl and expectedStatus (#5831).
  • Development standards live in docs/development/: architecture and ownership, unified RPC, testing and review, workflow, Rust and TypeScript code style, frontend packages and repository scripts.

Performance

The numbers below come from A/B comparisons of specific changes made during development, under differing test conditions. They cannot be added up and do not represent an overall comparison with 1.6.

Scenario Test conditions Before → after
Windows main window No longer created as a transparent window, 3840×2064 window One fewer repaint bitmap of about 30 MB while the window is open (scales with window size)
Standalone widget (Windows) Release build, launched from the app subcommand Working set about 150 → 24 MiB; threads about 32 → 3
Standalone widget (macOS) Apple M3, 2x scaling, 1 update/s, software rendering vs. femtovg Memory footprint about 77 → 16 MiB
enable-loopback v0.1.4, building only rows in the visible area Private working set at startup about 107 → 71 MiB
Runtime configuration snapshots Windows, DHAT, same configuration, window open for 90 s Rust heap (at exit) 10.99 → 8.23 MiB; snapshots 3.63 → 0.61 MiB
Windows background memory Main window closed, 1 hour of synthetic proxy load, Segment Heap enabled Private bytes 43 → 32 MiB
Traffic report query 500,000 rows of hourly data, full report About 72 → 9 ms (vs. the initial tsdb implementation); allocations per request 21.8 → 0.77 MiB
Connections page Chromium, 4x CPU throttling, 6,000 connections sorted by download speed Longest sampled frame 50–67 → 17–33 ms; longest task on open 301–375 → 108–113 ms
Switching proxy groups 30 groups × 1,500 nodes, Chromium, 4x CPU throttling Longest frame 73 → 27 ms
Profile Inspect WebView2, in-app median Open 181 → 43 ms; Output tab 175 → 15 ms
Large diff 1,500 hunks, Chromium Longest task 327–422 ms → no task over 50 ms; highlighting 1.6–2.1 s → about 0.1 s
Opening a large local Profile Large YAML file Main-thread scripting 843 → 319 ms (YAML parsing moved to a worker)
Connection data decoding 150 connections per frame Bytes allocated per request down about 47%–55%

Notes:

  • Windows Segment Heap trades CPU time for memory: in two 30-minute runs, CPU time was 1.3x and 2x that of the default heap, both below 0.5% of a single core. It does not affect WebView2 processes, and Windows versions before 10 2004 ignore the setting.
  • On Linux the widget still renders with femtovg (OpenGL), so the widget numbers above do not apply to Linux.
  • DHAT counts only the Rust allocator, not WebView2, the core process or native system allocations. Most frontend numbers come from large synthetic data sets with 4x CPU throttling, for comparing long tasks and jank; they do not represent absolute frame rates on real devices.
  • Other memory changes: the log buffer shrinks from 128,000 lines to 4,096 (saving about 3.8 MiB); proxy fingerprints use streaming hashes instead of keeping about 2 MiB of JSON resident; the Provider cache keeps summaries only; the shared tokio runtime is capped at 4 worker threads.

Notable Fixes

  • When a subscription's port equaled Nyanpasu's mixed-port, the core could grab the HTTP port first on a cold start, so the mixed port failed to listen and the dashboard wrongly reported "port in use by another program" (#5720).
  • Enabling IPv6 had no effect with Clash Rust: a built-in compatibility script removed the top-level ipv6, which clash-rs actually reads (#6019).
  • After a window was hidden to the tray or minimized, its WebView kept rendering at the display refresh rate, with the renderer and GPU processes using about 0.2 of a core (#5817).
  • Issues when moving windows between monitors with different scaling, restoring window state after minimizing, and Linux window management.
  • Single-instance detection interfering across Windows users and configuration directories.
  • On Windows shutdown or sign-out, the system now waits for the app to finish its clean exit before continuing.
  • Registry-related commands on Windows no longer flash a PowerShell window.
  • Autostart on Linux not working under desktop environments such as KDE; GTK icon cache updates failing.
  • After restarting the core, the routing mode reverted to the old value in the configuration file instead of keeping the user's choice.
  • Inconsistent Clash Rust version formats breaking version display and comparison.
  • NSIS upgrades across versions now update in place by default; auto-update no longer replaces the NSIS installer with the updater executable.
  • Settings such as allow-lan lost after a restart; multiple selected entries in the same proxy group in the tray; the dashboard freezing after the window was hidden.
  • Background jobs, the internal HTTP server and the core shut down in order when the app exits, the main thread panics, a workflow terminates abnormally, or the update installer is launched.

Dependencies and Toolchain

Only migrations that affect users, platforms or architecture are listed; routine version bumps are omitted.

  • Tauri 1 → 2: all window, tray, dialog, clipboard, updater, shell and path APIs migrated.
  • rustls replaces OpenSSL, reqwest replaces isahc: no more dependency on the system OpenSSL.
  • Boa 0.22, mlua 0.12: for JavaScript / Lua Transforms.
  • Specta 2: type generation between frontend and backend.
  • Slint: for the standalone widget and the crash report window, avoiding loading a WebView and GPU stack for these small windows. Windows / macOS use software rendering (softbuffer); Linux uses femtovg.
  • redb and our own nyanpasu-tsdb: for KV storage and traffic time-series data respectively.
  • gxhash: hardware-accelerated hashing used for log indexing and similar tasks, and the reason the CPU must support hardware AES.
  • Frontend dependency migrations are covered under "Architecture → Frontend Engineering".

Thanks

Thanks to everyone who contributed to 2.0, including @greenhat616, @keiko233, @3gf8jv4dv, @Slinetrac, @4o3F, @lmmqxyx404, @xmh0511, @kolya13245, @moduvoice, @latin-1, @MNDIA, @Jimie165, @yokinanya, @trhao99, @temp-maker-temp, @legiz-ru, @gengjiawen, @Sn0wo2, @SherkeyXD, @Rbqwow, @C4a15Wh, @Bihrys, @ArakawaHenri, and everyone who filed issues and helped test.

Full Changelog: v1.6.1...v2.0.0

简体中文

2.0 是自 1.6 系列以来的第一个 stable 版本。本版本重写了前端界面,重建了后端的状态管理与内核管理方式,并新增流量分析、Profile 处理链检查、独立 widget、诊断与崩溃报告等功能。

本文对照的基线是 v1.6.1。Beta 与 RC 期间先合入、后又被替换的实现不单独列出。

升级前请先阅读

  • 配置会自动迁移。 首次启动时会把旧的 verge.yaml、profiles.yaml 等拆分并迁移为新的分域配置。迁移前会自动备份配置目录和 storage.db;迁移失败时,启动对话框提供“打开备份目录”“打开迁移日志”和“退出”。旧配置的语义尽量原样保留,例如 auto_close_connection: false 迁移为“切换代理时不断开连接”,非随机的混合端口迁移为固定端口。跨大版本升级前,仍建议先手动备份一次配置目录;之后也可以在设置中随时创建备份。
  • 发布平台收窄为 6 个目标:Windows、Linux、macOS 各自的 x86_64 与 aarch64。不再提供 Windows/Linux 的 i686 构建,也不再提供 Linux ARMv7(armel/armhf)构建。
  • CPU 需要硬件 AES:x86_64 需支持 AES-NI(Intel 2010 年 Westmere 及以后,AMD 2011 年 Bulldozer 及以后);aarch64 需支持 ARMv8 AES 扩展。部分不带该扩展的 ARM 设备(如 Raspberry Pi 4/5)无法运行。
  • macOS 最低版本提高到 12.6(1.6 为 11.0)。
  • 服务模式需要 nyanpasu-service 2.0.1 或更高版本。 低于该版本的服务会被版本检查拒绝,不会退回旧协议;在系统设置中按提示更新服务即可。
  • Profile、Merge/Overlay 和脚本中的 port、socks-port 不再传给内核。 这两个端口改为与 mixed-port 一样由 Clash 设置统一管理,未设置时会被移除。这样可以避免订阅自带的 port: 7890 抢占混合端口(#5720)。
  • Profile 模型调整。 原来的“多选 Profile + Chain”拆为单个当前 Config 加若干 Transform:多个订阅合并改用 Composition Config 表达,Merge 更名为 Overlay,全局 Chain 改为 Global Transform。Remote / Local 不再是 Profile 的类型,而是每个 Profile 的来源属性(见“Profile 与处理链”)。迁移会自动转换已有数据。
  • Clash Premium 已标记为弃用,将在后续版本移除。 本版本仍可使用;内核管理和仪表盘会标注弃用,切换到它时会给出提示。
  • 第三方面板请使用应用提供的 HTTP 外部控制器设置。内核的命名管道 / Unix socket 控制通道由运行时按实例分配和授权,不再作为可自定义的稳定接口。

新功能

重新设计的界面

  • 主界面按 Material You 重新设计,旧界面已移除。组件基于自有的 @nyanpasu/ui(Radix primitives + Tailwind CSS),不是在旧页面上替换主题。
  • 仪表盘由可自由排列的 widget 组成,可保存布局并单独配置每个 widget;窗口尺寸变化后会按新尺寸选择布局。
  • 主题:跟随系统强调色,或在 HCT 色板中选色并实时预览;支持亮色/暗色/跟随系统,可编写自定义 CSS 或 LESS。默认主题色为 #3e64a7。
  • 内置 Inter Variable 字体,并调整中日韩字体的回退顺序;页面的 lang 属性跟随应用语言,汉字会按所选语言而不是系统区域显示对应的字形。
  • 响应式侧栏与窄窗口导航、按方向的页面切换动画、按平台区分的标题栏(Windows / macOS / Linux),以及可配置的窗口装饰。Linux 默认不再使用原生标题栏。
  • 标题栏菜单(File / Settings / Help)改为统一的菜单栏,支持键盘导航和在已打开的菜单间切换。
  • 设置页按类别分组,内容较多的页面拆分为子页。
  • 关于页显示开源软件许可清单。

流量分析

新增 Traffic Analytics 页面,用于回看历史流量并定位异常:

  • 按总览、连接路径、地理位置、设备、进程等视图查看流量,排行可按流量或连接数加权;选定某个维度筛选后,该维度的其他候选项仍保留在排行中,便于对比。
  • 流量按 Profile 分别统计,按时间分桶并自动清理过期数据;已关闭的连接也可按条件分页查看。
  • 地图按流量占比着色。地区由应用自带的国家索引(基于内核的 geo 数据库)查询,并标注每个地区是如何定位到的。
  • DIRECT 流量和本机来源可以通过公网 IP 探测定位。该探测需要用户明确授权,TUN 开启时不会发起。
  • 规则、连接、流量三个页面之间可以互相跳转并带上筛选条件,跳转后可以返回原页面。
  • 数据由新的时序数据层 nyanpasu-tsdb 保存(见“架构”一节)。Beta/RC 期间记录的流量数据会在升级时自动导入。

Profile 与处理链

  • 类型与来源分离:1.6 的 Profile 类型是 Remote、Local、Merge、Script 四选一,只有配置文件能从远程订阅。2.0 把“是什么”和“从哪来”拆开:类型分为 Config(单个配置文件,或由多个来源组合的 Composition)和 Transform(YAML Overlay、JavaScript / Lua 脚本);来源是每个 Profile 的独立属性,可以是:

    • 远程:从 URL 下载并按间隔同步;
    • 本地托管:文件由应用管理,在应用内编辑;
    • 链接本地文件:引用用户自己的文件,分为“符号链接”(直接引用原文件,Windows 下需要开发者模式或管理员权限)和“镜像”(保存副本,原文件变化时自动同步)。

    因此 Overlay 和脚本也能像订阅一样从远程同步,或直接链接到用户在别处维护的文件。

  • 处理链:Config 之后可以挂接 Overlay、JavaScript、Lua 三类 Transform,并可设置对所有 Config 生效的 Global Transform。处理链支持拖拽排序。

  • Inspect:以全高的步骤浏览器展示配置的生成过程。每一步都有快照、相对上一步的 diff、变更字段列表和步骤日志,并标出最终生效节点和每一步的最高日志级别。最终视图对应内核实际加载的配置。打开时的文档标签和步骤筛选会被记住。

  • Profile 文件夹:可以新建文件夹,用拖拽或“移动到”菜单整理 Profile,删除后可撤销。

  • 从 URL 导入前先预览:先下载内容,再根据响应头和内容判断它是 Config、Overlay 还是脚本,由用户确认类型与来源后导入。

  • Profile 卡片和详情页重新设计,订阅显示剩余流量配额;订阅可全部一键更新,并显示同步状态和历史运行记录;自动更新关闭时会隐藏更新间隔。

  • clash://install-config 深度链接导入可以指定名称,并与快速导入共用同一流程。链接先在后端排队,由主窗口加载后依次导入,页面重载或窗口尚未加载时到达的链接不会丢失。

  • 订阅相关:支持 Remnawave 的 HWID、从响应头同步 Profile 名称、订阅元数据中的隐藏代理组,以及订阅 URL 使用 IP 主机名。

  • 代理组的 include-all 会按 Mihomo 兼容的方式展开,可在 Clash 设置中开关。

  • 生成的配置保持源文件中的键顺序。1.6 会按固定字段表重排顶层键,导致生成的配置与源文件的布局对不上。嵌套映射同样保持原有顺序,dns.nameserver-policy 这类字段的顺序对内核是有意义的。

  • 脚本:JavaScript 支持导入 JSON/纯文本模块、内置辅助模块、内存执行并保留调用栈;JavaScript 与 Lua 都有 console 输出,Lua 处理后保持原有的键顺序。

  • 保存失败时,错误信息会注明是哪个 Profile、哪个文件。

代理、连接与规则

  • 代理:代理组显示在侧栏中,可分文件夹、拖拽排序,布局按 Profile 分别保存;可置顶常用组。组内节点支持搜索、排序和筛选。延迟测试使用各组自己的测试 URL,超时时间可配置;节点卡片显示近期延迟历史;组头显示可用节点数和当前选择链(如 A › B › 节点)。可以对 Provider 触发健康检查。“切换代理时断开连接”改为三档:关闭 / 仅本组 / 全部。
  • 连接:新增已关闭连接标签页、可配置的列、按流量维度与数值范围筛选、连接详情和总量统计;排序和大列表滚动经过优化。
  • 规则:规则列表虚拟化渲染,可按代理筛选,并显示每条规则当前的连接数和流量。
  • Provider:新增独立的 Providers 页面。

内核

  • 新增 Meow(meow-rs)内核,以及独立的 Meow Alpha 通道;新增 Clash Rust Alpha,包括 Windows ARM64。
  • Alpha 内核每次检查更新时都会读取上游滚动发布中当前的构建,避免上游更新后版本清单仍指向已删除的文件,导致下载 404。
  • 内核更新会校验压缩包 SHA-256 和二进制版本;已安装内核无法报告版本时提供“重新安装”。
  • 新的内核管理界面:显示内核状态、控制通道(HTTP / 命名管道 / Unix socket)和服务模式状态。控制通道可以在设置中选择,界面会同时显示实际生效的通道。
  • 使用 Meow 内核时,内核更新会一并安装其附带的 meow-cli 和 agent skill,设置中新增的 AI 页面提供一句话,交给 Claude Code、Codex 等 agent 即可安装该 skill。
  • macOS 上开启 TUN 时,系统 DNS 的接管与恢复纳入内核事务;修改前先持久记录原有 DNS,应用异常退出后也能恢复。
  • 同时运行多个实例(例如开发版与正式版)时,一个实例不会再停止另一个实例通过服务启动的内核。
  • 服务模式改为一项偏好:服务就绪时由服务运行内核,服务未安装、已停止或版本不兼容时改为本地运行,并在设置中提示。启动和保存设置都不会自动安装或启动服务,因此不会意外弹出 UAC;服务恢复就绪后,下一次启动或显式操作会重新使用服务。
  • 本地模式与服务模式使用同一份由应用管理、归当前用户所有的内核数据目录,切换模式后缓存不会因权限不同而无法写入。
  • Windows 下服务通过命名管道控制。停止内核时先经服务发送 Ctrl+C,避免强杀 Meow 后残留适配器 DNS;单独开关 Meow 的 TUN 时先尝试热更新并回读确认,失败后才重启内核。
  • TUN 的 auto-route 可单独管理;Unix 上会检查 TUN 权限并在需要时自动授权。

系统代理与网络设置

  • 新增 PAC 模式,支持下载、校验以及失败时回退。
  • 混合端口、SOCKS5 端口、HTTP 端口可分别启用并选择策略:固定、随机,或被占用时改用空闲端口;运行中实际绑定的端口与配置不同时会一并显示。1.6 中非随机的混合端口迁移后保持“固定”。
  • 系统代理绕过列表为空时恢复默认值。
  • 1.6 中“自动关闭连接”只有一个开关。2.0 拆为三项:切换代理时(关闭 / 仅当前代理组 / 所有连接)、切换 Profile 时、切换路由模式时,分别决定是否关闭现有连接。旧设置会自动迁移。
  • 新增 DNS 缓存管理和外部控制器设置页;unified-delay、tcp-concurrent 等字段可以按需交给 Profile 管理。即使开启了 Clash 字段过滤,指定交给 Profile 的字段也会保留 Profile 中的值。

日志、诊断与崩溃报告

  • 日志查看器合并应用、服务和内核三类日志:支持搜索高亮、日期筛选、JSON 高亮、滚动加载历史和实时跟随。
  • 应用日志按文件大小和本地日期轮转;内核日志的轮转与压缩可在设置中修改并立即生效,会话日志按磁盘预算轮转,并使用预置和训练得到的字典压缩。
  • 前端的 warning 和 error 也会写入应用日志。
  • 诊断:“报告问题”会收集系统、CPU/GPU、WebView、当前内核等环境信息,以及最近的应用日志和内核日志,并显示进度。日志经过脱敏后打包为 ZIP(保留最近 5 份),可以在文件夹中直接定位,拖进 issue 即可附上。脱敏会去掉 URL 中的用户信息和查询参数值、凭据类字段、Bearer token 以及用户主目录路径。
  • 崩溃报告:发生致命 panic 时,弹出一个独立的原生窗口(Slint 实现,不依赖主 WebView),显示可滚动、可复制的完整报告,并能一键打开预填好的 issue。崩溃同样会附带诊断信息。栈帧以模块偏移记录,Windows 发布同时归档符号文件,便于事后还原。报告窗口跟随应用语言。

独立 widget、托盘与窗口

  • 独立网络统计 widget:以应用自身子进程运行的轻量原生窗口(Slint),不加载主 WebView,有大、小两种样式,显示上下行速率和累计流量。Logo 可以像托盘图标一样随代理状态(无代理 / TUN / 系统代理)切换,并可选用托盘图标或单独的一套图标。Windows release 构建实测工作集约 24 MiB、3 个线程。

托盘

  • WebView 托盘菜单:新增 Material You 风格的托盘面板,可打开主窗口、开关系统代理和 TUN、切换规则 / 全局 / 直连 / 脚本模式、逐级选择代理组和节点、复制 Shell / Cmd / PowerShell 环境变量、打开数据 / 配置 / 内核 / 日志目录、重启应用或内核、退出。原生菜单仍然保留,可在设置中切换;Windows 默认使用 WebView 菜单,其他平台默认使用原生菜单。
  • 图标:Windows 提供“简约小猫”“看板娘”两套预设,以及自定义编辑器:可把内置图标拖到无代理 / TUN / 系统代理三个状态上(也支持键盘操作),或为每个状态上传图片。macOS 继续使用单色模板图标。
  • 可以在托盘中显示文字和实时上下行速率;macOS 支持彩色图标。
  • 原生托盘菜单中的代理节点改为按“组 + 节点”识别,代理组同名或节点名称变化时不会再勾错或点错节点。
  • 托盘菜单弹出时不再抢占焦点。

窗口

  • 新的窗口管理器统一负责窗口的创建、显示、隐藏和销毁。所有窗口都先隐藏创建,页面准备好后才显示,编辑器和托盘菜单不再闪出空白窗口;10 秒内未就绪会兜底显示。从托盘或快捷键快速连按打开/关闭,结果也不再取决于事件到达的顺序。
  • 关闭方式可以设置为“销毁”或“隐藏”:设一个全局值,主窗口、编辑器、托盘菜单再分别选择继承、销毁或隐藏。旧版的托盘菜单关闭设置会自动迁移。
  • Windows 主窗口不再以透明窗口创建。透明窗口每次重绘都要分配一块与窗口等大的位图,取消后,窗口打开时的内存会少一块与窗口尺寸成正比的占用(3840×2064 窗口约 30 MB)。
  • Profile 编辑器和自定义 CSS 编辑器在独立窗口中打开。
  • 窗口隐藏到托盘或最小化后,WebView 会被标记为不可见并请求降低内存占用,后台不再继续渲染动画。

更新与分发

  • 可在 Stable、Beta、Nightly 三个更新通道间切换。从 Beta 切回 Stable 时,会保留当前版本直到出现更高的稳定版。
  • 更新对话框会列出当前版本之后所有跳过版本的更新说明,并按 GitHub 格式渲染。
  • 可配置下载源的优先顺序(新增 ghfast 等镜像),下载测速改为按固定时间窗口采样。启动安装程序前会先有序关闭应用和内核。
  • Windows 安装包和便携版各提供两种变体:使用系统 WebView2 的标准版,以及内置固定版本 WebView2 的版本。
  • 发布产物同时上传到 SourceForge 和 Internet Archive 作为镜像。
  • NSIS 安装程序增加侧栏图片,macOS DMG 增加背景和图标布局。

Windows 回环豁免工具

  • 原来的 UWP 回环工具(enableLoopback.exe,一个 .NET Framework 4 WinForms 程序,从第三方仓库下载 latest,没有源码、版本和校验)改为自研的 enable-loopback,使用 Rust 与 WinUI 3 编写。
  • 功能上完整复刻原工具:列出 AppContainer,支持搜索、排序、多选、复制、勾选后保存豁免,以及命令行模式(-all、-none、-allow、-deny)。修复了原工具的保存缺陷:写入失败时保留未保存的修改,可以直接重试。
  • 界面跟随应用语言,支持英语、简体中文、繁体中文、日语、韩语和俄语。
  • 工具版本随 submodule 固定,下载后按 GitHub release 的 SHA-256 校验。启动时检查 Windows App Runtime,缺失时可从 Microsoft Store 安装,Store 不可用的系统(如 LTSC)改用官方下载。
  • 应用列表只为可见区域构建行,启动时的私有工作集约从 107 MiB 降到 71 MiB(v0.1.4)。

语言

  • 新增日语、韩语和繁体中文(含 NSIS 安装程序),现支持英语、简体中文、繁体中文、日语、韩语、俄语。
  • 首次启动时按系统语言自动选择界面语言。
  • 简体中文、繁体中文、英语和韩语的翻译经过了逐条校对。

架构

这一部分主要面向贡献者,也解释了很多稳定性改进的来源。

从全局单例到显式组合

  • Config、CoreManager、Handle、Logger 等进程级全局单例已全部删除。依赖改由构造器、builder、函数参数或 actor 启动参数注入,对象图在启动时的 composition root 中组装。仍保留的少数进程级 static 都有登记,并由 CI 检查。
  • 长期持有可变状态的部分(配置、Profile、内核、服务、WebSocket 流、托盘、快捷键、更新下载、流量记录等)由 actor 串行管理;配置生成、校验、运行时配置构建等确定性逻辑保持为不依赖 Tauri 的纯函数。
  • 应用层统一通过 NyanpasuClient 对外提供领域操作。它不是 service locator,也不暴露 actor 引用。窗口、托盘、对话框、文件系统、网络等通过端口和适配器接入,业务逻辑不直接使用 Tauri 类型。与界面无关的路径解析、运行时和平台能力已拆到 nyanpasu-core、nyanpasu-platform 等中立 crate,为后续 CLI 等非 GUI 前端做准备。

配置层

  • 配置按领域拆分为类型化的 nyanpasu-config:应用设置(Application)、窗口与会话状态(SessionState)、Clash 设置(ClashConfig)和 Profiles 分别持久化、分别由各自的 actor 管理,不再共用一个可随意读写的全局对象。每个配置文件都带有 schema revision,旧数据由一次性迁移转换,迁移前自动备份,迁移后检查状态一致性。
  • 运行时配置由纯函数从类型化快照生成:Profile 来源 → 处理链 → 托管字段的守卫与过滤 → 后处理 → 最终配置,每一步都记录快照和变更。“保存了什么”“生成了什么”“内核实际加载了什么”分开记录。
  • nyanpasu-state 采用类似 TCC 的控制反转型状态事务:配置 actor 只负责构造候选值,由状态层编排 prepare、持久化、CAS commit 和通知。对当前运行有影响的参与者(运行中的配置、切换内核、切换服务模式等)通过 Try / Confirm / Cancel 参与同一笔事务:Try 失败时源配置不提交,持久化失败时 Cancel 恢复原状态。托盘、界面、系统代理等外围效果在提交之后再协调,其失败会单独显示为“已提交但未收敛”,不会被当作“配置未保存”。
  • 每次提交都有收据和状态事件,界面可以显示配置的收敛状态和结果未确认的操作,并提供重试。提交事件会推送到所有窗口和 HTTP 客户端,前端只重新读取实际发生变化的数据。

内核管理(nyanpasu-runtime)

  • 内核生命周期由新的 Core Manager 负责。每个内核实例有单调递增的 epoch,只有通过健康探测才算启动成功;由 supervisor 负责崩溃后的退避重启;运行时配置由 manager 私有保存,带 revision 乐观并发控制。配置变更会被分类为 Noop / Patch / Reload / Restart / Switch,失败时回滚。
  • 内核和配置支持时,切换内核会先让新内核以不监听任何入站端口的配置启动并完成探活,再停止旧内核、恢复监听,从而把秒级的启动时间移出停机窗口;端口交接仍有短暂中断。不满足条件时(如 HTTP 控制器、监听冲突)退回直接切换。无法确认旧进程已退出时进入隔离状态,不贸然启动冲突实例。
  • CoreControl 统一了本地模式和服务模式的语义:校验、revision CAS、分类、执行、验证、回退和发布在同一个 Reconcile 事务中完成;操作经有界串行队列执行,并以 OperationId 保证幂等。调用方断开或放弃等待不会中断已开始的操作。服务端承载的是同一套完整的 CoreControl,不是简化版后端。
  • 应用内的 CoreActor 只负责选择本地或服务端点、转发操作和投影状态,不再保存第二份生命周期状态;ServiceActor 负责服务的安装、版本兼容、探活、重连与卸载。本地与服务之间的切换是显式的控制权交接,带 generation 防护。
  • 服务端协议升级为 v2:错误以 CoreErrorKind 结构化返回,状态以完整快照推送,事件流丢失(Lagged)后自动重新同步;配置以内容和摘要传输,不再传递服务端本地路径。Windows 内核命名管道增加访问授权,服务日志不记录环境变量的值。
  • Clash API 访问绑定到具体内核实例,实例更换后旧句柄失效,避免请求打到已被替换的内核。

统一 RPC

  • 应用命令用 #[nyanpasu_macro::rpc] 声明,Tauri IPC 和可选的本地 HTTP 服务共用同一个应用层;前端类型由 Specta 生成,前端只通过 @nyanpasu/rpc 和 @nyanpasu/query 调用后端。
  • 命令按实际副作用区分 query 与 mutation,错误以结构化数据跨传输层传递,并可复制详情。连接详情只发给订阅了它的页面。
  • 本地 HTTP 服务默认关闭,只绑定回环地址,每次启动生成新的访问凭据,并检查 Host/Origin。

新的基础组件

  • nyanpasu-tsdb:为流量分析编写的列式时序数据层。数据按时间分桶,标签以字典编码,按列分块存储;查询基于快照;保留期清理、合并与空间回收在后台维护任务中完成;所有按数据量分配的内存都计入内存预算,以 redb 作为持久化后端。
  • nyanpasu-local-channel:父子进程之间的类型化本地双向通道,带访问令牌、类型指纹校验、帧大小上限和平台 ACL。独立 widget 通过它与主程序通信。
  • 后台任务(订阅更新等)由 runtime 中的 actor 调度,执行记录写入事务型 redb 日志,并按任务分别捕获日志。

前端工程

  • 前端拆分为 constants、utils、hooks、platform、rpc、query、theme、ui 等源码包,包之间的依赖方向由检查脚本约束。
  • 主要技术栈:React 19、TanStack Router / Query / Table、Tailwind CSS 4(取代 Sass)、Paraglide JS(取代原 i18n 方案)、Monaco 0.56(按需加载,不进入主包)、es-toolkit(取代 lodash-es)、Oxlint(取代 ESLint),仓库脚本迁移到 Deno。
  • 界面状态存储:1.6 中仪表盘、代理组排序、主题等界面状态由 jotai atom 写在各窗口自己的 localStorage 里。2.0 改为写入后端 storage.db(redb)中的 KV 存储,前端通过 useKvStorage 读写,用法类似 useState:同一窗口内同一个键只读取一次后端,此后由变更事件保持最新;写入会立即反映到所有使用该键的组件,并按调用顺序提交;每次读、写和变更事件都带 revision,事件积压后会触发重新同步。localStorage 只作为首帧缓存。这些状态因此在多个窗口和 HTTP 客户端之间共享,也会随配置备份一起保存。
  • 后端事件:事件以 tauri-specta 类型导出,与命令一起生成绑定,并可桥接到 HTTP。配置提交后,状态变化事件会说明具体改了哪类数据(应用设置、Clash 设置、Profiles,以及涉及的 Profile),前端据此只刷新受影响的查询。

开发与验证

  • 架构约束由脚本检查:lint:architecture-ledger 禁止新增全局服务单例,进程级 static 必须登记用途;lint:backend-boundaries 检查后端 crate 的依赖方向(中立 crate 不得依赖 Tauri、egui 或 Slint);lint:frontend-boundaries 检查前端包之间的依赖方向。
  • 测试:actor 通过类型化 client 配合假适配器测试;新增可替代真实内核的 fake-core,runtime 另有使用真实内核的集成测试;前端使用 Vitest 的单元测试和浏览器测试。
  • 性能:页面基准测试可以统计渲染次数、主线程最长忙碌时间,并输出 profile 和 trace;deno task bench:ab 在两个提交之间交替运行 A/B 对比。后端提供 trace-chrome 和 dhat-heap 两个 profiling feature。
  • 进程内的请求与应答一律等待真实结果,超时只设在网络和 IPC 边界;调用方放弃等待不会取消已经开始的工作。
  • 对接口调用方不兼容的变化:clash_api_get_providers_proxies 只返回 Provider 摘要(含 proxyCount),不再返回完整节点列表、testUrl 和 expectedStatus(#5831)。
  • 开发规范集中在 docs/development/:架构与所有权、统一 RPC、测试与评审、工作流、Rust 与 TypeScript 代码风格、前端包、仓库脚本。

性能

以下数据来自开发期间针对具体改动的 A/B 对比,测试条件各不相同。它们不能相加,也不代表与 1.6 的整体对比。

场景 测试条件 改动前 → 改动后
Windows 主窗口 不再以透明窗口创建,3840×2064 窗口 窗口打开时少一块约 30 MB 的重绘位图(随窗口尺寸变化)
独立 widget(Windows) release 构建,从应用子命令启动 工作集约 150 → 24 MiB;线程约 32 → 3
独立 widget(macOS) Apple M3,2x 缩放,1 次/秒更新,软件渲染对比 femtovg 内存占用(footprint)约 77 → 16 MiB
enable-loopback v0.1.4,只构建可见区域的行 启动私有工作集约 107 → 71 MiB
运行时配置快照 Windows,DHAT,同一配置,窗口打开 90 秒 Rust 堆(结束时)10.99 → 8.23 MiB;快照部分 3.63 → 0.61 MiB
Windows 后台内存 主窗口关闭,1 小时合成代理负载,启用 Segment Heap 私有字节 43 → 32 MiB
流量报表查询 500,000 行小时数据,完整报表 约 72 → 9 ms(相对初版 tsdb 实现);单次请求分配 21.8 → 0.77 MiB
连接页 Chromium,4x CPU 降速,6,000 条连接按下载速度排序 采样最长帧 50–67 → 17–33 ms;打开时最长任务 301–375 → 108–113 ms
切换代理组 30 组 × 1,500 节点,Chromium,4x CPU 降速 最长帧 73 → 27 ms
Profile Inspect WebView2,应用内中位数 打开 181 → 43 ms;Output 标签 175 → 15 ms
大型 diff 1,500 个 hunk,Chromium 最长任务 327–422 ms → 无超过 50 ms 的任务;高亮 1.6–2.1 s → 约 0.1 s
打开大型本地 Profile 大 YAML 文件 主线程脚本耗时 843 → 319 ms(YAML 解析移入 worker)
连接数据解码 每帧 150 条连接 请求的分配字节减少约 47%–55%

说明:

  • Windows Segment Heap 以更多 CPU 时间换取更少内存:两轮 30 分钟测试中 CPU 时间为原堆的 1.3 倍和 2 倍,但都低于单核 0.5%。它不影响 WebView2 进程,Windows 10 2004 之前的系统会忽略该设置。
  • Linux 上的 widget 仍使用 femtovg(OpenGL)渲染,上表中的 widget 数据不适用于 Linux。
  • DHAT 只统计 Rust 分配器,不包括 WebView2、内核进程和系统原生分配。前端数据多来自合成的大数据量和 4x CPU 降速,用于比较长任务和卡顿,不代表真实设备上的绝对帧率。
  • 其他内存调整:日志缓冲区从 128,000 行降为 4,096 行(约省 3.8 MiB);代理指纹改为流式哈希,不再常驻约 2 MiB 的 JSON;Provider 缓存只保留摘要;共享 tokio 运行时的 worker 线程上限为 4。

重要修复

  • 订阅中的 port 与 Nyanpasu 的 mixed-port 相同时,内核在冷启动时可能先占用 HTTP 端口,导致混合端口监听失败、仪表盘误报“端口被其他程序占用”(#5720)。
  • Clash Rust 下开启 IPv6 不生效:内置兼容脚本会删除顶层 ipv6,而 clash-rs 实际读取该字段(#6019)。
  • 窗口隐藏到托盘或最小化后,WebView 仍按显示器刷新率渲染,渲染与 GPU 进程持续占用约 0.2 个核心(#5817)。
  • 跨缩放比例的多显示器之间移动窗口、最小化后恢复窗口状态、Linux 窗口管理等问题。
  • Windows 多用户、多配置目录下单实例检测互相干扰的问题。
  • Windows 关机或注销时,系统会等待应用完成正常退出的清理流程,然后再继续关机。
  • Windows 上执行注册表相关命令时不再闪出 PowerShell 窗口。
  • Linux 开机自启在 KDE 等桌面环境下不生效;GTK 图标缓存更新失败。
  • 重启内核后路由模式回到配置文件中的旧值,没有保留用户的选择。
  • Clash Rust 内核版本号格式不一致,导致版本显示和比较出错。
  • NSIS 跨版本升级默认改为原位更新;自动更新不会再用 updater 可执行文件替换 NSIS 安装程序。
  • allow-lan 等设置在重启后丢失;托盘中同一代理组出现多个选中项;仪表盘在窗口隐藏后冻结。
  • 应用退出、主线程 panic、工作流异常终止和启动更新安装程序时,后台任务、内部 HTTP 服务和内核按顺序关闭。

依赖与工具链

只列出影响用户、平台或架构的迁移,常规版本更新从略。

  • Tauri 1 → 2:窗口、托盘、对话框、剪贴板、更新、shell 与路径相关 API 全部迁移。
  • rustls 取代 OpenSSL,reqwest 取代 isahc:不再依赖系统 OpenSSL。
  • Boa 0.22、mlua 0.12:用于 JavaScript / Lua Transform。
  • Specta 2:前后端类型生成。
  • Slint:用于独立 widget 和崩溃报告窗口,避免为这些小窗口加载 WebView 和 GPU 栈。Windows / macOS 使用软件渲染(softbuffer),Linux 使用 femtovg。
  • redb 与自研 nyanpasu-tsdb:分别用于 KV 存储与流量时序数据。
  • gxhash:硬件加速哈希,用于日志索引等场景,也是要求 CPU 支持硬件 AES 的原因。
  • 前端依赖迁移见“架构 → 前端工程”。

致谢

感谢参与 2.0 开发的所有贡献者,包括 @greenhat616、@keiko233、@3gf8jv4dv、@Slinetrac、@4o3F、@lmmqxyx404、@xmh0511、@kolya13245、@moduvoice、@latin-1、@MNDIA、@Jimie165、@yokinanya、@trhao99、@temp-maker-temp、@legiz-ru、@gengjiawen、@Sn0wo2、@SherkeyXD、@Rbqwow、@C4a15Wh、@Bihrys、@ArakawaHenri,以及提交 issue 和参与测试的用户。

完整变更:v1.6.1...v2.0.0

Don't miss a new clash-nyanpasu release

NewReleases is sending notifications on new releases.