TechMoon 科技月球
WordPress、SEO 與 AI 工具實測指南
TechMoon 科技月球
WordPress、SEO 與 AI 工具實測指南

KeyStats 是一款 MIT 授權的 macOS 選單列鍵鼠計數器,用 CGEvent tap 記錄每日按鍵與滑鼠點擊次數。原始碼驗證發現它只記數字鍵碼不記文字、事件攔截器唯讀,但 macOS 版啟動即送 PostHog 遙測且無關閉開關,與 README 稱資料留在本機的說法有落差。
用 AI 摘要這篇文章:
想知道自己一天到底敲了多少鍵、點了多少下滑鼠,這件事在 macOS 上的老牌選項是 WhatPulse。它的代價是要註冊帳號、把統計送上它的雲端,還有排行榜和公開的個人頁面。KeyStats(GitHub 上的 debugtheworldbot/keyStats)走的是另一個方向:一個裝在選單列的小圖示,README 寫明資料留在本機、不上傳。不過實際把原始碼拉下來讀,會發現「留在本機」這四個字只說了一半的故事,另一半藏在 AppDelegate.swift 裡。
KeyStats 是一款原生 macOS 選單列應用,用 Swift 寫成,MIT 授權,截至 2026 年 7 月底在 GitHub 拿到 1400 多顆星、53 個 fork,最新版本是 7 月 27 日發布的 v1.51。專案 2025 年 12 月底才建立,七個月內從 v1 發展到 v1.51,發布節奏密集(v1.49 在 7 月 4 日、v1.50 在 7 月 18 日加端到端加密同步、v1.51 在 7 月 27 日),目前只剩 2 個 open issue 而且都是功能請求而非 bug 回報。作者署名 pipizhu,原始碼註解和提交紀錄都以中文撰寫,官方網站設在 keystats.vercel.app。它也提供 Windows 版(用 C# 和 WPF 寫,依賴 .NET Framework 4.8,Windows 10 以上免額外安裝執行階段),社群另有人(GitHub 帳號 0x5c0f)維護 Linux 分支。下面談的隱私與機制以 macOS 版的原始碼為準。

KeyStats 用的是 macOS 的 CGEvent tap 這套系統級事件監聽 API。在 KeyStatsHelper/EventTapController.swift 第 63 行,事件攔截器的選項明確寫著 .listenOnly,意思是它只被動觀察鍵鼠事件通過,不會攔截、修改或吞掉任何輸入。這和鍵盤記錄器(keylogger)的行為有本質差別:後者會把你的輸入攔下來偷偷送出去,前者只是站在旁邊數次數。事件遮罩涵蓋 keyDown、flagsChanged、左右鍵和其他滑鼠按下、滑鼠移動與拖曳、捲動,其中滑鼠移動取樣被限制在每秒 30 次避免吃效能。
具體記下哪些欄位,可以從 KeyStatsHelper/PayloadBuilder.swift 第 14 到 17 行看得很清楚。按鍵事件只取 keyCode(數字鍵碼,代表你按了鍵盤上哪個物理位置)、keyboardType(鍵盤型號)、flags(修飾鍵狀態,用來算組合鍵)和 isAutoRepeat(是否自動重複),沒有 characters 欄位。換句話說,它知道你按了 QWERTY 鍵盤的某個位置,但不把你打出的文字內容存下來。滑鼠點擊只記左右鍵次數和按鈕編號,不記游標座標;滑鼠移動會記位置用來算總移動距離,捲動記滾動差值。每日午夜自動歸零,重開機後統計還在(靠 UserDefaults 和本地檔案持久化,沒有用到 CoreData 或 SQLite)。

README 還提到「per-key 與組合鍵次數」這個欄位,意思是它會記你按了哪些鍵各幾次(例如空白鍵今天按了 487 次、Shift 加某鍵的組合按了 12 次),可以用來畫鍵盤熱力圖。這比單純總次數多了資訊量,但仍然不包含輸入順序和文字內容:知道空白鍵被按 487 次和知道你打了什麼字,是兩回事。從原始碼看,KeyStats 在這層面上的設計是誠實的,它只在做計數器該做的事。
問題出在另一條資料流。打開 KeyStats/AppDelegate.swift,第 2 行是 import PostHog,第 30 到 35 行在應用程式啟動的 applicationDidFinishLaunching 裡無條件初始化了 PostHog 分析 SDK:
let config = PostHogConfig(
apiKey: "phc_TYyyKIfGgL1CXZx7t9dY7igE3yNwNpjj9aqItSpNVLx",
host: "https://us.i.posthog.com"
)
config.captureApplicationLifecycleEvents = true
config.captureScreenViews = true
PostHogSDK.shared.setup(config)
這代表每次 KeyStats 啟動,它就會把應用生命週期事件(安裝、開啟、關閉)、你點開的每個視窗或面板畫面(因為 captureScreenViews 開著),以及每次你點按 UI 元素(例如「請求輔助使用權限」「重置統計」「匯入統計」)送到 PostHog 的美國雲端伺服器(us.i.posthog.com)。PostHog SDK 還會自動帶上 IP 位址(用來推測地理位置)、裝置型號、螢幕解析度、語系、安裝識別碼等標準屬性。應用程式自己登記的基礎屬性還包含 app 版號、build 編號、作業系統版本。
更要緊的是,macOS 版沒有給你關掉這層遙測的開關。整個 KeyStats/ 目錄找不到 AnalyticsEnabled 或任何分析設定欄位;設定介面(SettingsViewController.swift)和在地化字串檔裡也沒有任何遙測或隱私相關的選項。PostHog 在啟動那一刻就初始化了,沒有同意流程、沒有首次彈窗問你要不要送遙測。
對比之下,Windows 版的 KeyStats.Windows/KeyStats/Models/AppSettings.cs 第 23 行有一個 AnalyticsEnabled 屬性,預設是 true(開),但起碼你在設定裡找得到它、關得掉。同一個專案的兩個平台在這件事上不對稱,macOS 使用者少了這個選擇權。repo 裡的開發文件 CLAUDE.md 甚至寫明「新增頁面或彈窗時要補上對應的 PostHog 分析事件」,顯示遙測是刻意的設計、而且還在持續擴充,不是忘了拿掉的 debug 工具。
這和 README 寫的「Data stays on the local device by default」(資料預設留在本機)形成一個落差。準確地說,README 講的是鍵鼠統計資料(次數、距離、熱力圖),那部分確實留在本機,PostHog 從不送鍵鼠統計數字;但應用程式本身的使用行為(你什麼時候開、點了哪些按鈕、用什麼系統、IP 大概在哪)是啟動就送上雲端的。如果你在乎的是「我打了多少字、有沒有人偷看內容」,KeyStats 過關;如果你在乎的是「這個 app 會不會跟外面講話」,它其實會,而且 macOS 版目前不讓你阻止它。挑個同類做對照:Speech-to-Markdown 也是需要輔助使用權限的 macOS 選單列工具,各自的遙測策略值得擺在一起看。
v1.50 版(2026 年 7 月中)加入的多裝置同步功能和上面的遙測是兩條獨立的管道,不該混為一談。同步功能預設關閉,你要主動用配對碼把兩台裝置連起來才會啟用。從 KeyStats/Sync/SyncCrypto.swift 可以看到它用 Apple 的 CryptoKit 做 AES GCM 加密,金鑰用 HKDF搭配 SHA256 從配對種子推導出來,伺服器端只收到加密過的資料 blob,解不開內容。
同步的範圍也有限制:每日按鍵總數、個別按鍵與組合鍵次數、滑鼠按鍵點擊次數會同步;滑鼠移動距離、捲動距離、個別應用程式統計不會同步。後端是一個跑在 Cloudflare Workers 的 TypeScript 服務(原始碼在 repo 的 services/sync-worker/ 目錄),用 D1 SQLite 存加密紀錄,端點走 HTTPS,有速率限制和裝置數量上限。所以即使你開了同步,伺服器營運者也看不到你的原始數字,這層加密設計經得起原始碼檢驗。
把這條和 PostHog 分開看很重要:同步是你主動選擇把鍵鼠統計加密傳出去,對象是 KeyStats 自己的 Cloudflare 後端,而且加密金鑰只在你裝置上;PostHog 遙測是 app 啟動就自動送使用行為,對象是第三方分析服務,而且是明文屬性(app 版號、作業系統、頁面瀏覽)。把兩者當成同一件事,會誤判這個工具的隱私模型。
KeyStats 的 macOS 版沒有經過蘋果程式碼簽章。首次安裝時你要手動到「系統設定 > 隱私與安全 > 輔助使用」裡勾選它,它才能監聽鍵鼠事件;未授權時一個數字都不會記。因為未簽章,macOS 不會在重新安裝或升級後自動延續授權,你要先移除舊的 KeyStats 條目再重新點 app 裡的「取得權限」按鈕。entitlements 檔(KeyStats.entitlements)裡 com.apple.security.app-sandbox 設為 false,App Sandbox 是關掉的,因為全域事件監聽本來就和 Sandbox 互斥,但這也意味著 app 以完整系統權限在跑,不受沙箱保護限制。
給一個未簽章的 app 輔助使用權限,等於讓它有能力讀取你在這台 Mac 上所有的鍵盤輸入。KeyStats 的原始碼證實它只用這個權力數次數、不存內容,而且事件攔截器是唯讀的,但這個信任是建立在「你相信原始碼描述的就是編譯出來的那份程式」之上。官方下載的 .dmg 和 .zip 是不是和 repo 裡的原始碼一模一樣,除非你自己用 SPM 從原始碼編譯,否則無法百分之百確認。Homebrew 安裝(brew tap debugtheworldbot/keystats 再 brew install keystats)是官方推薦的路徑,至少 Homebrew 的 cask 有 checksum 可以核對檔案完整性,比直接下載多一層保障。Windows 版的權限模型完全不同:它不需要任何額外權限設定,啟動就能開始記錄,因為 .NET 的全域事件鉤子不需要等同 macOS 輔助使用權限那樣的門檻。這對台灣讀者值得留意的地方是,如果你同時有 Mac 和 Windows 機器,兩邊的隱私代價不對稱:Mac 要你手動授權但遙測關不掉,Windows 不用授權但遙測可以關。
Sparkle 自動更新框架每 24 小時會去 GitHub Releases 拉 appcast.xml 檢查有沒有新版本,這是除了 PostHog 之外另一個固定的網路呼叫。從 v1.51 的下載數字看,appcast.xml 被抓了 4500 多次(代表正在使用的 macOS 實例做更新檢查),KeyStats.zip 直接下載 313 次、.dmg 62 次,Windows 版下載 87 次。Sparkle 用 Ed25519 簽章驗證更新檔來源,更新檔如果不是原作者簽的會被擋下,算是一個靠譜的更新驗證機制。
回到開頭的對比。把資料模型擺第一,就能解釋兩者的差別。WhatPulse 靠雲端帳號運作:你的統計上傳到它的伺服器,才能做跨裝置比對、排行榜、歷史趨勢圖、公開的個人檔案頁。KeyStats 把鍵鼠統計留在本機,同步是加密的選項,理論上伺服器看不到明文。但 KeyStats 多了一層 WhatPulse 在商業模式上比較透明的東西:PostHog 使用遙測,而且是 macOS 版關不掉的那種。WhatPulse 送的是你同意上傳的統計資料(你註冊帳號那一刻就知道要上雲端),KeyStats 送的是 app 使用行為而且 README 沒提。兩者的「不意外程度」不同。
如果你的需求只是「想知道今天敲了多少下鍵盤、哪個鍵最常按」,而且不在意 app 啟動時送一些使用次數給分析服務,KeyStats 的原始碼品質和活躍度是可以考慮的。如果你對任何形式的背景網路流量都零容忍,那就要知道 macOS 版目前不給你關 PostHog 的選項。同樣是 macOS 選單列工具,FindDiskKiller 走的是磁碟 I/O 監控路線,不碰鍵鼠事件,權限模型完全不同。
適合的人:macOS 13 Ventura 以上、想用選單列看每日鍵鼠點擊量、願意給未簽章 app 輔助使用權限、不在意啟動遙測的開發者或效率追蹤愛好者。這群人拿到的是一個輕量(.dmg 約 4 MB)、原始碼公開、MIT 授權、可以用 Homebrew 裝的原生工具,鍵鼠統計本身確實留在本機,而且 per-key 熱力圖能告訴你哪些鍵最操。和 Logi Options+ Mini 那種精簡官方驅動的方向不同,KeyStats 量的是使用行為,Logi Options+ Mini 量的是硬體狀態,方向不同。
該先等一下的人:對背景網路流量零容忍的隱私硬核使用者(macOS 版的 PostHog 目前無法關閉)、只接受程式碼簽章 app 的人、需要長期歷史趨勢圖而且不想自己匯出的人(KeyStats 的統計每日歸零,歷史要靠手動匯出或開同步留存)、以及系統版本低於 macOS 13 的人。這些限制不一定是缺點,取決於你怎麼定義「夠用」。
想裝的話,官方路徑是 Homebrew:brew tap debugtheworldbot/keystats 再 brew install keystats,或從 GitHub Releases 下 .dmg。裝完跑起來要在系統設定裡授輔助使用權限。原始碼在 github.com/debugtheworldbot/keyStats,想自己驗證上面講的任何一條都可以 clone 下來看,特別是 AppDelegate.swift 第 30 行那段 PostHog 初始化和 EventTapController.swift 第 63 行的 listenOnly,這兩行決定了這個工具的隱私邊界到底畫在哪。如果你只想看每日數字、不打算開同步、也不在意啟動時送一點使用統計給分析服務,裝起來放著它就會在選單列幫你數。如果你在意,那就直接去 repo 開 issue 問作者會不會在 macOS 版補上和 Windows 版一樣的遙測開關。