gh-weld-issue
Create a new GitHub issue through a brief HITL interview.
NEVER
- NEVER pass a body with
#-prefixed lines as an inline--bodyargument — write to.weld/tmp/issue-body.mdwith the Write tool and pass via--body-file; headers trigger Claude Code's security check on every execution - NEVER skip the duplicate check — a missed duplicate creates noise and confusion in the backlog
- NEVER create issues for work you are about to implement in the same session — the issue would be created and immediately closed with no meaningful history; for same-session work use
gh-weld-adoptinstead (it creates the issue, branch, and commit for work you're implementing now), orgh-weld-shiponce the work is done on a feature branch (it links the issue to the branch and closes it on merge) - NEVER batch multiple ideas into one issue — one issue, one merge, one audit trail; batched issues can't be independently closed or reverted
- NEVER chain Bash commands with
&∨— Claude Code's safety check fires on multi-command calls and interrupts mid-flow; run each as a separate Bash tool call - NEVER use
|(pipe) in Bash tool calls — Claude Code stops execution on pipe; redirect to a temp file with>and read back with the Read tool. Note:|in markdown table syntax is unaffected. - NEVER use
$()command substitution or backtick substitution (`cmd`) — Claude Code's permission system prompts on both during execution; use fixed paths under.weld/tmp/instead - NEVER use bash heredoc (
cat > file << 'EOF') for content with#-prefixed lines — headers trigger Claude Code's security check; use the Write tool instead - NEVER use
echo >orcatto write file content — use the Write tool; it shows content as a reviewable file-write in Claude Code's approval dialog, while echo and cat are invisible to the approval UI - NEVER use
find,grep, orcatas Bash commands — use Glob, Grep, and Read tools instead; dedicated tools surface progress in the approval UI and integrate with Claude Code's permission model, while bash equivalents bypass both - NEVER warn on ambiguous repo fit — only surface the warning when the mismatch is clear and specific enough to name the other repo; false positives erode trust in the warning, and users warned repeatedly about non-issues will dismiss the next real one
- NEVER include the newly created issue number in the Related comment — it's self-referential noise; always filter it from search results before formatting
- NEVER surface the related-issue search to the user when no matches remain after filtering — the issue URL is the only post-creation signal; extra output dilutes it
Workflow
Phase 0 — Target repo
Ask: "Target repo? Enter owner/name to file into a different repo, or n for the current one. [n]"
- If the user provides an
owner/namevalue (e.g.WrathZA/github-weld): store it as the target repo and append--repo <owner>/<name>to everyghcommand for the rest of this skill. Skip the repo-fit check in Phase 1 step 2 — the user has already chosen the destination. If the firstghcommand fails after a cross-repo target was given, surface: "Could not reach<owner/name>— check repo name andgh auth status. (r)etry / (Q)uit?" Do not silently fall through to current-repo behavior. - If
nor blank: use the current repo. No--repoflag is added.
Phase 1 — Discover
A good issue has one outcome (one merge closes it) and criteria you can verify without running the code in your head. If you can't name the artifact the implementation produces, the scope isn't clear yet.
Ask: "What are you trying to build or fix?"
Repo-fit check (skip if a target repo was specified in Phase 0) — read visible project signals:
gh repo view --json name,descriptionAlso read the first 50 lines of CLAUDE.md if present (Read tool), and open PR titles:
gh pr list --state open --json titleIf either command fails, skip the fit check and proceed silently. Compare against the user's stated intent. If the issue clearly targets a different repo — references a component, skill, or project unambiguously scoped elsewhere (e.g., user describes a React UI feature in a CLI-only repo, or names a skill that lives in a different repo) — surface:
This looks like it belongs in `<other-repo>` — create it here anyway? (y/n)If yes, continue without friction. If no, stop. If ambiguous, proceed silently.
From the response, infer a candidate title (specific, action-oriented: "Add X", "Fix Y when Z") and type (bug / feature / task / chore) before asking. Ask only when genuinely ambiguous.
Run a duplicate check using 2–4 key terms extracted from the inferred title:
gh issue list --search "<key terms>" --state all --json number,title,state,updatedAt- If the result is non-empty: display each as
#N — Title [OPEN]or#N — Title [CLOSED, X days](compute age fromupdatedAt) - If open duplicates exist, show:
Possible match(es): #N — Title [OPEN] (c)ontinue as new, (u)se existing, (e)xpand existing, (d)rop?- (c) — proceed
- (u) — output the issue URL and stop;
gh-weld-issuecreates issues, not edits them - (e) — output the open issue's URL with the message: "Expand this issue's scope with your new requirements — use
gh issue editor the GitHub UI", then stop without creating a new issue. Only offered when at least one match is open; closed-only matches do not get(e). - (d) — stop
- If only closed matches: show them for context, offer
(c)ontinue / (d)rop - If empty: proceed silently
- If the result is non-empty: display each as
Scope is clear when you can name a concrete artifact the implementation produces (a flag, a command output, a visible UI change). Ask follow-ups until that artifact is nameable — one question at a time.
Show the recap:
Title: <title> Type: <bug|feature|task|chore> Scope: <one sentence>Ask: "Does this look right?" Loop until confirmed.
Phase 2 — Lock in
Acceptance criteria — draft from scope context, show as a numbered list, ask for additions/corrections. Each criterion must name a verifiable state: a command that exits 0, a visible change, a value that differs. Push back on unverifiable criteria.
Blockers — list open issues:
gh issue list --state open --json number,title,labelsInfer likely blockers from the scope. If none are obvious, ask once: "Does this depend on any open issues? Enter numbers or (n)one."
Phase 3 — Create
Determine labels to apply. At minimum, apply the type label if it exists in the repo:
gh label list --json nameMatch
bug,enhancement,feature,task,choreagainst what exists. Note matching labels for step 10. If the command fails or returns empty, skip labels and note "no labels applied".Use the Write tool to write the issue body to
.weld/tmp/issue-body.md:## Summary <scope sentence> ## Acceptance Criteria - [ ] <criterion 1> - [ ] <criterion 2> ## Blockers <"None" or "Depends on #N, #M"> --- *Created with [gh-weld](https://github.com/WrathZA/github-weld)*Create the issue:
gh issue create --title "<title>" --body-file .weld/tmp/issue-body.md --label "<labels>"If no matching labels exist, omit
--label. If the command fails or produces no URL, surface the error and ask "(r)etry / (Q)uit?" — do not clean up until creation is confirmed.Link related issues — read the issue number from the URL
gh issue createprinted. Extract 2–4 topic keywords from the new issue's title (favor distinctive nouns and compound terms; skip common verbs like "add", "fix", "update"). Search open issues in the target repo:gh issue list --search "<keywords>" --state open --json number,titleFilter out the newly created issue number. If no matches remain, skip the rest of this step silently — no comment, no output. If 1–5 matches remain, include all. If more than 5, keep the 5 closest by title similarity (shared topic words, similar phrasing).
Use the Write tool to write the comment body to
.weld/tmp/related-comment.mdas a single line:Related: #M (Title), #P (Title)Post the comment on the newly created issue:
gh issue comment <N> --body-file .weld/tmp/related-comment.mdClean up:
rm .weld/tmp/related-comment.mdClean up and output the issue URL:
rm .weld/tmp/issue-body.mdOutput the URL. Done.