git-project について
git-project は GitHub Projects v2 でリポジトリの課題とロードマップを管理するスキルです。エピック、作業項目、ボードの進行を扱うチーム向けで、ネイティブな親子課題リンクと独立したプロジェクト項目で構造と状態を管理します。
主な機能
- 01プロジェクトとロードマップビューの設定
- 02ネイティブなサブ課題でエピックを整理
- 03課題の移動と優先度の調整
- 04課題タイプとマイルストーンの設定
- 05プロジェクトの状態項目を更新
- 06リポジトリとプロジェクトのアクセス管理
活用シーン
- 01個別の課題をエピックのロードマップに整理
- 02課題を別のエピックへ移動
- 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 プロジェクト管理
GitHub Project(v2)でリポジトリのIssueをエピックベースのロードマップに整理し、日々の運用を行うための主要スキルです。 セットアップ(プロジェクト、フィールド、ビュー、標準ワークフロー)と運用(サブIssueを含むエピックの作成、ステータスの管理、作業の移動、優先順位付け)を網羅します。gh project と gh api(RESTサブIssue+GraphQL)を使う、GitHub専用の手順です。
gh v2.103.2に対して検証済み(2026-10-27):ここで使用するすべてのghサブコマンドとフラグについて、まずv2.102.0(2026-09-30)の--helpで確認し、次に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をクローズすることも、このどちらにも影響しません。この2点を誤ると、構造が気づかないうちに崩れているのに、作業が完了したように見えてしまいます。このスキルを使えば、最初から正しい流れで進められます。
使用するタイミング
- プロジェクト/ロードマップをセットアップする -- Project、フィールド(Status、Priority)、EpicビューとUpcomingビューを作成し、標準ワークフローを有効にする
- エピックとIssueを作成する -- 「Issue Xのエピックを作って」「これらを1つのエピックにまとめて」
- 作業を起票/移動する -- Issueをエピックの配下に追加する、エピック間でIssueを移動する、新しい作業を追加する
- ボードを運用する -- Issueに着手する(-> In Progress)、Issueをクローズする(-> Done)、優先順位を付け直す
- 作業を分類する -- タイプラベルではなく、Issueの標準Type(Task/Bug/Feature)を設定する
- マイルストーンの範囲を設定する -- 成果物のマイルストーンを作成してIssueを割り当て、完了時にクローズする。「current milestone」/「milestone N」に対応する
- 既存リポジトリの未整理なIssueをこの構造に移行する
- アクセス権を付与する -- チームメイトがラベルの適用、担当者の割り当て、サブIssueのリンク、Status/Priorityの編集をできない
- ツールの許可リストを設定する -- 読み取り専用の
gh projectコマンドに対する自動承認パターンを設定する
重要なルール
ここには落とし穴があります。どれも、一見正しそうな操作をしても、構造が正しくならないケースです。
- エピックは、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を参照してください。 - イシューを別のエピックに移すには、ネイティブリンクの親を変更します。 コマンドは 1 つです。
gh issue edit <child> --parent <newEpic>(古い親を置き換えます)を実行してから、本文を整えます。箇条書きだけを編集しても、イシューは古いエピックの配下に残ります。これは「移動したように見えるが、実際には移動していない」という最もよくある見落としです。 - ボードの Status は自動では更新されません。 ネイティブの Item closed ワークフローが有効でない限り、イシューをクローズしても
Doneにはなりません。Status を明示的に設定するか、ネイティブワークフローを一度有効にしてください(references/project-setup.mdを参照)。 - ボードのフィールドは名前で設定します(gh >= 2.97)。
gh project item-edit <num> --owner @me --url <issue-url> --field Status --value "In Progress"を使うと、名前からアイテム、フィールド、単一選択のオプションを特定できます。--urlにはプロジェクトではなく、イシューの URL を指定します。ID 形式(--id/--project-id/--field-id/--single-select-option-id)は、古いghを使う場合や、ルックアップを繰り返さないループで使用します。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サブコマンドはありません(GraphQL のupdateProjectV2Collaboratorsを使用します)。references/access-and-roles.mdを参照してください。
前提条件
- GitHub のみ -- Projects v2 に GitLab 相当の機能はありません。
- ここで使用するネイティブな Issue フラグ(
--type、--milestone、--parent、--add-sub-issue)にはgh>= 2.94 が必要です。それ以前のghでは、参考資料にある REST API の手順に切り替えてください。名前ベースのitem-edit(ルール 4)にはgh>= 2.97 が必要です。 - トークンのスコープによって使用できる機能が決まります。
gh auth statusで確認できます。gh projectコマンドとprojectV2を使う GraphQL にはprojectスコープが必要です(gh auth refresh -s project)。読み取り専用のクエリならread:projectだけで十分です。このスコープがない場合、すべてのrepoスコープの機能は使えるのに、認証/権限エラーでこれらの機能だけ失敗します。これは「プロジェクト機能が見つからないように見える」という典型的な落とし穴です。Issue、サブ Issue、タイプ、マイルストーンは通常のrepoスコープで利用できます。組織所有のプロジェクトへのアクセスにはread:orgも必要です。 - スコープは自動化の可否を左右し、ロールはチームメイトの可否を左右します。 ロールが不足していると UI のコントロールが表示されず、理由も説明されないため、ボードが壊れているように見えます(同じ API 呼び出しは失敗し、403、またはリソースを隠す 404 が返ります)。ラベル/担当者/サブ Issue の操作にはトリアージ権限が最低限必要で、Status/Priority の操作にはプロジェクトの Write 権限が必要です。チームへの権限付与には、クラシックトークンでは
admin:orgが必要です(ファイングレインドトークンの場合、メンバーシップには組織のMembers: write、チームへのリポジトリ権限付与にはリポジトリのAdministration: writeが必要です)。これらはデフォルトのghログインには含まれません(組織設定への PATCH ではrepoも使用できます)。さらに、呼び出し元には適切なロールも必要です。メンバーシップの変更には組織オーナーまたはチームメンテナー、チームへの権限付与にはリポジトリの管理者、プロジェクトのコラボレーター変更にはプロジェクト管理者(組織オーナーにはこの権限があります)が必要です。references/access-and-roles.mdを参照してください。 - プロジェクトは、
--owner(@meまたは組織のログイン名)配下の 番号 で指定します。リポジトリとプロジェクトのオーナーは異なる場合があります。組織所有のプロジェクトでは、組織のログイン名を--ownerに渡し、GraphQL の読み取りではviewer { projectV2 }の代わりにorganization(login: "ORG") { projectV2 }を使用してください(references/cli-and-graphql.mdを参照)。
モデル
| レイヤー | 内容 | 仕組み |
|---|---|---|
| エピック | 大きな作業項目 -- Epic: ... というタイトルの Issue。epic ラベルを付けます | gh issue create + epic ラベル |
| サブ Issue | ちょうど 1 つのエピックに属する作業単位 | ネイティブな親子リンク(--parent / --add-sub-issue) |
| タイプ | 作業の種類:Task / Bug / Feature(組織のリポジトリのみ) | ラベルではなく、ネイティブな Issue タイプ(gh issue edit --type) |
| マイルストーン | 期限があり、完了として閉じられるスコープ -- リリースや提供単位。複数のエピックにまたがることもあります | リポジトリのマイルストーン(gh issue edit --milestone)。ボードにも反映されます |
| ボードの状態 | 各項目の位置と優先度 | プロジェクトのフィールド:Status(Todo/In Progress/Done)、Priority(単一選択) |
すべての Issue はエピックに属します(または、それ自体がエピックです)。優先度はプロジェクトの Priority フィールドで管理し(item-edit で設定)、種類はネイティブな Issue Type で管理します。どちらもラベルではありません。これにより、ラベルの乱立を最小限に抑えられます。使用するラベルは epic だけです(エピックの識別やフィルタリング/グループ化に使います。組織がカスタムの Epic Issue タイプを定義している場合は、そちらを優先し、このラベルも使わないでください)。エピックは「これはどのテーマに属するか」に答え、マイルストーンは「このスコープはいつリリースされるか」に答えます。通常、1 つの Issue は両方に属します。Epic ビューではツリーが表示され、Upcoming ビューでは Done が除外され、Priority 順に並べ替えられます。
操作(プレイブック)
具体的な手順です。{owner}/{repo} は現在のリポジトリから gh が補完します。<num> はプロジェクト番号です。ID の確認方法については references/cli-and-graphql.md を参照してください。
エピックと Issue を作成する
# 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)
既存のエピックに Issue を追加する
gh issue edit <epic> --add-sub-issue <child> # by number or URL; also re-parents if homed elsewhere
Issue を別のエピックに移動する(親の付け替え -- ルール 2)
gh issue edit <child> --parent <newEpic> # replaces the old parent in one step
# then tidy any body bullets that referenced the old epic
分類とスコープ設定(タイプ + マイルストーン -- ルール 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 形式(ID の確認にはfield-list/item-list --format jsonを使用)、item-list --queryによる絞り込み、ロードマップの並べ替えに使うupdateProjectV2ItemPosition。references/sub-issues.md-- ネイティブリンクのフラグ、REST の代替手段(データベース ID が必要)、親の付け替え、1 リクエストあたり約 25 件のバッチ上限。references/types-and-milestones.md-- 組織のイシュータイプ、マイルストーンの CRUD、「現在のマイルストーン」/「マイルストーン N」の規則の詳細。references/access-and-roles.md-- 2 つのゲートの詳細、チームメイトがブロックされている場合の診断、プロジェクトのコラボレーターの確認、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 API のサブイシューにはデータベースの
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)。
- サブイシューの変更は 1 リクエストあたり約 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を参照)。 - アクセス権は 2 つの関門で決まります -- ラベル、担当者、サブイシューにはリポジトリの Triage 権限、Status と Priority にはプロジェクトの Write 権限が必要です。必要なロールがない場合、UI コントロールは理由を示さずに非表示になりますが、同じ操作を API 経由で実行すると認可エラーが返されます。
.permissionは Triage 権限を持つコラボレーターをreadと誤って表示するため、.role_nameで確認してください(ルール 7)。