黑苹果macOS Alfred效率工具与Workflow开发完全实战指南:从基础搜索到自定义API集成的工作流自动化生态

发布时间:2026年6月 | 分类:黑苹果 | 关键词:Alfred、效率工具、Workflow、自动化、API集成、启动器

前言:Alfred为何成为macOS效率工具之王

对于macOS用户而言,Spotlight是系统自带的搜索工具,但功能有限。Alfred则通过插件化的Workflow系统将启动器进化为效率工具的核心中枢。Alfred不仅能搜索应用、文件、执行计算、查字典,还能通过自定义Workflow完成Git操作、AWS CLI、JSON格式化、密码管理、二维码生成等几乎任何可编程的任务。

对于黑苹果用户,Alfred的价值更加凸显:黑苹果的某些macOS原生功能可能不完整,但Alfred的运行只依赖基础系统服务(Spotlight元数据、剪贴板、AppleScript),在黑苹果环境下表现稳定。本文将系统讲解Alfred的高级用法、Workflow开发、API集成、性能调优,帮助你建立专业级的效率工作流。

第一部分:Alfred基础与高级设置

Alfred Powerpack激活与配置

Alfred的基础功能免费,但Workflow、剪贴板历史、1Password集成等高级功能需要Powerpack许可证:

1. 个人许可证:单用户终身使用,45英镑(约400元人民币)

2. Mega Supporter:包含未来所有付费功能,约75英镑

购买后获得许可证文件,Alfred 5中通过License > Activate激活。

# Alfred偏好设置目录
~/Library/Application Support/Alfred/
# Workflow存储位置
~/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/
# 缓存
~/Library/Caches/com.runningwithcrayons.Alfred/
# 日志
~/Library/Logs/Alfred/

许可证激活后,Alfred的所有高级功能解锁:自定义搜索范围、Workflow系统、剪贴板历史、1Password集成、Snippets片段、Terminal/Shell集成等。开发Workflow是Alfred最强大的特性,下面详细讲解。

通用配置优化

# Alfred Preferences > General
# 启动快捷键:⌥Space(推荐,不与Spotlight冲突)
# 开机自启动:勾选
# 隐藏菜单栏图标:可选

# Alfred Preferences > Features > Default Results
# Search Scope:Applications, Settings, Bookmarks等
# 排序方式:Best Match(默认)
# 限制搜索目录:排除System、Library等

# Alfred Preferences > Features > Web Bookmarks
# 启用并配置自定义书签搜索

# Alfred Preferences > Features > Clipboard History
# 保留时间:3个月
# 最大数量:1000条
# 快捷键:⌥⌘C

通用设置的核心是"快捷键+搜索范围"的精细化配置。启动快捷键建议使用⌥Space或⌃Space,避免与Spotlight(⌘Space)冲突;搜索范围可按需排除Library等系统目录以减少噪音;剪贴板历史建议开启3个月保留+1000条上限,足够日常使用。

第二部分:核心Workflow生态

必备官方与社区Workflow

Alfred的Workflow生态极其丰富。以下是黑苹果用户必备的核心Workflow:

1. GitHub Workflow:在Alfred中搜索GitHub仓库、Issue、PR,浏览代码片段。

2. Dash Workflow:在Alfred中搜索Dash文档(macOS上最流行的API文档浏览器)。

3. Terminal/Shell Workflow:快速打开iTerm2、运行命令、切换目录。

4. 1Password Workflow:在Alfred中快速搜索和填充密码。

5. 系统控制Workflow:清空回收站、隐藏应用、睡眠/唤醒、调节音量。

6. 时间戳转换Workflow:Unix时间戳与人类可读时间互转。

7. 颜色选择器Workflow:取色、转换颜色格式。

8. Hash计算Workflow:MD5、SHA1、SHA256等哈希值计算。

# 安装Workflow的方法
# 1. 从alfredapp.com/workflows下载
# 2. 双击.alfredworkflow文件自动安装
# 3. 付费Workflow可能通过Packal.org或开发者官网分发

# 必备Workflow列表(开发相关)
# - Dash:https://github.com/Kapeli/Dash-Alfred-Workflow
# - GitHub:https://github.com/gharlan/alfred-github-workflow
# - Can I Use:浏览器兼容性查询
# - Emoji Search:Emoji搜索
# - JetBrains:打开JetBrains IDE项目
# - VS Code:VS Code项目快速打开

