"Automate GitHub workflow so validated session artifacts become ship-ready issue/PR/merge actions with explicit human control points. Triggers: \"/ship\""
Resources
2Install
npx skillscat add corca-ai/claude-plugins/ship Install via the SkillsCat registry.
Ship (/ship)
Convert validated CWF session artifacts into issue → PR → merge execution with explicit human merge control.
Quick Start
/ship Show usage
/ship issue [--base B] [--no-branch] Create issue + feature branch
/ship pr [--base B] [--issue N] [--draft] Create PR linked to issue
/ship merge [--squash|--merge|--rebase] Check & merge if ready
/ship status Show open issues, PRs, checksNo args or help → print the usage block above and stop.
Defaults
- Base branch: auto-detect remote default branch →
main→master(override with--base) - Merge strategy:
--squash(override with--mergeor--rebase)
Prerequisites
Before any subcommand, verify:
command -v gh >/dev/null 2>&1 || { echo "gh CLI not found"; exit 1; }
gh auth status 2>&1 | grep -q "Logged in" || { echo "Not authenticated — run: gh auth login"; exit 1; }If either fails, do not stop with a passive failure only. Ask the user:
Install/configure now (recommended):- if
ghis missing, runbash {SKILL_DIR}/../setup/scripts/install-tooling-deps.sh --install gh - if auth is missing, run
gh auth login - then retry prerequisite checks once
- if
Show commands only:- print exact install/auth commands and stop
Skip ship for now:- stop without executing ship actions
Output Persistence (Mandatory)
For every /ship invocation (issue, pr, merge, status, and help or no-args):
- Resolve session directory from live state (
live.dir). - Persist a structured execution summary to
{session_dir}/ship.mdwith these required sections:## Execution Status## Ambiguity Resolution## Next Step
- In
## Ambiguity Resolution, always write these scalar lines:mode: strict|defer-blocking|defer-reversible|explore-worktreesblocking_open_count: <integer>blocking_issue_refs: <comma-separated refs or none>issue_ref: <issue URL or none>pr_ref: <PR URL or none>merge_allowed: yes|no- Resolve
modefrom live state (live.ambiguity_mode) and derive counts from{session_dir}/run-ambiguity-decisions.mdif it exists. - For
defer-blocking,merge_allowedmust benowhenblocking_open_count > 0. - When the current branch is not the resolved base branch,
issue_refandpr_refmust contain concrete GitHub URLs before ship-stage closure.
- Synchronize live ambiguity debt state before gate closure:
bash {CWF_PLUGIN_DIR}/scripts/sync-ambiguity-debt.sh \
--base-dir . \
--session-dir "{session_dir}"- When running under
cwf:run, enforce the stage gate:
bash {CWF_PLUGIN_DIR}/scripts/check-run-gate-artifacts.sh \
--session-dir "{session_dir}" \
--stage ship \
--strict \
--record-lessons/ship issue
Create a GitHub issue for the current session and optionally a feature branch.
Workflow
Detect session context:
- Find the current session directory in
.cwf/projects/(most recentYYMMDD-NN-*) - Read
plan.mdif it exists for purpose, scope, success criteria - Read master-plan (search for
master-plan.mdor similar) for session number - Resolve
{base}:- if
--baseis provided, use it - otherwise detect with
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||' - if unresolved, fallback to
main, thenmaster; if none exists, ask the user for base branch explicitly
- if
- Find the current session directory in
Compose issue body:
- Read
{SKILL_DIR}/references/issue-template.md - Substitute variables from session context:
{BACKGROUND}— why this work is needed; extract from plan.md context/motivation section, or summarize from session history{PROBLEM}— specific problem being solved; from plan.md or ask the user{GOAL}— desired outcome; from plan.md objectives or ask the user{SCOPE}— files/areas from plan.md or summarize{BRANCH}— the feature branch name to be created{BASE}— the base branch{PLAN_LINK}— relative path to plan.md{RETRO_SUMMARY}— concise retro outcome summary from.cwf/projects/{session}/retro.md- Prefer
Post-Retro Findingswhen present - Otherwise synthesize up to 3 bullets from waste/CDM/tools sections
- If retro artifact is missing, use
_No retro summary recorded yet._
- Prefer
{RETRO_PERSIST_PROPOSALS}— actionable persistence proposals from retro/lessons- Include owner/apply-layer/target when available
- If no actionable proposal exists, use
_No persistence proposal recorded yet._
- If plan.md is missing or incomplete, ask the user for the missing fields
- Read
Create issue:
gh issue create \ --title "S{N}: {title}" \ --body "$(cat <<'EOF' {composed_body} EOF )" \ --label "cwf-v3"- If
cwf-v3label doesn't exist, create it first:gh label create cwf-v3 --color 0E8A16 --description "CWF v3 migration"
- If
Create feature branch (unless
--no-branch):git checkout {base} && git pull origin {base} git checkout -b feat/{short-name}Report: Print issue URL and branch name.
/ship pr
Create a pull request from the current feature branch.
Workflow
Pre-flight checks (stop with message if any fail):
- Resolve
{base}using the same rule as/ship issue - Not on the resolved base branch
- Has commits ahead of base:
git log {base}..HEAD --onelineis non-empty - No uncommitted changes:
git status --porcelainis empty- If dirty, ask user whether to commit first or abort
- Resolve
Auto-detect linked issue:
- If
--issue Nprovided, use that - Otherwise:
gh issue list --label cwf-v3 --search "S{N}" --json number,title - Match by session number from the current session artifact directory name
- If no match found, proceed without issue link (warn the user)
- If
Build PR body from
{SKILL_DIR}/references/pr-template.md:{ISSUE_LINK}—Closes #{N}if issue found, otherwise omit{PURPOSE}— synthesize fromgit log {base}..HEAD --onelineand plan.md;
describe why this change exists, not what files changed{DECISIONS}— extract key decisions from:.cwf/projects/{session}/lessons.mdtakeaways.cwf/projects/{session}/retro.mdCDM section.cwf/projects/{session}/plan.mddecision points- Format as markdown table:
| Decision | Rationale | Alternatives |(in user's language) - If no decisions found, write a brief "no significant decisions" note (in user's language)
{VERIFICATION}— concrete, reproducible verification steps:- Include exact commands to run (e.g.,
claude --plugin-dir ... -p "...") - Describe expected output/behavior
- Cover both happy path and edge cases if relevant
- Include exact commands to run (e.g.,
{HUMAN_JUDGMENT}— agent self-assessment of items needing human review:- Architecture changes, UX decisions, security implications, breaking changes
- Read
live.ambiguity_modeand{session_dir}/run-ambiguity-decisions.mdwhen present - If mode is
defer-blockingandblocking_open_count > 0, list all open blocking decision debts here (never writeNone) - If none, write
None(this enables autonomous merge — see/ship merge)
{SYSTEM_IMPACT}— behavioral changes visible to end users or dependent systems{FUTURE_IMPACT}— impact on future development (new patterns, constraints, tech debt){GIT_DIFF_STAT}— output ofgit diff {base}...HEAD --stat
wrapped in a```textcode fence{LESSONS}— extract from.cwf/projects/{session}/lessons.mdif exists,
otherwise write_No lessons recorded for this session._{CDM}— extract from.cwf/projects/{session}/retro.mdCDM section if exists,
otherwise write_No CDM recorded yet._{RETRO_SUMMARY}— concise retro outcome summary from.cwf/projects/{session}/retro.md- Prefer
Post-Retro Findingswhen present - Otherwise synthesize up to 3 bullets from waste/CDM/tools sections
- If retro artifact is missing, use
_No retro summary recorded yet._
- Prefer
{RETRO_PERSIST_PROPOSALS}— actionable persistence proposals from retro/lessons- Include owner/apply-layer/target when available
- If no actionable proposal exists, use
_No persistence proposal recorded yet._
{CONDITIONAL_ITEMS}— add checklist items based on changed file types:*.shchanged →- [ ] Scripts are executable and pass shellcheckSKILL.mdchanged →- [ ] SKILL.md under 500 linesplugin.jsonchanged →- [ ] Version bumped appropriatelyhooks.jsonchanged →- [ ] Hook matchers are correct*.mdchanged →- [ ] Markdown lint passes
Push and create PR:
git push -u origin $(git branch --show-current)gh pr create \ --title "S{N}: {title}" \ --body "$(cat <<'EOF' {composed_body} EOF )" \ --base {base}- Add
--draftif the user specified it
- Add
Report: Print PR URL.
/ship merge
Check PR status and merge if ready.
Workflow
Find current PR:
gh pr view --json number,state,reviewDecision,statusCheckRollup,mergeable,headRefName- If no PR found for current branch, report and stop
Assess readiness:
Core checks (always required):
state=OPEN- All status checks passed (parse
statusCheckRollup) mergeable=MERGEABLE
Review requirement (conditional):
- Parse the PR body for
## Human Judgment Requiredsection - Check branch protection:
gh api repos/{owner}/{repo}/branches/{base}/protection 2>&1 - Parse
{session_dir}/run-ambiguity-decisions.mdand/orship.mdambiguity block:- if
mode: defer-blockingandblocking_open_count > 0, merge is blocked
- if
Decision matrix:
Human judgment Branch protected Review required defer-blockingwith open blocking debtAny Stop — do not merge Noneor emptyNo Skip — autonomous merge Noneor emptyYes reviewDecision=APPROVEDrequiredItems listed Any Report items, stop — do not merge If not ready, report which conditions are blocking and stop. Do not attempt to merge.
Merge:
gh pr merge {N} --squash --delete-branch- Use
--mergeor--rebaseif the user specified an override - Default is
--squash
- Use
Post-merge cleanup:
git checkout {base} && git pull origin {base}Report: Merge confirmation, deleted branch name.
/ship status
Read-only overview of current GitHub state.
Workflow
Open issues:
gh issue list --label cwf-v3 --state open --json number,title,assigneesOpen PRs:
gh pr list --json number,title,state,headRefName,reviewDecision,statusCheckRollupCurrent branch PR (if exists):
gh pr view --json number,title,state,reviewDecision,mergeable,statusCheckRollup- If no PR for current branch, note that
Session progress (optional):
- If
master-plan.mdexists, parse the session roadmap - Show completed vs remaining sessions
- If
Report: Format as a readable summary table.
Error Handling
| Situation | Action |
|---|---|
gh not installed |
Ask whether to install now via setup installer script; if declined/fails, print manual commands and stop |
| Not authenticated | Report, suggest gh auth login, stop |
| No commits ahead of base | Report "nothing to PR", stop |
| Issue already exists for session | Show existing issue, ask user before creating duplicate |
| PR already exists for branch | Show existing PR URL, stop |
| Merge conflicts | Report, suggest git rebase {base} instructions, stop |
Missing lessons.md or retro.md |
Use placeholder text, do not fail |
Label cwf-v3 missing |
Create it automatically |
| Dirty working tree on PR | Ask user: commit or abort |
Usage Message
When invoked with no args or help, print:
Ship — GitHub workflow automation for cwf sessions
Usage:
/ship Show this message
/ship issue [--base B] [--no-branch] Create issue + feature branch
/ship pr [--base B] [--issue N] [--draft] Create PR
/ship merge [--squash|--merge|--rebase] Merge approved PR
/ship status Show issues, PRs, checks
Defaults: base=auto-detected (origin/HEAD -> main -> master), merge=squashRules
- Use
ghas the primary interface; do not craft raw GitHub API payloads whenghalready supports the operation. - Stop immediately on failed prerequisites (
ghmissing, unauthenticated, or invalid branch state). - Keep PR purpose and decision sections evidence-backed from session artifacts when available (
plan.md,lessons.md,retro.md). - Never auto-merge when human-judgment items are present in the PR body.
- Preserve user-created files and branches; do not perform destructive cleanup beyond explicit merge cleanup.
- All code fences must have language specifiers.
- Missing prerequisites must trigger an install/configure choice prompt, not a passive "missing tool" report only.
/shipmust always persist{session_dir}/ship.mdbefore returning.- In
defer-blockingmode, unresolved ambiguity debt is merge-blocking until tracked follow-up references are recorded andblocking_open_countis zero. - Language override: issue/PR narrative sections are written in the user's language; code blocks, file paths, commit hashes, and CLI output remain verbatim.
retrooutcomes and persistence proposals must be visible in issue/PR body sections, not only hidden in collapsed details blocks.
References
- issue-template.md — Issue body template
- pr-template.md — PR body template
- agent-patterns.md — Shared workflow pattern reference