Skip to content

feat(github,commit): remove terminal-ui-design, add batch ops and PR templates#20

Merged
duyet merged 2 commits into
masterfrom
feat/remove-terminal-ui-add-github-enhancements
Mar 4, 2026
Merged

feat(github,commit): remove terminal-ui-design, add batch ops and PR templates#20
duyet merged 2 commits into
masterfrom
feat/remove-terminal-ui-add-github-enhancements

Conversation

@duyet
Copy link
Copy Markdown
Owner

@duyet duyet commented Mar 4, 2026

Summary

This PR removes the terminal-ui-design plugin (consolidated with frontend-design) and significantly enhances the GitHub and commit plugins with batch operations, PR templates, automation workflows, and comprehensive documentation.

Changes

Removed

  • terminal-ui-design/ plugin directory (4 files) - consolidated with frontend-design

GitHub Plugin (v1.1.0 → v1.2.0)

  • New batch commands: /github:bulk-close-issues, /github:bulk-merge-prs, /github:bulk-label
  • New README: github/README.md with usage examples and troubleshooting
  • Enhanced skill documentation:
    • Batch operations section with usage examples
    • Common gotchas (rate limiting, auth issues, branch detection, CI status, JSON processing)
    • Real-world examples (PR triage, CI failure analysis, repo cleanup, release automation)
  • New examples directory:
    • bulk-close-issues.sh - Close issues by label with confirmation
    • bulk-merge-prs.sh - Merge approved PRs with passing CI
    • pr-automation.sh - Auto-label, auto-assign, and welcome contributors

Commit Plugin (v1.2.1 → v1.3.0)

  • New PR templates in commit/.pr-templates/:
    • default.md - General purpose PR template
    • bugfix.md - Bug fix PR template with root cause and regression risk
    • feature.md - New feature PR template with motivation and breaking changes
  • Enhanced /commit:and-create-pr command:
    • Template selection based on commit type (fix→bugfix, feat→feature, other→default)
    • --template <name> option for explicit template selection
    • --draft option to create draft PRs
    • Optimized bash: removed TOCTOU anti-pattern, using parameter expansion

Marketplace Updates

  • Updated .claude-plugin/marketplace.json (13 → 12 plugins)
  • Updated marketplace.json with new plugin versions
  • Updated README.md - removed terminal-ui-design references
  • Updated CHANGELOG.md with all new features
  • Updated .github/ISSUE_TEMPLATE/feature_request.md - removed checkbox

GitHub Actions

  • New workflow: .github/workflows/pr-automation.yml
    • Auto-label PRs based on changed files (area:api, area:frontend, etc.)
    • Auto-assign reviewers based on code ownership
    • Welcome message for first-time contributors
  • Source documentation: .github/workflows/pr-automation.md

Code Quality Improvements

As part of the simplify review:

  • Fixed TOCTOU anti-pattern (file existence check → direct read with error handling)
  • Replaced inefficient subshells with bash parameter expansion
  • Removed duplicate "Context" section header
  • Added template name constants to avoid stringly-typed code
  • Optimized API call patterns in documentation examples

Testing

Run through documented examples to verify:

# Test batch commands with dry-run
/github:bulk-label --dry-run --add "test"
/github:bulk-close-issues --dry-run --label "wontfix"

# Test PR template workflow
echo "# test" > test.md
git add test.md
/commit:and-create-pr --template default --draft

Generated with Claude Code

Summary by Sourcery

Introduce GitHub batch operation commands, PR templates for the commit plugin, and an automated PR triage workflow while removing the deprecated terminal-ui-design plugin.

New Features:

  • Add GitHub batch commands for bulk closing issues, bulk merging PRs, and bulk labeling issues/PRs.
  • Introduce PR templates for the commit plugin tailored for default, bugfix, and feature workflows.
  • Add a PR automation GitHub Actions workflow to auto-label PRs, assign reviewers, and welcome first-time contributors.

Enhancements:

  • Expand GitHub plugin documentation with batch operation usage, best practices, troubleshooting, and real-world workflow examples.
  • Enhance the commit-and-create-PR flow with template selection, draft PR support, and clearer option documentation.
  • Add example scripts demonstrating GitHub batch operations and PR triage automation.

CI:

  • Introduce a PR automation workflow to automatically label PRs, assign reviewers, and greet first-time contributors.

Documentation:

  • Add a dedicated GitHub plugin README detailing features, usage, and versioning.
  • Update the main README and changelog to reflect new GitHub/commit features and the removal of terminal-ui-design.
  • Document the PR automation workflow behavior, configuration, and permissions.

Chores:

  • Remove the terminal-ui-design plugin and its references from documentation, marketplace metadata, and issue templates.
  • Update plugin manifests and marketplace metadata to reflect new versions and the reduced plugin set.

Summary by CodeRabbit

  • New Features

    • GitHub batch operations: bulk-close-issues, bulk-merge-prs, bulk-label, and watch-and-fix automation
    • PR templating: default, bugfix, and feature templates; template-driven PR creation options
    • Automated PR automation for labeling, reviewer assignment, and welcoming first-time contributors
  • Documentation

    • Extensive GitHub plugin docs, examples, and usage guides added
  • Removed

    • Terminal UI Design plugin and its documentation

…templates

- Remove terminal-ui-design plugin (consolidated with frontend-design)
- Add GitHub batch commands: bulk-close-issues, bulk-merge-prs, bulk-label
- Add PR templates to commit plugin (default, bugfix, feature)
- Add PR automation GitHub Action for auto-labeling and reviewer assignment
- Enhance GitHub documentation with examples, troubleshooting, and gotchas
- Add github/examples/ directory with automation scripts
- Update plugin versions: github@1.2.0, commit@1.3.0

Co-Authored-By: duyetbot <duyetbot@users.noreply.github.com>
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Mar 4, 2026

Reviewer's Guide

Removes the deprecated terminal-ui-design plugin, adds GitHub batch operation commands and documentation, enhances the commit plugin with PR templates and improved /commit:and-create-pr behavior, and introduces a PR automation GitHub Action plus marketplace/readme metadata updates.

Sequence diagram for enhanced /commit:and-create-pr with PR templates and draft option

sequenceDiagram
  actor Developer
  participant CommitCommand as Commit_and_create_pr
  participant Git
  participant TemplateSelector
  participant PRTemplates as PR_template_files
  participant GitHubCLI as gh

  Developer->>CommitCommand: invoke /commit:and-create-pr [options]
  CommitCommand->>Git: git status, git diff, git branch
  Git-->>CommitCommand: repo state

  CommitCommand->>Git: git commit -m "semantic message"
  Git-->>CommitCommand: commit created

  CommitCommand->>TemplateSelector: determine template(commit_type, cli_template_option)
  TemplateSelector-->>CommitCommand: template_name (default | bugfix | feature)

  CommitCommand->>PRTemplates: read template_file(template_name)
  alt template file exists
    PRTemplates-->>CommitCommand: template_body
    CommitCommand->>CommitCommand: substitute placeholders (description, changes, etc.)
    CommitCommand-->>CommitCommand: PR_BODY
  else template missing or read error
    PRTemplates-->>CommitCommand: read error
    CommitCommand->>CommitCommand: build fallback PR_BODY
  end

  alt --draft flag provided
    CommitCommand->>GitHubCLI: gh pr create --title COMMIT_MSG --body PR_BODY --draft
  else
    CommitCommand->>GitHubCLI: gh pr create --title COMMIT_MSG --body PR_BODY
  end

  GitHubCLI-->>Developer: PR URL
Loading

Class diagram for GitHub and commit plugin structures with batch commands and PR templates

classDiagram
  class GitHubPlugin {
    +string name
    +string version
    +GitHubSkill github
    +BulkCloseIssuesCommand bulk_close_issues
    +BulkMergePrsCommand bulk_merge_prs
    +BulkLabelCommand bulk_label
  }

  class GitHubSkill {
    +string description
    +string documentation_file
  }

  class BulkCloseIssuesCommand {
    +string description
    +execute(label, search, comment, state, dry_run)
  }

  class BulkMergePrsCommand {
    +string description
    +execute(label, reviewer_approved, search, method, delete_branch, dry_run)
  }

  class BulkLabelCommand {
    +string description
    +execute(add_labels, remove_labels, label, search, type, dry_run)
  }

  GitHubPlugin --> GitHubSkill
  GitHubPlugin --> BulkCloseIssuesCommand
  GitHubPlugin --> BulkMergePrsCommand
  GitHubPlugin --> BulkLabelCommand

  class CommitPlugin {
    +string name
    +string version
    +CommitAndCreatePrCommand commit_and_create_pr
    +PrTemplate default_template
    +PrTemplate bugfix_template
    +PrTemplate feature_template
  }

  class CommitAndCreatePrCommand {
    +string description
    +run(template_name, draft, title, body)
    +select_template(commit_type, template_name)
    +build_pr_body(template)
  }

  class PrTemplate {
    +string name
    +string file_path
    +string content
  }

  CommitPlugin --> CommitAndCreatePrCommand
  CommitPlugin --> PrTemplate : uses
  CommitAndCreatePrCommand --> PrTemplate : selects

  class PrAutomationWorkflow {
    +string name
    +auto_label(files, commits)
    +auto_assign(files)
    +welcome_first_time(author)
  }

  class LabelRules {
    +apply_area_labels(files)
    +apply_breaking_label(commits)
    +apply_documentation_label(files)
  }

  class ReviewerRules {
    +assign_frontend(files)
    +assign_backend(files)
    +assign_api(files)
    +assign_devops(files)
  }

  PrAutomationWorkflow --> LabelRules
  PrAutomationWorkflow --> ReviewerRules
Loading

Flow diagram for GitHub bulk operations commands (close issues, merge PRs, label)

flowchart TD
  Start([Start])
  ChooseCmd{Select command}
  CmdClose["/github:bulk-close-issues"]
  CmdMerge["/github:bulk-merge-prs"]
  CmdLabel["/github:bulk-label"]

  GatherOpts["Parse CLI options\n(label, search, type, method, add/remove, delete-branch)"]
  ListItems["Query matching items via gh\n(issues or PRs)"]
  AnyItems{Any items found?}
  ShowPreview["Show items and planned changes"]
  DryRun{--dry-run?}
  Confirm["Ask for confirmation"]
  ApplyClose["gh issue close\n(+ optional comment)"]
  ApplyMerge["gh pr merge\n(+ optional delete branch)"]
  ApplyLabel["gh issue/pr edit\n(add/remove labels)"]
  End([End])

  Start --> ChooseCmd
  ChooseCmd -->|bulk-close-issues| CmdClose
  ChooseCmd -->|bulk-merge-prs| CmdMerge
  ChooseCmd -->|bulk-label| CmdLabel

  CmdClose --> GatherOpts
  CmdMerge --> GatherOpts
  CmdLabel --> GatherOpts

  GatherOpts --> ListItems
  ListItems --> AnyItems
  AnyItems -->|No| End
  AnyItems -->|Yes| ShowPreview

  ShowPreview --> DryRun
  DryRun -->|Yes| End
  DryRun -->|No| Confirm
  Confirm -->|No| End

  Confirm -->|Yes and bulk-close-issues| ApplyClose
  Confirm -->|Yes and bulk-merge-prs| ApplyMerge
  Confirm -->|Yes and bulk-label| ApplyLabel

  ApplyClose --> End
  ApplyMerge --> End
  ApplyLabel --> End
Loading

File-Level Changes

Change Details Files
Add GitHub batch operation commands with docs and examples.
  • Introduce three new GitHub commands for bulk closing issues, bulk merging PRs, and bulk labeling items.
  • Document batch operation usage, gotchas, and real-world workflows in the main GitHub skill and a new plugin README.
  • Add example shell scripts demonstrating bulk close, bulk merge, and PR automation flows using gh CLI.
github/commands/bulk-close-issues.md
github/commands/bulk-merge-prs.md
github/commands/bulk-label.md
github/skills/github.md
github/README.md
github/examples/bulk-close-issues.sh
github/examples/bulk-merge-prs.sh
github/examples/pr-automation.sh
github/.claude-plugin/plugin.json
Enhance commit plugin with PR templates and smarter /commit:and-create-pr behavior.
  • Add default, bugfix, and feature PR templates with structured sections under commit/.pr-templates.
  • Update /commit:and-create-pr docs to cover template selection, draft PR flag, and custom title/body options.
  • Refine example bash implementation to derive template from semantic commit type, avoid TOCTOU on template reads, and support draft PR creation.
commit/.pr-templates/default.md
commit/.pr-templates/bugfix.md
commit/.pr-templates/feature.md
commit/commands/and-create-pr.md
commit/.claude-plugin/plugin.json
Introduce PR automation GitHub Action and supporting docs/examples.
  • Add pr-automation GitHub Actions workflow that labels PRs based on changed files, assigns reviewers by area, detects breaking changes, and welcomes first-time contributors.
  • Document the PR automation workflow behavior, configuration points, and required permissions.
  • Provide a standalone pr-automation example script that mirrors labeling, reviewer assignment, and welcome logic via gh CLI.
