OpenClaw Apple Reminders 技能:用 remindctl 在终端里管理 Apple 提醒事项
【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 🦞项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw
本篇技术指南以 OpenClaw 仓库内置的apple-reminders技能为核心,完整讲解该技能如何通过第三方 CLI 工具remindctl实现 Apple Reminders 的增删查改:从 SKILL.md 的 frontmatter 元数据(平台限定、二进制依赖、Homebrew 安装规范),到全部常用命令与日期格式,再到 OpenClaw 加载该技能时的源码级解析链路。读完本文后,你可以复现该技能在 macOS 上的完整使用方式,并理解 OpenClaw 是如何解析、校验并发现这类"依赖外部二进制"的技能的。
技能定位:给 Agent 一个操作 Apple 提醒事项的抓手
OpenClaw 的skills/目录内置了一批面向 macOS 生态的技能包,每个技能以一个目录加一份SKILL.md的形式组织,例如与本文同类的 things-mac 技能。本文的主角 apple-reminders 技能 的定位很明确:让 Agent 能够代表用户直接管理 Apple 提醒事项(Reminders)App,包括查询、创建、编辑、完成、删除提醒以及管理提醒列表,所有操作经由终端工具remindctl完成。
技能文档开篇给出的使用边界值得注意,它同时回答了"什么时候用"和"什么时候不要用"两个问题:
应该使用的场景:
- 用户明确提到 "reminder" 或 "Reminders app";
- 需要创建会同步到 iOS 设备的个人待办(含截止日期);
- 需要管理 Apple Reminders 的列表;
- 用户希望任务出现在其 iPhone/iPad 的 Reminders App 中。
不应使用的场景(技能文档明确列举):
- 调度 OpenClaw 自身的任务或提醒 → 应改用
cron工具并配合 systemEvent; - 日历事件或约会 → 应使用 Apple Calendar;
- 项目/工作类任务管理 → 应使用 Notion、GitHub Issues 或任务队列;
- 一次性通知 → 用
cron工具做定时提醒; - 用户说 "remind me" 但实际指的是 OpenClaw 告警 → 必须先澄清意图。
这种"能力边界声明"本身就是技能设计的关键部分:它防止 Agent 把 Apple 提醒事项当成通用提醒/调度机制滥用。文档末尾的示例演示了这一点——当用户说"2 小时后提醒我检查部署"时,Agent 应当反问:"你希望这是 Apple Reminders(会同步到手机),还是 OpenClaw 告警(我直接在这里发消息给你)?"前者的答案走本技能,后者走cron工具。
Frontmatter 元数据:平台、依赖与安装规范
技能的全部"机器可读"信息都写在 SKILL.md 的 YAML frontmatter 中,这也是 OpenClaw 技能体系的核心约定:
--- name: apple-reminders description: "List, add, edit, complete, or delete Apple Reminders and reminder lists via remindctl." homepage: https://github.com/steipete/remindctl metadata: { "openclaw": { "emoji": "⏰", "os": ["darwin"], "requires": { "bins": ["remindctl"] }, "install": [ { "id": "brew", "kind": "brew", "formula": "steipete/tap/remindctl", "bins": ["remindctl"], "label": "Install remindctl via Homebrew", }, ], }, } ---各字段的含义:
| 字段 | 取值 | 作用 |
|---|---|---|
name | apple-reminders | 技能标识名 |
description | 一句话能力描述 | 供 Agent/用户理解技能用途 |
homepage | remindctl 项目主页 | 外部工具的出处(第三方 CLI 项目) |
metadata.openclaw.emoji | ⏰ | UI 展示用图标 |
metadata.openclaw.os | ["darwin"] | 仅在 macOS 上激活 |
metadata.openclaw.requires.bins | ["remindctl"] | 声明运行前提:PATH 中必须存在remindctl |
metadata.openclaw.install | brew 安装规范 | 声明缺失时的安装方式(Homebrew tap 公式steipete/tap/remindctl) |
源码佐证:frontmatter 的解析与校验
OpenClaw 对这段元数据的解析并非"信任即使用"。从源码结构看,frontmatter 解析入口 中的parseSkillFrontmatter()先用 markdown-core 的 frontmatter 解析器提取头部并严格报错(frontmatter 非法会直接抛出invalid frontmatter错误),随后resolveSkillManifestMetadata()负责解析metadata.openclaw块,抽取emoji、os、requires、install等字段。
对安装规范的处理尤其严格:parseInstallSpec()支持brew/node/go/uv/download五种安装类型,其中 brew 公式必须通过normalizeSafeBrewFormula()的安全校验——公式需匹配^[A-Za-z0-9][A-Za-z0-9@+._/-]*$,且不能以-开头、不能包含反斜杠或..路径穿越片段,校验不过的公式会被静默丢弃而非报错执行。steipete/tap/remindctl这类 tap 公式正是靠这个正则才被认为是安全的。此外kind: "brew"且缺少formula的规范会被整体判为无效返回undefined,保证进入运行时的安装规范始终完整可执行(见 frontmatter 解析实现)。
技能二进制依赖的汇总由 collectSkillBins 完成:它遍历一批技能条目,合并requires.bins、requires.anyBins与install[].bins三类声明,输出去重排序后的二进制名列表,供后续的 PATH 探测与环境准备使用。对 apple-reminders 而言,这条链路收集到的就是remindctl。
至于仓库内置的skills/目录本身如何被定位,bundled-dir 解析逻辑 给出了答案:优先读环境变量OPENCLAW_BUNDLED_SKILLS_DIR覆盖;否则对编译产物检查可执行文件同级skills/目录;否则以包根目录为基准解析<packageRoot>/skills,并用looksLikeSkillsDir()校验目录里确实存在SKILL.md才认定有效。仓库根目录下的 skills/apple-reminders/SKILL.md 就属于这条"包根目录 skills"路径所覆盖的内置技能。
仓库测试也印证了该技能元数据的完整性:onboard-skills 测试 断言了bins: ["remindctl"]与 brew 安装标签,执行审批配置测试 则把remindctl列入命令 allowlist 的示例,说明它被视为受审批管控的终端命令之一。
Setup:安装与授权
技能文档给出的安装步骤(适用于 macOS,因为 frontmatter 中os: ["darwin"]限定了平台):
brew install steipete/tap/remindctl # 安装 remindctl remindctl status # 检查状态 remindctl authorize # 请求访问权限关键点:
- macOS 专属:
remindctl依赖 Apple 的 Reminders 框架,只能在 macOS 上运行; - 系统授权:首次调用会触发 macOS 的 Reminders 隐私权限弹窗,需用户手动授予;
- 两步状态确认:
remindctl status用于确认二进制与数据源可用,remindctl authorize用于显式请求访问令牌/权限,两者都应在执行任何读写命令前完成。
常用命令全解
以下命令分组完整继承自技能文档,是 Agent 在会话中执行remindctl时的主要操作面。
查看提醒(按时间维度)
remindctl # 今天的提醒(默认) remindctl today # 今天 remindctl tomorrow # 明天 remindctl week # 本周 remindctl overdue # 已逾期 remindctl all # 全部提醒 remindctl 2026-01-04 # 指定日期管理提醒列表
remindctl list # 列出所有列表 remindctl list Work # 查看指定列表 remindctl list Projects --create # 创建列表 remindctl list Work --delete # 删除列表创建提醒
remindctl add "Buy milk" remindctl add --title "Call mom" --list Personal --due tomorrow remindctl add --title "Meeting prep" --due "2026-02-15 09:00"创建时可用--title指定标题、--list指定所属列表、--due指定截止日期,三者均可省略(省略时进入默认列表/无截止日)。
完成与删除
remindctl complete 1 2 3 # 按 ID 标记完成(支持批量) remindctl delete 4A83 --force # 按 ID 强制删除注意示例中 ID 既有纯数字(1 2 3)也有十六进制样式(4A83),说明remindctl输出的 ID 格式可能随提醒来源不同而变化,Agent 应先通过查询命令拿到 ID 再操作。
输出格式
remindctl today --json # JSON 输出,适合脚本/Agent 解析 remindctl today --plain # TSV 格式 remindctl today --quiet # 仅输出数量对 Agent 集成而言,--json是最有用的格式:结构化字段便于程序化处理;--quiet则适合只做计数判断(例如"今天还有没有待办")。
日期格式:--due与日期过滤器通用
remindctl的--due参数和日期过滤位置参数接受四种格式:
- 相对词:
today、tomorrow、yesterday; - 日期:
YYYY-MM-DD; - 日期 + 时间:
YYYY-MM-DD HH:mm; - ISO 8601:
2026-01-04T12:34:56Z。
这个设计兼顾了人类自然语言("明天")与机器时间戳(ISO 8601),Agent 在把用户的模糊表达("下周三上午十点")转换成命令前,需要先将其归一化为上述某种格式。
意图澄清:Apple Reminders 与 OpenClaw 定时提醒的边界
技能文档最后用一个对话示例固化了边界判断规则:
用户:"Remind me to check on the deploy in 2 hours"
Agent 应答:"Do you want this in Apple Reminders (syncs to your phone) or as an OpenClaw alert (I'll message you here)?"
判断依据只有一条:提醒最终该落在哪个世界。落到 iPhone/iPad 的 Reminders App、需要随 iCloud 同步的,用remindctl;留在 OpenClaw 会话内、由 Agent 到时发消息的,用cron工具的 systemEvent。两者能力相似,但存储位置、同步范围与提醒通道完全不同,混淆它们会让用户"在手机上看不到提醒"或"在聊天里收不到消息"。
小结与延伸阅读
- 技能本体(能力声明、边界、全部命令与日期格式):skills/apple-reminders/SKILL.md
- 技能元数据解析与安装规范校验:src/skills/loading/frontmatter.ts
- 内置 skills 目录的发现逻辑:src/skills/loading/bundled-dir.ts
- 技能二进制依赖汇总:src/skills/discovery/bins.ts
- 元数据完整性的测试佐证:src/commands/onboard-skills.test.ts、src/infra/exec-approvals-config.test.ts
apple-reminders 是 OpenClaw 技能体系的一个典型样本:一份带严格 frontmatter 约束的 Markdown 声明"这个技能需要什么二进制、在什么平台跑、缺失时怎么装",正文则以自然语言告诉 Agent 何时该用、何时不该用、以及每类操作的确切命令。技能本身不打包任何代码,全部能力来自外部工具remindctl——这种"声明式元数据 + 外部 CLI"的组合,也是仓库内其他 macOS 生态技能(如 Things、Apple Notes 等)共同采用的模式。
【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 🦞项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考