AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Cycle Review

skill-axisrow-claude-code-cycle-review-skill-cycle-review · by axisrow

Automated PR review cycle — request review, fix issues, repeat until approved, then merge. Cloud mode pings GitHub review bots; local mode reviews with an in-process Claude subagent, plus Codex locally when @codex is configured.

No reviews yet
0 installs
18 views
0.0% view→install

Install

$ agentstack add skill-axisrow-claude-code-cycle-review-skill-cycle-review

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-axisrow-claude-code-cycle-review-skill-cycle-review)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Cycle Review? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Cycle Review

Automated PR review cycle until full approval, with multi-PR merge strategy planning.

PR numbers come from $ARGUMENTS. Parse them as a free-form string — accept any format (space-separated, comma-separated, prose like "twenty, twenty-one and twenty-five"). If $ARGUMENTS is empty — auto-detect the current PR from the branch via gh pr view --json number -q .number. Other authors' PRs are never included automatically; the user must pass their numbers explicitly.

If $ARGUMENTS contains the standalone command token onboard, or the legacy flags --onboard / --reconfigure, strip that token out before parsing PR numbers and force the onboarding in step 0 to run again, overwriting the saved config. Treat onboard as the preferred user-facing form, e.g. /cycle-review onboard.

Review mode: cloud vs local

The skill has two review modes. Pick the active one in step 0.1 before anything else, then branch on it at step 2/3/4.

| Mode | Who reviews | Network to bots? | Use when | |---|---|---|---| | cloud (default, original behavior) | GitHub bots @claude / @codex pinged in a PR comment | yes — waits for the bots to post on GitHub | you want the same reviewers a human teammate would see on the PR, and a fully autonomous loop through merge | | local | an in-process Claude subagent (Agent tool) reading gh pr diff directly — like the inline review the main loop does itself — plus Codex (local companion) when @codex is configured | no bot ping, no GitHub wait; only posts the findings as a PR comment afterwards | you want a fast review without waiting on GitHub bots, or the bots aren't installed. The Claude subagent always runs; if @codex is in your reviewers list, Codex also reviews locally via its companion script (run in parallel, findings merged). No GitHub bot ping either way |

Mode selection — flag overrides config, config is the default:

  • A standalone leading token local or cloud in $ARGUMENTS (also accept --local / --cloud) forces that mode for this run and is stripped out before parsing PR numbers — exactly like the onboard token.
  • Otherwise the mode comes from mode in the saved config (step 0).
  • If neither a flag nor a saved mode is present, default to cloud (backward-compatible).

Local mode is review-only on merge: it runs the full triage→reply→fix→commit→push loop, but it never merges on its own. It stops after pushing and hands back to the user; merge happens only when the user explicitly asks. Cloud mode keeps the original autonomous merge (step 8).

Cycle

Run step 0 (onboarding) and step 0.1 (resolve mode) once at the start of every invocation. Then, for each PR, run step 1.5 (verify the PR implements its linked issue 100% — fix any gap BEFORE asking for review), repeat steps 2–6 until the PR has no FIX verdicts — but no more than 3 cycles; if a 3rd cycle still has FIXs, stop and hand back to the user to narrow scope. Once a round is clean, run step 6.5 (final cleanup pass — apply the minor findings deferred across all earlier rounds). Then: cloud mode runs step 7 (CI) and step 8 (merge); local mode stops and reports — it does not auto-merge.

0. Onboarding — reviewers + default mode (run once per invocation)

The skill needs two things from the user, stored once: which review bots they have installed (@claude, @codex, or both — drives cloud mode), and the default review mode (cloud or local). The reviewers list drives who gets pinged in step 2 and whose comments we wait for in step 3 (cloud only). The mode is the default when no local/cloud flag is passed (step 0.1).

Config location (global, per user): ~/.claude/cycle-review/config.json. It is intentionally global — not committed into the reviewed repo, set once, reused across all projects.

Schema:

{
  "reviewers": ["@claude", "@codex"],
  "mode": "cloud",
  "version": 2
}

reviewers is a non-empty array of mention handles (valid: @claude, @codex; order irrelevant) — used by cloud mode. mode is "cloud" or "local" — the default review mode. version is 2 since the mode field was added; a version: 1 config (no mode) is still valid and is treated as mode: "cloud" until re-onboarded.

Flow:

  1. Decide whether onboarding is needed. It is needed when onboard, --onboard, or --reconfigure was passed OR the config is missing/invalid. Detect a valid config with (note: mode is NOT required for validity — a v1 config without it stays valid and means cloud):

