Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:39:15 +08:00
commit b999e5074a
14 changed files with 2460 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
# GitHub Personal Access Token (OBRIGATÓRIO)
# Create a token at: https://github.com/settings/tokens
# Required scopes: 'repo' (full control of private repositories)
GITHUB_TOKEN=ghp_your_personal_access_token_here
# Diretório de saída (OPCIONAL)
# Onde os arquivos serão salvos (relativo à raiz do projeto)
# Padrão: ./.reviews
OUTPUT_DIR=./.reviews
# Timezone para formatação de datas (OPCIONAL)
# Padrão: timezone do sistema local
# Exemplos: America/Sao_Paulo, Europe/London, UTC
# PR_REVIEW_TZ=America/Sao_Paulo
# Nível de logging (OPCIONAL)
# Padrão: info
# Opções: error, warn, info, debug
# LOG_LEVEL=debug

19
skills/pull-request-skill/.gitignore vendored Normal file
View File

@@ -0,0 +1,19 @@
# Environment files
.env
.env.local
# Dependencies
node_modules/
bun.lockb
# Logs
*.log
pr-review-combined.log
pr-review-error.log
# Temporary files
.temp-execution-*.js
*.tmp
# Backup files
*.bak

View File

@@ -0,0 +1,359 @@
---
name: pull-request-skill
description: Pull Request review manager for CodeRabbit AI. **ALWAYS use when user needs to work with PR reviews, fix CodeRabbit issues, or check review status.** Downloads, organizes, and helps resolve review comments systematically. Examples - "download PR reviews", "fix CodeRabbit issues for PR 123", "check review status", "organize review comments by severity".
---
You are an expert Pull Request Review Manager specializing in working with CodeRabbit AI review comments from GitHub Pull Requests.
## When to Engage
You should proactively assist when:
- User mentions working with CodeRabbit reviews
- User wants to download PR review comments
- User needs to fix issues from a PR review
- User asks about PR review status
- User mentions CodeRabbit, PR reviews, or review comments
- User wants to organize or prioritize review feedback
- User needs to resolve review threads
**Trigger Keywords**: coderabbit, pr review, pull request review, review comments, fix issues, download reviews, pr status
## Your Role
As a Pull Request Review Manager, you:
1. **Download** - Fetch CodeRabbit AI review comments from GitHub PRs
2. **Organize** - Categorize issues by severity (critical, major, trivial)
3. **Track** - Monitor issue resolution status
4. **Guide** - Help users systematically resolve review feedback
5. **Report** - Provide clear summaries of review status
## Available Commands
The reviewer plugin provides three slash commands:
1. `/reviewer:download-issues --pr <number>` - Download CodeRabbit reviews
2. `/reviewer:fix-issues --pr <number>` - Fix issues from a PR review
3. `/reviewer:pr-status --pr <number>` - Check review status
**Note**: PR number is optional - if not provided, the latest open PR is used.
## Workflow
### 1. Download Reviews
```bash
# Download reviews for PR #123
/reviewer:download-issues --pr 123
# Download latest open PR
/reviewer:download-issues
```
**What happens:**
- Fetches all CodeRabbit AI comments from the PR
- Organizes them into issues (review threads) and comments
- Categorizes by severity: 🔴 Critical, 🟠 Major, 🔵 Trivial
- Saves to `.reviews/reviews-pr-<number>/` in the working directory
- Generates a summary report
**Output Structure:**
```
.reviews/reviews-pr-123/
├── summary.md # 📊 Overview with statistics
├── pr-review-combined.log # 📋 Full execution logs
├── pr-review-error.log # ⚠️ Error logs only
├── issues/ # 🔧 Resolvable issues (threads)
│ ├── issue_001_critical_unresolved.md
│ ├── issue_002_major_unresolved.md
│ └── issue_003_trivial_resolved.md
└── comments/ # 💬 General comments
├── comment_001.md
└── comment_002.md
```
### 2. Review Summary
After downloading, **always** read and show the user:
```bash
# Read the summary
cat .reviews/reviews-pr-<number>/summary.md
```
The summary includes:
- Total issues by severity
- Resolved vs unresolved count
- Issue list with file paths and descriptions
- Quick overview for prioritization
### 3. Fix Issues
Help users systematically resolve issues:
```bash
# Fix issues from PR #123
/reviewer:fix-issues --pr 123
```
**Your role when fixing:**
1. Read the issue file to understand the problem
2. Locate the relevant code file
3. Analyze the CodeRabbit suggestion
4. Implement the fix following best practices
5. Mark the issue as resolved
6. Move to the next issue
**Priority order:**
1. 🔴 Critical issues first
2. 🟠 Major issues next
3. 🔵 Trivial issues last
### 4. Check Status
Monitor progress on review resolution:
```bash
# Check status of PR #123
/reviewer:pr-status --pr 123
```
Shows:
- Total issues vs resolved
- Remaining critical/major/trivial issues
- Progress percentage
- Next recommended actions
## Prerequisites
### GitHub Token Setup
The skill requires a `.env` file in its installation directory:
```bash
# Location: ~/.claude/plugins/marketplaces/claude-craftkit/plugins/reviewer/skills/pull-request-skill/.env
GITHUB_TOKEN=ghp_your_personal_access_token_here
OUTPUT_DIR=./.reviews
LOG_LEVEL=info
PR_REVIEW_TZ=America/Sao_Paulo
```
**If the token is not set:**
1. Guide user to create `.env` file in skill directory
2. Help them generate token at: https://github.com/settings/tokens
3. Required scopes: `repo` (full repository access)
### Dependencies
Dependencies are auto-installed on first run. The skill uses:
- `@octokit/rest` - GitHub API client
- `@octokit/graphql` - GraphQL API
- `winston` - Logging
- `zod` - Validation
- `dotenv` - Environment variables
## Issue Severity Levels
Issues are automatically categorized:
- **🔴 Critical**: Security issues, bugs, breaking changes
- **Action**: Fix immediately
- **Examples**: Memory leaks, security vulnerabilities, data corruption
- **🟠 Major**: Important issues affecting functionality
- **Action**: Fix before merging
- **Examples**: Logic errors, performance issues, incorrect behavior
- **🔵 Trivial**: Minor issues and style improvements
- **Action**: Fix when convenient
- **Examples**: Code style, formatting, minor optimizations
## Best Practices
### When Downloading Reviews
1. **Always show summary first**
```bash
/reviewer:download-issues --pr 123
# Then immediately:
cat .reviews/reviews-pr-123/summary.md
```
2. **Verify repository context**
- Ensure you're in the correct repository
- Check git remote: `git remote -v`
3. **Handle errors gracefully**
- Check for `.env` file if token error
- Verify PR exists and has CodeRabbit comments
- Check logs if issues occur: `pr-review-error.log`
### When Fixing Issues
1. **Work systematically**
- Start with critical issues
- Fix one issue at a time
- Test after each fix
2. **Read the full issue**
- Understand CodeRabbit's reasoning
- Check the suggested code change
- Consider the context and impact
3. **Follow project standards**
- Use project's code style
- Run linters/formatters after changes
- Ensure tests pass
4. **Mark issues as resolved**
- Rename file: `issue_001_critical_unresolved.md` → `issue_001_critical_resolved.md`
- Or move to `resolved/` subfolder
### When Reporting Status
1. **Provide clear summary**
- Total issues vs resolved
- Breakdown by severity
- Estimated remaining work
2. **Recommend next actions**
- Prioritize critical issues
- Suggest grouping similar issues
- Identify quick wins
## Environment Variables
- `GITHUB_TOKEN` (required): GitHub Personal Access Token
- `OUTPUT_DIR` (optional): Output directory relative to working dir (default: `./.reviews`)
- `CWD` (optional): Override working directory (default: current directory)
- `LOG_LEVEL` (optional): Logging level - `error`, `warn`, `info`, `debug` (default: `info`)
- `PR_REVIEW_TZ` (optional): Timezone for dates (default: system timezone)
## Common Scenarios
### Scenario 1: User wants to work on PR feedback
**User**: "I got CodeRabbit feedback on my PR, help me fix it"
**Your actions**:
1. Ask for PR number (or auto-detect)
2. Run `/reviewer:download-issues --pr <number>`
3. Show the summary
4. Ask which severity level to start with
5. Begin fixing issues systematically
### Scenario 2: User wants to see what needs fixing
**User**: "What issues are left on PR 123?"
**Your actions**:
1. Run `/reviewer:pr-status --pr 123`
2. Show breakdown by severity
3. Recommend starting with critical issues
4. Offer to begin fixing
### Scenario 3: User completed some fixes
**User**: "I fixed the critical issues, what's next?"
**Your actions**:
1. Run `/reviewer:pr-status --pr 123`
2. Verify critical issues are resolved
3. Show remaining major issues
4. Offer to continue with major issues
## Troubleshooting
### "GITHUB_TOKEN is not set"
**Solution**:
1. Create `.env` file: `~/.claude/plugins/marketplaces/claude-craftkit/plugins/reviewer/skills/pull-request-skill/.env`
2. Add: `GITHUB_TOKEN=ghp_...`
3. Generate token at: https://github.com/settings/tokens
### "No CodeRabbit AI comments found"
**Causes**:
- CodeRabbit hasn't reviewed the PR yet
- PR doesn't have comments from `@coderabbitai[bot]`
- Wrong PR number
**Solution**: Verify PR has CodeRabbit comments on GitHub
### "Repository information could not be parsed"
**Causes**:
- Not in a git repository
- No remote configured
- Remote URL format incorrect
**Solution**:
1. Check: `git remote -v`
2. Remote must be: `https://github.com/owner/repo.git`
### "Dependencies not found"
**Solution**:
```bash
cd ~/.claude/plugins/marketplaces/claude-craftkit/plugins/reviewer/skills/pull-request-skill
bun install
```
## Integration with Development Workflow
This skill works best when integrated with other tools:
1. **After PR creation** → Download reviews
2. **While fixing** → Use `/quality:check` to verify changes
3. **After fixes** → Use `/git:commit` for conventional commits
4. **Before merge** → Use `/reviewer:pr-status` to verify all issues resolved
## Remember
- **Always download first** - Get fresh reviews before working
- **Prioritize by severity** - Critical → Major → Trivial
- **One issue at a time** - Focus on quality over speed
- **Test after changes** - Ensure fixes don't break anything
- **Track progress** - Use status command to monitor completion
- **Communicate clearly** - Show summaries and next steps to users
## Success Criteria
A successful review resolution workflow:
**Downloads** reviews successfully with clear summary
**Prioritizes** issues by severity (critical first)
**Fixes** issues systematically with proper testing
**Tracks** progress with status updates
**Completes** all critical and major issues before merge
**Maintains** code quality and project standards
**Communicates** progress clearly to the user
---
**You are the Pull Request Review Manager. When users need to work with CodeRabbit reviews, use this skill to guide them through the process systematically.**

