Skip to content

fix(release): write release notes to file instead of capturing stdout#688

Merged
jdx merged 2 commits intomainfrom
fix/release-notes-formatting
Feb 10, 2026
Merged

fix(release): write release notes to file instead of capturing stdout#688
jdx merged 2 commits intomainfrom
fix/release-notes-formatting

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Feb 10, 2026

Summary

  • Use Claude's Write tool to write release notes to a temp file instead of capturing raw stdout with --output-format text, eliminating formatting artifacts
  • Scope the Write tool to only /tmp/release-notes-output.md using path restriction
  • Upgrade model from claude-opus-4-5 to claude-opus-4-6

🤖 Generated with Claude Code


Note

Low Risk
Low risk: changes are limited to the gen-release-notes automation script and primarily adjust how Claude output is captured and validated.

Overview
Release note generation now instructs Claude to write directly to a temporary markdown file via the Write($output_file) tool, instead of capturing stdout, to avoid formatting artifacts.

The task now creates/cleans up temp output+stderr files, switches to claude-opus-4-6, discards Claude stdout, and validates the output file is non-empty before printing it alongside the changelog.

Written by Cursor Bugbot for commit 5c08df5. This will update automatically on new commits. Configure here.

Use Claude's Write tool to write release notes to a temp file instead
of capturing raw stdout with --output-format text. This eliminates
formatting artifacts like extraneous markdown headers in the title or
conversational preamble in the output.

Also upgrades model from claude-opus-4-5 to claude-opus-4-6.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @jdx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refines the automated release note generation process by transitioning from stdout capture to direct file writing via Claude's Write tool. This modification ensures cleaner output by avoiding formatting issues and includes an upgrade to a newer Claude model, improving the overall reliability and quality of the generated notes.

Highlights

  • Release Note Generation: Changed the method of generating release notes from capturing Claude's stdout to using Claude's Write tool to output directly to a temporary file. This change aims to eliminate formatting artifacts previously encountered with stdout capture.
  • Tool Scoping: Scoped the Write tool to only allow writing to /tmp/release-notes-output.md, enhancing security and control over file operations.
  • Model Upgrade: Upgraded the Claude model used for generating release notes from claude-opus-4-5-20251101 to claude-opus-4-6.
Changelog
  • mise-tasks/gen-release-notes
    • Modified the prompt instructions to explicitly tell Claude to write output to /tmp/release-notes-output.md.
    • Updated the claude CLI command to use --allowedTools "Read,Grep,Glob,Write($output_file)", enabling the Write tool with path restriction.
    • Changed the Claude model from claude-opus-4-5-20251101 to claude-opus-4-6.
    • Removed the --output-format text flag as direct file writing is now used.
    • Replaced stdout capture and subsequent validation/parsing logic with a check for the existence and content of the output file.
    • Added rm -f "$output_file" to the trap command to ensure the temporary output file is cleaned up.
Activity
  • No human activity has occurred on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the release notes generation script to write Claude's output to a temporary file instead of capturing stdout, which is a good improvement to avoid formatting issues. I've identified two areas for improvement. First, the script uses a hardcoded path for the temporary file, which could cause race conditions; using mktemp would be more robust. Second, the validation for the release note header format has been removed, and it would be safer to reintroduce this check. With these adjustments, this will be a solid enhancement.

Comment thread mise-tasks/gen-release-notes Outdated
echo "Changelog length: ${#changelog} chars" >&2

# Capture stderr separately to avoid polluting output
output_file="/tmp/release-notes-output.md"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using a hardcoded temporary file path /tmp/release-notes-output.md can lead to race conditions if this script is run concurrently. It's safer to create a unique temporary file using mktemp. This would require defining output_file with mktemp before the prompt is constructed, and then using the $output_file variable in the prompt string, the claude command, and the trap.

