> ## Documentation Index
> Fetch the complete documentation index at: https://docs.newenergycoder.club/llms.txt
> Use this file to discover all available pages before exploring further.

# qclaw-cron-skill

> | [MANDATORY - MUST LOAD] 凡是涉及定时/提醒/闹钟/周期执行/打卡/签到/cron/schedule/remind 等需求，以及修改/编辑/更新/暂停/恢复/删除/取消推送/改推送目标/改推送渠道等已有定时任务的操作，必须读取本 skill，严禁凭记忆猜测参数。

| 项目 | 内容                                                                                                                                                                                                                                                                      |
| -- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 来源 | [skills/qclaw-cron-skill/SKILL.md](https://github.com/new-energy-coder-club/new_energy_coder_club/blob/Skill/skills/qclaw-cron-skill/SKILL.md)                                                                                                                          |
| 分类 | QClaw/OpenClaw 平台                                                                                                                                                                                                                                                       |
| 安装 | 克隆 [Skill 分支](https://github.com/new-energy-coder-club/new_energy_coder_club/tree/Skill) 后，将 `skills/qclaw-cron-skill/` 目录复制到 `~/.claude/skills/`（Claude Code）、`~/.trae/skills/`（Trae IDE）或 `~/.qclaw/skills/`（QClaw/OpenClaw），详见 [Skill 安装方式](/community/skill-branch) |

### cron — 定时任务

> 🚨 **\[MANDATORY]** 用户提到「提醒/定时/每天X点/X分钟后/周期/重复/打卡/签到」等时，**必须创建 cron 任务**，口头承诺无效。

#### 第一步：判断「推送目标」

> 🚨 **\[MANDATORY] 默认就在用户当前所处渠道提醒，禁止主动反问"推送到哪里"**。
> 用户说「提醒我 / 叫我 / 告诉我 / 让我」等**自指代**表达 → 推送目标 = **当前会话渠道**，不要追问。
> 仅当用户**显式**说"推到企微/飞书/微信群/告诉张三"等**他指代**时，才使用外部渠道。

| 当前会话 sender / channel                            | 推送目标           | mode                                                  |
| ------------------------------------------------ | -------------- | ----------------------------------------------------- |
| `openclaw-control-ui`（本地 UI / webchat）           | 本地（不投递，直接渲染回复） | **`none`**                                            |
| `wechat-access` / `dingtalk-connector`           | 当前外部渠道         | `announce`                                            |
| `wecom` / `feishu` / `openclaw-weixin` / `qqbot` | 当前外部渠道         | `announce`                                            |
| 本地 UI **+** 用户显式说"推送到 X"                         | 外部渠道 X         | `announce`（**必须**先读 `~/.qclaw/channel-defaults.json`） |

#### 第二步：判断创建方式

| 场景                                                                                | 方式                                                                |
| --------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| sender=`openclaw-control-ui`（本地） / channel=`wechat-access` / `dingtalk-connector` | **A：内置 `cron` 工具**, 不需要再读取channel-defaults.json（toolCall，JSON 参数） |
| channel=`wecom`/`feishu`/`openclaw-weixin`/`qqbot`                                | **B：`openclaw cron add` CLI**（通过 `exec`）                          |
| sender=`openclaw-control-ui` 但推送到外部渠道                                             | **B：CLI**（**必须**先读 `~/.qclaw/channel-defaults.json`）              |

> 外部渠道 session 中内置 `cron` 工具被 ownerOnly 策略过滤，LLM 不可见，必须走 CLI。dingtalk-connector可以使用内置`cron`工具。

**渠道识别**：显式 `channel` 字段 → 直接使用；无 `channel` 但 `message_id` 以 `openclaw-weixin:` / `wechat-access:` 开头 → 对应渠道。

> 🚨 **\[MANDATORY] 外部渠道 `to` 获取规则**：
> 当需要创建推送到外部渠道（wecom/feishu/openclaw-weixin/qqbot/dingtalk-connector/wechat-access）的定时任务时：
>
> 1. **当前会话有 `sender_id`** → 直接用作 `to`
> 2. **当前会话无 `sender_id`**（如本地 UI 创建推送到外部渠道）→ **必须先读 `~/.qclaw/channel-defaults.json`**，用当前 agentId + 目标 channel 查找 `to`
> 3. **channel-defaults.json 不存在 / 无对应渠道条目 / 无 `to` 值** → **严禁创建任务**，必须告知用户：「请先通过该渠道给机器人发送一条消息，系统会自动记录投递目标，之后再来创建定时任务」
>
> ⛔ **绝对禁止创建 delivery 中没有 `to` 字段的外部渠道定时任务**——这类任务会投递失败，浪费用户的期望。

#### 第三步：时间类型

* 具体时刻 / X分钟后 / 无周期词 → **一次性**（`deleteAfterRun:true` / `--delete-after-run`）
* 每天/每小时/每X分钟 → **周期任务**
* **绝对时间必须先 `date +%z` 获取时区**（`+0800`→`+08:00`），禁止硬编码

#### 第四步：时间参数速查

| 用户说法   | schedule（JSON）                                   | CLI 参数                          |
| ------ | ------------------------------------------------ | ------------------------------- |
| 每30分钟  | `{"kind":"every","everyMs":1800000}`             | `--every 30m`                   |
| 每2小时   | `{"kind":"every","everyMs":7200000}`             | `--every 2h`                    |
| 每天早上9点 | `{"kind":"cron","cron":"0 9 * * *"}`             | `--cron "0 9 * * *"`            |
| 每周一10点 | `{"kind":"cron","cron":"0 10 * * 1"}`            | `--cron "0 10 * * 1"`           |
| 工作日18点 | `{"kind":"cron","cron":"0 18 * * 1-5"}`          | `--cron "0 18 * * 1-5"`         |
| 今天下午3点 | `{"kind":"at","at":"2026-04-09T15:00:00+08:00"}` | `--at "..." --delete-after-run` |
| 10分钟后  | `{"kind":"at","at":"<now+10min ISO>"}`           | `--at "..." --delete-after-run` |

> cron 表达式：`分 时 日 月 星期`，0=周日，1-5=周一至五。

#### 公共规则（方式 A/B 通用）

> 🚨 **\[MANDATORY] message 行为约束**：`payload.message`（方式A）/ `--message`（方式B）末尾**必须**加：
> `要求：(1) 不要回复 HEARTBEAT_OK (2) 不要调用 message 工具 (3) 直接输出提醒文字 (4) 控制在 2-3 句话以内`

> 🚨 **\[MANDATORY] agentId 必传，禁止省略，禁止默认填 `"main"`**：
>
> * sessionKey `agent:【agentId】:session-xxx` → 取第二段
> * 无 sessionKey 但有 cwd `/path/workspace-agent-xxx` → 取最后一段去掉 `workspace-` 前缀（即 `agent-xxx`），禁止再去 `agent-`
> * 以上均无才传 `"main"`；从**当前对话**上下文提取，禁止复用历史

> 🚨 **\[MANDATORY] delivery 参数获取优先级**：
>
> 1. **优先从当前会话上下文** — `channel`、`sender_id`（→`to`）
> 2. **其次读 `~/.qclaw/channel-defaults.json`**（本地→外部渠道时）— 用当前 agentId + 目标 channel 查找
> 3. **无 `to` 则中止** — ⛔ **严禁创建没有 `to` 的外部渠道任务**，必须告知用户：「请先通过该渠道（如企微/飞书）给机器人发送一条消息，之后再来创建定时任务」
>
> 插件辅助处理：本地渠道/无 to 时自动注入 `bestEffort:true`（无须手写）；外部渠道自动写入 channel-defaults.json；**delivery 缺 `channel`/`to` 时插件从 sessionKey 自动补全（硬保底，仅 tool 路径）**。
> ⚠️ **插件保底 ≠ 可以不传 to**：插件的 sessionKey 补全仅适用于外部渠道 session 内（sessionKey 包含渠道信息），本地 UI 发起时 sessionKey 无渠道信息，补全不会生效；CLI 路径完全无 sessionKey 补全。

**🚨 \[MANDATORY] mode 必须显式传入**（插件不再自动推断 mode，按下表选择）：

| 场景                | mode         | 说明          |
| ----------------- | ------------ | ----------- |
| 推送到任何渠道（外部）       | `"announce"` | 创建/修改推送任务必传 |
| 不推送或本地渠道（仅本地静默执行） | `"none"`     | 取消推送时必传     |

> 💡 **mode 是必填项，不要省略**：
>
> * 想推送 → `mode:"announce"`，同时给 channel/to
> * 不想推送 → `mode:"none"`，同时**显式清空** channel/to（传空字符串）

**delivery 值速查（mode 必传）：**

| 场景                    | delivery                                                                    |
| --------------------- | --------------------------------------------------------------------------- |
| 本地                    | `{"mode":"none"}`                                                           |
| wechat-access         | `{"mode":"announce","channel":"wechat-access","to":"<sender_id>"}`          |
| wecom/feishu/dingtalk | `{"mode":"announce","channel":"<渠道>","to":"<sender_id>"}`                   |
| openclaw-weixin       | `{"mode":"announce","channel":"openclaw-weixin","to":"<openid>@im.wechat"}` |

#### 方式 A：内置 `cron` 工具模板

> 🚨 调用 toolName=`cron`，**不是** `exec`，参数为 JSON 对象。
> ⚠️ 模板中的 `delivery` 默认是**本地**场景（`mode:"none"`，对应 webchat/本地 UI 自指代提醒）。
> 推送到外部渠道时按上方"delivery 值速查"替换为 `{"mode":"announce","channel":"...","to":"..."}`。

**周期任务**：

```json theme={null}
{
  "action": "add",
  "job": {
    "name": "<任务名>", "agentId": "<agentId>",
    "schedule": {"kind":"every","everyMs":1800000},
    "sessionTarget": "isolated",
    "payload": {"kind":"agentTurn","message":"你是一个暖心的提醒助手。请用温暖、有趣的方式提醒用户：{内容}。要求：(1) 不要回复 HEARTBEAT_OK (2) 不要调用 message 工具 (3) 直接输出提醒文字 (4) 控制在 2-3 句话以内"},
    "delivery": {"mode":"none"}
  }
}
```

**一次性**：schedule→`{"kind":"at","at":"<ISO+时区>"}`，加 `"deleteAfterRun":true`

#### 方式 B：`openclaw cron add` CLI 模板

> ⚠️ 末尾的投递参数按场景选择：
>
> * 本地（webchat 自指代提醒） → `--no-deliver`
> * 外部渠道 → `--announce --channel <渠道> --to <sender_id>`

```bash theme={null}
openclaw cron add \
  --name "<任务名>" --every 30m --session isolated --agent <agentId> \
  --message "你是一个暖心的提醒助手。请用温暖、有趣的方式提醒用户：{内容}。要求：(1) 不要回复 HEARTBEAT_OK (2) 不要调用 message 工具 (3) 直接输出提醒文字 (4) 控制在 2-3 句话以内" \
  --announce --channel <渠道> --to <sender_id>
```

**一次性**：`--every 30m` → `--at "<ISO+时区>" --delete-after-run`

> 🚨 命令失败最多重试一次，仍失败直接告知用户。

#### 管理命令

> 暂停/停止 ≠ 删除。"暂停/禁用"→disable，"删除"→remove。

**内置工具**：列表 `{"action":"list"}` / 暂停 `{"action":"update","jobId":"<id>","patch":{"enabled":false}}` / 恢复 `…{"enabled":true}` / 删除 `{"action":"remove","jobId":"<id>"}` / 执行 `{"action":"run","jobId":"<id>"}`

**CLI**：`openclaw cron list` / `edit <id> --enabled false/true` / `remove <id>` / `run <id>`

#### 🚨 修改任务专用规则（仅适用于 update / cron edit）

修改任务的 delivery 配置有独特的语义陷阱，必须严格遵守以下规则。

**规则 1：patch 是增量覆盖，不是整体替换**

> 🚨 **\[MANDATORY]** `patch.delivery` 仅覆盖**显式传入的字段**。
>
> * `patch.delivery = {"mode":"announce"}` → **只改 mode**，原有的 channel/to 全部保留 ⚠️
> * 想清掉某字段必须**显式传空串**：`{"channel":"","to":""}` ✅
> * **不传 ≠ 清除！** 这是 LLM 最常踩的坑。

**规则 2：取消推送的唯一正确方式**

> ⛔ **"不再推送到 X" / "改回本地提醒" / "取消推送" 等用户表达，统一识别为「取消推送」意图**，不要误解为"切换到本地 announce"。
>
> * **tool 路径**：`patch.delivery = {"mode":"none","channel":"","to":""}`（mode 显式 none + 空串清掉 channel/to，三字段缺一不可）
> * **CLI 路径**：`openclaw cron edit <id> --no-deliver`（一键搞定，等价于上面整套清空）

**修改投递配置速查表**（mode 必须显式传）：

| 用户表达                          | 修改意图     | 内置工具（patch.delivery）                                 | CLI                                     |
| ----------------------------- | -------- | ---------------------------------------------------- | --------------------------------------- |
| "不再推送到微信" / "取消推送" / "改回本地提醒" | **取消推送** | `{"mode":"none","channel":"","to":""}`               | `--no-deliver`                          |
| "改成推送到飞书 / 企微"                | 改推送渠道    | `{"mode":"announce","channel":"<新渠道>","to":"<新to>"}` | `--announce --channel <新渠道> --to <新to>` |

#### 回复模板

一次性：`⏰ 好的，{时间}提醒你{内容}~` | 周期：`⏰ 收到，{周期}提醒你{内容}~` | 取消：`✅ 已取消"{名称}"`

> 外部渠道只输出确认话术，严禁输出推理过程。