View File

@@ -0,0 +1,35 @@
{
"name": "pull-request-skill",
"version": "1.0.0",
"description": "Pull Request review exporter and issue resolver for CodeRabbit AI comments",
"author": "marcio",
"main": "run.js",
"type": "module",
"scripts": {
"setup": "bun install",
"download": "bun run pr-review.ts",
"download-pr": "bun run pr-review.ts"
},
"keywords": [
"pull-request",
"code-review",
"coderabbit",
"github",
"claude-skill"
],
"dependencies": {
"@octokit/graphql": "^9.0.2",
"@octokit/plugin-retry": "^8.0.2",
"@octokit/plugin-throttling": "^11.0.2",
"@octokit/rest": "^22.0.0",
"@octokit/types": "^15.0.1",
"@types/node": "^24.9.1",
"dotenv": "^17.2.3",
"winston": "^3.18.3",
"zod": "^4.1.12"
},
"engines": {
"bun": ">=1.0.0"
},
"license": "MIT"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,139 @@
#!/usr/bin/env bash
# Read PR Issues Script
# Displays issues from the PR review export in a clean, readable format
#
# Usage:
# ./read-pr-issues.sh --pr 277 --type issue --all
# ./read-pr-issues.sh --pr 277 --type issue --from 1 --to 10
# ./read-pr-issues.sh --pr 277 --type critical --all
# ./read-pr-issues.sh --pr 277 --type major --all
# ./read-pr-issues.sh --pr 277 --type trivial --all
set -euo pipefail
# Default values
PR=""
TYPE="issue"
FROM=""
TO=""
ALL=false
# Use CWD if provided (for when called from skill location), otherwise use current directory
WORKING_DIR="${CWD:-$(pwd)}"
BASE_DIR="${OUTPUT_DIR:-./.reviews}"
# Resolve BASE_DIR relative to WORKING_DIR if it's not absolute
if [[ ! "$BASE_DIR" = /* ]]; then
BASE_DIR="${WORKING_DIR}/${BASE_DIR}"
fi
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--pr)
PR="$2"
shift 2
;;
--type)
TYPE="$2"
shift 2
;;
--from)
FROM="$2"
shift 2
;;
--to)
TO="$2"
shift 2
;;
--all)
ALL=true
shift
;;
--base-dir)
BASE_DIR="$2"
shift 2
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 --pr PR_NUMBER --type TYPE [--from N --to M | --all] [--base-dir DIR]"
echo "Types: issue, critical, major, trivial"
exit 1
;;
esac
done
# Validate PR number
if [[ -z "$PR" ]]; then
echo "❌ Error: --pr is required"
exit 1
fi
# Set PR directory
PR_DIR="${BASE_DIR}/reviews-pr-${PR}"
if [[ ! -d "$PR_DIR" ]]; then
echo "❌ Error: PR directory not found: $PR_DIR"
echo "Have you run the download command first?"
exit 1
fi
echo "📂 Reading issues from: $PR_DIR"
echo ""
# Determine which files to read based on type
case "$TYPE" in
critical|major|trivial)
PATTERN="*_${TYPE}_*.md"
DIR="${PR_DIR}/issues"
;;
issue)
PATTERN="issue_*.md"
DIR="${PR_DIR}/issues"
;;
*)
echo "❌ Error: Unknown type: $TYPE"
echo "Valid types: issue, critical, major, trivial"
exit 1
;;
esac
# Find matching files
if [[ "$ALL" == true ]]; then
FILES=($(find "$DIR" -name "$PATTERN" -type f | sort))
else
if [[ -z "$FROM" ]] || [[ -z "$TO" ]]; then
echo "❌ Error: Either use --all or specify both --from and --to"
exit 1
fi
FILES=()
for i in $(seq "$FROM" "$TO"); do
ISSUE_NUM=$(printf "%03d" "$i")
MATCHES=($(find "$DIR" -name "issue_${ISSUE_NUM}_*.md" -type f))
if [[ ${#MATCHES[@]} -gt 0 ]]; then
FILES+=("${MATCHES[0]}")
fi
done
fi
if [[ ${#FILES[@]} -eq 0 ]]; then
echo "⚠️ No issues found matching criteria"
exit 0
fi
echo "Found ${#FILES[@]} issue(s)"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Display each file
for file in "${FILES[@]}"; do
filename=$(basename "$file")
echo "📄 $filename"
echo ""
cat "$file"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
done
echo "✅ Displayed ${#FILES[@]} issue(s)"

View File

@@ -0,0 +1,179 @@
#!/usr/bin/env bash
# Resolve PR Issues Script
# Marks review threads as resolved using GitHub CLI and updates the summary
#
# Usage:
# ./resolve-pr-issues.sh --pr-dir ./ai-docs/reviews-pr-277 --from 1 --to 10
# ./resolve-pr-issues.sh --pr-dir ./ai-docs/reviews-pr-277 --all
set -euo pipefail
# Default values
PR_DIR=""
FROM=""
TO=""
ALL=false
# Use CWD if provided (for when called from skill location), otherwise use current directory
WORKING_DIR="${CWD:-$(pwd)}"
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--pr-dir)
PR_DIR="$2"
shift 2
;;
--from)
FROM="$2"
shift 2
;;
--to)
TO="$2"
shift 2
;;
--all)
ALL=true
shift
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 --pr-dir PR_DIR [--from N --to M | --all]"
exit 1
;;
esac
done
# Validate PR directory
if [[ -z "$PR_DIR" ]]; then
echo "❌ Error: --pr-dir is required"
exit 1
fi
# Resolve PR_DIR relative to WORKING_DIR if it's not absolute
if [[ ! "$PR_DIR" = /* ]]; then
PR_DIR="${WORKING_DIR}/${PR_DIR}"
fi
if [[ ! -d "$PR_DIR" ]]; then
echo "❌ Error: PR directory not found: $PR_DIR"
exit 1
fi
ISSUES_DIR="${PR_DIR}/issues"
if [[ ! -d "$ISSUES_DIR" ]]; then
echo "❌ Error: Issues directory not found: $ISSUES_DIR"
exit 1
fi
# Check if gh is installed
if ! command -v gh &> /dev/null; then
echo "❌ Error: GitHub CLI (gh) is not installed"
echo "Install from: https://cli.github.com"
exit 1
fi
echo "🔧 Resolving issues in: $PR_DIR"
echo ""
# Find unresolved issue files
if [[ "$ALL" == true ]]; then
FILES=($(find "$ISSUES_DIR" -name "issue_*_unresolved.md" -type f | sort))
else
if [[ -z "$FROM" ]] || [[ -z "$TO" ]]; then
echo "❌ Error: Either use --all or specify both --from and --to"
exit 1
fi
FILES=()
for i in $(seq "$FROM" "$TO"); do
ISSUE_NUM=$(printf "%03d" "$i")
MATCHES=($(find "$ISSUES_DIR" -name "issue_${ISSUE_NUM}_*_unresolved.md" -type f))
if [[ ${#MATCHES[@]} -gt 0 ]]; then
FILES+=("${MATCHES[@]}")
fi
done
fi
if [[ ${#FILES[@]} -eq 0 ]]; then
echo "✅ No unresolved issues found in specified range"
exit 0
fi
echo "Found ${#FILES[@]} unresolved issue(s) to process"
echo ""
RESOLVED_COUNT=0
FAILED_COUNT=0
# Process each file
for file in "${FILES[@]}"; do
filename=$(basename "$file")
# Extract thread ID from file
THREAD_ID=$(grep -m1 "^- Thread ID:" "$file" | sed 's/^- Thread ID: `\(.*\)`$/\1/' || echo "")
if [[ -z "$THREAD_ID" ]] || [[ "$THREAD_ID" == "(not found)" ]]; then
echo "⚠️ Skipping $filename - no thread ID found"
((FAILED_COUNT++))
continue
fi
echo "Processing: $filename"
echo " Thread ID: $THREAD_ID"
# Resolve the thread using GitHub CLI
if gh api graphql \
-f query='mutation($threadId: ID!) { resolveReviewThread(input: { threadId: $threadId }) { thread { isResolved } } }' \
-F threadId="$THREAD_ID" &> /dev/null; then
echo " ✅ Resolved successfully"
# Rename file from unresolved to resolved
NEW_FILE="${file/_unresolved.md/_resolved.md}"
mv "$file" "$NEW_FILE"
# Update status in file
sed -i.bak 's/- \[ \] UNRESOLVED/- [x] RESOLVED ✓/g' "$NEW_FILE"
sed -i.bak 's/UNRESOLVED/RESOLVED/g' "$NEW_FILE"
rm -f "${NEW_FILE}.bak"
((RESOLVED_COUNT++))
else
echo " ❌ Failed to resolve"
((FAILED_COUNT++))
fi
echo ""
done
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Summary:"
echo " ✅ Resolved: $RESOLVED_COUNT"
echo " ❌ Failed: $FAILED_COUNT"
echo " 📊 Total processed: ${#FILES[@]}"
echo ""
if [[ $RESOLVED_COUNT -gt 0 ]]; then
echo "🔄 Re-running PR review export to update summary..."
# Extract PR number from directory name
PR_NUM=$(basename "$PR_DIR" | sed 's/reviews-pr-//')
# Re-run the export script to update summary
if command -v bun &> /dev/null; then
SCRIPT_DIR="$(dirname "$0")"
if CWD="$WORKING_DIR" bun run "$SCRIPT_DIR/pr-review.ts" "$PR_NUM"; then
echo "✅ Summary updated successfully"
else
echo "⚠️ Warning: Failed to update summary, but issues were resolved"
fi
else
echo "⚠️ Warning: Bun not found, summary not updated automatically"
echo "Run manually: CWD=$(pwd) bun run <skill-path>/pr-review.ts $PR_NUM"
fi
fi
echo ""
echo "✅ Done!"

173
skills/pull-request-skill/run.js Executable file
View File

@@ -0,0 +1,173 @@
#!/usr/bin/env node
/**
* Universal Pull Request Review Exporter for Claude Code
*
* Executes the PR review export script with Bun:
* - Download PR reviews: node run.js download [PR_NUMBER]
* - Help: node run.js --help
*
* Ensures proper module resolution and dependency installation.
*/
import { execSync, spawn } from 'node:child_process';
import { existsSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Change to skill directory for proper module resolution
process.chdir(__dirname);
/**
* Check if Bun is installed
*/
function checkBunInstalled() {
try {
execSync('bun --version', { stdio: 'pipe' });
return true;
} catch (e) {
return false;
}
}
/**
* Check if dependencies are installed
*/
function checkDependenciesInstalled() {
return existsSync(join(__dirname, 'node_modules'));
}
/**
* Install dependencies using Bun
*/
function installDependencies() {
console.log('📦 Dependencies not found. Installing...');
try {
execSync('bun install', { stdio: 'inherit', cwd: __dirname });
console.log('✅ Dependencies installed successfully');
return true;
} catch (e) {
console.error('❌ Failed to install dependencies:', e.message);
console.error('Please run manually: cd', __dirname, '&& bun install');
return false;
}
}
/**
* Show help message
*/
function showHelp() {
console.log(`
Pull Request Review Exporter - Claude Code Skill
USAGE:
node run.js download [PR_NUMBER] Download CodeRabbit comments for a PR
node run.js download Download comments for latest open PR
node run.js --help Show this help message
EXAMPLES:
node run.js download 123 Download PR #123 reviews
node run.js download Download latest open PR reviews
# From any directory (saves to that directory's .reviews/)
CWD=/path/to/repo node run.js download 123
ENVIRONMENT VARIABLES:
GITHUB_TOKEN GitHub Personal Access Token (required)
OUTPUT_DIR Output directory for reviews (default: ./.reviews)
CWD Working directory to save reviews (default: current directory)
LOG_LEVEL Logging level: error, warn, info, debug (default: info)
PR_REVIEW_TZ Timezone for dates (default: system timezone)
SETUP:
1. Create .env file in skill directory:
echo "GITHUB_TOKEN=ghp_your_token_here" > .env
2. Optionally configure output directory and logging:
echo "OUTPUT_DIR=./my-reviews" >> .env
echo "LOG_LEVEL=debug" >> .env
For more information, see README.md
`);
}
/**
* Run the PR review export script
*/
function runPRReviewScript(args) {
const scriptPath = join(__dirname, 'pr-review.ts');
if (!existsSync(scriptPath)) {
console.error('❌ Error: pr-review.ts not found in skill directory');
console.error('Expected at:', scriptPath);
process.exit(1);
}
console.log('🚀 Starting PR Review Exporter...\n');
// Use spawn to stream output in real-time
const bunProcess = spawn('bun', ['run', scriptPath, ...args], {
cwd: __dirname,
stdio: 'inherit',
env: { ...process.env }
});
bunProcess.on('error', (error) => {
console.error('❌ Failed to start Bun process:', error.message);
process.exit(1);
});
bunProcess.on('exit', (code) => {
process.exit(code || 0);
});
}
/**
* Main execution
*/
async function main() {
const args = process.argv.slice(2);
// Show help
if (args.includes('--help') || args.includes('-h')) {
showHelp();
process.exit(0);
}
// Check Bun installation
if (!checkBunInstalled()) {
console.error('❌ Bun is not installed or not in PATH');
console.error('Please install Bun from: https://bun.sh');
console.error('Or use: curl -fsSL https://bun.sh/install | bash');
process.exit(1);
}
// Check and install dependencies if needed
if (!checkDependenciesInstalled()) {
const installed = installDependencies();
if (!installed) {
process.exit(1);
}
}
// Parse command
const command = args[0];
if (command === 'download' || !command) {
// Extract PR number if provided
const prArgs = args.slice(1);
runPRReviewScript(prArgs);
} else {
console.error(`❌ Unknown command: ${command}`);
console.error('Run "node run.js --help" for usage information');
process.exit(1);
}
}
// Run main function
main().catch((error) => {
console.error('❌ Fatal error:', error.message);
process.exit(1);
});