/loop-gh-pr
Compose a /loop that watches all open GitHub PRs for activity (new PRs, new commits, new comments) and auto-prepares a READ-ONLY /lets:review draft for each code change - never posting. Use when the user says "watch PRs", "monitor github PRs", "loop-gh-pr", "стеж за PR", "поллі
$ npx -y skills add restarter/lets-workflow --skill loop-gh-pr --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/loop-gh-pr
Context preview
The summary Claude sees to decide when to auto-load this skill.
Compose a /loop that watches all open GitHub PRs for activity (new PRs, new commits, new comments) and auto-prepares a READ-ONLY /lets:review draft for each code change - never posting. Use when the user says "watch PRs", "monitor github PRs", "loop-gh-pr", "стеж за PR", "поллі
SKILL.md
loop-gh-pr.SKILL.mdname: loop-gh-pr
description: Compose a /loop that watches all open GitHub PRs for activity (new PRs, new commits, new comments) and auto-prepares a READ-ONLY /lets:review draft for each code change - never posting. Use when the user says "watch PRs", "monitor github PRs", "loop-gh-pr", "стеж за PR", "поллі гітхаб PR", or wants a hands-near PR-review watcher. Composes a paste-ready /loop block - does NOT invoke /loop (UI command). Local test skill.
loop-gh-pr
Compose a `/loop` that periodically lists open GitHub PRs via `gh`, detects what is new since the last tick (new PR / new commits / new comments), auto-runs a READ-ONLY `/lets:review <N> --json` draft for each code change, fires a `lets cmux notify`, and reschedules - WITHOUT ever posting to a PR.
The skill **never invokes `/loop` itself** - Claude Code's `/loop` is a UI command. It composes the prompt and presents it for paste; once active, the autonomous run uses `ScheduleWakeup` per tick.
**Autonomy boundary (the whole point):** `/lets:review --json` is read-only - it computes findings and posts NOTHING. So the loop safely auto-runs review. Posting (inline / general / approve / merge) is ALWAYS the human's call, out-of-band. The loop stops at a ready draft in `.lets/reviews/` + a notification and keeps watching. Never saw -> reviewed -> posted.
> **IMPORTANT:** If the spec below invokes any deferred tool (e.g. `AskUserQuestion`), you MUST load and call it as specified.
Step 1: Pre-flight (always run)
Confirm github flow + `gh` auth + that listing PRs works, before composing a long-lived loop.
LETS_PROJECT_ROOT=$(git rev-parse --show-toplevel)
# 1. github flow only (v1). LETS_PR_FLOW is substituted by the orchestrator from LETS Config.
# If LETS_PR_FLOW != github -> surface "loop-gh-pr is github-only in v1 (LETS_PR_FLOW={value});
# bitbucket waits on lets-6pxvm" and exit.
# 2. gh present + authed
gh auth status 2>&1 | head -5 || { echo "gh not authed - run: gh auth login"; exit 1; }
# 3. smoke: list open PRs (the watch set). If `comments` is rejected as a list field,
# drop it here and have the loop fall back to per-PR `gh pr view <N> --json comments`.
gh pr list --state open --json number,title,headRefOid,isDraft,url,updatedAt,comments --limit 30 2>&1 | head -40Surface a short summary of the current open non-draft PRs (number, title, head SHA short, comment count) so the user sees exactly what the loop will watch. If `gh auth status` fails -> surface and exit. If `gh pr list` errors (e.g. not a GitHub remote) -> surface verbatim and exit. Never compose a loop the autonomous run cannot execute.
Step 2: State file
`.lets/pr-watch-state.json` - one file, keyed by PR number. `.lets/` is gitignored and symlinked across worktrees (per-repo state - fine; we key by PR number).
Shape:
{
"captured_at": "<iso8601>",
"prs": {
"42": {
"title": "...",
"head_sha": "<headRefOid>",
"comment_count": 3,
"updated_at": "<updatedAt from gh>",
"last_reviewed_sha": "<headRefOid the latest draft covers, or null if not yet/failed>",
"last_seen": "<iso8601>"
}
}
}- `head_sha` vs stored -> new-commits signal.
- `comment_count` vs stored -> new-comments signal; `updated_at` is a cheap secondary signal.
- `last_reviewed_sha == head_sha` -> already reviewed at this SHA; skip re-review (dedup).
- `last_reviewed_sha == null` (review never ran, or review FAILED) -> a failed review keeps it `null` so the next tick re-attempts; never advance it on failure.
- A PR absent from the current `gh pr list` but present in state -> merged/closed; drop it and report once.
- The baseline is captured ONCE on first tick; never silently re-baselined. On tick-1, PRs beyond `INIT_REVIEW_CAP` are baselined with `last_reviewed_sha = head_sha` (seen, not reviewed) and surfaced for manual review.
Step 3: Compose /loop
Template (dynamic mode - the model self-paces via ScheduleWakeup). The body is always English. Present this for paste:
/loop Watch all open GitHub PRs for activity and prepare READ-ONLY review drafts. NEVER post to any PR.
State file: .lets/pr-watch-state.json (keyed by PR number). Initial-review cap: 5.
Each tick:
1. Resolve root: LETS_PROJECT_ROOT=$(git rev-parse --show-toplevel)
2. Fetch the watch set (READ-ONLY):
gh pr list --state open --json number,title,headRefOid,isDraft,url,updatedAt,comments --limit 30
If `comments` is rejected as a list field, re-run without it and read each count via
`gh pr view <number> --json comments -q '.comments | length'`.
Drop isDraft=true entries.
Review primitive (used below): run `/lets:review <number> --json`. It saves
.lets/reviews/<date>-PR-<number>.json + .md and posts NOTHING, and must run with NO interactive
prompt. If it returns no JSON artifact (failed/empty), treat the review as FAILED: do NOT advance
last_reviewed_sha for that PR (leave it null), surface "review failed for #<number> - will retry",
and let the next tick re-attempt. Never mark a PR reviewed when it was not.
FIRST tick (.lets/pr-watch-state.json does not exist):
- Create the file. Take the open non-draft PRs in listed order.
- For the FIRST 5: run the review primitive, read verdict + findings_count from the saved JSON,
set last_reviewed_sha=head_sha only on success (null on failure).
- For any open non-draft PR BEYOND the first 5: baseline as already-seen (last_reviewed_sha=head_sha)
WITHOUT reviewing, and add to a "baselined without initial review (large open set): #a #b ..." line.
- Write baseline per PR: {title, head_sha=headRefOid, comment_count=(comments|length),
updated_at=updatedAt, last_reviewed_sha=(per above), last_seen=now}.
- Surface a combined summary (one line per reviewed PR: #N "title" -> verdict, K findings ->
.lets/reviews/<file>), plus the baselined-without-review line if any.
- Build the notify body safely, then fire one notification:
BODY=$(printf '%s' "<combined summary>")
letRead more
name: loop-gh-pr description: Compose a /loop that watches all open GitHub PRs for activity (new PRs, new commits, new comments) and auto-prepares a READ-ONLY /lets:review draft for each code change - never posting. Use when the user says "watch PRs", "monitor github PRs", "loop-gh-pr", "стеж за PR", "поллі гітхаб PR", or wants a hands-near PR-review watcher. Composes a paste-ready /loop block - does NOT invoke /loop (UI command). Local test skill.
loop-gh-pr
Compose a `/loop` that periodically lists open GitHub PRs via `gh`, detects what is new since the last tick (new PR / new commits / new comments), auto-runs a READ-ONLY `/lets:review <N> --json` draft for each code change, fires a `lets cmux notify`, and reschedules - WITHOUT ever posting to a PR.
The skill **never invokes `/loop` itself** - Claude Code's `/loop` is a UI command. It composes the prompt and presents it for paste; once active, the autonomous run uses `ScheduleWakeup` per tick.
**Autonomy boundary (the whole point):** `/lets:review --json` is read-only - it computes findings and posts NOTHING. So the loop safely auto-runs review. Posting (inline / general / approve / merge) is ALWAYS the human's call, out-of-band. The loop stops at a ready draft in `.lets/reviews/` + a notification and keeps watching. Never saw -> reviewed -> posted.
> **IMPORTANT:** If the spec below invokes any deferred tool (e.g. `AskUserQuestion`), you MUST load and call it as specified.
Step 1: Pre-flight (always run)
Confirm github flow + `gh` auth + that listing PRs works, before composing a long-lived loop.
LETS_PROJECT_ROOT=$(git rev-parse --show-toplevel)
# 1. github flow only (v1). LETS_PR_FLOW is substituted by the orchestrator from LETS Config.
# If LETS_PR_FLOW != github -> surface "loop-gh-pr is github-only in v1 (LETS_PR_FLOW={value});
# bitbucket waits on lets-6pxvm" and exit.
# 2. gh present + authed
gh auth status 2>&1 | head -5 || { echo "gh not authed - run: gh auth login"; exit 1; }
# 3. smoke: list open PRs (the watch set). If `comments` is rejected as a list field,
# drop it here and have the loop fall back to per-PR `gh pr view <N> --json comments`.
gh pr list --state open --json number,title,headRefOid,isDraft,url,updatedAt,comments --limit 30 2>&1 | head -40Surface a short summary of the current open non-draft PRs (number, title, head SHA short, comment count) so the user sees exactly what the loop will watch. If `gh auth status` fails -> surface and exit. If `gh pr list` errors (e.g. not a GitHub remote) -> surface verbatim and exit. Never compose a loop the autonomous run cannot execute.
Step 2: State file
`.lets/pr-watch-state.json` - one file, keyed by PR number. `.lets/` is gitignored and symlinked across worktrees (per-repo state - fine; we key by PR number).
Shape:
{
"captured_at": "<iso8601>",
"prs": {
"42": {
"title": "...",
"head_sha": "<headRefOid>",
"comment_count": 3,
"updated_at": "<updatedAt from gh>",
"last_reviewed_sha": "<headRefOid the latest draft covers, or null if not yet/failed>",
"last_seen": "<iso8601>"
}
}
}- `head_sha` vs stored -> new-commits signal.
- `comment_count` vs stored -> new-comments signal; `updated_at` is a cheap secondary signal.
- `last_reviewed_sha == head_sha` -> already reviewed at this SHA; skip re-review (dedup).
- `last_reviewed_sha == null` (review never ran, or review FAILED) -> a failed review keeps it `null` so the next tick re-attempts; never advance it on failure.
- A PR absent from the current `gh pr list` but present in state -> merged/closed; drop it and report once.
- The baseline is captured ONCE on first tick; never silently re-baselined. On tick-1, PRs beyond `INIT_REVIEW_CAP` are baselined with `last_reviewed_sha = head_sha` (seen, not reviewed) and surfaced for manual review.
Step 3: Compose /loop
Template (dynamic mode - the model self-paces via ScheduleWakeup). The body is always English. Present this for paste:
/loop Watch all open GitHub PRs for activity and prepare READ-ONLY review drafts. NEVER post to any PR.
State file: .lets/pr-watch-state.json (keyed by PR number). Initial-review cap: 5.
Each tick:
1. Resolve root: LETS_PROJECT_ROOT=$(git rev-parse --show-toplevel)
2. Fetch the watch set (READ-ONLY):
gh pr list --state open --json number,title,headRefOid,isDraft,url,updatedAt,comments --limit 30
If `comments` is rejected as a list field, re-run without it and read each count via
`gh pr view <number> --json comments -q '.comments | length'`.
Drop isDraft=true entries.
Review primitive (used below): run `/lets:review <number> --json`. It saves
.lets/reviews/<date>-PR-<number>.json + .md and posts NOTHING, and must run with NO interactive
prompt. If it returns no JSON artifact (failed/empty), treat the review as FAILED: do NOT advance
last_reviewed_sha for that PR (leave it null), surface "review failed for #<number> - will retry",
and let the next tick re-attempt. Never mark a PR reviewed when it was not.
FIRST tick (.lets/pr-watch-state.json does not exist):
- Create the file. Take the open non-draft PRs in listed order.
- For the FIRST 5: run the review primitive, read verdict + findings_count from the saved JSON,
set last_reviewed_sha=head_sha only on success (null on failure).
- For any open non-draft PR BEYOND the first 5: baseline as already-seen (last_reviewed_sha=head_sha)
WITHOUT reviewing, and add to a "baselined without initial review (large open set): #a #b ..." line.
- Write baseline per PR: {title, head_sha=headRefOid, comment_count=(comments|length),
updated_at=updatedAt, last_reviewed_sha=(per above), last_seen=now}.
- Surface a combined summary (one line per reviewed PR: #N "title" -> verdict, K findings ->
.lets/reviews/<file>), plus the baselined-without-review line if any.
- Build the notify body safely, then fire one notification:
BODY=$(printf '%s' "<combined summary>")
letA development workflow plugin for Claude Code Stop babysitting your AI. Start shipping with it.
Repo: restarter/lets-workflow
Other skills on lets-workflow.
goal-test
Local sandbox for experimenting with Claude Code's /goal command (stop-hook condition + LLM-evaluator driving autonomous work toward a verifiable end state)…
loop-bb-pr
Compose a /loop that monitors a Bitbucket PR for activity (new comments, review state changes, merge, decline) via the bb-api wrapper. Use when the user says…
loop-test
Local sandbox for experimenting with Claude Code's /loop command (interval + dynamic/self-paced scheduling) applied to LETS workflows. Use when the user says…
actor-fetch-personalit…
Internal skill for commands. Fetch and validate personality from URL or file path for Actor agent. Do not trigger on user conversation - only when commands…
apply-fixes
Internal skill for commands. Apply a review's verified fixes to the working tree when nothing needs deciding - the --fix flag of /lets:check, /lets:review and…

