dev-ship/SKILL.md
Pick the next ready AFK GitHub issue, implement it with TDD, run the full Next.js quality gate, call /dev-simplify, create a PR, call /dev-review + /dev-security-review, and verify the app at runtime with Chrome DevTools MCP. Use when the user wants to process the backlog, implement the next issue, or run the dev loop. Trigger phrases - "/dev-ship", "ship the next issue", "work through the backlog".
npx skillsauth add paulund/skills dev-shipInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Process the next ready autonomous issue end-to-end: implement it, prove it works, open a PR with automated review, and leave it ready for the user to merge.
Intended to run repeatedly via /loop /dev-ship until no issues remain.
next build passing doesn't mean the app runs — Chrome DevTools MCP proves it does./dev-review + /dev-security-review; fixes happen back in the parent where implementation memory is still loaded.gh issue list --label "planned,afk" --state open --json number,title,labels,body
Then verify blockers with open/closed state — never assume a referenced issue is open without checking:
import json, sys, re, subprocess
data = json.load(sys.stdin)
def get_blockers(body):
m = re.search(r'##\s+Blocked by\s*\n(.*?)(?=\n##|\Z)', body or '', re.DOTALL | re.IGNORECASE)
if not m:
return []
return re.findall(r'#(\d+)', m.group(1))
def is_open(num):
r = subprocess.run(['gh', 'issue', 'view', num, '--json', 'state'], capture_output=True, text=True)
return r.returncode == 0 and json.loads(r.stdout).get('state') == 'OPEN'
def sort_key(i):
labels = [l['name'] for l in i['labels']]
is_bug = 0 if 'bug' in labels else 1
priority = next((l for l in labels if re.match(r'^p[123]$', l)), 'p9')
return (is_bug, priority)
for issue in sorted(data, key=sort_key):
labels = [l['name'] for l in issue['labels']]
if 'hitl' in labels or 'blocked' in labels:
continue
open_blockers = [b for b in get_blockers(issue['body']) if is_open(b)]
if not open_blockers:
print(f"PICK: #{issue['number']} — {issue['title']}")
break
Rules:
hitlblockedBlocked by #N references have open state — always query gh issue view N --json state to confirm; a merged/closed blocker does NOT blockbug is picked before any non-bug, regardless of priorityp1 > p2 > p3). Same for non-bugs once the bug bucket is emptyRead the issue body fully — the acceptance criteria drive the TDD cycles.
main)agent/issue-<N>-<slug>planned, add in-progressFor each acceptance criterion, run a RED → GREEN → REFACTOR cycle:
Tests verify behaviour through public interfaces, not implementation. They should survive internal refactors.
Run in this order. Each step must pass before moving on.
pnpm lint # or: npx next lint
pnpm types # tsc --noEmit
pnpm build # or: npx next build
On failure — Stop-the-Line:
Max 2 diagnose-fix cycles per issue. If still failing, stop and leave the branch for the user — do NOT open a broken PR.
Invoke the built-in /dev-simplify skill to review recently changed code for clarity, unused code, and consistency. Apply its suggestions before the PR.
Re-run the quality gate if /dev-simplify made non-trivial changes.
Push the branch and create the PR:
gh pr create \
--base "main" \
--title "<short descriptive title>" \
--body "$(cat <<'EOF'
## What this does
[Plain-English summary of the change.]
Closes #<issue-number>
EOF
)"
Rules:
Closes #N. No AI output, no checklists, no screenshots.Spawn /dev-review and /dev-security-review as sub-agents (fresh context, read-only) so they read the PR diff without implementation bias.
~/.agents/skills/dev-review/SKILL.md, run against PR #<N>, return findings as severity | file:line | category | description | suggested fix~/.agents/skills/dev-security-review/SKILL.md, run against branch vs origin/HEAD, return report per that skillFix loop (parent context — implementation memory is still loaded):
Create GitHub issues for every accepted-as-is item that isn't already tracked by an open issue. Do this before posting the PR comments so you can reference issue numbers inline.
For each deferred item:
gh issue list --state open for an existing issue covering it — skip if one exists, note its numbergh issue create \
--title "chore: <short description of the deferred finding>" \
--body "$(cat <<'EOF'
## Context
Deferred from PR #<N> review — accepted as-is because <reason>.
## What to do
<concrete description of the fix needed, with file:line reference>
## Acceptance criteria
- [ ] <specific, testable criterion>
EOF
)" \
--label "planned"
Post two separate PR comments so each can be resolved independently on GitHub:
gh pr comment <pr-number> --body "$(cat <<'EOF'
## Automated review
### Fixed
- [list of issues fixed with file:line reference]
### Accepted as-is (Low only — Critical/High/Medium must always be fixed)
- [item — reason — tracked in #N]
EOF
)"
gh pr comment <pr-number> --body "$(cat <<'EOF'
## Security review
### Fixed
- [list of issues fixed with file:line reference]
### Accepted as-is (Low only — Critical/High/Medium must always be fixed)
- [item — reason — tracked in #N]
EOF
)"
in-progress, add in-reviewIf no more planned AFK issues exist, stop and report:
Backlog processed.
- Shipped: <list of PR URLs>
- Still in-review: <list>
- HITL issues waiting for you: <list>
Stop and leave the branch for the user in these cases:
hitl) — flag the issue and stopAlways better to leave a clean branch than to push a broken PR.
Before implementing, always read the repo's AGENTS.md if present. It overrides generic guidance.
Framework rules apply automatically via global skills:
~/.agents/skills/standards-nextjs.md~/.agents/skills/standards-typescript.mdIf you repeatedly see a pattern these skills don't cover, tell the user — the rule belongs in one of those files.
hitl issues autonomouslydevelopment
Use when the user wants to run the project's lint + types + build sequence as a gate before pushing, opening a PR, or merging. Invoked by chained dev skills between phases. Trigger phrases - "/quality-gate", "run the quality gate", "check it builds".
tools
Use when the user wants to verify a PR's feature works at runtime by booting the dev server, exercising the affected UI via Chrome DevTools MCP, and posting a screenshot summary back to the PR. Idempotent — skips if `verified` or `verify-failed` is already on the PR. Trigger phrases - "/pr-verify", "verify this PR", "runtime check the pr".
testing
Use when the user wants a security-focused review pass on a PR with findings actioned as commits on the same branch. Trigger phrases - "/pr-security-review", "security review and fix".
testing
Use when the user wants to open a pull request for an already-pushed branch that implements a specific issue. Idempotent — returns the existing PR if one is already open for the branch. Trigger phrases - "/pr-open", "open the pr", "create pr for this branch".