Agent Skills › KiwiCanopy/KiwiDesk › file-issue

file-issue

GitHub

通过手动渲染模板和调用 API,为 GitHub 仓库创建包含正确标题、正文、类型及优先级的 Issue。

.claude/skills/file-issue/SKILL.md KiwiCanopy/KiwiDesk

Trigger Scenarios

需要创建 GitHub Issue 使用 gh 命令提交 Bug 或功能请求

Install

npx skills add KiwiCanopy/KiwiDesk --skill file-issue -g -y
More Options

Non-standard path

npx skills add https://github.com/KiwiCanopy/KiwiDesk/tree/main/.claude/skills/file-issue -g -y

Use without installing

npx skills use KiwiCanopy/KiwiDesk@file-issue

指定 Agent (Claude Code)

npx skills add KiwiCanopy/KiwiDesk --skill file-issue -a claude-code -g -y

安装 repo 全部 skill

npx skills add KiwiCanopy/KiwiDesk --all -g -y

预览 repo 内 skill

npx skills add KiwiCanopy/KiwiDesk --list

SKILL.md

Frontmatter
{
    "name": "file-issue",
    "description": "File a KiwiDesk GitHub issue the way an agent must — render the template body by hand, then set the Type and the Priority\/Effort issue fields the web form would have set for a human. Use whenever creating an issue with `gh`.",
    "argument-hint": "[template: bug_report|feature_request|report_docs|collector]"
}

File a GitHub issue for this repository. AGENTS.md §3 (Branching & Pull Requests) owns the why — which template an issue takes, and why its questions must be answered rather than skipped. This skill owns the mechanics.

gh issue create does not apply the .github/ISSUE_TEMPLATE/*.yml forms: the body observation is AGENTS.md §3's (2026-08-02, gh 2.x — a --body-file filing starts blank), and since the form never runs, its type: key cannot apply either (inferred from that observation, not separately tested — a filing that does land with a Type set is news worth updating this line with). So reproduce by hand what the web form gives a human for free.

1. Render the template

The template to use is $ARGUMENTS (pick per AGENTS.md §3 if not given). Read it and reproduce it — the three reporter shapes live in .github/ISSUE_TEMPLATE/$ARGUMENTS.yml, while collector is ours rather than a reporter's and lives in templates/collector.yml beside this skill, out of the chooser GitHub builds from .github/ISSUE_TEMPLATE/ alone. Never route an issue to collector on your own reading — it groups work instead of reporting it, so the owner names it:

  • each label: becomes a ### heading, in declared order, answered honestly — an internal issue answers the user-shaped questions from the dev machine, never drops them;
  • the template's title: prefix goes on the title;
  • any labels: the template declares go on the command line (--label …).

Then:

gh issue create --title "<prefix> <title>" --body-file <file>

2. Set the Type

Set it explicitly — Bug, Feature, or Task, matching the template's type: value. {owner}/{repo} is literal: gh resolves it from the current repository, so never substitute a hand-written owner.

gh api -X PATCH repos/{owner}/{repo}/issues/<n> -f type=Bug

3. Set Priority and Effort

Skip this step for a collector issue — it sequences work rather than being work, so it takes a Type but no Priority/Effort.

For everything else, set both single-select issue fields. Discover the current field and option IDs rather than trusting a stale copy (:owner/:repo are literal too — gh fills them):

gh api graphql -F owner=':owner' -F name=':repo' -f query='
  query($owner:String!, $name:String!) {
    repository(owner:$owner, name:$name) {
      issueFields(first:20) { nodes {
        ... on IssueFieldSingleSelect { id
          options { id name } } } } } }'

Do not add name beside that id. The field's own name needs the read:project scope, which the working token here has not had (observed 2026-08-12); asking for it fails the whole query with INSUFFICIENT_SCOPES and looks exactly like "this token cannot set these fields". It can — only the label is withheld. Identify which node is which from its options: Priority has four (Urgent/High/Medium/Low), Effort three (High/Medium/Low). The inline fragment is likewise required, not stylistic: issueFields is a union, so a bare id on nodes is a selectionMismatch.

A read-only cross-check that needs no extra scope, and which also shows what an issue currently carries:

gh api repos/{owner}/{repo}/issues/<n> --jq '.issue_field_values'

It returns each field's name, its numeric issue_field_id and the selected option — useful for confirming the write landed, and for harvesting an option's name from an issue that already has the value you want. Its numeric ids are not the GraphQL node ids, so they cannot be pasted into the mutation.

Then, with the issue's node id (gh api repos/{owner}/{repo}/issues/<n> --jq .node_id):

gh api graphql -f query='mutation($id:ID!){
  setIssueFieldValue(input:{issueId:$id, issueFields:[
    {fieldId:"<priority-field-id>",
     singleSelectOptionId:"<option-id>"},
    {fieldId:"<effort-field-id>",
     singleSelectOptionId:"<option-id>"}]})
  { issue { number } } }' -f id="<node-id>"

The ids here are the IFSS_… (field) and IFSSO_… (option) node ids from the discovery query. A NOT_FOUND naming a global id means one of them is an IFSSV_… — a field VALUE node id, which is what the REST cross-check above returns and what a half-remembered copy tends to be. The three prefixes differ by one letter and the error does not say which kind it wanted.

Read the issue back (step 5) rather than trusting a null response shape: the mutation returns the issue number on success.

The Priority ladder

Read it against the milestone's current contents, which are the authority on what the release has actually committed to:

  • Urgent — blocks the next release, or daily use is broken now.
  • High — the release's own work: an issue the milestone already carries, or a defect that belongs beside one.
  • Medium — the quality bar behind it: localization and terminology defects, docs parity, test debt, polish the release wants but does not gate on.
  • Low — deferred, icebox, or blocked on the OS; behind the release deliberately.

The Effort ladder

The honest size of the fix, not its importance:

  • Low — one sitting: a pin, a caption, a rename with a parity guard, a worksheet fix.
  • Medium — a lane: one subsystem, its tests and its review round.
  • High — a dedicated session or more: cross-subsystem, a new surface, or an unscoped investigation.

4. Set the milestone, or deliberately don't

Unlike the three above, this is not something the web form would have set — it is a triage decision, and it has its own question. A milestone says which release must not ship without this. It is not a second priority: Priority ranks work within a release, the milestone decides whether the release waits.

  • Set 1.0 for a defect a user can meet in a shipped surface, a terminology or docs error that would ship wrong, or work the milestone already carries.
  • Leave it empty for new behavior deliberately deferred, an icebox idea, or anything blocked on the OS. Empty is an ANSWER — it says the release does not wait for this — so decide it rather than skipping it.
gh issue edit <n> --milestone "1.0"

Read the bar off the milestone's current contents, not off the two lines above: gh issue list --milestone "1.0" is the authority on what the release has actually committed to, and a ladder restated here would rot against it.

A collector issue takes a milestone when it scopes a release (#663 does) — it only skips Priority and Effort.

5. Verify

Read the issue back and confirm all four landed:

gh api repos/{owner}/{repo}/issues/<n> \
  --jq '{type: .type.name, milestone: .milestone.title,
  fields: [.issue_field_values[]
  | {(.issue_field_name): .single_select_option.name}]}'

Version History

  • cfa7caf Current 2026-09-27 10:24

Same Skill Collection

.claude/skills/review-change/SKILL.md
.claude/skills/verify-gate/SKILL.md

Metadata

Files
0
Version
cfa7caf
Hash
a0465366
Indexed
2026-09-27 10:24

Home - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-27 19:31
浙ICP备14020137号-1