关于 issuekit
issuekit 是面向使用 `gh` CLI 的团队和 Agent 的 GitHub issue 生命周期技能。它通过五种模式创建、启动、关闭、同步和分流 issue,并为变更设置明确的确认规则,与 gitkit 协作管理工作树。
主要功能
- 01从计划或描述创建 issue
- 02在 gitkit 工作树中启动 issue
- 03PR 合并后关闭 issue
- 04修正 issue 与 PR 的关联状态
- 05分流并修复跟踪器
适用场景
- 01将计划转为可执行的 GitHub issue
- 02开始处理 ready 或 stacked issue
- 03PR 合并后清理对应 issue
- 04检查并修复待办状态
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mimukit/ skills --skill issuekit安装后在 Claude Code 中输入/issuekit确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
modes/close.mdcreate.mdstart.mdsync.mdtriage.md详细介绍
issuekit
通过 gh CLI 管理 GitHub issue 的整个生命周期,分为五种明确的模式:
create。 将计划文档或纯文本描述转化为格式规范的 issue。start。 将ready或stacked状态的 issue 放入专属 worktree,并将其状态改为in-progress。close。 PR 合并后,关闭 issue、解除它阻塞的事项,并拆除 worktree。sync。 事后协调并修复 PR↔issue 关系(合并的 PR 本应关闭但尚未关闭的 issue、现有 PR 上缺失的链接,以及仍被已合并 issue 标记为blocked的依赖项)。triage。 报告跟踪器的健康状况,然后应用你批准的修复,包括 issue 经 grill 讨论确定后将其从needs-planning晋升为ready,以及关闭已完成、重复或过时的 issue。
一个技能,五项任务,因为它们其实是开发工作流中五个阶段的同一项工作:提交工作、接手工作、合并工作、随着 PR 合并保持所有内容同步,以及确保跟踪器如实反映情况。
close 与 sync。 两者会处理一些相同的跟踪器事务,但区分依据是范围而非机制:close 处理一个指定的 issue,且你已确认其 PR 合并;它也是唯一会触及文件系统的模式(拆除 worktree)。sync 会事后扫描整个跟踪器以查找状态偏差,包括合并的 PR 本应关闭却未关闭的 issue、缺失的链接,以及仍被已合并工作标记为 blocked 的依赖项,并且绝不会触及 worktree。close 会复用 sync 的协调逻辑,而不是重复描述。
何时触发
用户想要处理 GitHub issue 时,根据其请求选择模式:
- create。 “根据这个计划创建 issue”“为
plan-auth.md创建 issue”“为 X 提交一个 issue”“把这个作为 issue 提交”“创建一个 GitHub issue”“将此记录为任务”“将此添加到待办列表”“为这些 TODO 创建 issue”。 - start。 “开始处理 issue #42”“开始 #42”“接手 #42”“为 #42 创建 worktree”“我现在开始处理 42”。
- close。 “关闭 #42”“结束处理 #42”“PR 已合并,现在收尾 #42”“拆除 #42 的 worktree”“#42 已合并,清理一下”。
- sync。 “同步我的 issue”“这个 PR 已合并,但 issue 仍处于打开状态”“将这个 PR 关联到 #42”“解除 #42 阻塞的事项”。
- triage。 “整理待办列表”“我的 issue 状态如何”“检查打开的 issue”“有没有过时的 issue”“为待办列表排定优先级”“设置 #42 的优先级”“都没有优先级”“为 #42 重新添加标签”“重命名 issue #42”“修正这些 issue 的标题”“这些标题不符合规范”“#42 已完成 grill 讨论,标记为 ready”“清理我的 issue”“哪些 issue 可以关闭”“合并这些重复的 issue”。
如果无法确定模式,请先询问。 将这些模式作为选项提供给用户,让用户先选择,再执行任何操作;不要猜测用户是要创建 issue 还是修改跟踪器。
Worktree 和分支由 gitkit 管理。 start 和 close 分别开启和结束 worktree 的生命周期,两者都通过 gitkit 处理;分支名称、路径约定、创建或接管,以及拆除操作都由 gitkit 管理。issuekit 回答的是*“这个 issue 是否可以着手处理,以及跟踪器当前显示什么状态?”;gitkit 回答的是“这个分支的代码放在哪里?”*两者都不会触及对方的内部机制:issuekit 向 gitkit 提供 issue 编号和标题,gitkit 返回分支和路径。
Pre检(所有模式)
在调用 GitHub 前,请先确认工具已就绪:
gh --version # gh installed?
gh auth status # authenticated?
gh repo view --json nameWithOwner -q .nameWithOwner # inside a repo?
- 如果缺少
gh或未完成身份验证,请说明情况,并提供https://cli.github.com/gh auth login。不要绕过这一要求。 - 调用 issuekit 就意味着项目使用 GitHub Issues。 并非每个项目都会在这里跟踪工作;调查仓库的技能在给出建议前必须先确认这一点。但 issuekit 不会这样做:提出创建、开始或关闭 issue 的人已经说明了工作在哪儿进行。因此,
create会直接创建 issue,不会先检查项目是否通过 issue 跟踪工作;任何模式都不会因为仓库似乎在别处跟踪工作而拒绝操作。 - 完全没有 shell 或
gh(例如基于浏览器的 Agent)?你无法调用gh。此时,请根据用户提供的信息进行判断,并输出可供用户自行运行的准确gh命令:issue 正文放在代码块中,gh issue create …/gh issue close …命令行应可直接粘贴运行。
适用于整个技能的安全原则。 创建、关闭、重新标记 issue 以及编辑 PR 正文,都是面向外部的变更。每次执行变更前都要先预览并征得同意,确保未经提示不会在 GitHub 上更改任何内容。 切勿合并 PR。
在 create、start、close 和 sync 中,所有调用方都可免于标签写入确认。 为 issue 或 PR 添加或移除标签时,无需预览或提示,直接执行;无论是由用户亲自操作,还是由编排器驱动运行,均如此。这适用于两个命名空间:生命周期和优先级。标签成本低、可见,而且只需一条命令即可撤销;每次写入都提示会分散过多注意力,而拒绝写入会导致跟踪器未能如实反映已发生的工作。在相应预览中注明每次标签写入,并在交接时报告标签的最终状态,确保变更仍可审计。
豁免仅适用于标签,不涉及其他任何内容。其他所有面向外部的变更仍须遵守上述规则:create 预览将要创建的 issue,close 预览关闭操作和工作树清理,sync 预览每一项配对和正文编辑。triage 不在豁免范围内。 它的标签写入并不记录已发生的工作;每项写入都是报告提出的一项判断(分类、排名或提升优先级),因此 triage 必须先生成报告,并且仅在用户批准后才应用所有修正,包括标签。切勿合并 PR。
标题规范(此技能创建的每个议题都适用)
议题标题采用与 commitkit 的提交说明和Conventional Commits 规范相同的格式,让跟踪器和 git 日志读起来像同一套工作流。格式:
type(scope): short imperative summary
根据议题交付的内容选择 type,而不是根据涉及的文件。类型集合采用 commitkit 的类型,不作更改:
| type | 适用情形 |
|---|---|
feat | 用户可见的新功能 |
fix | 修复错误 |
hotfix | 直接在基分支上紧急修复 |
docs | 仅涉及文档 |
refactor | 不改变行为的代码修改 |
perf | 性能改进 |
test | 添加或修复测试 |
build / ci | 构建系统、依赖项或流水线 |
style | 格式或空白字符调整,不涉及逻辑 |
chore | 不属于以上类别的例行维护 |
你生成的每个标题都必须遵循以下规则:
- 必须包含
(scope),指出工作所属的模块、软件包、目录或功能领域(feat(auth): …)。对于真正的全局性工作(全仓库配置、工具、跨领域清理),使用repo:chore(repo): …。 - 全部使用小写。 标题中的任何词都不得大写,包括首词。专有名词和缩写(
OIDC、SSO、CI)除外。 - 使用祈使语气,描述效果(“添加 sso 登录”),而不是活动(“对 auth 的修改”)。末尾不加句号。 保持简洁。
- 标题概括整个议题,而非仅其第一阶段。 多阶段议题应命名其端到端交付的功能(
feat(auth): add sso login),各阶段则写在正文中。若标题读起来像只涉及某一个阶段,就说明议题拆分得过细。
紧急修复无需先创建议题。 直接在基分支上修补的紧急工作从症状出发:有人创建 hotfix-<slug> 分支,并直接发起 hotfix(scope): 拉取请求,无需等待跟踪器。因此,此处没有任何模式会限制紧急修复,且它不经过 start。如果用户事后补建议题作为记录,标题应为 hotfix(scope): …;如果对应的 PR 已经打开,则添加 in-review 标签;绝不要添加 ready 标签,因为 ready 表示工作尚未开始。
如果仓库有自己的议题标题风格(可在 gh issue list 或 .github/ISSUE_TEMPLATE/ 中查看),则遵循该风格并说明你已这样做;参见备注。
生命周期标签(所有模式)
issuekit 使用一组精简、扁平的状态标签来跟踪问题在工作流中的位置。它会使用这些标签,但绝不会创建它们。配置标签是配套技能 repokit 的职责。如果仓库中缺少此技能需要的标签,请停止并告知用户如何添加(运行 repokit,或执行准确的 gh label create 命令),不要自行创建,也不要默默跳过。
规范映射中任何时候都恰好只有一个状态标签生效,并沿工作流从左向右推进;符合条件时,还会应用三个旁路标签。本表是与负责配置这些标签的技能 repokit 的共同约定。维护者必须确保两张表中的名称、颜色和含义一致:
| 标签 | 颜色 | 含义 | 通常由谁设置 |
|---|---|---|---|
triage | FBCA04 | 已提交,尚未评估或拆分 | 创建(临时)、分类 |
needs-planning | F1C40F | 规格尚不充分,无法着手处理;仍需人工规划/讨论 | issuekit create / afkkit gate |
ready | 0E8A16 | 规格完善且独立,现在即可安全地放入自己的 git worktree | issuekit create |
blocked | D93F0B | 有一项尚未开始且尚未满足的前置条件 | issuekit create / sync |
stacked | 006B75 | 其前置事项已有未关闭的 PR,因此现在可以在基于该 PR 的分支上处理 | prkit / issuekit sync |
in-progress | 1D76DB | 正在 worktree 中积极处理 | issuekit start |
in-review | 5319E7 | PR 已打开,等待审查或合并 | 创建 PR 的技能 / sync |
needs-info | D4C5F9 | 因等待更多详情而停滞,暂时无法继续 | 分类 |
wontfix | FFFFFF | 不会处理 | 分类 |
duplicate | CFD3D7 | 已被另一个问题取代 | 分类 |
已关闭的问题无需 done 标签,因为关闭状态本身就是信号。
ready 与 blocked 是并行工作标签对。 issuekit 会确定问题的规模并安排顺序,使每个问题都能在自己的 worktree 中独立着手处理,无需遵循先后顺序;这类问题会标记为 ready。例外情况是某个问题确实必须等另一个问题合并后才能开始,此时会标记为 blocked,并记录指出前置事项的依赖关系。这样,gh issue list --label ready 就会准确列出用户现在可以并行分派处理的问题。
blocked 与 stacked 将等待和可堆叠区分开来,这正是这种区分的意义。 如果没人开始处理前置事项,那就是真正的等待,其依赖问题会保持 blocked。如果前置事项的代码已完成、已推送,并且已有一个打开的 PR,那就根本不是等待:代码已经存在,因此可以立即从前置事项的分支切出一个分支来处理依赖问题,其 PR 则以该分支而非 trunk 为目标。这类问题标记为 stacked。混淆这两种状态会让单人项目陷入停滞,因为作者只能等待自己来审查 PR。
stacked 是存储的标签,而非计算得出的状态,因此它和 ready 一样支持通过 gh issue list --label stacked 分派工作。存储的标签可能过时,因此它本身绝不会作为任何操作的门槛:start 会在实际切出分支前实时重新检查前置事项的 PR。
记录依赖关系
GitHub 原生议题依赖关系是事实来源。 使用 gh issue edit 写入依赖边,并将其读回为结构化数据,而不是解析说明文字:
gh issue edit 44 --add-blocked-by 43
gh issue list --state open --json number,title,labels,blockedBy,blocking
也要在正文中保留一行 Blocked by #N,这样阅读议题的人无需打开另一个视图就能看到它在等待什么。这行是说明文字,不是存储记录。 如果两者不一致,以原生依赖边为准,并修正这行文字。
这些标志需要 gh 2.94.0 或更高版本。低于此版本时,应降级处理,而不是拒绝操作: 只写入正文行,并说明一次原生依赖边为何被跳过。这些标签和工作流必须能在机器上安装的任何 gh 版本中继续使用。
needs-planning 与 ready 是人工把关标签对。 ready 表示规格已足够明确,可以无人值守地开展工作,因此 Agent(或 afkkit 之类的编排工具)可以直接将其推进到 PR,无需人工介入。needs-planning 表示在议题真正可执行之前,还需要进行人工规划/讨论。只有在通过 grill 确定各项决策后,议题才能获得 ready 标签;请参阅创建时的 grill 把关流程。此时,gh issue list --label needs-planning 就是仍需人工处理的准确列表,也是 ready 扇出集合的对应集合。
类型体现在标题中,而不是标签中。 根据标题约定,议题标题已包含 feat(scope):/fix(scope):,因此此映射不包含 type: 标签,只有生命周期状态。
缺少所需标签时,先用 gh label list 检查一次,然后报告缺失情况,不要通过变通方式绕过:
此仓库中没有标签
blocked。请使用 repokit 配置工作流标签,或仅添加此标签:gh label create blocked --color D93F0B --description "has an unmet prerequisite that has not started"
只有标签存在后才应用它(gh issue edit <n> --add-label <label>)。根据标签豁免规则,此写入操作无需提示;在随附的预览中注明该标签,并在交接时报告。
推进依赖议题
一条转换规则决定依赖议题的标签,所有会移动或检查依赖议题的模式都必须应用它。 某个前置条件状态发生变化时,应根据其所有未关闭的前置条件重新计算每个依赖议题的标签,而不是只看刚刚发生变化的那个。议题 C 依赖 A 和 B:A 合并后,只要 B 尚未开始,C 就仍为 blocked。
通过原生依赖边查找依赖议题;此存储记录见记录依赖关系,并以相同方式读取每个议题的完整前置条件集合:
gh issue view 43 --json blocking -q '[.blocking[].number]' # who waits on #43
gh issue view 44 --json blockedBy,labels # everything #44 waits on
低于 gh 2.94.0 时,改为读取正文中的 Blocked by #N 行,并说明一次原生依赖边不可用。然后选择第一个匹配的行:
| 未关闭的前置条件 | 新标签 |
|---|---|
| 无 | ready |
| 每个前置条件都有一个未关闭的 PR,且这些 PR 构成一条链(每个 PR 的基础分支都是下一个 PR 的头部分支) | stacked,添加到该链最顶层的 PR 对应议题 |
| 每个前置条件都有一个未关闭的 PR,但这些 PR 不构成一条链 | 保留当前标签,并报告不兼容的父项 |
| 至少有一个前置条件没有未关闭的 PR | blocked |
- 前置条件的变化只会推进标签为
blocked和stacked的依赖议题。needs-planning依赖议题保留原标签,因为拦住它的是 grill 把关流程,而不是依赖关系。in-progress或in-review依赖议题也保留原标签,因为它们的工作已经开始。 - 每一层只有一个父分支。 如果未关闭的 PR 位于不同分支上,就没有一个基础分支能满足所有 PR。请在报告中列出每个候选父 PR,让用户决定;绝不能擅自选择一个。
- 每次状态转换都要替换标签。 在添加新生命周期标签的同一次调用中移除当前标签:
gh issue edit 44 --remove-label blocked --add-label ready。 - PR 查询失败时,不要改动依赖议题。 将其报告为未知,并注明失败的调用;出错并不能证明不存在 PR。
优先级标签(所有模式)
第二个标签命名空间,也是决定接下来处理什么的标签。与生命周期标签组一样,issuekit 会使用这些标签,但绝不会创建它们:由 repokit 提供;如果缺少标签,会报告问题,而不是绕过处理。
| label | color | 含义 | 通常由谁设置 |
|---|---|---|---|
critical | B60205 | 暂停其他所有工作;优先于正在进行的工作 | issuekit create / triage |
high | E99695 | 优先于其他可处理的问题 | issuekit create / triage |
medium | FEF2C0 | 常规优先级,评估后默认使用 | issuekit create / triage |
low | C5DEF5 | 值得以后处理;绝不会优先于其他事项 | issuekit create / triage |
此表是与 repokit 共享约定的另一半;请确保两个技能中的名称、颜色和含义保持一致。
生命周期和优先级彼此独立,因此各选一个标签,且两者互不蕴含。 生命周期回答能否处理?;优先级回答接下来应该处理哪个? 问题可以是 ready 且 high,也可以是 blocked 且 critical,两者都合理:当前可处理的 low 问题仍然可以处理,而被阻塞的 critical 问题恰恰说明了其阻塞因素为何重要。绝不要从其中一个推断另一个,因为仅仅因为问题是 critical 就将其提升为 ready,会让未经把关的工作落到无人值守的工作者手中,而设置 ready 防护的目的正是防止这种情况。
没有优先级标签表示尚未评估,而不是 medium。 缺少标签是一种真实状态,也是 triage 要查找的状态。不要默默地将问题默认设为中等优先级:一个未定级的问题,如果大家都以为它是常规优先级,就无法与真正经过考虑的问题区分开来,而优先级量表的全部价值就在于这种区别。除侧向退出状态(wontfix、duplicate)外,所有未关闭问题都应设置优先级;这些问题不会继续处理,无需定级。
一次只能有一个优先级标签,而且必须强制执行,因为 GitHub 不会替你保证。 标签是一个扁平命名空间,不存在互斥机制,因此问题可以同时带有 critical 和 low,而具有两个优先级的问题在下游各处都会出现不可预测的排序。因此,每次写入都应执行替换,而不是添加:读取问题当前的标签,并在添加新标签的同一次调用中移除实际存在的同级标签。
gh issue view 42 --json labels -q '[.labels[].name]' # → ["ready","medium"]
gh issue edit 42 --add-label high --remove-label medium
根据问题实际带有的标签来计算要移除的标签,而不是盲目移除另外三个同级标签;这样预览内容才准确(medium → high 与 set high 的含义不同),也不必依赖你的 gh 版本如何处理移除不存在的标签。
模式
每个模式的正文都各自存放在 modes/ 下的一个文件中。根据触发条件选择模式,读取对应文件并遵循其中的说明。此行以上的所有内容适用于每个模式,模式文件中不会重复说明。
- 模式
create→ 读取 modes/create.md,然后遵循其中的说明。 - 模式
start→ 读取 modes/start.md,然后遵循其中的说明。 - 模式
close→ 读取 modes/close.md,然后遵循其中的说明。 - 模式
sync→ 读取 modes/sync.md,然后遵循其中的说明。 - 模式
triage→ 读取 modes/triage.md,然后遵循其中的说明。
共享操作:评论计划或决定
在 create 和 triage 中,你可以将计划摘录或决定发布到问题中,作为审计记录。这是一项共享操作,不属于任何模式:
gh issue comment <n> --body-file <file>
多行 Markdown 内容请使用临时文件,并在之后删除。
备注
- 绝不合并 PR,也绝不在未展示变更并事先获得同意的情况下更改 GitHub 状态。
- 如果仓库有自己的 issue 规范,无论是
.github/ISSUE_TEMPLATE/中的模板、标签方案,还是gh issue list中显示的标题格式,都应优先遵循这些规范,并说明你已遵循。 - 对于任何多行内容,优先使用
--body-file而非--body;完成后清理临时文件。 - 让 issue 的规模与工作量相称:一行修复对应一个 issue 和一条验收标准,而不是分阶段扩建。根据计划的实际范围调整正文篇幅,大型计划可以保留为一个大型 issue。