make-changelog

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Changelog Generator

变更日志生成工具

Create or update
CHANGELOG.md
from git history using Keep-a-Changelog format. Launch one haiku subagent per version range for parallel, token-efficient processing.
基于Git历史,按照Keep-a-Changelog格式创建或更新
CHANGELOG.md
文件。 为每个版本范围启动一个Haiku子代理,以实现并行、高效的令牌处理。

Step 1 — Assess Project State

步骤1 — 评估项目状态

Run the range-planning script to validate the repo and gather all version ranges:
bash
python3 ${CLAUDE_PLUGIN_ROOT}/skills/make-changelog/scripts/list_ranges.py --output json
  • Exit 2 = not a git repository, or repository has no commits. Stop and report the error message from stderr to the user.
  • Exit 0 = proceed. JSON output contains all ranges the skill would cover.
Also check for an existing changelog:
bash
ls CHANGELOG.md CHANGELOG 2>/dev/null
If
CHANGELOG.md
exists, read it to identify the last documented version (the most recent
## [x.y.z]
heading).
运行范围规划脚本以验证仓库并收集所有版本范围:
bash
python3 ${CLAUDE_PLUGIN_ROOT}/skills/make-changelog/scripts/list_ranges.py --output json
  • 退出码2 = 不是Git仓库,或仓库无提交。停止执行并将stderr中的错误信息反馈给用户。
  • 退出码0 = 继续执行。JSON输出包含此Skill将覆盖的所有范围。
同时检查是否存在现有变更日志:
bash
ls CHANGELOG.md CHANGELOG 2>/dev/null
如果
CHANGELOG.md
存在,读取文件以确定最后记录的版本(最新的
## [x.y.z]
标题)。

Step 2 — Determine Scope

步骤2 — 确定范围

No tags exist: Script returns a single Unreleased range. Proceed in fresh mode.
Tags exist, no CHANGELOG.md: Fresh mode — process all ranges the script returned.
Tags exist, CHANGELOG.md exists: Fill mode — re-run the script with
--since-tag
to get only the uncovered ranges:
bash
python3 ${CLAUDE_PLUGIN_ROOT}/skills/make-changelog/scripts/list_ranges.py \
  --since-tag <last_documented_tag> --output json
If the intent is ambiguous (user said "update changelog" but the file has extensive existing content), ask the user to choose:
  • "Fill missing only" — add new versions/unreleased since last entry
  • "Rebuild from scratch" — regenerate the full file from git history
  • "Unreleased only" — refresh only the
    [Unreleased]
    section
无标签存在: 脚本返回一个单一的Unreleased(未发布)范围。以全新模式继续。
存在标签,但无CHANGELOG.md: 全新模式 — 处理脚本返回的所有范围。
存在标签且CHANGELOG.md存在: 填充模式 — 使用
--since-tag
参数重新运行脚本,仅获取未覆盖的范围:
bash
python3 ${CLAUDE_PLUGIN_ROOT}/skills/make-changelog/scripts/list_ranges.py \
  --since-tag <last_documented_tag> --output json
如果意图不明确(用户说“更新变更日志”但文件已有大量现有内容),请询问用户选择:
  • "仅填充缺失内容" — 添加上次条目之后的新版本/未发布内容
  • "从头重建" — 从Git历史重新生成完整文件
  • "仅处理未发布内容" — 仅刷新
    [Unreleased]
    部分

Step 3 — Plan Subagents

步骤3 — 规划子代理

Inspect the JSON output from Step 1 or 2. Each range object has:
  • label
    — version string (
    1.2.0
    or
    Unreleased
    )
  • from_ref
    — lower git ref (empty string = from initial commit)
  • to_ref
    — upper git ref
  • date
    — tag date or today
  • commit_count
    — number of commits in range
