A Python script to analyze GitHub pull request review activity between you and other contributors.
- π Track PRs you reviewed vs. PRs others reviewed for you
- π Calculate lines of code reviewed in both directions
- π’ Count review events (approvals, change requests)
- βοΈ Calculate review balance (offset) between users
- π Sortable review balance table by different columns
- πΎ Caching to speed up subsequent runs
- π Includes open (unmerged) PRs in analysis
- π List all reviewed PRs with clickable links
The script generates both console output and an interactive HTML report with color-coded sections for easy readability.
The tool automatically generates an interactive HTML report saved to the reports/ directory with a filename like github_review_analysis_<username>_<timestamp>.html.
This report includes:
- Interactive sortable tables - Click column headers to sort by different metrics
- Clickable rows - Click on a user to jump to their open PRs
- Collapsible sections - Expand/collapse detailed information as needed
- Copy-to-Slack buttons - One-click copying of formatted review request messages
- Visual feedback - Color-coded priorities and review balances
- Review history - Detailed per-user review metrics and PR lists
The review balance table shows:
- Total PR interactions with each collaborator
- Lines reviewed in both directions (with +additions/-deletions breakdown)
- Review balance and recommended next actions
- Click any user to jump to their open PRs
A collapsible section showing your open PRs with:
- Two buttons per PR: One for code review requests, one for testing requests
- Slack-ready messages: Click to copy formatted messages to your clipboard
- PR metrics: Line changes, repository info, and direct links
Shows PRs awaiting your review, grouped by author with:
- Priority indicators: Based on your review balance with each author
- Review status badges: Shows review count, changes requested, etc.
- Personalized messages: Click to copy a customized Slack review request for each author
- Review history: Expandable section showing your past interactions with each author
- Complete metrics: PRs reviewed, lines reviewed, review events, comments
- Full list of PRs you reviewed with titles and links
- Full list of PRs they reviewed with titles and links
- Expandable sections to keep the report clean and focused
- Python 3.7+
requestslibrary- GitHub Personal Access Token (recommended for higher rate limits)
-
Install required dependencies:
pip install -r requirements-review-analyzer.txt
-
Create env file (optional but recommended)
cp .env.example .env
-
Replace the placeholders in the
.envfile
You can configure the script using environment variables in your .env file:
GITHUB_USERNAME: Your GitHub usernameGITHUB_TOKEN: Your GitHub personal access tokenGITHUB_REPOS: Comma-separated list of repositories (e.g.,owner/repo1,owner/repo2)ANALYSIS_MONTHS: Number of months to analyze (default: 3)EXCLUDED_USERS: Comma-separated list of users to exclude from analysisUSE_CACHE: Enable/disable caching (default: true)SORT_BY: Column to sort the review balance table by (default: total_prs)SHOW_EXTENDED_REPORT: Show detailed review history per user (default: false)SHOW_OVERALL_STATISTICS: Show overall statistics section (default: true)MAX_REVIEW_COUNT_THRESHOLD: Filter out PRs with N or more reviews from the open PRs list (default: no filtering)FILTER_NON_PR_AUTHORS: Filter out users who have not opened any PRs (default: true)
Simply run the script and follow the prompts (or provide parameters via .env file):
python3 github-review-analyzer.pyThe script will:
- Analyze your PR review activity
- Display a summary in the console
- Generate an HTML report saved to the
reports/directory - Print the path to the HTML file for easy access
Open the generated HTML file in your browser to access the full interactive report with sortable tables, collapsible sections, and copy-to-Slack functionality.
Note: All generated reports are saved to the reports/ folder, which is gitignored to keep your repository clean.
You can configure the script using environment variables in your .env file:
GITHUB_USERNAME: Your GitHub usernameGITHUB_TOKEN: Your GitHub personal access tokenGITHUB_REPOS: Comma-separated list of repositories (e.g.,owner/repo1,owner/repo2)ANALYSIS_MONTHS: Number of months to analyze (default: 3)EXCLUDED_USERS: Comma-separated list of users to exclude from analysisUSE_CACHE: Enable/disable caching (default: true)SORT_BY: Column to sort the review balance table by (default: total_prs)SHOW_EXTENDED_REPORT: Show detailed review history per user (default: false)SHOW_OVERALL_STATISTICS: Show overall statistics section (default: true)MAX_REVIEW_COUNT_THRESHOLD: Filter out PRs with N or more reviews from the open PRs list (default: no filtering)FILTER_NON_PR_AUTHORS: Filter out users who have not opened any PRs (default: true)
By default, the script outputs a concise report showing only the review balance table, open PRs, and overall statistics. To see the detailed review history section with per-user breakdowns of all reviewed PRs, you can enable the extended report:
# Enable extended report for a single run
SHOW_EXTENDED_REPORT=true python3 github-review-analyzer.py
# Or in your .env file
SHOW_EXTENDED_REPORT=trueThe extended report includes:
- Detailed metrics table for each collaborator
- Complete list of PRs you reviewed for them with links
- Complete list of PRs they reviewed for you with links
- Line review offset calculations per user
This is useful for in-depth analysis but can make the output quite long if you have many collaborators.
By default, the script displays an overall statistics section at the end showing aggregate metrics across all collaborators. To hide this section and make the output more concise, you can disable it:
# Disable overall statistics for a single run
SHOW_OVERALL_STATISTICS=false python3 github-review-analyzer.py
# Or in your .env file
SHOW_OVERALL_STATISTICS=falseThe overall statistics section includes:
- Total number of PRs you reviewed
- Total number of PRs others reviewed for you
- Total lines reviewed (with separate additions and deletions)
- Number of collaborators
This is useful if you only want to focus on the per-user review balance and open PRs without the aggregate summary.
You can configure the tool to filter out PRs from the "Open PRs That Need Your Review" section based on how many reviews they've already received. This is useful when you want to focus on PRs that haven't gotten much attention yet.
Key Features:
- PRs with N or more reviews will be hidden from the open PRs list
- Exception: PRs that explicitly requested your review will ALWAYS be shown, regardless of review count
- The filter displays how many PRs were filtered out
- Color coding (green/yellow/red) is applied based on review balance with each author
Example usage:
# Only show PRs with fewer than 2 reviews (unless you were requested)
MAX_REVIEW_COUNT_THRESHOLD=2 python3 github-review-analyzer.py
# Or in your .env file
MAX_REVIEW_COUNT_THRESHOLD=2Example output:
In the HTML report, filtered PRs are shown at the top of the "Open PRs That Need Your Review" section with clear indicators:
- Green-highlighted PRs indicate you owe them reviews (positive balance)
- Priority messages show the line count balance
- Badges indicate review count, requested reviews, and changes requested
- Each PR has buttons to copy personalized Slack review requests
The review balance table can be sorted by different columns using the SORT_BY environment variable. Available options:
total_prs(default): Total number of PRs reviewed between you and each userbalance: Review balance (positive = you reviewed more of their code, negative = they reviewed more of yours)user: Username (alphabetically)they_reviewed: Total lines they reviewed of your codei_reviewed: Total lines you reviewed of their codetheir_prs: Number of their PRs you reviewedmy_prs: Number of your PRs they reviewed
Example usage:
# Sort by review balance to see who you owe reviews to
SORT_BY=balance python3 github-review-analyzer.py
# Sort alphabetically by username
SORT_BY=user python3 github-review-analyzer.py
# Or in your .env file
SORT_BY=balanceThe script automatically caches API responses to .github_review_cache.json in the current directory. This significantly speeds up subsequent runs by avoiding redundant API calls.
- Automatic: Caching is enabled by default
- Smart PR-state aware: Only caches data for closed PRs (open PRs always fetch fresh data)
- Permanent: Cache entries never expire (closed PRs don't change)
- Selective: Only fetches new data when not in cache
- Persistent: Cache is saved to disk and reused across runs indefinitely
To disable caching, set the USE_CACHE environment variable:
# Disable caching for a single run
USE_CACHE=false python3 github-review-analyzer.py
# Or in your .env file
USE_CACHE=falseTo clear the cache, simply delete the cache file:
rm .github_review_cache.json- Without token: 60 requests/hour
- With token: 5,000 requests/hour
Using a token is highly recommended for analyzing repositories with many PRs.
- The script tracks additions (+lines) and deletions (-lines) separately and also shows the total
- Fetches full PR details to ensure accurate line counts
- Both open and closed PRs are included in the analysis
- Only closed PRs are cached; open PRs always fetch fresh data to reflect ongoing changes
- Cached data never expires since closed PR data is immutable
- You can exclude specific users (e.g., bots like dependabot) from the analysis
- Review events include approvals, change requests, and dismissals
- Comments include both review comments and general PR comments
- PRs are filtered by creation date within the specified time range
- The script handles pagination automatically for repositories with many PRs
Error: Rate limit exceeded
Solution: Use a GitHub Personal Access Token
If you notice missing review data, ensure:
- The time range is appropriate
- You have access to the repository
- The PRs were created within the specified time range
For comprehensive testing instructions, see the Testing Guide.
-
Install development dependencies:
pip install -r requirements-dev.txt
-
Run all tests:
pytest tests/ -v
-
Run tests with coverage report:
pytest tests/ --cov=src --cov-report=term-missing