# Workflow安装目录
open ~/Library/Application\ Support/Alfred/Alfred.alfredpreferences/workflows/

# 调试Workflow(如果运行异常)
# Alfred Preferences > Workflows > 选中具体Workflow > 右上角"🐛"调试按钮

社区Workflow的质量参差不齐,建议优先使用活跃维护、有GitHub仓库的Workflow。判断标准:最近的更新日期、Issue响应、Star数量。Alfred Gallery(alfredapp.com/workflows)收录了大量官方和社区Workflow,质量有基本保障。

第三部分:自定义Workflow开发入门

Workflow结构与开发环境

Alfred Workflow本质是一个Alfred.alfredpreferences/工作流目录,其中包含info.plist(定义Workflow元数据)和各种脚本/二进制:

# 创建Workflow的目录结构
mkdir -p ~/Desktop/MyFirstWorkflow
cd ~/Desktop/MyFirstWorkflow

# 基本结构
# ├── icon.png  (Workflow图标,建议256x256像素)
# ├── info.plist (Workflow配置)
# └── script.sh  (执行脚本,可选)
# 或
# ├── icon.png
# ├── info.plist
# └── main.py (Python脚本)

# 打包为.alfredworkflow文件
# Alfred Preferences > Workflows > 右下角"+" > Blank Workflow
# 添加Script Filter、Keyword等节点
# 完成开发后右键Workflow > Export

Workflow的最小单元是"Node"(节点)。常见节点类型:

Trigger:触发器(Keyword、Hotkey、AppleScript、File Filter等)

Input:输入(Script Filter、Arg and Vars、List Filter等)

Action:动作(Open URL、Run Script、Copy to Clipboard、Post Notification等)

Output:输出(Show Alfred、Connect to Hotkey等)

一个完整的Workflow是这些节点的连接图,从触发到输入到动作到输出形成数据流。

第一个Script Filter Workflow

Script Filter是最常用的节点,它执行脚本并以结构化方式显示结果:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 文档说明(docstring)
# Alfred Workflow: 快速搜索黑苹果相关Kext
# Keyword: k

import json
import sys
import os
import subprocess

# 模拟kext数据库
KEXTS = [
    {"name": "Lilu", "version": "1.6.7", "desc": "内核扩展补丁框架,几乎所有kext的基础"},
    {"name": "VirtualSMC", "version": "1.3.4", "desc": "SMC模拟器,Hackintosh必备"},
    {"name": "WhateverGreen", "version": "1.6.6", "desc": "显卡补丁框架"},
    {"name": "AppleALC", "version": "1.9.2", "desc": "声卡驱动"},
    {"name": "USBInjectAll", "version": "0.7.7", "desc": "USB端口注入"},
    {"name": "IntelMausi", "version": "1.0.7", "desc": "Intel有线网卡驱动"},
    {"name": "RealtekRTL8111", "version": "2.4.2", "desc": "Realtek千兆网卡驱动"},
    {"name": "AirportItlwm", "version": "2.2.0", "desc": "Intel Wi-Fi驱动"},
    {"name": "BrcmPatchRAM", "version": "2.6.7", "desc": "博通蓝牙驱动"},
    {"name": "CpuTscSync", "version": "1.1.0", "desc": "TSC同步,解决唤醒问题"},
    {"name": "NVMeFix", "version": "1.1.0", "desc": "NVMe SSD电源管理"},
    {"name": "HibernationFixup", "version": "1.4.4", "desc": "休眠修复"},
    {"name": "RTCMemoryFixup", "version": "1.0.7", "desc": "CMOS内存修复"},
    {"name": "RestrictEvents", "version": "1.1.3", "desc": "进程阻止"},
    {"name": "SMCBatteryManager", "version": "1.3.0", "desc": "笔记本电池支持"},
]

def filter_kexts(query):
    """根据查询过滤kext列表"""
    query_lower = query.lower()
    results = []
    for k in KEXTS:
        # 计算简单匹配分数
        score = 0
        if query_lower in k['name'].lower():
            score += 100
        if query_lower in k['desc'].lower():
            score += 50
        if score > 0:
            results.append((score, k))
    # 按分数排序
    results.sort(key=lambda x: -x[0])
    return [k for _, k in results[:10]]

