Gh Apply
Find an issue in the 'apply' stage, read its implementation plan, implement all code changes, create a pull request, and move the…
# GitHub Apply Worker
Find an issue in the 'apply' stage, read its implementation plan, implement all code changes, create a pull request, and move the card to 'test'. Runs continuously — polls every 5 minutes when the queue is empty.
## Usage
/gh-apply
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 'apply' after a human moves the card from 'review → apply', signifying the implementation plan has been approved. This skill implements all code changes from the plan and opens a pull request on the goodtribes-org org repository.
## Workflow
Steps 0 and 0.5 run **once** at startup. Steps 1–15 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.
0.5. Verify local repo setup (runs once at startup)
Check that all three sub-project repositories are cloned locally and have the correct git remotes. Run these checks for each sub-project in this order:
| Sub-project | Directory | Remote | Expected URL |
|---|---|---|---|
kickfix |
kickfix/ |
goodtribes |
git@github.com:goodtribes-org/kickfix.git |
asylguiden.se |
asylguiden.se/ |
goodtribes |
git@github.com:goodtribes-org/asylguiden.se.git |
goodtribes.org |
goodtribes.org/ |
origin |
git@github.com:goodtribes-org/goodtribes.org.git |
Check A — Directory exists:
ls /home/mattias/projects/goodtribes.org/<subdir>/
If the directory is missing, clone it automatically (no confirmation needed — cloning is always safe):
git clone git@github.com:goodtribes-org/<repoName>.git /home/mattias/projects/goodtribes.org/<subdir>
For kickfix and asylguiden.se only, rename the default origin remote to goodtribes:
git -C /home/mattias/projects/goodtribes.org/<subdir> remote rename origin goodtribes
For goodtribes.org, keep origin as-is.
If git clone fails, pause and ask the user via AskUserQuestion:
Sub-project setup problem: <name>
Issue: clone failed
Error: <full error output>
Options:
A) Retry the clone (fix SSH/network first, then select A)
B) Skip this sub-project for this session (issues labelled '<name>' will be rejected at step 5)
C) Stop the worker entirely
Wait for the user's response. If A: retry the clone. If B: mark sub-project as unavailable in session memory and continue to the next sub-project. If C: stop entirely.
Check B — Is a git repo:
git -C /home/mattias/projects/goodtribes.org/<subdir> rev-parse --git-dir 2>&1
If this fails (directory exists but is not a git repository), ask the user via AskUserQuestion — do not auto-fix:
Sub-project setup problem: <name>
Issue: directory exists at <subdir> but is not a git repository
Error: <command output>
Options:
A) Skip this sub-project for this session
B) Stop the worker entirely
Check C — Remote name and URL correct:
git -C /home/mattias/projects/goodtribes.org/<subdir> remote get-url <remoteName> 2>&1
If the remote doesn't exist or points to the wrong URL, ask the user via AskUserQuestion and offer to fix:
Sub-project setup problem: <name>
Issue: <remote '<remoteName>' not found | remote '<remoteName>' points to '<actualUrl>' instead of '<expectedUrl>'>
Options:
A) Fix automatically (run: git remote <add|set-url> <remoteName> <expectedUrl>)
B) Skip this sub-project for this session
C) Stop the worker entirely
If A: run the appropriate fix command, then re-run Check C. If it still fails, ask again with the new error output.
Fix commands:
- Remote missing:
git -C <subdir> remote add <remoteName> <expectedUrl> - Remote wrong URL:
git -C <subdir> remote set-url <remoteName> <expectedUrl>
After all checks pass for all three sub-projects, report:
Pre-flight OK: kickfix ✓ asylguiden.se ✓ goodtribes.org ✓
Then proceed to the loop.
↻ LOOP — repeat from here after each issue or after sleeping
1. List items in 'apply' 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 apply (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 withPVTI_)content.number— linked issue numbercontent.repository— the repo the issue lives in (e.g.goodtribes-org/kickfix)projectNumberandprojectNodeId— the board this item came from (needed for step 13)
If no items in 'apply' status on any board, OR all candidates have a picked-by-* label:
echo "No issues in apply — 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 #$PICKED_LABEL."
Store $PICKED_LABEL — yo
```
Maintain Gh Apply?
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 Apply on getagentictools](https://getagentictools.com/loops/goodtribes-org-github-apply-worker?ref=badge) npx agentictools info loops/goodtribes-org-github-apply-worker The second line is the CLI lookup for this page — handy in READMEs and docs.