From a5c3a0ebf38461eee71dd0b201bdb37307b87285 Mon Sep 17 00:00:00 2001 From: Sebastien Taggart Date: Thu, 9 Apr 2026 19:25:43 -0400 Subject: [PATCH] Use --body-file - stdin heredoc for gh multi-line bodies to preserve Bash(gh:*) permission match --- .agents/skills/deploy/SKILL.md | 8 +++----- .agents/skills/submit-for-review/SKILL.md | 12 ++++++------ .claude/commands/deploy.md | 8 +++----- .claude/commands/submit-for-review.md | 12 ++++++------ .cursor/rules/deploy.mdc | 8 +++----- .cursor/rules/submit-for-review.mdc | 12 ++++++------ .gemini/skills/deploy/SKILL.md | 8 +++----- .gemini/skills/submit-for-review/SKILL.md | 12 ++++++------ skills/deploy.md | 15 +++++---------- skills/submit-for-review.md | 10 +++++----- 10 files changed, 46 insertions(+), 59 deletions(-) diff --git a/.agents/skills/deploy/SKILL.md b/.agents/skills/deploy/SKILL.md index 7a67b52..037b39a 100644 --- a/.agents/skills/deploy/SKILL.md +++ b/.agents/skills/deploy/SKILL.md @@ -169,7 +169,7 @@ Wait for the user to type "release" or an explicit confirmation. Any other respo ```bash gh pr create --base main --head dev \ --title "Release vX.Y.Z" \ - --body "$(cat <<'EOF' + --body-file - <<'EOF' Release vX.Y.Z PRs included: @@ -179,7 +179,6 @@ PRs included: Closes #14 Closes #15 EOF -)" ``` Note the PR number from the output. @@ -215,7 +214,7 @@ Create the release: ```bash gh release create \ --title "" \ - --notes "$(cat <<'EOF' + --notes-file - <<'EOF' ## Changes - # (PR #) @@ -223,7 +222,6 @@ gh release create \ **Full changelog:** https://github.com///compare/... EOF -)" ``` Format each PR line as `- # (PR #)`. If a PR had no linked issue, omit the `#` prefix and use just the PR title. @@ -237,4 +235,4 @@ After the command runs, note the release URL from the output. Tell the user: > "Released vX.Y.Z. Issues #N, #M closed automatically. GitHub Release vX.Y.Z created at ``. Run `make deploy-prod` to ship to production." - + diff --git a/.agents/skills/submit-for-review/SKILL.md b/.agents/skills/submit-for-review/SKILL.md index 496b492..b004d8e 100644 --- a/.agents/skills/submit-for-review/SKILL.md +++ b/.agents/skills/submit-for-review/SKILL.md @@ -111,14 +111,15 @@ Use `Issue #` as the issue reference — the issue stays open until `/de Then create the PR with explicit title and body (never use an interactive editor): ``` -gh pr create --base --title "" --body "$(cat <<'EOF' +gh pr create --base <target-branch> --title "<title>" --body-file - <<'EOF' <description of what changed and why> <Closes #N OR Issue #N, based on target above> EOF -)" ``` +> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc redirection is not command substitution — the matcher sees a clean `gh pr create …` invocation and `Bash(gh:*)` matches. Apply this pattern to every multi-line `--body` / `--notes` in skills (`gh pr create`, `gh issue create`, `gh issue comment`, and `gh release create` all accept `-` for their `*-file` flags). + Add `--reviewer` to the `gh pr create` command above using the handles from `@sebastientaggart`. Before passing them, strip any leading `@` from each comma-separated handle (e.g. `@alice,@org/team` becomes `alice,org/team`) — the `gh` CLI requires bare usernames. If a CODEOWNERS file exists, both apply: CODEOWNERS triggers automatic review requests from GitHub; the `--reviewer` flag adds the explicitly configured handles on top. @@ -227,15 +228,14 @@ Accept: comma-separated numbers, `all`, or `none`/`skip`/empty. If the input is ``` gh issue create \ --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ - --body "$(cat <<'EOF' + --body-file - \ + [--label "<pool-selected labels>"] <<'EOF' Follow-up from PR #<merged-pr-number> — auto-proposed from the code review. **Finding:** <full finding text, prefix included> See the review comment on the PR for context. EOF -)" \ - [--label "<pool-selected labels>"] ``` Label resolution for each follow-up issue: use the pool-based selection tier from `/start` — pick 1–3 labels from `bug, documentation, enhancement, chore` that genuinely fit the finding. If `bug, documentation, enhancement, chore` is empty or no pool label fits, omit `--label`. Do not attempt per-invocation flag resolution (there is no flag here) and never create new labels from follow-ups, even if label creation is enabled for the project. @@ -261,4 +261,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. -<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: codex | hash: 6957b622 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: codex | hash: 61513e5d | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.claude/commands/deploy.md b/.claude/commands/deploy.md index eaf91f2..4c919ad 100644 --- a/.claude/commands/deploy.md +++ b/.claude/commands/deploy.md @@ -164,7 +164,7 @@ Wait for the user to type "release" or an explicit confirmation. Any other respo ```bash gh pr create --base main --head dev \ --title "Release vX.Y.Z" \ - --body "$(cat <<'EOF' + --body-file - <<'EOF' Release vX.Y.Z PRs included: @@ -174,7 +174,6 @@ PRs included: Closes #14 Closes #15 EOF -)" ``` Note the PR number from the output. @@ -210,7 +209,7 @@ Create the release: ```bash gh release create <version-tag> \ --title "<version-tag>" \ - --notes "$(cat <<'EOF' + --notes-file - <<'EOF' ## Changes - #<issue> — <PR title> (PR #<pr-number>) @@ -218,7 +217,6 @@ gh release create <version-tag> \ **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> EOF -)" ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, omit the `#<issue>` prefix and use just the PR title. @@ -232,4 +230,4 @@ After the command runs, note the release URL from the output. Tell the user: > "Released vX.Y.Z. Issues #N, #M closed automatically. GitHub Release vX.Y.Z created at `<url>`. Run `make deploy-prod` to ship to production." -<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: claude | hash: f84c747b | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: claude | hash: b1efee29 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.claude/commands/submit-for-review.md b/.claude/commands/submit-for-review.md index 846a1db..b7231f5 100644 --- a/.claude/commands/submit-for-review.md +++ b/.claude/commands/submit-for-review.md @@ -106,14 +106,15 @@ Use `Issue #<number>` as the issue reference — the issue stays open until `/de Then create the PR with explicit title and body (never use an interactive editor): ``` -gh pr create --base <target-branch> --title "<title>" --body "$(cat <<'EOF' +gh pr create --base <target-branch> --title "<title>" --body-file - <<'EOF' <description of what changed and why> <Closes #N OR Issue #N, based on target above> EOF -)" ``` +> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc redirection is not command substitution — the matcher sees a clean `gh pr create …` invocation and `Bash(gh:*)` matches. Apply this pattern to every multi-line `--body` / `--notes` in skills (`gh pr create`, `gh issue create`, `gh issue comment`, and `gh release create` all accept `-` for their `*-file` flags). + Add `--reviewer` to the `gh pr create` command above using the handles from `@sebastientaggart`. Before passing them, strip any leading `@` from each comma-separated handle (e.g. `@alice,@org/team` becomes `alice,org/team`) — the `gh` CLI requires bare usernames. If a CODEOWNERS file exists, both apply: CODEOWNERS triggers automatic review requests from GitHub; the `--reviewer` flag adds the explicitly configured handles on top. @@ -222,15 +223,14 @@ Accept: comma-separated numbers, `all`, or `none`/`skip`/empty. If the input is ``` gh issue create \ --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ - --body "$(cat <<'EOF' + --body-file - \ + [--label "<pool-selected labels>"] <<'EOF' Follow-up from PR #<merged-pr-number> — auto-proposed from the code review. **Finding:** <full finding text, prefix included> See the review comment on the PR for context. EOF -)" \ - [--label "<pool-selected labels>"] ``` Label resolution for each follow-up issue: use the pool-based selection tier from `/start` — pick 1–3 labels from `bug, documentation, enhancement, chore` that genuinely fit the finding. If `bug, documentation, enhancement, chore` is empty or no pool label fits, omit `--label`. Do not attempt per-invocation flag resolution (there is no flag here) and never create new labels from follow-ups, even if label creation is enabled for the project. @@ -256,4 +256,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. -<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: claude | hash: d5d59df8 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: claude | hash: 2aa076dc | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.cursor/rules/deploy.mdc b/.cursor/rules/deploy.mdc index 73dfb6b..a34de2c 100644 --- a/.cursor/rules/deploy.mdc +++ b/.cursor/rules/deploy.mdc @@ -170,7 +170,7 @@ Wait for the user to type "release" or an explicit confirmation. Any other respo ```bash gh pr create --base main --head dev \ --title "Release vX.Y.Z" \ - --body "$(cat <<'EOF' + --body-file - <<'EOF' Release vX.Y.Z PRs included: @@ -180,7 +180,6 @@ PRs included: Closes #14 Closes #15 EOF -)" ``` Note the PR number from the output. @@ -216,7 +215,7 @@ Create the release: ```bash gh release create <version-tag> \ --title "<version-tag>" \ - --notes "$(cat <<'EOF' + --notes-file - <<'EOF' ## Changes - #<issue> — <PR title> (PR #<pr-number>) @@ -224,7 +223,6 @@ gh release create <version-tag> \ **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> EOF -)" ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, omit the `#<issue>` prefix and use just the PR title. @@ -238,4 +236,4 @@ After the command runs, note the release URL from the output. Tell the user: > "Released vX.Y.Z. Issues #N, #M closed automatically. GitHub Release vX.Y.Z created at `<url>`. Run `make deploy-prod` to ship to production." -<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: cursor | hash: bb0fe2f1 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: cursor | hash: 96c1037f | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.cursor/rules/submit-for-review.mdc b/.cursor/rules/submit-for-review.mdc index 6e3c5ef..b0d2f4b 100644 --- a/.cursor/rules/submit-for-review.mdc +++ b/.cursor/rules/submit-for-review.mdc @@ -112,14 +112,15 @@ Use `Issue #<number>` as the issue reference — the issue stays open until `/de Then create the PR with explicit title and body (never use an interactive editor): ``` -gh pr create --base <target-branch> --title "<title>" --body "$(cat <<'EOF' +gh pr create --base <target-branch> --title "<title>" --body-file - <<'EOF' <description of what changed and why> <Closes #N OR Issue #N, based on target above> EOF -)" ``` +> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc redirection is not command substitution — the matcher sees a clean `gh pr create …` invocation and `Bash(gh:*)` matches. Apply this pattern to every multi-line `--body` / `--notes` in skills (`gh pr create`, `gh issue create`, `gh issue comment`, and `gh release create` all accept `-` for their `*-file` flags). + Add `--reviewer` to the `gh pr create` command above using the handles from `@sebastientaggart`. Before passing them, strip any leading `@` from each comma-separated handle (e.g. `@alice,@org/team` becomes `alice,org/team`) — the `gh` CLI requires bare usernames. If a CODEOWNERS file exists, both apply: CODEOWNERS triggers automatic review requests from GitHub; the `--reviewer` flag adds the explicitly configured handles on top. @@ -228,15 +229,14 @@ Accept: comma-separated numbers, `all`, or `none`/`skip`/empty. If the input is ``` gh issue create \ --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ - --body "$(cat <<'EOF' + --body-file - \ + [--label "<pool-selected labels>"] <<'EOF' Follow-up from PR #<merged-pr-number> — auto-proposed from the code review. **Finding:** <full finding text, prefix included> See the review comment on the PR for context. EOF -)" \ - [--label "<pool-selected labels>"] ``` Label resolution for each follow-up issue: use the pool-based selection tier from `/start` — pick 1–3 labels from `bug, documentation, enhancement, chore` that genuinely fit the finding. If `bug, documentation, enhancement, chore` is empty or no pool label fits, omit `--label`. Do not attempt per-invocation flag resolution (there is no flag here) and never create new labels from follow-ups, even if label creation is enabled for the project. @@ -262,4 +262,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. -<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: cursor | hash: 71f7fe12 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: cursor | hash: 7fefc571 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.gemini/skills/deploy/SKILL.md b/.gemini/skills/deploy/SKILL.md index 913e745..9146f22 100644 --- a/.gemini/skills/deploy/SKILL.md +++ b/.gemini/skills/deploy/SKILL.md @@ -169,7 +169,7 @@ Wait for the user to type "release" or an explicit confirmation. Any other respo ```bash gh pr create --base main --head dev \ --title "Release vX.Y.Z" \ - --body "$(cat <<'EOF' + --body-file - <<'EOF' Release vX.Y.Z PRs included: @@ -179,7 +179,6 @@ PRs included: Closes #14 Closes #15 EOF -)" ``` Note the PR number from the output. @@ -215,7 +214,7 @@ Create the release: ```bash gh release create <version-tag> \ --title "<version-tag>" \ - --notes "$(cat <<'EOF' + --notes-file - <<'EOF' ## Changes - #<issue> — <PR title> (PR #<pr-number>) @@ -223,7 +222,6 @@ gh release create <version-tag> \ **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> EOF -)" ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, omit the `#<issue>` prefix and use just the PR title. @@ -237,4 +235,4 @@ After the command runs, note the release URL from the output. Tell the user: > "Released vX.Y.Z. Issues #N, #M closed automatically. GitHub Release vX.Y.Z created at `<url>`. Run `make deploy-prod` to ship to production." -<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: gemini | hash: adfc11de | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: gemini | hash: cde00382 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.gemini/skills/submit-for-review/SKILL.md b/.gemini/skills/submit-for-review/SKILL.md index 9a7a93d..32c0a9c 100644 --- a/.gemini/skills/submit-for-review/SKILL.md +++ b/.gemini/skills/submit-for-review/SKILL.md @@ -111,14 +111,15 @@ Use `Issue #<number>` as the issue reference — the issue stays open until `/de Then create the PR with explicit title and body (never use an interactive editor): ``` -gh pr create --base <target-branch> --title "<title>" --body "$(cat <<'EOF' +gh pr create --base <target-branch> --title "<title>" --body-file - <<'EOF' <description of what changed and why> <Closes #N OR Issue #N, based on target above> EOF -)" ``` +> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc redirection is not command substitution — the matcher sees a clean `gh pr create …` invocation and `Bash(gh:*)` matches. Apply this pattern to every multi-line `--body` / `--notes` in skills (`gh pr create`, `gh issue create`, `gh issue comment`, and `gh release create` all accept `-` for their `*-file` flags). + Add `--reviewer` to the `gh pr create` command above using the handles from `@sebastientaggart`. Before passing them, strip any leading `@` from each comma-separated handle (e.g. `@alice,@org/team` becomes `alice,org/team`) — the `gh` CLI requires bare usernames. If a CODEOWNERS file exists, both apply: CODEOWNERS triggers automatic review requests from GitHub; the `--reviewer` flag adds the explicitly configured handles on top. @@ -227,15 +228,14 @@ Accept: comma-separated numbers, `all`, or `none`/`skip`/empty. If the input is ``` gh issue create \ --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ - --body "$(cat <<'EOF' + --body-file - \ + [--label "<pool-selected labels>"] <<'EOF' Follow-up from PR #<merged-pr-number> — auto-proposed from the code review. **Finding:** <full finding text, prefix included> See the review comment on the PR for context. EOF -)" \ - [--label "<pool-selected labels>"] ``` Label resolution for each follow-up issue: use the pool-based selection tier from `/start` — pick 1–3 labels from `bug, documentation, enhancement, chore` that genuinely fit the finding. If `bug, documentation, enhancement, chore` is empty or no pool label fits, omit `--label`. Do not attempt per-invocation flag resolution (there is no flag here) and never create new labels from follow-ups, even if label creation is enabled for the project. @@ -261,4 +261,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. -<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: gemini | hash: 39738177 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: gemini | hash: c5b1249c | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/skills/deploy.md b/skills/deploy.md index cd10ad5..a0c21c4 100644 --- a/skills/deploy.md +++ b/skills/deploy.md @@ -242,7 +242,7 @@ The version tag and PR/issue list are already known. If no previous tag exists, ```bash gh release create <version-tag> \ --title "<version-tag>" \ - --notes "$(cat <<'EOF' + --notes-file - <<'EOF' ## Changes - #<issue> — <PR title> (PR #<pr-number>) @@ -250,7 +250,6 @@ gh release create <version-tag> \ **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> EOF -)" ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, use just the PR title. @@ -272,7 +271,7 @@ Tell the user: ```bash gh pr create --base {{BRANCH_PROD}} --head {{BRANCH_DEV}} \ --title "Release vX.Y.Z" \ - --body "$(cat <<'EOF' + --body-file - <<'EOF' Release vX.Y.Z PRs included: @@ -282,7 +281,6 @@ PRs included: Closes #14 Closes #15 EOF -)" ``` Note the PR number from the output. @@ -318,7 +316,7 @@ Create the release: ```bash gh release create <version-tag> \ --title "<version-tag>" \ - --notes "$(cat <<'EOF' + --notes-file - <<'EOF' ## Changes - #<issue> — <PR title> (PR #<pr-number>) @@ -326,7 +324,6 @@ gh release create <version-tag> \ **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> EOF -)" ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, omit the `#<issue>` prefix and use just the PR title. @@ -347,7 +344,7 @@ Tell the user: ```bash gh pr create --base {{BRANCH_PROD}} --head {{BRANCH_TEST}} \ --title "Release vX.Y.Z" \ - --body "$(cat <<'EOF' + --body-file - <<'EOF' Release vX.Y.Z PRs included: @@ -357,7 +354,6 @@ PRs included: Closes #14 Closes #15 EOF -)" ``` Note the PR number from the output. @@ -393,7 +389,7 @@ Create the release: ```bash gh release create <version-tag> \ --title "<version-tag>" \ - --notes "$(cat <<'EOF' + --notes-file - <<'EOF' ## Changes - #<issue> — <PR title> (PR #<pr-number>) @@ -401,7 +397,6 @@ gh release create <version-tag> \ **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> EOF -)" ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, omit the `#<issue>` prefix and use just the PR title. diff --git a/skills/submit-for-review.md b/skills/submit-for-review.md index a7d91a3..c746095 100644 --- a/skills/submit-for-review.md +++ b/skills/submit-for-review.md @@ -128,14 +128,15 @@ Use `Closes #<number>` as the issue reference — merging to the default branch Then create the PR with explicit title and body (never use an interactive editor): ``` -gh pr create --base <target-branch> --title "<title>" --body "$(cat <<'EOF' +gh pr create --base <target-branch> --title "<title>" --body-file - <<'EOF' <description of what changed and why> <Closes #N OR Issue #N, based on target above> EOF -)" ``` +> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc redirection is not command substitution — the matcher sees a clean `gh pr create …` invocation and `Bash(gh:*)` matches. Apply this pattern to every multi-line `--body` / `--notes` in skills (`gh pr create`, `gh issue create`, `gh issue comment`, and `gh release create` all accept `-` for their `*-file` flags). + {{#if DEFAULT_REVIEWERS}} Add `--reviewer` to the `gh pr create` command above using the handles from `{{DEFAULT_REVIEWERS}}`. Before passing them, strip any leading `@` from each comma-separated handle (e.g. `@alice,@org/team` becomes `alice,org/team`) — the `gh` CLI requires bare usernames. @@ -267,15 +268,14 @@ Accept: comma-separated numbers, `all`, or `none`/`skip`/empty. If the input is ``` gh issue create \ --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ - --body "$(cat <<'EOF' + --body-file - \ + [--label "<pool-selected labels>"] <<'EOF' Follow-up from PR #<merged-pr-number> — auto-proposed from the code review. **Finding:** <full finding text, prefix included> See the review comment on the PR for context. EOF -)" \ - [--label "<pool-selected labels>"] ``` Label resolution for each follow-up issue: use the pool-based selection tier from `/start` — pick 1–3 labels from `{{TICKET_LABELS}}` that genuinely fit the finding. If `{{TICKET_LABELS}}` is empty or no pool label fits, omit `--label`. Do not attempt per-invocation flag resolution (there is no flag here) and never create new labels from follow-ups, even if label creation is enabled for the project.