diff --git a/package.json b/package.json
index f4b00ac3bb6e197dc47d4c416576a8007e946fc7..799d6974f5f01795fc1a52f75107791e4758b126 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
   },
   "devDependencies": {
     "@tauri-apps/cli": "^1.0.0-beta.10",
+    "@types/fs-extra": "^9.0.13",
     "@types/react": "^17.0.0",
     "@types/react-dom": "^17.0.0",
     "@vitejs/plugin-react": "^1.1.1",
diff --git a/scripts/pre-dev.mjs b/scripts/pre-dev.mjs
index 982e4ce90814e2ad2a34c02b01f15d958fa16427..2adf798261f42f45b34dc1be03111aab2e82ca71 100644
--- a/scripts/pre-dev.mjs
+++ b/scripts/pre-dev.mjs
@@ -1,4 +1,5 @@
 import fs from "fs-extra";
+import zlib from "zlib";
 import path from "path";
 import AdmZip from "adm-zip";
 import fetch from "node-fetch";
@@ -16,15 +17,17 @@ const CLASH_LATEST_DATE = "2021.12.07";
 function resolveClash() {
   const { platform, arch } = process;
 
-  let name = "";
-
   // todo
-  if (platform === "win32" && arch === "x64") {
-    name = `clash-windows-386`;
-  }
+  const map = {
+    "win32-x64": "clash-windows-386",
+    "darwin-x64": "clash-darwin-amd64",
+    "darwin-arm64": "clash-darwin-arm64",
+  };
+
+  const name = map[`${platform}-${arch}`];
 
   if (!name) {
-    throw new Error("todo");
+    throw new Error(`unsupport platform "${platform}-${arch}"`);
   }
 
   const isWin = platform === "win32";
@@ -60,14 +63,28 @@ async function resolveSidecar() {
   if (!(await fs.pathExists(tempZip))) await downloadFile(binInfo.url, tempZip);
 
   // Todo: support gz
-  const zip = new AdmZip(tempZip);
-  zip.getEntries().forEach((entry) => {
-    console.log("[INFO]: entry name", entry.entryName);
-  });
-  zip.extractAllTo(tempDir, true);
-
-  // save as sidecar
-  await fs.rename(tempExe, sidecarPath);
+  if (binInfo.zip === "zip") {
+    const zip = new AdmZip(tempZip);
+    zip.getEntries().forEach((entry) => {
+      console.log("[INFO]: entry name", entry.entryName);
+    });
+    zip.extractAllTo(tempDir, true);
+    // save as sidecar
+    await fs.rename(tempExe, sidecarPath);
+    console.log(`[INFO]: unzip finished`);
+  } else {
+    // gz
+    const readStream = fs.createReadStream(tempZip);
+    const writeStream = fs.createWriteStream(sidecarPath);
+    readStream
+      .pipe(zlib.createGunzip())
+      .pipe(writeStream)
+      .on("finish", () => {
+        console.log(`[INFO]: gunzip finished`);
+        execSync(`chmod 755 ${sidecarPath}`);
+        console.log(`[INFO]: chmod binary finished`);
+      });
+  }
 
   // delete temp dir
   await fs.remove(tempDir);
@@ -97,6 +114,8 @@ async function downloadFile(url, path) {
   });
   const buffer = await response.arrayBuffer();
   await fs.writeFile(path, new Uint8Array(buffer));
+
+  console.log(`[INFO]: download finished "${url}"`);
 }
 
 /// main
diff --git a/yarn.lock b/yarn.lock
index 5d67fc6ceacbbd9e7bfd1e7b0a5973209cde96db..ed3aaa245b24a4fc62cdc61c13ea13be089c0ed2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -559,6 +559,13 @@
     "@types/node" "*"
     "@types/responselike" "*"
 
+"@types/fs-extra@^9.0.13":
+  version "9.0.13"
+  resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45"
+  integrity sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==
+  dependencies:
+    "@types/node" "*"
+
 "@types/http-cache-semantics@*":
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812"