前言
MacOS 的桌面管理体验有些糟糕。似乎直到最近,MacOS 才开始支持拖动窗口到屏幕边缘进行分屏。在切换窗口时,台前调度在最开始使用起来让人很喜欢,但是在需要大量窗口同时打开,或者频繁切换窗口的环境下,台前调度就显得力不从心,它 fancy 的动画效果反而成了一种负担。
我最近在使用 Raycast 和 Aerospace。这两款软件让我在 Mac 上的桌面管理体验有了质的飞跃。
Raycast
Raycast: https://raycast.com/
Raycast 是一款快捷启动器软件,可以代替 MacOS 的 Spotlight,用于快速启动应用、搜索文件等等。
但是 Raycast 绝对不只是一个快捷启动器,它还有很多强大得多的功能。以下是我最近会使用 Raycast 的一些场景:
计算器 & 计时器
训练深度学习模型的时候,估计一个任务具体需要花费的时间可能需要一些小学数学知识。
比如,某个数据集上训练某个模型的预计效率是 5115s/epoch,那么在 20 个规模相近的数据集上训练,epoch 设置为 3,训练并行度是 8 的情况下,需要多少时间?
这个问题就可以交给 Raycast,只需要按下 Cmd + Space
唤起 Raycast,输入 5115s * 3 * 20 / 8 to h
,Raycast 就会给出答案。
同时,我可以顺手设定一个计时器,Raycast 会在时间到达时提醒我,只需要输入 timer,然后输入需要定时的时间:
右上角就会生成一个倒计时的托盘图标,倒计时结束后有声音提示,非常方便。
AI 工具
2025 年,AI 工具已经成为我日常工作的一部分。遇到一些临时的问题需要用到时,打开网页浏览器访问某个工具的页面,输入问题后等待结果,再复制回到原来的地方使用,这个过程还是太繁琐了。
有了 Raycast,我可以方便地唤起 Raycast,输入 Chat 并回车,就可以直接在 Raycast 中使用 API 访问大模型:
得到回答后,只要再敲击一下回车,就可以将结果复制到剪贴板,粘贴到需要的地方。
这实际上是由 Raycast 的插件功能实现的。这是用户为 Raycast 编写的 OpenAI 插件,用于访问 OpenAI 的各个模型。由于大量的大模型都是兼容 OpenAI 的 API 的,所以这个插件可以切换到其他的模型上使用,例如,我这里使用的就是便宜大碗的 DeepSeek.
快捷键 & 自定义脚本
作为一个本科生,我经常需要访问学校的内网来查看通知、课程表等等。然而,校园网使用的 DNS 服务器存在各种各样的问题,比如,会将 GitHub 解析到境内的代理镜像,导致在终端的 git 工具常常出现 SSL 证书错误而无法工作(尽管这个问题可以修改 /etc/hosts 解决);而如果我选择代理 DNS 请求,又无法正常访问校园网内的资源。
长期以来,我解决这个问题的方法只有痛苦地手动关闭代理,手动修改 DNS 服务器,打开浏览器进行校园网认证,查看我所需要的所有信息后再打开代理。如果我此时发现我需要访问另一个校园网资源,那么这个痛苦的过程就需要再重复一遍。
目前,我使用 Raycast 自定义快捷键和脚本的功能,实现了一键切换网络环境:option + Z 连接校园网并认证,option + P 开启代理,option + X 关闭代理。
这是我自定义的几个脚本,连接校园网脚本写得冗长,还包含了连接我们宿舍 Wi-Fi(接入校园网)的代码,就不在此展示了。
function Set_Proxy
set -x http_proxy http://127.0.0.1:7897
set -x https_proxy $http_proxy
networksetup -setwebproxy Wi-Fi 127.0.0.1 7897
networksetup -setsecurewebproxy Wi-Fi 127.0.0.1 7897
networksetup -setwebproxystate Wi-Fi on
networksetup -setsecurewebproxystate Wi-Fi on
networksetup -setdnsservers Wi-Fi 8.8.8.8
echo "Set Proxy."
end
function Unset_Proxy
set -e http_proxy
set -e https_proxy
networksetup -setwebproxystate Wi-Fi off
networksetup -setsecurewebproxystate Wi-Fi off
networksetup -setdnsservers Wi-Fi 223.6.6.6 114.114.114.114
echo "Unset Proxy."
end
alias p 'Set_Proxy'
alias u 'Unset_Proxy'
我使用的 shell 是 fish,语法上不兼容 MacOS 原生的 zsh,不过如果需要迁移相当容易。
有了上面的脚本,我只需要在终端输入 p
,就可以开启代理,输入 u
就可以关闭代理,输入 z
就可以连接校园网并自动认证。
结合 Raycast 的快捷键和自定义脚本功能,我可以将这些脚本分别绑定到 option + Z, option + P, option + U,从此实现一键切换网络环境。
其他功能
Raycast 的其他功能无法一一列举,这里我简单介绍几个我正在使用的插件或内置功能:
- My IP: 查看本机的 IP 地址
- Coffee: 防止 Mac 休眠的插件,提供一对 Caffeinate/Decaffeinate 命令来进入和退出防休眠状态,也可以使用 for、while、util 等等逻辑来管理。这一使用场景还是特别常见的,相比前往电池管理界面更加方便
- Tesseract: OCR 识别,可以直接识别截图中的文字。识别中文的效果不是特别好,有大量多余空格,可以结合 OpenAI 插件让大模型自动校对,不需要精确识别的情况下,效果还算不错
- Unsplash: 在 Upsplash 网站上搜索高质量、可商用的免费图片,直接在 Raycast 中下载到本地
- Bilibili: 快速搜索 B 站视频,回车后跳转到浏览器打开并播放,在想要查找一些简单的教程类视频时比较方便
总体来说,Raycast 的功能相当强大,这主要得益于它的插件系统。Raycast 的插件是由社区维护的,用户可以编写和上传自己的插件,需要什么样奇奇怪怪的功能,几乎都能在插件市场中找到。
如果有自己非常定制化的需求,写一个简单脚本并绑定到某个快捷键或 alias 上就可以实现。
Aerospace
Aerospace: https://github.com/nikitabobko/AeroSpace
少数派上有一篇介绍 Aerospace 的文章,写得很好。珠玉在前,推荐大家先去读这篇文章:「Aerospace:消除窗口重叠,世界属于平铺」。
简单地来说,Aerospace 是一款类 i3wm 的平铺式窗口管理器。
对于知道什么是平铺式窗口管理器,并试图在 MacOS 上使用的人来说,Aerospace 相较于先前的两个解决方案(yabai 和 Amethyst)显得更加友好。
MacOS 并没有将窗口管理相关的 API 开放给开发者,因此先前的所有 Mac 平铺窗口解决方案,要么是调用一些系统的私有 API,要么关闭 SIP(System Integrity Protection),直接向系统组件注入代码。这两个方法都很容易因为系统更新而失效,使用的门槛和风险都比较高。
Aerospace 的工作原理有些灰色幽默。它建立了一套属于自己的虚拟桌面,所有的虚拟桌面实际上都在同一个 MacOS 的桌面上。当切换虚拟桌面时,Aerospace 会将当前桌面上的所有窗口“隐藏”,然后显示目标虚拟桌面上的窗口。这样,Aerospace 就实现了平铺式窗口管理的效果。
所谓的隐藏,就是将窗口移动到屏幕的外部,左下角或者右下角。这样,虽然窗口不可见,但是窗口的状态并没有被改变,窗口的位置和大小都会被记录下来。当切换回原来的虚拟桌面时,窗口会被移动回原来的位置。
引用少数派文章的一张图:
关于 Aerospace 的介绍,少数派的文章介绍得很好,我在这里不再赘述。我分享一下我的 aerospace 配置,以及我使用的一些心得。
配置
官方配置教程:AeroSpace Guide。
Aerospace 并不自带一个配置文件,如果希望自己配置一些快捷键,或者修改一些默认配置,需要自己创建配置文件。根据 Aerospace 的官方文档,配置文件可以放在 ~/.aerospace.toml
,也可以在 ~/.config/aerospace/aerospace.toml
。我这里使用后者,和 fish、nvim 等配置文件放在一起,便于管理。
使用 curl 下载默认配置文件:
curl -o aerospace.toml https://nikitabobko.github.io/AeroSpace/config-examples/default-config.toml
按照我的使用习惯,我对配置文件做了一些修改:
start-at-login = true
[gaps]
inner.horizontal = 5
inner.vertical = 5
outer.left = 10
outer.bottom = 10
outer.top = 10
outer.right = 10
设置开机自启动,并设置窗口之间留一些间隙。
alt-shift-minus = 'resize smart -75'
alt-shift-equal = 'resize smart +75'
我修改了 alt+shift+-
和 alt+shift+=
的调整幅度,这一点可以按照自己的习惯来确定。
alt-1 = 'workspace 1'
alt-2 = 'workspace 2'
alt-3 = 'workspace 3'
alt-4 = 'workspace 4'
alt-0 = 'workspace 0'
# See: https://nikitabobko.github.io/AeroSpace/commands#move-node-to-workspace
ctrl-0 = ['move-node-to-workspace 0', 'workspace 0']
ctrl-1 = ['move-node-to-workspace 1', 'workspace 1']
ctrl-2 = ['move-node-to-workspace 2', 'workspace 2']
ctrl-3 = ['move-node-to-workspace 3', 'workspace 3']
ctrl-4 = ['move-node-to-workspace 4', 'workspace 4']
关于虚拟桌面切换,我觉得创建过多的虚拟桌面并不必要,虽然 aerospace 支持创建几十个虚拟桌面,但是我只启用了五个。
同时,我将移动窗口到指定虚拟桌面的快捷键从 alt+shift+1 改为 ctrl+1。我的键盘通过 Karabiner-Elements 进行了一些键位的映射,ctrl+1 对于我来说是 capslock+1,因此更加顺手。我还在后面添加了 workspace 切换的指令,在移动窗口后自动切换到目标的虚拟桌面。
[workspace-to-monitor-force-assignment]
0 = 'Built-in Retina Display'
1 = ['X41Q', 'X71Q','Built-in Retina Display']
2 = ['X41Q', 'X71Q','Built-in Retina Display']
3 = ['X41Q', 'X71Q','Built-in Retina Display']
4 = ['X41Q', 'X71Q','Built-in Retina Display']
这段代码是用于多桌面管理的,当我外接显示器使用的时候,我会将虚拟桌面 1 到 4 映射到外接显示器上,将虚拟桌面 0 留在 MacBook 的屏幕上,保持一些简单的通知、音乐播放器等窗口。
最后,还有最重要的一段配置:
[[on-window-detected]]
if.window-title-regex-substring = '(setting|设置)'
run = 'layout floating'
[[on-window-detected]]
if.window-title-regex-substring = '(Picture-in-Picture|画中画)'
run = 'layout floating'
[[on-window-detected]]
if.app-id = 'com.apple.Music'
run = 'layout floating'
[[on-window-detected]]
if.app-id = 'com.tencent.qq'
run = 'layout floating'
[[on-window-detected]]
if.app-id = 'com.tencent.xinWeChat'
run = 'layout floating'
[[on-window-detected]]
if.app-id = 'com.alibaba.DingTalkMac'
run = 'layout floating'
这段配置会将设置、画中画、QQ、微信、钉钉、音乐播放器等窗口设置为浮动窗口,不参与平铺。
结合 Raycast,如果在我工作学习中收到了微信通知或者消息,需要查看或者及时回复。只需要按下 Cmd + Space
,输入 we
(我为微信设置的 alias),就可以快速打开微信,回复消息,然后按下 Cmd + W
关闭微信聊天窗口。这个过程非常顺利和丝滑,不会影响我的工作流。而如果没有这段代码设置浮动,微信窗口会以平铺的方式显示在桌面,打乱我的工作窗口。
使用心得
平铺窗口能最大利用屏幕空间,但是有些时候我需要一些窗口最大化显示,例如编辑复杂的深度学习模型,我希望 VSCode 能最大化利用我的屏幕空间。
然而,有时会出现这样的恼人情况:我需要同时在多个不同的工作目录上打开 VSCode,并需要来回切换(这通常发生在我需要把某些神经网络设计融合到我们模型的时候)。这时候既不适用于平铺多个窗口在同一个桌面,也不适合把窗口分散在不同的桌面来反复切换。
这时候只要按下 option + ,
就可以切换到 Aerospace 提供的卡片堆叠模式:所有的 VSCode 窗口可以在一个桌面上管理,每个窗口都能够最大利用屏幕,使用原生的 option + H/J/K/L
就可以在不同窗口之间导航。