def main():
    # Alfred传入的查询字符串
    query = sys.argv[1] if len(sys.argv) > 1 else ""
    
    # 过滤kext
    results = filter_kexts(query)
    
    # 构造Alfred XML/JSON输出
    items = []
    for k in results:
        item = {
            "uid": k['name'],
            "title": k['name'],
            "subtitle": f"v{k['version']} - {k['desc']}",
            "arg": k['name'],
            "autocomplete": k['name'],
            "icon": {
                "path": "icon.png"
            },
            "mods": {
                "cmd": {
                    "subtitle": "复制版本号",
                    "arg": k['version']
                },
                "alt": {
                    "subtitle": "复制描述",
                    "arg": k['desc']
                }
            }
        }
        items.append(item)
    
    # 输出JSON到stdout
    print(json.dumps({"items": items}))

if __name__ == "__main__":
    main()

将以上Python脚本保存为kext_search.py,配置Alfred Workflow:

1. Trigger:Keyword = "k"(或你喜欢的触发词)

2. Connection to:Script Filter(调用上面的脚本)

3. Script Filter的Action:Run Script(这里我们直接用Script Filter输出,无需额外Action)

4. 配置Language = /usr/bin/python3

现在在Alfred中输入"k whatever"即可看到WhateverGreen等匹配项,按Enter选中,⌘+点击复制版本号,⌥+点击复制描述。

第四部分:API集成Workflow

调用外部API实现天气查询

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Alfred Workflow: 快速查询天气
Keyword: weather
使用wttr.in免费天气API
"""

import json
import sys
import urllib.request
import urllib.parse

def get_weather(city):
    """通过wttr.in获取天气信息"""
    try:
        # wttr.in的简单文本API
        url = f"https://wttr.in/{urllib.parse.quote(city)}?format=j1"
        req = urllib.request.Request(url, headers={'User-Agent': 'curl/7.79'})
        with urllib.request.urlopen(req, timeout=10) as response:
            data = json.loads(response.read().decode('utf-8'))
            
            current = data['current_condition'][0]
            weather_desc = current['weatherDesc'][0]['value']
            temp_c = current['temp_C']
            feels_like_c = current['FeelsLikeC']
            humidity = current['humidity']
            wind_speed = current['windspeedKmph']
            
            return {
                "success": True,
                "title": f"{city}当前天气: {weather_desc}",
                "subtitle": f"温度: {temp_c}°C (体感 {feels_like_c}°C) | 湿度: {humidity}% | 风速: {wind_speed}km/h"
            }
    except Exception as e:
        return {
            "success": False,
            "title": f"获取天气失败: {city}",
            "subtitle": str(e)
        }

def main():
    query = sys.argv[1] if len(sys.argv) > 1 else "Beijing"
    result = get_weather(query)
    
    if result['success']:
        items = [{
            "uid": "weather",
            "title": result['title'],
            "subtitle": result['subtitle'],
            "arg": result['subtitle'],
            "icon": {"path": "weather_icon.png"}
        }]
    else:
        items = [{
            "uid": "weather_error",
            "title": result['title'],
            "subtitle": result['subtitle'],
            "arg": "",
            "icon": {"path": "error_icon.png"}
        }]
    
    print(json.dumps({"items": items}))

if __name__ == "__main__":
    main()

使用方式:在Alfred中输入"weather Wuhan"即可查询武汉天气。wttr.in是无需API Key的免费服务,返回JSON格式的详细天气数据。这个Workflow展示了Alfred调用外部API的完整模式:HTTP请求 → JSON解析 → 结构化输出。

集成GitHub API的个人仓库搜索

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Alfred Workflow: 搜索个人GitHub仓库
Keyword: gh
需要配置GitHub Personal Access Token
"""

import json
import sys
import urllib.request
import os

def get_github_repos(query, token):
    headers = {
        'Authorization': f'token {token}',
        'User-Agent': 'Alfred-GitHub-Workflow'
    }
    url = f"https://api.github.com/search/repositories?q={urllib.parse.quote(query)}+user:YOURUSERNAME"
    
    req = urllib.request.Request(url, headers=headers)
    with urllib.request.urlopen(req, timeout=10) as response:
        return json.loads(response.read().decode('utf-8'))

