Install
$ agentstack add skill-thijsvos-claude-skills-github-ship ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Call EnterPlanMode immediately before doing anything else.
You automate a GitHub issue + PR workflow. The user runs you with no arguments. You look at the current branch and figure out what to do:
- If there is a merged PR for the current branch → clean up the branch.
- Otherwise → create an issue and a linked PR for the local changes.
You never merge the PR yourself — that is always the user's action on GitHub.
Pre-rendered context
These values are computed by the harness before this skill runs (via Claude Code's dynamic context injection), so Step 1 has the data it needs without an extra Bash round-trip:
- In a git repo? !
git rev-parse --is-inside-work-tree 2>/dev/null || echo "no" - GitHub remote? !
git remote get-url origin 2>/dev/null | grep -qE 'github\.com[:/]' && echo "yes" || echo "no" - gh authed? !
gh auth status 2>&1 | grep -q "Logged in" && echo "yes" || echo "no" - Current branch: !
git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "(unavailable)" - Default branch: !
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || git rev-parse --verify main >/dev/null 2>&1 && echo main || git rev-parse --verify master >/dev/null 2>&1 && echo master || echo "(unknown)" - Working tree: !
if [ -n "$(git status --porcelain 2>/dev/null)" ]; then echo "DIRTY ($(git status --porcelain 2>/dev/null | wc -l | tr -d ' ') files)"; else echo "clean"; fi - Existing PR for current branch: !
gh pr list --head "$(git rev-parse --abbrev-ref HEAD 2>/dev/null)" --state all --json number,state,mergedAt,url --limit 1 --jq 'if length > 0 then .[0] else "(none)" end' 2>/dev/null || echo "(gh unavailable)"
Step 1: Pre-flight and Decide
Read the Pre-rendered context above to make the routing decision without re-running the same commands. Stop with an actionable error on any failure (In a git repo? = no, GitHub remote? = no, gh authed? = no).
If the existing-PR row shows a MERGED state → go to Step 3 (Cleanup). Otherwise → go to Step 2 (Create). If a non-merged PR already exists, note that in the plan and offer to update it rather than create a new one.
If you need fresher data than the pre-rendered values provide (e.g., the user just made changes after the skill loaded), re-run the relevant git/gh command via Bash.
- If the PR state is
MERGED→ go to Step 3 (Cleanup). - Otherwise → go to Step 2 (Create). If a non-merged PR already exists, note that in the plan and offer to update it rather than create a new one.
Step 2: Create — Draft, Approve, Execute
Gather the change:
git status --porcelain
git log "$default_branch"..HEAD --format="%h %s"
git diff "$default_branch"...HEAD --stat
git diff "$default_branch"...HEAD
git diff HEAD
Read the full content of any non-trivial files in the diff so your descriptions are accurate.
Draft these yourself:
- Issue title (≤70 chars, imperative mood, no trailing period).
- Issue body (2-4 sentences describing the problem or need).
- PR title (≤70 chars).
- PR body: starts with
Closes #(placeholder until the issue is created), then a Summary (bullets) and Test plan (checklist). - Branch name (kebab-case, prefixed
fix/,feat/,chore/,docs/, orrefactor/) — only if currently on the default branch. - Commit message (imperative, ≤72 chars) — only if there are uncommitted changes.
Present the plan:
## Ship Plan
**On**: `` → `` on ``
### Actions
- [] Commit: `` (skip if nothing uncommitted)
- [] Create branch: `` (skip if already on a feature branch)
- [] Push to origin
- [ ] Create issue
- [ ] Create PR linking to the issue
### Issue
**Title**:
**Body**:
>
### Pull Request
**Title**:
**Body**:
> Closes #
>
> ## Summary
>
>
> ## Test plan
>
Call ExitPlanMode, then ask:
> Ship it? (e.g., "go", "shorten the title", "rewrite the body")
After approval, execute in order. If any step fails, stop and report.
- Commit if needed:
``bash git add -A && git commit -m "" ` Never use --no-verify`.
- Create a feature branch if currently on
$default_branch:
``bash git checkout -b "" ``
- Push:
``bash git push -u origin HEAD ``
- Create the issue and capture the number:
``bash issue_url=$(gh issue create --title "" --body "$(cat EOF )") issue_number=$(echo "$issue_url" | grep -oE '[0-9]+$') ``
- Create the PR. Build the body with
Closes #$issue_numberinterpolated into the first line, but use a quoted heredoc (`
## Test plan
EOF ) printf '%s\n' "$prbody" | gh pr create --base "$defaultbranch" --title "" --body-file - ```
- Report:
> Shipped. > - Issue: ` > - PR: > > Merge the PR on GitHub when ready, then run /github-ship` again to clean up.
Step 3: Cleanup — Verify, Approve, Execute
Verify the state:
git status --porcelain # must be clean
gh pr view --json number,state,mergedAt,headRefName,url 2>/dev/null
If the working tree is dirty, stop: Commit or stash your changes before cleanup.
Present the cleanup plan:
## Ship Cleanup
**PR**: # merged ()
**Branch**: ``
### Actions
1. Checkout ``
2. `git pull --ff-only`
3. Delete local branch ``
4. Delete remote branch `` (if it still exists)
Call ExitPlanMode, then ask:
> Clean up? ("go" / "no")
After approval:
git checkout "$default_branch"
git pull --ff-only
Try the safe local delete. Capture the exit code — do NOT proceed to remote delete unless local delete succeeded or the user explicitly approves the force-delete:
if git branch -d "$current_branch" 2>&1; then
local_deleted=yes
else
local_deleted=no
fi
If local_deleted=no (normal for squash-merged or rebase-merged PRs), ask inline:
> Local branch has commits not on ``. This is normal for squash/rebase merges. Force-delete? (yes/no)
If the user answers yes:
git branch -D "$current_branch" && local_deleted=yes
If the user answers no, stop here — do NOT delete the remote branch. The user can rerun the skill after sorting the branch out, or delete it manually.
Only after local_deleted=yes, delete the remote branch if it still exists:
if [ "$local_deleted" = "yes" ] && git ls-remote --heads origin "$current_branch" | grep -q .; then
git push origin --delete "$current_branch"
fi
Report: > Cleaned up. On ` at . Branch ` removed.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: thijsvos
- Source: thijsvos/Claude_Skills
- License: MIT
- Homepage: https://github.com/thijsvos/Claude_Skills#readme
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.