mcpField
W
watch-github

watch-github

github.com/vivswan开发119 次安装2 天前更新
代码仓库

关于 watch-github

watch-github 是一项技能,在 Claude Code 会话中轮询 GitHub 上的 PR 和分支动态。它发送评论、评审、CI 结果、提交头变更、标签、冲突、合并及关闭事件摘要,并支持指定工作流作为门禁。

主要功能

  1. 01监视 PR 和分支头
  2. 02报告评论与评审动态
  3. 03按指定工作流判断 CI
  4. 04跟踪提交头、标签、冲突和合并
  5. 05按动态调整轮询间隔

适用场景

  1. 01推送更改后监视 CI
  2. 02跟进开放 PR 的评审和评论
  3. 03合并后监视主线分支

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/vivswan/skills --skill watch-github

安装后在 Claude Code 中输入/watch-github确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE.md
README.md
.codex-plugin/
plugin.json
agents/
openai.yaml
scripts/
github-events.mts
scripts/github/
check-suites.mts
gh.mts
pr-activity.mts
repository.mts
scripts/targets/
branch.mts
ci.mts
pr.mts

详细介绍

监控 GitHub

每个 Claude Code 会话启动一个守护进程作为后台任务,轮询该会话关注的拉取请求和分支最新提交。会话只需订阅一次,然后继续工作。评论、评审、CI 结果、头部变更、标签变更、与基准分支的冲突、合并和关闭都会作为消息发送到会话中,每次轮询一条消息;同时也会作为日志行写入,供其他 Agent 读取。

守护进程属于 /session-events 技能,与本技能安装在一起;本技能是它的 GitHub 数据源。该页面规定消息封装格式、运行时目录和文件、文件接收器以及两小时上限。本页面规定轮询内容和事件含义。

运行条件:一个 Claude Code 会话、一个用户、由该会话启动一次的守护进程,以及通过已认证的 gh 访问 GitHub。

示例

一次推送已完成,PR 处于打开状态。每个会话启动一次守护进程作为后台任务,然后用一行命令订阅该 PR 及其门禁工作流:

bun "<skill-dir>/scripts/github-events.mts" daemon     # once per session, as a BACKGROUND task
bun "<skill-dir>/scripts/github-events.mts" watch owner/repo#12 --expect-workflow checks

会话继续工作。几分钟后,门禁检查完成,以下消息会自动出现在对话中:

<cross-session-message from="uds:/run/user/1000/session-events/4242.github-events.sock" from-name="github-events" from-mode="bypass">
PR owner/repo#12: CI green on 1a2b3c4d5e6f: 3 workflows
https://github.com/owner/repo/pull/12/checks
automated notice from github-events; no reply needed
</cross-session-message>

无需花费一个轮次询问“还没有变化吗”。守护进程是会话自身的子进程:其消息会立即到达,封装中的名称为 github-events;会话结束时,它也会自行退出。

适用场景

  • 刚在启用了 CI 的分支上运行 git push,或刚打开 PR:监控该 PR。
  • 等待 PR 更新:等待评审、回复、合并,或确认“CI 是否通过?”
  • PR 刚合并,或直接推送已进入主线:每个会话监控一次主线分支 owner/repo:main;此后该分支的每个最新提交都会接受检查。

目标

bun "<skill-dir>/scripts/github-events.mts" watch owner/repo#12 --expect-workflow checks --expect-workflow lint
bun "<skill-dir>/scripts/github-events.mts" watch owner/repo:main --expect-workflow checks
目标事件结束条件
owner/repo#n,一个拉取请求评论、评审、ci、head、标签、冲突、已合并、已关闭、异常合并或关闭时
owner/repo:branch,一个分支最新提交ci、head、异常永不结束;每次推送到该分支都会产生一个新的 head

Issue 和安全警报是此数据源未来支持的目标形式,不会成为新的命令或技能。

--expect-workflow <name> 可重复使用,用于指定门禁:即 .github/workflows/ 下工作流文件的 name:,该工作流负责检查目标。单次调用中的标志构成完整的门禁集合。对同一目标重复执行 watch 会替换门禁和游标:重新检查其 CI,并从此刻重新建立活动基线。

