From issue-workflow
End-to-end workflow: preflight → plan → worktree → implement → verify → review → PR → CI → merge.
How this command is triggered — by the user, by Claude, or both
Slash command
/issue-workflow:issue-workflowThe summary Claude sees in its command listing — used to decide when to auto-load this command
# Issue Workflow End-to-end workflow: preflight → plan → worktree → implement → verify → review → PR → CI → merge. Runs in an isolated git worktree by default. Use `--no-worktree` to run in the current directory. ## Arguments $ARGUMENTS: GitHub issue URL or task description `[--no-worktree]` **Flags:** - `--no-worktree` — Run in the current directory instead of creating a git worktree (default: worktree mode) ## Phase 0: Preflight Check ### 0a. Parse Flags ### 0b. Environment Checks 1. Check project has verification capability: - Run `test -f .claude/commands/verify.md` to che...
End-to-end workflow: preflight → plan → worktree → implement → verify → review → PR → CI → merge.
Runs in an isolated git worktree by default. Use --no-worktree to run in the current directory.
$ARGUMENTS: GitHub issue URL or task description [--no-worktree]
Flags:
--no-worktree — Run in the current directory instead of creating a git worktree (default: worktree mode)# Default: worktree mode
USE_WORKTREE=true
# Parse --no-worktree flag from arguments
if echo "$ARGUMENTS" | grep -q -- '--no-worktree'; then
USE_WORKTREE=false
fi
test -f .claude/commands/verify.md to check for verify commandMakefile or package.json exists in project root.claude/commands/verify.md or add a Makefile/package.json with test/lint targets."gh CLI is authenticated: gh auth status
gh auth logingit status --porcelain
git branch --show-current
main → WARN user: "Currently on branch <name>, not main. Worktree branches should be created from main."git checkout main first, or proceed from current branchIf $ARGUMENTS is a GitHub issue URL, fetch it: gh issue view <number> --json title,body,labels
Use the Plan agent (subagent_type: "Plan") to:
The planner prompt MUST include this verification mandate verbatim:
Before finalizing any change, you MUST verify three things by reading
actual code (not guessing from filenames or summaries):
1. CONTRACTS — for every symbol / file / endpoint / column you plan to
modify, find ALL existing consumers and confirm your change does not
break their assumptions. Examples: a model also used as an LLM /
serializer schema; a component's props relied on by parents; a DB
column read elsewhere; an env var, config key, event payload, or
public type re-exported by something else.
2. DEPENDENCIES — for every helper / util / pattern / verb you plan to
introduce, grep the codebase first to see if it already exists under
a different name, or if there is an established way to do it. Do
not assume a helper exists; do not invent one that already does.
3. CONVENTIONS — cross-check against any CLAUDE.md, AGENTS.md, and
.claude/rules/*.md in the repo. If your plan violates a rule,
either change the plan or explicitly flag the exception with a
reason.
At the top of the plan, output two sections:
"Files fully read:" — list every file you opened end-to-end
"Greps performed:" — list every search query you ran
If you did not read a file, do not plan changes that depend on its
internals. Surface-level reasoning from filenames or directory
listings is not sufficient.
Sanity check before forwarding to codex — Before invoking codex-plan-reviewer, the main agent MUST do a quick self-review:
MANDATORY — codex plan review (DO NOT SKIP):
You MUST use the Agent tool with subagent_type: "codex-plan-reviewer" to review the plan before presenting it to the user. Pass the complete plan text as the agent prompt. Wait for the agent to return its review. If the review surfaces issues, incorporate feedback and refine the plan, then re-run the reviewer until it passes.
Gate: Do NOT proceed to step 5 until the codex-plan-reviewer agent has been invoked and returned results.
Present plan AND codex review results to user, WAIT for confirmation
If USE_WORKTREE=true:
# Derive branch name from the approved plan (e.g., feat/issue-42-add-export)
BRANCH_NAME="<type>/issue-<number>-<short-description>"
# MUST create worktree from main branch (not current HEAD)
# Use .claude/worktrees/ to match Claude Code's built-in worktree behavior
WORKTREE_DIR=".claude/worktrees/${BRANCH_NAME##*/}"
git worktree add "$WORKTREE_DIR" -b "$BRANCH_NAME" main
# Switch to the worktree — ALL subsequent work happens here
cd "$WORKTREE_DIR"
echo "Working in worktree: $(pwd) (branch: $BRANCH_NAME)"
CRITICAL: Worktree MUST be created and entered BEFORE Phase 2 begins. No code changes should happen in the main working directory. The branch is always based on main to ensure a clean starting point.
Prerequisite: If USE_WORKTREE=true, Phase 1b MUST be completed first. Verify you are in the worktree directory before writing any code.
USE_WORKTREE=true): Branch already created in Phase 1b. Confirm CWD is the worktree path before proceeding.--no-worktree): Create a feature branch from main: git checkout main && git checkout -b <type>/<short-description>Run verification inline:
.claude/commands/verify.md exists → read its contents and execute the instructions defined thereMakefile exists → make lint && make build && make testpackage.json exists → npm run lint && npm test (or equivalent scripts)pyproject.toml / setup.py exists → python -m pytestExtensible review pipeline. Each reviewer runs independently, main agent triages all results.
| Reviewer | Tool | Focus | Status |
|---|---|---|---|
| codex | Codex CLI | Bugs, logic, code quality | Active |
| gemini | Gemini CLI | Code quality, alternative perspective | Planned |
| security | security-reviewer agent | OWASP, secrets, permissions | Planned |
| architect | architect agent | Design patterns, coupling | Planned |
Currently only codex is active. Future reviewers plug in by adding to this table.
For each active reviewer, invoke in parallel where possible:
Codex Review:
codex exec "You are a code reviewer. DO NOT modify any files.
1. Read CLAUDE.md for project conventions
2. Run: git diff --stat
3. Run: git diff
4. For each changed file, read full context
5. Review for: bugs, security issues, logic errors, code quality
6. Output JSON: {\"status\": \"PASS|FAIL\", \"issues\": [{\"file\": \"...\", \"line\": N, \"severity\": \"high|medium|low\", \"description\": \"...\"}], \"summary\": \"...\"}"
Future reviewers follow same JSON output format:
{"reviewer": "<name>", "status": "PASS|FAIL", "issues": [...], "summary": "..."}
Merge all reviewer outputs. For each issue:
Report triage summary:
REVIEW PIPELINE TRIAGE
─────────────────────────
Codex: X issues (Y fixed, Z dismissed)
[Gemini]: (not active)
[Security]: (not active)
─────────────────────────
Total: X fixed, Z dismissed
If any fixes were made:
Show user:
git add -A)gh pr create --title "<type>: <description>" --body "$(cat <<'EOF'
## Summary
<bullets summarizing changes>
## Verification
- [x] Verification checks passed
- [x] Review pipeline: all active reviewers PASS or triaged
## Issue
Closes #<issue-number>
EOF
)"
# Wait for checks to complete
gh pr checks <pr-number> --watch
If any check FAILS:
# Find the failed run
gh run list --branch <branch> --status failure --json databaseId,name --limit 5
# Inspect failure logs
gh run view <run-id> --log-failed | tail -100
Fix the issue → push → re-wait for CI. Repeat until CI is green.
Fetch review threads with resolution state using GraphQL.
First, resolve the actual owner / repo / PR number (do not leave OWNER / REPO / NUMBER as literal placeholders):
OWNER=$(gh repo view --json owner -q .owner.login)
REPO=$(gh repo view --json name -q .name)
NUMBER=$(gh pr view --json number -q .number)
Then run the query:
gh api graphql -f query='
query($owner:String!, $repo:String!, $number:Int!) {
repository(owner:$owner, name:$repo) {
pullRequest(number:$number) {
reviewThreads(first:100) {
nodes {
isResolved
isOutdated
comments(first:10) {
nodes { body author { login } path line }
}
}
}
}
}
}
' -f owner="$OWNER" -f repo="$REPO" -F number="$NUMBER"
For each unresolved, non-outdated thread:
gh api repos/{owner}/{repo}/pulls/comments/{comment_id}/replies -f body="..."
After fixes → re-run verification (Phase 3 inline steps) → git push
Loop until no unresolved threads remain.
Pre-check (MUST pass before merging):
# Fetch merge readiness signals
PR_STATE=$(gh pr view <number> --json mergeable,reviewDecision,statusCheckRollup)
# Required gates:
# - mergeable == "MERGEABLE"
# - reviewDecision == "APPROVED" (or null if reviews not required by branch protection)
# - every entry in statusCheckRollup has conclusion == "SUCCESS" (or status == "COMPLETED" with SUCCESS)
# If ANY check is still PENDING/IN_PROGRESS → wait, do NOT merge
# If ANY check FAILED → STOP and surface the failure to the user; do NOT fall back to a manual merge that bypasses CI
If all gates green:
# Detect if we're in a worktree
if git rev-parse --git-dir | grep -q '\.git/worktrees'; then
# Worktree: cd to main repo root to avoid "fatal: 'main' is already used by worktree"
cd "$(git rev-parse --path-format=absolute --git-common-dir)/.." && gh pr merge <number> --squash --delete-branch
else
# Non-worktree: merge directly. Use --auto only if the repo has auto-merge enabled.
# DO NOT chain `|| gh pr merge --squash` — that silently bypasses CI when --auto is unavailable.
if gh pr merge <number> --auto --delete-branch 2>/dev/null; then
echo "Auto-merge queued; will land when CI passes."
else
# Auto-merge unavailable. Re-confirm CI is green RIGHT NOW, then squash.
gh pr checks <number> # show current state
echo "Auto-merge not available. Confirm CI is green above, then run:"
echo " gh pr merge <number> --squash --delete-branch"
# Wait for explicit user confirmation before running the squash command.
fi
fi
if [ "$USE_WORKTREE" = "true" ]; then
# Worktree mode: suggest cleanup (don't auto-remove)
WORKTREE_PATH=$(pwd)
MAIN_WORKTREE=$(git worktree list | head -n1 | awk '{print $1}')
echo "PR merged successfully!"
echo "Main worktree: $MAIN_WORKTREE"
echo "To clean up this worktree, run:"
echo " cd $MAIN_WORKTREE && git worktree remove $WORKTREE_PATH"
else
# Non-worktree mode: switch back to main and clean up
BASE_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
FEATURE_BRANCH=$(git branch --show-current)
git checkout "$BASE_BRANCH"
git pull
git branch -d "$FEATURE_BRANCH" 2>/dev/null || true
fi
| Gate | Requirement |
|---|---|
| Phase 0 | Preflight must pass (flags parsed, env checks OK) |
| Phase 1 → 1b | User confirmation of plan + codex review passed |
| Phase 1b → 2 | Worktree created (if worktree mode) |
| Phase 3 | All verification checks must pass |
| Phase 4 | All active reviewers PASS or issues triaged |
| Phase 4 → 5 | User acknowledgment of triage results |
| Phase 5 → 6a | Automatic (PR created) |
| Phase 6a → 6b | CI must pass |
| Phase 6b → 6c | No unresolved review threads |
| Phase 6c | User confirmation required before merge |
| Phase 6d | Cleanup suggested (worktree) or auto-cleaned (non-worktree) |
npx claudepluginhub pierrelzw/issue-workflow --plugin issue-workflow