通过 CalDAV 读写 iCloud 日历事件
30.8/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/2 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add CaiMingshen/dsh-icloud-calendar该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · market
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 33 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意未发布到 npm registry,仅可从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包dsh-icloud-calendar(未发布到 npm,仅可源码安装)
✓Node 引擎要求 ^22.19.0 || >=24.0.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/16 14:08:10
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 10 处,展示前 9 条)
- 发起网络请求lib/client.js:180
const principalResponse = await this.request('PROPFIND', this.credentials.serverUrl, { - 发起网络请求lib/client.js:191
const homeResponse = await this.request('PROPFIND', principal, { - 发起网络请求lib/client.js:208
const response = await this.request('PROPFIND', home, { - 发起网络请求lib/client.js:313
const response = await this.request('REPORT', calendar.url, { - 发起网络请求lib/client.js:368
const response = await this.request('GET', url, { expect: [200], signal, context: 'Reading an event' }); - 发起网络请求lib/client.js:396
const response = await this.request('PUT', url, { - 执行外部命令来自配置/变量lib/credentials.js:52
const child = execFile(file, [...args], { - 写入本地文件lib/credentials.js:123
await mkdir(this.directory, { recursive: true, mode: 0o700 }); - 删除本地文件lib/credentials.js:143
await rm(this.fileFor(account));
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-tools@deepseek-ai/dsh-util-values@deepseek-ai/schemastery给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- CalDAV读写日历事件
- 跨平台凭据存储
- 删除前试运行确认
Apple iCloud 日历走 CalDAV 接入 DeepSeek Harness(DSH):五个工具、跨平台凭据存储、请求超时,以及删除前必须确认精确对象数量的试运行。
README
由 DeepSeek 最新模型翻译生成dsh-icloud-calendar auth set --account you@example.com
工具
插件向模型暴露 5 个工具:
| 工具 | 作用 |
| icloud_calendar_list | 列出所有日历(名称、URL、颜色、是否只读) |
| icloud_calendar_events | 按时间窗读取事件,自动展开重复日程 |
| icloud_calendar_create | 新建事件 |
| icloud_calendar_update | 修改事件 |
| icloud_calendar_delete | 删除事件(四道闸门,见下) |
删除的四道闸门
删除默认关闭,且即使打开也要连过四关:
1. allowDeletes: true —— 配置层开关
2. maxDeletesPerCall —— 单次调用删除数量上限,默认 1
3. 事件必须带 ETag —— 防止误删已被改动的条目
4. 模型必须显式传入 confirm: true —— 挡住自动补全式的误触
任何一关不过,删除都会被拒绝并说明原因。
展开完整文档(README 剩余 1 节)
dsh-icloud-calendar auth set --account you@example.com 工具 插件向模型暴露 5 个工具: | 工具 | 作用 | | icloud_calendar_list | 列出所有日历(名称、URL、颜色、是否只读) | | icloud_calendar_events | 按时间窗读取事件,自动展开重复日程 | | icloud_calendar_create | 新建事件 | | icloud_calendar_update | 修改事件 | | icloud_calendar_delete | 删除事件(四道闸门,见下) | 删除的四道闸门 删除默认关闭,且即使打开也要连过四关: 1. allowDeletes: true —— 配置层开关 2. maxDeletesPerCall —— 单次调用删除数量上限,默认 1 3. 事件必须带 ETag —— 防止误删已被改动的条目 4. 模型必须显式传入 confirm: true —— 挡住自动补全式的误触 任何一关不过,删除都会被拒绝并说明原因。 命令行 dsh-icloud-calendar status # 查看连接状态与日历数量 dsh-icloud-calendar status --probe # 主动探测 iCloud 连通性(首次使用建议先跑) dsh-icloud-calendar calendars # 列出日历 dsh-icloud-calendar auth set # 写入 App 专用密码到系统凭据存储 dsh-icloud-calendar auth clear # 清除已存的密码 开发 pnpm install pnpm build # tsc 编译到 lib/ pnpm test # 77 项测试 pnpm lint 测试覆盖 DAV 读取器、内存 CalDAV 假服务器,以及一套真实 cordis 挂载测试 —— 全部离线运行,不需要真实 iCloud 账号。 许可 MIT Windows:密码只经过 stdin,不进 argv、不进 shell 历史 $p = Read-Host 'App 专用密码' $p | node lib/cli.js login --account you@example.com macOS / Linux read -rs -p 'app-specific password: ' P && printf '%s' "$P" | node lib/cli.js login --account you@example.com 安全边界: - 密钥永不进入 profile 配置、工具参数、session log 或错误信息; - DPAPI 明文只交给 PowerShell 子进程的 stdin,磁盘上是 DPAPI 密文(%LOCALAPPDATA%\dsh-icloud-calendar,.gitignore 已排除 .dpapi.xml); - Linux 走 secret-tool 时密码走 stdin;macOS 钥匙串是唯一例外,security 只接受命令行参数,argv 会短暂可见(已在代码注释中标注); - 环境变量名刻意不叫 PASSWORD* 之外的花样(DSH_CALENDAR_PASSWORD 那类名字会被部分日志脱敏工具整行打码,反而破坏文件)——本插件用 ICLOUD_APP_PASSWORD,DPAPI 子进程内部用 DSH_ICLOUD_STORE_FILE。 工具(模型可见) | 工具 | 说明 | | calendar_status | 配置/凭据来源/连通性自检,不返回密码 | | calendar_list_calendars | 列出日历(名称、集合 URL、颜色、时区、组件类型);iCloud 提醒事项列表会标 supportsEvents=false | | calendar_list_events | 按时间窗读事件,重复日程展开为逐条,可取消的实例被跳过;返回 uid 供删除使用 | | calendar_create_event | 建事件;两个日期=全天事件(end 为排他),两个带偏移的时间戳=定时事件 | | calendar_delete_events | 删除,默认干跑,四道闸门见下 | 删除的四道闸门(针对"一次误删 8 条") 1. 总开关:allowDeletes: false 是默认值,不打开就没有任何删除路径; 2. 窗口必填:start / end 必填,且删除窗口上限(默认 90 天)比读窗口(366 天)更小; 3. 精确指名:只能给 uid(来自 calendar_list_events)或 summaryEquals(完整标题、区分大小写)——子串/模糊匹配一律拒绝; 4. 二次确认:默认 dryRun=true 只报告匹配结果;真删必须 dryRun=false 且 confirmCount 等于匹配到的对象数,同时受 maxDeletesPerCall(默认 1)封顶。 注意:命中重复日程时"对象数"小于"出现次数",删除会移除整个重复序列,结果里会明确写出这一点。 命令行(不走模型也能用) dsh-icloud-calendar status [--probe] [--json] dsh-icloud-calendar login --account you@example.com # 密码从 stdin 读 dsh-icloud-calendar logout --account you@example.com dsh-icloud-calendar calendars dsh-icloud-calendar events --start 2026-01-05T00:00:00+08:00 --end 2026-01-12T00:00:00+08:00 dsh-icloud-calendar add --summary "评审" --start 2026-01-05T09:00:00+08:00 --end 2026-01-05T10:00:00+08:00 --time-zone Asia/Shanghai dsh-icloud-calendar delete --start 2026-01-01T00:00:00+08:00 --end 2026-02-01T00:00:00+08:00 --uid <uid> dsh-icloud-calendar delete ... --uid <uid> --dry-run=false --yes CLI 复用同一套客户端与删除闸门;delete 永远先跑一次干跑,再要求 --yes,所以 --yes 单独出现不会删掉任何没人看过的东西。 踩坑清单(实测) | # | 坑 | 现象 | 处理 | | 1 | 用登录密码 | HTTP 401,看起来像服务器故障 | 只能 App 专用密码;错误码 CALENDAR_AUTH_FAILED 会直接说明 | | 2 | 每次调用新建连接 | 单次操作约 13 秒 | host 服务常驻复用连接;CLI 单进程内完成多步;读操作本身按日历串行以免被限流 | | 3 | DPAPI 走 PowerShell | 本机实测每次读写约 9 秒 | 只在建立连接时读一次密钥并缓存;不要把凭据读取放进每步 | | 4 | 删除慢 | 按日历全扫描,事件越多越慢 | 删除必须带日期窗口(默认 ≤90 天),不做全库扫描 | | 5 | 删除过杀 | 模糊匹配一次删掉 8 条 | 精确匹配 + 干跑 + confirmCount + 上限 1 | | 6 | 没有超时 | 网络卡住就干等 | 每请求 30s deadline,429/5xx 指数退避重试;401 不重试(避免锁号) | | 7 | 时区 | 全天事件差一天、无偏移时间戳含义不明 | 无 offset 的时间戳直接拒绝;全天事件按 iCalendar 的日期字段读取,不经过本地时区 | | 8 | 代理 | 国内直连 iCloud 可能不通 | proxyUrl(需要可选依赖 undici,未装时给出明确提示) | | 9 | 热重载预期 | 换了插件 JS 却没生效 | 新增 bundle 可经 HMR 生效,替换已安装包必须重启 | | 10 | 重复日程 | 以为删的是"这一次" | 删除作用于整个对象(整个序列),结果中明确提示 | | 11 | Reminders 列表 | 被当成日历读/写 | 若服务端公布了组件集合且不含 VEVENT,该集合会被跳过、显式指名则报错。但实测中国区 iCloud 的 19 个日历全部不公布组件集合,所以无法预判:对「提醒」集合查询一个月返回 0 条,代价只是多一次请求。写入该集合的行为未在本插件内验证 | | 12 | 多日历歧义 | 不知道写进哪个日历 | 只有唯一候选时才允许省略 calendar,否则报错并列出候选。实测账号里有两个都叫「家庭」的日历,裸用名字会被拒绝并要求给集合 URL | | 13 | 中国区账号的分区主机 | 以为要连 caldav.icloud.com | 入口仍填 https://caldav.icloud.com/ 即可;principal/calendar-home 发现会跟着服务端给出的分区主机走。实测真实账号的日历 URL 落在 p236-caldav.icloud.com.cn,19 个日历全部正常 | 架构 | 文件 | 职责 | | src/client.ts | CalDAV 客户端:principal/home 自动发现、calendar-query、PUT/GET/DELETE、超时与重试、可选代理 | | src/xml.ts | 面向 CalDAV 多状态响应的极小 XML 读取器(命名空间前缀无关) | | src/ical.ts | iCalendar 语义:时间戳校验、重复日程展开、事件构造与折行、全天事件边界 | | src/credentials.ts | 跨平台凭据存储(DPAPI / 钥匙串 / libsecret / 关闭) | | src/config.ts | schemastery 配置模式、默认值、凭据解析与来源说明 | | src/policy.ts | 删除闸门(唯一实现,服务与命令行共用) | | src/host.ts | cordis 服务 ctx.icloudCalendar:连接复用、缓存、策略 | | src/tools.ts | defineTool 注册 5 个模型可见工具 | | src/cli.ts | 独立命令行入口 | | tests/ | vitest:DAV 读取器(xml.test.ts,含「只返回第一个自闭合元素」这类回归)、内存 CalDAV 假服务器(401/503/超时)、iCalendar、删除闸门、凭据存储、以及用真实 cordis 上下文挂载两个插件行的激活测试 | 一个刻意的取舍:不手填日历集合 URL。插件走标准的 current-user-principal → calendar-home-set → 列日历 发现流程,所以换账号/换服务器只要改 account。 开发 pnpm install pnpm typecheck # src + tests pnpm test # 77 项:DAV 读取器 + mock CalDAV + 真实 cordis 挂载 pnpm build # tsc → lib/ 测试不需要 Apple ID、不需要网络:tests/mock-caldav.ts 是一个进程内 HTTP 服务器,实现了发现、REPORT、PUT、GET、DELETE,并可注入 401、连续 503、慢响应。tests/activation.test.ts 则用真实 @deepseek-ai/cordis 上下文把 host 行与 tools 行挂起来,断言服务注册、inject 满足、5 个工具入册、calendar_status 可执行、以及只读闸门生效。 启动验证(以及为什么「没报错」能算证据) 除单测外,还做了两层真机验证: 1. 组合层:dsh plugin --profile <probe> add <本包> 后 dsh --profile <probe> --dump-config,能看到 # == dsh-icloud-calendar 层与两行; 2. 启动层:从官方 headless 模板建一个临时 profile 装上本包并真实启动,进程 2.2 秒内走到 LLM 阶段、只因缺少 LLM 凭据退出(MISSING_CREDENTIAL),没有任何插件行报错。 第 2 条之所以有说服力,是因为做了反证实验:把 cordis.patch.yml 里的模块名改成不存在的路径后,启动会直接卡在组合阶段(600 秒不退出),而不是静默继续。也就是说「启动能走到 LLM 阶段」确实等价于「两行插件成功激活」,而不是「错误被吞了」。 3. 端到端:把测试用的 CalDAV 服务编译成独立进程跑在真实 HTTP 端口上,再用构建产物 lib/ 里的命令行走完整流程(结果见下表)。这条路径覆盖了真实的 HTTP 层、iCalendar 构造、策略闸门与退出码,而不只是单测内的函数调用。 | 命令 | 结果 | | status --probe | 配置/凭据来源/连接全部正常,退出码 0 | | calendars | 5 个日历:Reminders 标 EVENTS=no、Shared 标 READ-ONLY=yes、Mixed(VTODO+VEVENT)标 EVENTS=yes | | events | 5 条出现:1 条单次 + 4 条 weekly 展开(RRULE 在窗口内正确展开) | | add(09:00+08:00) | 建成 2026-01-06T01:00:00Z,时区正确折算 | | delete(未加 --dry-run=false) | DRY RUN — 1 object(s),什么都没删 | | delete(--dry-run=false 但没 --yes) | 拒绝:CALENDAR_UNSAFE_DELETE: Refusing to delete 1 object(s) without --yes | | delete --summary-equals=E2E(部分标题) | 匹配 0 条 —— 模糊匹配确实不存在 | | delete --summary-equals=E2E review --dry-run=false --yes | DELETED — 1 object(s) | | 删除后再 events | 新建的那条消失,原有 5 条出现完好 | | 退出码契约 | 成功 0 / 闸门或配置问题 1 / 未知命令 2 / help 0 | 已知限制 / 路线图 - 没有设置页表单(配置项未标 .volatile()),改配置需编辑 profile 并重载; - 暂不支持更新事件(calendar_update_event)与多账号同时挂载(可用多个 profile 行 + 不同 account 变通); - 重复日程的 RRULE 展开在客户端完成,单序列上限 maxOccurrencesPerSeries(默认 400),命中上限会在结果里报告; - 未做真实 iCloud 账号的端到端验收(见文首状态说明)。 许可证与致谢 MIT。 设计与实现参考了同一生态里的两个开源项目(代码为独立实现,未复制): - moziforge/calendar-plugins(Apache-2.0)—— iCloud CalDAV 的凭据与错误码处理思路; - STARDUSTLC666/dsh-calendar(MIT)—— DSH 插件形态与多日历解析实践。 插件形态遵循官方 cordis-plugin-development skill 与 docs/user/develop/basic/publish.md。
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
CaiMingshen/dsh-icloud-calendar
通过 CalDAV 读写 iCloud 日历事件
相关插件 · 市场 / 管理
插件精选列表awesome-dsh-plugin/awesome-dsh-plugin
DeepSeek Harness(dsh)插件精选列表
★ 22,225未汉化DSH
73.6
新词雷达zhuyansen/new-term-radar
new-term-radar新词雷达
★ 2,049已汉化MCP
72.8
插件生态导航0xsline/awesome-deepseek-harness
安装 贡献指南 DeepSeek Docs 公开插件目录 Issues
★ 1,188已汉化DSH
72.6
技能注册中心iflytek/skillhub
企业级开源智能体技能注册中心——发布、发现并管理组织内可复用的技能包。
★ 5,370已汉化DSH
71.9
插件市场目录imsai-sh/awesome-deepseek-harness-plugins
面向 DeepSeek Harnessdsh生态的社区插件目录,共收录 13941 个插件含 PR 收录与…
★ 355已汉化DSH
71.8
插件精选清单Anil-matcha/awesome-dsh-plugin
DeepSeek Harnessdsh精选指南——DeepSeek…
★ 1,013已汉化DSH
71.7
这是你的仓库?认领条目