.github/workflows/pr-automation.yml
.github/workflows/pr-automation.md
github/examples/pr-automation.sh
Remove terminal-ui-design plugin and update marketplace/README metadata.
  • Delete terminal-ui-design plugin directory and manifest files.
  • Remove terminal-ui-design references from the main README, changelog, issue templates, and marketplace metadata.
  • Update plugin registry and individual plugin manifests to reflect new versions and reduced plugin count.
terminal-ui-design/.claude-plugin/plugin.json
terminal-ui-design/CLAUDE.md
terminal-ui-design/README.md
terminal-ui-design/skills/terminal-ui-design/SKILL.md
README.md
CHANGELOG.md
.github/ISSUE_TEMPLATE/feature_request.md
.claude-plugin/marketplace.json
marketplace.json
github/.claude-plugin/plugin.json
commit/.claude-plugin/plugin.json

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 4, 2026

📝 Walkthrough

Walkthrough

Removed the terminal-ui-design plugin and its docs; added GitHub PR automation workflow, scripts, and docs for auto-labeling/assigning/welcome; introduced commit PR templates and template-driven PR creation docs; added GitHub batch operation commands, examples, and plugin version/marketplace metadata updates.

Changes

Cohort / File(s) Summary
Plugin Removal: terminal-ui-design
terminal-ui-design/.claude-plugin/plugin.json, terminal-ui-design/CLAUDE.md, terminal-ui-design/README.md, terminal-ui-design/skills/terminal-ui-design/SKILL.md
Deleted terminal-ui-design plugin metadata, documentation, and skill files.
Marketplace & Root Docs
.claude-plugin/marketplace.json, marketplace.json, README.md, .github/ISSUE_TEMPLATE/feature_request.md
Removed terminal-ui-design references; updated marketplace metadata (lastUpdated, totalPlugins) and README entries; removed feature-request checklist item.
PR Automation Workflow
.github/workflows/pr-automation.yml, .github/workflows/pr-automation.md, github/examples/pr-automation.sh
Added GitHub Actions workflow and docs for auto-labeling, reviewer assignment, breaking-change detection, and first-time contributor welcome; included a Bash example script.
Commit Plugin & PR Templates
commit/.claude-plugin/plugin.json, commit/.pr-templates/bugfix.md, commit/.pr-templates/default.md, commit/.pr-templates/feature.md, commit/commands/and-create-pr.md
Bumped commit plugin version and description; added three PR templates and documented template-driven PR creation (template selection, draft support).
GitHub Plugin: Batch Ops & Docs
github/.claude-plugin/plugin.json, github/README.md, github/skills/github.md, github/commands/bulk-close-issues.md, github/commands/bulk-merge-prs.md, github/commands/bulk-label.md, github/examples/bulk-close-issues.sh, github/examples/bulk-merge-prs.sh, github/commands/watch-and-fix.md, github/examples/watch-and-fix.sh
Bumped github plugin version and description; added docs and example scripts for bulk-close, bulk-merge, bulk-label, and watch-and-fix workflows; expanded GitHub plugin README and skills documentation.
Marketplace & Changelog Updates
CHANGELOG.md, marketplace.json
Updated Unreleased and Version History entries to reflect removals, additions (batch commands, PR templates), and plugin version bumps.
Misc / Internal plugin metadata
commit/.claude-plugin/plugin.json, github/.claude-plugin/plugin.json
Plugin manifest updates: description expansions and version bumps (commit 1.2.1→1.3.0, github 1.1.0→1.3.0).

Sequence Diagram(s)

sequenceDiagram
    participant GH as GitHub
    participant WF as Workflow Runner
    participant API as GitHub API
    participant Script as pr-automation.sh
    participant PR as Pull Request

    GH->>WF: PR opened/reopened event
    WF->>Script: Run automation (passes PR number)
    Script->>API: gh pr diff --name-only (fetch changed files)
    API-->>Script: File list
    Script->>Script: Map files -> labels & reviewers rules
    Script->>API: Apply labels to PR
    Script->>API: Assign reviewers to PR
    Script->>API: Query author PR count
    alt First-time contributor (PR count = 1)
        Script->>API: Add first-time-contributor label
        Script->>API: Post welcome comment
    end
    Script-->>WF: Exit status
    WF-->>GH: Workflow completed (labels/reviewers/comments applied)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A plugin gently hops away,
New scripts tidy PRs each day,
Templates guide each careful plea,
Batch tools bustle busily,
I nibble changes—clean and spry.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: removing terminal-ui-design plugin and adding batch operations and PR templates to GitHub and commit plugins.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/remove-terminal-ui-add-github-enhancements

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the GitHub and commit plugins by introducing powerful batch operations and flexible PR templating, alongside a new GitHub Actions workflow for PR automation. These changes aim to streamline development workflows, improve efficiency in managing GitHub resources, and provide a more robust and user-friendly experience for contributors. The plugin ecosystem has also been refined through the consolidation of the terminal-ui-design plugin.

Highlights

  • Plugin Consolidation: The terminal-ui-design plugin has been removed and its functionality consolidated, streamlining the plugin ecosystem.
  • GitHub Plugin Enhancements: The GitHub plugin now includes new batch commands for bulk closing issues, merging pull requests, and applying labels, significantly improving workflow efficiency. Comprehensive documentation and examples for these new features have also been added.
  • Commit Plugin with PR Templates: The commit plugin has been upgraded to support PR templates (default, bugfix, feature) and allows for template selection based on commit type, as well as an option to create draft PRs.
  • Automated PR Workflows: A new GitHub Actions workflow has been introduced to automate PR labeling based on changed files, assign reviewers, and send welcome messages to first-time contributors.
  • Code Quality Improvements: Several code quality improvements were implemented, including fixing TOCTOU anti-patterns, replacing inefficient subshells with parameter expansion, and optimizing API call patterns in documentation examples.
Changelog
  • .claude-plugin/marketplace.json
    • Removed the 'terminal-ui-design' plugin entry.
    • Updated the 'commit' plugin's description and version to reflect new PR template features.
    • Updated the 'github' plugin's description and version to include batch operations.
    • Decremented the total plugin count from 13 to 12.
  • .github/ISSUE_TEMPLATE/feature_request.md
    • Removed the 'terminal-ui-design' checkbox from the feature request template.
  • CHANGELOG.md
    • Added new entries for GitHub batch commands, commit plugin PR templates, PR automation GitHub Action, and enhanced GitHub documentation.
    • Updated existing entries for GitHub and commit plugins to reflect new features.
    • Added a 'Removed' section detailing the removal of the 'terminal-ui-design' plugin.
  • README.md
    • Removed installation instructions and descriptions for the 'terminal-ui-design' plugin.
  • commit/.claude-plugin/plugin.json
    • Updated the plugin description to include PR workflow with templates.
    • Incremented the plugin version from 1.2.1 to 1.3.0.
  • commit/.pr-templates/bugfix.md
    • Added a new PR template specifically for bug fixes, including sections for summary, root cause, solution, changes, testing, regression risk, and related issues.
  • commit/.pr-templates/default.md
    • Added a new general-purpose PR template with sections for summary, changes, context, testing, and a checklist.
  • commit/.pr-templates/feature.md
    • Added a new PR template for new features, including sections for summary, motivation, implementation, changes, breaking changes, migration guide, testing, documentation, and related issues.
  • commit/commands/and-create-pr.md
    • Added new options for the /commit:and-create-pr command, including --template, --draft, --title, and --body.
    • Implemented logic to dynamically select PR templates based on commit type (fix, feat, other).
    • Improved template loading and placeholder replacement, with a fallback for missing templates.
    • Added examples for explicit template selection and creating draft PRs.
  • github/.claude-plugin/plugin.json
    • Updated the plugin description to include batch operations.
    • Incremented the plugin version from 1.1.0 to 1.2.0.
  • github/README.md
    • Added a new comprehensive README for the GitHub plugin, detailing its features, usage examples, real-world workflows, troubleshooting, and plugin structure.
  • github/commands/bulk-close-issues.md
    • Added a new command definition for /github:bulk-close-issues, allowing bulk closure of issues by label or search query with options for comments and dry runs.
  • github/commands/bulk-label.md
    • Added a new command definition for /github:bulk-label, enabling bulk application or removal of labels from issues/PRs by label, search query, or type.
  • github/commands/bulk-merge-prs.md
    • Added a new command definition for /github:bulk-merge-prs, facilitating bulk merging of approved PRs with options for merge method, branch deletion, and dry runs.
  • github/examples/bulk-close-issues.sh
    • Added a new example script demonstrating how to bulk close GitHub issues by label with confirmation and dry-run functionality.
  • github/examples/bulk-merge-prs.sh
    • Added a new example script illustrating how to bulk merge approved GitHub PRs with passing CI, including dry-run and squash merge options.
  • github/examples/pr-automation.sh
    • Added a new example script for PR automation, showcasing auto-labeling based on changed files, auto-assigning reviewers, and welcoming first-time contributors.
  • github/skills/github.md
    • Added a new 'Batch Operations' section detailing the usage of bulk close, merge, and label commands.
    • Expanded the 'Best Practices' section to include dedicated bulk commands and the importance of --dry-run.
    • Introduced a 'Common Gotchas' section covering rate limiting, authentication, branch detection, CI status, and JSON processing.
    • Added a 'Real-World Examples' section with detailed scripts for automated PR triage, bulk label updates, CI failure analysis, repository cleanup, and release automation.
    • Updated 'Notes' to emphasize --json output and --dry-run for bulk operations.
  • marketplace.json
    • Removed the 'terminal-ui-design' plugin entry.
    • Updated the 'commit' plugin's description and version to reflect new PR template features.
    • Updated the 'github' plugin's description and version to include batch operations.
    • Decremented the total plugin count from 13 to 12.
    • Updated the 'lastUpdated' metadata field.
  • terminal-ui-design/.claude-plugin/plugin.json
    • Removed the plugin manifest file for 'terminal-ui-design'.
  • terminal-ui-design/CLAUDE.md
    • Removed the CLAUDE.md documentation file for 'terminal-ui-design'.
  • terminal-ui-design/README.md
    • Removed the README.md documentation file for 'terminal-ui-design'.
  • terminal-ui-design/skills/terminal-ui-design/SKILL.md
    • Removed the skill definition file for 'terminal-ui-design'.
