Clash Verge Developer Docs

How the interface, the Tauri layer, and Mihomo divide the work, what you need locally, how to build, and what to check before opening a pull request.

  • ClientTauri 2 + Rust + React
  • CoreMihomo (formerly Clash Meta)
  • LicenseGPL-3.0

Clash Verge Frontend, Tauri Layer and Mihomo Core

Clash Verge is a Tauri 2 desktop application with separate frontend, desktop integration and proxy-core layers. React and TypeScript implement the interface, Rust and Tauri provide desktop and operating-system integration, while Mihomo handles configuration parsing, DNS, routing rules, proxy groups and traffic forwarding. Debugging should identify whether a problem belongs to the interface, desktop application layer or Mihomo core.

Layer Technology Responsibilities
Interface layer React + TypeScript + Vite Profile, node, proxy-group, rule, connection and log presentation and interaction
Application layer Tauri 2 + Rust Window and tray handling, Mihomo process control, system proxy, TUN, config read/write and desktop integration
Core layer Mihomo (Clash Meta) Configuration parsing, protocol handling, DNS, rule matching, proxy groups, traffic forwarding and external-controller API

Note A UI symptom does not necessarily indicate a frontend fault. Trace the feature through the React interface, Tauri / Rust application layer and Mihomo core before locating the issue. System integration and privileged operations belong to the desktop layer; proxy and routing behavior belong to Mihomo.

Clash Verge Local Development Dependencies

Local development requires Node.js, Corepack / pnpm, a Rust toolchain and the operating-system dependencies required by Tauri. Windows, macOS and Linux need different system-level tools.

System What to install Notes
All platforms Node.js, Corepack/pnpm and a Rust toolchain Enable Corepack, then confirm node, pnpm and cargo are available
Windows MSVC Rust toolchain and GNU patch; Windows ARM also needs LLVM/clang Make sure Rust and Node.js are on PATH; Windows ARM needs clang because of native dependencies
macOS Xcode Command Line Tools xcode-select --install
Linux WebKitGTK 4.1, Ayatana AppIndicator, librsvg, patchelf and related build packages Dependency names differ by distribution; compare the current Tauri requirements with your Linux package manager

Caution The current contribution guide lists Ubuntu packages such as libwebkit2gtk-4.1-dev, libayatana-appindicator3-dev, librsvg2-dev and patchelf. Other distributions use different package names, so follow the error and your platform's Tauri requirements.

Clash Verge prebuild, dev and build Commands

The local sequence installs JavaScript dependencies, prepares Mihomo and related runtime resources with prebuild, then starts development mode or produces a platform build.

  1. Clone the repository

    Get the source and change into the project directory.

  2. Install Project Dependencies

    Enable Corepack and use the repository's pnpm setup so the lockfile and dependency state match the project.

  3. Prepare Mihomo and Runtime Assets

    Run prebuild to prepare the Mihomo core and service / sidecar resources required by the current platform.

  4. Start Development Mode

    pnpm dev is the standard development command. The repository also exposes pnpm dev:diff and pnpm dev:tauri for specific development cases.

  5. Generate a Platform Build

    Use pnpm build for the standard Tauri build or pnpm build:fast for a faster local test build. Output paths depend on the active target and Tauri bundle configuration.

shell
# 1. Clone the repository
git clone https://github.com/clash-verge-rev/clash-verge-rev.git
cd clash-verge-rev

# 2. Enable Corepack and install dependencies
corepack enable
pnpm install

# 3. Download Mihomo and service binaries
pnpm run prebuild
# Re-download and overwrite them when needed:
# pnpm run prebuild --force

# 4. Start development
pnpm dev
# Alternatives:
# pnpm dev:diff
# pnpm dev:tauri

# 5. Build the current platform
pnpm build
# Faster test build:
# pnpm build:fast

Note The dev branch currently defines prebuild, dev, dev:diff, dev:tauri, build and build:fast in package.json. Check that file again when working against a different commit or release branch.

