"""ai-code-review-bots-compared.py - turn the vendors' published per-review cost figures into a monthly range for your own pull-request volume and trigger setting. The per-review figures are the ones the vendors publish, read 2026-09-24: GitHub Copilot code review: "an estimated $0.05 USD to $1 USD worth of AI credits with 'Lite' effort, and $0.25 USD to $5 USD worth of AI credits with 'Balanced' effort" (excludes GitHub Actions minutes). Claude Code Review (managed service): "Each review averages $15-25 in cost". Gemini Code Assist on GitHub and the self-hosted claude-code-action publish no per-review figure, so they are not estimated here. The two figures are not the same kind of number: Copilot's is a typical range per review, Claude's an average band. Treat the output as the order of magnitude, not a quote. Reviews per pull request follow the trigger setting: once - one review when the PR opens (Copilot automatic review without "Review new pushes"; Claude "Once after PR creation") push - one review on opening plus one per later push (Copilot "Review new pushes"; Claude "After every push") Standard library only; Python 3.8 or later. Run: python ai-code-review-bots-compared.py [prs_per_month] [pushes_after_opening] (defaults: 200 pull requests a month, 3 pushes after opening) """ import sys PER_REVIEW = { # (low, high) US dollars per review, as published "Copilot, Lite effort": (0.05, 1.00), "Copilot, Balanced effort": (0.25, 5.00), "Claude Code Review": (15.00, 25.00), } def reviews_per_pr(trigger, pushes_after_opening): return 1 if trigger == "once" else 1 + pushes_after_opening def monthly(prs, pushes_after_opening): rows = [] for name, (lo, hi) in PER_REVIEW.items(): for trigger in ("once", "push"): n = prs * reviews_per_pr(trigger, pushes_after_opening) rows.append((name, trigger, n, n * lo, n * hi)) return rows if __name__ == "__main__": prs = int(sys.argv[1]) if len(sys.argv) > 1 else 200 pushes = int(sys.argv[2]) if len(sys.argv) > 2 else 3 print(f"{prs} pull requests a month, {pushes} pushes after opening each") print(f"{'service':26} {'trigger':8} {'reviews':>8} {'low':>12} {'high':>12}") for name, trigger, n, lo, hi in monthly(prs, pushes): print(f"{name:26} {trigger:8} {n:8,d} {lo:12,.2f} {hi:12,.2f}")