diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs
index 2b07b5878da0166d7b0bd31de6d4cf80c753ec2e..efa3818b598d23f172ae0583fd538159d95fdc7d 100644
--- a/src-tauri/src/cmds.rs
+++ b/src-tauri/src/cmds.rs
@@ -193,24 +193,7 @@ pub fn patch_clash_config(payload: Mapping) -> Result<(), String> {
   save_clash(&config)
 }
 
-/// set the system proxy
-/// Tips: only support windows now
-#[tauri::command]
-pub fn set_sys_proxy(enable: bool, verge_state: State<'_, VergeState>) -> Result<(), String> {
-  let mut verge = verge_state.0.lock().unwrap();
-
-  if let Some(mut sysproxy) = verge.cur_sysproxy.take() {
-    sysproxy.enable = enable;
-    if sysproxy.set_sys().is_err() {
-      log::error!("failed to set system proxy");
-    }
-    verge.cur_sysproxy = Some(sysproxy);
-  }
-  Ok(())
-}
-
 /// get the system proxy
-/// Tips: only support windows now
 #[tauri::command]
 pub fn get_sys_proxy() -> Result<SysProxyConfig, String> {
   match SysProxyConfig::get_sys() {
@@ -219,6 +202,8 @@ pub fn get_sys_proxy() -> Result<SysProxyConfig, String> {
   }
 }
 
+/// get the current proxy config
+/// which may not the same as system proxy
 #[tauri::command]
 pub fn get_cur_proxy(verge_state: State<'_, VergeState>) -> Result<Option<SysProxyConfig>, String> {
   match verge_state.0.lock() {
@@ -244,24 +229,7 @@ pub async fn patch_verge_config(
   verge_state: State<'_, VergeState>,
 ) -> Result<(), String> {
   let mut verge = verge_state.0.lock().unwrap();
-
-  if payload.theme_mode.is_some() {
-    verge.config.theme_mode = payload.theme_mode;
-  }
-
-  if payload.enable_self_startup.is_some() {
-    verge.config.enable_self_startup = payload.enable_self_startup;
-  }
-
-  if payload.enable_system_proxy.is_some() {
-    verge.config.enable_system_proxy = payload.enable_system_proxy;
-  }
-
-  if payload.system_proxy_bypass.is_some() {
-    verge.config.system_proxy_bypass = payload.system_proxy_bypass;
-  }
-
-  verge.config.save_file()
+  verge.patch_config(payload)
 }
 
 /// start dragging window
diff --git a/src-tauri/src/core/verge.rs b/src-tauri/src/core/verge.rs
index 751d05bc052ecfbdfb1a612d2c51a5412fd01b97..9a7eceaecd699d456b57a5df7aa00e49d97b2ab1 100644
--- a/src-tauri/src/core/verge.rs
+++ b/src-tauri/src/core/verge.rs
@@ -1,5 +1,7 @@
-use crate::utils::{config, dirs, sysopt::SysProxyConfig};
+use crate::utils::{config, dirs, startup, sysopt::SysProxyConfig};
 use serde::{Deserialize, Serialize};
+use std::path::PathBuf;
+use tauri::api::path::resource_dir;
 
 /// ### `verge.yaml` schema
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
@@ -34,6 +36,7 @@ impl VergeConfig {
   }
 }
 
+/// Verge App abilities
 #[derive(Debug)]
 pub struct Verge {
   pub config: VergeConfig,
@@ -41,6 +44,8 @@ pub struct Verge {
   pub old_sysproxy: Option<SysProxyConfig>,
 
   pub cur_sysproxy: Option<SysProxyConfig>,
+
+  pub exe_path: Option<PathBuf>,
 }
 
 impl Default for Verge {
@@ -55,6 +60,7 @@ impl Verge {
       config: VergeConfig::new(),
       old_sysproxy: None,
       cur_sysproxy: None,
+      exe_path: None,
     }
   }
 
@@ -90,4 +96,95 @@ impl Verge {
       }
     }
   }
+
+  /// set the exe_path
+  pub fn set_exe_path(&mut self, package_info: &tauri::PackageInfo) {
+    let exe = if cfg!(target_os = "windows") {
+      "clash-verge.exe"
+    } else {
+      "clash-verge"
+    };
+    let path = resource_dir(package_info).unwrap().join(exe);
+    self.exe_path = Some(path);
+  }
+
+  /// sync the startup when run the app
+  pub fn sync_startup(&self) -> Result<(), String> {
+    let enable = self.config.enable_self_startup.clone().unwrap_or(false);
+
+    if !enable {
+      return Ok(());
+    }
+    if self.exe_path.is_none() {
+      return Err("should init the exe_path first".into());
+    }
+
+    let exe_path = self.exe_path.clone().unwrap();
+    match startup::get_startup(&exe_path) {
+      Ok(sys_enable) => {
+        if sys_enable || (!sys_enable && startup::set_startup(true, &exe_path).is_ok()) {
+          Ok(())
+        } else {
+          Err("failed to sync startup".into())
+        }
+      }
+      Err(_) => Err("failed to get system startup info".into()),
+    }
+  }
+
+  /// update the startup
+  fn update_startup(&mut self, enable: bool) -> Result<(), String> {
+    let conf_enable = self.config.enable_self_startup.clone().unwrap_or(false);
+
+    if enable == conf_enable {
+      return Ok(());
+    }
+    if self.exe_path.is_none() {
+      return Err("should init the exe_path first".into());
+    }
+    let exe_path = self.exe_path.clone().unwrap();
+    match startup::set_startup(enable, &exe_path) {
+      Ok(_) => Ok(()),
+      Err(_) => Err("failed to set system startup info".into()),
+    }
+  }
+
+  /// patch verge config
+  /// There should be only one update at a time here
+  /// so call the save_file at the end is savely
+  pub fn patch_config(&mut self, patch: VergeConfig) -> Result<(), String> {
+    // only change it
+    if patch.theme_mode.is_some() {
+      self.config.theme_mode = patch.theme_mode;
+    }
+
+    // should update system startup
+    if patch.enable_self_startup.is_some() {
+      let enable = patch.enable_self_startup.unwrap();
+      self.update_startup(enable)?;
+      self.config.enable_self_startup = Some(enable);
+    }
+
+    // should update system proxy
+    if patch.enable_system_proxy.is_some() {
+      let enable = patch.enable_system_proxy.unwrap();
+      if let Some(mut sysproxy) = self.cur_sysproxy.take() {
+        sysproxy.enable = enable;
+        if sysproxy.set_sys().is_err() {
+          log::error!("failed to set system proxy");
+          return Err("failed to set system proxy".into());
+        }
+        self.cur_sysproxy = Some(sysproxy);
+      }
+      self.config.enable_system_proxy = Some(enable);
+    }
+
+    // todo
+    // should update system proxt too
+    if patch.system_proxy_bypass.is_some() {
+      self.config.system_proxy_bypass = patch.system_proxy_bypass;
+    }
+
+    self.config.save_file()
+  }
 }
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index 0b63178a834bdce1233d6cda95e0746196c653af..efeb61cdbba5bf3e175609d2285192c62e7dd1e7 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -71,7 +71,6 @@ fn main() -> std::io::Result<()> {
     .invoke_handler(tauri::generate_handler![
       // common
       cmds::restart_sidecar,
-      cmds::set_sys_proxy,
       cmds::get_sys_proxy,
       cmds::get_cur_proxy,
       cmds::win_drag,
diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs
index c2dda384cc6c081c38608dfe21e99e9b4c708bbb..1266f64d225619d2d94e9fd7caaedf28d9c00658 100644
--- a/src-tauri/src/utils/resolve.rs
+++ b/src-tauri/src/utils/resolve.rs
@@ -33,7 +33,11 @@ pub fn resolve_setup(app: &App) {
     log::error!("{}", err);
   }
 
+  verge.set_exe_path(app.package_info());
   verge.init_sysproxy(clash.info.port.clone());
+  if let Err(err) = verge.sync_startup() {
+    log::error!("{}", err);
+  }
 }
 
 /// reset system proxy
diff --git a/src/components/setting-verge.tsx b/src/components/setting-verge.tsx
index 760639aea877fead1e1d2eb2ec3a7fc38bbde013..288fc8a6993f2f53008fbc6b40652861a2447c1c 100644
--- a/src/components/setting-verge.tsx
+++ b/src/components/setting-verge.tsx
@@ -6,11 +6,7 @@ import {
   Switch,
   Typography,
 } from "@mui/material";
-import {
-  setSysProxy,
-  getVergeConfig,
-  patchVergeConfig,
-} from "../services/cmds";
+import { getVergeConfig, patchVergeConfig } from "../services/cmds";
 import { CmdType } from "../services/types";
 import { version } from "../../package.json";
 import GuardState from "./guard-state";
@@ -50,9 +46,9 @@ const SettingVerge = ({ onError }: Props) => {
           onCatch={onError}
           onFormat={onSwitchFormat}
           onChange={(e) => onChangeData({ theme_mode: e ? "dark" : "light" })}
-          onGuard={async (c) => {
-            await patchVergeConfig({ theme_mode: c ? "dark" : "light" });
-          }}
+          onGuard={(c) =>
+            patchVergeConfig({ theme_mode: c ? "dark" : "light" })
+          }
         >
           <PaletteSwitch edge="end" />
         </GuardState>
@@ -66,9 +62,7 @@ const SettingVerge = ({ onError }: Props) => {
           onCatch={onError}
           onFormat={onSwitchFormat}
           onChange={(e) => onChangeData({ enable_self_startup: e })}
-          onGuard={async (e) => {
-            await patchVergeConfig({ enable_self_startup: e });
-          }}
+          onGuard={(e) => patchVergeConfig({ enable_self_startup: e })}
         >
           <Switch edge="end" />
         </GuardState>
@@ -82,10 +76,7 @@ const SettingVerge = ({ onError }: Props) => {
           onCatch={onError}
           onFormat={onSwitchFormat}
           onChange={(e) => onChangeData({ enable_system_proxy: e })}
-          onGuard={async (e) => {
-            await setSysProxy(e);
-            await patchVergeConfig({ enable_system_proxy: e });
-          }}
+          onGuard={(e) => patchVergeConfig({ enable_system_proxy: e })}
         >
           <Switch edge="end" />
         </GuardState>
diff --git a/src/services/cmds.ts b/src/services/cmds.ts
index 8d3b9b3f7776df1600d7e1b458d1cc38ac423cd0..1fc160884ba3eb7ab7cc02fb2d2cddf99df6d192 100644
--- a/src/services/cmds.ts
+++ b/src/services/cmds.ts
@@ -56,10 +56,6 @@ export async function patchClashConfig(payload: Partial<ApiType.ConfigData>) {
   return invoke<void>("patch_clash_config", { payload });
 }
 
-export async function setSysProxy(enable: boolean) {
-  return invoke<void>("set_sys_proxy", { enable });
-}
-
 export async function getVergeConfig() {
   return invoke<CmdType.VergeConfig>("get_verge_config");
 }