# Create Pr

> Create a GitHub pull request with `gh pr create`. Title and body are English, AI-generated from the latest git commit (HEAD) plus the current branch vs the default base. Before push, rewrite commit messages with git commit-tree if they contain Cursor trailers. After create, re-apply a clean body and verify with gh pr view. Use only when the user explicitly asks to create a PR, open a pull request, run this skill, or invoke create-pr.

- Skill: `emiyaaaaa/create-pr` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add emiyaaaaa/create-pr`
- Raw SKILL.md: https://api.skillmd.com/api/skills/emiyaaaaa/create-pr/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: emiyaaaaa (https://skillmd.com/u/emiyaaaaa)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/emiyaaaaa/create-pr

---


# Create PR

从当前分支的 git 记录生成**英文**标题与正文，调用 `gh pr create` 开 PR。不要用 `--fill` / `--fill-first`。

## 对外文案（硬性）

**最终对外产物必须干净**，不是「自己别主动写」。

- 本环境跑 `git commit` 会注入 `Co-authored-by: Cursor <cursoragent@cursor.com>`。push **之前**必须 `git log -1 --format=%B`（以及 `base..HEAD` 全部 `%B`）。有 cursor 就跑 `scrub-commits.sh`（commit-tree 重写），不要把脏 commit push 出去。不要用 `git commit` 重做（会再注入）。
- `gh pr create` 之后平台可能在 body 尾部追加 `Made with [Cursor](https://cursor.com)`。create 之后必须立刻 `gh pr view`，并用 `scrub-pr.sh` 把 title/body 写回已知干净稿；再 `view` 一次，仍含 cursor 则失败，不要把 URL 当成功。

PR title/body、commit message **都不能带有任何 cursor 相关的字样**（大小写均禁），包括：`Cursor`、`cursor`、`.cursor`、`cursor.com`、Cursor Agent、Made with Cursor、Generated by Cursor、`Co-authored-by: Cursor`。HEAD 里若已有这些字，改写时去掉，不要原样抄进 PR。

禁止把 Cursor 写成协作者：不要 `--reviewer` / `--assignee` 填 Cursor，不要在 body 里 @ Cursor。

改动若是仓库 agent skill，对外只写 skill 名（如 `create-pr`），不要写工具目录路径。

## 何时执行

仅在用户显式要求创建 PR、打开 pull request、执行本 skill 时运行。不要在提交、推送、或闲聊里主动开 PR。切分支、暂存、commit 走 `create-branch` skill，不要在本 skill 里做。

## 工作流

按顺序执行。任一步失败则停下并说明原因，不要继续 `gh pr create`。

```
- [ ] 1. 收集 git 上下文
- [ ] 2. 预检（脏工作区 / 在默认分支 / 已有 PR）
- [ ] 3. 若 commit %B 含 cursor：`scrub-commits.sh` 后重新收集
- [ ] 4. 根据 git 记录生成 title + body，写入临时文件并自检
- [ ] 5. 如未跟踪远程则 push（仅在刚 rewrite 且已有 upstream 时允许 `--force-with-lease`）
- [ ] 6. `gh pr create`（--body-file）
- [ ] 7. `scrub-pr.sh`：view → 写回干净稿 → 再 view
- [ ] 8. 只有最终 view 干净才把 PR URL 回给用户
```

### 1. 收集 git 上下文

从仓库根目录执行 `.cursor/skills/create-pr/scripts/collect-context.sh`。它会打印：

- **HEAD**：上一条 git 记录（`git log -1 --format=fuller` + `%B` 全文含 trailer）
- 当前分支、默认 base、是否已 push、`range_has_cursor`
- `base...HEAD` 的 commit 列表与 diffstat
- 工作区是否干净

标题与正文**以上一条（HEAD）提交为主**。若该分支相对 base 还有更早提交，把它们并入 Changes / Test plan，不要只复述 HEAD 的 subject 而漏掉其余 diff。

需要补细节时再跑（不要打印带凭据的 remote URL）：

```bash
git show --format= --no-ext-diff HEAD
git diff --stat "${BASE}...HEAD"
```

`${BASE}` 用脚本输出的 default base（通常是 `origin/main`）。

### 2. 预检

| 情况 | 动作 |
|------|------|
| 当前就在默认分支（`main` / `master`） | 停止。请用户先执行 `create-branch`，或切到 feature 分支后再执行。 |
| 工作区有未提交改动 | 警告用户：PR 只包含已提交内容。不要擅自 commit。 |
| `gh pr view` 对该分支已有 **OPEN** 的 PR | 停止，返回已有 URL，不要再 create。MERGED / CLOSED 不挡。 |
| HEAD 与默认分支没有 diff | 停止，没有可开的 PR。 |
| `gh` 未登录 / 无权限 | 停止，说明要用 `gh auth status` 检查。 |
| `range_has_cursor: true` | **不要停止、不要 push。** 进入步骤 3 用 commit-tree 清 trailer。 |

禁止：改 git config、`--no-verify` / `--no-gpg-sign`、interactive rebase、`git add .`、`git commit`（会再注入 Cursor）。`--force` / `--force-with-lease` 仅步骤 5 在刚 rewrite 且已有 upstream 时允许。

### 3. 清掉 commit 上的 Cursor trailer

`range_has_cursor: true` 时必须执行；否则跳过。

```bash
.cursor/skills/create-pr/scripts/scrub-commits.sh "${BASE_REF}"
```

`${BASE_REF}` 用 collect-context 的 `base_ref`（通常 `origin/main`）。脚本对 `base..HEAD` 做线性 `commit-tree` 重写，去掉 message 里所有 cursor 行（含 `Co-authored-by: Cursor`）。

失败则停下。成功后**再跑一次** `collect-context.sh`，确认 `range_has_cursor: false`，并记下 `rewritten: true`。

不要 `git commit`、不要 `git commit --amend`、不要 soft reset 后再 `git commit`。

### 4. 生成 title 与 body

只根据收集到的 git 记录与 diff 生成，不要编造未出现的功能、文件或测试。

**Language: English only.** Title and body must be English, even if the git record, branch name, or user prompt is Chinese. Translate; do not copy non-English commit text into the PR.

**Title**

- English imperative sentence, ≤72 characters, no trailing period.
- 仓库已用 Conventional Commits（`feat:` / `fix:` / `docs:` 等）则沿用；HEAD subject 已经合适就微调复用，不要为了炫技重写。若 HEAD subject 不是英文，先译成英文再套 conventional prefix。
- 范围以 HEAD 为准：HEAD 是 bugfix 就不要写成巨大 refactor。

**Body（GitHub Flavored Markdown，多段式）**

必须用下面结构。空段删掉，不要留占位符。语气像给 reviewer 的简报：先 What+Why，再可扫的 Changes，最后可执行的 Test plan。

```markdown
## Summary

<1–3 条 bullet：做了什么、为什么。写意图，不要列文件名。>

## Changes

- <按主题分组的具体改动，点出行为 / API / schema / 兼容性>
- <必要时用 **Area:** 前缀，如 **Worker:** / **API:** / **Console:**>

## Test plan

- [ ] <可执行的验证步骤：命令、路径、手动操作>

## Notes

<可选：breaking change、rollout、follow-up、截图。没有就整段省略。>
```

风格约束：

- 用 GFM：`##` 标题、`-` 列表、`- [ ]` task list。需要折叠大段日志时才用 `<details>`。
- 关联 issue 写成 `Closes #123` / `Fixes #123`（仅当 git 记录或用户明确提到）。
- 不要写 “This PR …”、不要贴完整 diff、不要空话 checklist（“tested locally” 这种不算）。
- Test plan 要能在本仓库执行：点名 `backend/`、`backend-java/`、`frontend/` 等真实路径与命令。含 `cursor` 的路径不要写进 PR，改用 skill 名或功能描述。
- Title 和 body 一律英文。专有名词、代码标识符、路径保持原样（**例外：任何 cursor 字样都要去掉或改写**）；不要写中文段落或中英混排说明。
- 写入临时文件后自检：title、body **都不含** `cursor`（任何大小写），也没有 Cursor 协作者 / `Co-authored-by`。这只是输入稿；发布后还要再 view。

把 title / body 写到临时文件（不要用 `--fill`）：

```bash
TITLE_FILE="$(mktemp)"
BODY_FILE="$(mktemp)"
printf '%s\n' "${TITLE}" > "${TITLE_FILE}"
cat > "${BODY_FILE}" <<'EOF'
## Summary

- ...

## Changes

- ...

## Test plan

- [ ] ...

EOF
```

### 5. Push

先确认 `range_has_cursor: false`，否则回到步骤 3。分支未跟踪远程，或 local 超前 remote 时：

```bash
git push -u origin HEAD
```

仅当步骤 3 打印了 `rewritten: true` **并且** 该分支已有 upstream 时，才允许：

```bash
git push --force-with-lease
```

不要无条件 force。不要 push 到 `main`/`master`。

### 6. 创建 PR

用 `--title` + `--body-file`，不要 HEREDOC 嵌套进 `--body` 再以为发布稿就是它：

```bash
gh pr create --base "${BASE_NAME}" --title "$(cat "${TITLE_FILE}")" --body-file "${BODY_FILE}"
```

`${BASE_NAME}` 是短名（`main`），不是 `origin/main`。仅当用户明确要求 draft 时加 `--draft`。

### 7. 发布后立刻核对并清掉平台注入

`gh pr create` 返回 URL **不算完成**。立刻：

```bash
.cursor/skills/create-pr/scripts/scrub-pr.sh --title-file "${TITLE_FILE}" --body-file "${BODY_FILE}"
```

脚本会 `gh pr edit` 写回干净稿，再 `gh pr view`。title/body 仍含 cursor 则失败，**不要把 URL 发给用户当成功**。

不要跳过 view。不要以为 create 时传的 body 就是线上 body。

### 8. 收尾

只有 `scrub-pr.sh` 打印 `pr_clean: true` 后，才把 URL 发给用户。若 create 或 scrub 失败，贴错误并停下。

## 示例

HEAD: `feat: integrate Temporal backend for durable workflows`

Title: `feat: integrate Temporal backend for durable workflows`

```markdown
## Summary

- Add Temporal as an opt-in durable backend so agent runs survive worker restarts.
- Keep the existing Redis job path as the default when Temporal is unset.

## Changes

- **Worker:** Temporal workflow + worker process for `Run` execution.
- **API:** persist workflow id on the run; map cancel to the Temporal handle.
- **Config:** `TEMPORAL_TARGET` / task-queue settings; no change to the default adapter.

## Test plan

- [ ] `uv run pytest` in `backend/`
- [ ] Start API + Temporal worker, create a run, confirm it completes
- [ ] Kill the worker mid-run, restart, confirm the run resumes
- [ ] Cancel an in-flight run and confirm the Temporal workflow is cancelled
```

