Scripts for integrating GitHub context and repository management into AI agent workflows.
If you're about to build PR monitoring, a Greptile review loop ("greploop"), self-merge logic,
a stale-PR sweep, or a Greptile score check — it already exists here. This toolchain is shared
across agents (Alice, Bob) and is hardened for scale. Don't rebuild a parallel; use or extend these.
(Origin of this note: 2026-06 an agent rebuilt greploop + a sweep + a score parser that all already
existed. See scripts/workflow/read-the-task-before-reinvestigating patterns.)
The canonical flow — drive a PR to merge ("greploop"):
| Step | Tool | Notes |
|---|---|---|
| Discover stalled PRs | activity-gate.sh (has a Greptile score sweep) · pr-queue-health.py |
event-driven; surfaces low-scored / stuck PRs |
| Trigger / re-trigger review | greptile-helper.sh (anti-spam: flock, ack-detect, max-retriggers) · pr-greptile-trigger.py (batch) |
NEVER post raw @greptileai review |
| Read the score signal | greptile-merge-signal.py (summary score ≥ threshold + "Safe to merge") |
reusable; default 5/5 |
| Address findings, push | (agent session) | fix the code |
| Resolve addressed threads | resolve-greptile-threads.py |
the resolveReviewThread mutation; fix-first; resolves Greptile-bot threads only |
| Gate the merge | self-merge-check.py |
CI green + a clean machine review + no unresolved threads + score floor (SELF_MERGE_MIN_GREPTILE_SCORE, default 5/5) + category/sensitive-path filter |
| Merge | self-merge-if-eligible.sh / pr-address-wait-and-merge.sh (Bob) |
bounded poll-budget wait → merge |
Greptile is not the only accepted reviewer. On repos Greptile does not cover, the gate was
unsatisfiable ("Greptile review not found"). self-merge-check.py now also accepts the self-hosted
reviewer's <!-- bob-ai-review {…} --> summary marker — but only at full strength: 5/5, at the
current head SHA, with an undegraded consensus record, non-abstaining, and posted by the
authenticated user. Anything less falls back to requiring Greptile. It is an OR, never a
replacement: when Greptile has reviewed, the path is byte-for-byte what it always was and the
marker is not even fetched. Kill switch: SELF_MERGE_ACCEPT_AI_REVIEW=0. The strictness is tuned
for recall, not precision — a false finding only lowers the score and costs a wasted round,
whereas a missed bug produces a clean score and an unreviewed merge.
Robustness patterns (tuned at scale — reuse, don't reinvent):
- Rate limits: gate on
github-rate-limit-health.sh(GH_RATE_LIMIT_HELPER;self-merge-check.pydefers with exit 76). Re-check before expensive sub-steps, not just at cycle start. - Fewer API calls: fetch Greptile review data ONCE per PR and reuse (see
self-merge-check.py's_fetch_greptile_review_datapassed to both helpers). Don't spawn a per-PR subprocess that re-fetches. - Caching: key Greptile status by PR head-SHA — unchanged PRs skip the fetch.
- Pagination: paginate
reviewThreads(avoids silently undercounting unresolved threads). - GraphQL attribution: wrap GraphQL calls for consumption accounting.
See also: knowledge/research/2026-06-12-monitoring-robustness-alice-vs-bob.md (Alice repo) and the
greploop skill (greptileai/skills, MIT) for the upstream pattern this implements.
Generates comprehensive GitHub context for AI agent conversations, reducing the need for manual tool calls during autonomous operation.
Features:
- GitHub notifications (unread, with type and reason)
- Open issues in agent workspace repository
- Multi-repository CI status checking
- Open PRs across all repositories
- Recent PRs in current repository
Usage:
./scripts/github/context-gh.shRequirements:
gh(GitHub CLI) installed and authenticated- Repository list configured in repo-status.sh
Output:
Markdown-formatted sections that can be included in agent context via gptme.toml's context_cmd.
Check CI status across multiple repositories to catch failing builds before pushing changes.
Features:
- Quick status check for multiple repos
- Color-coded output (✓ passing, ✗ failing, ⚠ other states)
- Workflow URL display for failing builds
- Configurable repository list
Usage:
./scripts/github/repo-status.shConfiguration:
Pass repositories as arguments (format: owner/repo:Label or just owner/repo):
./scripts/github/repo-status.sh gptme/gptme:gptme gptme/gptme-rag:gptme-ragOr set GH_USER environment variable to customize user for PR checking:
export GH_USER=myusername
./scripts/github/repo-status.shDefault behavior (no arguments): Checks gptme ecosystem repos.
Requirements:
gh(GitHub CLI) installed and authenticated
Lightweight pre-check that scans GitHub for actionable activity before spawning an expensive LLM session. Uses state-tracked timestamps to avoid re-reporting old items.
Without this gate, monitoring services can waste hundreds of LLM sessions per week on empty runs. In Bob's deployment, this gate prevents ~97% of NOOP monitoring runs.
Checks performed:
- PR updates (new comments, reviews — excluding self-authored)
- CI failures (state-change tracked, dedup by conclusion hash)
- Merge conflicts (always reported until resolved)
- Merge readiness (CLEAN status + acceptable Greptile score)
- GitHub notifications (filtered for actionable reasons)
- Greptile score sweep (finds low-scored PRs needing code fixes)
- Assigned issues (issues assigned to the configured author)
- Master branch CI failures (CI regressions on the main branch)
Exit codes:
0= actionable work found (items printed to stdout)1= no actionable work found2= usage error
Usage:
# Basic usage
activity-gate.sh --author MyBot --org myorg
# With extra repos outside the org
activity-gate.sh --author MyBot --org myorg --repo OtherOrg/repo
# JSONL output for structured processing
activity-gate.sh --author MyBot --org myorg --format jsonl
# Custom state directory (default: /tmp/github-activity-gate-state)
activity-gate.sh --author MyBot --org myorg --state-dir /tmp/my-state
# Use as a gate before spawning a session
if work=$(./activity-gate.sh --author MyBot --org myorg); then
echo "Work found, spawning session..."
echo "$work"
else
echo "Nothing to do, skipping."
fiState tracking: Each check type uses files in the state directory to remember what it last reported. On first run, all items are seeded (state created) but NOT reported — only changes after the first run trigger output. This prevents a flood of items on initial setup.
Integration pattern (project monitoring):
# In your monitoring script:
ACTIVITY_GATE="$WORKSPACE/gptme-contrib/scripts/github/activity-gate.sh"
STATE_DIR="/tmp/my-agent-monitoring-state"
# Use a pending state dir so crashes don't lose state
PENDING_STATE_DIR="${STATE_DIR}-pending"
mkdir -p "$STATE_DIR" "$PENDING_STATE_DIR"
rsync -a --delete "$STATE_DIR/" "$PENDING_STATE_DIR/"
gate_exit=0
work=$("$ACTIVITY_GATE" --author "$AUTHOR" --org "$ORG" \
--state-dir "$PENDING_STATE_DIR" --format jsonl) || gate_exit=$?
if [ "$gate_exit" -eq 2 ]; then
echo "Error: activity-gate.sh usage error (check AUTHOR/ORG/STATE_DIR are set)" >&2
exit 2
elif [ "$gate_exit" -ne 0 ]; then
echo "No work found, skipping session."
exit 0
fi
# Promote state only after successful session — uncomment after your session call:
# rsync -a "$PENDING_STATE_DIR/" "$STATE_DIR/"
# Without this, all items re-emit every run (state is never committed).Requirements:
gh(GitHub CLI) installed and authenticatedjqfor JSONL output parsing
Safe Greptile review trigger with anti-spam guards (flock, age guard, max re-triggers,
fail-safe cooldown). Always use this instead of posting raw @greptileai review comments.
Usage:
# Trigger a review (safe — checks guards first)
bash scripts/github/greptile-helper.sh trigger OWNER/REPO PR_NUMBER
# Check review status
bash scripts/github/greptile-helper.sh status OWNER/REPO PR_NUMBERRequirements:
gh(GitHub CLI) installed and authenticated- Greptile GitHub app installed on the target repository
Fetch and format unread GitHub notifications for agent context injection.
Usage:
./scripts/github/check-notifications.shThese scripts are designed to be integrated into gptme agent workflows:
-
Dynamic Context: Include context-gh.sh in your agent's main context.sh script:
# In your agent's scripts/context.sh ./gptme-contrib/scripts/github/context-gh.shOr use directly in gptme.toml (less common):
context_cmd = "gptme-contrib/scripts/github/context-gh.sh"
-
Pre-Push Checks: Run repo-status.sh before pushing to ensure CI health:
./scripts/github/repo-status.sh && git push -
Autonomous Operations: Include GitHub context automatically in agent prompts to reduce exploratory tool calls.
-
Project Monitoring Gate: Use activity-gate.sh to prevent wasted LLM sessions:
# In your monitoring timer/service script if work=$(./gptme-contrib/scripts/github/activity-gate.sh \ --author MyAgent --org myorg --format jsonl); then # Spawn LLM session with $work as context echo "$work" | your-agent-harness fi
- Reduced Tool Calls: GitHub context is served upfront instead of requiring multiple API calls
- Faster Decision Making: Agent can see notifications, issues, and CI status immediately
- Better Coordination: Agent aware of open issues and PRs without manual checking
- CI Health Awareness: Catch failing builds before adding more changes
Batch-trigger safe Greptile re-review requests for open PRs.
Scans open PRs authored by the authenticated user, identifies which ones need a
re-review because new commits landed since the last Greptile review, and routes
triggers through greptile-helper.sh. Never triggers initial reviews — Greptile
auto-reviews new PRs.
Features:
- Safe re-review triggering (no spam — uses greptile-helper.sh guards)
- Configurable repo list via
GREPTILE_REPOSenv var or--repoflag - Dry-run mode by default (use
--executeto actually trigger) - Status overview mode (
--status) - Filter PRs by author via
--author(default: authenticated user)
Usage:
# Show what would be triggered (dry-run)
python3 scripts/github/pr-greptile-trigger.py
# Actually trigger re-reviews
python3 scripts/github/pr-greptile-trigger.py --execute
# Show review status for all open PRs
python3 scripts/github/pr-greptile-trigger.py --status
# Scan a specific repo
python3 scripts/github/pr-greptile-trigger.py --repo gptme/gptme
# Use custom repo list
GREPTILE_REPOS=myorg/repo1,myorg/repo2 python3 scripts/github/pr-greptile-trigger.py
# Filter by a specific author (useful in shared CI contexts)
python3 scripts/github/pr-greptile-trigger.py --author mybotRequirements:
gh(GitHub CLI) installed and authenticatedgreptile-helper.shin the same directory
Evaluates whether a PR is eligible for autonomous agent self-merge.
Applies a conservative policy: CI must be green, Greptile must have reviewed with no unresolved threads, and changed files must fall into a low-risk category (tests, docs, lessons, internal tooling, task metadata). Sensitive/infra paths immediately disqualify.
Features:
- Auto-detects workspace repo from git remote (override with
--workspace-repoorWORKSPACE_REPO) - Cross-repo PRs disqualified when workspace repo is set (clear
WORKSPACE_REPOto disable) - JSON output mode for scripting
- Detailed per-check reasoning
Usage:
# Check a PR by URL
python3 scripts/github/self-merge-check.py https://github.com/owner/repo/pull/123
# Check by repo and number
python3 scripts/github/self-merge-check.py --repo gptme/gptme 456
# JSON output for scripting
python3 scripts/github/self-merge-check.py --json https://github.com/owner/repo/pull/123
# Allow cross-repo merges (clear workspace repo restriction)
WORKSPACE_REPO="" python3 scripts/github/self-merge-check.py https://github.com/gptme/gptme/pull/456
# Override workspace repo detection
python3 scripts/github/self-merge-check.py --workspace-repo myorg/myrepo <pr-url>Exit codes: 0 = eligible, 1 = not eligible, 2 = error
Requirements:
gh(GitHub CLI) installed and authenticated- Greptile installed on the target repo for review checking
Evaluates whether a Greptile summary comment is strong enough for fast-path merge use:
allowlisted bot login + "Safe to merge" + score ≥ threshold (default 5/5). A reusable score signal —
self-merge-check.py wires it in as the score floor so resolving threads alone can't merge a
low-scored PR. Parse failure does not block (the thread/category gates still apply).
python3 scripts/github/greptile-merge-signal.py --repo owner/repo 123 # JSON; exit 0 eligible, 1 notResolves addressed Greptile review threads via the resolveReviewThread GraphQL mutation —
the gap that blocks self-merge-check.py (it requires no unresolved threads, but we reply to
nitpicks rather than resolve them, so the deterministic merge path never fires on nitpick-laden
PRs). Call it after addressing findings (fix-first), or with --outdated-only for the
conservative "code changed since the comment" heuristic. Safety: only ever resolves
Greptile-bot-authored threads — never touches human threads. Paginates reviewThreads so it
can't silently undercount; per-thread resolve failures are non-fatal (the loop continues).
# Dry-run first — list what would be resolved
python3 scripts/github/resolve-greptile-threads.py owner/repo#123 --dry-run
# Resolve all addressed Greptile threads (JSON summary on stdout, progress on stderr)
python3 scripts/github/resolve-greptile-threads.py owner/repo#123 --json
# Conservative: only resolve threads whose code changed since the comment
python3 scripts/github/resolve-greptile-threads.py owner/repo 123 --outdated-onlyExit codes: 0 = ok (prints count resolved), 2 = arg/gh error.
- gptme - The AI agent framework these scripts support
- gptme-agent-template - Template for creating new agents