关于 git-project
git-project 是用于通过 GitHub Projects v2 管理仓库议题和路线图的技能,面向需要组织 Epic、拆分任务并推进看板的团队。它以原生父子议题关系和独立的项目状态字段维护结构与进度。
主要功能
- 01创建项目及路线图视图
- 02用原生子议题组织 Epic
- 03移动议题并调整优先级
- 04设置议题类型和里程碑
- 05更新项目状态字段
- 06管理仓库与项目访问权限
适用场景
- 01把零散议题整理为 Epic 路线图
- 02在 Epic 之间重新归属议题
- 03推进任务状态并设置优先级
- 04按交付范围分配和关闭里程碑
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dmythro/ agent-skills --skill git-project安装后在 Claude Code 中输入/git-project确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/access-and-roles.mdallowlist.mdcli-and-graphql.mdproject-setup.mdsub-issues.mdtypes-and-milestones.md详细介绍
GitHub 项目管理
用于将仓库中的 Issue 整理到基于 Epic 的路线图中,并通过 GitHub Project(v2)进行日常管理的主要技能。 涵盖设置(项目、字段、视图、原生工作流)和操作(创建包含子 Issue 的 Epic、推进状态、移动工作、设置优先级)。仅适用于 GitHub,通过 gh project + gh api(REST 子 Issue + GraphQL)操作。
已针对 gh v2.103.2 验证(2026-10-27):先根据 v2.102.0(2026-09-30)的 --help 检查此处使用的每个 gh 子命令和标志,再对比 v2.102.0 和 v2.103.2 的 pkg/cmd 源码(2026-10-27),因为 --help 是根据源码生成的:此处使用的子命令没有标志发生变化(gh issue create/edit 仅更改了 --body-file 解析附件路径的方式)。在适用位置标注了最低版本(gh >= 2.94、>= 2.97)。如果 gh --version 显示的版本更新,请先阅读 v2.103.2 之后的发行说明,了解 gh project 和 gh issue 的变更,再依赖此处的标志详情。
这里的惯例不太直观,而且很容易只做到一半:UI 通过原生父子链接嵌套 Issue,并通过单独的看板状态字段跟踪进度——Markdown 检查清单和关闭 Issue 都不会影响这两者。如果这两点处理不当,工作看起来已经完成,实际结构却在悄然偏离。本技能可确保工作流默认正确。
使用场景
- 设置项目/路线图——创建 Project、字段(Status、Priority)、Epic 和 Upcoming 视图,并启用原生工作流
- 创建包含 Issue 的 Epic——“创建一个 Epic X,并包含这些 Issue”,“将这些 Issue 归到一个 Epic 下”
- 提交/移动工作——将 Issue 添加到某个 Epic 下、在不同 Epic 之间移动 Issue、添加新工作
- 推进看板——开始处理某个 Issue(-> In Progress)、关闭 Issue(-> Done)、(重新)设置优先级
- 分类工作——设置原生 Issue 类型(Task/Bug/Feature),而不是使用类型标签
- 限定里程碑范围——为某项交付成果创建里程碑、分配 Issue、完成里程碑;解析“当前里程碑”/“里程碑 N”
- 迁移现有仓库中尚未归类的 Issue,使其符合此结构
- 授予访问权限——团队成员无法应用标签、分配负责人、关联子 Issue,或编辑 Status/Priority
- 配置工具允许列表——为只读
gh project命令设置自动批准模式
关键规则
这些都是容易踩的坑——每一条中,看似顺理成章的操作都会让结构出错。
- Epic 应通过原生子问题嵌套,而不是使用 Markdown 任务清单。
- [ ] #123只是表面形式,不会建立 UI 和路线图读取的父子关联。请使用原生方式关联:gh issue edit <epic> --add-sub-issue <child>/gh issue create --parent <epic>(gh >= 2.94),或使用 REST 子问题 API。请参阅references/sub-issues.md。 - 在 Epic 之间移动问题 = 重新设置原生父级关联。 只需一条命令:
gh issue edit <child> --parent <newEpic>(会替换旧的父级),然后整理正文。只修改任务清单会让问题仍留在旧 Epic 下——这是最常见的“看起来移过去了,实际没有”问题。 - 看板状态不会自动更新。 关闭问题不会将其设为
Done,除非启用了原生 Item closed 工作流。请明确设置状态,或一次性启用原生工作流(请参阅references/project-setup.md)。 - 按名称设置看板字段(gh >= 2.97)。
gh project item-edit <num> --owner @me --url <issue-url> --field Status --value "In Progress"会根据名称解析条目、字段和单选选项。--url必须是问题 URL,而非项目 URL。旧版gh以及不应重复执行查找操作的循环中,请使用 ID 形式(--id/--project-id/--field-id/--single-select-option-id);请参阅references/cli-and-graphql.md。 - 视图和启用工作流只需在 UI 中设置一次;其他操作都可脚本化。 没有 API 可以创建或重命名视图,也无法切换工作流。请在 UI 中操作一次(或复制模板),其余操作编写脚本完成。
- Type 和 Milestone 是问题元数据,不是项目字段。 请在问题上设置它们(
gh issue edit <n> --type Bug --milestone "v1.0");看板会将它们显示为内置列,用于分组和筛选,但gh project item-edit无法修改它们,而且它们不会出现在field-list中。问题类型仅适用于 org 仓库。请参阅references/types-and-milestones.md。 - 仓库角色和项目角色是两道独立的权限关卡。 仓库的 Write 权限不允许团队成员设置 Status 或 Priority;项目的 Write 权限也不允许他们添加标签或分配负责人。运行路线图的人员需要拥有仓库的 Triage 权限 + 项目的 Write 权限——而且没有
gh project子命令可用于项目访问权限(请使用 GraphQLupdateProjectV2Collaborators)。请参阅references/access-and-roles.md。
前置条件
- 仅支持 GitHub——Projects v2 没有对应的 GitLab 版本。
- 这里使用的原生问题标志(
--type、--milestone、--parent、--add-sub-issue)要求gh>= 2.94;较旧的gh需使用参考文档中的 REST 操作方案。gh>= 2.97 才支持基于名称的item-edit(规则 4)。 - 令牌范围决定哪些功能可用。
gh auth status可查看范围。gh project命令和任何projectV2GraphQL 操作都需要project范围(gh auth refresh -s project);只读查询只需read:project。如果没有所需范围,这些操作会因身份验证或权限错误而失败,尽管所有需要repo范围的功能都正常——这是经典的“项目功能似乎缺失”陷阱。问题、子问题、类型和里程碑使用常规的repo范围;访问组织所有的项目还需要read:org。 - 范围决定自动化能做什么;角色决定队友能做什么。 角色权限不足时,界面控件会直接隐藏,不会说明原因,因此看起来像是看板坏了(通过 API 执行相同调用则会失败,并返回 403,或隐藏资源的 404)。添加标签、指定负责人和子问题至少需要 Triage 角色;更改 Status/Priority 需要项目 Write 权限。授予团队权限需要经典令牌的
admin:org(细粒度令牌:成员关系需要组织Members: write,团队对仓库的授权需要仓库Administration: write),而默认的gh登录不包含这些权限(组织设置 PATCH 也接受repo)——此外还需要相应的调用者角色:更改成员关系需要组织所有者或团队维护者;将权限授予团队需要仓库管理员;更改项目协作者需要项目管理员(组织所有者拥有此权限)。参见references/access-and-roles.md。 - 项目通过
--owner下的编号寻址(@me或组织登录名)。仓库和项目的所有者可能不同。对于组织所有的项目,向--owner传入组织登录名;在 GraphQL 查询中使用organization(login: "ORG") { projectV2 },而不是viewer { projectV2 }(参见references/cli-and-graphql.md)。
模型
| 层级 | 含义 | 机制 |
|---|---|---|
| Epic | 大型工作项——标题为 Epic: ...、带有 epic 标签的问题 | gh issue create + epic 标签 |
| 子问题 | 归属于一个 Epic 的工作单元 | 原生父子链接(--parent / --add-sub-issue) |
| 类型 | 工作类型:Task / Bug / Feature(仅限组织仓库) | 原生问题类型(gh issue edit --type),而非标签 |
| 里程碑 | 有日期且可关闭的范围——一个发布或交付阶段,通常跨越多个 Epic | 仓库里程碑(gh issue edit --milestone);并同步到看板 |
| 看板状态 | 每个项目的位置及其优先级 | 项目字段:Status(Todo/In Progress/Done)、Priority(单选) |
每个问题都归属于某个 Epic(也可以自身就是 Epic)。优先级保存在项目的 Priority 字段中(通过 item-edit 设置),而工作类型保存在原生问题 Type 中——两者都不是标签。这样可将标签数量降至最低:唯一使用的标签是 epic(用于识别 Epic,以便筛选和分组;如果组织定义了自定义 Epic 问题类型,优先使用它,甚至可以去掉这个标签)。Epic 回答“这属于什么主题”;里程碑回答“这个范围何时交付”——一个问题通常两者兼有。Epic 视图显示树状结构;Upcoming 视图筛除 Done 项目,并按 Priority 排序。
操作(操作手册)
具体操作序列。{owner}/{repo} 由 gh 根据当前仓库填入;<num> 是项目编号。ID 的查找详情见 references/cli-and-graphql.md。
创建一个 Epic 和相关问题
# Epic issue (gh issue create prints the URL; the number is its last path segment)
epic=$(gh issue create --title "Epic: <name>" --label epic --body "<goal>"); epic=${epic##*/}
# Link existing issues as NATIVE sub-issues (flag repeats; on a partial GraphQL failure re-run -- it's a
# transient sub-issue burst limit, and already-linked children are unaffected)
gh issue edit $epic --add-sub-issue <existing#> --add-sub-issue <existing#>
# New work goes straight under the epic, typed and scoped at creation
# (--type is org-only: DROP it on personal repos or the whole command fails with 'type not found')
gh issue create --title "<task>" --type Task --milestone "<title>" --parent $epic --body "<detail>"
# Put the epic on the board; its children auto-join IF the native "Auto-add sub-issues" workflow is on
gh project item-add <num> --owner @me --url "$(gh issue view $epic --json url --jq .url)"
# (if that workflow is off, item-add each child's URL too)
将问题添加到现有 Epic
gh issue edit <epic> --add-sub-issue <child> # by number or URL; also re-parents if homed elsewhere
在不同 Epic 之间移动问题(更改父级——规则 2)
gh issue edit <child> --parent <newEpic> # replaces the old parent in one step
# then tidy any body bullets that referenced the old epic
分类并确定范围(Type + Milestone——规则 6)
gh issue edit <n> --type Bug # org repos only; Task/Bug/Feature (+ org customs)
gh issue edit <n> --milestone "v1.0" # by TITLE; --remove-milestone / --remove-type to unset
gh issue list --milestone "v1.0" --json number,title,state # -m takes a title or the milestone NUMBER
里程碑(创建、解析“当前”里程碑、结束一个范围)
“当前里程碑”=到期日期最早的未关闭里程碑——包括已过期的里程碑,因为它最紧急。“里程碑 N”=编号为 N 的里程碑(/milestone/N URL 路径段),绝不是“第 N 个未关闭的里程碑”。
# create (no gh subcommand -- REST)
gh api --method POST repos/{owner}/{repo}/milestones -f title="v1.0" -f due_on="2026-08-01T00:00:00Z" -f description="<scope>"
# current milestone (open only; undated ones sort last)
gh api repos/{owner}/{repo}/milestones --jq 'sort_by(.due_on // "9999-12-31") | first | {number, title, due_on}' --method GET
# close out the scope once nothing is left open in it
gh api repos/{owner}/{repo}/milestones/<N> --jq '{title, open_issues}' --method GET # expect open_issues: 0
gh api --method PATCH repos/{owner}/{repo}/milestones/<N> -f state=closed
开始处理/完成/设定优先级(看板 Status + Priority)
# Fields and options by name (gh >= 2.97); --url is the ISSUE's URL
url=$(gh issue view <issue> --json url --jq .url)
# pick up
gh project item-edit <num> --owner @me --url "$url" --field Status --value "In Progress"
# finish -- close the issue (pick ONE close form; the plain one means "completed"):
gh issue close <issue> # done as planned
gh issue close <issue> --reason "not planned" # abandoned
gh issue close <issue> --duplicate-of <original> # duplicate; links it natively to the original (gh >= 2.88)
# closing normally advances the board via the native "Item closed" workflow -- nothing more to do.
# ONLY IF that workflow is off, set Status manually:
gh project item-edit <num> --owner @me --url "$url" --field Status --value Done
# (re)prioritize
gh project item-edit <num> --owner @me --url "$url" --field Priority --value P1
授予队友看板工作权限
# repo side -- labels, assignees, apply milestones, sub-issue links (Triage, no code push; creating labels or milestones is Write)
gh api --method PUT orgs/<org>/teams/<team>/memberships/<user> -f role=member
gh api --method PUT orgs/<org>/teams/<team>/repos/{owner}/{repo} -f permission=triage
# project side -- Status, Priority, every field (no gh subcommand exists for this)
gh api graphql -f query='mutation($p:ID!,$t:ID!){ updateProjectV2Collaborators(input:{projectId:$p,
collaborators:[{teamId:$t, role:WRITER}]}){ collaborators(first:20){ nodes{ __typename } } } }' \
-f p=<projectId> -f t=<teamId>
# that payload echoes back only what you passed -- verify the team grant by reading it back; a per-user grant (userId in place of teamId) has no read, and the base role is UI-only
gh api graphql -f query='query($endCursor:String){ organization(login:"<org>"){ team(slug:"<team>"){ projectsV2(first:100, after:$endCursor, minPermissionLevel: WRITE){ nodes{ number } pageInfo{ hasNextPage endCursor } } } } }' --paginate --jq '.data.organization.team.projectsV2.nodes[].number' # <num> listed = Write or higher
# verify the repo side by role_name -- .permission reports a triage collaborator as "read"
gh api repos/{owner}/{repo}/collaborators/<user>/permission --jq .role_name --method GET
参考:
references/cli-and-graphql.md——完整命令集、item-edit的 ID 格式(使用field-list/item-list --format json获取 ID)、item-list --query筛选,以及用于路线图排序的updateProjectV2ItemPosition。references/sub-issues.md——原生关联标志、REST 回退方案(要求数据库 ID)、更改父项,以及每次请求约 25 项的批量限制。references/types-and-milestones.md——组织问题类型、里程碑 CRUD,以及完整的“当前里程碑”/“里程碑 N”约定。references/access-and-roles.md——完整介绍两道权限关卡、诊断队友受阻问题、读取项目协作者、刷新admin:org权限,以及组织设置 REST 接口接受但会静默忽略的内容。
设置(一次性)
参考:
references/project-setup.md——完整流程:创建 Project、添加Status/Priority(以及可选的Stage)字段、构建 Epic 和 Upcoming 视图(使用 UI——无 API)、启用原生工作流(Item added、Auto-add sub-issues、Item closed -> Done)、可选的模板复制快捷路径,以及现有代码库的迁移操作指南。
基本结构:
gh project create --owner @me --title "Roadmap"
gh project field-create <num> --owner @me --name "Priority" --data-type SINGLE_SELECT \
--single-select-options "P0,P1,P2,P3"
gh label create epic --color B60205 --description "Roadmap epic"
接下来,在 UI 中创建 Epic 和 Upcoming 视图,并切换 Settings -> Workflows 中的开关(这些功能没有 API)。
只读与写入分类
- 只读(可安全自动批准):
gh project list/view/field-list/item-list、GraphQL 读取查询、gh label list、gh issue list/view、里程碑读取(gh api repos/{owner}/{repo}/milestones)、问题类型读取(gh api orgs/{org}/issue-types)、权限读取(gh api repos/{owner}/{repo}/collaborators/<user>/permission、gh api orgs/{org}/teams/{team}/repos)——每个 REST 读取命令都以--method GET结尾,这是允许列表用于匹配的标志 - 写入(需要批准):
gh project create/copy/edit/link/field-create/item-add/item-edit/item-archive/item-delete、gh label create、gh issue create/edit(包括--type/--milestone/--parent/--add-sub-issue)、里程碑POST/PATCH/DELETE、子问题POST/DELETE、GraphQL 修改操作、权限授予(团队成员资格/仓库PUT、updateProjectV2Collaborators、PATCH /orgs/{org})
参考:只读
gh project模式和可选启用的写入命令集,请参阅references/allowlist.md。
关键注意事项
- 使用原生链接,而非检查清单——树结构由子议题链接构建;项目符号只是装饰(规则 1)。
- 通过更改父级来移动——
gh issue edit <child> --parent <newEpic>;仅编辑正文不会移动议题(规则 2)。 - REST 子议题接口使用数据库中的
id——如果改用gh api .../sub_issues,请通过--jq .id获取该值;议题编号无效(原生gh标志接受编号或 URL)。 item-edit --url接受议题 URL——项目由<num>和--owner指定,而其所有者可以与议题所属仓库的所有者不同。名称需要 gh >= 2.97;较旧版本的 gh 需要使用field-list --format json获取选项 id(规则 4)。- 视图和工作流开关只能通过 UI 操作——没有 API;操作一次即可(或复制模板)(规则 5)。
- 子议题变更每次请求最多约 25 项——较大的批次会触发
RESOURCE_LIMITS_EXCEEDED;包含多个--add-sub-issue的编辑也可能因相同限制而部分失败——可以安全地重新运行。 - 类型/里程碑不是项目字段——请在议题上设置,它们会同步显示在看板上;
item-edit无法设置这些内容,field-list也不会显示(规则 6)。类型仅适用于组织(在个人仓库中使用--type会显示type "..." not found; available types:——此时请改用标签)。 - “当前里程碑” = 未关闭议题中截止日期最早的里程碑(包括已逾期的);“里程碑 N” = 编号为 N 的里程碑,而不是第 N 个未关闭的里程碑(参见
references/types-and-milestones.md)。 - 访问权限分两道门槛——仓库的 Triage 权限用于标签/指派人/子议题,项目的 Write 权限用于状态/优先级。缺少角色时,UI 控件会直接隐藏,而不会说明原因;不过,通过 API 执行相同操作会返回授权错误。
.permission会错误地将拥有 Triage 权限的协作者报告为read,因此请通过.role_name核实(规则 7)。