Clash Verge src, src-tauri and Build Scripts

The repository separates the React frontend from the Tauri / Rust application layer, with build scripts and CI configuration around them. Use the current tree to locate the real implementation before changing code.

directory tree (illustrative)
clash-verge-rev/
├─ src/                    # React + TypeScript frontend
├─ src-tauri/              # Tauri 2 + Rust desktop application
│  ├─ src/                 # Rust application and system integration
│  ├─ resources/           # Runtime resources
│  ├─ sidecar/             # Mihomo and related sidecar binaries
│  ├─ Cargo.toml           # Rust dependencies
│  └─ tauri.conf.json      # Tauri app and bundle configuration
├─ scripts/                # Prebuild, release and development scripts
├─ .github/                # CI and GitHub Actions
├─ package.json            # pnpm scripts and frontend dependencies
├─ CONTRIBUTING.md         # Current development and contribution process
└─ UPDATELOG.md            # Project update log

Note This is an orientation map rather than a frozen contract. The current i18n process uses locale folders under src/locales/<lang>/ for frontend strings and separate backend locale files, so follow CONTRIBUTING_i18n.md when a change affects translated copy.

Clash Verge Tauri invoke and event IPC

Clash Verge uses Tauri APIs to connect the React frontend with the Rust application layer. Frontend code can call registered Rust commands with invoke, while longer-lived state changes can be delivered through Tauri events. Command and event names should be traced from the current source tree.

typescript
import { invoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";

// Example only: use command and event names from the current source tree
const result = await invoke("command_name", {
  payload: { key: "value" },
});

const unlisten = await listen("event-name", (event) => {
  console.log(event.payload);
});

// Stop listening when the component or view is disposed
unlisten();
rust
// Example only: expose a Rust function as a Tauri command
#[tauri::command]
fn command_name(payload: serde_json::Value) -> Result<serde_json::Value, String> {
    Ok(payload)
}

fn main() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![command_name])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Caution These snippets explain the Tauri IPC model, not the current Clash Verge command registry. Trace the frontend call site to the corresponding Rust command, event and data type before implementing or documenting a feature.

Mihomo external-controller API

Mihomo can expose control endpoints through external-controller. Clash Verge uses core APIs to inspect and modify runtime state, while external tools can query configs, proxies, connections, rules, logs and traffic when the controller is enabled and authenticated.

shell
# Example only: replace with the controller address used by your running profile
BASE=http://127.0.0.1:9090
AUTH="Authorization: Bearer your-secret"

# Version and current runtime config
curl -H "$AUTH" "$BASE/version"
curl -H "$AUTH" "$BASE/configs"

# Change runtime mode: rule / global / direct
curl -X PATCH -H "$AUTH" -d '{"mode":"rule"}' "$BASE/configs"

# Proxy groups and active connections
curl -H "$AUTH" "$BASE/proxies"
curl -H "$AUTH" "$BASE/connections"

# Live traffic and logs can also be consumed over WebSocket
# ws://127.0.0.1:9090/traffic?token=your-secret
# ws://127.0.0.1:9090/logs?level=info&token=your-secret
Endpoint Method Purpose
/version GET Core version; commonly used to check whether the API is reachable
/configs GET / PATCH / PUT Read the config, patch parts of it (mode, ports), or reload the whole config file
/proxies GET List all nodes and proxy groups along with the current selection
/proxies/{name} GET / PUT Inspect a single node, or switch the selected node for a proxy group
/proxies/{name}/delay GET Returns latency for a given test URL and timeout
/rules GET The rules currently in effect, useful for confirming that rules loaded as expected
/connections GET / DELETE List active connections, or close a specific one
/traffic, /logs WebSocket Live upload/download traffic and the log stream

Caution Treat the controller URL and secret as runtime configuration rather than fixed values from an example. An exposed controller can change proxy behavior and inspect runtime state, so bind it conservatively and protect it with authentication when appropriate.