如果没有守护进程,watch 会以状态码 3 退出并打印准确的启动命令。首次发现 PR 时,不会上报 PR 上已有的评论、评审或标签;只有此后新增的内容才会成为事件。PR 的 CI 结果、已合并或已关闭状态,以及已有的冲突,都会立即进行判定。

事件

每条消息包含一次轮询的事件,每个事件都有一个 URL,结尾一行是 automated notice from github-events; no reply needed。永远不要回复这类消息。每段文本都是结构化信息:谁、在哪里、数量、状态以及 SHA。消息中不会包含评论、审查或构建日志的内容;请通过 URL 查看。

类型行中的内容操作
commentPR owner/repo#12: 2 new comments by octocat at src/x.ts:41, src/y.ts:7,后面是最新评论的 URL打开 URL,并按一轮审查来处理
reviewPR owner/repo#12: review by octocat (CHANGES_REQUESTED), 3 comments,后面是该审查的 URL按照 /pr-landing-discipline 技能进行同样的处理
ciPR owner/repo#12: CI green on 1a2b3c4d5e6f: 3 workflows,后面是检查页面;如果某个未列出的工作流失败,则会附上 ; other checks red: claude-review;或者 PR owner/repo#12: CI red on 1a2b3c4d5e6f: checks / check / Run tests,后面是失败运行的 URL绿色:继续;红色:运行 gh run view <id> --log-failed 查看摘要,修复后推送,下一条结果会自动送达
headPR owner/repo#12: head moved to 1a2b3c4d5e6f; last commit by octocat(这是提交的作者,不是推送者),每次更新都会发送,包括你自己的推送如果 head 不是你推送的:操作分支前先拉取
labelPR owner/repo#12: label added: merge-when-green;同一次轮询中有多个标签时:PR owner/repo#12: labels added: approved, merge-when-green;PR owner/repo#12: label removed: needs-rebase;如果同一次轮询中既添加又移除标签,则在同一行中用 ; 分隔;后面是该 PR 的 URL标签名称提到你或某个门禁时:采取行动;其他标签仅供参考
conflictPR owner/repo#12: conflicts with main; rebase needed;在你完成变基后,或合并测试自行恢复正常后,会发送 PR owner/repo#12: conflicts resolved;后面是该 PR 的 URL变基到基准分支并推送;如果推送后冲突依然存在,这条消息会再次出现
mergedPR owner/repo#12: merged into main停止跟进;主分支的 CI 由目标分支负责
closedPR owner/repo#12: closed without merging停止跟进
troublePR owner/repo#12 is not readable; unwatch it or check access;PR owner/repo#12: CI settled on 1a2b3c4d5e6f with no run of checks; check the workflow name(或 no checks on 1a2b3c4d5e6f after 2 polls, so no run of checks);PR owner/repo#12: 3 reads failed; read the daemon log;或连续三次轮询失败后 /session-events 技能发出的消息工具故障,不代表流水线失败或通过;参见下方的注意事项
忙碌不是一种类型:如果某次轮询中有事件、待处理的汇总结果,或 head 仍在评估中,则间隔保持为 60 s;每次无事发生的轮询都会将等待时间加倍,依次为 120 s、240 s,最后为 300 s无需操作

目标为分支的消息则以 branch owner/repo:main: 开头。评论行会统计所有作者的评论,包括当前会话自己的登录名:如果某位所有者使用同一登录名,就无法将其与 Agent 区分开;其决定也绝不会被当作回声丢弃。审查中的行内评论只会在审查行中统计,不会再次作为评论统计。

当前登录用户撰写的审查在提交之前不会触发事件;提交后会以相同 ID 产生一个事件。有两种情况不会提示或表现异常:如果草稿提交时,较新的活动已使其超出读取窗口(十条审查,或线程中的三条回复),就无法找到;如果删除操作将较早的评论重新纳入窗口,则该评论会被报告一次。

任一方推送后,GitHub 都会重新计算合并测试,并在此期间返回 UNKNOWN。测试结果确定之前不会有任何通知。

