Skip to content

Instantly share code, notes, and snippets.

@avinayak
Last active May 23, 2025 02:13
Show Gist options
  • Save avinayak/2054c61262bebb41b1600acaaf534fe2 to your computer and use it in GitHub Desktop.
Save avinayak/2054c61262bebb41b1600acaaf534fe2 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
# <xbar.title>prs</xbar.title>
# <xbar.version>v1.0</xbar.version>
# <xbar.author>Atul Vinayak</xbar.author>
# <xbar.author.github>avinayak</xbar.author.github>
# <xbar.desc>Shows a list of merged pull requests for the current user</xbar.desc>
# <xbar.dependencies>bash</xbar.dependencies>
import subprocess
import json
from datetime import datetime, timedelta, timezone
def get_username():
return subprocess.check_output(
["/opt/homebrew/bin/gh", "api", "user", "--jq", ".login"], encoding="utf-8"
).strip()
def get_last_monday_iso():
today = datetime.now(timezone.utc)
monday = today - timedelta(days=today.weekday())
return monday.strftime("%Y-%m-%dT00:00:00Z")
def get_one_month_ago_iso():
today = datetime.now(timezone.utc)
one_month_ago = today - timedelta(days=30)
return one_month_ago.strftime("%Y-%m-%dT00:00:00Z")
def get_merged_prs_since_monday(username):
cmd = [
"/opt/homebrew/bin/gh", "search", "prs",
"--author", username,
"--merged",
"--sort", "updated",
"--order", "desc",
"--json", "title,number,url,updatedAt,repository",
"--jq", f'.[] | select(.updatedAt >= "{get_last_monday_iso()}")'
]
output = subprocess.check_output(cmd, encoding="utf-8").strip()
if not output:
return []
return [json.loads(line) for line in output.splitlines()]
def get_open_prs(username):
cmd = [
"/opt/homebrew/bin/gh", "search", "prs",
"--author", username,
"--state", "open",
"--sort", "updated",
"--order", "desc",
"--json", "title,number,url,updatedAt,repository,isDraft", # Added isDraft
"--jq", f'.[] | select(.updatedAt >= "{get_one_month_ago_iso()}") | select(.isDraft == false)' # Added isDraft filter
]
output = subprocess.check_output(cmd, encoding="utf-8").strip()
if not output:
return []
return [json.loads(line) for line in output.splitlines()]
def get_approved_not_merged_prs(username):
cmd = [
"/opt/homebrew/bin/gh", "search", "prs",
"--author", username,
"--state", "open",
"--review", "approved",
"--sort", "updated",
"--order", "desc",
"--json", "title,number,url,updatedAt,repository,isDraft",
"--jq", f'.[] | select(.updatedAt >= "{get_one_month_ago_iso()}") | select(.isDraft == false)' # Ensure draft PRs are excluded
]
output = subprocess.check_output(cmd, encoding="utf-8").strip()
if not output:
return []
return [json.loads(line) for line in output.splitlines()]
def get_growth_emoji(count):
if count <= 1:
return "🌱"
elif count <= 3:
return "πŸƒ"
elif count <= 5:
return "🌿"
elif count <= 7:
return "πŸͺ΄"
elif count <= 9:
return "🌴"
elif count <= 11:
return "🌲"
elif count <= 13:
return "🌳"
elif count <= 15:
return "🌸"
elif count <= 17:
return "🌺"
elif count <= 19:
return "🌻"
else:
return "🌟"
def main():
try:
username = get_username()
merged_prs = get_merged_prs_since_monday(username)
open_prs = get_open_prs(username)
approved_not_merged_prs = get_approved_not_merged_prs(username)
growth_emoji = get_growth_emoji(len(merged_prs))
print(f"{growth_emoji}{len(merged_prs)}/{len(open_prs)}/{len(approved_not_merged_prs)}")
print("---")
print(f"βœ… Merged PRs since last Monday: {len(merged_prs)}")
for pr in merged_prs:
print(f"--{pr['title']} (#{pr['number']}) | href={pr['url']}")
print(f"⏳ Open PRs: {len(open_prs)}")
for pr in open_prs:
print(f"--{pr['title']} (#{pr['number']}) | href={pr['url']}")
print(f"πŸ‘ Approved but not merged PRs: {len(approved_not_merged_prs)}")
for pr in approved_not_merged_prs:
print(f"--{pr['title']} (#{pr['number']}) | href={pr['url']}")
except Exception as e:
print(f"❌ Error: {e}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment