Loading...
Loading...
GitHub Projects (v2) setup and management via gh CLI + GraphQL: organize a repo's issues into epics with native sub-issues, drive a board Status flow (Todo -> In Progress -> Done), set Project Priority, classify with native issue Types (Task/Bug/Feature) instead of labels, scope work with milestones (incl. resolving "current milestone"), and maintain an Epic + Upcoming roadmap. Use when setting up or managing a GitHub Project/roadmap, creating an epic with issues, adding or moving issues between epics, picking up or closing work on the board, (re)prioritizing, setting issue types, creating or closing milestones, enabling project workflows, or configuring gh project read-only allowlists. Not for PR workflows (git-pr), CI/CD status (git-ci), or commit messages (git-commit)
npx skill4agent add dmythro/agent-skills git-projectgh projectgh apigh project- [ ] #123gh issue edit <epic> --add-sub-issue <child>gh issue create --parent <epic>references/sub-issues.mdgh issue edit <child> --parent <newEpic>Donereferences/project-setup.mdgh project field-list <num> --owner @me --format jsonitem-editgh issue edit <n> --type Bug --milestone "v1.0"gh project item-editfield-listreferences/types-and-milestones.mdgh--type--milestone--parent--add-sub-issueghgh auth statusgh projectprojectV2projectgh auth refresh -s projectread:projectreporeporead:org--owner@me--ownerorganization(login: "ORG") { projectV2 }viewer { projectV2 }references/cli-and-graphql.md| Layer | What it is | Mechanism |
|---|---|---|
| Epic | A big work item -- an issue titled | |
| Sub-issue | A unit of work homed under exactly one epic | native parent/child link ( |
| Type | What kind of work: Task / Bug / Feature (org repos only) | native issue type ( |
| Milestone | A dated, closeable scope -- a release or delivery slice, often cross-epic | repo milestone ( |
| Board state | Where each item sits + its priority | Project fields: Status (Todo/In Progress/Done), Priority (single-select) |
Priorityitem-editepicEpic{owner}/{repo}<num>references/cli-and-graphql.md# 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)gh issue edit <epic> --add-sub-issue <child> # by number or URL; also re-parents if homed elsewheregh issue edit <child> --parent <newEpic> # replaces the old parent in one step
# then tidy any body bullets that referenced the old epicgh 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/milestone/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}'
# close out the scope once nothing is left open in it
gh api repos/{owner}/{repo}/milestones/<N> --jq '{title, open_issues}' # expect open_issues: 0
gh api --method PATCH repos/{owner}/{repo}/milestones/<N> -f state=closed# Discover the item id + field/option ids once (see references/cli-and-graphql.md), then:
# pick up
gh project item-edit --id <item> --project-id <proj> --field-id <statusField> --single-select-option-id <inProgress>
# 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 --id <item> --project-id <proj> --field-id <statusField> --single-select-option-id <done>
# (re)prioritize
gh project item-edit --id <item> --project-id <proj> --field-id <priorityField> --single-select-option-id <p1>Reference:-- full command set, gettingreferences/cli-and-graphql.md/<item>/field+option ids (<proj>/field-list), anditem-list --format jsonfor roadmap ordering.updateProjectV2ItemPosition-- native link flags, the REST fallback (database-id requirement), re-parenting, and the ~25/request batch limit.references/sub-issues.md-- org issue types, milestone CRUD, and the current-milestone / milestone-N conventions in full.references/types-and-milestones.md
Reference:-- end to end: create the Project, addreferences/project-setup.md/Status(and optionalPriority) fields, build the Epic and Upcoming views (UI -- no API), enable the native workflows (Item added, Auto-add sub-issues, Item closed -> Done), the optional template-copy fast-path, and the migration playbook for an existing repo.Stage
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"gh project list/view/field-list/item-listgh label listgh issue list/viewgh api repos/{owner}/{repo}/milestonesgh api orgs/{org}/issue-typesgh project create/copy/edit/link/field-create/item-add/item-edit/item-archive/item-deletegh label creategh issue create/edit--type/--milestone/--parent/--add-sub-issuePOSTPATCHDELETEPOSTDELETEReference: Seefor read-onlyreferences/allowlist.mdpatterns and the opt-in write set.gh project
gh issue edit <child> --parent <newEpic>idgh api .../sub_issues--jq .idghfield-list --format jsonitem-editRESOURCE_LIMITS_EXCEEDED--add-sub-issueitem-editfield-list--typetype "..." not found; available types:references/types-and-milestones.md