我把“显示器有单独的空间”关掉后,系统菜单栏只留在主显示器顶端,副屏顶部空空如也,观感和可用性都不太好。于是配置了SketchyBar,在多个屏幕显示统一的顶栏,并添加了一些自定义组件。SketchyBar一般和yabai或aerospace窗口管理工具配合使用,我进行了一些开发,使其能单独正常工作。

左边栏:系统菜单、桌面切换、在屏窗口、桌面和App菜单快速切换
左边栏:系统菜单、桌面切换、在屏窗口、桌面和App菜单快速切换
右边栏:iStat Menus、实时天气、App状态、Wi-Fi信息
右边栏:iStat Menus、实时天气、App状态、Wi-Fi信息

安装和配置SketchyBar

基于SketchyBar作者的配置文件,采用 SketchyBar + SbarLua 的组合,主要逻辑用 Lua,少量 C语言小工具做事件和数据采集。辅助程序(定位、桌面窗口扫描等)放在 helpers/ 下,按需编译调用。由于窗口最大化会盖住SketchyBar,我使用Hammerspoon做了顶部调整,不用依赖 yabai 或 aerospace 窗口管理工具。

安装方法有两种:快速安装和手动安装。

快速安装

运行一行命令,自动下载配置文件并安装所需软件。

curl -L https://raw.githubusercontent.com/binbinsh/sketchybar-config/main/install_sketchybar.sh | sh

自动安装脚本会完成以下操作:

  • 安装 lua、nowplaying-cli、sketchybar 这三个软件。

  • 安装字体:SF Symbols、SF Mono、SF Pro 和 sketchybar-app-font.ttf.

  • 安装 SbarLua.

  • 下载配置文件到 ~/.config/sketchybar 文件夹(如果已有旧配置会先备份)。

  • 重新启动 SketchyBar.

  • 安装和配置 Hammerspoon,并添加最大化快捷键。

为了防止窗口挡住顶部SketchyBar状态栏,需要配置 Hammerspoon:设置窗口顶部留出 32px 空间,并添加 Alt+Shift+M 快捷键来最大化窗口(但不遮挡状态栏)。

手动安装

按照自动安装脚本的步骤,逐个安装需要的软件和字体,然后启动服务。

SketchyBar组件

我的主要目的是“显示器有单独的空间”关闭时,实现跨屏一致的顶栏,多个桌面和App菜单快速切换。我陆陆续续添加了组件:音量和SoundSource配置、更详细的WiFi信息、基于设备定位的实时OpenWeather天气、剪贴板管理、基于Raycast的快速谷歌翻译、加载/卸载LM Studio模型、最近3个Time Machine备份、微信未读信息、1Password、Synergy状态、Quantumult X和公网IP信息、iStat Menus 整合。

大部分组件支持点击弹窗、右键直达设置或应用,减少跳转。

前台应用

显示当前激活应用名,点击通过 swap_menus_and_spaces 事件在 menus/spaces 之间切换。

LM Studio

点击弹出已安装模型列表,点击即可加载模型,右键打开 LM Studio 应用。所有操作通过lms完成,安装LM Studio CLI的方法: https://lmstudio.ai/docs/cli .

Clipboard

点击打开 Raycast Clipboard History,右键打开 Raycast Ask Clipboard.

Dictionary

点击即时翻译所选文本,右键打开 Raycast Quick Translate。需要安装 Raycast Google Translate (gebeto/translate) 扩展。

Volume

显示当前的输出音量,点击打开 SoundSource 配置界面,SoundSource 支持设置耳机EQ,比如我的Sennheiser HD 490 Pro耳机。右键打开系统声音设置。

Quantumult X

点击弹出公网 IP、位置、ISP,这些信息从ipinfo.io获取,右键点击打开 Quantumult X.

1Password

点击打开1Password Quick Access (通过Cmd+Shift+Space),右键打开应用。

微信

通过读取 Dock Badge 显示未读信息数,点击打开微信。需要安装 macOS 版 WeChat,并打开WeChat的通知图标标记。

iStat Menus

通过SketchyBar的alias功能,从macOS原menubar获取和显示iStat Menus合并组件。点击打开活动监视器。

Time Machine

点击通过系统自带 tmutil 读取最近1-3次备份时间,并弹窗显示。右键打开time machine.

Synergy

点击弹窗显示Synergy 1的server和client运行状态,右键打开Synergy配置界面。

Weather

使用OpenWeather One Call API 3.0获取当前天气,通过SketchyBar Location Helper获取当前设备定位,再用OpenStreetMap Nominatim反查地点名,最后从OpenWeather获取实时天气。

使用OpenWeather API需要注册API key并写入钥匙串:

# 将OpenWeather API密钥存在钥匙串中
security add-generic-password -a "$USER" -s OPENWEATHERMAP_API_KEY -w '<YOUR_API_KEY>' -U

# SketchyBar读取OpenWeather API的方法
security find-generic-password -a "$USER" -s OPENWEATHERMAP_API_KEY -w

API key申请后,可能需要等1–2小时才会生效。

SketchyBar Location Helper

为了能够获取本地实时天气,我实现了小工具SketchyBarLocationHelper.app,用Core Location获取设备定位,并写入缓存文件 ~/.cache/sketchybar/location.txt(格式:ts|lat|lon|label)。天气小部件读取定位、用OpenStreetMap反查地点名、再请求 OpenWeather获取天气。

手动触发方式:

open -W ~/.config/sketchybar/helpers/event_providers/location/bin/SketchyBarLocationHelper.app

首次运行会出现While Using the App的定位授权,可在系统设置→隐私与安全性→定位服务管理。无法获取定位会出现⚠️ LOC错误,可以重试或检查定位服务。

space_scan获取桌面所有窗口

由于不使用yabai和aerospace等窗口管理工具,SketchyBar又无法获取桌面所有窗口,我实现了一个小工具 helpers/event_providers/space_scan/space_scan.c,通过CoreGraphics和SkyLight API获取窗口。在启动SketchyBar或切换桌面时,会扫描当前活跃桌面上的所有窗口,以应用为维度计数,并发布 space_snapshot 事件,items/spaces.lua 订阅后即时更新对应 space.<index> 的图标与计数。

macOS系统设置

  1. 把系统菜单栏设为始终自动隐藏:系统设置→菜单栏→自动隐藏和显示菜单栏→始终

  2. 若使用天气组件,首次定位授权选择“使用App期间即可”。

  3. 用iStat Menus时,需启用合并菜单项,用于整体alias到SketchyBar.

参考资料