@releasekit/notes 0.3.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,15 +1,21 @@
1
1
  # @releasekit/notes
2
2
 
3
- Release notes and changelog generation from conventional commits with LLM-powered enhancement and flexible templating
3
+ [![@releasekit/notes](https://img.shields.io/badge/@releasekit-notes-9feaf9?labelColor=1a1a1a&style=plastic)](https://www.npmjs.com/package/@releasekit/notes)
4
+ [![Version](https://img.shields.io/npm/v/@releasekit/notes?color=28a745&labelColor=1a1a1a)](https://www.npmjs.com/package/@releasekit/notes)
5
+ [![Downloads](https://img.shields.io/npm/dw/@releasekit/notes?color=6f42c1&labelColor=1a1a1a)](https://www.npmjs.com/package/@releasekit/notes)
6
+
7
+ **Changelog and release notes generation from conventional commits**
8
+
9
+ Generates CHANGELOG.md and release notes from `@releasekit/version` output, with optional LLM-powered enhancement and flexible templating.
4
10
 
5
11
  ## Features
6
12
 
7
- - **Multiple input sources** — `@releasekit/version` JSON, git log, or manual JSON
8
- - **Flexible templating** — Liquid, Handlebars, or EJS with single-file or composable templates
9
- - **LLM enhancement** (optional) summarize, categorize, enhance descriptions, generate release notes
10
- - **Monorepo support** — root aggregation, per-package changelogs, or both
11
- - **Multiple outputs** — Markdown, JSON, or GitHub Releases API
12
- - **Dry-run mode** — preview without writing files
13
+ - 📝 **Conventional changelog** — Keep a Changelog, Angular, or custom format
14
+ - 🤖 **LLM enhancement** (optional) enhance descriptions, summarize, categorize, or generate prose release notes
15
+ - 🎨 **Flexible templating** — Liquid, Handlebars, or EJS; single-file or composable layout
16
+ - 📦 **Monorepo support** — root aggregation, per-package changelogs, or both
17
+ - 🔀 **Two outputs** — `CHANGELOG.md` and `RELEASE_NOTES.md` are configured independently
18
+ - 🔍 **Dry-run mode** — preview without writing files
13
19
 
14
20
  ## Installation
15
21
 
@@ -19,7 +25,7 @@ npm install -g @releasekit/notes
19
25
  pnpm add -g @releasekit/notes
20
26
  ```
21
27
 
22
- > **Note:** This package is ESM only and requires Node.js 20+.
28
+ > **Note:** ESM only. Requires Node.js 20+.
23
29
 
24
30
  ## Quick Start
25
31
 
@@ -30,107 +36,122 @@ releasekit-version --json | releasekit-notes
30
36
  # From a file
31
37
  releasekit-notes --input version-data.json
32
38
 
33
- # With LLM enhancement
34
- releasekit-notes --input version-data.json --llm-provider openai --llm-model gpt-4o-mini
35
-
36
39
  # Preview without writing
37
40
  releasekit-notes --dry-run
41
+
42
+ # With LLM enhancement
43
+ releasekit-notes --input version-data.json \
44
+ --llm-provider openai \
45
+ --llm-model gpt-4o-mini \
46
+ --llm-tasks enhance,summarize
38
47
  ```
39
48
 
40
49
  ## CLI Reference
41
50
 
51
+ ### `releasekit-notes generate` (default)
52
+
42
53
  | Flag | Description | Default |
43
54
  |------|-------------|---------|
44
55
  | `-i, --input <file>` | Input file path | stdin |
45
- | `-o, --output <spec>` | Output spec (`format:file`) | config |
56
+ | `--changelog-mode <mode>` | Changelog location: `root`, `packages`, `both` | `root` |
57
+ | `--changelog-file <name>` | Changelog file name override | `CHANGELOG.md` |
58
+ | `--no-changelog` | Disable changelog generation | — |
59
+ | `--release-notes-mode <mode>` | Enable release notes file output: `root`, `packages`, `both` | — |
60
+ | `--release-notes-file <name>` | Release notes file name override | `RELEASE_NOTES.md` |
61
+ | `--no-release-notes` | Disable release notes generation | — |
46
62
  | `-t, --template <path>` | Template file or directory | built-in |
47
63
  | `-e, --engine <engine>` | Template engine: `handlebars`, `liquid`, `ejs` | `liquid` |
48
64
  | `--monorepo <mode>` | Monorepo mode: `root`, `packages`, `both` | — |
49
65
  | `--llm-provider <name>` | LLM provider | — |
50
66
  | `--llm-model <model>` | LLM model | — |
51
- | `--llm-tasks <tasks>` | Comma-separated LLM tasks | — |
52
- | `--no-llm` | Disable LLM processing | `false` |
67
+ | `--llm-base-url <url>` | Base URL for openai-compatible providers | — |
68
+ | `--llm-tasks <tasks>` | Comma-separated tasks: `enhance`, `summarize`, `categorize`, `release-notes` | — |
69
+ | `--no-llm` | Disable LLM processing | — |
70
+ | `--target <package>` | Filter to a specific package name | — |
53
71
  | `--config <path>` | Config file path | `releasekit.config.json` |
72
+ | `--regenerate` | Regenerate entire file instead of prepending | `false` |
54
73
  | `--dry-run` | Preview without writing | `false` |
55
- | `--regenerate` | Regenerate entire changelog | `false` |
56
- | `-v, --verbose` | Verbose logging | `false` |
57
- | `-q, --quiet` | Suppress non-error output | `false` |
58
-
59
- ## Subcommands
60
-
61
- ### `releasekit-notes init`
62
-
63
- Create a default configuration file.
64
-
65
- ```bash
66
- releasekit-notes init [--force]
67
- ```
74
+ | `-v, --verbose` | Verbose logging (repeat for more: `-vv`) | — |
75
+ | `-q, --quiet` | Suppress non-error output | |
68
76
 
69
77
  ### `releasekit-notes auth <provider>`
70
78
 
71
- Configure API key for an LLM provider.
79
+ Store an API key for an LLM provider.
72
80
 
73
81
  ```bash
74
- releasekit-notes auth openai --key sk-...
75
- releasekit-notes auth anthropic
82
+ releasekit-notes auth openai
83
+ releasekit-notes auth anthropic --key sk-ant-...
76
84
  ```
77
85
 
86
+ Keys are saved to `~/.config/releasekit/auth.json`.
87
+
78
88
  ### `releasekit-notes providers`
79
89
 
80
90
  List available LLM providers.
81
91
 
82
92
  ## Configuration
83
93
 
84
- Configure via `releasekit.config.json`:
94
+ All options live under the `notes` key in `releasekit.config.json`:
85
95
 
86
96
  ```json
87
97
  {
98
+ "$schema": "https://goosewobbler.github.io/releasekit/schema.json",
88
99
  "notes": {
89
- "output": [
90
- { "format": "markdown", "file": "CHANGELOG.md" }
91
- ],
92
- "updateStrategy": "prepend",
93
- "templates": {
94
- "path": "./templates/",
95
- "engine": "liquid"
100
+ "changelog": {
101
+ "mode": "root",
102
+ "file": "CHANGELOG.md",
103
+ "templates": {
104
+ "path": "./templates/changelog/",
105
+ "engine": "liquid"
106
+ }
96
107
  },
97
- "llm": {
98
- "provider": "openai",
99
- "model": "gpt-4o-mini",
100
- "tasks": {
101
- "summarize": true,
102
- "enhance": true
108
+ "releaseNotes": {
109
+ "mode": "root",
110
+ "llm": {
111
+ "provider": "openai",
112
+ "model": "gpt-4o-mini",
113
+ "tasks": {
114
+ "enhance": true,
115
+ "summarize": true
116
+ }
103
117
  }
104
- }
118
+ },
119
+ "updateStrategy": "prepend"
105
120
  }
106
121
  }
107
122
  ```
108
123
 
124
+ `changelog` and `releaseNotes` are configured independently. Set either to `false` to disable it entirely.
125
+
109
126
  ## LLM Providers
110
127
 
111
- | Provider | Config Key | Notes |
112
- |----------|------------|-------|
113
- | OpenAI | `openai` | Requires `OPENAI_API_KEY` |
114
- | Anthropic | `anthropic` | Requires `ANTHROPIC_API_KEY` |
115
- | Ollama | `ollama` | Local, no API key needed |
116
- | OpenAI-Compatible | `openai-compatible` | Any OpenAI-compatible endpoint |
128
+ LLM configuration lives under `notes.releaseNotes.llm`:
129
+
130
+ | Provider | Key | Auth |
131
+ |----------|-----|------|
132
+ | OpenAI | `openai` | `OPENAI_API_KEY` or `releasekit-notes auth openai` |
133
+ | Anthropic | `anthropic` | `ANTHROPIC_API_KEY` or `releasekit-notes auth anthropic` |
134
+ | Ollama | `ollama` | None (local) |
135
+ | OpenAI-compatible | `openai-compatible` | Varies — set `baseURL` and `apiKey` |
117
136
 
118
137
  ### LLM Tasks
119
138
 
120
- | Task | Description |
139
+ | Task | What it does |
121
140
  |------|-------------|
122
- | `enhance` | Improve entry descriptions |
123
- | `summarize` | Create version summary |
124
- | `categorize` | Group entries by category |
125
- | `releaseNotes` | Generate release notes |
141
+ | `enhance` | Rewrites each changelog entry description to be clearer |
142
+ | `summarize` | Generates a one-paragraph summary of the release |
143
+ | `categorize` | Groups entries into user-friendly categories (Features, Fixes, …) |
144
+ | `releaseNotes` | Generates full prose release notes (use as GitHub release body) |
126
145
 
127
146
  ## Templates
128
147
 
129
- ### Built-in
148
+ ### Built-in Templates
130
149
 
131
- - `keep-a-changelog` Keep a Changelog format (default)
132
- - `angular` — Angular-style changelog
133
- - `github-release` GitHub release notes
150
+ | Name | Engine | Description |
151
+ |------|--------|-------------|
152
+ | `keep-a-changelog` | Liquid | [Keep a Changelog](https://keepachangelog.com) format (default) |
153
+ | `angular` | Handlebars | Angular-style changelog |
154
+ | `github-release` | EJS | GitHub release notes format |
134
155
 
135
156
  ### Custom Templates
136
157
 
@@ -138,32 +159,37 @@ Configure via `releasekit.config.json`:
138
159
  # Single file
139
160
  releasekit-notes --template ./my-changelog.liquid
140
161
 
141
- # Composable directory
162
+ # Composable directory (document + version + entry)
142
163
  releasekit-notes --template ./templates/
143
164
  ```
144
165
 
145
- Composable directory structure:
146
-
147
- ```
148
- templates/
149
- ├── document.liquid
150
- ├── version.liquid
151
- └── entry.liquid
152
- ```
166
+ See **[Templates guide](./docs/templates.md)** for the full template context reference and authoring guide.
153
167
 
154
168
  ## Monorepo Support
155
169
 
156
170
  ```bash
157
171
  # Root changelog only (aggregates all packages)
158
- releasekit-notes --monorepo root
172
+ releasekit-notes --changelog-mode root
159
173
 
160
174
  # Per-package changelogs
161
- releasekit-notes --monorepo packages
175
+ releasekit-notes --changelog-mode packages
162
176
 
163
- # Both
164
- releasekit-notes --monorepo both
177
+ # Both root and per-package
178
+ releasekit-notes --changelog-mode both
165
179
  ```
166
180
 
181
+ See **[Monorepo guide](./docs/monorepo.md)** for details on file placement and aggregation behaviour.
182
+
183
+ ## Documentation
184
+
185
+ **Getting Started**
186
+ - [Configuration reference](./docs/configuration.md) — all `notes.*` options
187
+ - [LLM providers](./docs/llm-providers.md) — provider setup, auth, tasks, prompt customisation
188
+
189
+ **Guides**
190
+ - [Templates](./docs/templates.md) — custom template authoring and context reference
191
+ - [Monorepo](./docs/monorepo.md) — per-package and root output modes
192
+
167
193
  ## License
168
194
 
169
195
  MIT
@@ -3,8 +3,8 @@ import {
3
3
  detectMonorepo,
4
4
  splitByPackage,
5
5
  writeMonorepoChangelogs
6
- } from "./chunk-DCQ32FVH.js";
7
- import "./chunk-E4454SIS.js";
6
+ } from "./chunk-F7MUVHZ2.js";
7
+ import "./chunk-7TJSPQPW.js";
8
8
  export {
9
9
  aggregateToRoot,
10
10
  detectMonorepo,
@@ -213,7 +213,7 @@ function writeMarkdown(outputPath, contexts, config, dryRun, options) {
213
213
  process.stdout.write(content);
214
214
  return;
215
215
  }
216
- if (config.updateStrategy === "prepend" && fs2.existsSync(outputPath) && contexts.length === 1) {
216
+ if (config.updateStrategy !== "regenerate" && fs2.existsSync(outputPath) && contexts.length === 1) {
217
217
  const firstContext = contexts[0];
218
218
  if (firstContext) {
219
219
  const updated = prependVersion(outputPath, firstContext, options);
@@ -5,7 +5,7 @@ import {
5
5
  prependVersion,
6
6
  renderMarkdown,
7
7
  success
8
- } from "./chunk-E4454SIS.js";
8
+ } from "./chunk-7TJSPQPW.js";
9
9
 
10
10
  // src/monorepo/aggregator.ts
11
11
  import * as fs from "fs";
@@ -57,11 +57,11 @@ function aggregateToRoot(contexts) {
57
57
  function writeMonorepoChangelogs(contexts, options, config, dryRun) {
58
58
  const files = [];
59
59
  if (options.mode === "root" || options.mode === "both") {
60
- const rootPath = path.join(options.rootPath, "CHANGELOG.md");
60
+ const rootPath = path.join(options.rootPath, options.fileName ?? "CHANGELOG.md");
61
61
  const fmtOpts = { includePackageName: true };
62
62
  info(`Writing root changelog to ${rootPath}`);
63
63
  let rootContent;
64
- if (config.updateStrategy === "prepend" && fs.existsSync(rootPath)) {
64
+ if (config.updateStrategy !== "regenerate" && fs.existsSync(rootPath)) {
65
65
  const newSections = contexts.map((ctx) => formatVersion(ctx, fmtOpts)).join("\n");
66
66
  const existing = fs.readFileSync(rootPath, "utf-8");
67
67
  const headerEnd = existing.indexOf("\n## ");
@@ -87,9 +87,9 @@ ${existing.slice(headerEnd + 1)}`;
87
87
  const simpleName = packageName.split("/").pop();
88
88
  const packageDir = packageDirMap.get(packageName) ?? (simpleName ? packageDirMap.get(simpleName) : void 0) ?? null;
89
89
  if (packageDir) {
90
- const changelogPath = path.join(packageDir, "CHANGELOG.md");
90
+ const changelogPath = path.join(packageDir, options.fileName ?? "CHANGELOG.md");
91
91
  info(`Writing changelog for ${packageName} to ${changelogPath}`);
92
- const pkgContent = config.updateStrategy === "prepend" && fs.existsSync(changelogPath) ? prependVersion(changelogPath, ctx) : renderMarkdown([ctx]);
92
+ const pkgContent = config.updateStrategy !== "regenerate" && fs.existsSync(changelogPath) ? prependVersion(changelogPath, ctx) : renderMarkdown([ctx]);
93
93
  if (writeFile(changelogPath, pkgContent, dryRun)) {
94
94
  files.push(changelogPath);
95
95
  }