lovstudio:finder-action
Installation
SKILL.md
finder-action — Mac Finder 右键菜单动作生成器
根据用户描述生成 Finder 右键菜单动作,自动判断模式:
| 场景 | 模式 | 技术方案 |
|---|---|---|
| 右键文件/文件夹 | Quick Action | Automator workflow |
| 右键空白处 | Finder Extension | Swift + xcodegen |
参数格式
<动作名称> [触发描述]
示例:
pdf2png .pdf 将PDF所有页面纵向拼接成一张PNG→ Quick Action新建md文件 在空白处右键创建markdown文件→ Finder Extension
模式判断
关键词命中 → Finder Extension 模式:
- 提到「空白处」「背景」「目录背景」「新建文件」「blank space」「background」
- 动作不需要选中文件即可触发
其他情况 → Quick Action 模式
Mode A: Quick Action(Automator workflow)
Step 1: 分析需求
收集(缺失时 AskUserQuestion):
- 动作名称:右键菜单显示名
- 触发文件类型:
.pdf、.md、.jpg等 - 核心命令:用什么工具做什么
Step 2: 检查依赖
which <所需工具>
不存在则提示 brew install <tool>。
Step 3: 生成 shell 脚本
#!/bin/bash
for f in "$@"; do
[[ "$f" == *.<ext> ]] || continue
output="${f%.<ext>}.<out_ext>"
<具体命令> "$f" -o "$output"
done
- 工具路径用绝对路径(Quick Action 环境没有
$PATH) "$@"接收文件参数(inputMethod=1)
Step 4: 创建 Automator workflow
创建 ~/Library/Services/<动作名称>.workflow/Contents/document.wflow。
模板见 references/automator-template.xml。
关键配置:
inputMethod:1serviceInputTypeIdentifier:com.apple.Automator.fileSystemObjectworkflowTypeIdentifier:com.apple.Automator.servicesMenu
Step 5: 验证注册
plutil -lint ~/Library/Services/<动作名称>.workflow/Contents/document.wflow
/System/Library/CoreServices/pbs -update
killall Finder
Step 6: Automator 保存(关键)
open -a Automator ~/Library/Services/<动作名称>.workflow
必须在 Automator 中 Cmd+S 保存一次才会正式注册。
Mode B: Finder Sync Extension(Swift app)
Step 1: 检查工具链
which xcodegen && which xcodebuild
缺 xcodegen 则 brew install xcodegen。
Step 2: 创建项目结构
<ProjectName>/
├── project.yml
├── <ProjectName>/
│ └── AppDelegate.swift
└── FinderExtension/
└── FinderSync.swift
Step 3: 生成 project.yml
模板见 references/xcodegen-template.yml。替换 APP_NAME 和 BUNDLE_ID。
关键点:
- 宿主 App:
LSUIElement: true(无 Dock 图标) - Extension:
NSExtensionPointIdentifier: com.apple.FinderSync - 签名:
CODE_SIGN_IDENTITY: "-"(ad-hoc) - 沙盒必须开启(
app-sandbox: true),否则扩展不会被系统加载 - 文件写入需用
temporary-exception.files.absolute-path.read-write: [/],files.user-selected.read-write无效
Step 4: 生成 AppDelegate.swift
import Cocoa
@main
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {}
}
Step 5: 生成 FinderSync.swift
模板见 references/finder-sync-template.swift。
核心 API:
FIFinderSyncController.default().directoryURLs = [URL(fileURLWithPath: "/")]— 监控所有目录menu(for: .contextualMenuForContainer)— 空白处右键菜单FIFinderSyncController.default().targetedURL()— 获取当前目录
常见 action 模式:
- 创建文件:
FileManager.default.createFile+ 自动递增文件名 - 打开终端:AppleScript 控制 iTerm2/Terminal(见
references/applescript-iterm.swift) - 执行脚本:
Process()启动 shell 命令
AppleScript 自动化需要在 entitlements 中添加:
com.apple.security.automation.apple-events: true
Step 6: 构建安装
xcodegen generate
xcodebuild -project APP_NAME.xcodeproj -scheme APP_NAME -configuration Debug build
cp -R ~/Library/Developer/Xcode/DerivedData/APP_NAME-*/Build/Products/Debug/APP_NAME.app /Applications/
open /Applications/APP_NAME.app
pluginkit -e use -i BUNDLE_ID.FinderExtension
Step 7: 验证
pluginkit -m -i BUNDLE_ID.FinderExtension
不出现时指引:系统设置 → 通用 → 登录项与扩展 → 已添加的扩展 → 勾选。
沙盒限制与 Helper App 方案
Finder Sync Extension 的沙盒限制非常严格:
| 操作 | 是否允许 | 说明 |
|---|---|---|
| 写入 /tmp | ❌ | 即使添加 temporary-exception 也被阻止 |
| Process() 子进程 | ❌ | 无法启动外部命令 |
| NSAppleScript | ❌ | 无法控制其他应用 |
| NSWorkspace.open(file) | ❌ | 无法打开文件/目录 |
| NSWorkspace.open(app) | ✅ | 可以打开应用 |
| NSPasteboard | ✅ | 可以读写剪贴板 |
推荐方案:创建一个非沙盒的 Helper App,Extension 把命令放入剪贴板后打开 Helper App,由 Helper App 执行实际操作。
Helper App 示例
mkdir -p "/Applications/OpenCCHelper.app/Contents/MacOS"
cat > "/Applications/OpenCCHelper.app/Contents/Info.plist" << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key><string>run.sh</string>
<key>CFBundleIdentifier</key><string>com.lovstudio.OpenCCHelper</string>
<key>LSUIElement</key><true/>
</dict>
</plist>
EOF
cat > "/Applications/OpenCCHelper.app/Contents/MacOS/run.sh" << 'EOF'
#!/bin/bash
CMD=$(pbpaste)
osascript << APPLESCRIPT
tell application "iTerm"
activate
tell current window
create tab with default profile
tell current session
write text "$CMD"
end tell
end tell
end tell
APPLESCRIPT
EOF
chmod +x "/Applications/OpenCCHelper.app/Contents/MacOS/run.sh"
Extension 中调用:
let command = "cd '\(targetPath)' && claude"
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(command, forType: .string)
NSWorkspace.shared.open(URL(fileURLWithPath: "/Applications/OpenCCHelper.app"))
其他已知限制
- Bundle ID 不能含下划线:使用连字符或驼峰命名(
OpenCC而非open_cc) - NSHomeDirectory() 返回容器路径:沙盒中返回
~/Library/Containers/<bundle-id>/Data/,监控目录需硬编码真实路径 - NSMenuItem 必须设置 target:
item.target = self,否则 action 不会触发 - Finder Extension 菜单项位置由系统决定,无法排在「新建文件夹」之前
- Quick Action 环境没有
$PATH,工具路径必须用绝对路径 - Automator workflow 需在 Automator 中打开保存才能注册
- Extension 使用 ad-hoc 签名,仅限本机使用
Weekly Installs
20
Repository
lovstudio/skillsGitHub Stars
40
First Seen
8 days ago
Installed on
opencode20
gemini-cli20
deepagents20
antigravity20
github-copilot20
codex20