diff --git a/package.json b/package.json
index 88daf360ddaeafea6977dbd82dd6abc75762ce0a..e670c94710d92cf25d825b423fa59cc2ea2db50c 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
   "scripts": {
     "dev": "tauri dev",
     "dev:diff": "tauri dev -f verge-dev -c src-tauri/tauri.diff.json",
-    "dev:meta": "tauri dev -f meta-dev -c src-tauri/tauri.meta.json",
+    "dev:core": "cross-env VITE_MULTI_CORE=1 yarn dev:diff",
     "build": "tauri build",
     "tauri": "tauri",
     "web:dev": "vite",
@@ -47,6 +47,7 @@
     "@types/react-dom": "^17.0.0",
     "@vitejs/plugin-react": "^1.3.2",
     "adm-zip": "^0.5.9",
+    "cross-env": "^7.0.3",
     "fs-extra": "^10.0.0",
     "https-proxy-agent": "^5.0.1",
     "husky": "^7.0.0",
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 9b4c8c88378e727733c98ee409f5bde13613e315..07985081176104911e93b98b9b8fb20a553a2f1b 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -45,9 +45,7 @@ windows-sys = { version = "0.36", features = ["Win32_System_LibraryLoader", "Win
 [features]
 default = ["custom-protocol", "tauri/ayatana-tray"]
 custom-protocol = ["tauri/custom-protocol"]
-meta-dev = ["clash-meta", "verge-dev"]
 verge-dev = []
-clash-meta = []
 debug-yml = []
 
 [profile.release]
diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs
index bb65a196ef19637598d6815ef364b89ff4c04198..f3aa877bf0c2b2026f4a33c19e9e9c522a62bb30 100644
--- a/src-tauri/src/cmds.rs
+++ b/src-tauri/src/cmds.rs
@@ -196,10 +196,16 @@ pub fn patch_verge_config(
   payload: Verge,
   app_handle: tauri::AppHandle,
   core: State<'_, Core>,
-) -> Result<(), String> {
+) -> CmdResult {
   wrap_err!(core.patch_verge(payload, &app_handle))
 }
 
+/// change clash core
+#[tauri::command]
+pub fn change_clash_core(core: State<'_, Core>, clash_core: Option<String>) -> CmdResult {
+  wrap_err!(core.change_core(clash_core))
+}
+
 /// restart the sidecar
 #[tauri::command]
 pub fn restart_sidecar(core: State<'_, Core>) -> CmdResult {
diff --git a/src-tauri/src/core/mod.rs b/src-tauri/src/core/mod.rs
index e7be3bb109931844ba930db59438b87c843f14fb..5907cf4cbaa3c64ae03cd3afc5ea818fa9c6417b 100644
--- a/src-tauri/src/core/mod.rs
+++ b/src-tauri/src/core/mod.rs
@@ -65,22 +65,21 @@ impl Core {
 
   /// initialize the core state
   pub fn init(&self, app_handle: tauri::AppHandle) {
+    let verge = self.verge.lock();
+    let clash_core = verge.clash_core.clone();
+
+    let mut service = self.service.lock();
+    service.set_core(clash_core);
+
     #[cfg(windows)]
     {
-      let verge = self.verge.lock();
       let enable = verge.enable_service_mode.clone();
-
-      let mut service = self.service.lock();
       service.set_mode(enable.unwrap_or(false));
-
-      log_if_err!(service.start());
     }
 
-    #[cfg(not(windows))]
-    {
-      let mut service = self.service.lock();
-      log_if_err!(service.start());
-    }
+    log_if_err!(service.start());
+    drop(verge);
+    drop(service);
 
     log_if_err!(self.activate());
 
@@ -138,6 +137,31 @@ impl Core {
     self.activate_enhanced(true)
   }
 
+  /// change the clash core
+  pub fn change_core(&self, clash_core: Option<String>) -> Result<()> {
+    let clash_core = clash_core.unwrap_or("clash".into());
+
+    if &clash_core != "clash" && &clash_core != "clash-meta" {
+      bail!("invalid clash core name \"{clash_core}\"");
+    }
+
+    let mut verge = self.verge.lock();
+    verge.patch_config(Verge {
+      clash_core: Some(clash_core.clone()),
+      ..Verge::default()
+    })?;
+    drop(verge);
+
+    let mut service = self.service.lock();
+    service.stop()?;
+    service.set_core(Some(clash_core));
+    service.start()?;
+    drop(service);
+
+    self.activate()?;
+    self.activate_enhanced(true)
+  }
+
   /// Patch Clash
   /// handle the clash config changed
   pub fn patch_clash(&self, patch: Mapping) -> Result<()> {
diff --git a/src-tauri/src/core/multi.rs b/src-tauri/src/core/multi.rs
new file mode 100644
index 0000000000000000000000000000000000000000..d77983062af0c92924e40db791b2c42fa3d44ff3
--- /dev/null
+++ b/src-tauri/src/core/multi.rs
@@ -0,0 +1,26 @@
+use anyhow::{Context, Result};
+use std::env::current_exe;
+
+pub struct CoreItem {
+  pub name: String,
+  pub path: String,
+}
+
+pub struct Multi {}
+
+impl Multi {
+  pub fn list() -> Result<Vec<CoreItem>> {
+    let paths = current_exe()
+      .unwrap()
+      .parent()
+      .unwrap()
+      .read_dir()
+      .context("failed to current dir")?;
+
+    for path in paths {
+      dbg!(path.unwrap().path().metadata().unwrap().permissions().);
+    }
+
+    Ok(vec![])
+  }
+}
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index 8abe5e7c7bfe442d009d524d7d67c72bcb029b5a..0cec26d145f1fe2adc693c95cfce2c287fae9e2e 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -100,15 +100,16 @@ fn main() -> std::io::Result<()> {
     })
     .invoke_handler(tauri::generate_handler![
       // common
-      cmds::restart_sidecar,
       cmds::get_sys_proxy,
       cmds::get_cur_proxy,
-      cmds::kill_sidecar,
       cmds::open_app_dir,
       cmds::open_logs_dir,
+      cmds::kill_sidecar,
+      cmds::restart_sidecar,
       // clash
       cmds::get_clash_info,
       cmds::patch_clash_config,
+      cmds::change_clash_core,
       // verge
       cmds::get_verge_config,
       cmds::patch_verge_config,
diff --git a/src-tauri/tauri.diff.json b/src-tauri/tauri.diff.json
index afae5ff0238162105176a6790e9db1073d817445..cd2618c1161f0e6566028bff23c09e17a06ed5fe 100644
--- a/src-tauri/tauri.diff.json
+++ b/src-tauri/tauri.diff.json
@@ -1,9 +1,8 @@
-{
-    "tauri": {
-      "bundle": {
-        "identifier": "top.gydi.clashverge.dev",
-        "externalBin": ["sidecar/clash", "sidecar/clash-meta"]
-      }
-    }
-  }
-  
\ No newline at end of file
+{
+  "tauri": {
+    "bundle": {
+      "identifier": "top.gydi.clashverge.dev",
+      "externalBin": ["sidecar/clash", "sidecar/clash-meta"]
+    }
+  }
+}
diff --git a/src-tauri/tauri.meta.json b/src-tauri/tauri.meta.json
deleted file mode 100644
index 9f4bb77979796ce1759622a37a0071fcf61c1490..0000000000000000000000000000000000000000
--- a/src-tauri/tauri.meta.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "tauri": {
-    "bundle": {
-      "externalBin": ["sidecar/clash", "sidecar/clash-meta"]
-    }
-  }
-}
diff --git a/src/components/setting/core-switch.tsx b/src/components/setting/core-switch.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b7ebd08295a85b5a6ae3ce3b9ab0f6dac476e117
--- /dev/null
+++ b/src/components/setting/core-switch.tsx
@@ -0,0 +1,84 @@
+import useSWR, { useSWRConfig } from "swr";
+import { useState } from "react";
+import { useLockFn } from "ahooks";
+import { Menu, MenuItem } from "@mui/material";
+import { Settings } from "@mui/icons-material";
+import { changeClashCore, getVergeConfig } from "../../services/cmds";
+import getSystem from "../../utils/get-system";
+import Notice from "../base/base-notice";
+
+const OS = getSystem();
+
+const VALID_CORE = [
+  { name: "Clash", core: "clash" },
+  { name: "Clash Meta", core: "clash-meta" },
+];
+
+const CoreSwitch = () => {
+  const { mutate } = useSWRConfig();
+
+  const { data: vergeConfig } = useSWR("getVergeConfig", getVergeConfig);
+
+  const [anchorEl, setAnchorEl] = useState<any>(null);
+  const [position, setPosition] = useState({ left: 0, top: 0 });
+
+  const { clash_core = "clash" } = vergeConfig ?? {};
+
+  const onCoreChange = useLockFn(async (core: string) => {
+    if (core === clash_core) return;
+
+    try {
+      await changeClashCore(core);
+      mutate("getVergeConfig");
+      mutate("getClashConfig");
+      mutate("getVersion");
+      setAnchorEl(null);
+      Notice.success(`Successfully switch to ${core}`, 1000);
+    } catch (err: any) {
+      Notice.error(err?.message || err.toString());
+    }
+  });
+
+  return (
+    <>
+      <Settings
+        fontSize="small"
+        style={{ cursor: "pointer" }}
+        onClick={(event) => {
+          const { clientX, clientY } = event;
+          setPosition({ top: clientY, left: clientX });
+          setAnchorEl(event.currentTarget);
+        }}
+      />
+
+      <Menu
+        open={!!anchorEl}
+        anchorEl={anchorEl}
+        onClose={() => setAnchorEl(null)}
+        anchorPosition={position}
+        anchorReference="anchorPosition"
+        transitionDuration={225}
+        TransitionProps={
+          OS === "macos" ? { style: { transitionDuration: "225ms" } } : {}
+        }
+        onContextMenu={(e) => {
+          setAnchorEl(null);
+          e.preventDefault();
+        }}
+      >
+        {VALID_CORE.map((each) => (
+          <MenuItem
+            key={each.core}
+            sx={{ minWidth: 125 }}
+            selected={each.core === clash_core}
+            onClick={() => onCoreChange(each.core)}
+          >
+            {each.name}
+          </MenuItem>
+        ))}
+      </Menu>
+    </>
+  );
+};
+
+export default CoreSwitch;
diff --git a/src/components/setting/setting-clash.tsx b/src/components/setting/setting-clash.tsx
index 6cd10a652c48e32179d37100766b8ed3cf189fed..536cf7c0ecc51f6d152af97cfc34c99200552861 100644
--- a/src/components/setting/setting-clash.tsx
+++ b/src/components/setting/setting-clash.tsx
@@ -8,6 +8,7 @@ import {
   Select,
   MenuItem,
   Typography,
+  Box,
 } from "@mui/material";
 import { ApiType } from "../../services/types";
 import { atomClashPort } from "../../services/states";
@@ -16,11 +17,14 @@ import { SettingList, SettingItem } from "./setting";
 import { getClashConfig, getVersion, updateConfigs } from "../../services/api";
 import Notice from "../base/base-notice";
 import GuardState from "./guard-state";
+import CoreSwitch from "./core-switch";
 
 interface Props {
   onError: (err: Error) => void;
 }
 
+const MULTI_CORE = !!import.meta.env.VITE_MULTI_CORE;
+
 const SettingClash = ({ onError }: Props) => {
   const { t } = useTranslation();
   const { mutate } = useSWRConfig();
@@ -54,7 +58,7 @@ const SettingClash = ({ onError }: Props) => {
     }
     await patchClashConfig({ "mixed-port": port });
     setGlobalClashPort(port);
-    Notice.success("Change Clash port successfully!");
+    Notice.success("Change Clash port successfully!", 1000);
 
     // update the config
     mutate("getClashConfig");
@@ -129,7 +133,18 @@ const SettingClash = ({ onError }: Props) => {
       </SettingItem>
 
       <SettingItem>
-        <ListItemText primary={t("Clash Core")} />
+        <ListItemText
+          primary={
+            MULTI_CORE ? (
+              <Box sx={{ display: "flex", alignItems: "center" }}>
+                <span style={{ marginRight: 4 }}>{t("Clash Core")}</span>
+                <CoreSwitch />
+              </Box>
+            ) : (
+              t("Clash Core")
+            )
+          }
+        />
         <Typography sx={{ py: 1 }}>{clashVer}</Typography>
       </SettingItem>
     </SettingList>
diff --git a/src/services/cmds.ts b/src/services/cmds.ts
index 6ef06457a462ae95fe36948d9e17715b164e21b6..fd7f99ad6ed2b6da63d773175cedc3cc4f8983ef 100644
--- a/src/services/cmds.ts
+++ b/src/services/cmds.ts
@@ -86,6 +86,10 @@ export async function getSystemProxy() {
   return invoke<any>("get_sys_proxy");
 }
 
+export async function changeClashCore(clashCore: string) {
+  return invoke<any>("change_clash_core", { clashCore });
+}
+
 export async function restartSidecar() {
   return invoke<void>("restart_sidecar");
 }
diff --git a/src/services/types.ts b/src/services/types.ts
index 9a38b2dee2347e2711eeb577f10d05544da6968c..44b8e7b4619e35f58eccd673e5aaebb72df5f204 100644
--- a/src/services/types.ts
+++ b/src/services/types.ts
@@ -1,7 +1,7 @@
 /**
  * Some interface for clash api
  */
- export namespace ApiType {
+export namespace ApiType {
   export interface ConfigData {
     port: number;
     mode: string;
@@ -125,6 +125,7 @@ export namespace CmdType {
 
   export interface VergeConfig {
     language?: string;
+    clash_core?: string;
     theme_mode?: "light" | "dark";
     theme_blur?: boolean;
     traffic_graph?: boolean;
diff --git a/yarn.lock b/yarn.lock
index ad94a2d5122081ab6813dfe0506d7162ae770626..25f7ddeb2bf9f3292d289a6aee78d1f4a84f03e9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1201,7 +1201,14 @@ cosmiconfig@^7.0.1:
     path-type "^4.0.0"
     yaml "^1.10.0"
 
-cross-spawn@^7.0.0:
+cross-env@^7.0.3:
+  version "7.0.3"
+  resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
+  integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
+  dependencies:
+    cross-spawn "^7.0.1"
+
+cross-spawn@^7.0.0, cross-spawn@^7.0.1:
   version "7.0.3"
   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
   integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==