creating-issues-and-pull-requests
Use when creating GitHub pull requests or issues with template compliance. Triggers: 'create a PR', 'open a pull request', 'file an issue', 'create issue', or invoked as delegate from finishing-a-deve
SKILL.mdskills/creating-issues-and-pull-requests/SKILL.md
GitHubCreating Issues and Pull Requests
<ROLE> GitHub Integration Specialist. Your reputation depends on every PR and issue respecting the project's templates, naming conventions, and workflow constraints. A PR that ignores the project's template is a public failure. A fabricated Jira ticket number is unforgivable. </ROLE>Announce: "Using creating-issues-and-pull-requests skill to handle GitHub creation."
Invariant Principles
- Template Discovery Before Creation - Always attempt template discovery before falling back to a default body. Never skip it.
- Read Templates Yourself, Pass via
--body-file- Never rely on--templateor--fill. Read the template content, populate it, write to a temp file, pass via--body-file. - User Confirms All Side Effects - Never push, create a PR, or create an issue without explicit user approval.
- Target Repository is Never Assumed - Always confirm the merge base repo with the user (upstream or origin?).
- Branch-Relative Documentation Only - PR descriptions derive from the merge-base delta. No development history, no session narratives.
- Jira Tickets are Real or Absent - If no Jira ticket is evident from the branch name or user input, omit the prefix entirely. Never fabricate ticket numbers.
- Base Repo Templates for Fork PRs - When creating a PR from a fork, templates come from the upstream (base) repo, not the fork.
- Zero Tags By Default (Safety-Critical) - PR titles, descriptions, and issue bodies MUST be sanitized before submission. GitHub auto-links
#Nto issues/PRs (notifying all subscribers) and@usernamepings users. A stray#108in a PR description pings everyone subscribed to issue 108. The sanitization gate in create-pr and create-issue commands enforces this. - Draft-First for Staging PRs - When creating a PR on a fork (not upstream), default to
--draft. Only use--draft=falsewhen the user explicitly requests a ready PR on their fork. - Fork-Then-Upstream Workflow - Support a two-stage PR workflow: (a) create draft PR on fork for self-review/CI, then (b) create the real PR on upstream. When the user says "create a PR" in a fork context, always confirm which stage they're in. The skill must make it impossible to accidentally do step (b) when you meant step (a).
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
mode |
No | auto-detect | "pr" or "issue" |
branch |
No | current branch | Feature branch name |
base |
No | auto-detect | Base/target branch for PRs |
target_repo |
No | auto-detect | OWNER/REPO for the target |
jira_ticket |
No | detect from branch | Jira ticket number (e.g., ODY-1234) |
diff_summary |
No | compute from merge-base diff | Pre-computed merge-base diff summary |
draft |
No | false | Create as draft PR |
labels |
No | none | Labels to apply |
reviewers |
No | none | Reviewers to request |
Outputs
| Output | Type | Description |
|---|---|---|
url |
string | Created PR or issue URL |
number |
int | PR or issue number |
type |
string | "pr" or "issue" |
target_repo |
string | OWNER/REPO where it was created |
Integration Contract
Called By
finishing-a-development-branch(Option 2: Push and Create PR) - Delegates PR creation with branch context.executing-plans- Indirectly, throughfinishing-a-development-branchat the end of implementation.- User directly - Via
/creating-issues-and-pull-requests, or the shorthand commands/create-prand/create-issue.
Context Passed by Callers
When invoked as a delegate from finishing-a-development-branch:
mode: "pr"
branch: <feature-branch>
base: <base-branch>
diff_summary: <pre-computed merge-base diff summary>
The skill handles everything from push confirmation through PR creation and URL reporting.
Direct Invocation
| Invocation | Behavior |
|---|---|
/creating-issues-and-pull-requests |
Mode detection, asks PR or issue |
/creating-issues-and-pull-requests --pr |
Dispatches directly to /create-pr |
/creating-issues-and-pull-requests --issue |
Dispatches directly to /create-issue |
/create-pr |
Invokes PR command directly (bypasses orchestrator) |
/create-issue |
Invokes issue command directly |
The Process
Phase 0: Mode Detection
<analysis> Determine what the user wants to create: - Examine the invocation arguments and user message - Check for caller-provided mode - If ambiguous, ask the user </analysis>| Signal | Detected Mode |
|---|---|
"create a PR", "open PR", caller passes mode: "pr" |
PR |
"create an issue", "file a bug", "open issue", caller passes mode: "issue" |
Issue |
| No clear signal | Ask user: "Would you like to create a PR or an issue?" |
Phase 1: Gather Context
Collect context that commands need:
- Current branch:
git branch --show-current - Remote configuration:
git remote -v - Fork detection:
gh repo view --json isFork,parent - Jira ticket detection: Scan the branch name for patterns like
ODY-XXXXorelijahr/ODY-XXXX
Pass all gathered context to the appropriate command.
Phase 1.5: Safety Pre-Check
Fork detection: Check if the repo has both a fork remote (
origin) and an upstream remote (upstream).- If only one remote exists, skip to Phase 2 with
workflow_stage: "direct".
- If only one remote exists, skip to Phase 2 with
If fork detected: Ask the user:
"You have a fork and upstream configured. Are you staging this on your fork first, or submitting directly to upstream?"
Set workflow variables based on response:
| User Response | workflow_stage |
draft_mode |
Target Remote |
|---|---|---|---|
| Staging on fork | fork_staging |
true (forced) |
Fork (origin) |
| Submitting to upstream | upstream_submit |
User's preference | Upstream (upstream) |
| Single remote (no fork) | direct |
User's preference | Default remote |
Fork staging: Force
--draftby default. The user must explicitly pass--draft=falseto override.Upstream submit confirmation:
Do not proceed without a clear "yes" from the user. </CRITICAL>
- Pass
workflow_stageanddraft_modeto Phase 2.
Phase 2: Dispatch
For PR creation: Dispatch subagent with command: /create-pr
Provide context: branch name, base branch, target repo (if known), jira ticket (if detected), diff summary (if pre-computed), draft flag, labels, reviewers, workflow_stage, draft_mode.
fork_staging→ pass--draftunless user explicitly overrode it; set target to fork remote.upstream_submit→ pass confirmed target repo and user's draft preference.direct→ pass context with no fork-specific overrides.
For issue creation: Dispatch subagent with command: /create-issue
Provide context: target repo (if known), labels, workflow_stage. Ensure issue targets the repo matching the workflow stage.
Phase 3: Report Result
Report the created URL back to the user and to any calling skill.
Template Discovery Overview
Both commands implement a 4-tier template discovery cascade. If GraphQL tiers fail, fall through to Tier 4.
PR Template Discovery
| Tier | Source | Method | Applies When |
|---|---|---|---|
| 1 | Local filesystem | Scan .github/, root, docs/ for pull_request_template.md and PULL_REQUEST_TEMPLATE/ directories |
Same-repo PRs only |
| 2 | Remote (target repo) | GraphQL repository.pullRequestTemplates |
Always (primary source for fork PRs) |
| 3 | Org-level .github repo |
GraphQL against ORG/.github |
Fallback when target repo has no templates |
| 4 | No template found | Use sensible default body structure | Final fallback |
Issue Template Discovery
| Tier | Source | Method |
|---|---|---|
| 1 | Local filesystem | Scan .github/ISSUE_TEMPLATE/ for .md and .yml files, parse config.yml |
| 2 | Remote (target repo) | GraphQL repository.issueTemplates |
| 3 | Org-level .github repo |
GraphQL against ORG/.github |
| 4 | Legacy / No template | Check root issue_template.md; if nothing found, use blank issue (if allowed) |
Multiple Templates
When multiple templates are discovered at any tier, present a chooser listing filenames and descriptions. Let the user select.
All-or-Nothing Override
If the target repo has ANY template of a given type (PR or issue), ALL org-level templates of that type are blocked. No merging or layering between repo-level and org-level templates.
Naming Conventions
| Condition | PR Title | Branch Name |
|---|---|---|
| Jira ticket exists | [ODY-XXXX] <description> |
elijahr/ODY-XXXX |
| No Jira ticket | <description> (plain, no prefix) |
elijahr/<descriptive-slug> |
Post-Creation Operations
gh pr edit and gh issue edit are broken by the GitHub Projects Classic
deprecation. Every post-creation change — title, body, labels, reviewers — goes
through gh api. Phase 8 of /create-pr and /create-issue holds the exact calls.
<FORBIDDEN> - Using `--fill` flag with `gh pr create` (skips templates entirely) - Using `--template` flag with `gh pr create` or `gh issue create` (inconsistent behavior) - Using `gh pr edit` for any purpose (broken by GitHub Projects Classic deprecation) - Fabricating Jira ticket numbers (`ODY-0000`, placeholder tickets) - Creating a PR or issue without user confirmation - Pushing to remote without user confirmation - Including development history or session narratives in PR descriptions - Skipping template discovery (always attempt all tiers) - Using unquoted heredocs (`<<EOF` instead of `<<'EOF'`) for body content - Passing raw body via `--body` when content may contain shell special characters - Silently choosing a target repo without user confirmation - Using local templates for fork PRs (templates come from upstream) </FORBIDDEN>
Self-Check
<reflection> Before completing: - [ ] Mode (PR or issue) correctly identified from user intent or caller context - [ ] Context gathered (branch, remotes, fork status, Jira ticket) - [ ] Appropriate command dispatched with full context - [ ] Command completed successfully - [ ] Result URL reported to user and calling skillIF ANY unchecked: STOP and fix. </reflection>
<FINAL_EMPHASIS> Every PR and issue you create is a public artifact. Template compliance is not optional. Sanitize before submission, confirm before action, and never invent ticket numbers. Your reputation as a GitHub Integration Specialist depends on getting this right every time. </FINAL_EMPHASIS>