Skip ranges where
commit_count == 0
— no subagent needed.
Cap at 12 subagents. If the non-empty range list exceeds 12, ask the user whether to limit to the most recent 12 or process all (noting it will take longer).
检查步骤1或2中的JSON输出。每个范围对象包含:
  • label
    — 版本字符串(如
    1.2.0
    Unreleased
  • from_ref
    — Git起始引用(空字符串 = 从初始提交开始)
  • to_ref
    — Git结束引用
  • date
    — 标签日期或当前日期
  • commit_count
    — 范围内的提交数量
跳过
commit_count == 0
的范围
— 无需子代理处理。
最多使用12个子代理。如果非空范围列表超过12个,请询问用户是限制为最近12个范围还是处理所有范围(注意处理所有范围耗时更长)。

Step 4 — Launch Haiku Subagents

步骤4 — 启动Haiku子代理

Spawn one Task per non-empty range in a single message (parallel). Use
model: "haiku"
for all subagents. Each subagent receives this self-contained prompt (substitute values from the range object):
You are generating one section of a CHANGELOG.md.

Version: [label]
Date: [date]
Git command: git log [from_ref]..[to_ref] --format="%s"
(If from_ref is empty, use: git log [to_ref] --format="%s")

Categorize by user-observable impact, not by commit prefix. The conventional
commit prefix (feat:, fix:, etc.) is a hint only — a commit labelled "feat:"
that clearly corrects a bug belongs in Fixed, not Added. Use the prefix as a
starting signal and override it when the commit subject contradicts it.

Sections and classification signals:
- Added: new capabilities users can invoke (add, introduce, implement, support)
- Changed: modified behavior of existing features (update, change, refactor, improve)
- Deprecated: features explicitly flagged for future removal
- Removed: capabilities or endpoints deleted (remove, drop, delete)
- Fixed: bugs corrected, regardless of prefix (fix, resolve, patch, correct, hotfix)
- Security: vulnerability patches (security, CVE, sanitize, escape)

Skip: merge commits, CI/CD configuration changes, version-bump commits,
formatting-only changes.

Use present tense, imperative mood: "Add X", not "Added X" or "adds X".
Omit empty sections. Omit internal variable names and implementation details.

Output ONLY the markdown block, no preamble:
单条消息中为每个非空范围生成一个任务(并行执行)。所有子代理使用
model: "haiku"
。每个子代理接收以下独立提示(替换范围对象中的值):
你正在生成CHANGELOG.md的一个章节。

版本:[label]
日期:[date]
Git命令:git log [from_ref]..[to_ref] --format="%s"
(如果from_ref为空,使用:git log [to_ref] --format="%s")

按用户可观察的影响分类,而非提交前缀。常规提交前缀(feat:、fix:等)仅作为参考 — 标记为"feat:"但明显是修复bug的提交应归入Fixed(修复)类别,而非Added(新增)。将前缀作为初始信号,当提交主题与前缀矛盾时优先遵循主题。

章节与分类信号:
- Added:用户可调用的新功能(add、introduce、implement、support)
- Changed:现有功能的行为修改(update、change、refactor、improve)
- Deprecated:明确标记为未来移除的功能
- Removed:已删除的功能或端点(remove、drop、delete)
- Fixed:已修复的bug,无论前缀如何(fix、resolve、patch、correct、hotfix)
- Security:漏洞补丁(security、CVE、sanitize、escape)

跳过:合并提交、CI/CD配置变更、版本号更新提交、仅格式变更的提交。

使用现在时、祈使语气:"Add X",而非"Added X"或"adds X"。
省略空章节。省略内部变量名和实现细节。

仅输出Markdown块,无需前置说明:

[VERSION] - DATE

[VERSION] - DATE

Added

Added

  • ...
  • ...

Fixed

Fixed

  • ...

Collect all Task results before Step 5.
  • ...

在进入步骤5之前收集所有任务结果。

Step 5 — Assemble Changelog

步骤5 — 组装变更日志

Order version blocks newest-first. Full document structure:
markdown
undefined
版本块按从新到旧的顺序排列。完整文档结构:
markdown
undefined

Changelog

Changelog

All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

[Unreleased]

[content from unreleased subagent, or omit section if empty]
[未发布子代理生成的内容,若为空则省略此章节]

[1.2.0] - 2024-03-15

[1.2.0] - 2024-03-15

[content from subagent]

**Fill mode:** Insert new version sections immediately after the `# Changelog` header
block, before the first existing `## [` entry. Preserve all existing content exactly.

**Fresh/rebuild mode:** Write the complete file.
[子代理生成的内容]

**填充模式:** 将新版本章节插入到`# Changelog`标题块之后、第一个现有`## [`条目之前。严格保留所有现有内容。

**全新/重建模式:** 写入完整文件。

Step 6 — Write and Report

步骤6 — 写入并报告

Fresh mode: Write
CHANGELOG.md
. Confirm overwrite with
AskUserQuestion
if the file already exists.
Fill mode: Use
Edit
to insert new sections at the correct position.
After writing, report:
  • Mode used (fresh / fill / unreleased-only)
  • Versions covered (label, date, commit count — from script output)
  • Number of subagents used
  • Any ranges that were empty (skipped)
  • Any commits that could not be confidently categorized (flag for user review)
全新模式: 写入
CHANGELOG.md
。如果文件已存在,使用
AskUserQuestion
确认是否覆盖。
填充模式: 使用
Edit
操作在正确位置插入新章节。
写入完成后,报告以下内容:
  • 使用的模式(全新/填充/仅未发布)
  • 覆盖的版本(标签、日期、提交数量 — 来自脚本输出)
  • 使用的子代理数量
  • 任何被跳过的空范围
  • 任何无法确定分类的提交(标记供用户审核)

Scripts

脚本

scripts/list_ranges.py
— queries git tags and computes version ranges. Invoked in Steps 1 and 2. Exit 2 = repo invalid or empty; exit 0 = success.
bash
undefined
scripts/list_ranges.py
— 查询Git标签并计算版本范围。在步骤1和2中调用。退出码2 = 仓库无效或为空;退出码0 = 执行成功。
bash
undefined

All ranges (text preview)

所有范围(文本预览)

python3 ${CLAUDE_PLUGIN_ROOT}/skills/make-changelog/scripts/list_ranges.py
python3 ${CLAUDE_PLUGIN_ROOT}/skills/make-changelog/scripts/list_ranges.py

All ranges (JSON for skill use)

所有范围(供Skill使用的JSON格式)

python3 ${CLAUDE_PLUGIN_ROOT}/skills/make-changelog/scripts/list_ranges.py --output json
python3 ${CLAUDE_PLUGIN_ROOT}/skills/make-changelog/scripts/list_ranges.py --output json

Fill mode: only ranges newer than a specific tag

填充模式:仅获取特定标签之后的范围

python3 ${CLAUDE_PLUGIN_ROOT}/skills/make-changelog/scripts/list_ranges.py
--since-tag v1.2.0 --output json
undefined
python3 ${CLAUDE_PLUGIN_ROOT}/skills/make-changelog/scripts/list_ranges.py
--since-tag v1.2.0 --output json
undefined