Skip to content
Registry

github

v0.4.0

GitHub CLI and event-driven PR monitoring — typed queries and mutations, authenticated temporary webhooks, CI/comment/review notifications, and merge-triggered cleanup.

Install

bash
iii trigger compose::add worker=github@0.4.0

Run in your project with the iii engine running. Exact versions are immutable and digest-pinned.

skill doc

SKILL.md

PR webhook monitoring (opt-in)

For durable PR monitoring, use github::pr::event, NOT github::called. First arm the trigger with a caller-chosen watch_id, then call github::pr::watch with that same ID, pr_url OR repo + number, optional events: [ci,comments,reviews,pr], stop_on: merged|closed (default merged), and mandatory future RFC3339 expires_at. Read github::pr::watch-status once after watch to close the initial race. Never interval-poll PRs.

Inspect status and health.last_error: preparing is not active ingress; cleanup_pending is not successful cleanup. unwatch and manual recover are mutations requiring approval. Internal github::webhooks::* functions must not be called by an agent. Event callbacks must dedupe event_id; namespace and metadata are preserved, errors propagate to the durable queue. A single passing check is NOT aggregate CI success. Closed without merge remains watched until expiry when stop_on is merged.

Operator setup requires persistent SQLite, queue builtin file_based (current Redis adapter is NOT durable), HTTP dedicated public listener, Quick Tunnel, cron, and gh auth with Webhooks write plus repository reads. Default enabled is false. See the webhook guide. Quick Tunnels are not zero-loss; recovery lists failed deliveries and requests bounded redelivery, reconciling current state. Do not enable merely because a public repository can be read.

github

The github worker wraps the GitHub CLI (gh). Thirty typed functions cover the high-traffic surface (pr, issue, repo, run, workflow, release, search); github::exec runs any other gh command verbatim, and github::api reaches any GitHub REST endpoint. Auth comes from the worker's GH_TOKEN configuration or the host's ambient gh auth login state. There is no local checkout: every repo-scoped call takes an explicit repo: "owner/name".

When to Use

  • Check a PR before landing: github::pr::view, github::pr::checks (failing/pending checks are data, not errors), github::pr::diff.
  • Open or shepherd a PR: github::pr::create / review / merge.
  • File and triage issues: github::issue::create / list / comment / close.
  • Watch or poke CI: github::run::list / view / rerun / cancel; dispatch with github::workflow::run.
  • Cut or inspect releases: github::release::create / list / view.
  • Find things org-wide: github::search::repos / issues / prs / code (qualifiers like repo:o/r is:open go in the query string).
  • Anything gh does that has no typed function → github::exec { args: [...] }.
  • Any REST endpoint → github::api { path: "repos/o/r/…", jq? }.

Boundaries

  • Needs the gh CLI on the worker host; a missing binary errors at call time with code gh_not_found (functions still register without it).
  • Mutations (create/edit/merge/comment/review/close/rerun/cancel/workflow run/release create) and both escape hatches are approval-gated by default; the read-only surface is allowed (see iii-permissions.yaml).
  • Curated functions error on a non-zero gh exit (the message carries gh's stderr); github::exec returns exit_code/stderr/timed_out as data instead.
  • Output is capped per stream (default 1 MiB) with *_truncated flags; per-call timeout_ms clamps to max_timeout_ms (default 120 s; 30 s when omitted).
  • github::api paths take concrete owner/repo values — {owner}/{repo} placeholders need a checkout the worker does not have.

Functions

  • github::pr::* — list, view, create, edit, merge, comment, review, diff, checks.
  • github::issue::* — list, view, create, edit, comment, close.
  • github::repo::* — view, list.
  • github::run::* — list, view, rerun, cancel (Actions runs).
  • github::workflow::* — list, run (workflow_dispatch).
  • github::release::* — list, view, create.
  • github::search::* — repos, issues, prs, code.
  • github::exec — { args, stdin?, timeout_ms? } → the full outcome as data (stdout, stderr, exit_code, timed_out, truncation flags).
  • github::api — { path, method?, fields?, body?, jq?, paginate?, timeout_ms? } → parsed JSON.

Actionable PR notifications (agent_actionable)

The default webhooks.notifications.profile in config.yaml delivers only what needs an agent action, as one kind: "digest" payload per watch:

  • ci.failed items: failure, timed_out, startup_failure, action_required on the current head. A failed workflow is dropped when its failed job is already reported. Failures of a superseded head are dropped at delivery.
  • New comments and reviews (created/submitted, approved, changes requested, unresolved threads), excluding edits, deletions, the agent's own login (ignore_self, discovered via GET /user) and known bot noise.
  • merged / closed lifecycle, delivered immediately with anything pending.

Never delivered: CI success or progress, cancelled/skipped/neutral runs, pushes, labels, assignments. The agent checks current CI with github::pr::checks when it acts. Every item carries event_id; fetch the full event with github::pr::event-detail.

Timing: a digest is sent after quiet_ms (15s) without new items, and never later than max_wait_ms (2min) after its first item. max_items (30) bounds the payload; extra items are counted in omitted_items.

Watch lifetime follows its listeners

A watch is kept alive by the github::pr::event bindings that listen to it (same watch_id, or a repo/number filter that matches it).

  • When the last listening binding goes away (its chat was deleted, or it unregistered), the watch is marked orphaned. If no binding listens again within webhooks.orphan_grace_minutes (default 60), maintenance stops it, releases its quick-tunnel lease and deletes the repository hook once no live watch remains there; the tunnel stops with its last lease. One-shot wakes are unregistered right after they fire, so re-arm before the grace period ends.
  • Bindings removed while the worker was offline are reconciled against the engine at most every five minutes.
  • Calling github::pr::watch again with the same watch_id and spec resumes a stopped watch; completed (merged/closed) and expired watches stay terminal.
  • expires_at must be within webhooks.max_watch_days (1..=30, default 30): a watch holds a quick-tunnel lease, and leases last at most 30 days.

Search the registry

Find workers, kits and executables, or jump to a page.