def main():
    # Token存储在环境变量中
    token = os.environ.get('GITHUB_TOKEN', '')
    if not token:
        print(json.dumps({"items": [{
            "title": "请先设置GITHUB_TOKEN环境变量",
            "subtitle": "在Alfred Workflow的Environment Variables中配置",
            "arg": ""
        }]}))
        return
    
    query = sys.argv[1] if len(sys.argv) > 1 else ""
    if not query:
        print(json.dumps({"items": [{
            "title": "输入仓库名关键词",
            "subtitle": "例如: hackintosh",
            "arg": ""
        }]}))
        return
    
    try:
        result = get_github_repos(query, token)
        items = []
        for repo in result.get('items', [])[:10]:
            items.append({
                "uid": str(repo['id']),
                "title": repo['full_name'],
                "subtitle": f"⭐ {repo['stargazers_count']} - {repo['description'] or '无描述'}",
                "arg": repo['html_url'],
                "autocomplete": repo['name'],
                "mods": {
                    "cmd": {
                        "subtitle": "复制SSH URL",
                        "arg": repo['ssh_url']
                    },
                    "alt": {
                        "subtitle": "复制clone URL",
                        "arg": repo['clone_url']
                    }
                }
            })
        print(json.dumps({"items": items}))
    except Exception as e:
        print(json.dumps({"items": [{
            "title": "查询失败",
            "subtitle": str(e),
            "arg": ""
        }]}))

if __name__ == "__main__":
    main()

使用Alfred Preferences > Workflows > 选中Workflow > Environment Variables配置GITHUB_TOKEN。这种方式将敏感信息存储在Alfred的加密环境中,比硬编码在脚本中更安全。GitHub Personal Access Token可在GitHub Settings > Developer settings > Personal access tokens生成。

第五部分:高级特性与性能优化

Snippets片段系统

Alfred Snippets(Powerpack功能)是文本片段快速展开工具,类似TextExpander但更轻量:

# 常用Snippets配置示例
# Keyword: ;sig
# Snippet: 
# --
# Best regards,
# Your Name
# Senior Engineer
# Email: you@example.com
# Tel: +86 138-0000-0000
# --

# Keyword: ;addr
# Snippet:
# 湖北省武汉市蔡甸区XX路XX号
# 邮编:430100

# Keyword: ;ssid
# Snippet: MyWiFi-{date:yyyyMMdd-HHmmss}

# Keyword: ;uuidgen
# Snippet: {some-uuid-generation-script}

# 自动展开设置
# Auto-expand: enabled
# 触发方式:输入keyword后空格/回车自动展开

Snippets的强大之处在于支持自动展开和占位符。{date:yyyyMMdd}会自动展开为当前日期,{clipboard}会插入剪贴板内容。在黑苹果使用中,可以用Snippets快速输入EFI配置模板、常用命令、SSDT表头等重复性内容。

剪贴板历史高级用法

# 剪贴板历史(Powerpack)
# 快捷键:⌥⌘C
# 或Alfred输入"clip"

# 查看图片剪贴板内容
# Alfred Preferences > Features > Clipboard History
# Preferential Text Types:
#   - Plain Text
#   - Rich Text
#   - Images
# Maximum: 1000 entries
# Keep: 3 months

# 收藏重要剪贴板
# 按⌘+1到⌘+9标记收藏
# 收藏项在"⌘+数字键"组合下快速访问

# 合并剪贴板(多行合并为单行)
# 默认在剪贴板历史中按⌘+⇧+M

剪贴板历史是Alfred的"后悔药"。忘记复制某个内容时,只需打开Alfred剪贴板历史搜索即可找到。在调试OpenCore配置时,经常需要复制多个kext的版本号、不同的config.plist片段、错误日志等,剪贴板历史使得切换变得无比轻松。

第六部分:自定义搜索源与Univeral Action

Universal Action设计

Universal Action允许对任何Alfred搜索结果(应用、文件、URL、文本)应用自定义动作。常见用途:

# Universal Action配置
# 1. 在Workflows中创建新的Universal Action
# 2. 设置Hotkey(如⌥+U)
# 3. 配置Input:Files, Text, URLs等
# 4. Connection to: Run Script

