Skip to content
Back to skills

Ship App

ASecurity

Stage, commit, push, and open a PR for one app, gated on a passing validation, then watch CI to a terminal state. Use when the user says "ship it", "open a PR", "deploy <slug>", or after preview and review look good.

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 1, 2026
datagobashsqlgit

Works with

  • claude code
  • terminal

Security analysis

A100/100

Scanned October 6, 2026

npx -y skills add kyle-chalmers/streamsnow --skill ship-app --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ship App?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ship App
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/kyle-chalmers-ship-app/badge)](https://www.skillsdirectory.com/skills/kyle-chalmers-ship-app)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ship-app
description: Stage, commit, push, and open a PR for one app, gated on a passing validation, then watch CI to a terminal state. Use when the user says "ship it", "open a PR", "deploy <slug>", or after preview and review look good.
argument-hint: "<slug>"
allowed-tools: [Bash, Read]
disable-model-invocation: true
---

# /ship-app

> **Repo overlay:** if `.streamsnow/overlays/ship-app.md` exists in this repo, read it first — committed, repo-specific additions/overrides ([_shared/overlays.md](../_shared/overlays.md)). Outside Claude Code, also read [_shared/other-agents.md](../_shared/other-agents.md).

Take a built app from working tree to open PR, gated on validation, then watch CI. **One app at a
time**; deployment is **CI-only on merge to `main`** — never a local Snowflake deploy. Repo-level
changes (templates, governance, CI) do not belong in a `/ship-app` PR; commit those separately.

## Steps

1. **Resolve the slug**; `git status --short apps/<slug>` must show changes to ship — zero changes
   ahead of `main` → nothing to PR; stop and say so.
2. **Preflight 0 — review gate (asks, never blocks):**
   `streamsnow review-gate classify <slug> --format json`. Reviewed/trivial/skip-marker → proceed.
   `.apps[0].needs_review == true` → offer the choice: review first (`/review-app <slug> --auto`) or **ship
   as-is** — always available (ships can be time-critical; /validate-app + CI are the real publish
   gates), but note "shipped unreviewed" in the PR body so the approver sees it. If the app's SQL
   changed, recommend `/sql-review <slug>` before merge (never required). Never auto-run either.
3. **Hard gate:** run /validate-app. Any FAIL → stop; report and do not stage, commit, or push.
   /validate-app is the fix-it path — don't auto-fix here.
4. **Branch hygiene.** On `main` → `git switch -c ship/<slug>-<desc>` first. **Never reuse a
   squash-merged branch** — Git's three-way merge can silently revert your own deletions. Check:
   `gh pr list --search "head:$(git branch --show-current) is:merged" --json number` — non-empty
   means the branch is spent; start fresh off `main` and re-apply (cherry-pick or copy edits, never
   `git merge` from the old branch).
5. **Stage only the app:** `git add apps/<slug>` (plus the repo README only if its app-index row
   changed). Show `git diff --cached --stat`; unstage anything else — don't widen scope to "fix one
   more thing".
6. **Commit** conventionally (`feat(<slug>): <summary>`), the summary matching the diff —
   underclaim, never overclaim. Pre-commit hooks block → **stop and surface the error**; never
   `--no-verify` (the hooks run the same checks CI does).
7. **Sync with `origin/main` before pushing** per
   [_shared/sync-with-main.md](../_shared/sync-with-main.md): rebase (never merge), then
   `git push --force-with-lease`. A rebase conflict stops with manual instructions — don't guess a
   resolution.
8. **Push** (`git push -u origin HEAD` if the sync didn't already) — refuse to push to `main`.
9. **Open the PR** (title/body: what changed, validation passed). Print the number and URL.
10. **Note the deploy path:** merging to `main` triggers CI, which deploys — no local deploy step.
11. **Watch checks to a terminal state** (`gh pr checks <num> --watch` in the background;
    `gh pr view <num> --json state,mergeStateStatus`) and report once on exit.

## Reporting the outcome

- **A check fails** → name it; translate deploy failures via
  [_shared/deploy-error-translator.md](../_shared/deploy-error-translator.md) (failure signatures
  differ by runtime — see [_shared/runtime-decision.md](../_shared/runtime-decision.md)); stop.
- **Green but unmerged** → it's waiting on a teammate's approval (you can't approve your own PR) —
  say so plainly rather than looping on the checks.
- **Merged** → confirm, then report the deploy run's outcome.

## Gotchas

- **Squash-merged branch reuse is the highest-severity trap** — it fails silently: CI passes, the
  deploy ships the wrong code. The step 4 check is non-negotiable.
- **Commit message must match the diff.** A claimed change with no matching hunk means a fix was
  lost (often in manual conflict resolution) — re-read the diff and correct one or the other before
  opening the PR.
- Most deploy-run failures resolve to one-time, admin-applied DDL emitted by
  `streamsnow deploy-setup --admin`: surface the named fix; never run DDL from here.

## Troubleshooting

Push rejected (stale `--force-with-lease`) → re-fetch, rebase, push — never plain `--force`. PR
opens "behind" → `main` moved; re-run the sync step and let checks re-run.

## Done when

The PR is open, validation passed before staging, the branch is rebased on current `origin/main`,
and checks reached a terminal state with the outcome reported: a named failed check, "awaiting
approval," or merged + the deploy result.

## System-evolution retro (always, even on a clean ship)

One question before closing: did anything go wrong or get re-done this ship? If so, **which
layer was insufficient** — the config (`streamsnow.config.yaml` / governance rules), a skill,
a check (`streamsnow validate-app` / CI), or the deploy path? Propose the concrete fix to
*that* artifact. If the gap is in StreamSnow itself, file it against the plugin repo (issue or
a note the user can act on) rather than patching around it locally. Fixing the layer, not the
instance, is what compounds. (Ported from ticketwright's /ship Phase C.)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…