plugins/gwt/skills/gwt-pr-check/SKILL.md
Check GitHub PR status with the gh CLI using REST-first PR lookups, including unmerged PR detection and post-merge new-commit detection for the current branch.
npx skillsauth add akiojin/gwt gwt-pr-checkInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Check PR status for the current branch with gh and report a recommended next action, using REST-first pull-request lookups instead of gh pr list as the primary path.
This skill is check-only:
head branch, and base branch.
head: current branch (git rev-parse --abbrev-ref HEAD)base: default develop unless user specifiesgit status --porcelaingit fetch origingh repo view --json nameWithOwner -q .nameWithOwner<owner>/<repo>gh api repos/<owner>/<repo>/pulls?state=all&head=<owner>:<head>&per_page=100NO_PR + recommended action CREATE_PRmergedAt == null
-> UNMERGED_PR_EXISTS + recommended action PUSH_ONLYmergedAtmergeCommit.oidgit merge-base --is-ancestor <merge_commit> HEADHEAD, count commits after merge:
git rev-list --count <merge_commit>..HEADALL_MERGED_WITH_NEW_COMMITS + CREATE_PRALL_MERGED_NO_NEW_COMMITS + NO_ACTIONHEAD:
git rev-list --count origin/<head>..HEADALL_MERGED_WITH_NEW_COMMITS + CREATE_PR (fallback)0, still compare against base:
git rev-list --count origin/<base>..HEADALL_MERGED_WITH_NEW_COMMITS + CREATE_PR (fallback)ALL_MERGED_NO_NEW_COMMITS + NO_ACTIONCHECK_FAILED + MANUAL_CHECKReturn a human-readable summary by default.
Do not return raw JSON as the default output. If JSON is explicitly requested by the user, append it after the human summary.
Recommended status values:
NO_PRUNMERGED_PR_EXISTSALL_MERGED_WITH_NEW_COMMITSALL_MERGED_NO_NEW_COMMITSCHECK_FAILEDRecommended action values:
CREATE_PRPUSH_ONLYNO_ACTIONMANUAL_CHECKOutput 1-3 lines using a signal prefix + action keyword on line 1.
| Prefix | Action | Meaning |
| --- | --- | --- |
| >> | CREATE PR | Create a new PR |
| > | PUSH ONLY | Push to existing PR |
| -- | NO ACTION | Nothing to do |
| !! | MANUAL CHECK | Manual check required |
Per-status format:
NO_PR:
>> CREATE PR — No PR exists for <head> -> <base>.
UNMERGED_PR_EXISTS (2 lines):
> PUSH ONLY — Unmerged PR open for `<head>`.
PR: #<number> <url>
ALL_MERGED_WITH_NEW_COMMITS (2 lines):
>> CREATE PR — <N> new commit(s) after last merge (#<pr_number>).
head: <head> -> base: <base>
ALL_MERGED_NO_NEW_COMMITS:
-- NO ACTION — All PRs merged, no new commits on <head>.
CHECK_FAILED (2 lines):
!! MANUAL CHECK — Could not determine PR status.
Reason: <reason>
head: <head> -> base: <base>
Append the following line only when the worktree is dirty:
(!) Worktree has uncommitted changes.
| Status | Prefix | Action | Template |
| --- | --- | --- | --- |
| NO_PR | >> | CREATE PR | No PR exists |
| UNMERGED_PR_EXISTS | > | PUSH ONLY | Unmerged PR open |
| ALL_MERGED_WITH_NEW_COMMITS | >> | CREATE PR | N new commit(s) |
| ALL_MERGED_NO_NEW_COMMITS | -- | NO ACTION | All PRs merged |
| CHECK_FAILED | !! | MANUAL CHECK | Could not determine |
NO_PR:
>> CREATE PR — No PR exists for `feature/my-branch` -> `develop`.
UNMERGED_PR_EXISTS:
> PUSH ONLY — Unmerged PR open for `feature/my-branch`.
PR: #456 https://github.com/org/repo/pull/456
ALL_MERGED_WITH_NEW_COMMITS:
>> CREATE PR — 3 new commit(s) after last merge (#123).
head: feature/my-branch -> base: develop
ALL_MERGED_NO_NEW_COMMITS:
-- NO ACTION — All PRs merged, no new commits on `feature/my-branch`.
CHECK_FAILED:
!! MANUAL CHECK — Could not determine PR status.
Reason: Could not resolve merge commit and fallback comparison failed
head: feature/my-branch -> base: develop
With dirty worktree (appended to any status):
>> CREATE PR — 3 new commit(s) after last merge (#123).
head: feature/my-branch -> base: develop
(!) Worktree has uncommitted changes.
git rev-parse --show-toplevelgit rev-parse --abbrev-ref HEADgh auth statusGH_TOKEN / GITHUB_TOKEN is already set for REST calls, do not treat gh auth status as the sole readiness gate.git status --porcelaingit fetch origingh pr list when checking branch PR state.origin/<head>..HEAD first and then origin/<base>..HEAD before returning NO_ACTION.# Human-readable output
python3 "${CLAUDE_PLUGIN_ROOT}/skills/gwt-pr-check/scripts/check_pr_status.py" --repo "."
# Explicit base branch
python3 "${CLAUDE_PLUGIN_ROOT}/skills/gwt-pr-check/scripts/check_pr_status.py" --repo "." --base develop
# Append machine-readable JSON after the summary
python3 "${CLAUDE_PLUGIN_ROOT}/skills/gwt-pr-check/scripts/check_pr_status.py" --repo "." --json
head="${HEAD_BRANCH:-$(git rev-parse --abbrev-ref HEAD)}"
base="${BASE_BRANCH:-develop}"
dirty=0
if [ -n "$(git status --porcelain)" ]; then
dirty=1
fi
git fetch origin
repo_slug="$(gh repo view --json nameWithOwner -q .nameWithOwner)"
owner="${repo_slug%%/*}"
pr_json="$(gh api "repos/$repo_slug/pulls?state=all&head=$owner:$head&per_page=100")"
pr_count="$(echo "$pr_json" | jq 'length')"
unmerged_count="$(echo "$pr_json" | jq 'map(select(.merged_at == null)) | length')"
if [ "$pr_count" -eq 0 ]; then
status="NO_PR"
action="CREATE_PR"
reason="No PR found for head branch"
elif [ "$unmerged_count" -gt 0 ]; then
status="UNMERGED_PR_EXISTS"
action="PUSH_ONLY"
reason="At least one PR for the head branch is not merged"
else
merge_commit="$(echo "$pr_json" | jq -r 'map(select(.merged_at != null)) | sort_by(.updated_at) | last | .merge_commit_sha')"
merge_commit_ancestor=0
if [ -n "$merge_commit" ] && [ "$merge_commit" != "null" ] && \
git merge-base --is-ancestor "$merge_commit" HEAD 2>/dev/null; then
merge_commit_ancestor=1
new_commits="$(
git rev-list --count "$merge_commit"..HEAD 2>/dev/null || echo ""
)"
else
new_commits=""
fi
if [ -n "$new_commits" ]; then
if [ "$new_commits" -gt 0 ]; then
status="ALL_MERGED_WITH_NEW_COMMITS"
action="CREATE_PR"
reason="$new_commits commits found after last merge"
else
status="ALL_MERGED_NO_NEW_COMMITS"
action="NO_ACTION"
reason="No commits found after last merge"
fi
else
upstream_commits="$(
git rev-list --count "origin/$head"..HEAD 2>/dev/null || echo ""
)"
fallback_commits="$(
git rev-list --count "origin/$base"..HEAD 2>/dev/null || echo ""
)"
if [ -n "$upstream_commits" ] && [ "$upstream_commits" -gt 0 ]; then
status="ALL_MERGED_WITH_NEW_COMMITS"
action="CREATE_PR"
reason="Fallback check found commits ahead of origin/$head"
elif [ -n "$fallback_commits" ]; then
if [ "$fallback_commits" -gt 0 ]; then
status="ALL_MERGED_WITH_NEW_COMMITS"
action="CREATE_PR"
reason="Fallback check found commits ahead of origin/$base"
else
status="ALL_MERGED_NO_NEW_COMMITS"
action="NO_ACTION"
reason="Fallback check found no commits ahead of origin/$head or origin/$base"
fi
else
status="CHECK_FAILED"
action="MANUAL_CHECK"
reason="Could not resolve merge commit and fallback comparison failed"
fi
fi
fi
latest_merged_pr="$(
echo "$pr_json" \
| jq -r 'map(select(.merged_at != null)) | sort_by(.updated_at) | last | .number // empty'
)"
unmerged_pr="$(
echo "$pr_json" \
| jq -r 'map(select(.merged_at == null)) | first | .number // empty'
)"
unmerged_pr_url="$(
echo "$pr_json" \
| jq -r 'map(select(.merged_at == null)) | first | .html_url // empty'
)"
case "$status" in
NO_PR)
echo ">> CREATE PR — No PR exists for \`$head\` -> \`$base\`."
;;
UNMERGED_PR_EXISTS)
echo "> PUSH ONLY — Unmerged PR open for \`$head\`."
echo " PR: #$unmerged_pr $unmerged_pr_url"
;;
ALL_MERGED_WITH_NEW_COMMITS)
n="${new_commits:-$upstream_commits}"
echo ">> CREATE PR — $n new commit(s) after last merge (#$latest_merged_pr)."
echo " head: $head -> base: $base"
;;
ALL_MERGED_NO_NEW_COMMITS)
echo "-- NO ACTION — All PRs merged, no new commits on \`$head\`."
;;
*)
echo "!! MANUAL CHECK — Could not determine PR status."
echo " Reason: $reason"
echo " head: $head -> base: $base"
;;
esac
if [ "$dirty" -eq 1 ]; then
echo " (!) Worktree has uncommitted changes."
fi
gwt-pr: creates/updates PRsgwt-pr-fix: diagnoses and fixes failing PRstools
Create distinctive, production-grade terminal user interfaces. Use when building TUI components with ratatui, CLI output styling, or xterm.js terminal rendering. Triggers: 'design TUI', 'terminal UI', 'TUIデザイン', 'ターミナルUI', 'ratatui widget'
testing
Semantic search over SPEC Issues (GitHub Issue cache at ~/.gwt/cache/issues/) using vector embeddings. Use when searching for existing specs, finding related specs, checking for duplicate specs, or determining which spec owns a scope. Mandatory preflight before gwt-discussion when the work may need a SPEC owner. Use when user says 'search specs', 'find related specs', 'check for duplicate specs', or asks which spec owns a scope.
testing
Mandatory preflight before gwt-discussion, gwt-register-issue, and gwt-fix-issue. Use proactively before creating any SPEC or Issue owner or before reusing an existing one. Searches SPEC Issues, GitHub Issues, and project files via ChromaDB. Triggers: 'search', 'find related', 'check duplicates'.
business
Use when the user wants to register new work from a bug report, idea, or task description and an existing GitHub Issue number is not already known.