Gh Plan

Find an issue in the 'plan' stage, read the actual codebase, write a detailed implementation plan, and move the card to 'review'.…

goodtribes-org updated 2mo ago
Claude CodeGeneric
View source ↗
# GitHub Plan Writer

Find an issue in the 'plan' stage, read the actual codebase, write a detailed implementation plan, and move the card to 'review'. Runs continuously — polls every 5 minutes when the queue is empty.

## Usage

/gh-plan


Run from the monorepo root (`~/projects/goodtribes.org`). The skill detects the project board and target sub-project automatically.

## Status flow context

new → request → plan → review → apply → test ↑ You are here


Issues arrive in 'plan' after a human approves the outline written by `/gh-request`. This skill writes the full file-level implementation plan and moves the card to 'review' for final human sign-off before implementation begins.

## Workflow

Step 0 runs **once** at startup. Steps 1–11 repeat in a loop until interrupted.

### 0. Find all project boards

```bash
gh project list --owner goodtribes-org --format json --limit 50

Collect ALL projects returned. Note each project's number and id (node ID starting with PVT_). There is no title filter — all org projects are processed.

If no projects found — report "No GitHub Project boards found" and stop entirely.


↻ LOOP — repeat from here after each issue or after sleeping

1. List items in 'plan' status across all boards

For each project number collected in step 0, run:

gh project item-list <number> --owner goodtribes-org --format json --limit 100

Collect all items where status equals plan (case-insensitive) across all boards.

For each candidate item (prefer unassigned first), fetch its issue labels:

gh issue view <content.number> --repo <content.repository> --json labels --jq '.labels[].name'

Skip the item if any label name starts with picked-by-. Pick the first item that passes this check.

Note the item's:

  • id — project item node ID (starts with PVTI_)
  • content.number — linked issue number
  • content.repository — the repo the issue lives in (e.g. goodtribes-org/kickfix)
  • projectNumber and projectNodeId — the board this item came from (needed for step 9)

If no items in 'plan' status on any board, OR all candidates have a picked-by-* label:

echo "No issues in plan — sleeping 5 minutes..." && sleep 300

Then go back to step 1 (do not re-run step 0).

1.5. Claim the issue with a picked-by label

Get the local hostname and immediately label the issue to prevent other agents from picking it up:

PICKED_LABEL="picked-by-$(hostname)"
gh label create "$PICKED_LABEL" --repo <issueRepo> --color "f9a825" --force
gh issue edit <issueNumber> --repo <issueRepo> --add-label "$PICKED_LABEL"

Report: "Claimed issue # with label $PICKED_LABEL."

Store $PICKED_LABEL — you will need it when removing the label in step 10.

2. Claim the item — move to 'plan' (keep status, set assignee context)

Look up the Status field and option IDs:

gh project field-list <number> --owner goodtribes-org --format json

Note:

  • Status field id<statusFieldId> (starts with PVTSSF_)
  • Option review<reviewOptionId>

The card stays at plan while you work. You will move it to review only after the plan comment is posted successfully.

3. Read the issue

gh issue view <issueNumber> --repo <issueRepo> --json title,body,labels,number,url,comments

Display the issue:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ISSUE #<number>: <title>
 Repo: <issueRepo>
 URL:  <url>
 Labels: <labels>
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

<body>

PREVIOUS COMMENTS:
<comments — include the gh-request outline if present>
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Read both the original request (body) and any existing plan outline posted by /gh-request (in comments). The outline is the starting point — the goal here is to expand it into a precise, file-level plan.

4. Validate the sub-project label

Check the issue labels for exactly one of these values:

  • kickfix
  • asylguiden.se
  • goodtribes.org

Then verify the directory exists in the monorepo:

ls /home/mattias/projects/goodtribes.org/<label>/

If no valid label is present, OR the directory does not exist — reject the issue:

Write the rejection comment to a temp file and post it:

cat > /tmp/gh-reject.md << 'EOF'
## Missing or invalid project label

This issue cannot be planned because it has no valid sub-project label. `/gh-plan` only processes issues labelled with an existing project:

- `kickfix`
- `asylguiden.se`
- `goodtribes.org`

Please add the correct label and move the card back to **plan** when ready.

*Card returned to request.*
EOF
gh issue comment <issueNumber> --repo <issueRepo> --body-file /tmp/gh-reject.md
rm /tmp/gh-reject.md

Move card back to request:

gh project item-edit \
  --id <itemNodeId> \
  --field-id <statusFieldId> \
  --project-id <projectNodeId> \
  --single-select-option-id <requestOptionId>

Look up requestOptionId from gh project field-list if not already known — it is the Status option named request.

Update labels:

gh issue edit <issueNumber> --repo <issueRepo> --remove-label "plan" --add-label "request"

Report: "Issue # has no valid sub-project label — rejected back to request." and stop.

If valid: note <subProject> and <localPath> and continue.

5. Identify the target sub-project path

Map the validated label to its local source path:

Label Local path
kickfix kickfix/
asylguiden.se asylguiden.se/
goodtribes.org goodtribes.org/

Report: "Target sub-project: at <localPath>"

6. Read the codebase

Read the sub-project's documentation and structure first:

cat /home/mattias/projects/goodtribes.org/<localPath>/CLAUDE.md 2>/dev/null
cat /home/mattias/projects/goodtribes.org/CLAUDE.md

Then explore the relevant source files. Use the issue body and the `gh- ```

Maintain Gh Plan?

Let people know it's listed here — add the badge (live metrics, light/dark aware) or a plain link to your README or docs.

[Gh Plan on getagentictools](https://getagentictools.com/loops/goodtribes-org-github-plan-writer?ref=badge)
npx agentictools info loops/goodtribes-org-github-plan-writer

The second line is the CLI lookup for this page — handy in READMEs and docs.