glreview
Track code review coverage with git-level precision. Know exactly which modules have been reviewed, at which commit, and what changed since.
The Problem
Code review is usually per-PR, but that doesn't answer: "Has this module ever been thoroughly reviewed?" Teams maintaining critical software need to know:
- Which files have never been reviewed?
- Which reviews are stale because the code changed?
- How much of the codebase has review coverage?
glreview tracks review status per-module, persisted in git, integrated with GitLab issues.
What It Looks Like
$ glreview status
Review Status
─────────────────────────────────────────────────────
Reviewed: 12 modules (2,450 lines) ██████████░░ 48%
In Progress: 2 modules (380 lines)
Needs Review: 11 modules (1,890 lines)
Stale (changed since review):
src/core/engine.py changed 3 days ago
src/utils/helpers.py changed 1 week ago
In Progress:
src/api/handlers.py issue #142, @alice
Needs Review:
src/auth/oauth.py 245 lines
src/core/scheduler.py 189 lines
src/api/middleware.py 156 lines
Installation
Prerequisites: Python 3.9+, git repository, GitLab project
pip install glreview
For AI-assisted review features, also install Claude Code.
Quick Start
1. Configure source patterns
Add to pyproject.toml:
[tool.glreview]
sources = ["src/**/*.py"]
exclude = ["**/test_*.py", "**/_version.py"]
2. Set up GitLab authentication
export GITLAB_PRIVATE_TOKEN=glpat-xxxxxxxxxxxx
# For self-hosted GitLab:
export GITLAB_URL=https://gitlab.example.com
3. Initialize
glreview init
This creates .glreview/registry.json. Commit it to version control.
4. Start reviewing
# See what needs review
glreview status
# Start a review (creates GitLab issue)
glreview start src/mymodule.py --assignee @reviewer
# After reviewer closes the issue, sign off
glreview signoff src/mymodule.py
# Commit the updated registry
git add .glreview/ && git commit -m "review: src/mymodule.py"
Core Workflow
Review lifecycle
┌─────────────┐
│ needs_review│◄──────────────────┐
└──────┬──────┘ │
│ start │ cancel (or code changes)
▼ │
┌─────────────┐ │
│ in_progress │───────────────────┤
└──────┬──────┘ │
│ signoff │
▼ │
┌─────────────┐ │
│ reviewed │───────────────────┘
└─────────────┘
Starting a review
# Basic - creates GitLab issue
glreview start src/module.py
# With assignee
glreview start src/module.py --assignee @alice
# Link to existing issue instead of creating new
glreview start src/module.py --issue "https://gitlab.com/.../issues/42"
Signing off
# Standard signoff (verifies GitLab issue is closed)
glreview signoff src/module.py
# Skip issue verification
glreview signoff src/module.py --skip-verify
# With explicit reviewer name
glreview signoff src/module.py --reviewer @bob
Handling changes during review
If code changes while a review is in progress:
# See what changed
glreview diff src/module.py --since-start
# Option 1: Acknowledge changes and sign off anyway
glreview signoff src/module.py --acknowledge
# Option 2: Cancel and restart at current commit
glreview cancel src/module.py --restart
Viewing diffs
# Changes since last review (deciding whether to re-review)
glreview diff src/module.py
# Changes during current review (before signing off)
glreview diff src/module.py --since-start
# Open in GitLab web UI
glreview diff src/module.py --web
AI-Assisted Review (Optional)
glreview integrates with Claude Code for automated code analysis. This is entirely optional - the core workflow works without it.
Setup
# Verify Claude CLI is installed
claude --version
# Generate project context (one-time)
glreview claude-init
This creates .glreview/context.json with project conventions, module relationships, and test file mappings. Commit it to version control.
Running AI review
# Run review and post findings to GitLab issue
glreview claude-review src/module.py
# Print findings to terminal only (don't post)
glreview claude-review src/module.py --no-post
# Preview the prompt without running
glreview claude-review src/module.py --dry-run
Reviews evaluate six criteria:
- Correctness - Logic errors, wrong results, unhandled edge cases
- Error Handling - Input validation, failure handling, resource leaks
- Code Quality - DRY, organization, naming, appropriate abstractions
- Testing - Coverage, meaningful assertions, edge cases
- Documentation - Non-obvious decisions explained, API documented
- Risk - Security, performance, data integrity (when applicable)
Each finding is rated OK, SUGGESTED, or REQUIRED.
Fixing issues
# Interactive - choose which items to fix
glreview claude-fix src/module.py
# Batch - fix all REQUIRED items automatically
glreview claude-fix src/module.py --batch
# Create a merge request with the fixes
glreview claude-fix src/module.py --batch --create-mr
# Specify a target branch for the MR
glreview claude-fix src/module.py --batch --create-mr --target-branch develop
The --create-mr flag automates the full workflow: creates a branch (fix/review-{module}-{issue}), commits the changes, pushes to origin, and opens a GitLab merge request that references the review issue. In interactive mode, you'll be prompted to confirm before the MR is created.
Updating context
# After significant codebase changes
glreview claude-sync
# View context for a module
glreview claude-context src/module.py
Batch Operations
Start reviews for multiple modules at once:
# Start reviews for all modules needing review
glreview batch-start
# Preview what would happen
glreview batch-start --dry-run
# Also run Claude review for each (posts to issues)
glreview batch-start --claude-review
CI Integration
Validate review coverage in your pipeline with glreview ci. No push tokens or git plumbing required — the registry is committed by developers as part of their normal workflow.
Setup
- Keep
.glreview/committed in your repo (runglreview synclocally when adding/removing source files) - Add to
.gitlab-ci.yml:
review:
stage: review
image: python:3.12
script:
- pip install glreview
- glreview ci --report REVIEW_COVERAGE.md
artifacts:
paths:
- REVIEW_COVERAGE.md
Run glreview ci-config for a complete example including release gates.
Enforcing coverage
# Block releases without 100% review coverage
glreview ci --fail-under 100
Staleness checks
# Fail if reviewed files have changed since last review
glreview check
Configuration Reference
Full pyproject.toml options:
[tool.glreview]
# Source file patterns (required)
sources = ["src/**/*.py", "lib/**/*.py"]
# Patterns to exclude
exclude = ["**/test_*.py", "**/_version.py", "**/conftest.py"]
# Registry file location (default: .glreview/registry.json)
registry = ".glreview/registry.json"
# Default labels for created issues
issue_labels = ["review::pending", "team::backend"]
# Custom issue template (Jinja2)
issue_template = ".glreview/issue_template.md"
# Reviewer teams (use with --assignee @team/security)
[tool.glreview.teams]
security = ["@alice", "@bob"]
frontend = ["@carol", "@dave"]
# Custom instructions injected into Claude prompts (optional)
[tool.glreview.claude]
fix_instructions = """
After making fixes:
- Run `python -m pytest tests/ -x` to verify nothing is broken
- Run `ruff check src/` for lint compliance
"""
review_instructions = """
This project uses numpy-style docstrings.
All public functions must have type annotations.
"""
Custom issue templates
Create a Jinja2 template with access to these variables:
| Variable | Description |
|---|---|
path |
Module path |
lines |
Line count |
current_commit |
Current git commit |
previous_commit |
Last reviewed commit (re-reviews) |
diff_url |
GitLab compare URL (re-reviews) |
classes |
List of public classes |
functions |
List of public functions |
Commands
| Command | Description |
|---|---|
init |
Initialize glreview in a project |
status |
Show review progress and what needs attention |
start PATH |
Start a review, create GitLab issue |
signoff PATH |
Sign off on completed review |
cancel PATH |
Cancel review (--restart to restart at HEAD) |
diff PATH |
Show changes since last review |
sync |
Sync registry with filesystem changes |
list |
List all tracked modules |
report |
Generate coverage report (markdown/json/badge) |
ci |
Run sync + coverage check for CI pipelines |
check |
CI check for changes to reviewed files |
batch-start |
Start reviews for all pending modules |
reviewers |
List configured reviewers |
ci-config |
Print recommended CI configuration |
claude-review PATH |
Run AI code review |
claude-fix PATH |
Fix issues from AI review (--create-mr to open MR) |
claude-init |
Generate AI project context |
claude-sync |
Update AI context |
claude-context |
View AI context |
Use glreview COMMAND --help for detailed options.
Troubleshooting
"Module not found in registry"
Run glreview sync to add new files, or check your sources patterns in pyproject.toml.
"GitLab API not available"
Set GITLAB_PRIVATE_TOKEN. For self-hosted GitLab, also set GITLAB_URL.
"Issue not closed"
Close the GitLab issue before signing off. Use --skip-verify to bypass this check.
"File changed during review"
Code was modified after start. Use --acknowledge to sign off anyway, or cancel --restart to restart.
Claude commands not working Install Claude Code CLI: https://claude.ai/code
License
MIT
Release files for glreview 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| glreview-0.6.0.tar.gz | 146.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| glreview-0.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 228.6 kB
Release files / glreview-0.6.0.tar.gz
| Download URL | glreview-0.6.0.tar.gz |
|---|---|
| Size | 146.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
80494fb6bb5972b4150620811233c8ba213145397254b47ff55267cec44ad351
|
|
BLAKE2b-256 checksum How to use checksums |
84e4c137808958e878b1a25f3c785fab325d8b390126abf5c6af1da71df1d0c9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.11.11
|
Release files / glreview-0.6.0-py3-none-any.whl
| Download URL | glreview-0.6.0-py3-none-any.whl |
|---|---|
| Size | 82.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7e8bcc810e16084d8485b99ed9f3c80117bbe020e62b5fa4a05a2237112c311c
|
|
BLAKE2b-256 checksum How to use checksums |
265c2fe189f15f01bb76d93c656217175bcef4f58d9379bf26e080c4eb9df0f8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.11.11
|