``bash CONFIG_FILE="$HOME/.claude/cycle-review/config.json" jq -e '.reviewers | type == "array" and length > 0' "$CONFIG_FILE" >/dev/null 2>&1 \ && echo CONFIGURED || echo NEEDS_ONBOARDING ` CONFIGURED → read the reviewers and mode (step 4's read commands) and skip to step 0.1. NEEDS_ONBOARDING (missing file, malformed JSON, or empty reviewers`) → run onboarding.

  1. Run onboarding. Ask the user TWO AskUserQuestion questions (one tool call, two questions):
  • Reviewers (multi-select): @claude, @codex — which review bots they have (one or both). Used by cloud mode.
  • Default mode (single-select): cloud (ping GitHub review bots, autonomous through merge) vs local (in-process Claude subagent reviews the diff, no bot ping, never auto-merges). This is just the default — a local/cloud flag always overrides it per run.

Do not free-text-parse either answer; use the structured picker.

  1. Persist the choice. Build the file with jq -n so the JSON is always well-formed (never hand-concatenate strings). Example for "both reviewers, cloud default":

``bash CONFIG_DIR="$HOME/.claude/cycle-review" CONFIG_FILE="$CONFIG_DIR/config.json" mkdir -p "$CONFIG_DIR" jq -n '{reviewers: ["@claude", "@codex"], mode: "cloud", version: 2}' > "$CONFIG_FILE" ` For a single reviewer, pass a one-element array (["@claude"] or ["@codex"]); for a local default, set mode: "local"`. Confirm to the user what was saved and where.

  1. Read the active config (always, whether freshly onboarded or already configured):

``bash jq -r '.reviewers[]' "$HOME/.claude/cycle-review/config.json" # reviewers, one per line (cloud mode) jq -r '.mode // "cloud"' "$HOME/.claude/cycle-review/config.json" # default mode; "cloud" when absent (v1 config) ``

0.1. Resolve the active review mode (run once per invocation, right after step 0)

Decide cloud vs local for this run, then remember it — every later branch (steps 2, 3, 4, 6.5, 7, 8) reads it.

  1. Flag wins. If $ARGUMENTS had a standalone leading local / cloud (or --local / --cloud) token, use that mode and remember it was stripped from PR-number parsing.
  2. Else config. Use the mode read in step 0.4 ("cloud" when the field is absent).
  3. Announce it so the run is self-documenting, e.g. Review mode: local (in-process Claude subagent; will not auto-merge). or Review mode: cloud (pinging @claude @codex).

In local mode no bots are pinged, but the reviewers list still matters: the Claude subagent always runs, and if the list contains @codex, Codex also reviews locally via its companion script (step 2b). @claude-only stays Claude-subagent-only. (The reviewers list read in step 0.4 is consulted by local step 2b too, not only cloud — no extra read is needed.)

Where each reviewer posts (useful for triage in step 4 — the step-3 waiter ignores this and just waits a fixed window):

| Handle | Mention (step 2) | Bot login | Where its review lands | |---|---|---|---| | @claude | @claude | claude[bot] | edits a single issue comment in place; finishes with the marker Claude finished | | @codex | @codex | chatgpt-codex-connector[bot] | a PR review object plus inline review comments (not issue comments) |

Timing. Claude usually finishes in ~2 min, Codex in ~5 min. The step-3 waiter uses one fixed window (WAIT, default 5 min) that covers both — no per-reviewer clocks.

The @codex bot login is a best-effort default and can vary by integration. On the first real Codex run, verify the actual login via gh api repos/{owner}/{repo}/issues/{PR}/comments --jq '[.[].user.login] | unique' (and pulls/{PR}/reviews), and if it differs, tell the user and use the observed value for that session.

1. Multi-PR strategy (run once per invocation)

