
字节笔记本
2026年10月5日 · 约 8 分钟读完
Permiso:macOS 权限授权从 7 步降到 2 步
macOS 的隐私权限授权一直有个出了名的体验问题:当应用需要辅助功能、屏幕录制这类敏感权限时,传统做法是让用户点「打开系统设置」,在侧栏里找到对应面板,在一长串列表里定位自己的应用,点「+」号,再到文件选择器里把应用添加进来,最后手动打开开关。七八步走完,相当一部分用户早已中途放弃。
OpenAI 的 AI Agent 编程工具 Codex 给出了一个被广泛称赞的解法:直接在系统设置的权限列表下方覆盖一个拖拽区域,用户把应用图标拖进去,授权就完成了。随后,这套交互被开源成了 Swift 包 Permiso,任何 macOS 应用都可以一行代码接入,目前在 GitHub 上已收获 500 多个 star。

Permiso 是什么
Permiso(仓库地址 zats/permiso)是一个极简的 Swift 包:全部实现只有 6 个源文件、合计 687 行代码,复刻的正是 Codex 那个「拖拽授权」交互。通过 Swift Package Manager 引入仓库后,一行代码就能在应用里弹出权限引导覆盖层:
import Permiso
@MainActor
func showAccessibilityHelper() {
PermisoAssistant.shared.present(panel: .accessibility)
}调用之后,用户看到的是:
- 系统设置自动打开,并跳到对应的权限面板;
- 权限列表正下方出现一个拖拽区域;
- 把应用图标拖进列表,授权完成。
而不再是传统那条「系统设置、隐私、辅助功能、找应用、点加号、添加、开启」的漫长路径。
技术原理:六个文件怎么协作
整条链路的实现非常克制,核心流程如下图:

六个源文件各司其职:
| 文件 | 行数 | 职责 |
|---|---|---|
| PermisoAssistant.swift | 85 | 入口,负责 present 与 dismiss、定时器追踪 |
| OverlayWindowController.swift | 315 | 透明覆盖窗口的创建、定位与渲染 |
| AppDragSourceView.swift | 136 | 可拖拽的应用图标视图 |
| SettingsWindowLocator.swift | 105 | 在屏幕上定位系统设置窗口的位置和大小 |
| PermisoPanel.swift | 23 | 定义权限面板类型与直达 URL |
| PermisoHostApp.swift | 23 | 描述「哪个应用需要授权」 |
有三个实现细节值得展开。
第一,窗口位置追踪。系统设置窗口可以被用户随意移动和调整大小,Permiso 用一个 0.15 秒间隔的定时器不断重新定位覆盖层,保证它始终贴在权限列表下方。定位依据来自 SettingsWindowLocator 对最前台窗口的快照,一旦找不到系统设置窗口,覆盖层会直接隐藏。
第二,应用切换监听。Permiso 向 NSWorkspace 的通知中心注册了 didActivateApplicationNotification,用户切走应用时立即刷新位置或隐藏覆盖层,不会留下一个悬在半空的孤儿窗口。
第三,拖拽源视图。AppDragSourceView 基于 NSDraggingItem 和 beginDraggingSession 这套原生拖放 API 实现,覆盖层里的应用图标可以被直接拖进系统设置的列表。覆盖窗口本身的 level 被设为 .statusBar,这也是它能盖在系统设置窗口上面的关键。
从 7 步到 2 步:设计为什么被称赞
把两条路径并排看,差距一目了然:

传统流程里,用户要经历提示、跳转、找面板、找应用、点加号、文件选择器、开启开关这七步,多数人卡在「列表里找不到自己的应用」和「不知道加号在哪」这两处。Permiso 把它压缩成两步:覆盖层弹出、拖进图标。有开发者在相关讨论里点评:「2026 年的好设计,是让平台故意设阻的事变得简单。」macOS 的权限链路偏长,某种程度上是安全上的有意为之,而覆盖层方案在不绕过任何安全机制的前提下,把复杂性留给了开发者,把简单留给了用户。
支持哪些权限
PermisoPanel 枚举目前提供两个面板:
public enum PermisoPanel: String, CaseIterable, Sendable {
case accessibility = "Privacy_Accessibility"
case screenRecording = "Privacy_ScreenCapture"
}这两个恰好是 macOS 开发者最常打交道的权限:全局快捷键、模拟点击需要辅助功能,截屏录屏类工具需要屏幕录制。每个面板各自维护一个 x-apple.systempreferences: 协议的直达 URL,present 时由系统直接跳到对应面板,省去用户翻找的过程。输入监控等更多面板类型目前源码里还没有,需要的话可以照着现有实现自行扩展。
怎么集成
通过 Swift Package Manager 添加仓库地址即可引入,使用时按需选择面板:
import Permiso
// 需要辅助功能权限时
PermisoAssistant.shared.present(panel: .accessibility)
// 需要屏幕录制权限时
PermisoAssistant.shared.present(panel: .screenRecording)拖拽区里展示的应用信息由 PermisoHostApp 描述,包含名称、bundleURL 和图标,默认通过 PermisoHostApp.current() 从主 bundle 自动读取,一般不需要手动配置。
一个通用的 macOS 模式:透明覆盖层
Permiso 依赖的核心技术,即用一个透明 NSWindow 盖在其他应用上面,是 macOS 原生开发里相当通用的模式。社区里可以找到不少同类实践:有的项目把覆盖层贴在刘海区展示 Agent 状态,有的盖在桌面上做截图标注,有的用来显示录音状态。Permiso 的价值在于,它把这个模式用在一个非常具体的痛点上,并且只用了不到 700 行代码,是一份很适合拿来精读的实现样本。
小结
Permiso 是 Codex 权限引导流的开源 Swift 实现:6 个源文件、687 行代码、一行 API,把 macOS 权限授权从 7 步压到 2 步。如果你的 macOS 应用需要辅助功能或屏幕录制权限,或者你想学习「覆盖层、窗口追踪、拖放」这套组合拳,它都值得一看。
有开发者的那句点评,可以作为这篇的注脚:「2026 年的好设计,是让平台故意设阻的事变得简单。」
本文基于 Permiso 仓库源码与相关公开讨论整理,仓库地址:https://github.com/zats/permiso



