| name | my-ship-it |
| description | 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. |
| trigger | /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:
-
The reviewer's verdict block (verbatim).
-
The drafted commit message in a fenced block.
-
The exact command to run to commit it, e.g.:
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.