Skip to content
Back to skills

Mav Github Issue Workflow

ASecurity

Standard patterns for interacting with GitHub issues — reading, commenting, updating, state tracking, branching, and PR creation. Use as a dependency from workflow skills, not directly.

  • 11 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added June 1, 2026
testinggobashgitapi

Works with

  • claude code
  • api

Security analysis

A100/100

Scanned June 1, 2026

npx -y skills add thermiteau/maverick --skill mav-github-issue-workflow --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Mav Github Issue Workflow?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Mav Github Issue Workflow
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/thermiteau-mav-github-issue-workflow/badge)](https://www.skillsdirectory.com/skills/thermiteau-mav-github-issue-workflow)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: mav-github-issue-workflow
description: Standard patterns for interacting with GitHub issues — reading, commenting, updating, state tracking, branching, and PR creation. Use as a dependency from workflow skills, not directly.
---

**Depends on:** mav-git-workflow

# GitHub Issue Workflow Patterns

Reusable patterns for GitHub issue interactions. Workflow skills (e.g., do-issue-guided, do-issue-solo) reference this skill for consistent GitHub operations.

## Issue State File

Maintain a local state file at `.claude/issue-state.json` to track progress across sessions and subagents. This file MUST be gitignored.

### Structure

```json
{
  "issue": 42,
  "repo": "owner/repo",
  "branch": "feat/42-short-description",
  "phase": "understand|design|plan|branch|implement|complete",
  "comments": {
    "design": null,
    "plan": null,
    "completion": null
  }
}
```

### Initialise State

Create the state file at the start of work. Infer the repo from the current git remote.

```bash
REPO=$(gh repo view --json nameWithOwner -q '.nameWithOwner')
mkdir -p .claude
cat > .claude/issue-state.json << EOF
{
  "issue": $ISSUE_NUMBER,
  "repo": "$REPO",
  "branch": null,
  "phase": "understand",
  "comments": {
    "design": null,
    "plan": null,
    "completion": null
  }
}
EOF
```

### Read State

```bash
cat .claude/issue-state.json
```

### Update State Field

Use `jq` (or equivalent) to update individual fields:

```bash
# Update phase
jq '.phase = "design"' .claude/issue-state.json > .claude/issue-state.tmp && mv .claude/issue-state.tmp .claude/issue-state.json

# Update branch
jq '.branch = "feat/42-add-export"' .claude/issue-state.json > .claude/issue-state.tmp && mv .claude/issue-state.tmp .claude/issue-state.json
```

### Ensure Gitignore

Before creating the state file, ensure it is gitignored:

```bash
grep -q 'issue-state.json' .gitignore 2>/dev/null || echo '.claude/issue-state.json' >> .gitignore
```

## Reading an Issue

Always fetch structured JSON to get the full picture including comments.

```bash
gh issue view $ISSUE_NUMBER --json title,body,labels,assignees,milestone,comments,state
```

### Reading Specific Fields

```bash
# Just the body
gh issue view $ISSUE_NUMBER --json body -q '.body'

# Labels as comma-separated list
gh issue view $ISSUE_NUMBER --json labels -q '[.labels[].name] | join(", ")'

# Comment count
gh issue view $ISSUE_NUMBER --json comments -q '.comments | length'
```

## Posting Comments

Use one comment per artifact (design, plan, completion). Capture the comment ID so it can be updated later.

### Identity

Maverick-generated comments — design, plan, tasks, completion, PR-review verdicts, and updates to any of those — are posted **as the Maverick GitHub App** so they are visually distinct from the human user's edits. Use `uv run maverick gh-app gh -- <args>` for any write that produces a comment. Plain `gh` is fine for **read** operations (`gh issue view`, `gh api ... --jq '.body'`).

**Failure modes — do not silently switch identity mid-workflow:**

- *App not configured* — `uv run maverick gh-app gh ...` exits with code `4` and a `GitHub App not configured` message. For solo / ad-hoc single-machine use this is acceptable; fall back to plain `gh issue comment ...` (the comment will be authored by the human user). The fallback only applies to the entire session, not per-call: if the App is configured, every comment goes through it.
- *App configured but missing `issues:write` or `pull_requests:write`* — the underlying `gh` call fails with HTTP 403. This is a **setup error**, not a runtime fallback. Stop the workflow and tell the user to grant the permission via the GitHub App settings, then re-run. Do not retry as the human user.

### Post and Capture ID

```bash
COMMENT_URL=$(uv run maverick gh-app gh -- issue comment $ISSUE_NUMBER --body "$(cat <<'EOF'
## Section Title

Content here

---
*Posted by Claude Code*
EOF
)" 2>&1)
```

Extract the comment ID from the URL for later updates:

```bash
# gh issue comment prints the URL to stdout, extract the numeric ID
COMMENT_ID=$(echo "$COMMENT_URL" | grep -o '[0-9]*$')
```

Then save to state:

```bash
jq ".comments.design = $COMMENT_ID" .claude/issue-state.json > .claude/issue-state.tmp && mv .claude/issue-state.tmp .claude/issue-state.json
```

### Post Design Comment

```bash
COMMENT_URL=$(uv run maverick gh-app gh -- issue comment $ISSUE_NUMBER --body "$(cat <<'DESIGN_EOF'
## Solution Design

### Approach
<high-level description>

### Areas Affected
- <list of packages/files>

### Key Decisions
- <architectural choices and rationale>

### Risks / Open Questions
- <anything that might complicate implementation>

---
*Posted by Claude Code*
DESIGN_EOF
)" 2>&1)

COMMENT_ID=$(echo "$COMMENT_URL" | grep -o '[0-9]*$')
jq ".comments.design = $COMMENT_ID | .phase = \"design\"" .claude/issue-state.json > .claude/issue-state.tmp && mv .claude/issue-state.tmp .claude/issue-state.json
```

### Post Plan Comment

```bash
COMMENT_URL=$(uv run maverick gh-app gh -- issue comment $ISSUE_NUMBER --body "$(cat <<'PLAN_EOF'
## Implementation Plan

1. **Step name**
   - Files: `path/to/file.ts`
   - Change: <what the change does>
   - Verify: <test command or check>

2. **Step name**
   - Files: `path/to/file.ts`
   - Change: <what the change does>
   - Verify: <test command or check>

---
*Posted by Claude Code*
PLAN_EOF
)" 2>&1)

COMMENT_ID=$(echo "$COMMENT_URL" | grep -o '[0-9]*$')
jq ".comments.plan = $COMMENT_ID | .phase = \"plan\"" .claude/issue-state.json > .claude/issue-state.tmp && mv .claude/issue-state.tmp .claude/issue-state.json
```

### Post Completion Comment

```bash
BRANCH=$(jq -r '.branch' .claude/issue-state.json)

COMMENT_URL=$(uv run maverick gh-app gh -- issue comment $ISSUE_NUMBER --body "$(cat <<DONE_EOF
## Implementation Complete

**Branch:** \`$BRANCH\`

### Changes Made
- <summary of changes>

### Verification
- [ ] Linting passes
- [ ] Tests pass

---
*Posted by Claude Code*
DONE_EOF
)" 2>&1)

COMMENT_ID=$(echo "$COMMENT_URL" | grep -o '[0-9]*$')
jq ".comments.completion = $COMMENT_ID | .phase = \"complete\"" .claude/issue-state.json > .claude/issue-state.tmp && mv .claude/issue-state.tmp .claude/issue-state.json
```

## Updating Comments

When a design or plan is revised, update the existing comment instead of posting a new one. Read the comment ID from the state file.

```bash
REPO=$(jq -r '.repo' .claude/issue-state.json)
COMMENT_ID=$(jq -r '.comments.design' .claude/issue-state.json)

uv run maverick gh-app gh -- api "repos/$REPO/issues/comments/$COMMENT_ID" \
  -X PATCH \
  -f body="$(cat <<'EOF'
## Solution Design (Revised)

<updated content>

---
*Posted by Claude Code*
EOF
)"
```

The update goes through the same App identity as the original post, so the comment author stays consistent across edits.

## Branching

Follow the mav-git-workflow skill for branch naming conventions, base branch identification, and branch creation.

After creating the branch, save to state:

```bash
jq ".branch = \"$BRANCH_NAME\" | .phase = \"branch\"" .claude/issue-state.json > .claude/issue-state.tmp && mv .claude/issue-state.tmp .claude/issue-state.json
```

## Pull Requests

### Create PR Referencing the Issue

```bash
ISSUE_NUMBER=$(jq -r '.issue' .claude/issue-state.json)
BRANCH=$(jq -r '.branch' .claude/issue-state.json)
PR_TARGET=$(uv run maverick git-workflow pr-target)

git push -u origin $BRANCH

gh pr create --base "$PR_TARGET" --title "<concise title>" --body "$(cat <<PR_EOF
## Summary
<1-3 bullet points>

Closes #$ISSUE_NUMBER

## Test Plan
- [ ] <verification steps>

---
*Created by Claude Code*
PR_EOF
)"
```

Using `Closes #N` in the PR body automatically closes the issue when the PR is merged.

## Resuming Work

When resuming work on an issue (new session, after crash, subagent picking up):

```dot
digraph resume {
    "State file exists?" [shape=diamond];
    "Read state file" [shape=box];
    "Read phase" [shape=box];
    "Continue from current phase" [shape=box];
    "Ask user for issue number" [shape=box];
    "Initialise state" [shape=box];

    "State file exists?" -> "Read state file" [label="yes"];
    "State file exists?" -> "Ask user for issue number" [label="no"];
    "Read state file" -> "Read phase";
    "Read phase" -> "Continue from current phase";
    "Ask user for issue number" -> "Initialise state";
    "Initialise state" -> "Continue from current phase";
}
```

1. Check if `.claude/issue-state.json` exists
2. If yes — read it, resume from the recorded phase
3. If no — this is a fresh start, initialise the state file
4. If comment IDs are present, verify they still exist on the issue before updating

## Cleanup

After the PR is created and the workflow is complete:

```bash
rm .claude/issue-state.json
```

Do not delete the state file until the PR is successfully created, as it is needed for crash recovery.

<!-- maverick-plugin-version: 3.3.5 -->

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.