Deterministic PR readiness detection for AI coding agents
Project description
Good To Go
Deterministic PR readiness detection for AI coding agents
Good To Go helps AI agents (like Claude Code) know exactly when a PR is ready to merge. No guessing, no polling indefinitely, no missing comments.
The Problem
AI agents creating PRs face a common challenge: How do I know when I'm actually done?
- CI is still running... is it done yet?
- CodeRabbit left 12 comments... which ones need action?
- A reviewer requested changes... did I address them all?
- There are 3 unresolved threads... are they blocking?
Without deterministic answers, agents either wait too long, miss comments, or keep asking "is it ready yet?"
The Solution
Good To Go provides deterministic PR state analysis via a simple CLI:
gtg 123 --repo owner/repo
Returns (default - AI-friendly):
- Exit code 0: Any analyzable state (ready, action required, threads, CI)
- Exit code 4: Error fetching data
For shell scripting, use -q for semantic exit codes without output, or --semantic-codes for output with semantic codes.
Installation
pip install gtg
That's it. No other dependencies required.
Usage
Basic Check
# Check if PR #123 in myorg/myrepo is ready to merge
gtg 123 --repo myorg/myrepo
# With JSON output for programmatic use
gtg 123 --repo myorg/myrepo --format json
# Human-readable text format
gtg 123 --repo myorg/myrepo --format text
Authentication
Set your GitHub token:
export GITHUB_TOKEN=ghp_your_token_here
Note: The CLI reads GITHUB_TOKEN from the environment. There is no --token flag for security reasons.
Exit Codes
Default (AI-friendly) - returns 0 for all analyzable states:
| Code | Meaning |
|---|---|
| 0 | Any analyzable state (parse the JSON status field for details) |
| 4 | Error fetching PR data |
With -q or --semantic-codes - returns different codes per status:
| Code | Status | Meaning |
|---|---|---|
| 0 | READY | All clear - good to go! |
| 1 | ACTION_REQUIRED | Actionable comments need fixes |
| 2 | UNRESOLVED | Unresolved review threads |
| 3 | CI_FAILING | CI/CD checks failing |
| 4 | ERROR | Error fetching PR data |
Use -q (quiet mode) for shell scripts that only need the exit code.
Quick Examples
Here's what the output looks like for each status (using --format text):
READY - All clear, ready to merge:
OK PR #123: READY
CI: success (5/5 passed)
Threads: 3/3 resolved
ACTION_REQUIRED - Actionable comments need attention:
!! PR #456: ACTION_REQUIRED
CI: success (5/5 passed)
Threads: 8/8 resolved
Action required:
- Fix CRITICAL comment from coderabbit in src/db.py:42
- 2 comments require investigation (ambiguous)
UNRESOLVED_THREADS - Review threads need resolution:
?? PR #789: UNRESOLVED_THREADS
CI: success (5/5 passed)
Threads: 2/4 resolved
Action required:
- 2 unresolved review threads need attention
CI_FAILING - CI checks not passing:
XX PR #101: CI_FAILING
CI: failure (3/5 passed)
Threads: 2/2 resolved
Action required:
- CI checks are failing - fix build/test errors
Text Format Status Icons
| Icon | Status | Meaning |
|---|---|---|
OK |
READY | All clear - good to go! |
!! |
ACTION_REQUIRED | Actionable comments need fixes |
?? |
UNRESOLVED_THREADS | Unresolved review threads |
XX |
CI_FAILING | CI/CD checks failing |
## |
ERROR | Error fetching PR data |
JSON Output
gtg 123 --repo myorg/myrepo --format json
Returns structured data including:
- CI status (passed/failed/pending checks)
- Thread summary (resolved/unresolved counts)
- Classified comments (actionable vs non-actionable)
- Action items list
See USAGE.md for full JSON schema and examples.
GitHub Actions & Branch Protection
Make gtg a required check to block merging until PRs are truly ready:
# Enable branch protection with gtg-check as required
# Use actual job names from your CI workflow, not the workflow name
gh api repos/OWNER/REPO/branches/main/protection -X PUT --input - <<'EOF'
{
"required_status_checks": {
"strict": true,
"contexts": ["Lint & Format", "Tests (3.9)", "Type Check", "gtg-check"]
},
"enforce_admins": true,
"required_pull_request_reviews": null,
"restrictions": null,
"allow_force_pushes": false
}
EOF
Note: Use actual job names (e.g.,
"Lint & Format") not workflow names (e.g.,"Tests & Quality").enforce_admins: truemeans admins must follow all rules. See USAGE.md for details.
See USAGE.md for the full GitHub Actions workflow setup.
Supported Automated Reviewers
Good To Go recognizes and classifies comments from:
- CodeRabbit - Critical/Major/Minor/Trivial severity
- Greptile - Actionable comment detection
- Claude Code - Must/should/error/bug patterns
- Cursor/Bugbot - Severity-based classification
- Generic - Fallback for unknown reviewers
For AI Agents
If you're an AI agent, use Good To Go in your PR workflow:
import subprocess
import json
result = subprocess.run(
["gtg", "123", "--repo", "owner/repo", "--format", "json"],
capture_output=True,
text=True
)
if result.returncode == 0:
print("Good to go! Ready to merge.")
elif result.returncode == 1:
data = json.loads(result.stdout)
print(f"Action required: {data['action_items']}")
Or use the Python API directly:
from goodtogo import PRAnalyzer, Container
container = Container.create_default(github_token="ghp_...")
analyzer = PRAnalyzer(container)
result = analyzer.analyze("owner", "repo", 123)
if result.status == "READY":
print("Good to go!")
else:
for item in result.action_items:
print(f"- {item}")
Documentation
- USAGE.md - Detailed CLI usage and examples
- CONTRIBUTING.md - Development setup and contribution guide
License
MIT License - see LICENSE for details.
Credits
Created by David Sifry with Claude Code.
Made with Claude Code
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gtg-0.4.0.tar.gz.
File metadata
- Download URL: gtg-0.4.0.tar.gz
- Upload date:
- Size: 51.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9aeefee7a01c8cd51684d146061990dadf714a10f783816aaa48123a06fe7a1c
|
|
| MD5 |
e3ae3e0ea66fb119d23922591dbf9481
|
|
| BLAKE2b-256 |
64a3e9a0df63a4276cdcef5901a5831d08db7444a248808ecd10e61de5ab18b6
|
Provenance
The following attestation bundles were made for gtg-0.4.0.tar.gz:
Publisher:
publish.yml on dsifry/goodtogo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gtg-0.4.0.tar.gz -
Subject digest:
9aeefee7a01c8cd51684d146061990dadf714a10f783816aaa48123a06fe7a1c - Sigstore transparency entry: 832749195
- Sigstore integration time:
-
Permalink:
dsifry/goodtogo@837b5b03e519f2ce84d9174566e4641483476a4b -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/dsifry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@837b5b03e519f2ce84d9174566e4641483476a4b -
Trigger Event:
release
-
Statement type:
File details
Details for the file gtg-0.4.0-py3-none-any.whl.
File metadata
- Download URL: gtg-0.4.0-py3-none-any.whl
- Upload date:
- Size: 61.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
794f18a53737aff0cff09901ff51dbd546a2dfca17a30fde2c2c990753d5785a
|
|
| MD5 |
d08b3d8bf3bc53924d787da188b3b42c
|
|
| BLAKE2b-256 |
9d23c1b521d4308a39e8c7bbe62f34dfece1f07d6e9cdf29a4a00f0aa15cfa6e
|
Provenance
The following attestation bundles were made for gtg-0.4.0-py3-none-any.whl:
Publisher:
publish.yml on dsifry/goodtogo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gtg-0.4.0-py3-none-any.whl -
Subject digest:
794f18a53737aff0cff09901ff51dbd546a2dfca17a30fde2c2c990753d5785a - Sigstore transparency entry: 832749196
- Sigstore integration time:
-
Permalink:
dsifry/goodtogo@837b5b03e519f2ce84d9174566e4641483476a4b -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/dsifry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@837b5b03e519f2ce84d9174566e4641483476a4b -
Trigger Event:
release
-
Statement type: