permiso-accessibility-permissions
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePermiso — macOS Permission Dialog Helper
Permiso — macOS权限对话框助手
Skill by ara.so — Daily 2026 Skills collection.
Permiso provides a polished permission dialog UI for macOS apps that guides users through enabling accessibility and privacy settings — replicating the guided flow seen in OpenAI's Codex Computer Use product.
由ara.so开发的Skill — 属于Daily 2026 Skills合集。
Permiso为macOS应用提供了一套精致的权限对话框UI,引导用户启用辅助功能和隐私设置——复刻了OpenAI Codex Computer Use产品中的引导流程。
What It Does
功能介绍
- Presents an animated, guided overlay panel directing users to open System Settings and enable specific permissions (e.g. Accessibility)
- Mirrors the UX pattern from Codex Computer Use: an on-screen assistant that walks users through enabling access
- Handles the common friction point of macOS permission flows with a clear, app-integrated UI
- 展示带有动画效果的引导式覆盖面板,指引用户打开系统设置并启用特定权限(如辅助功能)
- 复刻Codex Computer Use的UX模式:通过屏幕助手引导用户完成权限启用流程
- 借助清晰的应用集成式UI,解决macOS权限流程中的常见痛点
Installation
安装方法
Swift Package Manager
Swift Package Manager
Add to your :
Package.swiftswift
dependencies: [
.package(url: "https://github.com/zats/permiso", branch: "main")
]Or in Xcode: File → Add Package Dependencies → enter
https://github.com/zats/permisoThen add to your target's dependencies:
Permisoswift
.target(
name: "YourApp",
dependencies: ["Permiso"]
)添加到你的中:
Package.swiftswift
dependencies: [
.package(url: "https://github.com/zats/permiso", branch: "main")
]或者在Xcode中操作:File → Add Package Dependencies → 输入
https://github.com/zats/permiso然后将添加到你的目标依赖中:
Permisoswift
.target(
name: "YourApp",
dependencies: ["Permiso"]
)Core API
核心API
Basic Usage
基础用法
swift
import Permiso
@MainActor
func showAccessibilityHelper() {
PermisoAssistant.shared.present(panel: .accessibility)
}swift
import Permiso
@MainActor
func showAccessibilityHelper() {
PermisoAssistant.shared.present(panel: .accessibility)
}Triggering on App Launch
应用启动时触发
swift
import SwiftUI
import Permiso
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onAppear {
checkAndRequestAccessibility()
}
}
}
@MainActor
func checkAndRequestAccessibility() {
let trusted = AXIsProcessTrusted()
if !trusted {
PermisoAssistant.shared.present(panel: .accessibility)
}
}
}swift
import SwiftUI
import Permiso
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onAppear {
checkAndRequestAccessibility()
}
}
}
@MainActor
func checkAndRequestAccessibility() {
let trusted = AXIsProcessTrusted()
if !trusted {
PermisoAssistant.shared.present(panel: .accessibility)
}
}
}AppDelegate Pattern
AppDelegate模式
swift
import AppKit
import Permiso
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
requestAccessibilityIfNeeded()
}
@MainActor
func requestAccessibilityIfNeeded() {
guard !AXIsProcessTrusted() else { return }
PermisoAssistant.shared.present(panel: .accessibility)
}
}swift
import AppKit
import Permiso
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
requestAccessibilityIfNeeded()
}
@MainActor
func requestAccessibilityIfNeeded() {
guard !AXIsProcessTrusted() else { return }
PermisoAssistant.shared.present(panel: .accessibility)
}
}Common Patterns
常见使用模式
Check Permission Before Sensitive Actions
敏感操作前检查权限
swift
import Permiso
import ApplicationServices
@MainActor
func performAccessibilityAction() {
guard AXIsProcessTrusted() else {
PermisoAssistant.shared.present(panel: .accessibility)
return
}
// Proceed with accessibility-dependent work
doAccessibilityWork()
}swift
import Permiso
import ApplicationServices
@MainActor
func performAccessibilityAction() {
guard AXIsProcessTrusted() else {
PermisoAssistant.shared.present(panel: .accessibility)
return
}
// 继续执行依赖辅助功能的操作
doAccessibilityWork()
}Polling for Permission Grant
轮询权限授予状态
swift
import Permiso
import ApplicationServices
import Combine
class PermissionMonitor: ObservableObject {
@Published var isAccessibilityGranted = false
private var timer: AnyCancellable?
@MainActor
func startMonitoring() {
if AXIsProcessTrusted() {
isAccessibilityGranted = true
return
}
PermisoAssistant.shared.present(panel: .accessibility)
timer = Timer.publish(every: 1.0, on: .main, in: .common)
.autoconnect()
.sink { [weak self] _ in
if AXIsProcessTrusted() {
self?.isAccessibilityGranted = true
self?.timer?.cancel()
}
}
}
}swift
import Permiso
import ApplicationServices
import Combine
class PermissionMonitor: ObservableObject {
@Published var isAccessibilityGranted = false
private var timer: AnyCancellable?
@MainActor
func startMonitoring() {
if AXIsProcessTrusted() {
isAccessibilityGranted = true
return
}
PermisoAssistant.shared.present(panel: .accessibility)
timer = Timer.publish(every: 1.0, on: .main, in: .common)
.autoconnect()
.sink { [weak self] _ in
if AXIsProcessTrusted() {
self?.isAccessibilityGranted = true
self?.timer?.cancel()
}
}
}
}SwiftUI View Integration
SwiftUI视图集成
swift
import SwiftUI
import Permiso
struct SettingsView: View {
@State private var accessibilityGranted = AXIsProcessTrusted()
var body: some View {
VStack(spacing: 16) {
HStack {
Image(systemName: accessibilityGranted ? "checkmark.circle.fill" : "xmark.circle.fill")
.foregroundColor(accessibilityGranted ? .green : .red)
Text("Accessibility Access")
}
if !accessibilityGranted {
Button("Enable Accessibility Access") {
requestAccess()
}
.buttonStyle(.borderedProminent)
}
}
.padding()
.onReceive(Timer.publish(every: 2, on: .main, in: .common).autoconnect()) { _ in
accessibilityGranted = AXIsProcessTrusted()
}
}
@MainActor
func requestAccess() {
PermisoAssistant.shared.present(panel: .accessibility)
}
}swift
import SwiftUI
import Permiso
struct SettingsView: View {
@State private var accessibilityGranted = AXIsProcessTrusted()
var body: some View {
VStack(spacing: 16) {
HStack {
Image(systemName: accessibilityGranted ? "checkmark.circle.fill" : "xmark.circle.fill")
.foregroundColor(accessibilityGranted ? .green : .red)
Text("辅助功能权限")
}
if !accessibilityGranted {
Button("启用辅助功能权限") {
requestAccess()
}
.buttonStyle(.borderedProminent)
}
}
.padding()
.onReceive(Timer.publish(every: 2, on: .main, in: .common).autoconnect()) { _ in
accessibilityGranted = AXIsProcessTrusted()
}
}
@MainActor
func requestAccess() {
PermisoAssistant.shared.present(panel: .accessibility)
}
}Requirements
系统要求
- macOS: The library targets macOS (version as specified by the package; check for macOS 13+ for best compatibility)
- Swift: Swift 5.9+
- Main Actor: must be called from the main thread /
PermisoAssistant.shared.present(panel:)context@MainActor
- macOS:本库面向macOS(具体版本以包内说明为准;建议使用macOS 13+以获得最佳兼容性)
- Swift:Swift 5.9+
- Main Actor:必须在主线程/
PermisoAssistant.shared.present(panel:)上下文调用@MainActor
Entitlements / Info.plist
权限配置 / Info.plist
For accessibility usage, ensure your app's includes a usage description (though macOS doesn't require this like iOS, it's good practice), and that your app is not sandboxed or has the correct entitlements if it needs to use accessibility APIs:
Info.plistxml
<!-- In your .entitlements file if needed -->
<key>com.apple.security.temporary-exception.apple-events</key>
<true/>For apps that actually use accessibility features after permission is granted:
swift
// Request trust prompt (system dialog) alongside Permiso's guided UI
let options = [kAXTrustedCheckOptionPrompt.takeRetainedValue(): true] as CFDictionary
AXIsProcessTrustedWithOptions(options)对于辅助功能使用,请确保应用的包含使用说明(尽管macOS不像iOS那样强制要求,但这是良好实践),并且应用未开启沙箱,或者如果需要使用辅助功能API,请配置正确的权限:
Info.plistxml
<!-- 如有需要,添加到你的.entitlements文件中 -->
<key>com.apple.security.temporary-exception.apple-events</key>
<true/>对于在获得权限后实际使用辅助功能的应用:
swift
// 在Permiso引导式UI之外,请求信任提示(系统对话框)
let options = [kAXTrustedCheckOptionPrompt.takeRetainedValue(): true] as CFDictionary
AXIsProcessTrustedWithOptions(options)Troubleshooting
故障排除
Panel doesn't appear
- Ensure you're calling from / main thread
@MainActor - Check that your app has a visible window; the panel attaches to the app's UI context
AXIsProcessTrusted()- macOS caches trust state; the app may need to be relaunched or the check polled with a timer (see polling pattern above)
- Some sandboxed apps require a full app restart after granting accessibility
Build errors:
cannot find 'PermisoAssistant' in scope- Confirm is at the top of the file
import Permiso - Confirm the package is added to the correct target in Xcode, not just the project
Panel appears but dismisses immediately
- Make sure you're not overriding the window or calling dismiss logic right after present
- Avoid calling present inside a that gets cancelled immediately
Task { }
面板不显示
- 确保你在/主线程中调用
@MainActor - 检查应用是否有可见窗口;面板会附加到应用的UI上下文
AXIsProcessTrusted()- macOS会缓存信任状态;可能需要重启应用,或者使用计时器轮询检查(参考上述轮询模式)
- 部分开启沙箱的应用在授予辅助功能权限后需要完全重启
编译错误:
cannot find 'PermisoAssistant' in scope- 确认文件顶部已添加
import Permiso - 确认包已添加到Xcode的正确目标中,而不只是项目中
面板显示后立即消失
- 确保你没有在调用present后立即覆盖窗口或调用关闭逻辑
- 避免在会立即被取消的中调用present
Task { }
Key Types Reference
关键类型参考
| Type | Description |
|---|---|
| Singleton entry point — use |
| Shows the guided permission dialog |
| Panel type for Accessibility settings |
| 类型 | 描述 |
|---|---|
| 单例入口点 — 使用 |
| 显示引导式权限对话框 |
| 用于辅助功能设置的面板类型 |