diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs
index 39e9bf4e63c23196a5bba55032c45bcaa58d8d65..d98017644411166e0cc15299fb070556829a16c9 100644
--- a/src-tauri/src/cmds.rs
+++ b/src-tauri/src/cmds.rs
@@ -14,8 +14,7 @@ type CmdResult<T = ()> = Result<T, String>;
 
 #[tauri::command]
 pub fn get_profiles() -> CmdResult<IProfiles> {
-    let profiles = ProfilesN::global().config.lock();
-    Ok(profiles.clone())
+    Ok(Config::profiles().data().clone())
 }
 
 #[tauri::command]
@@ -27,47 +26,80 @@ pub async fn enhance_profiles() -> CmdResult {
 #[tauri::command]
 pub async fn import_profile(url: String, option: Option<PrfOption>) -> CmdResult {
     let item = wrap_err!(PrfItem::from_url(&url, None, None, option).await)?;
-    let mut profiles = ProfilesN::global().config.lock();
-    wrap_err!(profiles.append_item(item))
+    wrap_err!(Config::profiles().data().append_item(item))
 }
 
 #[tauri::command]
 pub async fn create_profile(item: PrfItem, file_data: Option<String>) -> CmdResult {
     let item = wrap_err!(PrfItem::from(item, file_data).await)?;
-    let mut profiles = ProfilesN::global().config.lock();
-    wrap_err!(profiles.append_item(item))
+    wrap_err!(Config::profiles().data().append_item(item))
 }
 
 #[tauri::command]
 pub async fn update_profile(index: String, option: Option<PrfOption>) -> CmdResult {
-    wrap_err!(ProfilesN::global().update_item(index, option).await)
+    wrap_err!(feat::update_profile(index, option).await)
 }
 
 #[tauri::command]
 pub async fn select_profile(index: String) -> CmdResult {
-    wrap_err!({ ProfilesN::global().config.lock().put_current(index) })?;
-    wrap_err!(CoreManager::global().activate_config().await)
+    wrap_err!({ Config::profiles().draft().put_current(index) })?;
+
+    match feat::handle_activate().await {
+        Ok(_) => {
+            Config::profiles().apply();
+            wrap_err!(Config::profiles().data().save_file())?;
+            Ok(())
+        }
+        Err(err) => {
+            Config::profiles().discard();
+            log::error!(target: "app", "{err}");
+            Err(format!("{err}"))
+        }
+    }
 }
 
 /// change the profile chain
 #[tauri::command]
 pub async fn change_profile_chain(chain: Option<Vec<String>>) -> CmdResult {
-    wrap_err!({ ProfilesN::global().config.lock().put_chain(chain) })?;
-    wrap_err!(CoreManager::global().activate_config().await)
+    wrap_err!({ Config::profiles().draft().put_chain(chain) })?;
+
+    match feat::handle_activate().await {
+        Ok(_) => {
+            Config::profiles().apply();
+            wrap_err!(Config::profiles().data().save_file())?;
+            Ok(())
+        }
+        Err(err) => {
+            Config::profiles().discard();
+            log::error!(target: "app", "{err}");
+            Err(format!("{err}"))
+        }
+    }
 }
 
 #[tauri::command]
 pub async fn change_profile_valid(valid: Option<Vec<String>>) -> CmdResult {
-    wrap_err!({ ProfilesN::global().config.lock().put_valid(valid) })?;
-    wrap_err!(CoreManager::global().activate_config().await)
+    wrap_err!({ Config::profiles().draft().put_valid(valid) })?;
+
+    match feat::handle_activate().await {
+        Ok(_) => {
+            Config::profiles().apply();
+            wrap_err!(Config::profiles().data().save_file())?;
+            Ok(())
+        }
+        Err(err) => {
+            Config::profiles().discard();
+            log::error!(target: "app", "{err}");
+            Err(format!("{err}"))
+        }
+    }
 }
 
 #[tauri::command]
 pub async fn delete_profile(index: String) -> CmdResult {
-    let should_update = { wrap_err!(ProfilesN::global().config.lock().delete_item(index))? };
-
+    let should_update = wrap_err!({ Config::profiles().data().delete_item(index) })?;
     if should_update {
-        wrap_err!(CoreManager::global().activate_config().await)?;
+        wrap_err!(feat::handle_activate().await)?;
     }
 
     Ok(())
@@ -75,19 +107,20 @@ pub async fn delete_profile(index: String) -> CmdResult {
 
 #[tauri::command]
 pub fn patch_profile(index: String, profile: PrfItem) -> CmdResult {
-    let mut profiles = ProfilesN::global().config.lock();
-    wrap_err!(profiles.patch_item(index, profile))?;
-    drop(profiles);
+    wrap_err!(Config::profiles().data().patch_item(index, profile))?;
 
     wrap_err!(timer::Timer::global().refresh())
 }
 
 #[tauri::command]
 pub fn view_profile(index: String) -> CmdResult {
-    let profiles = ProfilesN::global().config.lock();
-    let item = wrap_err!(profiles.get_item(&index))?;
+    let file = {
+        wrap_err!(Config::profiles().latest().get_item(&index))?
+            .file
+            .clone()
+            .ok_or("the file field is null")
+    }?;
 
-    let file = item.file.clone().ok_or("the file field is null")?;
     let path = dirs::app_profiles_dir().join(file);
     if !path.exists() {
         ret_err!("the file not found");
@@ -98,7 +131,8 @@ pub fn view_profile(index: String) -> CmdResult {
 
 #[tauri::command]
 pub fn read_profile_file(index: String) -> CmdResult<String> {
-    let profiles = ProfilesN::global().config.lock();
+    let profiles = Config::profiles();
+    let profiles = profiles.latest();
     let item = wrap_err!(profiles.get_item(&index))?;
     let data = wrap_err!(item.read_file())?;
     Ok(data)
@@ -110,14 +144,15 @@ pub fn save_profile_file(index: String, file_data: Option<String>) -> CmdResult
         return Ok(());
     }
 
-    let profiles = ProfilesN::global().config.lock();
+    let profiles = Config::profiles();
+    let profiles = profiles.latest();
     let item = wrap_err!(profiles.get_item(&index))?;
     wrap_err!(item.save_file(file_data.unwrap()))
 }
 
 #[tauri::command]
 pub fn get_clash_info() -> CmdResult<ClashInfoN> {
-    Ok(ClashN::global().info.lock().clone())
+    wrap_err!(Config::clash().latest().get_info())
 }
 
 #[tauri::command]
@@ -153,18 +188,18 @@ pub fn get_runtime_logs() -> CmdResult<HashMap<String, Vec<(String, String)>>> {
 }
 
 #[tauri::command]
-pub fn patch_clash_config(payload: Mapping) -> CmdResult {
-    wrap_err!(feat::patch_clash(payload))
+pub async fn patch_clash_config(payload: Mapping) -> CmdResult {
+    wrap_err!(feat::patch_clash(payload).await)
 }
 
 #[tauri::command]
 pub fn get_verge_config() -> CmdResult<IVerge> {
-    Ok(VergeN::global().config.lock().clone())
+    Ok(Config::verge().data().clone())
 }
 
 #[tauri::command]
-pub fn patch_verge_config(payload: IVerge) -> CmdResult {
-    wrap_err!(feat::patch_verge(payload))
+pub async fn patch_verge_config(payload: IVerge) -> CmdResult {
+    wrap_err!(feat::patch_verge(payload).await)
 }
 
 #[tauri::command]
diff --git a/src-tauri/src/config/clash.rs b/src-tauri/src/config/clash.rs
index e59b307bcd8afd922704988badec2efd2f8bb26e..d590383ea2ee95622a0db6d609b33add441236ee 100644
--- a/src-tauri/src/config/clash.rs
+++ b/src-tauri/src/config/clash.rs
@@ -1,10 +1,7 @@
 use crate::utils::{config, dirs};
 use anyhow::Result;
-use once_cell::sync::OnceCell;
-use parking_lot::Mutex;
 use serde::{Deserialize, Serialize};
 use serde_yaml::{Mapping, Value};
-use std::{net::SocketAddr, sync::Arc};
 
 #[derive(Default, Debug, Clone)]
 pub struct IClashTemp(pub Mapping);
@@ -33,69 +30,6 @@ impl IClashTemp {
     }
 }
 
-#[derive(Debug)]
-#[deprecated]
-pub struct ClashN {
-    /// maintain the clash config
-    pub config: Arc<Mutex<Mapping>>,
-    /// some info
-    pub info: Arc<Mutex<ClashInfoN>>,
-}
-
-impl ClashN {
-    pub fn global() -> &'static ClashN {
-        static DATA: OnceCell<ClashN> = OnceCell::new();
-
-        DATA.get_or_init(|| {
-            let config = ClashN::read_config();
-            let info = ClashInfoN::from(&config);
-
-            ClashN {
-                config: Arc::new(Mutex::new(config)),
-                info: Arc::new(Mutex::new(info)),
-            }
-        })
-    }
-
-    /// get clash config
-    pub fn read_config() -> Mapping {
-        config::read_merge_mapping(dirs::clash_path())
-    }
-
-    /// save the clash config
-    pub fn save_config(&self) -> Result<()> {
-        let config = self.config.lock();
-
-        config::save_yaml(
-            dirs::clash_path(),
-            &*config,
-            Some("# Default Config For ClashN Core\n\n"),
-        )
-    }
-
-    /// 返回旧值
-    pub fn patch_info(&self, info: ClashInfoN) -> Result<ClashInfoN> {
-        let mut old_info = self.info.lock();
-        let old = (*old_info).to_owned();
-        *old_info = info;
-        Ok(old)
-    }
-
-    /// patch update the clash config
-    /// if the port is changed then return true
-    pub fn patch_config(&self, patch: Mapping) -> Result<()> {
-        let mut config = self.config.lock();
-
-        for (key, value) in patch.into_iter() {
-            config.insert(key, value);
-        }
-
-        drop(config);
-
-        self.save_config()
-    }
-}
-
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
 pub struct ClashInfoN {
     /// clash sidecar status
@@ -245,21 +179,3 @@ pub struct IClashFallbackFilter {
     pub ipcidr: Option<Vec<String>>,
     pub domain: Option<Vec<String>>,
 }
-
-#[test]
-fn test() {
-    let socket = SocketAddr::new("127.0.0.1".parse().unwrap(), 9090);
-
-    let s = "[::]:8080".parse::<SocketAddr>();
-
-    dbg!(s);
-
-    // match "::8080".parse::<SocketAddr>() {
-    //     Ok(_) => {}
-    //     Err(err) => {
-
-    //     }
-    // }
-
-    // assert_eq!(":8080".parse(), Ok(socket));
-}
diff --git a/src-tauri/src/config/config.rs b/src-tauri/src/config/config.rs
index 9ca78df158628da7eb5685929364c0014df6706b..56b7149f6d2ba61e36f9a8af9d9cab63f562ff7a 100644
--- a/src-tauri/src/config/config.rs
+++ b/src-tauri/src/config/config.rs
@@ -1,7 +1,5 @@
 use super::{Draft, IClashTemp, IProfiles, IVerge};
-use crate::config::ClashN;
 use once_cell::sync::OnceCell;
-use serde_yaml::Mapping;
 
 pub struct Config {
     clash_config: Draft<IClashTemp>,
@@ -20,18 +18,6 @@ impl Config {
         })
     }
 
-    // pub fn clash<'a>() -> MappedMutexGuard<'a, IClash> {
-    //     Self::global().clash_config.latest()
-    // }
-
-    // pub fn verge<'a>() -> MappedMutexGuard<'a, IVerge> {
-    //     Self::global().verge_config.latest()
-    // }
-
-    // pub fn profiles<'a>() -> MappedMutexGuard<'a, IProfiles> {
-    //     Self::global().profiles_config.latest()
-    // }
-
     pub fn clash() -> Draft<IClashTemp> {
         Self::global().clash_config.clone()
     }
diff --git a/src-tauri/src/config/draft.rs b/src-tauri/src/config/draft.rs
index 64bc5c82135d8a5405d0972d3d823fe1c84e5272..2f70b288b7c130ccbbf85c4b72f92b38ca3fe9a9 100644
--- a/src-tauri/src/config/draft.rs
+++ b/src-tauri/src/config/draft.rs
@@ -1,6 +1,5 @@
-use super::{IClash, IClashTemp, IProfiles, IVerge};
+use super::{IClashTemp, IProfiles, IVerge};
 use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
-use serde_yaml::Mapping;
 use std::sync::Arc;
 
 #[derive(Debug, Clone)]
@@ -64,10 +63,10 @@ macro_rules! draft_define {
     };
 }
 
-draft_define!(IClash);
+// draft_define!(IClash);
 draft_define!(IClashTemp);
 draft_define!(IVerge);
-draft_define!(Mapping);
+// draft_define!(Mapping);
 draft_define!(IProfiles);
 
 #[test]
diff --git a/src-tauri/src/config/prfitem.rs b/src-tauri/src/config/prfitem.rs
index 62dc9b63d6287cc889531301b9cc29cab5e1d29e..a377fb918b80905aaab4061832a1229bad79fe96 100644
--- a/src-tauri/src/config/prfitem.rs
+++ b/src-tauri/src/config/prfitem.rs
@@ -6,6 +6,8 @@ use serde_yaml::Mapping;
 use std::fs;
 use sysproxy::Sysproxy;
 
+use super::Config;
+
 #[derive(Debug, Clone, Deserialize, Serialize)]
 pub struct PrfItem {
     pub uid: Option<String>,
@@ -192,9 +194,9 @@ impl PrfItem {
 
         // 使用软件自己的代理
         if self_proxy {
-            let clash = super::ClashN::global();
-            let port = clash.info.lock().port.clone();
+            let port = Config::clash().data().get_info()?.port;
             let port = port.ok_or(anyhow::anyhow!("failed to get clash info port"))?;
+
             let proxy_scheme = format!("http://127.0.0.1:{port}");
 
             if let Ok(proxy) = reqwest::Proxy::http(&proxy_scheme) {
diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs
index 3779c51d370dbf803c4e7a954fdbc5145fc6fc6e..fe7f4c02eddd3b88cd9c9a6c593de2edebf3f8fd 100644
--- a/src-tauri/src/config/profiles.rs
+++ b/src-tauri/src/config/profiles.rs
@@ -1,82 +1,25 @@
-use super::{prfitem::PrfItem, ChainItem, PrfOption};
-use crate::{
-    core::CoreManager,
-    utils::{config, dirs, help},
-};
+use super::{prfitem::PrfItem, ChainItem};
+use crate::utils::{config, dirs, help};
 use anyhow::{bail, Context, Result};
-use once_cell::sync::OnceCell;
-use parking_lot::Mutex;
 use serde::{Deserialize, Serialize};
 use serde_yaml::Mapping;
 use std::collections::HashMap;
-use std::sync::Arc;
 use std::{fs, io::Write};
 
-#[deprecated]
-pub struct ProfilesN {
-    pub config: Arc<Mutex<IProfiles>>,
-}
-
-impl ProfilesN {
-    pub fn global() -> &'static ProfilesN {
-        static PROFILES: OnceCell<ProfilesN> = OnceCell::new();
-
-        PROFILES.get_or_init(|| ProfilesN {
-            config: Arc::new(Mutex::new(IProfiles::read_file())),
-        })
-    }
-
-    /// 更新单个配置
-    pub async fn update_item(&self, uid: String, option: Option<PrfOption>) -> Result<()> {
-        let url_opt = {
-            let profiles = self.config.lock();
-            let item = profiles.get_item(&uid)?;
-            let is_remote = item.itype.as_ref().map_or(false, |s| s == "remote");
-
-            if !is_remote {
-                None // 直接更新
-            } else if item.url.is_none() {
-                bail!("failed to get the profile item url");
-            } else {
-                Some((item.url.clone().unwrap(), item.option.clone()))
-            }
-        };
-
-        let should_update = match url_opt {
-            Some((url, opt)) => {
-                let merged_opt = PrfOption::merge(opt, option);
-                let item = PrfItem::from_url(&url, None, None, merged_opt).await?;
-
-                let mut profiles = self.config.lock();
-                profiles.update_item(uid.clone(), item)?;
-
-                Some(uid) == profiles.get_current()
-            }
-            None => true,
-        };
-
-        if should_update {
-            CoreManager::global().activate_config().await?;
-        }
-
-        Ok(())
-    }
-}
-
 /// Define the `profiles.yaml` schema
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
 pub struct IProfiles {
     /// same as PrfConfig.current
-    current: Option<String>,
+    pub current: Option<String>,
 
     /// same as PrfConfig.chain
-    chain: Option<Vec<String>>,
+    pub chain: Option<Vec<String>>,
 
     /// record valid fields for clash
-    valid: Option<Vec<String>>,
+    pub valid: Option<Vec<String>>,
 
     /// profile list
-    items: Option<Vec<PrfItem>>,
+    pub items: Option<Vec<PrfItem>>,
 }
 
 macro_rules! patch {
@@ -134,7 +77,7 @@ impl IProfiles {
 
         if items.iter().find(|&each| each.uid == some_uid).is_some() {
             self.current = some_uid;
-            return self.save_file();
+            return self.save_file(); // todo remove
         }
 
         bail!("invalid uid \"{uid}\"");
diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs
index 7df68f9a4b94beacd9b9b9466c70c908baf018ec..c5986a95cc6bf822488642a2a743e7da0c9d6ec5 100644
--- a/src-tauri/src/config/verge.rs
+++ b/src-tauri/src/config/verge.rs
@@ -1,53 +1,6 @@
 use crate::utils::{config, dirs};
 use anyhow::Result;
-use once_cell::sync::OnceCell;
-use parking_lot::Mutex;
 use serde::{Deserialize, Serialize};
-use std::sync::Arc;
-
-#[deprecated]
-pub struct VergeN {
-    pub config: Arc<Mutex<IVerge>>,
-}
-
-impl VergeN {
-    pub fn global() -> &'static VergeN {
-        static DATA: OnceCell<VergeN> = OnceCell::new();
-
-        DATA.get_or_init(|| {
-            let config = config::read_yaml::<IVerge>(dirs::verge_path());
-            VergeN {
-                config: Arc::new(Mutex::new(config)),
-            }
-        })
-    }
-
-    /// Save IVerge App Config
-    pub fn save_file(&self) -> Result<()> {
-        self.config.lock().save_file()
-    }
-
-    /// patch verge config
-    /// only save to file
-    pub fn patch_config(&self, patch: IVerge) -> Result<()> {
-        {
-            self.config.lock().patch_config(patch);
-        }
-        self.save_file()
-    }
-
-    /// 在初始化前尝试拿到单例端口的值
-    pub fn get_singleton_port() -> u16 {
-        let config = config::read_yaml::<IVerge>(dirs::verge_path());
-
-        #[cfg(not(feature = "verge-dev"))]
-        const SERVER_PORT: u16 = 33331;
-        #[cfg(feature = "verge-dev")]
-        const SERVER_PORT: u16 = 11233;
-
-        config.app_singleton_port.unwrap_or(SERVER_PORT)
-    }
-}
 
 /// ### `verge.yaml` schema
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
@@ -177,4 +130,16 @@ impl IVerge {
         patch!(auto_close_connection);
         patch!(default_latency_test);
     }
+
+    /// 在初始化前尝试拿到单例端口的值
+    pub fn get_singleton_port() -> u16 {
+        let config = config::read_yaml::<IVerge>(dirs::verge_path());
+
+        #[cfg(not(feature = "verge-dev"))]
+        const SERVER_PORT: u16 = 33331;
+        #[cfg(feature = "verge-dev")]
+        const SERVER_PORT: u16 = 11233;
+
+        config.app_singleton_port.unwrap_or(SERVER_PORT)
+    }
 }
diff --git a/src-tauri/src/core/clash_api.rs b/src-tauri/src/core/clash_api.rs
index 2504280a746b032db455552017c34f160e0ceaa1..3dd796c6525d1ddd33b7af918f1b31cc2c7956ef 100644
--- a/src-tauri/src/core/clash_api.rs
+++ b/src-tauri/src/core/clash_api.rs
@@ -1,4 +1,4 @@
-use crate::{config, utils::dirs};
+use crate::{config::Config, utils::dirs};
 use anyhow::{bail, Result};
 use reqwest::header::HeaderMap;
 use serde_yaml::Mapping;
@@ -40,7 +40,7 @@ pub async fn patch_configs(config: &Mapping) -> Result<()> {
 
 /// 根据clash info获取clash服务地址和请求头
 fn clash_client_info() -> Result<(String, HeaderMap)> {
-    let info = { config::ClashN::global().info.lock().clone() };
+    let info = { Config::clash().data().get_info()? };
 
     if info.server.is_none() {
         let status = &info.status;
diff --git a/src-tauri/src/core/hotkey.rs b/src-tauri/src/core/hotkey.rs
index cd844db5a61a7d40187dc0d5d2352c479a0b5d02..38565bc326fc9c595aac8c38b1b6d7bb6d310bc8 100644
--- a/src-tauri/src/core/hotkey.rs
+++ b/src-tauri/src/core/hotkey.rs
@@ -64,12 +64,12 @@ impl Hotkey {
             "clash_mode_global" => || feat::change_clash_mode("global".into()),
             "clash_mode_direct" => || feat::change_clash_mode("direct".into()),
             "clash_mode_script" => || feat::change_clash_mode("script".into()),
-            "toggle_system_proxy" => || log_err!(feat::toggle_system_proxy()),
-            "enable_system_proxy" => || log_err!(feat::enable_system_proxy()),
-            "disable_system_proxy" => || log_err!(feat::disable_system_proxy()),
-            "toggle_tun_mode" => || log_err!(feat::toggle_tun_mode()),
-            "enable_tun_mode" => || log_err!(feat::enable_tun_mode()),
-            "disable_tun_mode" => || log_err!(feat::disable_tun_mode()),
+            "toggle_system_proxy" => || feat::toggle_system_proxy(),
+            "enable_system_proxy" => || feat::enable_system_proxy(),
+            "disable_system_proxy" => || feat::disable_system_proxy(),
+            "toggle_tun_mode" => || feat::toggle_tun_mode(),
+            "enable_tun_mode" => || feat::enable_tun_mode(),
+            "disable_tun_mode" => || feat::disable_tun_mode(),
 
             _ => bail!("invalid function \"{func}\""),
         };
diff --git a/src-tauri/src/core/sysopt.rs b/src-tauri/src/core/sysopt.rs
index f9231e07376399c3302d2a2f5a3441509e02852c..152ce581e0ac3ba6178534ca507005d669b95cd3 100644
--- a/src-tauri/src/core/sysopt.rs
+++ b/src-tauri/src/core/sysopt.rs
@@ -144,13 +144,8 @@ impl Sysopt {
 
     /// init the auto launch
     pub fn init_launch(&self) -> Result<()> {
-        let enable = {
-            Config::verge()
-                .latest()
-                .enable_auto_launch
-                .clone()
-                .unwrap_or(false)
-        };
+        let enable = { Config::verge().latest().enable_auto_launch.clone() };
+        let enable = enable.unwrap_or(false);
 
         let app_exe = current_exe()?;
         let app_exe = dunce::canonicalize(app_exe)?;
@@ -213,13 +208,8 @@ impl Sysopt {
             drop(auto_launch);
             return self.init_launch();
         }
-        let enable = {
-            Config::verge()
-                .latest()
-                .enable_auto_launch
-                .clone()
-                .unwrap_or(false)
-        };
+        let enable = { Config::verge().latest().enable_auto_launch.clone() };
+        let enable = enable.unwrap_or(false);
         let auto_launch = auto_launch.as_ref().unwrap();
 
         match enable {
diff --git a/src-tauri/src/core/timer.rs b/src-tauri/src/core/timer.rs
index 0c612b0c1946fff6e7f4d17c47974838ed7de1a0..853736723786f0f5cdaff1461e34cef15498f7be 100644
--- a/src-tauri/src/core/timer.rs
+++ b/src-tauri/src/core/timer.rs
@@ -1,4 +1,5 @@
-use crate::config::{self, ProfilesN};
+use crate::config::Config;
+use crate::feat;
 use anyhow::{Context, Result};
 use delay_timer::prelude::{DelayTimer, DelayTimerBuilder, TaskBuilder};
 use once_cell::sync::OnceCell;
@@ -36,12 +37,10 @@ impl Timer {
 
         let cur_timestamp = chrono::Local::now().timestamp();
 
-        let profiles = config::ProfilesN::global().config.lock();
-
         let timer_map = self.timer_map.lock();
         let delay_timer = self.delay_timer.lock();
 
-        profiles.get_items().map(|items| {
+        Config::profiles().latest().get_items().map(|items| {
             items
                 .iter()
                 // .filter_map(|item| {
@@ -100,11 +99,9 @@ impl Timer {
 
     /// generate a uid -> update_interval map
     fn gen_map(&self) -> HashMap<String, u64> {
-        let profiles = config::ProfilesN::global().config.lock();
-
         let mut new_map = HashMap::new();
 
-        if let Some(items) = profiles.get_items() {
+        if let Some(items) = Config::profiles().latest().get_items() {
             for item in items.iter() {
                 if item.option.is_some() {
                     let option = item.option.as_ref().unwrap();
@@ -178,7 +175,7 @@ impl Timer {
     /// the task runner
     async fn async_task(uid: String) {
         log::info!(target: "app", "running timer task `{uid}`");
-        crate::log_err!(ProfilesN::global().update_item(uid, None).await);
+        crate::log_err!(feat::update_profile(uid, None).await);
     }
 }
 
diff --git a/src-tauri/src/core/tray.rs b/src-tauri/src/core/tray.rs
index 36fa65283517d0a0a1ddc6de5e9be97d029c5fc0..8ec8d095bc1136b62fa99aaa268dafb645b777c6 100644
--- a/src-tauri/src/core/tray.rs
+++ b/src-tauri/src/core/tray.rs
@@ -1,4 +1,3 @@
-use crate::log_err;
 use crate::{config::Config, feat, utils::resolve};
 use anyhow::Result;
 use tauri::{
@@ -109,8 +108,8 @@ impl Tray {
                 }
 
                 "open_window" => resolve::create_window(app_handle),
-                "system_proxy" => log_err!(feat::toggle_system_proxy()),
-                "tun_mode" => log_err!(feat::toggle_tun_mode()),
+                "system_proxy" => feat::toggle_system_proxy(),
+                "tun_mode" => feat::toggle_tun_mode(),
                 "restart_clash" => feat::restart_clash_core(),
                 "restart_app" => api::process::restart(&app_handle.env()),
                 "quit" => {
diff --git a/src-tauri/src/data/clash.rs b/src-tauri/src/data/clash.rs
deleted file mode 100644
index 73ecd35381c77912e8cd138a9ee2e722159ad7c2..0000000000000000000000000000000000000000
--- a/src-tauri/src/data/clash.rs
+++ /dev/null
@@ -1,167 +0,0 @@
-use crate::utils::{config, dirs};
-use anyhow::Result;
-use serde::{Deserialize, Serialize};
-use serde_yaml::{Mapping, Value};
-
-#[derive(Default, Debug, Clone, Deserialize, Serialize)]
-pub struct ClashInfo {
-    /// clash sidecar status
-    pub status: String,
-
-    /// clash core port
-    pub port: Option<String>,
-
-    /// same as `external-controller`
-    pub server: Option<String>,
-
-    /// clash secret
-    pub secret: Option<String>,
-}
-
-impl ClashInfo {
-    /// parse the clash's config.yaml
-    /// get some information
-    pub fn from(config: &Mapping) -> ClashInfo {
-        let key_port_1 = Value::from("mixed-port");
-        let key_port_2 = Value::from("port");
-        let key_server = Value::from("external-controller");
-        let key_secret = Value::from("secret");
-
-        let mut status: u32 = 0;
-
-        let port = match config.get(&key_port_1) {
-            Some(value) => match value {
-                Value::String(val_str) => Some(val_str.clone()),
-                Value::Number(val_num) => Some(val_num.to_string()),
-                _ => {
-                    status |= 0b1;
-                    None
-                }
-            },
-            _ => {
-                status |= 0b10;
-                None
-            }
-        };
-        let port = match port {
-            Some(_) => port,
-            None => match config.get(&key_port_2) {
-                Some(value) => match value {
-                    Value::String(val_str) => Some(val_str.clone()),
-                    Value::Number(val_num) => Some(val_num.to_string()),
-                    _ => {
-                        status |= 0b100;
-                        None
-                    }
-                },
-                _ => {
-                    status |= 0b1000;
-                    None
-                }
-            },
-        };
-
-        // `external-controller` could be
-        // "127.0.0.1:9090" or ":9090"
-        let server = match config.get(&key_server) {
-            Some(value) => match value.as_str() {
-                Some(val_str) => {
-                    if val_str.starts_with(":") {
-                        Some(format!("127.0.0.1{val_str}"))
-                    } else if val_str.starts_with("0.0.0.0:") {
-                        Some(format!("127.0.0.1:{}", &val_str[8..]))
-                    } else if val_str.starts_with("[::]:") {
-                        Some(format!("127.0.0.1:{}", &val_str[5..]))
-                    } else {
-                        Some(val_str.into())
-                    }
-                }
-                None => {
-                    status |= 0b10000;
-                    None
-                }
-            },
-            None => {
-                status |= 0b100000;
-                None
-            }
-        };
-
-        let secret = match config.get(&key_secret) {
-            Some(value) => match value {
-                Value::String(val_str) => Some(val_str.clone()),
-                Value::Bool(val_bool) => Some(val_bool.to_string()),
-                Value::Number(val_num) => Some(val_num.to_string()),
-                _ => None,
-            },
-            _ => None,
-        };
-
-        ClashInfo {
-            status: format!("{status}"),
-            port,
-            server,
-            secret,
-        }
-    }
-}
-
-#[derive(Debug)]
-pub struct Clash {
-    /// maintain the clash config
-    pub config: Mapping,
-
-    /// some info
-    pub info: ClashInfo,
-}
-
-impl Clash {
-    pub fn new() -> Clash {
-        let config = Clash::read_config();
-        let info = ClashInfo::from(&config);
-
-        Clash { config, info }
-    }
-
-    /// get clash config
-    pub fn read_config() -> Mapping {
-        config::read_merge_mapping(dirs::clash_path())
-    }
-
-    /// save the clash config
-    pub fn save_config(&self) -> Result<()> {
-        config::save_yaml(
-            dirs::clash_path(),
-            &self.config,
-            Some("# Default Config For Clash Core\n\n"),
-        )
-    }
-
-    /// patch update the clash config
-    /// if the port is changed then return true
-    pub fn patch_config(&mut self, patch: Mapping) -> Result<()> {
-        let port_key = Value::from("mixed-port");
-        let server_key = Value::from("external-controller");
-        let secret_key = Value::from("secret");
-
-        let change_info = patch.contains_key(&port_key)
-            || patch.contains_key(&server_key)
-            || patch.contains_key(&secret_key);
-
-        for (key, value) in patch.into_iter() {
-            self.config.insert(key, value);
-        }
-
-        if change_info {
-            self.info = ClashInfo::from(&self.config);
-        }
-
-        self.save_config()
-    }
-}
-
-impl Default for Clash {
-    fn default() -> Self {
-        Clash::new()
-    }
-}
diff --git a/src-tauri/src/data/mod.rs b/src-tauri/src/data/mod.rs
deleted file mode 100644
index eb6a406433242d3e6f06a485c2286ece68451439..0000000000000000000000000000000000000000
--- a/src-tauri/src/data/mod.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-mod clash;
-mod prfitem;
-mod profiles;
-mod verge;
-
-pub use self::clash::*;
-pub use self::prfitem::*;
-pub use self::profiles::*;
-pub use self::verge::*;
-
-use once_cell::sync::OnceCell;
-use parking_lot::Mutex;
-use std::sync::Arc;
-
-#[derive(Debug, Clone)]
-pub struct Data {
-    pub clash: Arc<Mutex<Clash>>,
-    pub verge: Arc<Mutex<Verge>>,
-    pub profiles: Arc<Mutex<Profiles>>,
-}
-
-impl Data {
-    pub fn global() -> &'static Data {
-        static DATA: OnceCell<Data> = OnceCell::new();
-
-        DATA.get_or_init(|| Data {
-            clash: Arc::new(Mutex::new(Clash::new())),
-            verge: Arc::new(Mutex::new(Verge::new())),
-            profiles: Arc::new(Mutex::new(Profiles::new())),
-        })
-    }
-}
diff --git a/src-tauri/src/data/prfitem.rs b/src-tauri/src/data/prfitem.rs
deleted file mode 100644
index 90b08f36045e1df6c8d041b8e67aa40512440243..0000000000000000000000000000000000000000
--- a/src-tauri/src/data/prfitem.rs
+++ /dev/null
@@ -1,406 +0,0 @@
-use crate::utils::{config, dirs, help, tmpl};
-use anyhow::{bail, Context, Result};
-use reqwest::StatusCode;
-use serde::{Deserialize, Serialize};
-use serde_yaml::Mapping;
-use std::fs;
-use sysproxy::Sysproxy;
-
-#[derive(Debug, Clone, Deserialize, Serialize)]
-pub struct PrfItem {
-    pub uid: Option<String>,
-
-    /// profile item type
-    /// enum value: remote | local | script | merge
-    #[serde(rename = "type")]
-    pub itype: Option<String>,
-
-    /// profile name
-    pub name: Option<String>,
-
-    /// profile file
-    pub file: Option<String>,
-
-    /// profile description
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub desc: Option<String>,
-
-    /// source url
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub url: Option<String>,
-
-    /// selected infomation
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub selected: Option<Vec<PrfSelected>>,
-
-    /// subscription user info
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub extra: Option<PrfExtra>,
-
-    /// updated time
-    pub updated: Option<usize>,
-
-    /// some options of the item
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub option: Option<PrfOption>,
-
-    /// the file data
-    #[serde(skip)]
-    pub file_data: Option<String>,
-}
-
-#[derive(Default, Debug, Clone, Deserialize, Serialize)]
-pub struct PrfSelected {
-    pub name: Option<String>,
-    pub now: Option<String>,
-}
-
-#[derive(Default, Debug, Clone, Copy, Deserialize, Serialize)]
-pub struct PrfExtra {
-    pub upload: usize,
-    pub download: usize,
-    pub total: usize,
-    pub expire: usize,
-}
-
-#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
-pub struct PrfOption {
-    /// for `remote` profile's http request
-    /// see issue #13
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub user_agent: Option<String>,
-
-    /// for `remote` profile
-    /// use system proxy
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub with_proxy: Option<bool>,
-
-    /// for `remote` profile
-    /// use self proxy
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub self_proxy: Option<bool>,
-
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub update_interval: Option<u64>,
-}
-
-impl PrfOption {
-    pub fn merge(one: Option<Self>, other: Option<Self>) -> Option<Self> {
-        match (one, other) {
-            (Some(mut a), Some(b)) => {
-                a.user_agent = b.user_agent.or(a.user_agent);
-                a.with_proxy = b.with_proxy.or(a.with_proxy);
-                a.self_proxy = b.self_proxy.or(a.self_proxy);
-                a.update_interval = b.update_interval.or(a.update_interval);
-                Some(a)
-            }
-            t @ _ => t.0.or(t.1),
-        }
-    }
-}
-
-impl Default for PrfItem {
-    fn default() -> Self {
-        PrfItem {
-            uid: None,
-            itype: None,
-            name: None,
-            desc: None,
-            file: None,
-            url: None,
-            selected: None,
-            extra: None,
-            updated: None,
-            option: None,
-            file_data: None,
-        }
-    }
-}
-
-impl PrfItem {
-    /// From partial item
-    /// must contain `itype`
-    pub async fn from(item: PrfItem, file_data: Option<String>) -> Result<PrfItem> {
-        if item.itype.is_none() {
-            bail!("type should not be null");
-        }
-
-        match item.itype.unwrap().as_str() {
-            "remote" => {
-                if item.url.is_none() {
-                    bail!("url should not be null");
-                }
-                let url = item.url.as_ref().unwrap().as_str();
-                let name = item.name;
-                let desc = item.desc;
-                PrfItem::from_url(url, name, desc, item.option).await
-            }
-            "local" => {
-                let name = item.name.unwrap_or("Local File".into());
-                let desc = item.desc.unwrap_or("".into());
-                PrfItem::from_local(name, desc, file_data)
-            }
-            "merge" => {
-                let name = item.name.unwrap_or("Merge".into());
-                let desc = item.desc.unwrap_or("".into());
-                PrfItem::from_merge(name, desc)
-            }
-            "script" => {
-                let name = item.name.unwrap_or("Script".into());
-                let desc = item.desc.unwrap_or("".into());
-                PrfItem::from_script(name, desc)
-            }
-            typ @ _ => bail!("invalid profile item type \"{typ}\""),
-        }
-    }
-
-    /// ## Local type
-    /// create a new item from name/desc
-    pub fn from_local(name: String, desc: String, file_data: Option<String>) -> Result<PrfItem> {
-        let uid = help::get_uid("l");
-        let file = format!("{uid}.yaml");
-
-        Ok(PrfItem {
-            uid: Some(uid),
-            itype: Some("local".into()),
-            name: Some(name),
-            desc: Some(desc),
-            file: Some(file),
-            url: None,
-            selected: None,
-            extra: None,
-            option: None,
-            updated: Some(help::get_now()),
-            file_data: Some(file_data.unwrap_or(tmpl::ITEM_LOCAL.into())),
-        })
-    }
-
-    /// ## Remote type
-    /// create a new item from url
-    pub async fn from_url(
-        url: &str,
-        name: Option<String>,
-        desc: Option<String>,
-        option: Option<PrfOption>,
-    ) -> Result<PrfItem> {
-        let opt_ref = option.as_ref();
-        let with_proxy = opt_ref.map_or(false, |o| o.with_proxy.unwrap_or(false));
-        let self_proxy = opt_ref.map_or(false, |o| o.self_proxy.unwrap_or(false));
-        let user_agent = opt_ref.map_or(None, |o| o.user_agent.clone());
-
-        let mut builder = reqwest::ClientBuilder::new().no_proxy();
-
-        // 使用软件自己的代理
-        if self_proxy {
-            let data = super::Data::global();
-            let port = data.clash.lock().info.port.clone();
-            let port = port.ok_or(anyhow::anyhow!("failed to get clash info port"))?;
-            let proxy_scheme = format!("http://127.0.0.1:{port}");
-
-            if let Ok(proxy) = reqwest::Proxy::http(&proxy_scheme) {
-                builder = builder.proxy(proxy);
-            }
-            if let Ok(proxy) = reqwest::Proxy::https(&proxy_scheme) {
-                builder = builder.proxy(proxy);
-            }
-            if let Ok(proxy) = reqwest::Proxy::all(&proxy_scheme) {
-                builder = builder.proxy(proxy);
-            }
-        }
-        // 使用系统代理
-        else if with_proxy {
-            match Sysproxy::get_system_proxy() {
-                Ok(p @ Sysproxy { enable: true, .. }) => {
-                    let proxy_scheme = format!("http://{}:{}", p.host, p.port);
-
-                    if let Ok(proxy) = reqwest::Proxy::http(&proxy_scheme) {
-                        builder = builder.proxy(proxy);
-                    }
-                    if let Ok(proxy) = reqwest::Proxy::https(&proxy_scheme) {
-                        builder = builder.proxy(proxy);
-                    }
-                    if let Ok(proxy) = reqwest::Proxy::all(&proxy_scheme) {
-                        builder = builder.proxy(proxy);
-                    }
-                }
-                _ => {}
-            };
-        }
-
-        let version = unsafe { dirs::APP_VERSION };
-        let version = format!("clash-verge/{version}");
-        builder = builder.user_agent(user_agent.unwrap_or(version));
-
-        let resp = builder.build()?.get(url).send().await?;
-
-        let status_code = resp.status();
-        if !StatusCode::is_success(&status_code) {
-            bail!("failed to fetch remote profile with status {status_code}")
-        }
-
-        let header = resp.headers();
-
-        // parse the Subscription UserInfo
-        let extra = match header.get("Subscription-Userinfo") {
-            Some(value) => {
-                let sub_info = value.to_str().unwrap_or("");
-
-                Some(PrfExtra {
-                    upload: help::parse_str(sub_info, "upload=").unwrap_or(0),
-                    download: help::parse_str(sub_info, "download=").unwrap_or(0),
-                    total: help::parse_str(sub_info, "total=").unwrap_or(0),
-                    expire: help::parse_str(sub_info, "expire=").unwrap_or(0),
-                })
-            }
-            None => None,
-        };
-
-        // parse the Content-Disposition
-        let filename = match header.get("Content-Disposition") {
-            Some(value) => {
-                let filename = value.to_str().unwrap_or("");
-                help::parse_str::<String>(filename, "filename=")
-            }
-            None => None,
-        };
-
-        // parse the profile-update-interval
-        let option = match header.get("profile-update-interval") {
-            Some(value) => match value.to_str().unwrap_or("").parse::<u64>() {
-                Ok(val) => Some(PrfOption {
-                    update_interval: Some(val * 60), // hour -> min
-                    ..PrfOption::default()
-                }),
-                Err(_) => None,
-            },
-            None => None,
-        };
-
-        let uid = help::get_uid("r");
-        let file = format!("{uid}.yaml");
-        let name = name.unwrap_or(filename.unwrap_or("Remote File".into()));
-        let data = resp.text_with_charset("utf-8").await?;
-
-        // check the data whether the valid yaml format
-        let yaml = serde_yaml::from_str::<Mapping>(&data) //
-            .context("the remote profile data is invalid yaml")?;
-
-        if !yaml.contains_key("proxies") && !yaml.contains_key("proxy-providers") {
-            bail!("profile does not contain `proxies` or `proxy-providers`");
-        }
-
-        Ok(PrfItem {
-            uid: Some(uid),
-            itype: Some("remote".into()),
-            name: Some(name),
-            desc,
-            file: Some(file),
-            url: Some(url.into()),
-            selected: None,
-            extra,
-            option,
-            updated: Some(help::get_now()),
-            file_data: Some(data),
-        })
-    }
-
-    /// ## Merge type (enhance)
-    /// create the enhanced item by using `merge` rule
-    pub fn from_merge(name: String, desc: String) -> Result<PrfItem> {
-        let uid = help::get_uid("m");
-        let file = format!("{uid}.yaml");
-
-        Ok(PrfItem {
-            uid: Some(uid),
-            itype: Some("merge".into()),
-            name: Some(name),
-            desc: Some(desc),
-            file: Some(file),
-            url: None,
-            selected: None,
-            extra: None,
-            option: None,
-            updated: Some(help::get_now()),
-            file_data: Some(tmpl::ITEM_MERGE.into()),
-        })
-    }
-
-    /// ## Script type (enhance)
-    /// create the enhanced item by using javascript(browserjs)
-    pub fn from_script(name: String, desc: String) -> Result<PrfItem> {
-        let uid = help::get_uid("s");
-        let file = format!("{uid}.js"); // js ext
-
-        Ok(PrfItem {
-            uid: Some(uid),
-            itype: Some("script".into()),
-            name: Some(name),
-            desc: Some(desc),
-            file: Some(file),
-            url: None,
-            selected: None,
-            extra: None,
-            option: None,
-            updated: Some(help::get_now()),
-            file_data: Some(tmpl::ITEM_SCRIPT.into()),
-        })
-    }
-
-    /// get the file data
-    pub fn read_file(&self) -> Result<String> {
-        if self.file.is_none() {
-            bail!("could not find the file");
-        }
-
-        let file = self.file.clone().unwrap();
-        let path = dirs::app_profiles_dir().join(file);
-        fs::read_to_string(path).context("failed to read the file")
-    }
-
-    /// save the file data
-    pub fn save_file(&self, data: String) -> Result<()> {
-        if self.file.is_none() {
-            bail!("could not find the file");
-        }
-
-        let file = self.file.clone().unwrap();
-        let path = dirs::app_profiles_dir().join(file);
-        fs::write(path, data.as_bytes()).context("failed to save the file")
-    }
-
-    /// get the data for enhanced mode
-    pub fn to_enhance(&self) -> Option<ChainItem> {
-        let itype = self.itype.as_ref()?.as_str();
-        let file = self.file.clone()?;
-        let uid = self.uid.clone().unwrap_or("".into());
-        let path = dirs::app_profiles_dir().join(file);
-
-        if !path.exists() {
-            return None;
-        }
-
-        match itype {
-            "script" => Some(ChainItem {
-                uid,
-                data: ChainType::Script(fs::read_to_string(path).unwrap_or("".into())),
-            }),
-            "merge" => Some(ChainItem {
-                uid,
-                data: ChainType::Merge(config::read_merge_mapping(path)),
-            }),
-            _ => None,
-        }
-    }
-}
-
-#[derive(Debug, Clone)]
-pub struct ChainItem {
-    pub uid: String,
-    pub data: ChainType,
-}
-
-#[derive(Debug, Clone)]
-pub enum ChainType {
-    Merge(Mapping),
-    Script(String),
-}
diff --git a/src-tauri/src/data/profiles.rs b/src-tauri/src/data/profiles.rs
deleted file mode 100644
index 6272cd8ccedc0a4b37390b7917296693e92cba10..0000000000000000000000000000000000000000
--- a/src-tauri/src/data/profiles.rs
+++ /dev/null
@@ -1,329 +0,0 @@
-use super::prfitem::PrfItem;
-use super::ChainItem;
-use crate::utils::{config, dirs, help};
-use anyhow::{bail, Context, Result};
-use serde::{Deserialize, Serialize};
-use serde_yaml::Mapping;
-use std::collections::HashMap;
-use std::{fs, io::Write};
-
-///
-/// ## Profiles Config
-///
-/// Define the `profiles.yaml` schema
-///
-#[derive(Default, Debug, Clone, Deserialize, Serialize)]
-pub struct Profiles {
-    /// same as PrfConfig.current
-    current: Option<String>,
-
-    /// same as PrfConfig.chain
-    chain: Option<Vec<String>>,
-
-    /// record valid fields for clash
-    valid: Option<Vec<String>>,
-
-    /// profile list
-    items: Option<Vec<PrfItem>>,
-}
-
-macro_rules! patch {
-    ($lv: expr, $rv: expr, $key: tt) => {
-        if ($rv.$key).is_some() {
-            $lv.$key = $rv.$key;
-        }
-    };
-}
-
-impl Profiles {
-    pub fn new() -> Self {
-        Profiles::read_file()
-    }
-
-    /// read the config from the file
-    pub fn read_file() -> Self {
-        let mut profiles = config::read_yaml::<Self>(dirs::profiles_path());
-
-        if profiles.items.is_none() {
-            profiles.items = Some(vec![]);
-        }
-
-        // compatiable with the old old old version
-        profiles.items.as_mut().map(|items| {
-            for mut item in items.iter_mut() {
-                if item.uid.is_none() {
-                    item.uid = Some(help::get_uid("d"));
-                }
-            }
-        });
-
-        profiles
-    }
-
-    /// save the config to the file
-    pub fn save_file(&self) -> Result<()> {
-        config::save_yaml(
-            dirs::profiles_path(),
-            self,
-            Some("# Profiles Config for Clash Verge\n\n"),
-        )
-    }
-
-    /// get the current uid
-    pub fn get_current(&self) -> Option<String> {
-        self.current.clone()
-    }
-
-    /// only change the main to the target id
-    pub fn put_current(&mut self, uid: String) -> Result<()> {
-        if self.items.is_none() {
-            self.items = Some(vec![]);
-        }
-
-        let items = self.items.as_ref().unwrap();
-        let some_uid = Some(uid.clone());
-
-        if items.iter().find(|&each| each.uid == some_uid).is_some() {
-            self.current = some_uid;
-            return self.save_file();
-        }
-
-        bail!("invalid uid \"{uid}\"");
-    }
-
-    /// just change the `chain`
-    pub fn put_chain(&mut self, chain: Option<Vec<String>>) -> Result<()> {
-        self.chain = chain;
-        self.save_file()
-    }
-
-    /// just change the `field`
-    pub fn put_valid(&mut self, valid: Option<Vec<String>>) -> Result<()> {
-        self.valid = valid;
-        self.save_file()
-    }
-
-    /// get items ref
-    pub fn get_items(&self) -> Option<&Vec<PrfItem>> {
-        self.items.as_ref()
-    }
-
-    /// find the item by the uid
-    pub fn get_item(&self, uid: &String) -> Result<&PrfItem> {
-        if self.items.is_some() {
-            let items = self.items.as_ref().unwrap();
-            let some_uid = Some(uid.clone());
-
-            for each in items.iter() {
-                if each.uid == some_uid {
-                    return Ok(each);
-                }
-            }
-        }
-
-        bail!("failed to get the profile item \"uid:{uid}\"");
-    }
-
-    /// append new item
-    /// if the file_data is some
-    /// then should save the data to file
-    pub fn append_item(&mut self, mut item: PrfItem) -> Result<()> {
-        if item.uid.is_none() {
-            bail!("the uid should not be null");
-        }
-
-        // save the file data
-        // move the field value after save
-        if let Some(file_data) = item.file_data.take() {
-            if item.file.is_none() {
-                bail!("the file should not be null");
-            }
-
-            let file = item.file.clone().unwrap();
-            let path = dirs::app_profiles_dir().join(&file);
-
-            fs::File::create(path)
-                .context(format!("failed to create file \"{}\"", file))?
-                .write(file_data.as_bytes())
-                .context(format!("failed to write to file \"{}\"", file))?;
-        }
-
-        if self.items.is_none() {
-            self.items = Some(vec![]);
-        }
-
-        self.items.as_mut().map(|items| items.push(item));
-        self.save_file()
-    }
-
-    /// update the item value
-    pub fn patch_item(&mut self, uid: String, item: PrfItem) -> Result<()> {
-        let mut items = self.items.take().unwrap_or(vec![]);
-
-        for mut each in items.iter_mut() {
-            if each.uid == Some(uid.clone()) {
-                patch!(each, item, itype);
-                patch!(each, item, name);
-                patch!(each, item, desc);
-                patch!(each, item, file);
-                patch!(each, item, url);
-                patch!(each, item, selected);
-                patch!(each, item, extra);
-                patch!(each, item, updated);
-                patch!(each, item, option);
-
-                self.items = Some(items);
-                return self.save_file();
-            }
-        }
-
-        self.items = Some(items);
-        bail!("failed to find the profile item \"uid:{uid}\"")
-    }
-
-    /// be used to update the remote item
-    /// only patch `updated` `extra` `file_data`
-    pub fn update_item(&mut self, uid: String, mut item: PrfItem) -> Result<()> {
-        if self.items.is_none() {
-            self.items = Some(vec![]);
-        }
-
-        // find the item
-        let _ = self.get_item(&uid)?;
-
-        if let Some(items) = self.items.as_mut() {
-            let some_uid = Some(uid.clone());
-
-            for mut each in items.iter_mut() {
-                if each.uid == some_uid {
-                    each.extra = item.extra;
-                    each.updated = item.updated;
-
-                    // save the file data
-                    // move the field value after save
-                    if let Some(file_data) = item.file_data.take() {
-                        let file = each.file.take();
-                        let file =
-                            file.unwrap_or(item.file.take().unwrap_or(format!("{}.yaml", &uid)));
-
-                        // the file must exists
-                        each.file = Some(file.clone());
-
-                        let path = dirs::app_profiles_dir().join(&file);
-
-                        fs::File::create(path)
-                            .context(format!("failed to create file \"{}\"", file))?
-                            .write(file_data.as_bytes())
-                            .context(format!("failed to write to file \"{}\"", file))?;
-                    }
-
-                    break;
-                }
-            }
-        }
-
-        self.save_file()
-    }
-
-    /// delete item
-    /// if delete the current then return true
-    pub fn delete_item(&mut self, uid: String) -> Result<bool> {
-        let current = self.current.as_ref().unwrap_or(&uid);
-        let current = current.clone();
-
-        let mut items = self.items.take().unwrap_or(vec![]);
-        let mut index = None;
-
-        // get the index
-        for i in 0..items.len() {
-            if items[i].uid == Some(uid.clone()) {
-                index = Some(i);
-                break;
-            }
-        }
-
-        if let Some(index) = index {
-            items.remove(index).file.map(|file| {
-                let path = dirs::app_profiles_dir().join(file);
-                if path.exists() {
-                    let _ = fs::remove_file(path);
-                }
-            });
-        }
-
-        // delete the original uid
-        if current == uid {
-            self.current = match items.len() > 0 {
-                true => items[0].uid.clone(),
-                false => None,
-            };
-        }
-
-        self.items = Some(items);
-        self.save_file()?;
-        Ok(current == uid)
-    }
-
-    /// generate the current Mapping data
-    fn gen_current(&self) -> Result<Mapping> {
-        let config = Mapping::new();
-
-        if self.current.is_none() || self.items.is_none() {
-            return Ok(config);
-        }
-
-        let current = self.current.clone().unwrap();
-        for item in self.items.as_ref().unwrap().iter() {
-            if item.uid == Some(current.clone()) {
-                let file_path = match item.file.clone() {
-                    Some(file) => dirs::app_profiles_dir().join(file),
-                    None => bail!("failed to get the file field"),
-                };
-
-                if !file_path.exists() {
-                    bail!("failed to read the file \"{}\"", file_path.display());
-                }
-
-                return Ok(config::read_merge_mapping(file_path.clone()));
-            }
-        }
-        bail!("failed to find current profile \"uid:{current}\"");
-    }
-
-    /// generate the data for activate clash config
-    pub fn gen_activate(&self) -> Result<PrfActivate> {
-        let current = self.gen_current()?;
-        let chain = match self.chain.as_ref() {
-            Some(chain) => chain
-                .iter()
-                .filter_map(|uid| self.get_item(uid).ok())
-                .filter_map(|item| item.to_enhance())
-                .collect::<Vec<ChainItem>>(),
-            None => vec![],
-        };
-        let valid = self.valid.clone().unwrap_or(vec![]);
-
-        Ok(PrfActivate {
-            current,
-            chain,
-            valid,
-        })
-    }
-}
-
-#[derive(Default, Clone)]
-pub struct PrfActivate {
-    pub current: Mapping,
-    pub chain: Vec<ChainItem>,
-    pub valid: Vec<String>,
-}
-
-#[derive(Default, Debug, Clone, Deserialize, Serialize)]
-pub struct RuntimeResult {
-    pub config: Option<Mapping>,
-    pub config_yaml: Option<String>,
-    // 记录在配置中(包括merge和script生成的)出现过的keys
-    // 这些keys不一定都生效
-    pub exists_keys: Vec<String>,
-    pub chain_logs: HashMap<String, Vec<(String, String)>>,
-}
diff --git a/src-tauri/src/data/verge.rs b/src-tauri/src/data/verge.rs
deleted file mode 100644
index 97c20166afc28f48fb9df587d730a782c3addec9..0000000000000000000000000000000000000000
--- a/src-tauri/src/data/verge.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-use crate::utils::{config, dirs};
-use anyhow::Result;
-use serde::{Deserialize, Serialize};
-
-/// ### `verge.yaml` schema
-#[derive(Default, Debug, Clone, Deserialize, Serialize)]
-pub struct Verge {
-    /// app listening port
-    /// for app singleton
-    pub app_singleton_port: Option<u16>,
-
-    // i18n
-    pub language: Option<String>,
-
-    /// `light` or `dark` or `system`
-    pub theme_mode: Option<String>,
-
-    /// enable blur mode
-    /// maybe be able to set the alpha
-    pub theme_blur: Option<bool>,
-
-    /// enable traffic graph default is true
-    pub traffic_graph: Option<bool>,
-
-    /// clash tun mode
-    pub enable_tun_mode: Option<bool>,
-
-    /// windows service mode
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub enable_service_mode: Option<bool>,
-
-    /// can the app auto startup
-    pub enable_auto_launch: Option<bool>,
-
-    /// not show the window on launch
-    pub enable_silent_start: Option<bool>,
-
-    /// set system proxy
-    pub enable_system_proxy: Option<bool>,
-
-    /// enable proxy guard
-    pub enable_proxy_guard: Option<bool>,
-
-    /// set system proxy bypass
-    pub system_proxy_bypass: Option<String>,
-
-    /// proxy guard duration
-    pub proxy_guard_duration: Option<u64>,
-
-    /// theme setting
-    pub theme_setting: Option<VergeTheme>,
-
-    /// web ui list
-    pub web_ui_list: Option<Vec<String>>,
-
-    /// clash core path
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub clash_core: Option<String>,
-
-    /// hotkey map
-    /// format: {func},{key}
-    pub hotkeys: Option<Vec<String>>,
-
-    /// 切换代理时自动关闭连接
-    pub auto_close_connection: Option<bool>,
-
-    /// 默认的延迟测试连接
-    pub default_latency_test: Option<String>,
-}
-
-#[derive(Default, Debug, Clone, Deserialize, Serialize)]
-pub struct VergeTheme {
-    pub primary_color: Option<String>,
-    pub secondary_color: Option<String>,
-    pub primary_text: Option<String>,
-    pub secondary_text: Option<String>,
-
-    pub info_color: Option<String>,
-    pub error_color: Option<String>,
-    pub warning_color: Option<String>,
-    pub success_color: Option<String>,
-
-    pub font_family: Option<String>,
-    pub css_injection: Option<String>,
-}
-
-impl Verge {
-    pub fn new() -> Self {
-        config::read_yaml::<Verge>(dirs::verge_path())
-    }
-
-    /// Save Verge App Config
-    pub fn save_file(&self) -> Result<()> {
-        config::save_yaml(
-            dirs::verge_path(),
-            self,
-            Some("# The Config for Clash Verge App\n\n"),
-        )
-    }
-
-    /// patch verge config
-    /// only save to file
-    pub fn patch_config(&mut self, patch: Verge) -> Result<()> {
-        macro_rules! patch {
-            ($key: tt) => {
-                if patch.$key.is_some() {
-                    self.$key = patch.$key;
-                }
-            };
-        }
-
-        patch!(language);
-        patch!(theme_mode);
-        patch!(theme_blur);
-        patch!(traffic_graph);
-
-        patch!(enable_tun_mode);
-        patch!(enable_service_mode);
-        patch!(enable_auto_launch);
-        patch!(enable_silent_start);
-        patch!(enable_system_proxy);
-        patch!(enable_proxy_guard);
-        patch!(system_proxy_bypass);
-        patch!(proxy_guard_duration);
-
-        patch!(theme_setting);
-        patch!(web_ui_list);
-        patch!(clash_core);
-        patch!(hotkeys);
-
-        patch!(auto_close_connection);
-        patch!(default_latency_test);
-
-        self.save_file()
-    }
-}
diff --git a/src-tauri/src/feat.rs b/src-tauri/src/feat.rs
index d94fe7d44e7b2b382ac9341faeed07cc57b69220..2667ebe2443764a1f996f9950dead31f032bf601 100644
--- a/src-tauri/src/feat.rs
+++ b/src-tauri/src/feat.rs
@@ -1,7 +1,7 @@
 use crate::config::*;
 use crate::core::*;
 use crate::log_err;
-use anyhow::Result;
+use anyhow::{bail, Result};
 use serde_yaml::{Mapping, Value};
 
 // 重启clash
@@ -22,11 +22,9 @@ pub fn change_clash_mode(mode: String) {
         match clash_api::patch_configs(&mapping).await {
             Ok(_) => {
                 // 更新配置
-                let mut clash = ClashN::global().config.lock();
-                clash.insert(Value::from("mode"), mode.into());
-                drop(clash);
+                Config::clash().data().patch_config(mapping);
 
-                if let Ok(_) = ClashN::global().save_config() {
+                if let Ok(_) = Config::clash().data().save_config() {
                     handle::Handle::refresh_clash();
                     log_err!(handle::Handle::update_systray_part());
                 }
@@ -39,163 +37,199 @@ pub fn change_clash_mode(mode: String) {
 }
 
 // 切换系统代理
-pub fn toggle_system_proxy() -> Result<()> {
-    let enable = {
-        let verge = VergeN::global().config.lock();
-        verge.enable_system_proxy.clone().unwrap_or(false)
-    };
-    patch_verge(IVerge {
-        enable_system_proxy: Some(!enable),
-        ..IVerge::default()
-    })?;
-    handle::Handle::refresh_verge();
-    Ok(())
+pub fn toggle_system_proxy() {
+    let enable = Config::verge().draft().enable_system_proxy.clone();
+    let enable = enable.unwrap_or(false);
+
+    tauri::async_runtime::spawn(async move {
+        match patch_verge(IVerge {
+            enable_system_proxy: Some(!enable),
+            ..IVerge::default()
+        })
+        .await
+        {
+            Ok(_) => handle::Handle::refresh_verge(),
+            Err(err) => log::error!(target: "app", "{err}"),
+        }
+    });
 }
 
 // 打开系统代理
-pub fn enable_system_proxy() -> Result<()> {
-    patch_verge(IVerge {
-        enable_system_proxy: Some(true),
-        ..IVerge::default()
-    })?;
-    handle::Handle::refresh_verge();
-    Ok(())
+pub fn enable_system_proxy() {
+    tauri::async_runtime::spawn(async {
+        match patch_verge(IVerge {
+            enable_system_proxy: Some(true),
+            ..IVerge::default()
+        })
+        .await
+        {
+            Ok(_) => handle::Handle::refresh_verge(),
+            Err(err) => log::error!(target: "app", "{err}"),
+        }
+    });
 }
 
 // 关闭系统代理
-pub fn disable_system_proxy() -> Result<()> {
-    patch_verge(IVerge {
-        enable_system_proxy: Some(false),
-        ..IVerge::default()
-    })?;
-    handle::Handle::refresh_verge();
-    Ok(())
+pub fn disable_system_proxy() {
+    tauri::async_runtime::spawn(async {
+        match patch_verge(IVerge {
+            enable_system_proxy: Some(false),
+            ..IVerge::default()
+        })
+        .await
+        {
+            Ok(_) => handle::Handle::refresh_verge(),
+            Err(err) => log::error!(target: "app", "{err}"),
+        }
+    });
 }
 
 // 切换tun模式
-pub fn toggle_tun_mode() -> Result<()> {
-    let enable = {
-        let verge = VergeN::global().config.lock();
-        verge.enable_tun_mode.clone().unwrap_or(false)
-    };
+pub fn toggle_tun_mode() {
+    let enable = Config::verge().data().enable_tun_mode.clone();
+    let enable = enable.unwrap_or(false);
 
-    patch_verge(IVerge {
-        enable_tun_mode: Some(!enable),
-        ..IVerge::default()
-    })?;
-    handle::Handle::refresh_verge();
-    Ok(())
+    tauri::async_runtime::spawn(async move {
+        match patch_verge(IVerge {
+            enable_tun_mode: Some(!enable),
+            ..IVerge::default()
+        })
+        .await
+        {
+            Ok(_) => handle::Handle::refresh_verge(),
+            Err(err) => log::error!(target: "app", "{err}"),
+        }
+    });
 }
 
 // 打开tun模式
-pub fn enable_tun_mode() -> Result<()> {
-    patch_verge(IVerge {
-        enable_tun_mode: Some(true),
-        ..IVerge::default()
-    })?;
-    handle::Handle::refresh_verge();
-    Ok(())
+pub fn enable_tun_mode() {
+    tauri::async_runtime::spawn(async {
+        match patch_verge(IVerge {
+            enable_tun_mode: Some(true),
+            ..IVerge::default()
+        })
+        .await
+        {
+            Ok(_) => handle::Handle::refresh_verge(),
+            Err(err) => log::error!(target: "app", "{err}"),
+        }
+    });
 }
 
 // 关闭tun模式
-pub fn disable_tun_mode() -> Result<()> {
-    patch_verge(IVerge {
-        enable_tun_mode: Some(false),
-        ..IVerge::default()
-    })?;
-    handle::Handle::refresh_verge();
-    Ok(())
+pub fn disable_tun_mode() {
+    tauri::async_runtime::spawn(async {
+        match patch_verge(IVerge {
+            enable_tun_mode: Some(false),
+            ..IVerge::default()
+        })
+        .await
+        {
+            Ok(_) => handle::Handle::refresh_verge(),
+            Err(err) => log::error!(target: "app", "{err}"),
+        }
+    });
 }
 
 /// 修改clash的配置
-pub fn patch_clash(patch: Mapping) -> Result<()> {
-    let patch_cloned = patch.clone();
-    let clash_mode = patch.get("mode").is_some();
-    let mixed_port = patch.get("mixed-port").is_some();
-    let external = patch.get("external-controller").is_some();
-    let secret = patch.get("secret").is_some();
+pub async fn patch_clash(patch: Mapping) -> Result<()> {
+    Config::clash().draft().patch_config(patch.clone());
 
-    // 更新info信息
-    if mixed_port || external || secret {
-        let mut tmp_config = { ClashN::global().config.lock().clone() };
-
-        for (key, value) in patch.into_iter() {
-            tmp_config.insert(key, value);
-        }
+    match {
+        let mixed_port = patch.get("mixed-port");
+        if mixed_port.is_some() {
+            let changed = mixed_port != Config::clash().data().0.get("mixed-port");
+            // 检查端口占用
+            if changed {
+                if let Some(port) = mixed_port.clone().unwrap().as_u64() {
+                    if !port_scanner::local_port_available(port as u16) {
+                        Config::clash().discard();
+                        bail!("the port not available");
+                    }
+                }
+            }
+        };
 
-        let old_info = ClashN::global().patch_info(ClashInfoN::from(&tmp_config))?;
+        // 激活配置
+        handle_activate().await?;
 
-        if let Err(err) = CoreManager::global().run_core() {
-            // 恢复旧值
-            ClashN::global().patch_info(old_info)?;
-            return Err(err);
+        // 更新系统代理
+        if mixed_port.is_some() {
+            log_err!(sysopt::Sysopt::global().init_sysproxy());
         }
-    }
-    // 存好再搞
-    ClashN::global().patch_config(patch_cloned)?;
 
-    // 激活配置
-    tauri::async_runtime::spawn(async move {
-        match handle_activate().await {
-            Ok(_) => {
-                // 更新系统代理
-                if mixed_port {
-                    log_err!(sysopt::Sysopt::global().init_sysproxy());
-                }
+        if patch.get("mode").is_some() {
+            log_err!(handle::Handle::update_systray_part());
+        }
 
-                if clash_mode {
-                    log_err!(handle::Handle::update_systray_part());
-                }
-            }
-            Err(err) => log::error!(target: "app", "{err}"),
+        <Result<()>>::Ok(())
+    } {
+        Ok(()) => {
+            Config::clash().apply();
+            Config::clash().data().save_config()?;
+            Ok(())
         }
-    });
-    Ok(())
+        Err(err) => {
+            Config::clash().discard();
+            Err(err)
+        }
+    }
 }
 
 /// 修改verge的配置
 /// 一般都是一个个的修改
-pub fn patch_verge(patch: IVerge) -> Result<()> {
-    VergeN::global().patch_config(patch.clone())?;
+pub async fn patch_verge(patch: IVerge) -> Result<()> {
+    Config::verge().draft().patch_config(patch.clone());
 
     let tun_mode = patch.enable_tun_mode;
     let auto_launch = patch.enable_auto_launch;
     let system_proxy = patch.enable_system_proxy;
     let proxy_bypass = patch.system_proxy_bypass;
-    let proxy_guard = patch.enable_proxy_guard;
     let language = patch.language;
 
-    #[cfg(target_os = "windows")]
-    {}
+    match {
+        #[cfg(target_os = "windows")]
+        {}
 
-    if tun_mode.is_some() {
-        tauri::async_runtime::spawn(async {
-            log_err!(handle_activate().await);
-        });
-    }
+        if tun_mode.is_some() {
+            handle_activate().await?;
+        }
 
-    if auto_launch.is_some() {
-        sysopt::Sysopt::global().update_launch()?;
-    }
-    if system_proxy.is_some() || proxy_bypass.is_some() {
-        sysopt::Sysopt::global().update_sysproxy()?;
-        sysopt::Sysopt::global().guard_proxy();
-    }
-    if proxy_guard.unwrap_or(false) {
-        sysopt::Sysopt::global().guard_proxy();
-    }
+        if auto_launch.is_some() {
+            sysopt::Sysopt::global().update_launch()?;
+        }
+        if system_proxy.is_some() || proxy_bypass.is_some() {
+            sysopt::Sysopt::global().update_sysproxy()?;
+            sysopt::Sysopt::global().guard_proxy();
+        }
 
-    if language.is_some() {
-        handle::Handle::update_systray()?;
-    } else if system_proxy.or(tun_mode).is_some() {
-        handle::Handle::update_systray_part()?;
-    }
+        if let Some(true) = patch.enable_proxy_guard {
+            sysopt::Sysopt::global().guard_proxy();
+        }
 
-    if patch.hotkeys.is_some() {
-        hotkey::Hotkey::global().update(patch.hotkeys.unwrap())?;
-    }
+        if let Some(hotkeys) = patch.hotkeys {
+            hotkey::Hotkey::global().update(hotkeys)?;
+        }
 
-    Ok(())
+        if language.is_some() {
+            handle::Handle::update_systray()?;
+        } else if system_proxy.or(tun_mode).is_some() {
+            handle::Handle::update_systray_part()?;
+        }
+
+        <Result<()>>::Ok(())
+    } {
+        Ok(()) => {
+            Config::verge().apply();
+            Config::verge().data().save_file()?;
+            Ok(())
+        }
+        Err(err) => {
+            Config::verge().discard();
+            Err(err)
+        }
+    }
 }
 
 /// 激活配置
@@ -216,5 +250,38 @@ pub async fn handle_activate() -> Result<()> {
 /// 更新某个profile
 /// 如果更新当前配置就激活配置
 pub async fn update_profile(uid: String, option: Option<PrfOption>) -> Result<()> {
+    let url_opt = {
+        let profiles = Config::profiles();
+        let profiles = profiles.latest();
+        let item = profiles.get_item(&uid)?;
+        let is_remote = item.itype.as_ref().map_or(false, |s| s == "remote");
+
+        if !is_remote {
+            None // 直接更新
+        } else if item.url.is_none() {
+            bail!("failed to get the profile item url");
+        } else {
+            Some((item.url.clone().unwrap(), item.option.clone()))
+        }
+    };
+
+    let should_update = match url_opt {
+        Some((url, opt)) => {
+            let merged_opt = PrfOption::merge(opt, option);
+            let item = PrfItem::from_url(&url, None, None, merged_opt).await?;
+
+            let profiles = Config::profiles();
+            let mut profiles = profiles.latest();
+            profiles.update_item(uid.clone(), item)?;
+
+            Some(uid) == profiles.get_current()
+        }
+        None => true,
+    };
+
+    if should_update {
+        handle_activate().await?;
+    }
+
     Ok(())
 }
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index f0005e7247f552bd0567823bcd3e4e607c6bc6f1..b019d0362bac0633c5967c53cd8ef06ea6814be2 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -6,7 +6,6 @@
 mod cmds;
 mod config;
 mod core;
-// mod data;
 mod enhance;
 mod feat;
 mod utils;
diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs
index 9034fce2fb3bfeac420415f2f88065ba5fd4a15b..e7810d789854b519799ffd9b182efadf64d5c607 100644
--- a/src-tauri/src/utils/resolve.rs
+++ b/src-tauri/src/utils/resolve.rs
@@ -1,5 +1,6 @@
+use crate::config::Config;
 use crate::log_err;
-use crate::{config::VergeN, core::*, utils::init, utils::server};
+use crate::{core::*, utils::init, utils::server};
 use tauri::{App, AppHandle, Manager};
 
 /// handle something when start app
@@ -19,10 +20,7 @@ pub fn resolve_setup(app: &mut App) {
 
     log_err!(tray::Tray::update_systray(&app.app_handle()));
 
-    let silent_start = {
-        let verge = VergeN::global().config.lock();
-        verge.enable_silent_start.clone()
-    };
+    let silent_start = { Config::verge().data().enable_silent_start.clone() };
     if !silent_start.unwrap_or(false) {
         create_window(&app.app_handle());
     }
diff --git a/src-tauri/src/utils/server.rs b/src-tauri/src/utils/server.rs
index 1e68326ff47bed25385cd33171fa3c7a5ce27bef..1d2ff59b0a1d10f35660524f5e094fbd68e9188b 100644
--- a/src-tauri/src/utils/server.rs
+++ b/src-tauri/src/utils/server.rs
@@ -1,14 +1,14 @@
 extern crate warp;
 
 use super::resolve;
-use crate::config::VergeN;
+use crate::config::IVerge;
 use port_scanner::local_port_available;
 use tauri::AppHandle;
 use warp::Filter;
 
 /// check whether there is already exists
 pub fn check_singleton() -> Result<(), ()> {
-    let port = VergeN::get_singleton_port();
+    let port = IVerge::get_singleton_port();
 
     if !local_port_available(port) {
         tauri::async_runtime::block_on(async {
@@ -25,7 +25,7 @@ pub fn check_singleton() -> Result<(), ()> {
 /// maybe it can be used as pac server later
 pub fn embed_server(app_handle: AppHandle) {
     let app_handle = app_handle.clone();
-    let port = VergeN::get_singleton_port();
+    let port = IVerge::get_singleton_port();
 
     tauri::async_runtime::spawn(async move {
         let commands = warp::path!("commands" / "visible").map(move || {