Install in Claude Code
Copygit clone --depth 1 https://github.com/kentcdodds/kody /tmp/ship-pr && cp -r /tmp/ship-pr/.agents/skills/ship-pr ~/.claude/skills/ship-prThen start a new Claude Code session; the skill loads automatically.
Definition
SKILL.md
# Ship PR
## Risk → merge authority
Self-assess; user policy overrides.
**Kent's standing policy (2026-08-08):** auto-ship (squash-merge + verify
deploy) once AI reviewer feedback is addressed and CI is green, unless **high**
risk. High risk still parks ready-for-review unless merge authority was granted
explicitly.
- **Low** — green CI; nits ignorable; squash-merge when policy allows.
- **Medium** — wait for AI reviewer(s); address **valid** feedback (ignore
insignificant nits / already-fixed / wrong); then merge when policy allows.
- **High** — leave ready-for-review unless the user granted merge authority.
## AI reviewers
Prefer **Cursor Bugbot** (`Cursor Bugbot` check / `cursor[bot]` review
comments). Never comment `bugbot run` or `cursor review` yourself, including via
`gh` or GitHub request as kody-bot. Trigger with `kody:@kentcdodds/bugbot` using
`{ prUrl }` or `{ owner, repo, prNumber }`. Do not pass a GitHub account.
```javascript
import triggerBugbot from 'kody:@kentcdodds/bugbot'
await triggerBugbot({ prUrl })
```
**CodeRabbit:** if it is rate-limited, errored, or otherwise unavailable, **do
not wait** on it for low/medium risk — proceed with Bugbot + CI. Only wait on
CodeRabbit when the change is **high** risk (or the user explicitly asks).
## Loop
1. Mark ready — `kody:@kentcdodds/github/pr/set-review-status`
`{ prUrl, status: 'ready' }` (or owner/repo/prNumber).
2. Wait for CI — `gh pr checks` (or compose `loop-on-ci` / `fix-ci`).
3. Fix failures; for **medium+**, wait on AI reviewer(s) (Bugbot first; see
above for CodeRabbit) and address valid feedback. Rebase only when actually
unmergeable. For **medium+**, also run `npm run control-kody -- preview` (or
`npm run preview:manual-test`) as the seeded user **with data for this
change** (`--request` / session cookie; see
[control-kody](../control-kody/SKILL.md) and
[preview-manual-test](../preview-manual-test/SKILL.md)). After merge,
`npm run control-kody -- health --origin https://kody.codes --sha <merge>`.
4. Green + (medium+: valid feedback cleared) → break.
5. Push → repeat.
## Gates ≠ CI
Blocked on soak / parity CHECK / calendar gate → **end the run** and schedule a
wake (`execute` + `workflows.create({ runAt, idempotencyKey })` calling
`createRun`). Don't sleep-poll or code-thrash an intentional time window.
Leftovers that wait on that gate need a GitHub issue (`Cleanup:` title); see
[cleanup-after-migrations](../cleanup-after-migrations/SKILL.md).
Batch related expand steps into fewer PRs when risk posture allows.
## Merge / deploy
When policy + risk allow: squash-merge via `kody:@kentcdodds/github/pr/merge`
`{ prUrl, mergeMethod: 'squash' }`, watch deploy. Useful: `pr/get-checks`,
`request`, `graphql` on the same package.
## Done → Discord
Always summarize (merged or not) via `kody:@kentcdodds/discord/send-shipped-pr`.
That export formats kind ship-pr, fetches Cursor token cost from the usage API,
and includes the model you pass. Never invent a dollar figure or a model id.
When the work deployed user-visible pages, put clickable links to those pages in
`extras` (see below) so Kent can open the live result from Discord.
**title (required):** a human headline of the change itself so the Discord post
is glanceable. Example: `OpenAPI spec fetches now count against daily quota`. Do
**not** use `ship owner/repo#N` as the title — repo, PR, and agent already
appear as links.
**difficulty (required):** `'Easy' | 'Medium' | 'Hard'`. Always pass it.
Distinct from Risk (merge authority). Easy = small/localized; Medium = several
files or real behavior change; Hard = architecture, migrations, subtle
correctness, or wide blast radius. The Discord export renders this on its own
line.
**agentId (required):**
- In a Cursor Cloud Agent VM, read it from the metadata socket:
`curl -fsS --unix-socket "${CURSOR_AGENT_SOCKET:-/run/cursor/api.sock}" http://cursor-agent/v1/meta-data/agent/id`
- Otherwise pass the `bc-` id from the agent URL you were launched as
(`https://cursor.com/agents/{id}`).
**model (deterministic — never infer):**
- In a Cursor Cloud Agent VM, read the model that **served this turn** from the
metadata socket (not a guess from writing style):
`curl -fsS --unix-socket "${CURSOR_AGENT_SOCKET:-/run/cursor/api.sock}" http://cursor-agent/v1/meta-data/turn/model`
If you selected Auto, this is the concrete model that served, not `Auto`. See
https://cursor.com/docs/cloud-agent/metadata
- Outside a managed VM, pass the `model.id` used at create/launch if you still
have that record.
- If the key is missing (`404` / empty), omit `model` so the export posts
`Model pending` — do **not** invent one.
**Deployed pages (when the work actually shipped UI/routes):**
- If merge+deploy produced live pages people can click, put those URLs in
`extras` as Discord markdown links (one per line item). Prefer the specific
routes/pages that changed, not only the site root.
- Skip this when nothing user-visible deployed (library-only, docs-only with no
hosted page, parked/blocked, or deploy not reached).
- Do **not** invent URLs. Only include pages you verified or that the deploy
output / PR preview / production URL clearly maps to.
```javascript
import sendShippedPr from 'kody:@kentcdodds/discord/send-shipped-pr'
export default async function main() {
return sendShippedPr({
agentId: 'bc-…', // metadata socket or launch URL
model: 'grok-4.6', // metadata turn/model (deterministic)
title: 'OpenAPI spec fetches now count against daily quota',
difficulty: 'Medium',
status: 'Shipped', // or Parked / Blocked
summary: 'One-screen what shipped and why it is done.',
prUrl: 'https://github.com/owner/repo/pull/123',
repo: 'owner/repo',
extras: [
'CI green',
'[Account](https://kody.codes/account)', // only when that page actually deployed
'[Connect](https://kody.codes/connect)',
],
})
}
```More from this repository
cleanup-after-migrationsSkill
>
conductSkill
>
control-kodySkill
>
orchestrateSkill
>
remixSkill
Build and review Remix 3 applications using the `remix` npm package and
testing-multi-worker-devSkill
How to run and test kody's multi-worker local dev (origin kody worker +
visual-recapSkill
Generate and maintain the system recap block in a PR description - a