CI 规则
  • 绿色表示每个指定门禁的最新一次运行均已通过(跳过也算通过);如果未指定门禁,则 PR 的汇总结果为 SUCCESS。指定门禁时,门禁之外失败的运行会列在 ; other checks red: 之后;之后变红的旁观检查会触发新的 ci 事件,因为 /pr-landing-discipline 技能会将所有检查都计入绿色状态。
  • 红色表示任一指定门禁的最新一次运行失败或已取消,且之后没有更新的运行;如果未指定门禁,则汇总结果为 FAILURE 或 ERROR。红色状态行会列出每个套件中最多 50 个失败作业,分别注明工作流、作业和第一个失败步骤;没有运行记录的门禁会列在 ; no run of 之后。
  • 门禁没有运行记录时,如果汇总结果仍在等待,则该门禁处于待处理状态;如果汇总结果已确定但仍没有该门禁的运行记录,则触发一次 trouble 事件。如果某个提交上完全没有检查,则轮询两次后也会触发一次 trouble 事件:这可能是门禁名称拼写错误,或工作流未在此引用上触发。
  • 没有检查且没有门禁表示没有 CI,而不是待处理:不会输出任何内容,提交会保持空闲,直到出现汇总结果。必须确保某项运行被登记时,请使用 --expect-workflow 指定门禁。
  • 单位是工作流。 对同一个 SHA 重新触发会累积多个运行;只判断每个工作流最新的一次运行,较早的已取消运行会被取代。
  • 给出判定后,有变动时会重新判断该提交:有门禁的提交每次轮询都会重新判断(门禁重新运行不一定会改变汇总结果),没有门禁的提交则在汇总结果变化时重新判断。判定相同则保持静默;判定不同则触发新的 ci 事件。新提交会从零开始判断。

轮询预算

GitHub 将 GraphQL 的请求限制单独计入一个配额,而 Actions REST 端点(gh run list、gh run watch、gh run view)则计入另一个配额;并行运行的 watcher 会长时间占用后者,超过一次运行所需的时间。守护进程只读取 GraphQL:有活动时每分钟一次;按照 /session-events 技能的渐进安排,在没有活动时每五分钟一次。

每次轮询对每个仓库消耗一个请求:包含每个被监控 PR 的条目、每个被监控分支的最新提交,以及每个仍在判断或带有指定门禁的提交的检查套件,并在一个查询中使用别名(每个仓库每 30 个 PR 额外消耗一个请求)。除此之外:

  • 每个条目有变动的 PR 读取一次详细信息(评论、评审、讨论串),分页读取到上次已查看的活动为止
  • 检查套件超过 100 个的提交分页读取一次
  • 每个红色判定读取一次,列出每个套件中最多 50 个失败作业及其步骤

在稳定状态下,没有任何变动时,每个仓库每五分钟只消耗一个请求。消息之间切勿运行 gh run watch、生成 watcher 子代理,或手动读取 PR:本会话的唯一轮询器是守护进程。

如果某个工作流的运行共用同一个 concurrency 组键,较新的推送会取消较早提交的待运行任务,因此只有最新提交会得到判定;再次推送前请等待判定结果。

Commands

