mcpField
G
git-project

git-project

github.com/dmythro开发7133 次安装6 天前更新
代码仓库

关于 git-project

git-project 是用于通过 GitHub Projects v2 管理仓库议题和路线图的技能,面向需要组织 Epic、拆分任务并推进看板的团队。它以原生父子议题关系和独立的项目状态字段维护结构与进度。

主要功能

  1. 01创建项目及路线图视图
  2. 02用原生子议题组织 Epic
  3. 03移动议题并调整优先级
  4. 04设置议题类型和里程碑
  5. 05更新项目状态字段
  6. 06管理仓库与项目访问权限

适用场景

  1. 01把零散议题整理为 Epic 路线图
  2. 02在 Epic 之间重新归属议题
  3. 03推进任务状态并设置优先级
  4. 04按交付范围分配和关闭里程碑

安装

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

$npx skills add https://github.com/dmythro/agent-skills --skill git-project

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

包含的文件

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

references/
access-and-roles.md
allowlist.md
cli-and-graphql.md
project-setup.md
sub-issues.md
types-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 命令设置自动批准模式

关键规则

这些都是容易踩的坑——每一条中,看似顺理成章的操作都会让结构出错。

  1. 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。
  2. 在 Epic 之间移动问题 = 重新设置原生父级关联。 只需一条命令:gh issue edit <child> --parent <newEpic>(会替换旧的父级),然后整理正文。只修改任务清单会让问题仍留在旧 Epic 下——这是最常见的“看起来移过去了,实际没有”问题。
  3. 看板状态不会自动更新。 关闭问题不会将其设为 Done,除非启用了原生 Item closed 工作流。请明确设置状态,或一次性启用原生工作流(请参阅 references/project-setup.md)。
  4. 按名称设置看板字段(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。
  5. 视图和启用工作流只需在 UI 中设置一次;其他操作都可脚本化。 没有 API 可以创建或重命名视图,也无法切换工作流。请在 UI 中操作一次(或复制模板),其余操作编写脚本完成。
  6. Type 和 Milestone 是问题元数据,不是项目字段。 请在问题上设置它们(gh issue edit <n> --type Bug --milestone "v1.0");看板会将它们显示为内置列,用于分组和筛选,但 gh project item-edit 无法修改它们,而且它们不会出现在 field-list 中。问题类型仅适用于 org 仓库。请参阅 references/types-and-milestones.md。
  7. 仓库角色和项目角色是两道独立的权限关卡。 仓库的 Write 权限不允许团队成员设置 Status 或 Priority;项目的 Write 权限也不允许他们添加标签或分配负责人。运行路线图的人员需要拥有仓库的 Triage 权限 + 项目的 Write 权限——而且没有 gh project 子命令可用于项目访问权限(请使用 GraphQL updateProjectV2Collaborators)。请参阅 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 命令和任何 projectV2 GraphQL 操作都需要 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. 使用原生链接,而非检查清单——树结构由子议题链接构建;项目符号只是装饰(规则 1)。
  2. 通过更改父级来移动——gh issue edit <child> --parent <newEpic>;仅编辑正文不会移动议题(规则 2)。
  3. REST 子议题接口使用数据库中的 id——如果改用 gh api .../sub_issues,请通过 --jq .id 获取该值;议题编号无效(原生 gh 标志接受编号或 URL)。
  4. item-edit --url 接受议题 URL——项目由 <num> 和 --owner 指定,而其所有者可以与议题所属仓库的所有者不同。名称需要 gh >= 2.97;较旧版本的 gh 需要使用 field-list --format json 获取选项 id(规则 4)。
  5. 视图和工作流开关只能通过 UI 操作——没有 API;操作一次即可(或复制模板)(规则 5)。
  6. 子议题变更每次请求最多约 25 项——较大的批次会触发 RESOURCE_LIMITS_EXCEEDED;包含多个 --add-sub-issue 的编辑也可能因相同限制而部分失败——可以安全地重新运行。
  7. 类型/里程碑不是项目字段——请在议题上设置,它们会同步显示在看板上;item-edit 无法设置这些内容,field-list 也不会显示(规则 6)。类型仅适用于组织(在个人仓库中使用 --type 会显示 type "..." not found; available types:——此时请改用标签)。
  8. “当前里程碑” = 未关闭议题中截止日期最早的里程碑(包括已逾期的);“里程碑 N” = 编号为 N 的里程碑,而不是第 N 个未关闭的里程碑(参见 references/types-and-milestones.md)。
  9. 访问权限分两道门槛——仓库的 Triage 权限用于标签/指派人/子议题,项目的 Write 权限用于状态/优先级。缺少角色时,UI 控件会直接隐藏,而不会说明原因;不过,通过 API 执行相同操作会返回授权错误。.permission 会错误地将拥有 Triage 权限的协作者报告为 read,因此请通过 .role_name 核实(规则 7)。

评论

支持 Markdown