用 Agent Skill 自动生成工作周报:从 git 提交到 Jira 的 Node.js 落地实践

发布时间:2026/9/28 4:04:29
用 Agent Skill 自动生成工作周报:从 git 提交到 Jira 的 Node.js 落地实践 1. 周报这件事为什么总是拖到周一才痛苦每到周一上午很多人都会经历同一个场景打开编辑器想写周报脑子一片空白只能回头翻 git log、翻 Jira 看板、翻聊天记录把零散的提交信息拼成一段“人话”。这个过程通常要花掉半小时甚至更久而且写出来的东西往往只是把 commit message 换个说法既没有提炼出真正的技术价值也没法在半年后回看时快速回忆起当时做了什么。更麻烦的是信息分散。git 提交在本地各个仓库里Jira 任务在浏览器标签页里两者之间没有自动关联。你记得自己改了一个接口字段但想不起来对应的 Jira 编号你记得修了一个构建问题但不确定是哪个仓库的哪次提交。这种“记忆碎片化”导致周报要么写得太粗要么写得太细最后变成流水账。我试过用纯 prompt 让 AI 直接读 git log 生成周报结果很不稳定token 消耗大、输出格式飘忽、遇到多仓库时经常漏掉提交。后来把确定性逻辑抽成 Node.js 脚本让 Agent Skill 只负责“把数据写成技术日志风格”整个流程才真正可复制。这篇就按这个思路从零搭一个/weekly-reportSkill把 git 提交和 Jira 编号自动汇总成中文周报并用 launchd 在 macOS 上定时触发。适合谁手上有多个 git 仓库、日常用 Jira 跟踪任务、每周要写周报但不想手动整理的开发者。你不需要懂 Agent Skill 的底层协议只要能跑 Node.js 脚本、会改 config.toml 就能跟做。2. 前置准备TaoToken 接入与目录结构Agent Skill 本身不绑定特定模型服务但要让 AI 稳定执行“读脚本输出 → 生成中文周报”这一步需要一个可编程调用的模型接口。TaoToken 提供 OpenAI 兼容的 API 入口适合放在 Skill 的编排层里做文本生成。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。先在你的项目根目录建一个 work-journal 仓库用来存放周报和 Skill 配置。目录结构建议如下work-journal/ ├── .claude/ │ └── skills/ │ └── weekly-report/ │ ├── SKILL.md │ ├── config.toml │ ├── calc-dates.js │ └── collect-commits.js ├── reports/ │ └── 2026-03-30.md └── .gitignoreconfig.toml 放个人路径和 Jira 基址不提交进仓库config.example.toml 作为模板随代码开源。.gitignore 里加上 config.toml 和 reports/ 下的临时文件。去 TaoToken 控制台创建一个 API Key地址是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。拿到 Key 后不要写进 SKILL.md而是放在环境变量里比如TAOTOKEN_API_KEY。这样 Skill 文件可以安全地提交到公开仓库。如果你更习惯用 Coding Plan 做长期编码和 Agent 任务可以在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 了解套餐只是想先验证模型输出效果可以直接用模型对话页 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 试一段 prompt。3. 可复制配置config.toml 与两个 Node.js 脚本3.1 config.toml 骨架config.toml 只放三类信息扫描根目录、Jira 基址、作者邮箱。不要放 API KeyKey 走环境变量。# config.toml —— 不提交进仓库加入 .gitignore [scan] # 你的所有 git 仓库所在的父目录脚本会向下扫描最大 3 层 base_dir /Users/yourname/workspace # 提交作者邮箱用于过滤只属于你的提交 author_email youexample.com [jira] # Jira 任务链接前缀TO-1234 会被拼成完整 URL base_url https://yourcompany.atlassian.net/browse [report] # 周报输出目录相对于 work-journal 根目录 output_dir reports # 生成语言 language zh-CN对应的 config.example.toml 把 base_dir、author_email、base_url 换成占位符即可提交进仓库供别人复制。3.2 calc-dates.js日期计算不靠 AI 心算时区和星期几的边界很容易出错所以把日期计算单独抽成脚本。无参数时返回上周一和上周日有参数时校验该日期是否为周日是则返回该周一到周日否则报错退出。// calc-dates.js [YYYY-MM-DD] // 无参数返回上周一和上周日 // 有参数验证是周日返回该周周一和周日 const input process.argv[2]; function formatDate(d) { const y d.getFullYear(); const m String(d.getMonth() 1).padStart(2, 0); const day String(d.getDate()).padStart(2, 0); return ${y}-${m}-${day}; } function getMonday(date) { const d new Date(date); const day d.getDay(); // 0周日 const diff day 0 ? -6 : 1 - day; d.setDate(d.getDate() diff); return d; } if (!input) { const today new Date(); const lastMonday getMonday(today); lastMonday.setDate(lastMonday.getDate() - 7); const lastSunday new Date(lastMonday); lastSunday.setDate(lastSunday.getDate() 6); console.log(JSON.stringify({ monday: formatDate(lastMonday), sunday: formatDate(lastSunday) })); } else { const d new Date(input); if (d.getDay() ! 0) { console.error(ERROR: ${input} 不是周日请传入周日日期); process.exit(1); } const monday getMonday(d); const sunday new Date(monday); sunday.setDate(sunday.getDate() 6); console.log(JSON.stringify({ monday: formatDate(monday), sunday: formatDate(sunday) })); }运行node .claude/skills/weekly-report/calc-dates.js会输出类似{monday:2026-03-30,sunday:2026-04-05}。如果传入2026-03-29周日会返回该周一到周日传入非周日日期则直接报错SKILL.md 把错误信息转给用户即可。3.3 collect-commits.js扫描多仓库提交AI 直接从 git log 提取提交很耗 token输出格式也不固定。把这段逻辑抽成 Node.js 脚本扫描 base_dir 下所有 git 仓库最大深度 3输出指定周期内属于 author_email 的提交。// collect-commits.js MONDAY SUNDAY AUTHOR_EMAIL const { execSync } require(child_process); const fs require(fs); const path require(path); const [monday, sunday, author] process.argv.slice(2); if (!monday || !sunday || !author) { console.error(用法: node collect-commits.js MONDAY SUNDAY AUTHOR_EMAIL); process.exit(1); } const configPath path.join(__dirname, config.toml); const configText fs.readFileSync(configPath, utf-8); const baseDir configText.match(/base_dir\s*\s*([^])/)[1]; function run(cmd) { try { return execSync(cmd, { encoding: utf-8, maxBuffer: 10 * 1024 * 1024 }); } catch (e) { return ; } } const repoList run(find ${baseDir} -maxdepth 3 -name .git -type d -prune) .split(\n) .filter(Boolean) .map((p) path.dirname(p)); for (const repo of repoList) { const hashes run( git -C ${repo} log --format%H --no-merges --after${monday} 00:00:00 --before${sunday} 23:59:59 --author${author} ) .split(\n) .filter(Boolean); if (hashes.length 0) continue; console.log( REPO: ${path.basename(repo)} ); for (const hash of hashes) { const msg run(git -C ${repo} log -1 --format%s%n%b ${hash}).trim(); const files run(git -C ${repo} show --stat --format ${hash}) .split(\n) .filter((l) l.includes(|)) .map((l) l.split(|)[0].trim()) .join(, ); console.log(--- COMMIT: ${hash.slice(0, 8)} ---); console.log(MESSAGE: ${msg}); console.log(FILES: ${files}); console.log(); } }脚本输出结构化文本以 REPO: xxx 和--- COMMIT: xxx ---分段。AI 拿到的是干净数据省 token也不会因为 git 输出格式变化而出错。3.4 SKILL.md编排层SKILL.md 由 frontmatter 和编号步骤组成。步骤里混写两类指令bash 指令调脚本处理确定性逻辑prose 指令告诉 AI 怎么生成。--- name: weekly-report description: 扫描上周 git 提交结合 Jira 编号生成中文周报并提交 --- # Weekly Report Skill ## 步骤 1. 运行 node .claude/skills/weekly-report/calc-dates.js拿到上周一和上周日。 如果用户传入了日期参数改为 node .claude/skills/weekly-report/calc-dates.js 日期。 2. 运行 node .claude/skills/weekly-report/collect-commits.js 周一 周日 邮箱 邮箱从 config.toml 的 author_email 读取。 3. 按以下规则生成中文周报 - 按仓库分段每个仓库一个段落。 - 提交信息里出现的 Jira 编号如 TO-1234转为完整链接 [TO-1234](https://yourcompany.atlassian.net/browse/TO-1234)。 - 写成工程师给半年后自己看的技术日志风格不要流水账。 - 归纳提交时保留关键技术名词比如字段名、接口名、构建阶段名。 4. 把生成的周报写入 reports/周一.md然后 git add 并 git commit。两类指令的边界是“确定性 vs 生成性”日期、commit 列表有固定答案写脚本把提交归纳成人话需要理解和表达写 prompt。4. 验证请求跑一次 /weekly-report 并核对条目配置完成后在 work-journal 目录下输入/weekly-reportSkill 会按顺序执行算日期 → 扫提交 → 生成周报 → 写入文件 → 提交。运行后先看控制台输出确认 calc-dates.js 返回的周一和周日是否正确。比如当前是 2026-04-06 周一应该返回{monday:2026-03-30,sunday:2026-04-05}。如果日期不对检查系统时区。然后看 collect-commits.js 的输出确认每个仓库的提交数量和 commit message 是否完整。如果某个仓库没有输出可能是 base_dir 路径不对或者 author_email 和 git 配置里的邮箱不一致。可以用git -C repo log --author你的邮箱 --oneline手动验证。生成的周报文件在 reports/ 目录下打开核对三件事第一Jira 编号是否转成了完整链接。比如提交信息里有TO-1234周报里应该是[TO-1234](https://yourcompany.atlassian.net/browse/TO-1234)。如果没转检查 SKILL.md 里的 base_url 是否和 config.toml 一致。第二按仓库分段是否正确。每个仓库一个段落段落开头是仓库名加粗。如果所有提交混在一起说明 SKILL.md 的 prose 指令不够明确可以加一句“每个仓库必须单独成段”。第三技术名词是否保留。比如提交里写了update_dependency阶段、17.0.2镜像版本周报里应该保留这些词而不是被概括成“优化了构建流程”。如果被过度概括在 SKILL.md 里加一句“保留字段名、接口名、版本号等具体名词”。核对完成后如果周报内容需要微调直接改 reports/ 下的 md 文件然后重新 commit。Skill 生成的只是初稿最终提交前人工过一遍是必要的。5. 本篇常见错排查5.1 calc-dates.js 报错“不是周日”如果你传入日期参数脚本会校验该日期是否为周日。传入周一、周二都会报错退出。这是故意的因为周报周期通常按周一到周日算传入周日才能确定整周范围。如果你想补生历史周报传上周日日期比如node calc-dates.js 2026-03-29。5.2 collect-commits.js 扫不到提交先确认 base_dir 路径存在并且下面有 .git 目录。脚本用find -maxdepth 3扫描如果你的仓库嵌套超过 3 层需要调大 maxdepth。然后确认 author_email 和 git 提交里的邮箱一致可以用git log --format%ae | sort -u看实际邮箱。最后确认日期范围--after和--before是闭区间边界如果提交时间在周一 00:00:00 之前或周日 23:59:59 之后不会被包含。5.3 Jira 链接没生成检查 SKILL.md 里的 base_url 是否写成了https://yourcompany.atlassian.net/browse末尾不要带斜杠。提交信息里的 Jira 编号格式要统一比如都是TO-1234如果有的写TO 1234有的写to-1234AI 可能识别不全。可以在 collect-commits.js 输出前用正则统一提取编号但更简单的做法是团队约定提交信息里 Jira 编号格式一致。5.4 launchd 定时任务没触发macOS 的 launchd 配置放在~/Library/LaunchAgents/下文件名比如com.yourname.weekly-report.plist。内容如下?xml version1.0 encodingUTF-8? !DOCTYPE plist PUBLIC -//Apple//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd plist version1.0 dict keyLabel/key stringcom.yourname.weekly-report/string keyProgramArguments/key array string/usr/local/bin/node/string string/Users/yourname/work-journal/.claude/skills/weekly-report/run.js/string /array keyStartCalendarInterval/key dict keyWeekday/key integer1/integer keyHour/key integer9/integer keyMinute/key integer0/integer /dict keyStandardOutPath/key string/tmp/weekly-report.log/string keyStandardErrorPath/key string/tmp/weekly-report.err/string /dict /plistWeekday 为 1 表示周一Hour 为 9 表示早上 9 点。加载命令是launchctl load ~/Library/LaunchAgents/com.yourname.weekly-report.plist。如果没触发先看/tmp/weekly-report.err里的报错常见原因是 node 路径不对用which node确认实际路径。另外 launchd 不会继承你 shell 里的环境变量如果 Skill 依赖TAOTOKEN_API_KEY需要在 plist 里加EnvironmentVariables字典或者把 Key 写进一个只有本机可读的配置文件。5.5 周报提交进仓库后想改直接改 reports/ 下的 md 文件然后git commit --amend或者新提交一次。如果已经 push 到远程新提交一次更安全。Skill 生成的周报是初稿人工润色后提交是正常流程不需要追求全自动。6. 把周报变成可检索的技术日志这套流程跑通后周报不再是一次性的汇报材料而是按周归档的技术日志。半年后写年终总结时直接翻 reports/ 目录每周做了什么、关联哪个 Jira 任务、改了哪些文件都能快速定位。git 提交和 Jira 编号自动关联省掉了手动拼链接的步骤。如果你想把生成环节换成更稳定的模型调用可以在 Skill 的 prose 步骤里接入 TaoToken 的 API基址是 https://taotoken.net/api 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。长期做编码和 Agent 任务的话Coding Plan 页面 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 有套餐说明。API Key 在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 创建记得只放在环境变量里不要提交进仓库。最后一个小技巧collect-commits.js 的输出可以顺手存一份 JSON 到 reports/raw/ 下以后想换生成风格或者做统计时不用重新扫 git。周报的原始数据和技术日志分开存改起来更灵活。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询