usage: github-events.mts <command> [options]
  daemon [--interval <s>] [--mode bypass|prompting] [--id <name> [--pid <pid>]]
  watch <target> [the source's flags] [--id <name>]
  unwatch <target> | --all [--id <name>]
  wait [--since <id>] [--timeout <s>] [--id <name>]
  poll | status | stop [--id <name>]
the daemon serves the Claude Code session named by CLAUDE_CODE_MESSAGING_SOCKET and exits with it;
--id <name> names a file-sink daemon for a non-Claude agent instead, --pid <pid> ends it with that process;
--mode is the session's permission mode, carried in the envelope: bypass (the default) or prompting;
--interval is 60 s by default, 1 to 86400
targets: <owner/repo>#<n> for a pull request, <owner/repo>:<branch> for a branch tip
--expect-workflow <name> names a workflow whose run must appear on the head before CI reads green; repeatable
the session-events skill must be installed beside this one; without it every command exits 2 naming the install: npx skills add Vivswan/skills -g --skill session-events
files: <dir>/<pid>-<start>.github-events.{state.json,events.jsonl,log} and <dir>/<pid>.github-events.sock for a session; <id>.github-events.* for a file sink;
  <dir> is $SESSION_EVENTS_DIR, else $XDG_RUNTIME_DIR/session-events, else $CLAUDE_CODE_TMPDIR/session-events-<uid>, else <os tmpdir>/session-events-<uid>, else /tmp/session-events-<uid>
prints: one message per poll with alerts, wrapped in <cross-session-message from="uds:<socket>" from-name="github-events" from-mode="<mode>"> and ending "automated notice from github-events; no reply needed";
  wait prints the new events as JSON lines, then cursor: <id>
exits: 0 ok (stop with no daemon running, and a second daemon start, are ok too); 2 usage, a state file that is not JSON, or no runtime directory;
       3 no daemon answers for this session: stderr names the socket and the background command that starts one; 4 wait only: the timeout passed with no newer line
退出码含义
0正常;没有守护进程运行时执行 stop 也正常,第二次启动 daemon 也正常
2用法错误(未设置 CLAUDE_CODE_MESSAGING_SOCKET 且没有 --id、目标未使用任一种形式、门名称为空)、没有运行时目录,或此技能旁未安装 /session-events 技能:install it beside this skill: npx skills add Vivswan/skills -g --skill session-events
3没有守护进程响应此会话:stderr 会列出套接字和用于启动守护进程的准确后台命令
4仅适用于 wait:等待超时,期间没有更新的行

默认情况下,--interval 为 60 s。文件接收端(--id)、wait 及其游标,以及运行时文件均属于 /session-events 技能;此来源的日志行为 {"id":17,"at":"2026-10-12T14:03:20Z","repo":"owner/repo","pr":12,"sha":"1a2b...","kind":"ci","text":"...","url":"..."},如果目标是分支,则该行用 branch 替代 pr。

在一组协作 Agent 中,负责协调的会话将守护进程作为自己的后台任务运行,--mode 与会话模式一致,并监视这一组中的 PR;构建者不会在那里运行 watch。负责协调的会话要让构建者处理某条评审意见时,会通过一条消息转发该行。

常见问题

现象含义处理方法
watch 以状态码 3 退出,并列出套接字和命令此会话没有守护进程将打印出的命令作为后台任务运行,然后再次运行 watch
守护进程运行约两小时后自行停止,但会话仍在运行执行环境对后台任务的时长设有限制;对应行由 /session-events 技能的页面负责使用相同命令重新启动;已保存的目标会继续监视
连续三次轮询失败后出现 trouble 事件gh、网络或 GitHub 连续三次拒绝轮询;首先检查 gh auth status修复守护进程日志中指出的问题;令牌过期时需要执行 stop 并重新启动,因为守护进程继承了会话的令牌
出现 trouble 事件:CI 已稳定,但没有任何门的运行记录指定的工作流从未在该提交上注册运行记录对照 .github/workflows/*.yml 检查名称,然后使用正确的门集合再次运行 watch;绝不要将汇总结果视为通过
出现 trouble 事件:无法读取PR 或分支返回 null:已删除、已重命名或无权访问执行 unwatch,或修复访问权限
出现 trouble 事件:3 次读取失败轮询仓库读取一直有响应,但此目标的详细信息或分页套件连续三次读取失败查看守护进程日志;每次轮询都会重试该目标,成功后计数器会重置
仅列出工作流名称的红色行读取失败作业时出错;判定结果仍然有效对运行 URL 中的 id 执行 gh run view <id> --log-failed
缺少 ghdaemon 从第一次轮询起就会失败安装并验证 GitHub CLI;在此之前,报告推送时附上 PR URL,绝不要悄悄跳过监视

使用 Agent 工具启动的本地子 Agent 与所属会话共享收件箱套接字和 pid,因此在其中运行 watch 会订阅该会话的守护进程,事件也会发送到该会话。来自 agent teams 的队友是拥有独立套接字的单独进程,并运行自己的守护进程。

评论

支持 Markdown