Clash Verge Local Data, Profiles and Logs

Client settings, downloaded profiles, generated configs, scripts and logs are stored locally. These files are relevant when debugging startup, migration, profile generation or service problems.

System Approximate location What's inside
Windows %APPDATA%\<app identifier>\ Client settings, profiles and generated configs, Extension Config/Script files, Mihomo and application logs
macOS ~/Library/Application Support/<app identifier>/
Linux ~/.local/share/<app identifier>/

Note Paths and application identifiers can differ by platform or build channel. Prefer the client's own app-directory and log-directory shortcuts when available, and back up important data before testing migrations or manual file edits.

Clash Verge Code Contributions and Local Checks

The contribution process focuses on a defined issue, a narrow code change, reproducible verification and the required frontend and Rust checks before review.

  1. Define the Change Scope

    Keep each change focused on one problem or feature area. Avoid mixing unrelated refactors, formatting changes or dependency updates into the same pull request.

  2. Fork and create a branch

    One branch, one thing, with a name that states the intent — for example fix/tray-menu-crash.

  3. Run the Required Checks

    Run cargo clippy-all for Rust, pnpm lint for the frontend, then format with cargo fmt and pnpm format. Also reproduce the reported behavior and verify the actual fix.

  4. Keep Commits Focused

    Keep commit messages and diffs focused enough that reviewers can connect each changed area to the problem being addressed. Follow the repository's current signing requirements.

  5. Explain Verification in the Pull Request

    Describe the problem in your own words, show how you reproduced and verified it, and include screenshots when UI behavior changes. Include the verification details required by the current contribution guidance in the pull request body.

Caution The repository applies its current contribution requirements to commit signing, scope and verification. GPL-3.0 licensing still applies, and new dependencies should have a clear technical reason and a compatible license.

Clash Verge Releases, AutoBuilds and Local Builds

Versioned releases and AutoBuilds are client build channels, while Mihomo Stable / Alpha belongs to the proxy-core layer. These version channels should be tracked separately.

Channel Purpose Notes
Stable Release Versioned release and archival Versioned application releases with release notes and release assets
AutoBuild Validation of newer development commits Development builds produced from newer commits; behavior can differ from a tagged release
Self-built Local development and customization Local output depends on your build target, signing configuration and platform setup

Note Application release channels and Mihomo core channels are different layers. A Clash Verge AutoBuild is not the same thing as switching the bundled Mihomo core to its Alpha channel. A locally built binary should be identified by its source commit, build settings and signing state.

Clash Verge Local Build and Runtime Troubleshooting

Local build and development failures usually involve dependencies, platform toolchains, missing prebuild resources or runtime WebView / system libraries. Start with the exact error and the step that produced it.

Symptom Common cause What to do
Dependency install reports a lockfile error Project dependencies were installed with a different package-manager state Enable Corepack, remove the conflicting install state if necessary, then run pnpm install
Dev mode exits right after starting The runtime asset preparation step was skipped Run pnpm run prebuild; use --force when you need to re-download Mihomo and service binaries
Rust build reports a missing linker Platform build tools are missing (MSVC / CLT) Install the system build tools, reopen the terminal, then build again
Linux reports a missing library Development libraries such as WebKitGTK are missing Install the matching -dev package for the library named in the error
Prebuild asset download times out The development environment cannot reach the asset download endpoints Fix terminal/network access first, then rerun the documented prebuild process
Packaging succeeds but the app opens blank The frontend assets weren't built properly, or WebView2 is missing Confirm the frontend build output exists; on Windows, install the WebView2 runtime
Interface strings you edited disappear after switching language Frontend and/or backend locale bundles were not kept in sync Follow CONTRIBUTING_i18n.md, align locale keys and run the current i18n checks for the area you changed

Clash Verge Repository and Contribution Entry Point

Set up the current development environment, reproduce the target behavior, keep the code change focused, run the required checks and document verification in the pull request.

Clash Verge for developers: building locally and the core API