echo "Error: No '# vX.X.X -' line found in Claude output" >&2
exit 1
fi
output=$(cat "$output_file")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The validation for the output format (checking for the # vX.X.X - header) has been removed. While writing to a file might be cleaner, it's still a good practice to validate the output from the LLM to ensure it follows the specified format. This prevents malformed release notes from being generated if the model doesn't follow instructions perfectly. Consider re-adding a check for the expected header.

output=$(cat "$output_file")

# Validate we got the expected format
if ! grep -q "^# $version - " "$output_file"; then
	echo "Error: Claude output does not have the expected format '# $version - <Creative Title>'" >&2
	echo "--- Claude output in $output_file ---" >&2
	cat "$output_file" >&2
	exit 1
fi

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is ON, but a Cloud Agent failed to start.

Comment thread mise-tasks/gen-release-notes Outdated
Address PR feedback:
- Use mktemp instead of a fixed /tmp path to avoid symlink attacks
- Redirect Claude's stdout to /dev/null since we read from the file
- Reference output_file variable in prompt instead of hardcoding path

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jdx jdx enabled auto-merge (squash) February 10, 2026 14:05
@jdx jdx merged commit 8c47244 into main Feb 10, 2026
18 checks passed
@jdx jdx deleted the fix/release-notes-formatting branch February 10, 2026 14:06
@jdx jdx mentioned this pull request Feb 10, 2026
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Mar 11, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [hk](https://github.com/jdx/hk) | minor | `1.36.0` → `1.38.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>jdx/hk (hk)</summary>

### [`v1.38.0`](https://github.com/jdx/hk/blob/HEAD/CHANGELOG.md#1380---2026-03-06)

[Compare Source](jdx/hk@v1.37.0...v1.38.0)

##### 🚀 Features

- **(hook)** add `fail_on_fix` option by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;725](jdx/hk#725)

##### 🐛 Bug Fixes

- **(builtins)** remove redundant check/check\_diff from builtins by [@&#8203;nkakouros](https://github.com/nkakouros) in [#&#8203;726](jdx/hk#726)

##### 📦️ Dependency Updates

- update anthropics/claude-code-action digest to [`26ec041`](jdx/hk@26ec041) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;720](jdx/hk#720)
- update jdx/mise-action digest to [`e79ddf6`](jdx/hk@e79ddf6) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;721](jdx/hk#721)
- update actions-rust-lang/setup-rust-toolchain digest to [`a0b538f`](jdx/hk@a0b538f) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;719](jdx/hk#719)
- update rust crate tokio to v1.50.0 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;722](jdx/hk#722)

### [`v1.37.0`](https://github.com/jdx/hk/blob/HEAD/CHANGELOG.md#1370---2026-03-03)

[Compare Source](jdx/hk@v1.36.0...v1.37.0)

##### 🚀 Features

- **(hook)** add env support to hooks by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;709](jdx/hk#709)
- parse Go-style diffs by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;704](jdx/hk#704)

##### 🐛 Bug Fixes

- **(builtins)** strip extra trailing newlines in end-of-file-fixer by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;708](jdx/hk#708)
- **(docs)** correctly document what --all is about by [@&#8203;nkakouros](https://github.com/nkakouros) in [#&#8203;715](jdx/hk#715)
- **(git)** exclude untracked files from unstaged\_files set by [@&#8203;nkakouros](https://github.com/nkakouros) in [#&#8203;716](jdx/hk#716)
- **(hkrc)** config format and load order by [@&#8203;ivy](https://github.com/ivy) in [#&#8203;710](jdx/hk#710)
- **(release)** write release notes to file instead of capturing stdout by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;688](jdx/hk#688)
- **(release)** make release notes editorialization non-blocking by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;690](jdx/hk#690)
- **(step)** gate check\_diff forced check\_first on Fix mode only by [@&#8203;nkakouros](https://github.com/nkakouros) in [#&#8203;717](jdx/hk#717)

##### 📚 Documentation

- **(shanty)** add audio player with sea shanty recording by [@&#8203;jdx](https://github.com/jdx) in [67a25ad](jdx/hk@67a25ad)
- document config file search paths by [@&#8203;ivy](https://github.com/ivy) in [#&#8203;701](jdx/hk#701)
- require AI disclosure on GitHub comments by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;703](jdx/hk#703)

##### 🔍 Other Changes

- replace gen-release-notes script with communique by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;700](jdx/hk#700)
- add autofix.ci workflow by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;705](jdx/hk#705)

##### 📦️ Dependency Updates

- lock file maintenance by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;686](jdx/hk#686)
- update taiki-e/upload-rust-binary-action digest to [`f391289`](jdx/hk@f391289) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;692](jdx/hk#692)
- update anthropics/claude-code-action digest to [`c22f7c3`](jdx/hk@c22f7c3) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;691](jdx/hk#691)
- update rust crate libc to v0.2.181 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;694](jdx/hk#694)
- update rust crate clap to v4.5.58 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;693](jdx/hk#693)
- lock file maintenance by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;695](jdx/hk#695)
- update anthropics/claude-code-action digest to [`edd85d6`](jdx/hk@edd85d6) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;698](jdx/hk#698)
- update rust crate clap to v4.5.60 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;699](jdx/hk#699)
- lock file maintenance by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;702](jdx/hk#702)
- lock file maintenance by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;711](jdx/hk#711)

##### New Contributors

- [@&#8203;ivy](https://github.com/ivy) made their first contribution in [#&#8203;710](jdx/hk#710)
- [@&#8203;nkakouros](https://github.com/nkakouros) made their first contribution in [#&#8203;715](jdx/hk#715)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40OS4wIiwidXBkYXRlZEluVmVyIjoiNDMuNTcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90IiwiYXV0b21hdGlvbjpib3QtYXV0aG9yZWQiLCJkZXBlbmRlbmN5LXR5cGU6Om1pbm9yIl19-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant