你打开 Codex 的 PR:title 是 “Update components”,body 是 “Refactored several components for better readability”——完。12 个文件、400 行 diff,没说改了什么、为什么、怎么测的。Reviewer 现在只能冷读全部 diff,没有作者意图作为参照。
**最快的修法:**加一个 .github/pull_request_template.md,写清你要的每一节,再在 AGENTS.md 里要求 Codex 从自己的 commit log 把每节填满。如果你是从 Codex Cloud 网页端(“Create PR” 按钮)发 PR,还有一个坑下面会讲:截至 2026 年 6 月,那个按钮不会自动套用你 repo 的 PR template,所以你还得让 agent 通过 gh CLI 来开 PR。
这不是 Codex 能力问题。让它写一份好 PR 描述完全办得到,默认糟糕是因为大多数 repo 没有 PR template、AGENTS.md 没写描述格式,model 就用最泛的语气填空。
先对号入座
| 现象 | 最可能的原因 | 跳到 |
|---|---|---|
| template 存在,但只有网页端发的 PR 不套用 | Cloud “Create PR” 按钮绕过了 template | 原因 1 |
ls .github/pull_request_template.md 是空的 | repo 里没有 PR template | 原因 2 |
| template 填上了,但每节都很泛 | AGENTS.md 没写 PR 格式规则 | 原因 3 |
| PR body 详细度跟你那行任务 prompt 一致 | 瓶颈在 prompt | 原因 4 |
| GitHub 上的 body 比 agent transcript 短 | harness 把 body 截断了 | 原因 5 |
| PR body 和第一个 commit subject 一字不差 | agent 复用了 commit message | 原因 6 |
常见原因
1. Codex Cloud “Create PR” 按钮跳过了 template
这个最容易漏,因为 template 确实在 repo 里,从 CLI 发的 PR 也好好的。截至 2026 年 6 月,Codex Cloud 网页端的 “Create PR” 按钮会把它自己生成的 summary 直接写进 PR body,并不套用 .github/pull_request_template.md(upstream 跟踪在 openai/codex issue #6750)。于是你的 Fixes #123 行和各节标题都不会出现,PR 也不会在 merge 时自动关掉关联的 issue。
同一个任务走 Codex CLI(codex 通过 gh pr create --template ... 开 PR)则会正确填上 template。这个差异就是判断点。
如何判断:手动开的 PR 和 CLI 开的 PR 都能渲染出 template,唯独 cloud agent 按钮开的 PR 缺了每一节。修法在 Step 1(用 CLI 开 PR,别用按钮)。
2. Repo 没有 PR template
GitHub “New pull request” 弹出来是空的。Codex 没锚点,写一句话就发了。
如何判断:ls .github/pull_request_template.md 没东西(也检查一下 repo 根目录和 docs/)。PR 描述直接从 model 的散文开始。
3. AGENTS.md 没写 PR 描述格式
Codex 读 AGENTS.md 拿 repo 约定。这个文件一句都没写 PR 格式,agent 就退回训练数据里的 default,通常很泛。
如何判断:grep -i 'pull request\|pr description\|pr body' AGENTS.md 没结果。
4. 任务 prompt 本身就一行
你说 “修一下 date picker 的 bug”。Codex 写的 PR body 详细度大约等于你的 prompt。短输入短输出。
如何判断:对比 Codex 任务描述和 PR body。都是一句话——瓶颈在 prompt。
5. Harness 把 PR body 截断了
有些 Codex wrapper 走 CLI flag 传 body,有长度上限;或者中间经过 script 把换行抹掉。Model 写得很详细,上传那一步被截了。(注意:gh pr create --body 本身没有实际意义上的长度上限,所以要怀疑的是自定义 wrapper,不是 gh。)
如何判断:对比 git log(或 agent transcript)里看到的 body 和 GitHub 上的 body。GitHub 上短,就是 harness 吃了。
6. Codex 把第一个 commit message 当成了 body
没有其他指引时 agent 会复制第一个 commit subject 同时当 title 和 body。结果 PR body 和 commit subject 完全一样,没有展开。
如何判断:看 PR body 是不是等于第一个 commit message。是的话,prompt 或 harness 没要求更丰富的 body。
最短修复路径
Step 1:写 PR template 并强制套用
新建 .github/pull_request_template.md。GitHub 认这个文件的三个位置:repo 根目录、.github/ 或 docs/;文件名大小写不敏感(pull_request_template.md 和 PULL_REQUEST_TEMPLATE.md 都行)。template 只有在 merge 进默认分支后才生效,所以测之前先把它提交到 main。
## 改了什么
<一段总结>
## 为什么
<问题、动机、或关联的 issue>
## Before / After
<行为变化的话:写清楚或贴图 before 和 after>
## 怎么测的
- [ ] `npm test` 本地通过
- [ ] 手动检查:<步骤>
- [ ] 新增测试覆盖:<场景>
## 风险
<什么可能坏,谁依赖被改的代码>
## 相关
<关联 issue、关联 PR>
手动开和 CLI 开的 PR,GitHub 会自动把这份 template 填到 body,Codex 看到空的 section 会填。
如果你用 Codex Cloud 的 “Create PR” 按钮,template 不会自动套用(原因 1)。改成强制走 CLI 开 PR,template 才会被尊重。最干净的位置是你的 Codex Cloud 环境 setup script(比如 scripts/codex/cloud/startup.sh),可以包一层 gh,让每个 PR 都带上 template:
gh pr create --template .github/pull_request_template.md
然后在 AGENTS.md 里加一行,让 agent 走 CLI 而不是网页按钮:
Always open pull requests with `gh pr create --template .github/pull_request_template.md`.
Do not use the Codex web "Create PR" button, which skips the template.
Step 2:AGENTS.md 写要求
追加到 AGENTS.md:
## PR 描述
你开的每个 PR 都必须严格遵循 `.github/pull_request_template.md`。每节都填。具体:
- **改了什么**:列出对用户可见的行为变化,或者按 file path 列结构性变化。
不要写 "重构组件"——要写 "把 `useSession` 从 `Header.tsx` 抽出来,
dashboard 可以复用了"。
- **为什么**:有 issue 就链,没有就描述 bug / 需求。
- **Before / After**:UI 或行为变化要展示两个状态。
- **怎么测的**:列具体跑过的命令,不要写 "本地测过了"。
- **风险**:至少指出一个可能坏的地方。
某节不适用时写 "N/A — <原因>",不许留空。
这样把 template 变成强制结构。
Step 3:用 commit log 起草 body
AGENTS.md 里加:
起草 PR body 时,"改了什么" 一节基于 commit log:
git log --reverse origin/main..HEAD --pretty=format:'- %s'
每个 commit 变成一条 bullet。然后每条 bullet 用一句话扩展 context。
这样 PR body 和真实改动对得上。
agent 写描述就有具体素材了,不是 vibes。
Step 4:CI 验证描述长度
加 workflow 拦短 body:
# .github/workflows/pr-description.yml
name: PR description check
on:
pull_request:
types: [opened, edited, synchronize]
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Require non-trivial description
env:
BODY: ${{ github.event.pull_request.body }}
run: |
if [ -z "$BODY" ] || [ ${#BODY} -lt 200 ]; then
echo "PR body 太短(需要 200+ 字符)。用 template。"
exit 1
fi
for section in "改了什么" "为什么" "怎么测的"; do
if ! echo "$BODY" | grep -q "$section"; then
echo "缺少节:$section"
exit 1
fi
done
这个 workflow 设为 required status check,Codex 一句话 body 就 merge 不了。
Step 5:写更好的任务 prompt
agent 镜像你的 prompt 详细度。用 prompt template:
TITLE: <一句话,祈使句>
CONTEXT: <为什么重要,链 issue>
SCOPE: <文件 / glob>
ACCEPTANCE:
- <具体测试或行为 1>
- <具体测试或行为 2>
NOTES FOR PR BODY:
- "Before / After" 一节提到 <X>
- 链 issue #<N>
Codex 把这些 note 翻译成 PR section。
怎么确认修好了
用你平时的 Codex 流程开一个新 PR,然后在 GitHub 的 PR 页面上(不是 transcript 里)检查:
- body 包含 template 的每个标题(
改了什么、为什么、怎么测的等),没有留空。 改了什么列的是具体 file path 或行为,不是 “重构组件”。怎么测的写的是真正跑过的命令(比如npm test),不是 “本地测过了”。- 如果你链了 issue,PR 的 “Development” 处应该显示它,并在 merge 时自动关闭(也就是 Cloud 按钮以前会丢掉的那行
Fixes #N)。 PR description checkworkflow 是绿勾,不是红叉。
如果第 5 步是红的但 body 看着没问题,是你的节标题和 workflow grep 的字符串对不上;把它们改成完全一致。
FAQ
为什么 CLI 能套上 template,网页按钮不行?
截至 2026 年 6 月,Codex Cloud “Create PR” 按钮会把它自己的 auto-summary 写进 body,跳过 .github/pull_request_template.md(openai/codex #6750)。CLI 走的是 gh pr create,会套用 template。在 OpenAI 修好之前,把开 PR 的动作走 CLI(Step 1)。
这是 AGENTS.md 还是 CLAUDE.md 控制的?
Codex 读 AGENTS.md。PR 格式规则放那里。CLAUDE.md 是 Claude Code 的文件,Codex 不读;如果你两个 agent 都用,把 PR 格式那块放在 AGENTS.md,在 CLAUDE.md 里引用它。
body 已经很详细了,但 title 还是 “Update components”,怎么修标题?
在 AGENTS.md 里加一条 title 规则(“PR title = 祈使句总结,60 字符以内,不要只用 Update/Refactor 这种泛动词”),让 agent 从最重要的那个 commit 取,而不是第一个。
不加 CI 关卡能不能强制 template? 能,但没有东西去执行它。是 required status check(Step 4)才真正挡住一句话 body 进 merge。再配 branch protection,绿勾就变成必须的。
GitHub 到哪找 template,我的为什么不加载?
根目录、.github/ 或 docs/,文件名 pull_request_template.md(大小写不敏感)。最常见的坑:它只有在 merge 进默认分支后才生效,所以只活在 feature 分支上的 template 不会填进来。
预防
- 把
.github/pull_request_template.md提交进 repo 的默认分支,节就是你真正想要的那些 AGENTS.md要求填每一节,不许无理由的 “N/A”- Codex Cloud 上用
gh pr create --template开 PR,别用网页按钮 - 让 agent 用
git log起草 “改了什么”,不要新写一份总结 - CI 检查 PR body 长度和节标题,设为 required status check
- 任务 prompt 也用结构化模板,agent 才有 PR body 素材
- 看 GitHub 上的真实 body,不只是 transcript——harness 可能截断