diff --git a/src-tauri/src/cmd.rs b/src-tauri/src/cmd.rs
index 12aee41d3abd30d23f7e2a20d1293cd5c2e5b448..5c2cb387aa020d1986307903aeb4c3be47ed48a5 100644
--- a/src-tauri/src/cmd.rs
+++ b/src-tauri/src/cmd.rs
@@ -1,17 +1,31 @@
-use tauri::api::process::kill_children;
-
-use crate::utils::{clash, import};
+use crate::{
+  events::{emit::ClashInfoPayload, state::ClashInfoState},
+  utils::{clash, import},
+};
+use tauri::{api::process::kill_children, AppHandle, State};
 
 #[tauri::command]
-pub fn cmd_restart_sidebar() {
+pub fn restart_sidebar(app_handle: AppHandle, clash_info: State<'_, ClashInfoState>) {
   kill_children();
-  clash::run_clash_bin();
+  let payload = clash::run_clash_bin(&app_handle);
+
+  if let Ok(mut arc) = clash_info.0.lock() {
+    *arc = payload;
+  }
 }
 
 #[tauri::command]
-pub async fn cmd_import_profile(url: String) -> Result<String, String> {
+pub async fn import_profile(url: String) -> Result<String, String> {
   match import::import_profile(&url).await {
     Ok(_) => Ok(String::from("success")),
     Err(_) => Err(String::from("error")),
   }
 }
+
+#[tauri::command]
+pub fn get_clash_info(clash_info: State<'_, ClashInfoState>) -> Option<ClashInfoPayload> {
+  match clash_info.0.lock() {
+    Ok(arc) => Some(arc.clone()),
+    _ => None,
+  }
+}
diff --git a/src-tauri/src/events/emit.rs b/src-tauri/src/events/emit.rs
new file mode 100644
index 0000000000000000000000000000000000000000..029cc35fdd978d262fd7b36c8a6cfa24a2a49df7
--- /dev/null
+++ b/src-tauri/src/events/emit.rs
@@ -0,0 +1,26 @@
+use serde::{Deserialize, Serialize};
+use tauri::{AppHandle, Manager};
+
+use crate::config::ClashController;
+
+#[derive(Default, Debug, Clone, Deserialize, Serialize)]
+pub struct ClashInfoPayload {
+  /// value between `success` and `error`
+  pub status: String,
+
+  /// the clash core's external controller infomation
+  pub controller: Option<ClashController>,
+
+  /// some message
+  pub message: Option<String>,
+}
+
+/// emit `clash_runtime` to the main windows
+pub fn clash_start(app_handle: &AppHandle, payload: &ClashInfoPayload) {
+  match app_handle.get_window("main") {
+    Some(main_win) => {
+      main_win.emit("clash_start", payload).unwrap();
+    }
+    _ => {}
+  };
+}
diff --git a/src-tauri/src/events/mod.rs b/src-tauri/src/events/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..c382b2f33dd1128a958d87e09b224b25f87921d6
--- /dev/null
+++ b/src-tauri/src/events/mod.rs
@@ -0,0 +1,2 @@
+pub mod emit;
+pub mod state;
diff --git a/src-tauri/src/events/state.rs b/src-tauri/src/events/state.rs
new file mode 100644
index 0000000000000000000000000000000000000000..22aa77ffa71ab1c92171b860da5e662f68546c71
--- /dev/null
+++ b/src-tauri/src/events/state.rs
@@ -0,0 +1,6 @@
+use std::sync::{Arc, Mutex};
+
+use super::emit::ClashInfoPayload;
+
+#[derive(Default)]
+pub struct ClashInfoState(pub Arc<Mutex<ClashInfoPayload>>);
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index 742cf33b7a4607f937141abaffa67b1210173f49..98765ec6741cd9df0422e6661ce74e174968a17a 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -7,10 +7,13 @@ extern crate tauri;
 
 mod cmd;
 mod config;
+mod events;
 mod utils;
 
+use crate::events::state::ClashInfoState;
+use std::sync::{Arc, Mutex};
 use tauri::{
-  CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
+  api, CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
   SystemTraySubmenu,
 };
 
@@ -41,6 +44,7 @@ fn main() -> std::io::Result<()> {
           window.set_focus().unwrap();
         }
         "quit" => {
+          api::process::kill_children();
           app.exit(0);
         }
         _ => {}
@@ -53,18 +57,18 @@ fn main() -> std::io::Result<()> {
       _ => {}
     })
     .invoke_handler(tauri::generate_handler![
-      cmd::cmd_import_profile,
-      cmd::cmd_restart_sidebar,
+      cmd::import_profile,
+      cmd::restart_sidebar,
+      cmd::get_clash_info,
     ])
     .build(tauri::generate_context!())
     .expect("error while running tauri application");
 
   // init app config
   utils::init::init_app(app.package_info());
-  // clash::run_clash_bin();
-
-  // 通过clash config初始化menu和tray
-  // 通过verge config干点别的
+  // run clash sidecar
+  let info = utils::clash::run_clash_bin(&app.handle());
+  app.manage(ClashInfoState(Arc::new(Mutex::new(info))));
 
   app.run(|app_handle, e| match e {
     tauri::Event::CloseRequested { label, api, .. } => {
@@ -75,6 +79,9 @@ fn main() -> std::io::Result<()> {
     tauri::Event::ExitRequested { api, .. } => {
       api.prevent_exit();
     }
+    tauri::Event::Exit => {
+      api::process::kill_children();
+    }
     _ => {}
   });
 
diff --git a/src-tauri/src/utils/clash.rs b/src-tauri/src/utils/clash.rs
index d028b7940b3a3df7694f76dc80e1cfacab8cff3c..9d2c46dda7d1c77ad3fe2292e5b6d9c2f80230ec 100644
--- a/src-tauri/src/utils/clash.rs
+++ b/src-tauri/src/utils/clash.rs
@@ -1,29 +1,63 @@
 extern crate log;
 
-use crate::utils::app_home_dir;
-use tauri::api::process::{Command, CommandEvent};
+use crate::{
+  config::read_clash_controller,
+  events::emit::{clash_start, ClashInfoPayload},
+  utils::app_home_dir,
+};
+use tauri::{
+  api::process::{Command, CommandEvent},
+  AppHandle,
+};
 
 /// Run the clash bin
-pub fn run_clash_bin() {
+pub fn run_clash_bin(app_handle: &AppHandle) -> ClashInfoPayload {
   let app_dir = app_home_dir();
+  let mut payload = ClashInfoPayload {
+    status: "success".to_string(),
+    controller: None,
+    message: None,
+  };
 
-  let (mut rx, _sidecar) = Command::new_sidecar("clash")
-    .expect("failed to create clash binary")
-    .args(["-d", &app_dir.as_os_str().to_str().unwrap()])
-    .spawn()
-    .expect("failed to spawn sidecar");
+  match Command::new_sidecar("clash") {
+    Ok(cmd) => match cmd
+      .args(["-d", &app_dir.as_os_str().to_str().unwrap()])
+      .spawn()
+    {
+      Ok((mut rx, _)) => {
+        log::info!("Successfully execute clash sidecar");
+        payload.controller = Some(read_clash_controller());
 
-  tauri::async_runtime::spawn(async move {
-    while let Some(event) = rx.recv().await {
-      match event {
-        CommandEvent::Stdout(line) => {
-          log::info!("{}", line);
-        }
-        CommandEvent::Stderr(err) => {
-          log::error!("{}", err);
-        }
-        _ => {}
+        tauri::async_runtime::spawn(async move {
+          while let Some(event) = rx.recv().await {
+            match event {
+              CommandEvent::Stdout(line) => log::info!("{}", line),
+              CommandEvent::Stderr(err) => log::error!("{}", err),
+              _ => {}
+            }
+          }
+        });
       }
+      Err(err) => {
+        log::error!(
+          "Failed to execute clash sidecar for \"{:?}\"",
+          err.to_string()
+        );
+        payload.status = "error".to_string();
+        payload.message = Some(err.to_string());
+      }
+    },
+    Err(err) => {
+      log::error!(
+        "Failed to execute clash sidecar for \"{:?}\"",
+        err.to_string()
+      );
+      payload.status = "error".to_string();
+      payload.message = Some(err.to_string());
     }
-  });
+  };
+
+  clash_start(app_handle, &payload);
+
+  payload
 }