Ignored Files
  • Ignored by pattern: .github/workflows/** (2)
    • .github/workflows/pr-automation.md
    • .github/workflows/pr-automation.yml
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • In commit/commands/and-create-pr.md, the "Default branch" context line now has an unmatched backtick (the closing backtick after the command is missing), which will break the markdown formatting for that section.
  • The github/examples/pr-automation.sh script attempts to detect breaking changes by grepping FILES for "BREAKING CHANGE", but FILES only contains file paths from gh pr diff, so this check will never succeed; consider inspecting commit messages instead (e.g., via gh api or gh pr view --json commits).
  • Label names related to breaking changes are inconsistent across the repo (type:breaking in the workflow, breaking in the example script, and textual references elsewhere); aligning on a single canonical label name will avoid confusion for users and automation.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `commit/commands/and-create-pr.md`, the "Default branch" context line now has an unmatched backtick (the closing backtick after the command is missing), which will break the markdown formatting for that section.
- The `github/examples/pr-automation.sh` script attempts to detect breaking changes by grepping `FILES` for `"BREAKING CHANGE"`, but `FILES` only contains file paths from `gh pr diff`, so this check will never succeed; consider inspecting commit messages instead (e.g., via `gh api` or `gh pr view --json commits`).
- Label names related to breaking changes are inconsistent across the repo (`type:breaking` in the workflow, `breaking` in the example script, and textual references elsewhere); aligning on a single canonical label name will avoid confusion for users and automation.

## Individual Comments

### Comment 1
<location path=".github/workflows/pr-automation.yml" line_range="101-103" />
<code_context>
+          AUTHOR=${{ github.event.pull_request.user.login }}
+
+          # Check if this is the author's first PR
+          PR_COUNT=$(gh pr list --author "$AUTHOR" --state all --limit 1 --json number --jq 'length')
+
+          if [ "$PR_COUNT" -eq 1 ]; then
+            gh pr edit "$PR_NUMBER" --add-label "first-time-contributor"
+
</code_context>
<issue_to_address>
**issue (bug_risk):** The first-time contributor detection will evaluate to true for any author with at least one PR in this repo, not just their first.

With `--limit 1`, `jq 'length'` will only ever return `0` or `1`, so any author with at least one prior PR will still produce `PR_COUNT=1` and trigger the welcome logic on every PR. To detect a true first PR, you’ll need to count all PRs for the author (e.g., drop `--limit` or use an API that exposes `totalCount`) and only treat it as first-time when the count is exactly 1. Another option is to query closed/merged PRs and gate on those instead.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +101 to +103
PR_COUNT=$(gh pr list --author "$AUTHOR" --state all --limit 1 --json number --jq 'length')

if [ "$PR_COUNT" -eq 1 ]; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): The first-time contributor detection will evaluate to true for any author with at least one PR in this repo, not just their first.

With --limit 1, jq 'length' will only ever return 0 or 1, so any author with at least one prior PR will still produce PR_COUNT=1 and trigger the welcome logic on every PR. To detect a true first PR, you’ll need to count all PRs for the author (e.g., drop --limit or use an API that exposes totalCount) and only treat it as first-time when the count is exactly 1. Another option is to query closed/merged PRs and gate on those instead.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant enhancements, including batch operations for the GitHub plugin and pull request templates for the commit plugin, while also removing the terminal-ui-design plugin. However, a critical security vulnerability was identified in the bulk-merge-prs.sh example script, where a maliciously crafted PR title containing a newline could lead to unauthorized merging of other pull requests. Additionally, the review highlights areas for improving script robustness, clarifying documentation, and correcting examples, including a logic bug in the PR template selection and platform-specific commands in the documentation that could cause confusion.

Comment on lines +8 to +36
PRS=$(gh pr list --search "review:approved status:success" --limit 50 --json number,title --jq '.[] | "\(.number)|\(.title)"')

if [ -z "$PRS" ]; then
echo "No approved PRs with passing CI found"
exit 0
fi

PR_COUNT=$(echo "$PRS" | wc -l)
echo "Found $PR_COUNT PRs:"
echo "$PRS"

if [ "$1" = "--dry-run" ]; then
echo "DRY RUN - Would merge the PRs listed above"
exit 0
fi

# Confirm
read -p "Merge $PR_COUNT PRs with squash? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Aborted"
exit 1
fi

# Merge each PR
echo "$PRS" | while IFS='|' read -r number title; do
echo "Merging PR #$number: $title"
gh pr merge "$number" --squash --delete-branch
done
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The script is vulnerable to a newline injection attack. The output of gh pr list is parsed using a while read loop with | as a delimiter. Since PR titles can contain newlines, an attacker can craft a PR title that introduces a new line into the output. This new line will be processed as a separate PR by the loop, allowing the attacker to specify an arbitrary PR number to be merged. If the user approves the attacker's PR, the script will also merge the injected PR number, which might not have been approved.

PRS=$(gh pr list --search "review:approved status:success" --limit 50 --json number --jq '.[].number')

if [ -z "$PRS" ]; then
  echo "No approved PRs with passing CI found"
  exit 0
fi

PR_COUNT=$(echo "$PRS" | wc -l)
echo "Found $PR_COUNT PRs:"
echo "$PRS"

if [ "$1" = "--dry-run" ]; then
  echo "DRY RUN - Would merge the PRs listed above"
  exit 0
fi

# Confirm
read -p "Merge $PR_COUNT PRs with squash? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
  echo "Aborted"
  exit 1
fi

# Merge each PR
for number in $PRS; do
  echo "Merging PR #$number"
  gh pr merge "$number" --squash --delete-branch
done

Comment on lines +98 to +104
if PR_BODY=$(cat "$TEMPLATE" 2>/dev/null); then
# Replace placeholders with actual values
PR_BODY="${PR_BODY//\{\{ brief description of what this PR does \}\}/Brief description based on commit}"
else
# Fallback to simple body with proper newlines
PR_BODY=$'## Summary\n'"${COMMIT_MSG#*:}"$'\n\n## Changes\n- Key changes here'
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The logic for populating the PR body from a template only replaces the placeholder {{ brief description of what this PR does }}, which is specific to default.md. The other templates (bugfix.md, feature.md) use different placeholders (e.g., {{ issue description }}, {{ feature description }}) that will not be replaced. This will result in PRs created from these templates containing unfilled placeholders. Consider implementing a more robust replacement mechanism that can handle the different placeholders in each template.

Comment on lines +26 to +28
if echo "$FILES" | grep -q "BREAKING CHANGE"; then
gh pr edit "$pr_number" --add-label "breaking"
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The check for "BREAKING CHANGE" incorrectly searches within the list of changed file paths ($FILES) instead of the commit messages where this information is conventionally located. This will likely cause the check to always fail. You should inspect the PR's commit messages to correctly identify breaking changes.

Suggested change
if echo "$FILES" | grep -q "BREAKING CHANGE"; then
gh pr edit "$pr_number" --add-label "breaking"
fi
if gh pr view "$pr_number" --json commits --jq '.commits[].messageBody' | grep -q "BREAKING CHANGE"; then
gh pr edit "$pr_number" --add-label "breaking"
fi

- Current Git diff (staged and unstaged changes): !`git diff HEAD`
- Current branch: !`git branch --show-current`
- Default branch: !`git remote show origin | grep 'HEAD branch' | cut -d' ' -f5`
- Default branch: !`git remote show origin | grep 'HEAD branch' | cut -d' ' -f5'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There appears to be a typo in this command. The trailing single quote ' will cause a syntax error. It should be removed for the command to execute correctly.

Suggested change
- Default branch: !`git remote show origin | grep 'HEAD branch' | cut -d' ' -f5'
- Default branch: !`git remote show origin | grep 'HEAD branch' | cut -d' ' -f5`

Comment thread github/README.md
### Repository Cleanup
```bash
# Close stale draft PRs
gh pr list --search "draft:yes updated:<30 days ago" --json number --jq '.[].number' | \
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The date format updated:<30 days ago in the search query is not a valid format for the GitHub CLI, which expects dates in YYYY-MM-DD format. This example will fail as written. It should be updated to use a dynamic, correctly formatted date. For example, on macOS/BSD, you could use updated:<$(date -v-30d +%Y-%m-%d). On Linux, the equivalent is updated:<$(date --date='30 days ago' +%Y-%m-%d).

Suggested change
gh pr list --search "draft:yes updated:<30 days ago" --json number --jq '.[].number' | \
gh pr list --search "draft:yes updated:<$(date -v-30d +%Y-%m-%d)" --json number --jq '.[].number' | \

/github:bulk-close-issues --label "duplicate" --comment "Closing as duplicate of #123"

# Close issues older than 90 days
/github:bulk-close-issues --search "updated:<2025-12-01"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The example for closing issues by date uses a hardcoded future date (2025-12-01). This makes the example not immediately runnable and it will eventually become outdated. Please consider using a placeholder like YYYY-MM-DD or demonstrating how to generate a dynamic date to make the documentation more helpful and timeless.

Suggested change
/github:bulk-close-issues --search "updated:<2025-12-01"
/github:bulk-close-issues --search "updated:<YYYY-MM-DD"

/github:bulk-label --add "priority:urgent" --add "needs-review" --label "bug"

# Preview changes
/github:bulk-label --dry-run --add "quarter-1" --search "created:>=2025-01-01"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This example uses a hardcoded future date (2025-01-01), which is not ideal for documentation. To improve clarity and usability, please consider replacing it with a placeholder like YYYY-MM-DD or an example of how to generate a dynamic date.

Suggested change
/github:bulk-label --dry-run --add "quarter-1" --search "created:>=2025-01-01"
/github:bulk-label --dry-run --add "quarter-1" --search "created:>=YYYY-MM-DD"

Comment on lines +5 to +6
LABEL="${1:-stale}"
DRY_RUN="${2:-}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The argument parsing in this script is fragile. If a user runs ./bulk-close-issues.sh --dry-run, the script will incorrectly assign LABEL="--dry-run" and DRY_RUN="", leading to unexpected behavior. Consider using a more robust argument parsing method, such as a while loop with getopts or a case statement, to handle flags and positional arguments correctly.

Comment thread github/skills/github.md
### Repository Cleanup
```bash
# Close all stale draft PRs older than 30 days
gh pr list --search "draft:yes updated:<$(date -v-30d +%Y-%m-%d)" --json number --jq '.[].number' | \
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The date -v-30d command is specific to macOS/BSD systems. On Linux systems, which are common in CI/CD environments, the equivalent command is date --date='30 days ago'. For better portability and to avoid confusion, please consider adding a note about this platform difference or providing both versions of the command in the documentation.

- Add /github:watch-and-fix command that watches PR, fixes issues from AI reviews, and auto-merges when ready
- Add options: --auto-merge, --max-iterations, --dry-run, --pr
- Add watch-and-fix.sh example script with full implementation
- Update github plugin to v1.3.0
- Update documentation with watch-and-fix usage examples

Co-Authored-By: duyetbot <duyetbot@users.noreply.github.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 18

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/pr-automation.md:
- Around line 93-95: The example in the PR automation doc is incorrect: for a PR
changing "src/api/users.ts" it should not apply "area:backend" unless backend
paths are changed; update the example under the diff block that currently shows
"Labels applied: `area:api`, `area:backend`" so it only shows the correct
label(s) (e.g., remove `area:backend` and leave `area:api`) or adjust the
example text to state that `area:backend` is only added when backend paths are
also modified; edit the snippet that references "src/api/users.ts" to reflect
this corrected labeling behavior.

In @.github/workflows/pr-automation.yml:
- Line 5: The workflow currently triggers only on pull_request types
["opened","reopened"]; add "synchronize" to the pull_request event types so the
job also runs on new commits to existing PRs (update the pull_request.types
array to include "synchronize") to ensure labels/reviewer assignment and other
automation update after pushes.
- Around line 101-104: The PR-count check is wrong: change the gh pr list
invocation used to set PR_COUNT (currently using --limit 1) to request up to 2
PRs so you can detect "exactly one PR" (the current one); update the command
that sets PR_COUNT (the gh pr list call referencing AUTHOR) to use --limit 2 and
keep the existing equality check on PR_COUNT == 1 before calling gh pr edit with
PR_NUMBER to add the "first-time-contributor" label.

In `@commit/commands/and-create-pr.md`:
- Around line 99-100: The current PR_BODY replacement only substitutes a single
placeholder token and leaves other {{ ... }} tokens intact; update the PR_BODY
population logic (the PR_BODY variable handling/replacement block) to iterate
over all template tokens or apply a global regex replace to substitute every
{{...}} placeholder with the appropriate value (or a sensible default) rather
than only replacing the single literal string; ensure the replacement step runs
after all placeholder values are computed and verify no leftover {{...}} tokens
remain in PR_BODY before using it.
- Line 22: The inline shell command on the "Default branch" line is missing its
closing backtick causing broken interpolation; update the inline command so the
backticks properly wrap the shell invocation (the text starting with !`git
remote show origin | grep 'HEAD branch' | cut -d' ' -f5`) by replacing the
trailing single quote with a closing backtick so the line becomes !`...` and
renders correctly.
- Around line 90-95: The current extraction sets COMMIT_TYPE to the full token
before the colon (e.g., "feat(auth)"), so the case on "fix" and "feat" never
matches; change the extraction so COMMIT_TYPE is the bare type without scope (or
adapt the case to accept scoped forms). Specifically, after
COMMIT_TYPE="${COMMIT_MSG%%:*}", strip any scope suffix (e.g., remove "(...)"
using parameter expansion on COMMIT_TYPE) so it becomes "feat" or "fix", then
keep the existing case that references TEMPLATE_DIR/TPL_FEATURE,
TEMPLATE_DIR/TPL_BUGFIX and TEMPLATE_DIR/TPL_DEFAULT to select the template.

In `@github/commands/bulk-label.md`:
- Line 38: Replace the unsupported `file:` search qualifier in the example
invocation of the /github:bulk-label command; locate the example string
`/github:bulk-label --add "area:backend" --type pr --search "file:src/api/*"`
and either remove the `--search` argument or swap `"file:src/api/*"` for a
supported PR search qualifier such as `"base:main"`, `"label:backend"`,
`"author:USERNAME"`, or `"review-requested:TEAM"` so the example uses valid gh
pr list search syntax.

In `@github/examples/bulk-close-issues.sh`:
- Around line 5-7: The script currently only reads positional args into LABEL
and DRY_RUN (variables LABEL="${1:-stale}" and DRY_RUN="${2:-}") which conflicts
with the documented flag-based interface; update the argument parsing to accept
the documented flags (--label, --search, --comment, --state, --dry-run) (while
preserving backward-compatible positional fallbacks), set corresponding
variables (e.g., LABEL, SEARCH, COMMENT, STATE, DRY_RUN) accordingly, and
implement a simple getopt/getopts loop to parse flags and set defaults so flag
usage in github/commands/bulk-close-issues.md works as advertised.
- Around line 36-41: The script currently iterates over $ISSUES calling gh issue
close but always prints "Closed $ISSUE_COUNT issues" even when individual closes
fail; update the loop in bulk-close-issues.sh to track failures by checking each
gh invocation's exit status (or using set -e and trap) and increment a failure
counter (e.g., FAILED_COUNT) when a close fails, optionally printing per-issue
error output; after the loop, print a summary that uses ISSUE_COUNT and
FAILED_COUNT to report successes (ISSUE_COUNT - FAILED_COUNT) and failures
(FAILED_COUNT) and exit with non-zero status if any failures occurred.

In `@github/examples/bulk-merge-prs.sh`:
- Around line 33-38: The script currently prints "Merged $PR_COUNT PRs"
regardless of individual merge failures; modify the loop that reads from PRS and
calls gh pr merge to detect when gh pr merge fails (non-zero exit status) and
increment a failure counter (e.g., MERGE_FAILS) while still attempting remaining
merges, and also increment a success counter if desired; after the loop, update
the final reporting to show successes and failures (use PR_COUNT and MERGE_FAILS
to compute succeeded = PR_COUNT - MERGE_FAILS) and return a non-zero exit code
(exit 1) if MERGE_FAILS > 0 so the script accurately reflects merge failures
rather than always reporting full success.

In `@github/examples/pr-automation.sh`:
- Around line 56-59: PR_COUNT is computed with gh pr list --limit 1 which forces
length to be 0 or 1 and breaks first-time contributor detection; update the gh
pr list invocation in the PR_COUNT assignment (the line using PR_COUNT and
--limit 1) to remove the --limit 1 (or set it to a sufficiently large number) so
the --json number --jq 'length' returns the total number of PRs by $AUTHOR, then
keep the existing if [ "$PR_COUNT" -eq 1 ] check to correctly detect first-time
contributors.
- Around line 25-28: The script currently checks the FILES variable for the
literal string "BREAKING CHANGE" and applies the "breaking" label; change this
to inspect commit messages and apply the workflow's label "type:breaking".
Replace the check that uses echo "$FILES" | grep -q "BREAKING CHANGE" with a
commit-message check (e.g., use git log --format=%B -n 1 "$pr_branch" or git
show --format=%B "$commit_sha" | grep -q "BREAKING CHANGE") and then call gh pr
edit "$pr_number" --add-label "type:breaking" instead of "breaking"; keep
references to the existing variables FILES, pr_number and the gh pr edit
invocation so it's easy to locate and update.

In `@github/README.md`:
- Around line 150-164: Two fenced code blocks in the README (the repository tree
block and the commit message list block) lack language identifiers; update the
opening fences from ``` to ```text so markdownlint rule MD040 is satisfied.
Locate the block containing "github/ ├── .claude-plugin/" (the directory tree)
and the block containing the commit lines starting with "feat(github): add new
batch command" and change their fence markers to use "text" as the language
identifier, leaving the contents unchanged.
- Around line 77-83: The script incorrectly uses the user's repo count to infer
first-time contributors; instead, determine if the author has prior PRs in THIS
repository. For each PR (variable pr), get the author via gh pr view $pr --json
author --jq '.author.login' and then count that author's prior PRs in the same
repo with gh pr list --author <author> --json number --jq 'length' (or an
equivalent gh api call filtering by repo/author), and only call gh pr edit $pr
--add-label "first-time-contributor" when that count is 1 (meaning the current
PR is their first) or 0 prior PRs; update the existing use of gh pr list/gh pr
view/gh pr edit in the loop accordingly.

In `@github/skills/github.md`:
- Around line 423-425: The gh CLI command in the docs uses an unsupported --page
2 flag; remove the --page 2 token from the second occurrence of the gh pr list
command (the line that currently reads "gh pr list --limit 100 --json
number,title --jq '.[]' --page 2") and leave the command using only supported
flags (e.g., --limit and --json); ensure the example shows "gh pr list --limit
100 --json number,title" (and the intended --jq usage) so the docs reflect valid
gh pr list usage.
- Around line 469-477: The current PR-labeling snippet uses a username regex
(test("^[a-z0-9_-]{4,}$")) which misidentifies first-time contributors; replace
that logic with a per-author PR count check by listing PRs (gh pr list --json
author) and counting PRs for each .author.login, then only call gh pr edit
--add-label "first-time-contributor" for authors whose PR count equals 1; locate
the pipeline that reads into "number" and "author" (the while IFS=' ' read -r
number author loop) and change the selection step to compute or filter by the PR
count before invoking gh pr edit so only true first-time contributors are
labeled.
- Around line 505-507: The script uses a macOS/BSD-specific date flag (`date
-v-30d`) in the command starting with `gh pr list --search "draft:yes
updated:<$(date -v-30d +%Y-%m-%d)"`; replace this with a portable solution by
detecting the date implementation and using `date -d '30 days ago'` on GNU/Linux
or `date -v-30d` on macOS (e.g., add a small helper that sets a variable like
RECENT_DATE="$(date -d '30 days ago' +%Y-%m-%d 2>/dev/null || date -v-30d
+%Y-%m-%d)" and then use `gh pr list --search "draft:yes
updated:<${RECENT_DATE}"`), so the `gh pr list` invocation works on both GNU and
BSD/macOS systems.

In `@marketplace.json`:
- Around line 81-82: The plugin "description" field is out of sync between
registries: update the other marketplace.json's "description" JSON value to
exactly match the new string "GitHub operations using gh CLI - PRs, issues,
workflows, batch operations, and smart branch detection" so both registry
manifests advertise the same capabilities; ensure you edit the "description" key
in the other manifest that still contains the previous text and leave the
version field unchanged unless an actual version bump is required.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: cf810ff1-83ea-45c2-9351-cfff746908ea

📥 Commits

Reviewing files that changed from the base of the PR and between 89d8264 and 0f55da6.

📒 Files selected for processing (25)
  • .claude-plugin/marketplace.json
  • .github/ISSUE_TEMPLATE/feature_request.md
  • .github/workflows/pr-automation.md
  • .github/workflows/pr-automation.yml
  • CHANGELOG.md
  • README.md
  • commit/.claude-plugin/plugin.json
  • commit/.pr-templates/bugfix.md
  • commit/.pr-templates/default.md
  • commit/.pr-templates/feature.md
  • commit/commands/and-create-pr.md
  • github/.claude-plugin/plugin.json
  • github/README.md
  • github/commands/bulk-close-issues.md
  • github/commands/bulk-label.md
  • github/commands/bulk-merge-prs.md
  • github/examples/bulk-close-issues.sh
  • github/examples/bulk-merge-prs.sh
  • github/examples/pr-automation.sh
  • github/skills/github.md
  • marketplace.json
  • terminal-ui-design/.claude-plugin/plugin.json
  • terminal-ui-design/CLAUDE.md
  • terminal-ui-design/README.md
  • terminal-ui-design/skills/terminal-ui-design/SKILL.md
💤 Files with no reviewable changes (7)
  • terminal-ui-design/.claude-plugin/plugin.json
  • .claude-plugin/marketplace.json
  • terminal-ui-design/skills/terminal-ui-design/SKILL.md
  • terminal-ui-design/README.md
  • README.md
  • .github/ISSUE_TEMPLATE/feature_request.md
  • terminal-ui-design/CLAUDE.md

Comment on lines +93 to +95
For a PR changing `src/api/users.ts`:
- Labels applied: `area:api`, `area:backend`
- Reviewers assigned: `api-team`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Example output labels are inconsistent with the documented path rules.

For a PR changing src/api/users.ts, area:backend should not be listed unless backend paths are also changed.

Suggested fix
-For a PR changing `src/api/users.ts`:
-- Labels applied: `area:api`, `area:backend`
+For a PR changing `src/api/users.ts`:
+- Labels applied: `area:api`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
For a PR changing `src/api/users.ts`:
- Labels applied: `area:api`, `area:backend`
- Reviewers assigned: `api-team`
For a PR changing `src/api/users.ts`:
- Labels applied: `area:api`
- Reviewers assigned: `api-team`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/pr-automation.md around lines 93 - 95, The example in the
PR automation doc is incorrect: for a PR changing "src/api/users.ts" it should
not apply "area:backend" unless backend paths are changed; update the example
under the diff block that currently shows "Labels applied: `area:api`,
`area:backend`" so it only shows the correct label(s) (e.g., remove
`area:backend` and leave `area:api`) or adjust the example text to state that
`area:backend` is only added when backend paths are also modified; edit the
snippet that references "src/api/users.ts" to reflect this corrected labeling
behavior.


on:
pull_request:
types: [opened, reopened]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Workflow should react to new commits on existing PRs.

Only opened and reopened are handled. Without synchronize, labels/reviewer assignment won't update after subsequent pushes.

Suggested fix
-    types: [opened, reopened]
+    types: [opened, reopened, synchronize]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
types: [opened, reopened]
types: [opened, reopened, synchronize]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/pr-automation.yml at line 5, The workflow currently
triggers only on pull_request types ["opened","reopened"]; add "synchronize" to
the pull_request event types so the job also runs on new commits to existing PRs
(update the pull_request.types array to include "synchronize") to ensure
labels/reviewer assignment and other automation update after pushes.

Comment on lines +101 to +104
PR_COUNT=$(gh pr list --author "$AUTHOR" --state all --limit 1 --json number --jq 'length')

if [ "$PR_COUNT" -eq 1 ]; then
gh pr edit "$PR_NUMBER" --add-label "first-time-contributor"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/pr-automation.yml | sed -n '90,115p'

Repository: duyet/claude-plugins

Length of output: 1290


🏁 Script executed:

# Verify the --limit 1 behavior and confirm the jq 'length' logic is the issue
# by checking if there are any other PR filtering mechanisms in the file

rg -n "gh pr list" .github/workflows/pr-automation.yml

Repository: duyet/claude-plugins

Length of output: 169


First-time contributor detection is logically incorrect and produces false positives.

At Line 101, using --limit 1 with jq 'length' returns at most 0 or 1. This means the condition on Line 103 triggers whenever the author has any existing PR, not just for first-time contributors. Any returning contributor opening a new PR will be incorrectly labeled.

The fix requires checking if the author has exactly one PR (the current one) by increasing the limit to 2:

Suggested fix
-PR_COUNT=$(gh pr list --author "$AUTHOR" --state all --limit 1 --json number --jq 'length')
+PR_COUNT=$(gh pr list --author "$AUTHOR" --state all --limit 2 --json number --jq 'length')
 
-if [ "$PR_COUNT" -eq 1 ]; then
+if [ "${{ github.event.action }}" = "opened" ] && [ "$PR_COUNT" -eq 1 ]; then
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
PR_COUNT=$(gh pr list --author "$AUTHOR" --state all --limit 1 --json number --jq 'length')
if [ "$PR_COUNT" -eq 1 ]; then
gh pr edit "$PR_NUMBER" --add-label "first-time-contributor"
PR_COUNT=$(gh pr list --author "$AUTHOR" --state all --limit 2 --json number --jq 'length')
if [ "${{ github.event.action }}" = "opened" ] && [ "$PR_COUNT" -eq 1 ]; then
gh pr edit "$PR_NUMBER" --add-label "first-time-contributor"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/pr-automation.yml around lines 101 - 104, The PR-count
check is wrong: change the gh pr list invocation used to set PR_COUNT (currently
using --limit 1) to request up to 2 PRs so you can detect "exactly one PR" (the
current one); update the command that sets PR_COUNT (the gh pr list call
referencing AUTHOR) to use --limit 2 and keep the existing equality check on
PR_COUNT == 1 before calling gh pr edit with PR_NUMBER to add the
"first-time-contributor" label.

- Current Git diff (staged and unstaged changes): !`git diff HEAD`
- Current branch: !`git branch --show-current`
- Default branch: !`git remote show origin | grep 'HEAD branch' | cut -d' ' -f5`
- Default branch: !`git remote show origin | grep 'HEAD branch' | cut -d' ' -f5'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix the broken inline command delimiter on default-branch line.

Line 22 appears to miss the closing backtick for the ! command, which can break command interpolation in this command spec.

Suggested fix
-- Default branch: !`git remote show origin | grep 'HEAD branch' | cut -d' ' -f5'
+- Default branch: !`git remote show origin | grep 'HEAD branch' | cut -d' ' -f5`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- Default branch: !`git remote show origin | grep 'HEAD branch' | cut -d' ' -f5'
- Default branch: !`git remote show origin | grep 'HEAD branch' | cut -d' ' -f5`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@commit/commands/and-create-pr.md` at line 22, The inline shell command on the
"Default branch" line is missing its closing backtick causing broken
interpolation; update the inline command so the backticks properly wrap the
shell invocation (the text starting with !`git remote show origin | grep 'HEAD
branch' | cut -d' ' -f5`) by replacing the trailing single quote with a closing
backtick so the line becomes !`...` and renders correctly.

Comment on lines +90 to +95
COMMIT_TYPE="${COMMIT_MSG%%:*}" # Extract first word before colon
case "$COMMIT_TYPE" in
fix) TEMPLATE="${TEMPLATE_DIR}/${TPL_BUGFIX}.md" ;;
feat) TEMPLATE="${TEMPLATE_DIR}/${TPL_FEATURE}.md" ;;
*) TEMPLATE="${TEMPLATE_DIR}/${TPL_DEFAULT}.md" ;;
esac
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Find the file and check if it exists
find . -name "and-create-pr.md" -o -name "and-create-pr.sh" | head -20

Repository: duyet/claude-plugins

Length of output: 130


🏁 Script executed:

# List files in commit directory
ls -la commit/ 2>/dev/null || echo "commit directory not found in root"
find . -path "*/commit/*" -type f | head -20

Repository: duyet/claude-plugins

Length of output: 752


🏁 Script executed:

# Search for COMMIT_TYPE extraction pattern
rg "COMMIT_TYPE.*COMMIT_MSG" --max-count 10

Repository: duyet/claude-plugins

Length of output: 163


🏁 Script executed:

# Read the file to see the context around lines 90-95
wc -l commit/commands/and-create-pr.md

Repository: duyet/claude-plugins

Length of output: 100


🏁 Script executed:

# Read specific lines with context
sed -n '85,100p' commit/commands/and-create-pr.md

Repository: duyet/claude-plugins

Length of output: 682


🏁 Script executed:

# Test the extraction logic with scoped commits
cat > /tmp/test_commit.sh << 'EOF'
#!/bin/bash

# Test current extraction
COMMIT_MSG='feat(auth): add OAuth login'
COMMIT_TYPE="${COMMIT_MSG%%:*}"
echo "Input: $COMMIT_MSG"
echo "Current extraction (%%:*): $COMMIT_TYPE"
echo "Expected for case match: feat"
echo "Does 'feat' match '$COMMIT_TYPE'? $([ "$COMMIT_TYPE" = "feat" ] && echo 'NO - FAILS' || echo 'YES - WORKS')"
echo ""

# Test the suggested fix
COMMIT_PREFIX="${COMMIT_MSG%%:*}"
COMMIT_TYPE="${COMMIT_PREFIX%%(*}"
echo "Suggested fix:"
echo "  COMMIT_PREFIX: $COMMIT_PREFIX"
echo "  COMMIT_TYPE: $COMMIT_TYPE"
echo "  Match test: $([ "$COMMIT_TYPE" = "feat" ] && echo 'YES - WORKS' || echo 'NO - FAILS')"
EOF
bash /tmp/test_commit.sh

Repository: duyet/claude-plugins

Length of output: 300


🏁 Script executed:

# Final validation: test actual bash case statement behavior
cat > /tmp/case_test.sh << 'EOF'
#!/bin/bash

test_case() {
  local COMMIT_TYPE="$1"
  echo "Testing COMMIT_TYPE='$COMMIT_TYPE':"
  case "$COMMIT_TYPE" in
    fix) echo "  Result: BUGFIX template" ;;
    feat) echo "  Result: FEATURE template" ;;
    *) echo "  Result: DEFAULT template (BUG!)" ;;
  esac
}

echo "=== CURRENT IMPLEMENTATION (BROKEN) ==="
COMMIT_MSG='feat(auth): add OAuth login'
COMMIT_TYPE="${COMMIT_MSG%%:*}"
test_case "$COMMIT_TYPE"

echo ""
echo "=== PROPOSED FIX (WORKING) ==="
COMMIT_PREFIX="${COMMIT_MSG%%:*}"
COMMIT_TYPE="${COMMIT_PREFIX%%(*}"
test_case "$COMMIT_TYPE"

echo ""
echo "=== TEST WITH fix SCOPE ==="
COMMIT_MSG='fix(bugfix): resolve issue'
COMMIT_PREFIX="${COMMIT_MSG%%:*}"
COMMIT_TYPE="${COMMIT_PREFIX%%(*}"
test_case "$COMMIT_TYPE"
EOF
bash /tmp/case_test.sh

Repository: duyet/claude-plugins

Length of output: 340


Template selection fails for all scoped conventional commits.

Line 90 extracts feat(auth) from feat(auth): ..., so the case statement at lines 91-95 won't match feat or fix and always falls back to default template. Since the project mandates scoped commits (feat(plugin), fix(plugin), docs(plugin)), this breaks template selection for all commits.

Suggested fix
-COMMIT_TYPE="${COMMIT_MSG%%:*}"  # Extract first word before colon
+COMMIT_PREFIX="${COMMIT_MSG%%:*}"   # e.g. feat(auth)
+COMMIT_TYPE="${COMMIT_PREFIX%%(*}"  # e.g. feat
 case "$COMMIT_TYPE" in
   fix) TEMPLATE="${TEMPLATE_DIR}/${TPL_BUGFIX}.md" ;;
   feat) TEMPLATE="${TEMPLATE_DIR}/${TPL_FEATURE}.md" ;;
   *) TEMPLATE="${TEMPLATE_DIR}/${TPL_DEFAULT}.md" ;;
 esac
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
COMMIT_TYPE="${COMMIT_MSG%%:*}" # Extract first word before colon
case "$COMMIT_TYPE" in
fix) TEMPLATE="${TEMPLATE_DIR}/${TPL_BUGFIX}.md" ;;
feat) TEMPLATE="${TEMPLATE_DIR}/${TPL_FEATURE}.md" ;;
*) TEMPLATE="${TEMPLATE_DIR}/${TPL_DEFAULT}.md" ;;
esac
COMMIT_PREFIX="${COMMIT_MSG%%:*}" # e.g. feat(auth)
COMMIT_TYPE="${COMMIT_PREFIX%%(*}" # e.g. feat
case "$COMMIT_TYPE" in
fix) TEMPLATE="${TEMPLATE_DIR}/${TPL_BUGFIX}.md" ;;
feat) TEMPLATE="${TEMPLATE_DIR}/${TPL_FEATURE}.md" ;;
*) TEMPLATE="${TEMPLATE_DIR}/${TPL_DEFAULT}.md" ;;
esac
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 95-95: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@commit/commands/and-create-pr.md` around lines 90 - 95, The current
extraction sets COMMIT_TYPE to the full token before the colon (e.g.,
"feat(auth)"), so the case on "fix" and "feat" never matches; change the
extraction so COMMIT_TYPE is the bare type without scope (or adapt the case to
accept scoped forms). Specifically, after COMMIT_TYPE="${COMMIT_MSG%%:*}", strip
any scope suffix (e.g., remove "(...)" using parameter expansion on COMMIT_TYPE)
so it becomes "feat" or "fix", then keep the existing case that references
TEMPLATE_DIR/TPL_FEATURE, TEMPLATE_DIR/TPL_BUGFIX and TEMPLATE_DIR/TPL_DEFAULT
to select the template.

Comment thread github/README.md
Comment on lines +150 to +164
```
github/
├── .claude-plugin/
│ └── plugin.json # Manifest (version 1.2.0)
├── commands/ # Slash commands
│ ├── bulk-close-issues.md
│ ├── bulk-merge-prs.md
│ └── bulk-label.md
├── skills/ # Reusable knowledge
│ └── github.md
└── examples/ # Example scripts
├── bulk-close-issues.sh
├── bulk-merge-prs.sh
└── pr-automation.sh
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add language identifiers to fenced code blocks (MD040).

Two fenced blocks are missing language tags, which is currently flagged by markdownlint.

Suggested fix
-```
+```text
 github/
 ├── .claude-plugin/
 │   └── plugin.json          # Manifest (version 1.2.0)
@@
-```
+```

-```
+```text
 feat(github): add new batch command
 fix(github): fix issue listing pagination
 docs(github): update examples
-```
+```

Also applies to: 188-192

🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 150-150: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/README.md` around lines 150 - 164, Two fenced code blocks in the
README (the repository tree block and the commit message list block) lack
language identifiers; update the opening fences from ``` to ```text so
markdownlint rule MD040 is satisfied. Locate the block containing "github/ ├──
.claude-plugin/" (the directory tree) and the block containing the commit lines
starting with "feat(github): add new batch command" and change their fence
markers to use "text" as the language identifier, leaving the contents
unchanged.

Comment thread github/skills/github.md
Comment on lines +423 to +425
gh pr list --limit 100 --json number,title | jq '.[]'
gh pr list --limit 100 --json number,title --jq '.[]' --page 2
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, find and read the file around lines 423-425
if [ -f "github/skills/github.md" ]; then
  sed -n '420,430p' github/skills/github.md
else
  echo "File not found, searching for it..."
  find . -name "github.md" -path "*/github/skills/*" 2>/dev/null | head -5
fi

Repository: duyet/claude-plugins

Length of output: 255


🌐 Web query:

GitHub CLI gh pr list --page flag pagination options

💡 Result:

gh pr list does not support a --page flag. The built-in pagination control is --limit (default 30), which tells gh how many PRs to fetch; gh will page internally as needed until it reaches that limit. [1]

What to use instead

  • Fetch more PRs in one go:
    • gh pr list --limit 100 (or any higher number you need) [1]
  • If you truly need manual page/offset-style pagination, switch to the API:
    • gh api --paginate ... (REST auto-pagination) [2]
    • For GraphQL, you must implement cursor pagination (pageInfo { hasNextPage endCursor }) and loop with --paginate. [2]

Docs

  • gh pr list options (shows --limit and no --page): [1]

Sources
[1] GitHub CLI manual: gh pr listhttps://cli.github.com/manual/gh_pr_list
[2] GitHub CLI discussion on gh api --paginatecli/cli#3257


🏁 Script executed:

# Read the actual file around the lines in question
sed -n '420,430p' "github/skills/github.md" | cat -n

Repository: duyet/claude-plugins

Length of output: 332


🏁 Script executed:

# The line numbers don't match. Let me search for the file content containing the pr list commands
rg "gh pr list.*--limit 100.*--json number,title" "github/skills/github.md" -A 1 -B 1 -n

Repository: duyet/claude-plugins

Length of output: 241


🏁 Script executed:

# Also search more broadly for the specific commands mentioned
rg "gh pr list" "github/skills/github.md" -n

Repository: duyet/claude-plugins

Length of output: 959


Remove --page 2 flag from the gh pr list command — it is not supported.

Line 447 uses --page 2 which is invalid for gh pr list. The command lacks pagination support for fetching "pages" of results; --limit sets the total number of results fetched, not pages.

Suggested fix
-gh pr list --limit 100 --json number,title --jq '.[]' --page 2
+gh api --paginate "repos/{owner}/{repo}/pulls" --jq '.[] | {number, title}'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/skills/github.md` around lines 423 - 425, The gh CLI command in the
docs uses an unsupported --page 2 flag; remove the --page 2 token from the
second occurrence of the gh pr list command (the line that currently reads "gh
pr list --limit 100 --json number,title --jq '.[]' --page 2") and leave the
command using only supported flags (e.g., --limit and --json); ensure the
example shows "gh pr list --limit 100 --json number,title" (and the intended
--jq usage) so the docs reflect valid gh pr list usage.

Comment thread github/skills/github.md
Comment on lines +469 to +477
```bash
# Label all PRs from first-time contributors (efficient batch approach)
gh pr list --author . --json number,author --jq '.[] |
select(.author.login | test("^[a-z0-9_-]{4,}$")) |
"\(.number) \(.author.login)"' | \
while IFS=' ' read -r number author; do
# Quick check for first-timers (avoid API call for known contributors)
gh pr edit "$number" --add-label "first-time-contributor" 2>/dev/null || true
done
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd github/skills && wc -l github.md

Repository: duyet/claude-plugins

Length of output: 77


🏁 Script executed:

cd github/skills && sed -n '469,477p' github.md

Repository: duyet/claude-plugins

Length of output: 243


🏁 Script executed:

cd github/skills && sed -n '460,485p' github.md

Repository: duyet/claude-plugins

Length of output: 605


🏁 Script executed:

cd github/skills && grep -n "first-time-contributor\|first-time contributor" github.md

Repository: duyet/claude-plugins

Length of output: 322


🏁 Script executed:

cd github/skills && grep -n "gh pr list.*author.*json" github.md

Repository: duyet/claude-plugins

Length of output: 122


🏁 Script executed:

cd github/skills && grep -n "select.*author\.login.*test" github.md

Repository: duyet/claude-plugins

Length of output: 120


🏁 Script executed:

cd github/skills && sed -n '493,505p' github.md

Repository: duyet/claude-plugins

Length of output: 699


Incorrect line numbers; the issue is confirmed as valid.

The actual code is at lines 493-505, not 469-477. Your analysis is correct: the username pattern check (^[a-z0-9_-]{4,}$) is unrelated to contribution history and will incorrectly label many contributors as first-time contributors regardless of their actual PR count. The suggested fix properly detects first-time contributors by counting PRs from each author and labeling only those with exactly one PR.

Suggested fix
-gh pr list --author . --json number,author --jq '.[] |
-  select(.author.login | test("^[a-z0-9_-]{4,}$")) |
-  "\(.number) \(.author.login)"' | \
-  while IFS=' ' read -r number author; do
-    # Quick check for first-timers (avoid API call for known contributors)
-    gh pr edit "$number" --add-label "first-time-contributor" 2>/dev/null || true
-  done
+gh pr list --json number,author --jq '.[] | "\(.number) \(.author.login)"' | \
+  while IFS=' ' read -r number author; do
+    pr_count=$(gh pr list --author "$author" --state all --limit 2 --json number --jq 'length')
+    if [ "$pr_count" -eq 1 ]; then
+      gh pr edit "$number" --add-label "first-time-contributor" 2>/dev/null || true
+    fi
+  done
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```bash
# Label all PRs from first-time contributors (efficient batch approach)
gh pr list --author . --json number,author --jq '.[] |
select(.author.login | test("^[a-z0-9_-]{4,}$")) |
"\(.number) \(.author.login)"' | \
while IFS=' ' read -r number author; do
# Quick check for first-timers (avoid API call for known contributors)
gh pr edit "$number" --add-label "first-time-contributor" 2>/dev/null || true
done
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 469-469: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/skills/github.md` around lines 469 - 477, The current PR-labeling
snippet uses a username regex (test("^[a-z0-9_-]{4,}$")) which misidentifies
first-time contributors; replace that logic with a per-author PR count check by
listing PRs (gh pr list --json author) and counting PRs for each .author.login,
then only call gh pr edit --add-label "first-time-contributor" for authors whose
PR count equals 1; locate the pipeline that reads into "number" and "author"
(the while IFS=' ' read -r number author loop) and change the selection step to
compute or filter by the PR count before invoking gh pr edit so only true
first-time contributors are labeled.

Comment thread github/skills/github.md
Comment on lines +505 to +507
# Close all stale draft PRs older than 30 days
gh pr list --search "draft:yes updated:<$(date -v-30d +%Y-%m-%d)" --json number --jq '.[].number' | \
while read pr; do
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find and examine the github.md file
find . -name "github.md" -type f | head -20

Repository: duyet/claude-plugins

Length of output: 89


🏁 Script executed:

# Check if the file exists and read the relevant lines
if [ -f "github/skills/github.md" ]; then
  echo "=== File found. Reading lines 500-510 ==="
  sed -n '500,510p' "github/skills/github.md" | cat -n
else
  echo "File not found at github/skills/github.md"
fi

Repository: duyet/claude-plugins

Length of output: 490


🏁 Script executed:

# Search for the specific code pattern in the github.md file
grep -n "draft:yes" "github/skills/github.md" | cat -n

Repository: duyet/claude-plugins

Length of output: 176


🏁 Script executed:

# Also search for "date -v-30d" to find the exact location
grep -n "date -v-30d" "github/skills/github.md" | cat -n

Repository: duyet/claude-plugins

Length of output: 176


🏁 Script executed:

# Read the context around line 529
sed -n '525,535p' "github/skills/github.md" | cat -n

Repository: duyet/claude-plugins

Length of output: 510


🌐 Web query:

date command -v flag BSD GNU Linux portability differences

💡 Result:

Key portability point

date -v ... is not POSIX, and it’s not supported by GNU date. On GNU/Linux (coreutils), relative/parsed dates are done with -d/--date, not -v. [1]

BSD/macOS/FreeBSD: -v = adjust components relative/absolute

On FreeBSD (and typically macOS’s BSD date), -v[+|-]val[y|m|w|d|H|M|S] adjusts the current (or specified) date by years/months/weeks/days/hours/minutes/seconds, and you can repeat -v multiple times (processed in order). Examples: -v+1d, -v-2H, -v1m (set month), etc. [2]

GNU/Linux (coreutils): use -d/--date instead

GNU date uses --date=STRING / -d STRING to parse expressions like "next friday", "yesterday", "2026-03-04 10:00", etc. [1]

Not all BSDs have -v

OpenBSD’s date(1) does not include -v (it has options like -f, -j, -r, -z, etc.), so even “BSD portability” is not guaranteed. [3]

Practical portable pattern

  • If you control the platform:
    • BSD/macOS/FreeBSD: date -v+1d ... [2]
    • GNU/Linux: date -d 'now + 1 day' ... [1]
  • If you need one script across systems: detect GNU vs BSD (date --version works on GNU) and branch, or use a language runtime (Python/Perl) for date arithmetic.

Sources: GNU coreutils date options [1]; FreeBSD date(1) including -v [2]; OpenBSD date(1) (no -v) [3].


Correct line numbers: lines 529-530 (not 505-507). The portability concern is valid.

date -v-30d is BSD/macOS-specific and unsupported by GNU date on Linux systems. The -v flag does not exist in GNU coreutils; use -d for relative date expressions instead.

Suggested fix
-gh pr list --search "draft:yes updated:<$(date -v-30d +%Y-%m-%d)" --json number --jq '.[].number' | \
+cutoff=$(date -u -d '30 days ago' +%Y-%m-%d 2>/dev/null || date -u -v-30d +%Y-%m-%d)
+gh pr list --search "draft:yes updated:<$cutoff" --json number --jq '.[].number' | \
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Close all stale draft PRs older than 30 days
gh pr list --search "draft:yes updated:<$(date -v-30d +%Y-%m-%d)" --json number --jq '.[].number' | \
while read pr; do
# Close all stale draft PRs older than 30 days
cutoff=$(date -u -d '30 days ago' +%Y-%m-%d 2>/dev/null || date -u -v-30d +%Y-%m-%d)
gh pr list --search "draft:yes updated:<$cutoff" --json number --jq '.[].number' | \
while read pr; do
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/skills/github.md` around lines 505 - 507, The script uses a
macOS/BSD-specific date flag (`date -v-30d`) in the command starting with `gh pr
list --search "draft:yes updated:<$(date -v-30d +%Y-%m-%d)"`; replace this with
a portable solution by detecting the date implementation and using `date -d '30
days ago'` on GNU/Linux or `date -v-30d` on macOS (e.g., add a small helper that
sets a variable like RECENT_DATE="$(date -d '30 days ago' +%Y-%m-%d 2>/dev/null
|| date -v-30d +%Y-%m-%d)" and then use `gh pr list --search "draft:yes
updated:<${RECENT_DATE}"`), so the `gh pr list` invocation works on both GNU and
BSD/macOS systems.

Comment thread marketplace.json Outdated
Comment on lines +81 to +82
"description": "GitHub operations using gh CLI - PRs, issues, workflows, batch operations, and smart branch detection",
"version": "1.2.0",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Synchronize GitHub plugin description across both marketplace registries.

Line 81 now advertises batch operations, but .claude-plugin/marketplace.json:48-51 still has the previous description. This can cause inconsistent plugin metadata depending on which registry is read.

Suggested alignment
--- a/.claude-plugin/marketplace.json
+++ b/.claude-plugin/marketplace.json
@@
-  "description": "GitHub operations using gh CLI - PRs, workflows, issues, repositories, and smart branch detection for implementation workflows"
+  "description": "GitHub operations using gh CLI - PRs, issues, workflows, batch operations, and smart branch detection"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@marketplace.json` around lines 81 - 82, The plugin "description" field is out
of sync between registries: update the other marketplace.json's "description"
JSON value to exactly match the new string "GitHub operations using gh CLI -
PRs, issues, workflows, batch operations, and smart branch detection" so both
registry manifests advertise the same capabilities; ensure you edit the
"description" key in the other manifest that still contains the previous text
and leave the version field unchanged unless an actual version bump is required.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

♻️ Duplicate comments (6)
marketplace.json (1)

81-82: ⚠️ Potential issue | 🟡 Minor

Keep GitHub plugin description synchronized across manifests.

marketplace.json and github/.claude-plugin/plugin.json describe different capability sets for the same plugin version, which can produce inconsistent catalog metadata.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@marketplace.json` around lines 81 - 82, The marketplace.json "description"
for version "1.3.0" is out of sync with github/.claude-plugin/plugin.json;
update the plugin metadata so both manifests share the same capability
description for the same "version" (e.g., align the "description" field in
marketplace.json with the "description" in github/.claude-plugin/plugin.json or
vice versa), or centralize the source of truth and propagate it to both files so
catalog metadata remains consistent.
github/skills/github.md (3)

446-448: ⚠️ Potential issue | 🟠 Major

Remove unsupported --page usage from gh pr list examples.

gh pr list examples currently include --page, which is not a valid flag for this command. This makes both the gotcha snippet and final note incorrect.

Suggested doc fix
-gh pr list --limit 100 --json number,title --jq '.[]' --page 2
+gh pr list --limit 100 --json number,title --jq '.[]'

-- Large operations may require pagination with `--limit` and `--page`
+- Large operations may require higher `--limit`, or `gh api --paginate` for explicit pagination

Also applies to: 564-565

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/skills/github.md` around lines 446 - 448, The examples use an
unsupported --page flag with the gh pr list command and also show a mistaken
mixed usage of --json and --jq; remove the unsupported --page 2 token from the
example(s) and update the surrounding gotcha/final note to no longer reference
--page, leaving the valid invocation(s) such as gh pr list --limit 100 --json
number,title (and gh pr list --limit 100 --json number,title --jq '.[]' if you
intend to demonstrate jq-style filtering), and make the same removal/update for
the duplicate occurrence that appears later in the file; ensure references to
--page are deleted and examples show only supported flags for gh pr list.

493-500: ⚠️ Potential issue | 🟠 Major

First-time contributor labeling logic is incorrect.

The regex-based username check does not represent contribution history and can mislabel contributors.

Suggested doc fix
-gh pr list --author . --json number,author --jq '.[] |
-  select(.author.login | test("^[a-z0-9_-]{4,}$")) |
-  "\(.number) \(.author.login)"' | \
+gh pr list --json number,author --jq '.[] | "\(.number) \(.author.login)"' | \
   while IFS=' ' read -r number author; do
-    # Quick check for first-timers (avoid API call for known contributors)
-    gh pr edit "$number" --add-label "first-time-contributor" 2>/dev/null || true
+    pr_count=$(gh pr list --author "$author" --state all --limit 2 --json number --jq 'length')
+    if [ "$pr_count" -eq 1 ]; then
+      gh pr edit "$number" --add-label "first-time-contributor" 2>/dev/null || true
+    fi
   done
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/skills/github.md` around lines 493 - 500, The current approach uses a
regex on the username in the gh pr list pipeline (the select(.author.login |
test("^[a-z0-9_-]{4,}$")) step and subsequent while loop/gh pr edit) which
misclassifies contributors; replace the regex check with a real
contribution-history check by calling the GitHub API for each PR author (e.g.,
via gh api) to verify whether they have previous contributions/merged PRs or
prior activity in the repo before adding the "first-time-contributor" label, and
update the pipeline so gh pr edit is invoked only when the API response confirms
zero prior contributions for that author.

529-530: ⚠️ Potential issue | 🟠 Major

Use portable date arithmetic in shell examples.

date -v-30d is BSD/macOS-specific and fails on GNU/Linux.

Suggested doc fix
-gh pr list --search "draft:yes updated:<$(date -v-30d +%Y-%m-%d)" --json number --jq '.[].number' | \
+cutoff=$(date -u -d '30 days ago' +%Y-%m-%d 2>/dev/null || date -u -v-30d +%Y-%m-%d)
+gh pr list --search "draft:yes updated:<$cutoff" --json number --jq '.[].number' | \
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/skills/github.md` around lines 529 - 530, The example uses BSD-only
date arithmetic ("date -v-30d") in the gh pr list command, which breaks on
GNU/Linux; replace the inline date substitution used in the gh pr list example
with a portable approach such as computing a 30-day-ago value with a fallback
that supports both BSD and GNU (e.g., set a DATE_30_DAYS_AGO variable using date
-v-30d ... 2>/dev/null || date -d '30 days ago' ... and then use that variable
in the gh pr list --search string), and update the snippet referencing the
substitution used with gh pr list to use that variable instead (refer to the gh
pr list --search "draft:yes updated:<$(...)" usage in the diff).
github/README.md (2)

170-186: ⚠️ Potential issue | 🟡 Minor

Add language identifiers to fenced code blocks.

The repository tree and commit-convention fenced blocks are missing language tags.

Suggested fix
-```
+```text
 github/
@@
-```
+```

-```
+```text
 feat(github): add new batch command
 fix(github): fix issue listing pagination
 docs(github): update examples
-```
+```

Also applies to: 210-214

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/README.md` around lines 170 - 186, The README has fenced code blocks
that lack language identifiers: update the repository tree block and the
commit-convention example blocks in the README to use ```text (i.e., change the
opening ``` to ```text for those blocks) so the tree and commit examples are
rendered as plain text; leave the closing ``` unchanged and ensure all similar
examples (the repository tree block and the commit message examples) receive the
same change.

87-93: ⚠️ Potential issue | 🟠 Major

First-time contributor detection is based on the wrong signal.

Using users/{login}/repos count does not determine whether a PR is a first contribution to this repository.

Suggested fix
-for pr in $(gh pr list --author . --json number --jq '.[].number'); do
-  count=$(gh api users/$(gh pr view $pr --json author --jq '.author.login')/repos --jq 'length' 2>/dev/null || echo 0)
-  if [ "$count" -lt 5 ]; then
-    gh pr edit $pr --add-label "first-time-contributor"
-  fi
+for pr in $(gh pr list --json number --jq '.[].number'); do
+  author=$(gh pr view "$pr" --json author --jq '.author.login')
+  pr_count=$(gh pr list --author "$author" --state all --limit 2 --json number --jq 'length')
+  if [ "$pr_count" -eq 1 ]; then
+    gh pr edit "$pr" --add-label "first-time-contributor"
+  fi
 done
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/README.md` around lines 87 - 93, The current script uses
users/$(login)/repos to count a user's total repos, which doesn't indicate
whether this is their first contribution to this repository; replace that check
with a repository-scoped PR count: after extracting the author via gh pr view
$pr --json author --jq '.author.login', call gh pr list --author "$author"
--repo "$(gh repo view --json nameWithOwner --jq '.nameWithOwner')" --state all
--json number --jq 'length' and treat the author as a first-time contributor
only if that count is 1 (meaning only the current PR exists); update the script
logic around the variables pr and count and the gh pr edit invocation
accordingly so labeling is based on prior PRs in this repo rather than total
user repos.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@github/commands/watch-and-fix.md`:
- Around line 39-41: The documentation in github/commands/watch-and-fix.md
claims the command applies fixes and commits/pushes and that it filters reviews
to “Bot-only”, but the implementation in github/examples/watch-and-fix.sh still
contains a fix placeholder and uses a `Bot or OWNER` filter; reconcile them by
either (A) implementing the automatic fix+commit+push flow in
github/examples/watch-and-fix.sh (replace the placeholder fix logic with the
real edit/apply/commit/push steps and ensure the script invokes git commit/push)
and update the review-source filter in the script to only accept `Bot` reviews,
or (B) revert the doc text to match the current script behavior (document that
fixes are placeholders and that the script filters `Bot` or `OWNER`), making
sure to update the review-source wording in github/commands/watch-and-fix.md and
remove any claim of Bot-only behavior. Ensure you update the unique files
github/examples/watch-and-fix.sh and github/commands/watch-and-fix.md
consistently so doc and implementation match.

In `@github/examples/watch-and-fix.sh`:
- Around line 125-134: The script currently only prints a warning where it
should run the automated fixer (the block with the "Applying fixes..." echo and
the "⚠️ Fix automation requires fix:and-update-pr skill integration" message);
replace that placeholder with a real invocation to the fix orchestration (e.g.
call the fix:and-update-pr skill/command or an apply_fixes helper), capture and
check its exit status, commit and push any updated files or update the PR if
fixes were applied, and only continue the loop (or retry with backoff) on
success—on failure emit an error and either abort the loop or retry according to
policy. Ensure you modify the section that currently contains the two echo
warnings and the comment about fix:and-update-pr so it runs the fixer, handles
errors, and updates the repo/PR when fixes are applied.
- Around line 17-20: The arg-parsing branches that assign MAX_ITERATIONS and
PR_NUMBER read "$2" without validating it, which under set -u can cause an
unbound-variable crash; update the --max-iterations and --pr cases to first
check that a next argument exists and is not another option (e.g., test that
"${2-}" is non-empty and does not start with "-"), emit a clear "missing value
for --max-iterations/--pr" error and exit if invalid, otherwise assign
MAX_ITERATIONS="$2" or PR_NUMBER="$2" and shift; also apply the same
presence-check pattern to any future flags that expect a value.
- Around line 37-41: The PR lookup assigns PR_NUMBER using gh and the jq
expression can return the literal string "null" when no PR matches; update the
check after retrieving PR_NUMBER (used with BRANCH) to treat both empty and the
string "null" as not found (e.g., test for -z OR equals "null") and exit with
the existing error path so subsequent GitHub CLI commands don't run with
PR_NUMBER="null".
- Around line 57-79: Initialize CI status vars and sanitize RUN_ID before the
merge check: set CONCLUSION="unknown" and STATUS="unknown" prior to the RUN_ID
logic so they are always defined under set -u, and change the RUN_ID assignment
to return an empty string when jq yields null (e.g. use --jq '.[0].databaseId //
""' or -r with '.[0].databaseId // ""') and/or ensure the merge check tests
RUN_ID for both empty and literal "null" (e.g. if [ -n "$RUN_ID" ] && [
"$RUN_ID" != "null" ]); keep REVIEW_STATE as-is but ensure the later if that
tests CONCLUSION uses the initialized CONCLUSION variable.
- Line 96: The current COMMENTS extraction uses a GH query filter allowing
`.authorAssociation == "OWNER"`, which lets human repo owners trigger fixes;
update the filter in the COMMENTS assignment (the gh pr view command that builds
COMMENTS) to restrict sources to bots only by removing or replacing the `or
.authorAssociation == "OWNER"` clause so the selector only checks `.author.type
== "Bot"`, ensuring only bot-authored comments are parsed as trusted AI review
sources.

In `@github/skills/github.md`:
- Around line 311-317: The docs currently claim the "watch-and-fix" command
fully automates parsing/applying fixes and pushing commits, but
github/examples/watch-and-fix.sh is only a placeholder; either update
github/skills/github.md to accurately describe the current manual workflow (call
out that github/examples/watch-and-fix.sh logs a placeholder and requires manual
edits) or implement the automation in github/examples/watch-and-fix.sh to
perform the listed steps: wait for CI, fetch review comments (e.g., via gh api
or gh pr review-comments), parse suggested fixes, apply patches (git apply or
patch), commit and push changes, and loop until CI/approval—choose one and make
the doc and the script consistent (reference: the "watch-and-fix" command and
github/examples/watch-and-fix.sh).

---

Duplicate comments:
In `@github/README.md`:
- Around line 170-186: The README has fenced code blocks that lack language
identifiers: update the repository tree block and the commit-convention example
blocks in the README to use ```text (i.e., change the opening ``` to ```text for
those blocks) so the tree and commit examples are rendered as plain text; leave
the closing ``` unchanged and ensure all similar examples (the repository tree
block and the commit message examples) receive the same change.
- Around line 87-93: The current script uses users/$(login)/repos to count a
user's total repos, which doesn't indicate whether this is their first
contribution to this repository; replace that check with a repository-scoped PR
count: after extracting the author via gh pr view $pr --json author --jq
'.author.login', call gh pr list --author "$author" --repo "$(gh repo view
--json nameWithOwner --jq '.nameWithOwner')" --state all --json number --jq
'length' and treat the author as a first-time contributor only if that count is
1 (meaning only the current PR exists); update the script logic around the
variables pr and count and the gh pr edit invocation accordingly so labeling is
based on prior PRs in this repo rather than total user repos.

In `@github/skills/github.md`:
- Around line 446-448: The examples use an unsupported --page flag with the gh
pr list command and also show a mistaken mixed usage of --json and --jq; remove
the unsupported --page 2 token from the example(s) and update the surrounding
gotcha/final note to no longer reference --page, leaving the valid invocation(s)
such as gh pr list --limit 100 --json number,title (and gh pr list --limit 100
--json number,title --jq '.[]' if you intend to demonstrate jq-style filtering),
and make the same removal/update for the duplicate occurrence that appears later
in the file; ensure references to --page are deleted and examples show only
supported flags for gh pr list.
- Around line 493-500: The current approach uses a regex on the username in the
gh pr list pipeline (the select(.author.login | test("^[a-z0-9_-]{4,}$")) step
and subsequent while loop/gh pr edit) which misclassifies contributors; replace
the regex check with a real contribution-history check by calling the GitHub API
for each PR author (e.g., via gh api) to verify whether they have previous
contributions/merged PRs or prior activity in the repo before adding the
"first-time-contributor" label, and update the pipeline so gh pr edit is invoked
only when the API response confirms zero prior contributions for that author.
- Around line 529-530: The example uses BSD-only date arithmetic ("date -v-30d")
in the gh pr list command, which breaks on GNU/Linux; replace the inline date
substitution used in the gh pr list example with a portable approach such as
computing a 30-day-ago value with a fallback that supports both BSD and GNU
(e.g., set a DATE_30_DAYS_AGO variable using date -v-30d ... 2>/dev/null || date
-d '30 days ago' ... and then use that variable in the gh pr list --search
string), and update the snippet referencing the substitution used with gh pr
list to use that variable instead (refer to the gh pr list --search "draft:yes
updated:<$(...)" usage in the diff).

In `@marketplace.json`:
- Around line 81-82: The marketplace.json "description" for version "1.3.0" is
out of sync with github/.claude-plugin/plugin.json; update the plugin metadata
so both manifests share the same capability description for the same "version"
(e.g., align the "description" field in marketplace.json with the "description"
in github/.claude-plugin/plugin.json or vice versa), or centralize the source of
truth and propagate it to both files so catalog metadata remains consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 74a20eaa-d90a-413e-995e-1ec1ce7daca8

📥 Commits

Reviewing files that changed from the base of the PR and between 0f55da6 and 64d5dfc.

📒 Files selected for processing (6)
  • github/.claude-plugin/plugin.json
  • github/README.md
  • github/commands/watch-and-fix.md
  • github/examples/watch-and-fix.sh
  • github/skills/github.md
  • marketplace.json

Comment on lines +39 to +41
4. **Fix issues**: Applies fixes based on review feedback
5. **Commit and push**: Commits fixes with semantic message
6. **Repeat**: Goes back to step 1
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Documented behavior is ahead of implementation and internally inconsistent.

The doc says the command applies fixes and commits/pushes, and defines a Bot-only review source, but current script (github/examples/watch-and-fix.sh) still has a fix placeholder and uses Bot or OWNER filtering.

Also applies to: 118-118, 121-125

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/commands/watch-and-fix.md` around lines 39 - 41, The documentation in
github/commands/watch-and-fix.md claims the command applies fixes and
commits/pushes and that it filters reviews to “Bot-only”, but the implementation
in github/examples/watch-and-fix.sh still contains a fix placeholder and uses a
`Bot or OWNER` filter; reconcile them by either (A) implementing the automatic
fix+commit+push flow in github/examples/watch-and-fix.sh (replace the
placeholder fix logic with the real edit/apply/commit/push steps and ensure the
script invokes git commit/push) and update the review-source filter in the
script to only accept `Bot` reviews, or (B) revert the doc text to match the
current script behavior (document that fixes are placeholders and that the
script filters `Bot` or `OWNER`), making sure to update the review-source
wording in github/commands/watch-and-fix.md and remove any claim of Bot-only
behavior. Ensure you update the unique files github/examples/watch-and-fix.sh
and github/commands/watch-and-fix.md consistently so doc and implementation
match.

Comment on lines +17 to +20
--max-iterations) MAX_ITERATIONS="$2"; shift ;;
--dry-run) DRY_RUN=true ;;
--pr) PR_NUMBER="$2"; shift ;;
*) echo "Unknown option: $1"; exit 1 ;;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n github/examples/watch-and-fix.sh

Repository: duyet/claude-plugins

Length of output: 5338


Validate required option values during arg parsing.

Lines 17 and 19 access $2 without checking if it exists. With set -u (enabled on line 5), missing values cause an "unbound variable" error instead of a user-friendly message.

Suggested fix
-    --max-iterations) MAX_ITERATIONS="$2"; shift ;;
+    --max-iterations)
+      [[ $# -ge 2 ]] || { echo "Missing value for --max-iterations"; exit 1; }
+      MAX_ITERATIONS="$2"; shift ;;
@@
-    --pr) PR_NUMBER="$2"; shift ;;
+    --pr)
+      [[ $# -ge 2 ]] || { echo "Missing value for --pr"; exit 1; }
+      PR_NUMBER="$2"; shift ;;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
--max-iterations) MAX_ITERATIONS="$2"; shift ;;
--dry-run) DRY_RUN=true ;;
--pr) PR_NUMBER="$2"; shift ;;
*) echo "Unknown option: $1"; exit 1 ;;
--max-iterations)
[[ $# -ge 2 ]] || { echo "Missing value for --max-iterations"; exit 1; }
MAX_ITERATIONS="$2"; shift ;;
--dry-run) DRY_RUN=true ;;
--pr)
[[ $# -ge 2 ]] || { echo "Missing value for --pr"; exit 1; }
PR_NUMBER="$2"; shift ;;
*) echo "Unknown option: $1"; exit 1 ;;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/examples/watch-and-fix.sh` around lines 17 - 20, The arg-parsing
branches that assign MAX_ITERATIONS and PR_NUMBER read "$2" without validating
it, which under set -u can cause an unbound-variable crash; update the
--max-iterations and --pr cases to first check that a next argument exists and
is not another option (e.g., test that "${2-}" is non-empty and does not start
with "-"), emit a clear "missing value for --max-iterations/--pr" error and exit
if invalid, otherwise assign MAX_ITERATIONS="$2" or PR_NUMBER="$2" and shift;
also apply the same presence-check pattern to any future flags that expect a
value.

Comment on lines +37 to +41
PR_NUMBER=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number')
if [ -z "$PR_NUMBER" ]; then
echo "Error: No PR found for branch $BRANCH"
exit 1
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the actual file
cat -n github/examples/watch-and-fix.sh | sed -n '30,50p'

Repository: duyet/claude-plugins

Length of output: 799


🏁 Script executed:

# Let's also check what jq outputs when accessing a missing array element
# Testing jq behavior with empty arrays
echo '[]' | jq '.[0].number'
echo '[]' | jq -r '.[0].number'
echo '[{"number": 123}]' | jq '.[0].number'

Repository: duyet/claude-plugins

Length of output: 77


🏁 Script executed:

# Check if gh command is available and understand the behavior
# Also look for any test cases or documentation in the repo
find . -type f \( -name "*.md" -o -name "*.txt" -o -name "*test*" \) | grep -i watch

Repository: duyet/claude-plugins

Length of output: 98


🏁 Script executed:

# Search for any mentions of gh pr list in the codebase
rg "gh pr list" -A 2 -B 2

Repository: duyet/claude-plugins

Length of output: 5153


🏁 Script executed:

# Check gh documentation or help
gh pr list --help | head -50

Repository: duyet/claude-plugins

Length of output: 2445


Treat null PR lookup as not found.

gh pr list ... --jq '.[0].number' returns the literal string null when no results match; the current empty-string check does not catch this, allowing the script to proceed with PR_NUMBER="null" and fail on subsequent GitHub CLI operations.

Suggested fix
 PR_NUMBER=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number')
-if [ -z "$PR_NUMBER" ]; then
+if [ -z "$PR_NUMBER" ] || [ "$PR_NUMBER" = "null" ]; then
   echo "Error: No PR found for branch $BRANCH"
   exit 1
 fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
PR_NUMBER=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number')
if [ -z "$PR_NUMBER" ]; then
echo "Error: No PR found for branch $BRANCH"
exit 1
fi
PR_NUMBER=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number')
if [ -z "$PR_NUMBER" ] || [ "$PR_NUMBER" = "null" ]; then
echo "Error: No PR found for branch $BRANCH"
exit 1
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/examples/watch-and-fix.sh` around lines 37 - 41, The PR lookup assigns
PR_NUMBER using gh and the jq expression can return the literal string "null"
when no PR matches; update the check after retrieving PR_NUMBER (used with
BRANCH) to treat both empty and the string "null" as not found (e.g., test for
-z OR equals "null") and exit with the existing error path so subsequent GitHub
CLI commands don't run with PR_NUMBER="null".

Comment on lines +57 to +79
RUN_ID=$(gh run list --workflow=ci.yml --branch "$BRANCH" --limit 1 --json databaseId --jq '.[0].databaseId' 2>/dev/null || echo "")

if [ -n "$RUN_ID" ]; then
echo "Watching CI run #$RUN_ID..."
gh run watch "$RUN_ID" --interval 10 || true

# Check CI status
CONCLUSION=$(gh run view "$RUN_ID" --json conclusion --jq '.conclusion' 2>/dev/null || echo "unknown")
STATUS=$(gh run view "$RUN_ID" --json status --jq '.status' 2>/dev/null || echo "unknown")

echo "CI Status: $STATUS"
echo "CI Conclusion: $CONCLUSION"
else
echo "No CI run found, checking PR status..."
fi

# Get PR review status
REVIEW_STATE=$(gh pr view "$PR_NUMBER" --json reviewDecision --jq '.reviewDecision // "PENDING"')
echo "Review State: $REVIEW_STATE"

# Check if we can merge
if [ "$CONCLUSION" = "success" ] && { [ "$REVIEW_STATE" = "APPROVED" ] || [ "$REVIEW_STATE" = "NULL" ]; }; then
echo "✅ CI passed and reviews approved!"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -name "watch-and-fix.sh" -type f

Repository: duyet/claude-plugins

Length of output: 98


🏁 Script executed:

cat -n github/examples/watch-and-fix.sh

Repository: duyet/claude-plugins

Length of output: 5338


Initialize CI state variables before the merge check to prevent script termination under set -u.

When no workflow run exists, CONCLUSION and STATUS are never initialized and remain unset. At line 78, the script accesses $CONCLUSION, which causes immediate termination under set -u (present at line 5). Additionally, if gh run list returns an empty array, jq produces the literal string null, which bypasses the || echo "" fallback on line 57, leaving RUN_ID="null".

Suggested fix
+CONCLUSION="unknown"
+STATUS="unknown"
 RUN_ID=$(gh run list --workflow=ci.yml --branch "$BRANCH" --limit 1 --json databaseId --jq '.[0].databaseId' 2>/dev/null || echo "")
+if [ "$RUN_ID" = "null" ]; then RUN_ID=""; fi
 
 if [ -n "$RUN_ID" ]; then
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
RUN_ID=$(gh run list --workflow=ci.yml --branch "$BRANCH" --limit 1 --json databaseId --jq '.[0].databaseId' 2>/dev/null || echo "")
if [ -n "$RUN_ID" ]; then
echo "Watching CI run #$RUN_ID..."
gh run watch "$RUN_ID" --interval 10 || true
# Check CI status
CONCLUSION=$(gh run view "$RUN_ID" --json conclusion --jq '.conclusion' 2>/dev/null || echo "unknown")
STATUS=$(gh run view "$RUN_ID" --json status --jq '.status' 2>/dev/null || echo "unknown")
echo "CI Status: $STATUS"
echo "CI Conclusion: $CONCLUSION"
else
echo "No CI run found, checking PR status..."
fi
# Get PR review status
REVIEW_STATE=$(gh pr view "$PR_NUMBER" --json reviewDecision --jq '.reviewDecision // "PENDING"')
echo "Review State: $REVIEW_STATE"
# Check if we can merge
if [ "$CONCLUSION" = "success" ] && { [ "$REVIEW_STATE" = "APPROVED" ] || [ "$REVIEW_STATE" = "NULL" ]; }; then
echo "✅ CI passed and reviews approved!"
CONCLUSION="unknown"
STATUS="unknown"
RUN_ID=$(gh run list --workflow=ci.yml --branch "$BRANCH" --limit 1 --json databaseId --jq '.[0].databaseId' 2>/dev/null || echo "")
if [ "$RUN_ID" = "null" ]; then RUN_ID=""; fi
if [ -n "$RUN_ID" ]; then
echo "Watching CI run #$RUN_ID..."
gh run watch "$RUN_ID" --interval 10 || true
# Check CI status
CONCLUSION=$(gh run view "$RUN_ID" --json conclusion --jq '.conclusion' 2>/dev/null || echo "unknown")
STATUS=$(gh run view "$RUN_ID" --json status --jq '.status' 2>/dev/null || echo "unknown")
echo "CI Status: $STATUS"
echo "CI Conclusion: $CONCLUSION"
else
echo "No CI run found, checking PR status..."
fi
# Get PR review status
REVIEW_STATE=$(gh pr view "$PR_NUMBER" --json reviewDecision --jq '.reviewDecision // "PENDING"')
echo "Review State: $REVIEW_STATE"
# Check if we can merge
if [ "$CONCLUSION" = "success" ] && { [ "$REVIEW_STATE" = "APPROVED" ] || [ "$REVIEW_STATE" = "NULL" ]; }; then
echo "✅ CI passed and reviews approved!"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/examples/watch-and-fix.sh` around lines 57 - 79, Initialize CI status
vars and sanitize RUN_ID before the merge check: set CONCLUSION="unknown" and
STATUS="unknown" prior to the RUN_ID logic so they are always defined under set
-u, and change the RUN_ID assignment to return an empty string when jq yields
null (e.g. use --jq '.[0].databaseId // ""' or -r with '.[0].databaseId // ""')
and/or ensure the merge check tests RUN_ID for both empty and literal "null"
(e.g. if [ -n "$RUN_ID" ] && [ "$RUN_ID" != "null" ]); keep REVIEW_STATE as-is
but ensure the later if that tests CONCLUSION uses the initialized CONCLUSION
variable.


# Get review comments
echo "Fetching review comments..."
COMMENTS=$(gh pr view "$PR_NUMBER" --json comments -q '.comments[] | select(.author.type == "Bot" or .authorAssociation == "OWNER") | [.path, .line, .body] | @tsv' 2>/dev/null || echo "")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd github && pwd && head -n 110 examples/watch-and-fix.sh | tail -n 20

Repository: duyet/claude-plugins

Length of output: 761


🏁 Script executed:

cat -n github/examples/watch-and-fix.sh | sed -n '85,110p'

Repository: duyet/claude-plugins

Length of output: 1119


🏁 Script executed:

cat -n github/examples/watch-and-fix.sh | head -n 50

Repository: duyet/claude-plugins

Length of output: 1704


🏁 Script executed:

rg -A 5 -B 5 "authorAssociation" github/examples/watch-and-fix.sh

Repository: duyet/claude-plugins

Length of output: 459


🏁 Script executed:

fd -t f "README|DOCS|\.md" github/examples/

Repository: duyet/claude-plugins

Length of output: 46


🏁 Script executed:

find github -name "*.md" -o -name "README*" -o -name "*.txt" | head -20

Repository: duyet/claude-plugins

Length of output: 238


🏁 Script executed:

rg -i "owner\|ai\|bot" github/examples/watch-and-fix.sh | head -20

Repository: duyet/claude-plugins

Length of output: 46


🏁 Script executed:

ls -la github/examples/

Repository: duyet/claude-plugins

Length of output: 444


🏁 Script executed:

cat -n github/examples/watch-and-fix.sh | sed -n '50,130p'

Repository: duyet/claude-plugins

Length of output: 3383


🏁 Script executed:

cat -n github/commands/watch-and-fix.md

Repository: duyet/claude-plugins

Length of output: 4560


🏁 Script executed:

cat -n github/README.md

Repository: duyet/claude-plugins

Length of output: 7115


Limit parsed fix sources to trusted AI review authors.

The documentation states the script automatically fixes "issues identified in AI reviews" and "AI agents", but the filter at line 96 includes .authorAssociation == "OWNER", which allows human repository owners (not just bots) to trigger the fix pipeline. Either restrict the filter to bot authors only (.author.type == "Bot"), or update the documentation to clarify that human owners are intentionally included.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/examples/watch-and-fix.sh` at line 96, The current COMMENTS extraction
uses a GH query filter allowing `.authorAssociation == "OWNER"`, which lets
human repo owners trigger fixes; update the filter in the COMMENTS assignment
(the gh pr view command that builds COMMENTS) to restrict sources to bots only
by removing or replacing the `or .authorAssociation == "OWNER"` clause so the
selector only checks `.author.type == "Bot"`, ensuring only bot-authored
comments are parsed as trusted AI review sources.

Comment on lines +125 to +134
# Apply fixes using the fix skill
echo "Applying fixes..."
# This would invoke the fix:and-update-pr skill
# For now, just notify that fixes need to be applied
echo "⚠️ Fix automation requires fix:and-update-pr skill integration"
echo "Please manually fix issues or ensure fix plugin is installed."

# After fixes, the loop continues
echo "Waiting for CI to restart..."
sleep 10
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

The loop cannot self-heal because fix execution is not implemented.

The script advertises automated fixing but only prints a warning and waits. This creates repeated iterations without applying or pushing changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/examples/watch-and-fix.sh` around lines 125 - 134, The script
currently only prints a warning where it should run the automated fixer (the
block with the "Applying fixes..." echo and the "⚠️ Fix automation requires
fix:and-update-pr skill integration" message); replace that placeholder with a
real invocation to the fix orchestration (e.g. call the fix:and-update-pr
skill/command or an apply_fixes helper), capture and check its exit status,
commit and push any updated files or update the PR if fixes were applied, and
only continue the loop (or retry with backoff) on success—on failure emit an
error and either abort the loop or retry according to policy. Ensure you modify
the section that currently contains the two echo warnings and the comment about
fix:and-update-pr so it runs the fixer, handles errors, and updates the repo/PR
when fixes are applied.

Comment thread github/skills/github.md
Comment on lines +311 to +317
The watch-and-fix command:
1. Waits for CI to complete
2. Gets review comments from AI agents
3. Parses and applies fixes
4. Commits and pushes changes
5. Repeats until CI passes and PR is approved
6. Optionally auto-merges when ready
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Watch-and-fix workflow is documented as fully automated, but current implementation is not.

This section says fixes are parsed/applied and committed/pushed, but github/examples/watch-and-fix.sh currently only logs a placeholder and asks for manual fixes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@github/skills/github.md` around lines 311 - 317, The docs currently claim the
"watch-and-fix" command fully automates parsing/applying fixes and pushing
commits, but github/examples/watch-and-fix.sh is only a placeholder; either
update github/skills/github.md to accurately describe the current manual
workflow (call out that github/examples/watch-and-fix.sh logs a placeholder and
requires manual edits) or implement the automation in
github/examples/watch-and-fix.sh to perform the listed steps: wait for CI, fetch
review comments (e.g., via gh api or gh pr review-comments), parse suggested
fixes, apply patches (git apply or patch), commit and push changes, and loop
until CI/approval—choose one and make the doc and the script consistent
(reference: the "watch-and-fix" command and github/examples/watch-and-fix.sh).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants