FIX: Add /ship skill for branch, atomic commits, and draft PR workflow#76
FIX: Add /ship skill for branch, atomic commits, and draft PR workflow#76tahierhussain wants to merge 4 commits intomainfrom
Conversation
Adds a manual-only Claude Code skill that walks uncommitted changes through branch creation, atomic commits, push, and draft PR. Includes the project's PR body template as the source of truth for PR descriptions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
| Filename | Overview |
|---|---|
| .claude/skills/ship/SKILL.md | Adds the main ship skill procedure; addresses most issues from the previous review round, but the "already committed" fast-path at line 79 silently skips the secrets scan despite the guardrail at line 325 explicitly forbidding that. |
| .claude/skills/ship/pr-body-template.md | Canonical PR body template with placeholder - values for all required sections; clean and consistent with the section mapping in SKILL.md Section 3. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A(["/ship invoked"]) --> B{Changes already\ncommitted locally?}
B -- Yes --> C["⚠️ Skip Phases 1–4\n(secrets scan bypassed)"]
C --> G[Phase 5: Draft PR body\n+ confirmation gate]
B -- No --> D[Phase 1: Discover\ngit status / git diff HEAD\ngit diff --cached]
D --> E{Secrets found?}
E -- Yes --> F[AskUserQuestion hard-stop:\nDrop/keep/cancel]
F --> D2[Phase 2: Plan branch name]
E -- No --> D2
D2 --> D3[Phase 3: Plan commits\n+ confirmation gate]
D3 --> D4[Phase 4: Execute\nbranch → commits → push]
D4 --> G
G --> H[Phase 6: gh auth check\nExisting PR check\nWrite /tmp body\ngh pr create --draft]
H --> I([Draft PR URL returned\nTemp file cleaned up])
Prompt To Fix All With AI
This is a comment left during a code review.
Path: .claude/skills/ship/SKILL.md
Line: 79-81
Comment:
**"Already committed" path bypasses the secrets scan**
The edge-case branch at line 79 says "skip Phases 1–4", but Phase 1 is exactly where the secrets scan lives. Any commits that were made locally before `/ship` was invoked — and that contain `AKIA*`, `sk-*`, `ghp_*`, or similar tokens — are pushed to origin without ever hitting the hard-stop gate. This directly contradicts the guardrail at line 325 ("Never skip the secrets scan").
The fix is to still run the scan against `git diff <base>...HEAD` (already referenced for discovery in this path) before proceeding to Phase 5:
```markdown
- **No uncommitted changes (everything already committed locally)** → run the secrets
scan against `git diff <base>...HEAD` first (same hard-stop rules apply); if clean,
skip commit-planning; derive the branch name and PR description from existing commit
messages and `git diff <base>...HEAD`; push existing commits in Phase 4; proceed to Phase 5
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (4): Last reviewed commit: "fix(claude): address /ship skill review ..." | Re-trigger Greptile
…n /ship skill - Fix line-continuation bug in the Phase 6 gh pr create example: move the FEAT/FIX note above the block so every flag carries a backslash. - Resolve --base dynamically via `gh repo view` so the skill works on repos whose default branch is not `main`. - Add `AskUserQuestion` to allowed-tools so the secrets-scan hard-stop can present its structured three-option prompt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Branch names always contain a `/` (feat/<kebab> or fix/<kebab>), so `/tmp/pr-body-<branch>.md` resolved to a non-existent subdirectory and broke the write, --body-file, and cleanup steps. Sanitize via `tr '/' '-'` into `$BRANCH_SAFE` and thread it through all three. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Drop unused Edit from allowed-tools. - Document the Co-Authored-By trailer in commit-format conventions. - Tighten the AWS secret-key scan to assignment + 40-char value so bare references in .env.example don't trip the gate. - Reorder Phase 6 so gh auth status runs before any temp-file write, add an existing-PR check that stops with the URL surfaced (no silent gh pr create failure on re-runs), make the title prefix derive from classification instead of hard-coded FEAT, and switch cleanup to rm -f. - Require every '-' placeholder from the PR-body template to be replaced with prose or a literal TODO before raising. - Update Section 9 to describe the existing-PR stop behavior. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| - **No uncommitted changes (everything already committed locally)** → skip Phases 1–4; | ||
| derive the branch name and PR description from existing commit messages and | ||
| `git diff <base>...HEAD`; push existing commits in Phase 4; proceed to Phase 5 |
There was a problem hiding this comment.
"Already committed" path bypasses the secrets scan
The edge-case branch at line 79 says "skip Phases 1–4", but Phase 1 is exactly where the secrets scan lives. Any commits that were made locally before /ship was invoked — and that contain AKIA*, sk-*, ghp_*, or similar tokens — are pushed to origin without ever hitting the hard-stop gate. This directly contradicts the guardrail at line 325 ("Never skip the secrets scan").
The fix is to still run the scan against git diff <base>...HEAD (already referenced for discovery in this path) before proceeding to Phase 5:
- **No uncommitted changes (everything already committed locally)** → run the secrets
scan against `git diff <base>...HEAD` first (same hard-stop rules apply); if clean,
skip commit-planning; derive the branch name and PR description from existing commit
messages and `git diff <base>...HEAD`; push existing commits in Phase 4; proceed to Phase 5Prompt To Fix With AI
This is a comment left during a code review.
Path: .claude/skills/ship/SKILL.md
Line: 79-81
Comment:
**"Already committed" path bypasses the secrets scan**
The edge-case branch at line 79 says "skip Phases 1–4", but Phase 1 is exactly where the secrets scan lives. Any commits that were made locally before `/ship` was invoked — and that contain `AKIA*`, `sk-*`, `ghp_*`, or similar tokens — are pushed to origin without ever hitting the hard-stop gate. This directly contradicts the guardrail at line 325 ("Never skip the secrets scan").
The fix is to still run the scan against `git diff <base>...HEAD` (already referenced for discovery in this path) before proceeding to Phase 5:
```markdown
- **No uncommitted changes (everything already committed locally)** → run the secrets
scan against `git diff <base>...HEAD` first (same hard-stop rules apply); if clean,
skip commit-planning; derive the branch name and PR description from existing commit
messages and `git diff <base>...HEAD`; push existing commits in Phase 4; proceed to Phase 5
```
How can I resolve this? If you propose a fix, please make it concise.
What
Adds a new manual-only Claude Code skill at
.claude/skills/ship/thatwalks uncommitted (or already-committed) changes through a structured
flow: branch creation → atomic Conventional-Commits → push → draft PR.
The skill is composed of
SKILL.md(the procedure) andpr-body-template.md(the source-of-truth PR description template).Why
Standardises how PRs get raised from this working directory so branch
names, commit grouping, and PR descriptions stay consistent across
sessions, without relying on memory or ad-hoc prompting. Manual-only
(
disable-model-invocation: true) so it never auto-fires fromconversational pattern-matching — it only runs when explicitly
invoked via
/ship.How
Two new files under
.claude/skills/ship/:SKILL.mddefines six phases (discover/classify, plan branch name,plan commits with confirmation gate, execute, draft PR body with
confirmation gate, raise PR), plus rules for branch prefixes (binary
feat/vsfix/), commit grouping, secrets scanning, and PR-sectionsource mapping.
pr-body-template.mdis the canonical PR body template the skillreads on every run, so future structural changes to PR descriptions
are made by editing the template alone.
Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)
No runtime impact. The change is purely additive Claude Code tooling
under
.claude/skills/— no application code, build config, CIworkflow, or product surface is touched. The skill is gated behind
manual
/shipinvocation, so it cannot auto-trigger.Database Migrations
None.
Env Config
None.
Relevant Docs
None.
Related Issues or PRs
None.
Dependencies Versions
None.
Notes on Testing
/shipon a clean working tree onmainand confirm it stops with a clear "no changes" message/shipwith mixed feat + fix changes and confirm it asks whether to split before proceeding/shipwith a staged file containing a fakesk-…token and confirm the secrets-scan hard-stop fires before any commit/shipend-to-end on a small change and confirm the draft PR is opened with the body sourced frompr-body-template.md(not.github/)--no-verifyretry and no amenddisable-model-invocation: truehonoured)Screenshots
N/A — tooling-only change, no UI surface.
Checklist
I have read and understood the Contribution Guidelines.