# Python脚本示例:对选中的文件执行操作
#!/usr/bin/env python3
import json
import sys
import os
import hashlib

# Alfred通过stdin传入文件路径
data = json.load(sys.stdin)
items_data = data.get("items", [])

items = []
for item in items_data:
    file_path = item.get("path", "")
    if not os.path.isfile(file_path):
        continue
    
    # 文件信息
    file_name = os.path.basename(file_path)
    file_size = os.path.getsize(file_path)
    
    # 计算SHA256
    sha256 = hashlib.sha256()
    with open(file_path, 'rb') as f:
        for chunk in iter(lambda: f.read(4096), b''):
            sha256.update(chunk)
    sha256_hex = sha256.hexdigest()
    
    # 计算MD5
    md5 = hashlib.md5()
    with open(file_path, 'rb') as f:
        for chunk in iter(lambda: f.read(4096), b''):
            md5.update(chunk)
    md5_hex = md5.hexdigest()
    
    items.append({
        "title": file_name,
        "subtitle": f"大小: {file_size} 字节",
        "arg": f"SHA256: {sha256_hex}
MD5: {md5_hex}",
        "mods": {
            "cmd": {
                "subtitle": "复制SHA256",
                "arg": sha256_hex
            },
            "alt": {
                "subtitle": "复制MD5",
                "arg": md5_hex
            }
        }
    })

print(json.dumps({"items": items}))

使用方式:在Finder中选择文件,按⌥+U(配置的Hotkey),Alfred显示可执行动作列表。选中后Alfred执行脚本,文件哈希值显示在通知中,⌘+点击复制SHA256,⌥+点击复制MD5。这种Universal Action设计可以应用到任何文件类型,是Alfred的高级用法精髓。

File Filter与动态过滤

# File Filter配置
# 在Finder中选择文件,通过Hotkey触发Alfred
# Alfred显示与文件相关的动作

# 实战:检查kext文件的有效性
#!/usr/bin/env python3
import json
import sys
import os
import plistlib
import zipfile

data = json.load(sys.stdin)
items_data = data.get("items", [])

items = []
for item in items_data:
    path = item.get("path", "")
    if path.endswith(".kext"):
        # 检查kext的Info.plist
        info_plist = os.path.join(path, "Contents", "Info.plist")
        if os.path.isfile(info_plist):
            try:
                with open(info_plist, 'rb') as f:
                    plist = plistlib.load(f)
                bundle_id = plist.get('CFBundleIdentifier', '未知')
                version = plist.get('CFBundleVersion', '未知')
                items.append({
                    "title": os.path.basename(path),
                    "subtitle": f"Bundle ID: {bundle_id} v{version}",
                    "arg": path,
                    "icon": {"path": path}
                })
            except Exception as e:
                items.append({
                    "title": os.path.basename(path),
                    "subtitle": f"无法解析Info.plist: {e}",
                    "arg": path
                })

print(json.dumps({"items": items}))

这个File Filter特别适合OpenCore EFI管理:在Finder中选择kext文件夹,按Hotkey即可看到所有kext的版本和Bundle ID,方便快速核对EFI配置。

总结:Alfred将黑苹果工作流效率提升到极致

Alfred的Workflow系统是一个完整的效率平台,远超简单的启动器功能。从基础的文件、应用搜索,到复杂的API集成、自定义动作、Shell命令执行,Alfred覆盖了黑苹果用户日常工作的方方面面。本文展示的Kext搜索、天气查询、GitHub仓库管理、文件哈希计算、kext检查只是冰山一角——Workflow的可能性只受限于你的想象力。

特别建议黑苹果用户从"复制粘贴OpenCore配置片段"、"快速查找kext最新版本"、"一键打开EFI分区"这些高频痛点出发,逐步构建自己的Workflow库。可以浏览Alfred官方Gallery和GitHub上的awesome-alfred-workflows仓库寻找灵感。当积累的Workflow达到10+个后,你会发现每天节省的时间累计可达数小时——这就是Alfred作为生产力工具的真实价值。

高级用户可以考虑将Alfred Workflow集成到CI/CD中:如GitHub Action发布新版本时自动更新Workflow内部的数据文件,确保Alfred查询的内容始终是最新版本。这使得Alfred不仅是个人效率工具,更可以与团队的工作流深度集成。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。