GitHub + gh Workflow
Defaults & constraints:
- •Use
ghCLI for GitHub activity. - •Follow repository merge settings (squash/rebase/merge); do not enforce a merge strategy.
- •Never merge into the base branch via CLI; merges happen via the GitHub UI.
PR targeting (avoid searching):
- •If the user did not specify a PR URL/number, assume they mean the PR for the current branch in the current repo.
- •Resolve the PR number/URL with:
- •
gh prw --number - •
gh prw --url
- •
- •If
gh prwfails, ask for the PR URL (or use-R OWNER/REPOif the user clearly intends a different repo).
When NOT to use:
- •The user wants to draft PR/issue text only (draft-only): use the
github-compose-*skills. - •The user wants PR review feedback:
- •Initial pass (batch draft):
~/.agents/skills/github-pr-review-start/SKILL.md - •Reply to existing threads:
~/.agents/skills/github-pr-review-reply/SKILL.md - •One comment at a time:
~/.agents/skills/github-pr-review/SKILL.md
- •Initial pass (batch draft):
- •The user wants local git operations (status/diff/commit/rebase):
~/.agents/skills/git-workflow/SKILL.md. - •The user wants worktree management (create/switch/remove worktrees):
~/.agents/skills/w-workflow/SKILL.md.
Approvals:
- •Any GitHub side effect requires explicit approval unless the user instructed otherwise (create/edit PRs, comments, reviews, labels, assignees, milestones, merges, releases).
PR review side effects (draft / pending reviews):
- •Creating a PENDING (draft) PR review requires the reviews API. Omit
eventin:POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews - •Batch draft comments: include all inline review comments in the
commentsarray in that same request. - •Practical constraint: GitHub generally allows only one
PENDINGreview per user per PR. If you need to change bodies/anchors, delete the pending review and recreate it. - •Pending inline review comments are not practically editable via API; do not waste time trying to PATCH. Delete the pending review and recreate it with the corrected payload.
- •Do not try to attach comments to an already-created pending review via the PR
comments endpoint (it won’t accept
pull_request_review_id). If you need to change anchors/bodies, delete the pending review and recreate it. - •File-level review comments (
subject_type=file) are immediately visible; they are not part of a pending review. In practice, while you have a pending review, you may not be able to create additional file-level review comments from the same user. - •Arrays: prefer
gh api ... --input /path/to.jsonfor payloads containing arrays (avoids accidentally sending arrays as strings via-f/-F).
If explicitly asked to POST a batch as a draft (PENDING) review:
- •Create a single PR review in
PENDINGstate by omittingeventwhen calling:POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews - •Include all inline comments in the
commentsarray in that same request. - •Every inline comment must resolve to a valid diff anchor.
- •Prefer
position(diff-relative). Compute it from the PR’s unified diff. - •If a file has multiple hunks (or repeated target lines), create separate comments and compute the correct anchor per hunk/occurrence.
- •Prefer
- •Keep the review summary body empty unless the user explicitly wants a public summary.
After submitting, verify what actually posted:
- •The submitted review body is whatever you submit with the final event call. If you want a summary, include it explicitly when submitting (COMMENT/APPROVE/REQUEST_CHANGES).
- •For COMMENT/REQUEST_CHANGES, treat the body as required: always include it.
- •UI gotcha: switching the event type (e.g. Comment -> Approve) can drop the typed
summary text in some flows. For API-based submission, prevent this by always
sending the intended
bodywith the submit request. - •Count posted inline comments and reconcile anything missing; if needed, post a follow-up (non-batch) comment with leftover deep links.
Example (create a pending review with many draft comments):
cat > /tmp/review-payload.json <<'EOF'
{
"commit_id": "HEAD_SHA",
"body": "",
"comments": [
{ "path": "path/to/file.ts", "position": 6, "body": "Comment text.\n\nWdyt" },
{ "path": "path/to/file.ts", "position": 19, "body": "Another comment.\n\nWdyt" }
]
}
EOF
gh api repos/OWNER/REPO/pulls/NUM/reviews -X POST --input /tmp/review-payload.json
# Verify:
# - Confirm the review is PENDING:
# gh api repos/OWNER/REPO/pulls/NUM/reviews --jq '.[] | {id,state}'
# - Confirm pending review has N draft comments:
# gh api repos/OWNER/REPO/pulls/NUM/reviews/REVIEW_ID/comments --jq 'length'
# - Confirm visible PR review comments are still empty (until submission):
# gh api repos/OWNER/REPO/pulls/NUM/comments --jq 'length'
# Submit later (include body explicitly if you want a summary):
# gh api repos/OWNER/REPO/pulls/NUM/reviews/REVIEW_ID/events -X POST -f event=APPROVE -f body=$'Looks good.
#
# Wdyt'
Posting PR review comments (examples):
- •Use bash/zsh
$'...'so\nbecomes real line breaks. Do NOT send literal\n. - •Anchoring rules and when to deep-link vs inline comment live in
~/.agents/skills/github-pr-review/SKILL.md.
Inline review comment (line or range; supports GitHub suggestion blocks):
gh api repos/OWNER/REPO/pulls/NUM/comments \ -f body=$'Text.\n\n```suggestion\ncode\n```\n\nWdyt' \ -f commit_id=SHA -f path=FILE -f side=RIGHT -f line=LINE
For multi-line, add: -f start_line=START -f start_side=RIGHT.
File-level review comment (file-scoped, immediately visible):
gh api repos/OWNER/REPO/pulls/NUM/comments \ -f body=$'Text.\n\nWdyt' \ -f commit_id=SHA -f path=FILE -f subject_type=file
Reply in an existing review thread (no quote reply):
gh api repos/OWNER/REPO/pulls/comments/COMMENT_ID/replies \ -f body=$'Text.\n\nWdyt'
PR-level timeline comment (use sparingly):
gh pr comment NUM -b "<text>"
Or:
gh pr review NUM --comment -b "<text>"
PR creation:
- •Create PRs as draft by default.
- •Always ask which existing issue the PR should reference (do not invent issue numbers).
- •Ask the user whether the PR should
Closes #XorAddresses #Xbefore creating the PR. - •If there is no existing issue, stop and ask whether to create one; do NOT create issues unless the user explicitly instructs you to.
- •PR title is a human-readable change summary (not necessarily the Conventional Commit header).
- •Multiline bodies/comments: use bash/zsh
$'...'so\nbecomes real newlines. Do NOT rely on\\nescapes inside normal quotes when usinggh api -f body=.... - •Test plan is inferred from the change surface; run the smallest sufficient set of checks and record the commands/results in the PR.
- •Always propose labels/assignees/milestone/projects first and get explicit confirmation before applying any of them.
Composition (draft-only) guidance:
- •Draft PR bodies using:
- •General repos:
~/.agents/skills/github-compose-pr-general/SKILL.md - •Elastic/Kibana repos:
~/.agents/skills/github-compose-pr-elastic/SKILL.md
- •General repos:
- •Draft issue bodies using:
- •General repos:
~/.agents/skills/github-compose-issue-general/SKILL.md - •Elastic/Kibana repos:
~/.agents/skills/github-compose-issue-elastic/SKILL.md
- •General repos:
- •Label proposals for Elastic/Kibana (propose-only):
~/.agents/skills/elastic-kibana-labels-propose/SKILL.md - •Kibana Management ownership hints:
~/.agents/skills/kibana-management-ownership/SKILL.md
Do not add/modify repo .github/* templates unless the user explicitly asks.
Sub-issues API:
GitHub's sub-issue API creates real parent-child relationships (not tasklists).
Create hierarchy:
- •Create child issues first with full descriptions.
- •Get GraphQL IDs:
gh api graphql -f query='{ repository(owner:"org",name:"repo") { issue(number:N) { id } } }'
- •Link:
gh api graphql -f query="mutation { addSubIssue(input:{issueId:\"PARENT_ID\",subIssueId:\"CHILD_ID\"}) { issue { number } } }"
- •Verify:
gh api repos/:owner/:repo/issues/NUM/sub_issues
Mutations: addSubIssue, removeSubIssue, reprioritizeSubIssue