Skip to content
Back to skills

Daily Report

ASecurity

產生 Claude Code 工作日報並經核可後寄 Gmail 給設定檔指定的收件人。掃描本機所有專案的當日 session 記錄,按專案分組摘要「做了什麼+待辦/未完成」,使用者過目核可後透過 Gmail SMTP 寄出。當使用者說「日報」、「產今天的日報」、「工作日報」、「今天做了什麼整理一下寄出去」、「昨天的日報補寄」、「daily report」時觸發。

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
ai-agentspythongonodegitapi

Works with

  • claude code
  • cli
  • api
  • mcp

Security analysis

A100/100

Pro scans all 11 files and shows the line behind each finding

Scanned October 5, 2026

npx -y skills add abs1294/fulin-claude-plugins --skill daily-report --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Daily Report?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Daily Report
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/abs1294-daily-report/badge)](https://www.skillsdirectory.com/skills/abs1294-daily-report)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: daily-report
description: 產生 Claude Code 工作日報並經核可後寄 Gmail 給設定檔指定的收件人。掃描本機所有專案的當日 session 記錄,按專案分組摘要「做了什麼+待辦/未完成」,使用者過目核可後透過 Gmail SMTP 寄出。當使用者說「日報」、「產今天的日報」、「工作日報」、「今天做了什麼整理一下寄出去」、「昨天的日報補寄」、「daily report」時觸發。
---

# daily-report — 工作日報產生與 Gmail 寄送

把一整天散在各專案的 Claude Code 對話,濃縮成一封收件人(主管/客戶)看得懂的工作日報。
資料來源是本機 `~/.claude/projects/` 的 session jsonl;寄送走 Gmail SMTP(應用程式密碼)。

## 核心原則

1. **寄信是對外動作,預設要人工核可**:報告在寄出前必須完整呈現給使用者。能不能「沒回應就自動寄」只看設定檔的一個開關 `require_approval`:
   - `true`(預設;沒寫、寫錯、讀不到設定檔都算這個)→ 每封都要使用者親口說「寄」才寄,沒有默許窗口。剛開始用請維持這樣。
   - `false`(使用者覺得運作順利後自己改)→ 才有「確認窗口到期沒人喊停就自動寄」。
   這個開關由寄送腳本強制:`require_approval` 不是 `false` 時,帶 `--auto` 的寄送一律被拒,不靠記得。
2. **收件人視角**:日報是給別人看的。寫「完成了什麼、產出是什麼」,不寫內部術語、不寫 prompt 原文、不寫統計數據(統計只在對話裡給使用者自己看)。
3. **機密不落 git**:SMTP 憑證只存 `~/.claude/daily-report/config.json`(家目錄)。

## 執行步驟

### 1. 定日期

預設今天;「昨天的日報」= 昨天;也可指定 `YYYY-MM-DD`。時區預設台北(+08:00)。

### 2. 萃取當日 session

```
python "${CLAUDE_PLUGIN_ROOT}/skills/daily-report/scripts/extract_sessions.py" --date <YYYY-MM-DD>
```

**預設只掃目前專案**(當前工作目錄及其子目錄的 session),不是全機器。這是刻意的:plugin 多裝在 project scope,「這個專案的日報」才是預期行為,掃全機器會把別的客戶/專案混進同一封信。要跨專案總覽時才加 `--all-projects`;要指定他處用 `--project <路徑>`。

- stdout 唯一輸出=中間檔路徑(`~/.claude/daily-report/out/<date>-<專案>.json`),直接 Read 它。
- exit 3 = 該日無記錄 → 告知使用者,不硬產空報告。
- 腳本已自動濾掉:subagent 對話、SDK/程式驅動 session、系統注入訊息、指令回顯。留下的都是「人打的 prompt」與 session 標題(ai-title)。
- 要連自動化 session 一起看時加 `--include-auto`(罕用)。

### 3. 生成日報

讀中間檔,寫日報 markdown 到 `~/.claude/daily-report/reports/<date>.md`。固定結構:

```markdown
# YYYY-MM-DD 工作日報

## <專案名(口語化,非路徑)>
- 完成/推進了什麼(1~4 條,說結果不說過程)

## 待辦與未完成
- 從對話中萃取的未收尾事項(沒有就寫「無」)
```

寫作要點:

- **專案名口語化**:`C:\...\winbond-vendor-platform` → 「Winbond 供應商平台」。相鄰子目錄的 session(如 `customer-hub` 與 `customer-hub\web`)併成同一個專案講。
- **從 title + prompts 歸納敘事**,不逐條翻譯 prompt。session 標題(Claude 自動生成)通常就是最好的主題句起點。
- **待辦線索**:對話尾段的「之後再」、「明天」、被中斷的工作、使用者說要做但當天沒做完的事。
- **私人 session 要過濾**:掃出來的 session 可能含私人事務(非工作專案)。判斷明顯私人的(如個人研究、家庭事務)**預設不寫進報告**,並在對話中告知使用者「已略過 N 個疑似私人 session(列標題)」,讓使用者可要求加回。

**表格**:內容本來就是表格的(工時、明細、逐項數據)直接寫 markdown 表格,`md_to_html()` 會轉成帶框線的 HTML `<table>`(1px 灰框、`#f4f4f4` 表頭底、Arial 13px;樣式硬寫不可調)。

```markdown
| Week | Start Date | End Date | Hours | Description |
|:-:|:-:|:-:|:-:|:-:|
| 2 | 07/09/2026 | 13/09/2026 | 9.0 | 供應商平台簽核流程 |
|  |  | Total hours | 9.0 |  |
```

- **對齊列(`|:-:|:-:|`)會被自動丟棄**,不會渲染成資料列。
- **合計列就寫成普通一列**(前幾格留空、寫 `Total hours` 與數字),轉換器不做特殊處理。
- 表格是「敘述放不下才用」的工具——一般日報的專案進度仍用條列,不要為了表格而表格。

### 4. 內容硬閘與易讀性閘(寄送腳本自動跑)

**日報是對外文件,不得出現任何 AI / 工具鏈痕跡**(AI、Claude、plugin、prompt、agent、token、紅藍對抗、自動彙整…),也要讀得懂(編號連續、沒有未定義代號、沒有「本次查核」這類異動紀錄用語)。兩道閘都寫在寄送腳本的共用前置流程裡(`send_common.prepare_send`):

- `content_guard.py`:AI/工具鏈字眼、憑證、個資。**不可豁免(公文式敬稱組除外,見下)**。
- `check-before/scripts/check_doc.js`:易讀性,與 Stop hook 同一套判準。硬缺陷擋寄送,提醒照印。

**Gmail API(A)與 SMTP(B)兩條路徑不用手動跑**——第 5 步呈現前跑的 `--dry-run` 就會經過這兩道閘,沒過就拿不到預覽;實寄時會再跑一次。

**MCP 建草稿(C)也不用手動跑**:這條路徑直接呼叫 Gmail 工具、不經寄送腳本,所以由 PreToolUse hook `hooks/daily-draft-gate.js` 在建立/更新草稿**之前**把關——主旨含「工作日報」的草稿,內文會先跑同樣兩支(`content_guard.py`、`check_doc.js`),任一不過就拒絕建立草稿並附上命中清單。想在建草稿前先看結果,可手動跑:

```
python "${CLAUDE_PLUGIN_ROOT}/skills/daily-report/scripts/content_guard.py" <報告.md> [--project <目錄>]
node "${CLAUDE_PLUGIN_ROOT}/skills/check-before/scripts/check_doc.js" <報告.md>
```

> **例外:公文式敬稱(易讀性鐵則 14)只提醒、不擋寄送**。「貴司/貴中心/本中心」這類敬稱命中時會印 `⚠ 提醒(不擋寄送)`,exit code 仍為 0——因為中文沒有詞邊界,「貴司機」「成本中心」「本司法」都會誤命中,擋下去會訓練使用者忽略警告。看到提醒請自己判斷:是敬稱就改「您們」,是正常詞就忽略。

命中時照它印的改寫原則重寫——**站在收件人角度寫「做了什麼、產出是什麼」,不寫用什麼工具做的**:

- ✗ 調整 AI 工作流程,讓 AI 遇到問題即時詢問 → ✓ 調整開發流程:遇到需求疑義即時確認,減少返工
- ✗ 新增 daily-report plugin,經紅藍對抗審查 → ✓ 新增工作記錄彙整工具,完成設計審查

若輸出含 **`⚠ 需要對外別名`**(專案名本身含禁用詞,改寫解決不了),問使用者「這個專案對外要怎麼稱呼?」,然後登記:

```
python content_guard.py --set-alias "<原名>" "<對外別名>" [--project <目錄>]
```

登記後永久生效,**同一個專案只會問一次**——別讓使用者每天重答。

### 5. 呈現與核可(先問開關:要人工說「寄」,還是允許默許窗口)

**先查開關,不要自己讀設定檔判斷**(跟第 6 步用 `setup_gate.py` 同一個道理——腳本每次都查同樣的條件):

```
python "${CLAUDE_PLUGIN_ROOT}/skills/daily-report/scripts/confirm_gate.py" policy [--project <目錄>]
```

- **exit 14(印 `[approval-required]`)** → 走 **5A 需人工核可**。開關是 `true`、沒寫、寫錯、讀不到設定檔,全都落在這裡。
- **exit 0(印 `[auto-allowed]`)** → 走 **5B 允許自動寄**(使用者已把 `require_approval` 改成 `false`)。

開關的位置與意思:`require_approval` 寫在專案 `<專案>/.claude/daily-report.json` 或家目錄 `~/.claude/daily-report/config.json` 的最外層(專案那份優先,兩邊都沒寫=`true`)。手動叫日報、定時觸發都看同一個開關,沒有第二個。

**呈現內容**(5A、5B 都一樣)——四塊,缺一不可:

1. **寄送資訊**:收件人、副本、寄件者、主旨;5B 另加「預計自動寄發時間」。使用者要在知道「這封會寄給誰」的前提下決定,不能只看內文。(這些**不放進郵件內文**——收件人從 header 就看得到,內文重複是冗餘。)

   ⚠ **每一項都顯示「真正會寄出的值」,不是佔位符或示意**。主旨尤其要注意:直接跑 `send_gmail.py --dry-run`(或 `gmail_oauth.py send --dry-run`)拿它印出的實際主旨,那已經是 `<前綴> <日期> 工作日報` 代換好的完整字串——**不要自己打「(日報前綴)」這種佔位文字給使用者看**。使用者看到的預覽必須等於實際會寄的內容,否則「呈現核可」形同虛設。dry-run 的輸出本身就是最可靠的預覽來源,直接用它。
2. **日報全文**(將寄出的內容,一字不差)。
3. **本機統計**(只顯示不寄出):專案數、session 數、活躍時段、工具呼叫 top 5。
4. **下一步怎麼走**:5A 寫「你說『寄』我才寄出,要改內容或不寄也直接說」;5B 寫「N 分鐘內沒有回覆或修改,我就用這個版本自動寄出」。

#### 5A. 需人工核可(`require_approval` 為 `true`,預設)

呈現完就**停下來等使用者回覆**。這條路**不 arm 自動寄、不排喚醒、不帶 `--auto`**——就算排了,寄送腳本也會以 `approval-required` 拒寄。

| 回應 | 動作 |
|---|---|
| 說「寄」 | 照第 6 步寄出,**不帶 `--auto`** |
| 改內容 | 更新報告 → 重跑 `--dry-run`(兩道閘隨之重跑)→ 重新呈現,繼續等 |
| 不寄 | 不寄,結束 |

想之後改成自動寄,告訴使用者:在專案的 `.claude/daily-report.json`(或家目錄 `config.json`)最外層把 `"require_approval"` 改成 `false`。**這個值只由使用者自己改**,不要主動改、也不要每次都問要不要改。

#### 5B. 允許自動寄(`require_approval` 為 `false`)

呈現後**立刻 arm(同一輪,不可延後)**:

```
python "${CLAUDE_PLUGIN_ROOT}/skills/daily-report/scripts/confirm_gate.py" arm <date> \
  --report <報告.md> --recipients <收件人> [--cc <副本>] [--project <目錄>]
```

窗口分鐘數讀 config 的 `confirm_wait_minutes`(預設 30)。arm 會記下報告內容指紋與到期時間——**之後的自動寄送必須通過 `check` 才放行**,這是機械閘,不是靠記得。

**接著同一輪排喚醒源**(arm 的輸出也會提醒):

- `ScheduleWakeup({ delaySeconds: <分鐘數×60>, reason: "日報確認窗口", prompt: "<重述:回到 daily-report 寄送步驟>" })`
- 無 ScheduleWakeup 時用 `CronCreate({ recurring:false, cron:<現在+N分> })`,記下 job id。(**不要傳 `durable`**——工具契約明寫該參數無效、所有 job 都只活在本 session。)

> ⚠ **不排喚醒 = 空頭承諾**:這一輪結束後控制權交還使用者,沒有計時器就沒有任何東西會觸發寄送。`confirm_gate check` 在逾期超過 1 小時時會回報 warning,那就是「當初漏排」的證據。

**使用者在窗口內回應時**:

| 回應 | 動作 |
|---|---|
| 改內容 | 更新報告 → 重跑 `--dry-run`(兩道閘隨之重跑;MCP 草稿路徑在重建草稿時由 hook 自動重跑)→ **`confirm_gate clear <date>`** → 重新呈現並 arm(窗口重新計時) |
| 喊停 | **`confirm_gate veto <date> --reason "..."`** → `CronDelete <id>` → 不寄 |
| 說「寄」 | 直接寄,**不帶 `--auto`**(這是他的意思表示,不必等窗口) |

**喚醒觸發時**:寄送指令**必須帶 `--auto`**,腳本會強制查 `confirm_gate check`——開關不是 `false`(approval-required)/ not-armed / still-waiting / vetoed / 內容被改過,任一情況都拒寄。

### 6. 交付(先跑閘,由腳本告訴你走哪條)

**不要自己讀 config 判斷,也不要問使用者「你想用哪種」**——跑這行,退出碼就是答案:

```
python "${CLAUDE_PLUGIN_ROOT}/skills/daily-report/scripts/setup_gate.py" status
```

- **exit 0(印 `SETUP_OK`)** → 輸出會寫明管道,照下面 A/B/C 對應執行。
- **exit 10(印 `SETUP_REQUIRED`)** → 設定未完成,**跳到「首次設定引導」**。此時不得自行猜測管道、不得直接寄送。

之所以用腳本判斷而非讀檔自行推論:判斷條件有四種未完成情境(檔案不存在、JSON 壞、有管道但無收件人、有檔但無管道),逐條記在腦中容易漏,腳本每次都查同樣的四條。

**A. Gmail API(OAuth)**
```
python "${CLAUDE_PLUGIN_ROOT}/skills/daily-report/scripts/gmail_oauth.py" send --report ~/.claude/daily-report/reports/<date>.md --date <date> --dry-run
```
先 `--dry-run` 給使用者看實際收件人與主旨,明確確認後拿掉 `--dry-run` 實寄。exit 2 含 `invalid_grant` → 授權失效(撤銷/改密碼/測試模式 7 天過期),重跑 `setup` 即可。

**B. SMTP 直寄**
```
python "${CLAUDE_PLUGIN_ROOT}/skills/daily-report/scripts/send_gmail.py" --report ~/.claude/daily-report/reports/<date>.md --date <date> --dry-run
```
同樣先 dry-run 再實寄。臨時改收件人用 `--to a@x,b@y`(會連 config 的 cc 一併清空,避免自我測試誤寄主管)。

**C. MCP 建草稿**(session 有 `mcp__claude_ai_Gmail__create_draft`;工具未載入先 ToolSearch)
`create_draft`:`to`/`cc` 讀 config、`subject`=`<subject_prefix> <date> 工作日報`、`body`=markdown 原文、`htmlBody`=`send_gmail.py` 的 `md_to_html()` 轉換結果。完成後告知「草稿已在你的 Gmail 草稿匣,過目後自己按送出」——**按送出即人工核可**,本 skill 不代按。

## 定時觸發(`schedule` 區塊,自續鏈)

設定檔的 `schedule` 區塊讓日報定時自動產生,用 **Claude Code 內建的 `CronCreate`**。

**架構是自續鏈,不是循環排程**:寄成功 → 立刻排下一次(一次性 job)→ 到點觸發 → 產稿 → 核可 → 寄出 → 再排下一次。**任何時刻只有一個 job 活著。**

為什麼不用 `recurring: true`:

| | `recurring:true` | 自續鏈 |
|---|---|---|
| 重複排導致爆量 | 靠 Claude 記得先 `CronList` 查重——**自律,會被繞過** | 結構上不可能:只在「寄成功」這單一時點排,一次一個 |
| 7 天自動過期 | 過期就斷,要有人記得重排 | 不受限——該限制只適用 `recurring:true` |
| 斷鏈 | 這次沒觸發,下次還會來 | **一次失敗就終止**(所以需要下面的候補檢查) |

> ⚠ **這是 session 級排程,不是系統排程**。工具契約原文:`Jobs live only in this Claude session — nothing is written to disk, and the job is gone when Claude exits`。**關掉 Claude Code 排程就消失**。要無人值守請另外用系統排程器(Windows 工作排程器 / crontab),那不在本 skill 範圍。

### 一、寄出成功之後,排下一次(鏈就是這樣接起來的)

`schedule.enabled` 為 `true` 時,**寄成功的同一輪**就要接上鏈:

```
python "${CLAUDE_PLUGIN_ROOT}/skills/daily-report/scripts/schedule_gate.py" next --project <目錄>
```

輸出會給下一次的時間與可直接用的 cron 欄位,照它排:

```
CronCreate({
  cron: "<next 輸出的 cron 欄位>",
  recurring: false,
  prompt: "產生今天的工作日報:依 daily-report skill 的執行步驟,萃取 session、生成日報、跑內容硬閘,然後呈現給我並進確認窗口。"
})
```

三件要注意的:

1. **`recurring: false`**——自續鏈每次只排一個一次性 job。排成 `true` 會同時有循環與自續兩套,重複觸發。
2. **prompt 寫自然語言,不要寫 slash command**——排程送出的 prompt 裡 slash 是純文字、不會被解析(Claude Code 2.1.196 起的行為)。
3. **不要傳 `durable`**——工具契約明寫該參數無效。

`enabled: false` 或無 `schedule` 區塊 → 不排,也**不要主動問要不要排**(沒設就是不要)。

### 二、忘了接鏈或鏈斷過,Stop hook 會講(他律,不靠你記得)

上面那句「寄成功的同一輪就要接上鏈」寫在這裡是**自律**——會被漏掉,而鏈一旦斷了就是靜默地永遠斷著。所以真正的保證在 `hooks/daily-report-chain-gate.js`(Stop hook,講完話就觸發):

| 情況 | hook 的反應 |
|---|---|
| 本回合寄出成功,但沒呼叫 `CronCreate` | **硬擋**(`decision:block`)並告訴你怎麼補——鏈斷在這裡最可惜,當下補排只要一步 |
| 過去有該寄而沒寄的日期 | **只警告**,列出缺口日期;補不補是使用者的選擇,不卡住結束對話 |
| 這輪沒碰 daily-report/`enabled:false`/任何判斷不確定 | 靜默放行 |

兩種提醒的節奏不同(使用者明定),這是刻意分開的:

| | 忘了接鏈 | 過去的缺口 |
|---|---|---|
| 頻率 | **每個日報週期一次**——有新的寄送就會再提醒 | **永久只問一次** |
| 為什麼 | 「這次寄完有沒有接鏈」每次都該問 | 你說過不補的日子,不該在下次寄信後又被翻出來 |
| 怎麼記 | 內部狀態記下上次提醒時的寄送快照 | 寫進設定檔的 `schedule.acknowledged_gaps` |

缺口的結案時機是**提醒的下一輪**——那一輪就代表使用者已經回應過了(不管回補、不補、還是沒理),整批日期寫進設定檔永不再問。「問完的下一則就是記錄點」是機械可偵測的時機,不必靠 Claude 記得去登記(那會被漏掉)。

`acknowledged_gaps` 刻意放**設定檔**而不是內部狀態:使用者看得到,想恢復提醒就自己把日期刪掉。實際補寄的日子不會留在清單裡(補了就有寄送紀錄,本來就不算缺口);超出 `lookback_days` 的舊項目自動裁掉。

還有一條不變的原則:**FAIL-OPEN**——讀檔失敗、解析例外、判斷不確定一律放行。這 hook 影響 session 能不能結束,寧可漏擋絕不卡死。

缺口判定由 `scripts/schedule_gate.py` 提供(`check` 列缺口、`next` 算下次時間)。它**不依賴 cron 有沒有觸發**,只比對 `sent/` 目錄裡事實上哪幾天沒有寄出紀錄,所以四種斷鏈成因都抓得到:使用者 veto、內容閘擋下、cron 到點時 REPL 不是 idle、Claude Code 被關掉。回溯天數讀 `schedule.lookback_days`(預設 30)。

### 三、觸發之後做什麼——跟手動叫日報完全一樣

定時觸發只是「誰按下開始」不同,之後照執行步驟 1~6 走,**寄不寄由第 5 步的同一個開關 `require_approval` 決定**(`confirm_gate.py policy` 查),這裡沒有另一套規則:

- 開關需人工核可(預設)→ 走 5A:呈現完停下來等使用者說「寄」。使用者當天沒回,這天就不寄,之後由下面的缺口檢查提醒。
- 開關允許自動寄 → 走 5B:呈現、arm、排喚醒,窗口到期沒人喊停就帶 `--auto` 寄出。

`schedule` 區塊裡舊版的 `require_approval` 仍會被讀到(最外層沒寫時),但它跟最外層是**同一個開關**,不是只管排程的第二個開關;新設定請寫在最外層。

> **鏈斷在哪都不會靜默**:`confirm_gate` 管「arm 之後沒寄」,`schedule_gate check` 管「根本沒觸發所以沒 arm」。兩者合起來,才補上 `confirm_gate.py` docstring 裡明文承認的缺口——「模型有沒有真的去排喚醒無法由腳本強制」。

## 首次設定引導(`status` 回 exit 10 時走這裡)

這一節的選項說明與步驟**全部由腳本產生**,你的工作是搬運與陪跑,不是自己組織內容。這麼設計的原因:使用者是在「這個選擇給出多少權限」的資訊下做決定的,而那正是長對話中最容易被壓縮掉的部分——交給腳本輸出,內容就不隨當下狀態浮動。

**步驟 1|取得選項並原文呈現**

```
python "${CLAUDE_PLUGIN_ROOT}/skills/daily-report/scripts/setup_gate.py" options
```

輸出是 JSON,含 `question` / `header` / 三個 `options`(各有 `label` 與 `description`)。用 **AskUserQuestion** 呈現:`label` 照抄、`description` 照抄。

`description` 內含權限、有效期、設定成本、代價四欄——**這四欄不可摘要、不可省略**。使用者選「應用程式密碼」前必須看見「等同整個信箱完整存取權、永不過期」,否則他不是在做選擇,是在賭。輸出的 `instruction` 欄位也寫著同一件事,照做即可。

**步驟 2|取得該管道的逐步引導**

```
python "${CLAUDE_PLUGIN_ROOT}/skills/daily-report/scripts/setup_gate.py" guide <oauth|app_password|mcp_draft>
```

輸出是編號步驟,每步含 `do`(做什麼)與 `確認`(怎麼知道成功了)。**一次講一步,等使用者回報再講下一步**;他卡住就根據他描述的畫面對照該步的「確認」給提示。指令裡的 `<PLUGIN>` 替換成實際路徑再給他。

過程中的兩條紅線:

- **OAuth 的 client_id / client_secret 可以直接請使用者貼給你**,當參數餵給 `gmail_oauth.py setup`(腳本自己寫進他家目錄)。桌面應用程式(Desktop app)類型的 client_secret **按 Google 設計就不是機密**——它必須隨程式散佈到每台使用者電腦,本來就藏不住,Google 文件明說桌面 app 的 secret 不當機密看待。所以不必遮遮掩掩、不必叫使用者改用別的方式輸入,那只會讓人以為卡關而浪費時間。(**app password 不同**:那是真憑證=整個信箱權限,請使用者自己編輯設定檔那一格,不要貼進對話。)
- **`config.example.json` 是隨 plugin 發布的空範本,永遠不要把真值寫進去**。真設定檔的位置是 `~/.claude/daily-report/config.json`。(真寫進去也會被 git-commit 的憑證閘擋下,但別依賴那道補救。)

⚠ **不要把「使用者說做完了」當成做完了**。實戰教訓:本 skill 的作者自己照這份引導跑,仍漏掉「啟用 Gmail API」那步,直到寄信被 403 才發現——每步的「確認」都靠人眼判斷加口頭回報,中間兩層都會失真。**每個宣稱完成的步驟後跑一次 `gmail_oauth.py doctor`**(見步驟 3),它實際打 API 驗,不接受自我回報。

⚠ **Console 的畫面與網址以 Google 當下回傳的訊息為準,不以引導文字為準。** 引導裡的路徑會隨 Google 改版過時,而 doctor 輸出的錯誤與連結是 Google 即時給的。兩者衝突時信 doctor。

### 依專案分設收件人

同一台機器上不同專案要寄給不同人時(Winbond 的日報不該寄給 AI Platform 的窗口),在**該專案**建 `.claude/daily-report.json`:

```json
{ "recipients": ["主管@example.com"], "cc": ["pm@example.com"], "subject_prefix": "[Winbond 日報]" }
```

解析規則:**專案層只能覆寫「寄給誰」**(`recipients` / `cc` / `subject_prefix` / `from_name`),憑證一律只從家目錄那份讀。這樣一組授權可以服務多個專案,而憑證不會因為放在專案目錄裡被 git 帶走。所有腳本都吃 `--project <路徑>`,省略即用目前工作目錄。

**步驟 3|驗收(用 doctor,不用問使用者)**

OAuth 管道跑 `gmail_oauth.py doctor`——五項全綠才算完成。常見的未通過與處置:

| doctor 輸出 | 意思 | 處置 |
|---|---|---|
| `尚未啟用 Gmail API`(附連結) | 專案沒開 API | 開它給的**那個連結**按啟用(別用文件裡的路徑,Google 給的才是對的) |
| `invalid_grant` | 授權已失效 | 重跑 `setup` |
| `授權範圍不含 gmail.send` | scope 不對 | 重跑 `setup` 重新授權 |
| `收件人未設定` | 缺 recipients | 問使用者收件人並寫進 config |

其他管道(app password / MCP 草稿)跑 `setup_gate.py status`,看到 `SETUP_OK` 才算完成。

驗收通過後回到第 5 步交付。**寄送若仍失敗,先跑 doctor 再猜原因**——它會直接指出是哪一環。

## 界線(誠實告知)

- 日報品質取決於 session 記錄的可讀性;純瀏覽器操作、外部會議等 Claude Code 之外的工作不會出現,提醒使用者可口頭補充後由 Claude 補進報告。
- **排程只到 session 級**:`schedule` 區塊用 Claude Code 內建 CronCreate 走自續鏈(寄成功排下一次,見「定時觸發」章),**關掉 Claude Code 就失效**。斷鏈由 `schedule_gate.py check` 事後偵測(比對實際寄出紀錄),不是即時的。要真正無人值守的每日寄送,仍須另行搭配 Windows 工作排程器或 delaylocal(屆時仍建議人工核可後寄)。
- 寄送對象由設定檔管理;本 skill 不維護聯絡人清單。

Files in this skill

  • SKILL.md14.1 KB
  • config.example.json1.5 KB
  • daily-report.project.example.json663 B
  • scripts/check_no_secrets.py4.3 KB
  • scripts/confirm_gate.py10.5 KB
  • scripts/content_guard.py13.8 KB
  • scripts/extract_sessions.py13 KB
  • scripts/gmail_oauth.py24 KB
  • scripts/send_common.py9.5 KB
  • scripts/send_gmail.py7.8 KB
  • scripts/setup_gate.py16.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.