# How to Update CHANGELOG.md and Documentation During a Release in Claude Skills

> Learn how to automate updating CHANGELOG.md and documentation during a release in Claude Skills. Discover the scripted release pipeline synchronizing version.json with docs.

- Repository: [Jeffallan/claude-skills](https://github.com/jeffallan/claude-skills)
- Tags: how-to-guide
- Published: 2026-02-16

---

**The Claude Skills repository uses a deterministic, scripted release pipeline that synchronizes CHANGELOG.md and all documentation with the single source of truth in [`version.json`](https://github.com/Jeffallan/claude-skills/blob/main/version.json), automated by [`scripts/update-docs.py`](https://github.com/Jeffallan/claude-skills/blob/main/scripts/update-docs.py) and GitHub Actions.**

When maintaining the [Jeffallan/claude-skills](https://github.com/Jeffallan/claude-skills) repository, understanding how to properly update CHANGELOG.md and documentation during a release ensures version consistency across README files, plugin manifests, and GitHub Releases. The project implements a multi-step pipeline that eliminates manual drift through automated count updates and structured changelog extraction.

## The Release Pipeline Overview

The release process follows five deterministic steps that trigger sequentially once a maintainer updates [`version.json`](https://github.com/Jeffallan/claude-skills/blob/main/version.json). Each step is designed to keep documentation synchronized with the actual state of the repository, ensuring that skill counts, reference tallies, and version badges reflect the current release accurately.

The pipeline relies on three core components:

- **[`version.json`](https://github.com/Jeffallan/claude-skills/blob/main/version.json)** — The single source of truth for version strings and computed counts
- **[`scripts/update-docs.py`](https://github.com/Jeffallan/claude-skills/blob/main/scripts/update-docs.py)** — Python script that updates HTML comment markers across markdown and JSON files
- **[`.github/workflows/release.yml`](https://github.com/Jeffallan/claude-skills/blob/main/.github/workflows/release.yml)** — GitHub Actions workflow that extracts changelog sections and creates releases

## Step 1: Version Bump in version.json

The release process begins when a maintainer manually edits [`version.json`](https://github.com/Jeffallan/claude-skills/blob/main/version.json) to set the new version field.

```json
{
  "version": "0.4.8",
  "skill_count": 12,
  "reference_count": 5,
  "workflow_count": 3
}

```

This file serves as the source of truth for all subsequent automation. The `skill_count`, `reference_count`, and `workflow_count` fields are computed and updated automatically in the next step, but the `version` string must be set manually to trigger the release sequence.

## Step 2: Automated Documentation Updates with update-docs.py

Once [`version.json`](https://github.com/Jeffallan/claude-skills/blob/main/version.json) contains the new version, the maintainer runs [`scripts/update-docs.py`](https://github.com/Jeffallan/claude-skills/blob/main/scripts/update-docs.py) to propagate changes across all documentation files. This script performs three critical functions: it recomputes counts from the source code, updates [`version.json`](https://github.com/Jeffallan/claude-skills/blob/main/version.json) with the new tallies, and replaces special HTML comment markers in markdown and JSON files.

### How HTML Comment Markers Work

The script uses invisible HTML comment markers as anchors for regex replacement. These markers allow precise updates without affecting surrounding text.

```markdown
<!-- SKILL_COUNT -->12<!-- /SKILL_COUNT --> skills available

```

When [`update-docs.py`](https://github.com/Jeffallan/claude-skills/blob/main/update-docs.py) runs, it searches for patterns like `<!-- SKILL_COUNT -->.*?<!-- /SKILL_COUNT -->` and replaces the content between markers with the current count. This approach works for both markdown files (README.md, QUICKSTART.md, ROADMAP.md) and JSON manifests ([`.claude-plugin/plugin.json`](https://github.com/Jeffallan/claude-skills/blob/main/.claude-plugin/plugin.json)).

### Running the Documentation Updater

The script supports three execution modes:

```bash

# Standard run - writes changes to files

python scripts/update-docs.py

# Preview mode - shows what would change without writing

python scripts/update-docs.py --dry-run

# CI validation - exits with error code 1 if files are out of sync

python scripts/update-docs.py --check

```

When executed, the script outputs the computed counts and lists every file it modifies, ensuring transparency in the documentation update process.

## Step 3: Manual Changelog Entry in CHANGELOG.md

Before tagging the release, maintainers must add a new entry to [`CHANGELOG.md`](https://github.com/Jeffallan/claude-skills/blob/main/CHANGELOG.md) following the Keep a Changelog format. This step remains manual (or via PR review) to ensure human-written release notes.

```markdown

## [0.4.8] - 2024-01-15

### Added

- New skill for parsing JSON schemas
- Support for custom workflow templates

### Fixed

- Resolved race condition in async skill loader

```

The entry must use the version number defined in [`version.json`](https://github.com/Jeffallan/claude-skills/blob/main/version.json) as the header anchor. This markdown structure is critical for the next step, where GitHub Actions extracts the section automatically.

## Step 4: GitHub Actions Release Workflow

The [`.github/workflows/release.yml`](https://github.com/Jeffallan/claude-skills/blob/main/.github/workflows/release.yml) workflow triggers automatically when a maintainer pushes a tag starting with `v`. This workflow handles the extraction of changelog sections and the creation of the GitHub Release.

### Extracting Release Notes with awk

The workflow uses an `awk` script to parse [`CHANGELOG.md`](https://github.com/Jeffallan/claude-skills/blob/main/CHANGELOG.md) and extract only the section corresponding to the current version:

```yaml
- name: Extract release notes from CHANGELOG
  id: changelog
  run: |
    VERSION="${{ steps.version.outputs.VERSION }}"
    NOTES=$(awk -v ver="$VERSION" '
      /^## \[/ {

        if (found) exit
        if ($0 ~ "\\[" ver "\\]") found=1
        next
      }
      found { print }
    ' CHANGELOG.md)
    
    echo "NOTES<<EOF" >> $GITHUB_OUTPUT
    echo "$NOTES" >> $GITHUB_OUTPUT
    echo "EOF" >> $GITHUB_OUTPUT

```

This script searches for the header pattern `## [VERSION]`, captures all content until the next `## [` header, and stores it in the workflow output for use in the release creation step.

### Creating the GitHub Release

The extracted notes are passed to the `softprops/action-gh-release` action:

```yaml
- name: Create GitHub Release
  if: startsWith(github.ref, 'refs/tags/v')
  uses: softprops/action-gh-release@v2
  with:
    name: v${{ steps.version.outputs.VERSION }}
    body: |
      ${{ steps.changelog.outputs.NOTES }}

      ---
      **Documentation:** https://jeffallan.github.io/claude-skills/

```

This creates the GitHub Release page with the exact changelog content extracted from [`CHANGELOG.md`](https://github.com/Jeffallan/claude-skills/blob/main/CHANGELOG.md), ensuring consistency between the repository file and the public release notes.

## Step 5: Documentation Site Deployment

The final step in the pipeline rebuilds the Astro-based documentation site located in the `site/` directory. The release workflow deploys this to GitHub Pages, ensuring that the version badge and "last updated" timestamps (both updated by [`update-docs.py`](https://github.com/Jeffallan/claude-skills/blob/main/update-docs.py) in Step 2) are visible on the public documentation site.

This deployment happens automatically within the same GitHub Actions workflow that creates the release, ensuring that the documentation site updates simultaneously with the GitHub Release publication.

## Summary

Updating CHANGELOG.md and documentation during a release in the Claude Skills repository follows a structured, five-step pipeline:

- **Version Control**: All releases start with a manual update to [`version.json`](https://github.com/Jeffallan/claude-skills/blob/main/version.json), establishing the single source of truth for version strings.
- **Automated Documentation**: The [`scripts/update-docs.py`](https://github.com/Jeffallan/claude-skills/blob/main/scripts/update-docs.py) script recomputes skill counts and updates HTML comment markers across all markdown and JSON files, eliminating manual count drift.
- **Structured Changelog**: Maintainers add Keep a Changelog formatted entries to [`CHANGELOG.md`](https://github.com/Jeffallan/claude-skills/blob/main/CHANGELOG.md), which serves as the source for GitHub Release notes.
- **CI/CD Extraction**: The [`.github/workflows/release.yml`](https://github.com/Jeffallan/claude-skills/blob/main/.github/workflows/release.yml) uses `awk` to parse changelog sections automatically when tags are pushed, creating GitHub Releases with extracted notes.
- **Site Deployment**: The Astro-based documentation site rebuilds and deploys to GitHub Pages, ensuring public documentation reflects the updated version and counts immediately.

## Frequently Asked Questions

### How does the documentation stay synchronized with the actual number of skills in the repository?

The [`scripts/update-docs.py`](https://github.com/Jeffallan/claude-skills/blob/main/scripts/update-docs.py) script automatically counts the current skills, references, and workflow commands by scanning the source code directories. It then updates the counts in [`version.json`](https://github.com/Jeffallan/claude-skills/blob/main/version.json) and replaces the content between HTML comment markers (like `<!-- SKILL_COUNT -->`) in all documentation files. This ensures that README badges, quickstart guides, and plugin manifests always display accurate numbers without manual editing.

### What happens if I forget to update CHANGELOG.md before pushing a release tag?

If you push a tag without adding the corresponding entry to [`CHANGELOG.md`](https://github.com/Jeffallan/claude-skills/blob/main/CHANGELOG.md), the GitHub Actions workflow will still trigger, but the `awk` extraction script will fail to find release notes for that version. The workflow may create a GitHub Release with empty body content or fail entirely depending on how the action handles empty inputs. The Release Checklist in [`CLAUDE.md`](https://github.com/Jeffallan/claude-skills/blob/main/CLAUDE.md) explicitly requires adding the changelog entry before tagging to prevent this issue.

### Can I preview documentation changes without committing them to the repository?

Yes, the [`update-docs.py`](https://github.com/Jeffallan/claude-skills/blob/main/update-docs.py) script supports a `--dry-run` flag that previews all changes without writing them to disk. This mode prints the computed counts and lists every file that would be modified, allowing you to verify that skill counts and version strings are correct before making permanent changes. For CI validation, the `--check` flag exits with error code 1 if files are out of sync, preventing merges that would break the release pipeline.

### Why does the release workflow use HTML comment markers instead of direct string replacement?

HTML comment markers like `<!-- SKILL_COUNT -->` provide invisible, reliable anchors for regex replacement that survive markdown rendering. Unlike direct string replacement, which might accidentally modify similar text in documentation content, these markers create explicit boundaries that the [`update-docs.py`](https://github.com/Jeffallan/claude-skills/blob/main/update-docs.py) script can target precisely. This approach works consistently across both markdown files (README.md, QUICKSTART.md) and JSON manifests (plugin.json), ensuring that badges and metadata stay synchronized without visible markup cluttering the rendered output.