Skip this step only when there is exactly one PR to handle (single-PR run, no other open PRs by the same author).

  1. Build the PR set:
  • If $ARGUMENTS lists explicit PR numbers — use exactly those (this is the only way other authors' PRs enter the queue).
  • Otherwise — current PR plus the author's other open PRs:

`` gh pr list --author "@me" --state open --json number,title,createdAt,headRefName,baseRefName --jq 'sort_by(.createdAt)' ``

  1. If the set has exactly one PR — proceed to step 2.
  1. Build the file-overlap map. For each PR fetch its changed files:

`` gh pr diff --name-only `` Treat PR-A and PR-B as overlapping if any of these holds:

  • their changed-file sets intersect;
  • baseRefName(A) == headRefName(B) or vice versa (PR stack);
  • baseRefName(A) is not the repo's default branch AND differs from baseRefName(B) (potential indirect stack).

When in doubt — mark them as overlapping. False positives are safer than missed conflicts.

  1. Decide the merge strategy autonomously, then announce it to the user before proceeding (do not block waiting for an answer):
  • No overlap anywhere → all independent. Process the queue from the earliest createdAt to the latest.
  • Some overlap → sequential by createdAt (earliest first). Overlapping PRs must merge in order; non-overlapping ones can interleave but the skill still walks the queue linearly within one session.

Print a short summary like: `` Found 3 open PRs: #20, #21, #25. Overlap: #20 ↔ #21 (shared src/foo.py); #25 independent. Plan: #20 → #21 → #25. ``

The user can interrupt and override; otherwise the plan stands.

  1. After each successful merge in step 8, return here: pop the merged PR from the queue, recompute file overlap for the rest (the codebase has changed), and continue with the next PR.

1.5. Verify the PR implements its linked issue 100% (before any review)

Run this once per PR, before step 2 — do NOT ask the bots to review a half-finished PR. Review bots check whether the code is correct, not whether it is complete relative to the issue's design; a PR can be approved by both bots and still ship only half of what the issue asked for. Catch that here, up front, not after a wasted review round (or after merging an incomplete issue).

  1. Find the linked issue. A repo convention may require a closing keyword (Closes #N) in every PR. Read the PR body and the structured closing references:

``bash gh pr view --json body,closingIssuesReferences \ --jq '{body, issues: [.closingIssuesReferences[].number]}' `` If there is no linked issue (e.g. a pure refactor/chore with none) — skip this step and go to step 2.

  1. Read the issue's design in full:

``bash gh issue view --json title,body --jq '{title, body}' `` Extract every concrete deliverable the design specifies — each output format, flag, marker, edge case, file the issue names. Treat the design section as a checklist, not a vibe.

  1. Confirm each deliverable is actually implemented. Read the changed code and grep the repo to verify every item on that checklist is present in this PR's diff (not merely planned, not "mostly"). A design that lists two markers/flags/outputs and a PR that ships one is a gap, even if the shipped half is flawless.
  1. If a gap exists — close it now (before review):
  • Implement the missing pieces test-first (write the failing test, then the code), following the repo's conventions.
  • Run the repo's linter and full test suite green.
  • Commit (conventional-commits style) and push to the PR branch.
  • Only then proceed to step 2. The bots now review a complete PR in one pass.

If the gap is large or the issue's design is ambiguous, surface it to the user (with the specific missing deliverables) and ask how to proceed rather than guessing.

  1. If the PR fully implements the issue — proceed to step 2.

2. Request review

Branch on the active mode (step 0.1).

2a. Cloud mode — ping the bots

Ping all configured reviewers in a single comment — concatenate every configured mention, space-separated, at the start of the body. The mention string depends on the active reviewers list from step 0:

| Configured reviewers | Mention string ` | |---|---| | both @claude and @codex | @claude @codex | | only @claude | @claude | | only @codex | @codex` |

Then post one comment:

gh pr comment  --body " review. Focus on critical issues: bugs, security vulnerabilities, logical errors, data loss risks, performance problems. Do NOT nitpick style, naming conventions, minor formatting, or subjective preferences — only flag issues that could break functionality or cause real harm in production."

For example, with both configured the body starts with @claude @codex review.; with only Codex it starts with @codex review.. Run via Bash with dangerouslyDisableSandbox: true. Then go to step 3a (wait).

2b. Local mode — Claude subagent (plus Codex when configured)

No bot is pinged and no GitHub wait happens. The Claude subagent always runs; if @codex is in the reviewers list (step 0.4), Codex also reviews locally, in parallel, and its findings are merged with the subagent's before triage. (@codex-only still runs the Claude subagent too — local mode always includes Claude; the reviewers list only adds Codex.)

Launch both in parallel, then wait for both:

  1. Start Codex first (background) when @codex is configured, so it runs while the Claude subagent works:
  • Discover the companion path at runtime — never hardcode the version. Pick the newest installed copy:

``bash COMPANION=$(ls -1 "$HOME"/.claude/plugins/cache/openai-codex/codex/*/scripts/codex-companion.mjs 2>/dev/null | sort -V | tail -1) ` If $COMPANION` is empty, Codex is not installed — treat as the fail-closed case in step 4.

  • Get the PR's base ref (this is what makes --base equal the PR diff, since local mode is checked out on the PR branch):

``bash BASE=$(gh pr view --json baseRefName -q .baseRefName) # Bash, dangerouslyDisableSandbox: true ``

  • Invoke the companion in the background, JSON output, against the PR base:

``bash node "$COMPANION" adversarial-review --wait --json --base "$BASE" \ "Critical-only review of PR #: bugs, security vulnerabilities, logical errors, data-loss risks, performance problems. Do NOT nitpick style, naming, formatting, or subjective preferences." ` Run via **Bash with runinbackground: true** *and* dangerouslyDisableSandbox: true (Codex needs network). --wait` keeps it blocking inside the backgrounded bash, so the background handle completes only when Codex is done. Record the returned background shell id.

  1. Spawn the Claude review subagent with the Agent tool (the same engine cloud mode uses for triage, pointed at the diff). Because Codex is already running in the background, the two reviews overlap. The subagent must:
  • Read the PR metadata and the full diff with gh pr view --json title,body,... and gh pr diff (run via Bash with dangerouslyDisableSandbox: true; the diff is read-only GitHub access).
  • Read the current contents of every file the diff touches (not just the patch hunks) so claims are grounded in real code, and grep the repo to confirm any cross-file assertion.
  • Review for the

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.