# My Ship It

> Use when the user says '/my-ship-it' or 'ship it' or wants to gate a commit/merge. Pre-commit pipeline that runs the project's lint + tests, invokes the my-code-reviewer subagent on the diff, drafts a Conventional Commits message, and presents everything for the user to approve. Never commits or pushes — that stays a manual step.

- Skill: `apoorva-01/my-ship-it` (Agent Skill)
- Install (CLI): `npx skillmds@latest add apoorva-01/my-ship-it`
- Raw SKILL.md: https://api.skillmd.com/api/skills/apoorva-01/my-ship-it/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: apoorva-01 (https://skillmd.com/u/apoorva-01)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/apoorva-01/my-ship-it

---


# /my-ship-it

Pre-commit gate. Stops you from shipping broken or sloppy code without permission, but does **not** take the action for you.

## When to invoke

Trigger phrases (case-insensitive): `/my-ship-it`, `ship it`, `ship this`. Run only when there's an active diff in the current repo.

If there is no diff (`git status --porcelain` empty), say so in one line and stop.

## Pipeline — execute in order, do not skip

### Step 1 — Detect project tooling

Probe the repo root. Pick the first match:

| File present | Test command | Lint command |
|---|---|---|
| `package.json` with a `test` script | `npm test --silent` (or `pnpm test`/`yarn test` if those lockfiles exist) | `npm run lint --silent` if a `lint` script exists |
| `pyproject.toml` or `pytest.ini` or `tests/` | `pytest -q` | `ruff check .` if `ruff` is installed, else `flake8 .` if installed, else skip |
| `go.mod` | `go test ./...` | `go vet ./...` |
| `Cargo.toml` | `cargo test --quiet` | `cargo clippy --quiet -- -D warnings` |
| `Gemfile` | `bundle exec rspec` if `rspec` present, else `bundle exec rake test` | `bundle exec rubocop` if installed, else skip |

If nothing matches, **stop** with a one-line message: `ship-it: no recognized test runner — verify manually before committing`.

### Step 2 — Run lint and tests in parallel

Single message, two `Bash` calls in parallel: lint and test. Use a generous timeout (up to 600000 ms).

- If **either** fails: print only the failing block (last ~40 lines), do NOT print the passing block, and stop. Verdict: `REQUEST CHANGES — fix tests/lint and rerun /my-ship-it`.
- If lint isn't applicable for the stack, say `lint: n/a` and just run tests.

### Step 3 — Invoke `my-code-reviewer` subagent

Single `Agent` call, `subagent_type: my-code-reviewer`. Prompt:

> Review the current diff in this repo against the rubric in ~/.claude/CLAUDE.md and the project's own CLAUDE.md if present. Run `git diff --no-color HEAD` to get the diff. Read full files for non-trivial hunks. Return your fixed-format verdict.

Pass through whatever the reviewer returns verbatim.

### Step 4 — Branch on verdict

- **`APPROVE`** → continue to Step 5.
- **`REQUEST CHANGES`** → print the reviewer's Blockers section and stop. Do NOT draft a commit message. The user must address Blockers and rerun.
- **`NEEDS DISCUSSION`** → print the reviewer's full output and stop. Ask the user one specific question that would unblock the call.

### Step 5 — Draft a commit message (do NOT commit)

Read the diff plus recent commit history (`git log --oneline -10`) to match the repo's style. Draft a Conventional Commits message:

```
<type>(<scope>): <imperative summary, ≤ 70 chars>

<body — 1–3 short paragraphs, focuses on *why*, not *what*. Wrap at 72.>
```

Types: `feat` / `fix` / `refactor` / `docs` / `test` / `chore` / `perf`. Pick the one that matches the largest portion of the diff. Scope is the top-level module or directory touched, lowercase, optional.

Show the user:

1. The reviewer's verdict block (verbatim).
2. The drafted commit message in a fenced block.
3. The exact command to run to commit it, e.g.:

   ```sh
   git commit -m "$(cat <<'EOF'
   <message body>
   EOF
   )"
   ```

End with the literal sentence: `Run the command above to commit, or edit the message first. ship-it does not commit for you.`

## Hard rules

- **Never run `git commit`, `git push`, `git tag`, or any mutating git command.** This skill stops at "drafted message ready."
- **Never run `--no-verify`.** If a hook is failing, surface it; don't bypass.
- **Run lint + test in parallel** in Step 2. Sequential wastes 30–60 seconds per invocation.
- **One subagent call** in Step 3. Don't spawn the reviewer twice.
- **Stop fast on failure.** If lint or tests fail, do not continue to review — fix-then-rerun is cheaper than reviewing broken code.

## Edge cases

- **Untracked files in the diff**: include them in the review (`git diff --no-color HEAD` won't show them, so also run `git status --porcelain` and read each untracked file).
- **Mixed staged/unstaged**: review everything (staged + unstaged) — what gets committed is the user's choice, and they need to see both.
- **Submodules / monorepos**: detect tooling in the *current working directory*, not the repo root, if a `package.json`/`pyproject.toml` is closer.
- **No tests at all**: if Step 1 found a test runner but the project has zero tests, note it as a Smell in the verdict but do not block. Suggest `my-test-writer` agent.

