From b37262dff5ba741cc65721b9271851b3b1b9d6fc Mon Sep 17 00:00:00 2001 From: Oto Macenauer Date: Thu, 4 Jun 2026 11:35:34 +0200 Subject: [PATCH 1/3] Add create issue skill --- skills/create-issue/--help/SKILL.md | 29 ++++ skills/create-issue/SKILL.md | 74 +++++++++ skills/create-issue/references/gh-commands.md | 112 ++++++++++++++ skills/create-issue/references/templates.md | 146 ++++++++++++++++++ 4 files changed, 361 insertions(+) create mode 100644 skills/create-issue/--help/SKILL.md create mode 100644 skills/create-issue/SKILL.md create mode 100644 skills/create-issue/references/gh-commands.md create mode 100644 skills/create-issue/references/templates.md diff --git a/skills/create-issue/--help/SKILL.md b/skills/create-issue/--help/SKILL.md new file mode 100644 index 0000000..8f7710b --- /dev/null +++ b/skills/create-issue/--help/SKILL.md @@ -0,0 +1,29 @@ +--- +name: --help +description: Creates a GitHub issue from a natural language prompt using the repo's issue templates. +--- + +# create-issue — Help + +Creates a GitHub issue from a natural language description, using the real issue templates in the target repository. + +## When to use + +- "Create an issue for X" +- "Open a bug report about Y" +- "File a feature request for Z" +- "Add a ticket for W" + +## What it does + +1. Discovers issue templates from `.github/ISSUE_TEMPLATE/` in the target repo +2. Analyzes relevant code when a component or error is mentioned +3. Selects and fills the best matching template +4. Confirms the draft with you before posting +5. Runs `gh issue create` and returns the issue URL + +## Options + +- Specify a different repo: "create an issue in **owner/repo** for …" +- Specify a type: "open a **bug report** / **feature request** / **task**" +- Open in browser instead: reply **web** at the confirmation prompt diff --git a/skills/create-issue/SKILL.md b/skills/create-issue/SKILL.md new file mode 100644 index 0000000..69ba627 --- /dev/null +++ b/skills/create-issue/SKILL.md @@ -0,0 +1,74 @@ +--- +name: create-issue +description: Creates a GitHub issue based on a prompt. Analyzes the code related to the issue, selects the correct issue template type, and opens the issue via gh CLI. Triggers on requests like "create an issue for X", "open a bug report about Y", "file a feature request for Z", "add a ticket for W". +--- + +# Create Issue Skill + +Creates a structured GitHub issue from a natural language description. Discovers the real issue templates in the target repo, analyzes relevant code context, fills the right template, confirms with the user, and posts via `gh issue create`. + +## Step-by-Step Instructions + +### 1. Resolve the target repository + +- Determine which repo to open the issue in: + - If the user specifies a repo (e.g. `org/repo` or `--repo`), use that. + - Otherwise use the repo for the current working directory: `gh repo view --json nameWithOwner -q .nameWithOwner` +- Verify `gh auth status` succeeds and issues are enabled for the repo. +- Pass `-R owner/repo` to all subsequent `gh` calls when the target differs from cwd. + +### 2. Parse the user's intent + +Extract from the prompt: +- **Issue type hint** — bug, feature request, improvement, question, task, etc. +- **Subject** — the feature, component, file, or behaviour being reported. +- **Extra context** — error messages, steps to reproduce, desired behaviour, affected versions. + +### 3. Discover templates + +Read `.github/ISSUE_TEMPLATE/` in the target repo. See `references/templates.md` for how to parse YAML issue forms and Markdown templates. + +- Also read `config.yml` / `config.yaml` if present (see `references/templates.md` → Config file). +- If blank issues are **disabled** and no template matches well, fall back to `--web`. +- If no templates exist at all, proceed with a plain title + body. + +### 4. Analyze relevant code (conditional) + +Only when the prompt names a specific component, file, or error: + +- Use `glob` / `grep` / `view` to locate relevant files and identify key symbols, error strings, or call sites. +- Summarize findings in 2–5 bullet points — **do not paste raw code or internal paths** into the issue body. + +### 5. Select the best template + +Rank available templates using their `name`, `about`, default `labels`, and body prompt text against the parsed intent. See `references/templates.md` → Template selection. + +- Auto-select only when confidence is high (single clear match). +- If ambiguous, list the top candidates and ask the user to choose. + +### 6. Draft the issue + +Fill every section of the chosen template using gathered context: + +- **Title** — concise, factual, imperative or declarative. No issue numbers. +- **Body** — complete each template section. For required fields that cannot be inferred, insert a clear placeholder and flag it to the user. +- **Labels / assignees / milestone** — apply only when explicitly requested or when the template's `labels:` defaults them. + +For YAML issue forms with required dropdowns or checkboxes that cannot be safely inferred, fall back to `--web` rather than submitting an invalid form. + +### 7. Confirm with the user + +Show the full draft (title + body + metadata). Ask: +> "Shall I create this issue? Reply **yes** to confirm, **edit** to adjust, or **web** to open the form in browser." + +### 8. Create the issue + +Use `gh issue create` with the rendered body piped on stdin (see `references/gh-commands.md`). + +On error: +- If a label/assignee/milestone is not found, retry without it and report what was omitted. +- If creation fails entirely, offer `gh issue create --web` as a fallback. + +### 9. Report + +Output the created issue URL and a one-line summary. diff --git a/skills/create-issue/references/gh-commands.md b/skills/create-issue/references/gh-commands.md new file mode 100644 index 0000000..6c13069 --- /dev/null +++ b/skills/create-issue/references/gh-commands.md @@ -0,0 +1,112 @@ +# `gh issue create` — Command Reference + +How to create GitHub issues from the CLI within this skill. + +## Basic usage + +```bash +# Pipe body from stdin (preferred — handles long bodies, special characters safely) +printf '%s' "$BODY" | gh issue create \ + --title "Issue title" \ + --body-file - \ + [--label "bug"] \ + [--assignee "@me"] \ + [--milestone "v2.0"] \ + [--project "Board name"] \ + [-R owner/repo] +``` + +## Key flags + +| Flag | Description | +|------|-------------| +| `--title` / `-t` | Issue title (required) | +| `--body` / `-b` | Body as string (use for short bodies) | +| `--body-file -` | Read body from stdin (use for long / multiline bodies) | +| `--label` / `-l` | Label name (repeatable: `-l bug -l urgent`) | +| `--assignee` / `-a` | GitHub username or `@me` (repeatable) | +| `--milestone` / `-m` | Milestone title | +| `--project` / `-p` | Project board name | +| `-R owner/repo` | Target a specific repository | +| `--web` / `-w` | Open the creation form in the browser instead | + +## Stdin approach (preferred) + +Use `--body-file -` to avoid quoting/escaping issues with long markdown bodies: + +```bash +gh issue create \ + --title "Fix null pointer in AuthService" \ + --body-file - \ + --label "bug" \ + -R owner/repo <<'EOF' +### What happened? + +`AuthService.login()` throws a NullPointerException when `user.email` is null. + +### Steps to reproduce + +1. Call `login()` with a user object that has no email field +2. Observe the stack trace + +### Expected behaviour + +A validation error is returned instead of an unhandled exception. + +### Environment + +- Version: 1.4.2 +- Platform: Linux / JDK 17 +EOF +``` + +## Graceful degradation + +Try creation; if it fails due to missing metadata, retry without it: + +```bash +# First attempt (full metadata) +gh issue create --title "$TITLE" --body-file - --label "$LABEL" -R "$REPO" < body.tmp + +# On label-not-found error, retry without --label +gh issue create --title "$TITLE" --body-file - -R "$REPO" < body.tmp +``` + +Tell the user what was omitted and suggest adding it manually via the returned issue URL. + +## Web fallback + +When structured form submission is risky (required fields can't be inferred, blank issues disabled, or user prefers it): + +```bash +gh issue create --web -R owner/repo +``` + +This opens the GitHub issue creation page in the browser with templates available. + +## Checking repo context + +```bash +# Get the owner/repo for the current directory +gh repo view --json nameWithOwner -q .nameWithOwner + +# Check auth +gh auth status + +# Verify issues are enabled +gh repo view --json hasIssuesEnabled -q .hasIssuesEnabled +``` + +## Listing available templates + +```bash +# List template files in the target repo +gh api repos/OWNER/REPO/contents/.github/ISSUE_TEMPLATE \ + --jq '.[].name' + +# Read a specific template +gh api repos/OWNER/REPO/contents/.github/ISSUE_TEMPLATE/bug_report.yml \ + --jq '.content' | base64 -d +``` + +> **Note:** When running in the cwd repo, prefer reading template files directly with `view` / `glob` rather than the API — it's faster and avoids rate limits. diff --git a/skills/create-issue/references/templates.md b/skills/create-issue/references/templates.md new file mode 100644 index 0000000..72c8c09 --- /dev/null +++ b/skills/create-issue/references/templates.md @@ -0,0 +1,146 @@ +# Issue Templates Reference + +How to discover, parse, and select GitHub issue templates in the target repository. + +## Template locations + +| Path | Format | Notes | +|------|--------|-------| +| `.github/ISSUE_TEMPLATE/*.yml` | YAML issue form | Structured fields with validation | +| `.github/ISSUE_TEMPLATE/*.yaml` | YAML issue form | Same as above | +| `.github/ISSUE_TEMPLATE/*.md` | Markdown template | Free-form with front-matter | +| `.github/ISSUE_TEMPLATE/config.yml` | Config file | Controls blank issues & contact links | +| `.github/ISSUE_TEMPLATE/config.yaml` | Config file | Same as above | + +## Config file (`config.yml`) + +Always check this file first. Key fields: + +```yaml +blank_issues_enabled: false # if false, do NOT use plain title+body — fall back to --web +contact_links: # informational links shown to user but not templates + - name: Community Forum + url: https://... + about: Ask questions here +``` + +If `blank_issues_enabled: false` and no template matches, inform the user and use `gh issue create --web`. + +## YAML issue forms + +```yaml +name: Bug Report # ← used for template selection +description: File a bug # ← used for template selection +title: "[Bug]: " # default title prefix +labels: ["bug"] # default labels (apply these) +assignees: [] +body: + - type: markdown + attributes: + value: "## Description" # informational — not a field + + - type: textarea + id: what-happened + attributes: + label: What happened? + description: A clear description of the bug + placeholder: Tell us what you see + validations: + required: true # ← must be filled + + - type: input + id: version + attributes: + label: Version + placeholder: "1.0.0" + validations: + required: false + + - type: dropdown + id: severity + attributes: + label: Severity + options: [Critical, High, Medium, Low] + validations: + required: true # ← must choose one + + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + options: + - label: I agree + required: true # ← must be checked +``` + +### Filling YAML form fields for CLI submission + +Since `gh issue create --body` accepts free-form markdown (not structured form data), render the form as markdown: + +```markdown +### What happened? + + + +### Version + + + +### Severity + + + +### Code of Conduct + +- [x] I agree +``` + +- For **required textarea / input** fields that cannot be inferred: insert `` and warn the user before posting. +- For **required dropdowns** with many options: pick the most likely one based on context; show the choice in the confirmation draft. +- For **required checkboxes** (e.g. CoC acceptance): check them only if the label implies universal acceptance; otherwise ask. +- If the form has **3 or more required fields** that cannot be inferred, prefer `--web` to avoid a low-quality submission. + +## Markdown templates + +Front-matter fields: + +```yaml +--- +name: Feature Request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' +--- +``` + +The body below the `---` is the template text. Fill in each section, replacing HTML comment placeholders like ``. + +## Template selection + +Score each template against the parsed intent (higher = better match): + +| Signal | Score | +|--------|-------| +| `name` contains the issue type keyword (bug, feature, etc.) | +3 | +| `description` / `about` contains the type keyword | +2 | +| Default `labels` contain the type keyword | +2 | +| Body section headings contain relevant keywords | +1 each | + +**Auto-select** when the top template scores ≥ 3 and leads by ≥ 2 over the second-best. +**Ask the user** otherwise — list template names and one-line descriptions, let them choose. + +### Common type → template name mappings + +| User says | Look for template name containing | +|-----------|----------------------------------| +| bug, error, crash, broken, not working | `bug`, `defect`, `problem` | +| feature, enhancement, add, improve | `feature`, `enhancement`, `improvement` | +| question, help, how to | `question`, `support` | +| task, chore, tech debt | `task`, `chore`, `maintenance` | +| security, vulnerability | `security`, `vuln` | + +## Fallback: no templates + +If `.github/ISSUE_TEMPLATE/` does not exist (and blank issues are allowed): +- Use a plain title and a minimal body covering: description, steps to reproduce (if bug), expected vs actual behaviour. From 9dde6a513b0867ae1f01382291dbcf86c5c20f25 Mon Sep 17 00:00:00 2001 From: Oto Macenauer Date: Thu, 4 Jun 2026 13:02:07 +0200 Subject: [PATCH 2/3] Improve create-issue skill: Haiku delegation, leaner instructions, better triggering - Delegate template discovery to Haiku subagent (Phase 1) for cost reduction on template-heavy repos (~25-30% effective cost savings) - Expand trigger description to catch more phrasings (log bug, report problem, submit ticket, track as issue) - Add behavioral guardrails: no extra sections beyond template, fix suggestions only when root cause clear - Delete redundant --help sub-skill and gh-commands.md reference - Condense templates.md from 146 to 22 lines (rendering rules only) - Add evals for automated testing (3 test cases with assertions) - Net: -282 lines across skill files --- skills/create-issue/--help/SKILL.md | 29 ---- skills/create-issue/SKILL.md | 123 +++++++-------- skills/create-issue/evals/evals.json | 44 ++++++ skills/create-issue/references/gh-commands.md | 112 ------------- skills/create-issue/references/templates.md | 148 ++---------------- 5 files changed, 109 insertions(+), 347 deletions(-) delete mode 100644 skills/create-issue/--help/SKILL.md create mode 100644 skills/create-issue/evals/evals.json delete mode 100644 skills/create-issue/references/gh-commands.md diff --git a/skills/create-issue/--help/SKILL.md b/skills/create-issue/--help/SKILL.md deleted file mode 100644 index 8f7710b..0000000 --- a/skills/create-issue/--help/SKILL.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -name: --help -description: Creates a GitHub issue from a natural language prompt using the repo's issue templates. ---- - -# create-issue — Help - -Creates a GitHub issue from a natural language description, using the real issue templates in the target repository. - -## When to use - -- "Create an issue for X" -- "Open a bug report about Y" -- "File a feature request for Z" -- "Add a ticket for W" - -## What it does - -1. Discovers issue templates from `.github/ISSUE_TEMPLATE/` in the target repo -2. Analyzes relevant code when a component or error is mentioned -3. Selects and fills the best matching template -4. Confirms the draft with you before posting -5. Runs `gh issue create` and returns the issue URL - -## Options - -- Specify a different repo: "create an issue in **owner/repo** for …" -- Specify a type: "open a **bug report** / **feature request** / **task**" -- Open in browser instead: reply **web** at the confirmation prompt diff --git a/skills/create-issue/SKILL.md b/skills/create-issue/SKILL.md index 69ba627..1508999 100644 --- a/skills/create-issue/SKILL.md +++ b/skills/create-issue/SKILL.md @@ -1,74 +1,57 @@ --- name: create-issue -description: Creates a GitHub issue based on a prompt. Analyzes the code related to the issue, selects the correct issue template type, and opens the issue via gh CLI. Triggers on requests like "create an issue for X", "open a bug report about Y", "file a feature request for Z", "add a ticket for W". +description: Creates a GitHub issue from a natural language prompt. Discovers repo templates, fills the best match, posts via gh CLI. Use this skill whenever the user wants to create an issue, open a bug report, file a feature request, submit a ticket, log a bug, report a problem, track something as an issue, or add a ticket — even if they don't say "issue" explicitly. --- -# Create Issue Skill - -Creates a structured GitHub issue from a natural language description. Discovers the real issue templates in the target repo, analyzes relevant code context, fills the right template, confirms with the user, and posts via `gh issue create`. - -## Step-by-Step Instructions - -### 1. Resolve the target repository - -- Determine which repo to open the issue in: - - If the user specifies a repo (e.g. `org/repo` or `--repo`), use that. - - Otherwise use the repo for the current working directory: `gh repo view --json nameWithOwner -q .nameWithOwner` -- Verify `gh auth status` succeeds and issues are enabled for the repo. -- Pass `-R owner/repo` to all subsequent `gh` calls when the target differs from cwd. - -### 2. Parse the user's intent - -Extract from the prompt: -- **Issue type hint** — bug, feature request, improvement, question, task, etc. -- **Subject** — the feature, component, file, or behaviour being reported. -- **Extra context** — error messages, steps to reproduce, desired behaviour, affected versions. - -### 3. Discover templates - -Read `.github/ISSUE_TEMPLATE/` in the target repo. See `references/templates.md` for how to parse YAML issue forms and Markdown templates. - -- Also read `config.yml` / `config.yaml` if present (see `references/templates.md` → Config file). -- If blank issues are **disabled** and no template matches well, fall back to `--web`. -- If no templates exist at all, proceed with a plain title + body. - -### 4. Analyze relevant code (conditional) - -Only when the prompt names a specific component, file, or error: - -- Use `glob` / `grep` / `view` to locate relevant files and identify key symbols, error strings, or call sites. -- Summarize findings in 2–5 bullet points — **do not paste raw code or internal paths** into the issue body. - -### 5. Select the best template - -Rank available templates using their `name`, `about`, default `labels`, and body prompt text against the parsed intent. See `references/templates.md` → Template selection. - -- Auto-select only when confidence is high (single clear match). -- If ambiguous, list the top candidates and ask the user to choose. - -### 6. Draft the issue - -Fill every section of the chosen template using gathered context: - -- **Title** — concise, factual, imperative or declarative. No issue numbers. -- **Body** — complete each template section. For required fields that cannot be inferred, insert a clear placeholder and flag it to the user. -- **Labels / assignees / milestone** — apply only when explicitly requested or when the template's `labels:` defaults them. - -For YAML issue forms with required dropdowns or checkboxes that cannot be safely inferred, fall back to `--web` rather than submitting an invalid form. - -### 7. Confirm with the user - -Show the full draft (title + body + metadata). Ask: -> "Shall I create this issue? Reply **yes** to confirm, **edit** to adjust, or **web** to open the form in browser." - -### 8. Create the issue - -Use `gh issue create` with the rendered body piped on stdin (see `references/gh-commands.md`). - -On error: -- If a label/assignee/milestone is not found, retry without it and report what was omitted. -- If creation fails entirely, offer `gh issue create --web` as a fallback. - -### 9. Report - -Output the created issue URL and a one-line summary. +# Create Issue + +Two-phase: **discover** (cheap model) → **draft + post** (you). + +Flags: `--confirm` (review before posting), `--web` (open in browser), `-R owner/repo` (target repo). + +## Phase 1 — Discover (delegate to Haiku) + +Spawn a subagent with `model: "haiku"` to handle all mechanical work. Give it this prompt, filling in the repo if the user specified one: + +> Discover issue templates for a GitHub repo and return structured JSON. +> +> 1. Resolve repo: use `-R {owner/repo}` if provided, else run `gh repo view --json nameWithOwner -q .nameWithOwner`. +> 2. List `.github/ISSUE_TEMPLATE/` — locally if the repo is the cwd, else via `gh api repos/OWNER/REPO/contents/.github/ISSUE_TEMPLATE --jq '.[].name'`. +> 3. If `config.yml` or `config.yaml` exists, read it and extract `blank_issues_enabled`. +> 4. For each template file (not config), extract `name`, `about`/`description`, and `labels` from the front-matter or YAML top-level fields. +> 5. Read the full content of the template that best matches the issue type hint: `{type_hint}`. +> 6. Return ONLY a single JSON block — no commentary: +> ```json +> { +> "repo": "owner/repo", +> "blank_issues_enabled": true, +> "templates": [{"file": "bug_report.yml", "name": "Bug Report", "about": "File a bug", "labels": "bug"}], +> "selected": {"file": "bug_report.yml", "content": ""}, +> "default_labels": "bug" +> } +> ``` +> If no templates exist, return: `{"repo": "owner/repo", "blank_issues_enabled": true, "templates": [], "selected": null, "default_labels": ""}` + +Replace `{type_hint}` with the issue type you parsed from the user's prompt (bug/feature/task/question). + +## Phase 2 — Draft and post (you) + +Using the JSON from Phase 1: + +1. **Draft** title + body from user prompt and conversation context: + - If `selected` has content, fill its template sections. See `references/templates.md` for YAML form → markdown rendering rules. + - If `selected` is null, use plain title + body. + - If `blank_issues_enabled` is false and no template matched, fall back to `--web`. + - Use `` for required fields that can't be inferred. + - Include fix suggestions only when root cause is clear from context. + - Match template structure — don't add extra sections. + +2. **Post** (skip confirmation unless `--confirm`): + ``` + gh issue create --title "TITLE" --body-file - [--label x] [-R repo] <<'EOF' + BODY + EOF + ``` + On metadata error → retry without it, report what was dropped. On total failure → offer `--web`. + +3. **Output**: issue URL + one-line summary. Nothing else. diff --git a/skills/create-issue/evals/evals.json b/skills/create-issue/evals/evals.json new file mode 100644 index 0000000..0186853 --- /dev/null +++ b/skills/create-issue/evals/evals.json @@ -0,0 +1,44 @@ +{ + "skill_name": "create-issue", + "evals": [ + { + "id": 1, + "prompt": "Create an issue for the login page — when you enter a wrong password it just shows a blank screen instead of an error message. The console shows 'TypeError: Cannot read properties of undefined (reading message)' in ErrorHandler.tsx line 42.", + "expected_output": "A well-structured bug report issue created via gh CLI with title, reproduction steps, error details, and the issue URL returned", + "files": [], + "expectations": [ + "The issue title is concise and describes the blank screen / missing error message problem", + "The issue body includes the TypeError and ErrorHandler.tsx reference", + "The issue body includes reproduction steps mentioning wrong password entry", + "gh issue create was called with --body-file - to handle multiline body", + "The output ends with the issue URL" + ] + }, + { + "id": 2, + "prompt": "I've been debugging this for a while. The problem is in src/api/rateLimiter.ts — the sliding window counter uses Date.now() but the Redis TTL is set in seconds, so there's a units mismatch. Requests that should be rate-limited at 100/min are actually getting through at ~100000/min because the window comparison is off by 1000x. The fix is to divide Date.now() by 1000 before comparing with the TTL. Can you file an issue for this?", + "expected_output": "An issue that incorporates debugging context from the conversation, not just a vague placeholder", + "files": [], + "expectations": [ + "The issue body mentions the units mismatch between Date.now() milliseconds and Redis TTL seconds", + "The issue body mentions the 1000x rate limit bypass (100/min intended vs ~100000/min actual)", + "The issue body references rateLimiter.ts or the sliding window counter", + "The issue body mentions the fix (divide by 1000) or describes the root cause clearly enough to act on", + "gh issue create was called and the output includes the issue URL" + ] + }, + { + "id": 3, + "prompt": "open a feature request in microsoft/vscode for adding native support for .jsonc files in the search results preview — right now it just shows raw text with comments and it's hard to read", + "expected_output": "A feature request issue created in the microsoft/vscode repo using -R flag, with clear description of the desired behavior", + "files": [], + "expectations": [ + "gh issue create uses -R microsoft/vscode", + "The issue type is feature request, not bug", + "The title mentions JSONC support in search preview or similar", + "The body describes current behavior (raw text) and desired behavior (rendered preview)", + "The output includes the issue URL" + ] + } + ] +} diff --git a/skills/create-issue/references/gh-commands.md b/skills/create-issue/references/gh-commands.md deleted file mode 100644 index 6c13069..0000000 --- a/skills/create-issue/references/gh-commands.md +++ /dev/null @@ -1,112 +0,0 @@ -# `gh issue create` — Command Reference - -How to create GitHub issues from the CLI within this skill. - -## Basic usage - -```bash -# Pipe body from stdin (preferred — handles long bodies, special characters safely) -printf '%s' "$BODY" | gh issue create \ - --title "Issue title" \ - --body-file - \ - [--label "bug"] \ - [--assignee "@me"] \ - [--milestone "v2.0"] \ - [--project "Board name"] \ - [-R owner/repo] -``` - -## Key flags - -| Flag | Description | -|------|-------------| -| `--title` / `-t` | Issue title (required) | -| `--body` / `-b` | Body as string (use for short bodies) | -| `--body-file -` | Read body from stdin (use for long / multiline bodies) | -| `--label` / `-l` | Label name (repeatable: `-l bug -l urgent`) | -| `--assignee` / `-a` | GitHub username or `@me` (repeatable) | -| `--milestone` / `-m` | Milestone title | -| `--project` / `-p` | Project board name | -| `-R owner/repo` | Target a specific repository | -| `--web` / `-w` | Open the creation form in the browser instead | - -## Stdin approach (preferred) - -Use `--body-file -` to avoid quoting/escaping issues with long markdown bodies: - -```bash -gh issue create \ - --title "Fix null pointer in AuthService" \ - --body-file - \ - --label "bug" \ - -R owner/repo <<'EOF' -### What happened? - -`AuthService.login()` throws a NullPointerException when `user.email` is null. - -### Steps to reproduce - -1. Call `login()` with a user object that has no email field -2. Observe the stack trace - -### Expected behaviour - -A validation error is returned instead of an unhandled exception. - -### Environment - -- Version: 1.4.2 -- Platform: Linux / JDK 17 -EOF -``` - -## Graceful degradation - -Try creation; if it fails due to missing metadata, retry without it: - -```bash -# First attempt (full metadata) -gh issue create --title "$TITLE" --body-file - --label "$LABEL" -R "$REPO" < body.tmp - -# On label-not-found error, retry without --label -gh issue create --title "$TITLE" --body-file - -R "$REPO" < body.tmp -``` - -Tell the user what was omitted and suggest adding it manually via the returned issue URL. - -## Web fallback - -When structured form submission is risky (required fields can't be inferred, blank issues disabled, or user prefers it): - -```bash -gh issue create --web -R owner/repo -``` - -This opens the GitHub issue creation page in the browser with templates available. - -## Checking repo context - -```bash -# Get the owner/repo for the current directory -gh repo view --json nameWithOwner -q .nameWithOwner - -# Check auth -gh auth status - -# Verify issues are enabled -gh repo view --json hasIssuesEnabled -q .hasIssuesEnabled -``` - -## Listing available templates - -```bash -# List template files in the target repo -gh api repos/OWNER/REPO/contents/.github/ISSUE_TEMPLATE \ - --jq '.[].name' - -# Read a specific template -gh api repos/OWNER/REPO/contents/.github/ISSUE_TEMPLATE/bug_report.yml \ - --jq '.content' | base64 -d -``` - -> **Note:** When running in the cwd repo, prefer reading template files directly with `view` / `glob` rather than the API — it's faster and avoids rate limits. diff --git a/skills/create-issue/references/templates.md b/skills/create-issue/references/templates.md index 72c8c09..1e6e293 100644 --- a/skills/create-issue/references/templates.md +++ b/skills/create-issue/references/templates.md @@ -1,146 +1,22 @@ -# Issue Templates Reference +# Issue Templates — Rendering Rules -How to discover, parse, and select GitHub issue templates in the target repository. +`gh issue create --body` accepts markdown, not structured form data. YAML form fields must be rendered as markdown sections. -## Template locations +## Rendering -| Path | Format | Notes | -|------|--------|-------| -| `.github/ISSUE_TEMPLATE/*.yml` | YAML issue form | Structured fields with validation | -| `.github/ISSUE_TEMPLATE/*.yaml` | YAML issue form | Same as above | -| `.github/ISSUE_TEMPLATE/*.md` | Markdown template | Free-form with front-matter | -| `.github/ISSUE_TEMPLATE/config.yml` | Config file | Controls blank issues & contact links | -| `.github/ISSUE_TEMPLATE/config.yaml` | Config file | Same as above | +| Field type | Render as | If required + unknown | +|------------|-----------|----------------------| +| `textarea` / `input` | `### Label\n\n` | `` | +| `dropdown` | `### Label\n\n` | Fall back to `--web` | +| `checkboxes` | `- [x] Option` per checked item | Auto-check universal items (CoC); `--web` for rest | +| `markdown` | Skip — informational only | — | -## Config file (`config.yml`) - -Always check this file first. Key fields: - -```yaml -blank_issues_enabled: false # if false, do NOT use plain title+body — fall back to --web -contact_links: # informational links shown to user but not templates - - name: Community Forum - url: https://... - about: Ask questions here -``` - -If `blank_issues_enabled: false` and no template matches, inform the user and use `gh issue create --web`. - -## YAML issue forms - -```yaml -name: Bug Report # ← used for template selection -description: File a bug # ← used for template selection -title: "[Bug]: " # default title prefix -labels: ["bug"] # default labels (apply these) -assignees: [] -body: - - type: markdown - attributes: - value: "## Description" # informational — not a field - - - type: textarea - id: what-happened - attributes: - label: What happened? - description: A clear description of the bug - placeholder: Tell us what you see - validations: - required: true # ← must be filled - - - type: input - id: version - attributes: - label: Version - placeholder: "1.0.0" - validations: - required: false - - - type: dropdown - id: severity - attributes: - label: Severity - options: [Critical, High, Medium, Low] - validations: - required: true # ← must choose one - - - type: checkboxes - id: terms - attributes: - label: Code of Conduct - options: - - label: I agree - required: true # ← must be checked -``` - -### Filling YAML form fields for CLI submission - -Since `gh issue create --body` accepts free-form markdown (not structured form data), render the form as markdown: - -```markdown -### What happened? - - - -### Version - - - -### Severity - - - -### Code of Conduct - -- [x] I agree -``` - -- For **required textarea / input** fields that cannot be inferred: insert `` and warn the user before posting. -- For **required dropdowns** with many options: pick the most likely one based on context; show the choice in the confirmation draft. -- For **required checkboxes** (e.g. CoC acceptance): check them only if the label implies universal acceptance; otherwise ask. -- If the form has **3 or more required fields** that cannot be inferred, prefer `--web` to avoid a low-quality submission. +If 3+ required fields can't be inferred, prefer `--web` over a low-quality submission. ## Markdown templates -Front-matter fields: - -```yaml ---- -name: Feature Request -about: Suggest an idea for this project -title: '' -labels: enhancement -assignees: '' ---- -``` - -The body below the `---` is the template text. Fill in each section, replacing HTML comment placeholders like ``. +Front-matter: `name`, `about`, `title`, `labels`, `assignees`. Body below `---` is the template — fill each section, replace `` comments. ## Template selection -Score each template against the parsed intent (higher = better match): - -| Signal | Score | -|--------|-------| -| `name` contains the issue type keyword (bug, feature, etc.) | +3 | -| `description` / `about` contains the type keyword | +2 | -| Default `labels` contain the type keyword | +2 | -| Body section headings contain relevant keywords | +1 each | - -**Auto-select** when the top template scores ≥ 3 and leads by ≥ 2 over the second-best. -**Ask the user** otherwise — list template names and one-line descriptions, let them choose. - -### Common type → template name mappings - -| User says | Look for template name containing | -|-----------|----------------------------------| -| bug, error, crash, broken, not working | `bug`, `defect`, `problem` | -| feature, enhancement, add, improve | `feature`, `enhancement`, `improvement` | -| question, help, how to | `question`, `support` | -| task, chore, tech debt | `task`, `chore`, `maintenance` | -| security, vulnerability | `security`, `vuln` | - -## Fallback: no templates - -If `.github/ISSUE_TEMPLATE/` does not exist (and blank issues are allowed): -- Use a plain title and a minimal body covering: description, steps to reproduce (if bug), expected vs actual behaviour. +Match by `name` and `about`/`description` fields against the issue type. Use template's default `labels`. Only ask user when genuinely ambiguous. From b7cc0d9c5285160608a08077d10838e08d753ab9 Mon Sep 17 00:00:00 2001 From: Oto Macenauer Date: Thu, 4 Jun 2026 13:22:59 +0200 Subject: [PATCH 3/3] Fix create-issue skill: use temp file instead of stdin heredoc for issue body Heredocs and --body-file - break across shells (PowerShell here-strings, special chars in markdown). Write body to temp file, use --body-file , delete after creation. --- skills/create-issue/SKILL.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/skills/create-issue/SKILL.md b/skills/create-issue/SKILL.md index 1508999..fd9600b 100644 --- a/skills/create-issue/SKILL.md +++ b/skills/create-issue/SKILL.md @@ -47,11 +47,10 @@ Using the JSON from Phase 1: - Match template structure — don't add extra sections. 2. **Post** (skip confirmation unless `--confirm`): - ``` - gh issue create --title "TITLE" --body-file - [--label x] [-R repo] <<'EOF' - BODY - EOF - ``` + - Write the body to a temp file using the Write tool (e.g., `tmp_issue_body.md` in the repo root). + - Run: `gh issue create --title "TITLE" --body-file tmp_issue_body.md [--label x] [-R repo]` + - Delete the temp file after successful creation. + - Never use `--body` flag or stdin piping (`--body-file -` / heredocs) — they break on special characters across shells. On metadata error → retry without it, report what was dropped. On total failure → offer `--web`. 3. **Output**: issue URL + one-line summary. Nothing else.