update_changelog

update_changelog is a skill for Claude Code, Codex from theafh/ai-modules. It costs 61 tokens per session (3,357 once invoked), scanned A, original, MIT.

A skill for creating or updating a repository’s CHANGELOG.md from Git commit history. A changelog is a readable record of what changed, grouped by date.

In plain words
What is it for?
Use it to generate a new changelog or add missing days from commits, with newest dates first and entries organized by the files and changes involved.
Why use it?
It keeps release history current while preserving existing entries and adding later changes without rewriting the past.

Skill for Claude CodeCodex

Written for no agent in particular: nothing here depends on one.

Part of the ai_dev plugin — 24 skills, 5 agents, 1 hook shipped together

Good fit Use it to generate a new changelog or add missing days from commits, with newest dates first and entries organized by the files and changes involved.

Compare 6 skills from other repositories ↓
Install with agentmods
npx agentmods add skills/theafh/ai-modules/update_changelog
Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

Any agent
npx skills add theafh/ai-modules --skill update_changelog
Clone the repo
git clone --depth 1 https://github.com/theafh/ai-modules

Made for: Claude Code, Codex.

Or install ai_dev, the plugin that ships this one along with the rest of its 24 skills, 5 agents, 1 hook.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for update_changelog

README.md
[![agentmods](https://agentmods.dev/badge/skills/theafh/ai-modules/update_changelog.svg)](https://agentmods.dev/skills/theafh/ai-modules/update_changelog)
Your own site
<a href="https://agentmods.dev/skills/theafh/ai-modules/update_changelog"><img src="https://agentmods.dev/badge/skills/theafh/ai-modules/update_changelog.svg" alt="Measured on agentmods" height="20"></a>
Per session 61 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 3,357 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe. Third-party audits
  • NVIDIA SkillSpector warn 7 Sept 2026
SkillSpector: 1 finding, up to medium

These are SkillSpector’s own severities. On a checked sample its high-severity flags on skills were ~96% false positives — a documented command, a public API, a “never do X” rule — so we show them as a caution to read, not a verdict. Why →

  • medium Memory Poisoning · line 33
    Skill attempts to fill the context window with filler content, displacing legitimate instructions and safety constraints. This can degrade agent performance or bypass safety boundaries.
    Fix: Implement context-window management that detects and rejects padding or stuffing attempts. Prioritize system instructions over user-injected content.
How audits are shown
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00061 $0.03357
Opus 5 $0.00030 $0.01679
Sonnet 5 $0.00012 $0.00671
Haiku 4.5 $0.00006 $0.00336

Measured yesterday against content hash 6348417db524, method: parsed. Prices are Anthropic first-party input rates as of 2026-09-07, from the pricing page.

Security

Grade A, and why

update_changelog scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured yesterday.

The scan reads SKILL.md. This mod also ships 1 executable file (scripts/prepare_changelog_day.sh), listed below but not scanned — reading those needs a real analyzer, not pattern matching.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

plugins/ai_dev/skills/update_changelog/SKILL.md · 71 lines

How it starts

The opening of the file, as written. The whole thing — 71 lines — stays where its author put it; the contents beside it link to each section on GitHub.

update_changelog

<update_changelog_skill> Create or update a CHANGELOG.md in the repository root: a human-readable, day-grouped, add-only history derived from git commits, newest day first. Record later committed changes as new entries or day sections while preserving existing entries as immutable historical facts. <command_intent>build CHANGELOG.md, refresh changelog from git history, add the missing days to the changelog</command_intent> <prepare_changelog_day>Run scripts/prepare_changelog_day.sh YYYY-MM-DD from this skill when it is available. The script writes one structured context blob for a single calendar day to a file under the system tmp dir, with the day's commit subjects and bodies, the deduplicated repo-relative file list, per-file net diffs for the day, and generic placeholders for binary files. Its stdout prints exactly two lines: the context file's absolute path, then a one-line consumption directive. Exits 1 with no commits on <date> when the date has no commits, so skip that date silently.</prepare_changelog_day> <consume_context> <full_read>Use the Read tool on the path printed by scripts/prepare_changelog_day.sh and read the entire file. This is the default path and works for normal-sized days.</full_read> <paginated_read>If the file overflows Read's default window, call Read again with offset/limit and continue in sequence until every byte is covered. Consume each page in order.</paginated_read> <ordered_slicing_fallback>Only when the file is so large that paginated Read is impractical, use grep/awk/sed via Bash to split the file into ordered slices. Read those slices sequentially from the top of the file through the end, preserving the original order of <commit> and <file_change> sections.</ordered_slicing_fallback> <hard_rules>Use the script's context file as the sole per-day source. Never re-derive the day with git log, git diff, or git status; never truncate the blob with head; never sample by filename. Iterate every <commit> and <file_change> section in order before composing the day section.</hard_rules> </consume_context> <output_contract> The file always begins with the H1 # CHANGELOG — {Project Name}, then a blank line, then the line stating that entries are grouped strictly by day, kept on their original implementation dates, and immutable once written. Substitute {Project Name} from the repo directory name, package.json, Cargo.toml, or the README's H1. <day_section>One ## YYYY-MM-DD — {Day theme} heading per calendar day that has commits, ordered newest-first. {Day theme} is a 2-5 word editorial summary of that day's dominant focus. End every day section with a horizontal rule (---).</day_section> <entry_line>One bullet per logical change inside the day section in the format - **Category:** Plain-English summary of the change..</entry_line> added for new features or capabilities. changed for behavior that differs from before. deprecated for retired or removed behavior, or behavior kept only for legacy use. refactored for the same output from the same input with faster, more robust, or less buggy internals. docs for documentation- or specification-only changes. Express replacement or removal as a deprecated or changed entry on the date that later work happened. <files_changed_line>End every day section with a files-changed bullet listing every path the day touched, repo-relative, backtick-wrapped, comma-separated, deduplicated. Shape: a - **Files changed:** prefix followed by each path wrapped in single backticks and separated by a comma plus a space.</files_changed_line> <insertion_anchor>The header block, the H1 plus the immutability/grouping line beneath it, ends at a stable boundary, and the first ## YYYY-MM-DD heading is the top of the day list. That boundary is the one anchor for every day-section insertion. Invariant: a new day section always lands in the seam immediately between the end of the header block and the current first ## YYYY-MM-DD heading, never inside the header block, never below an existing day section. The invariant governs new day sections only; when a run reopens the most recent recorded day, that day's existing section is extended in place per <last_recorded_day_reconciliation>, not re-inserted.</insertion_anchor> </output_contract> <run_scope>Build each run from committed git history only; ignore uncommitted and untracked working-tree state. On incremental runs, treat the most recent recorded day as provisionally complete because commits can share that calendar day after its section was first written. Reopen that day and every later committed date; days older than the most recent recorded day are settled for that run.</run_scope> <context_safety>Two things are released incrementally, on different schedules, so keep them distinct. The large per-day context blob from <consume_context> is what can overflow the context window on a long history, so consume and release it one day at a time on both paths, incremental and cold build alike. Flushing each composed day section to CHANGELOG.md before the next is the separate cold-build rule: a cold build walks the full history, so it writes each completed day section to disk and lets it fall out of working context before composing the next, keeping only one day's material live at a time. An incremental run touches only a few new days, so it composes their small sections together and lands them in one insert per <newest_first> with no per-day section flush. Only the composed-section batch size differs between the two paths; the one-day-at-a-time discipline for the context blob is identical on both.</context_safety> <newest_first>Maintain strict newest-first day ordering, and land every new day section against the single anchor defined in <insertion_anchor>: the seam between the header block and the current first ## YYYY-MM-DD heading. Locate that seam with a bounded read of only the header block plus the first existing ## heading, never a whole-file read. One anchor, two insertion shapes: <incremental_prepend>Incremental run (a few new days, the common case): compose all the run's new day sections into one block already ordered newest-first, then perform a single insert that splices that block into the seam, anchoring the edit on the first existing day heading. One edit, one seam, nothing below it reordered.</incremental_prepend> <cold_build_insert>Cold build (no CHANGELOG.md, long history): under <context_safety>, insert each completed day section into the same seam immediately below the header block as it is composed. Processing oldest→newest with every day inserted at the top yields a newest-first file without holding the whole history in context.</cold_build_insert> When a run reopens the most recent recorded day, extend that day's existing section in place per <last_recorded_day_reconciliation> rather than inserting a new section.</newest_first> <one_entry_per_logical_change>Squash related commits into a single bullet. Write one entry per logical change, not per commit.</one_entry_per_logical_change> <date_immutability>Keep entries on their original implementation date forever. Treat each existing entry's date, text, and category as frozen once written. Record later committed changes only as new entries on the dates those changes happened.</date_immutability> <summary_style>Write summaries in plain English, past tense, describing what was done. Leave why and how out of the summary. Stay concise but specific enough that a reader unfamiliar with the codebase understands the scope.</summary_style> <preserve_existing>Preserve existing day sections and entries in place. Add new day sections or entries for later committed changes while keeping existing entry dates, text, and categories unchanged. For the reopened most recent recorded day, follow <last_recorded_day_reconciliation> instead of regenerating the section.</preserve_existing> <last_recorded_day_reconciliation>When an incremental run reprocesses the most recent recorded day, compare that day's committed history with the existing section. Keep every existing entry's date, category, and text unchanged; add entries for newly found logical changes, extend the - **Files changed:** line with missing paths, and revise the day theme only when the added commits change the day's dominant focus.</last_recorded_day_reconciliation> <model_authority>The model owns summarization, day-theme composition, and category assignment. Use script output as evidence and execution support.</model_authority> <workflow_authority>Treat this skill as the source of truth for /update_changelog workflow, output format, and entry style.</workflow_authority> <resolve_project_name>Resolve {Project Name} from the repository directory name, an existing project title in the README's H1, the name field of package.json or Cargo.toml, or another canonical project metadata file.</resolve_project_name> <enumerate_dates>Build the date list from committed history. When CHANGELOG.md does not exist, run git log --reverse --format='%ad' --date=short --no-merges | sort -u to list every distinct commit date in the repository, oldest-first. When updating an existing changelog, read from the top only until the first ## YYYY-MM-DD heading; because the changelog is newest-first, that heading is the most recent recorded day D. Then run git log --reverse --format='%ad' --date=short --no-merges --since={D}T00:00:00 | sort -u (or an equivalent committed-history query) to list D and every later distinct commit date. Keep D in the list because same-day commits can land after its section was written.</enumerate_dates> <ensure_header>If CHANGELOG.md does not exist, create it with the header block. If it exists, leave the header in place.</ensure_header> <day_loop> For each selected date, oldest-first: Run scripts/prepare_changelog_day.sh YYYY-MM-DD to produce that day's context file path. If the script exits 1, skip the date silently. Read the returned context file according to <consume_context>, covering the full file before composing the day section. Read every <commit> and <file_change> block from the consumed context. Aggregate related changes into logical entries, choose categories, and compose a 2-5 word day theme. Build the day section from the day theme, the entry bullets, and the - **Files changed:** ... bullet using the paths from <files_changed>. End the section with ---. Place the composed section by run type, per <newest_first> and <context_safety>. On a cold build, insert this day's section into the seam immediately below the header block now, then flush to disk before composing the next day so prior detail falls out of working context. On an incremental run, add this day's section to the top of the run's accumulating newest-first block and hold it, because the single splice happens in <land_new_days>. For the reopened most recent recorded day, reconcile its existing section in place per <last_recorded_day_reconciliation> instead of inserting a new one. </day_loop> <land_new_days>On an incremental run, after the loop has composed every selected day, perform the one anchored prepend: splice the accumulated newest-first block into the seam between the header block and the first existing day heading, per <newest_first>. On a cold build, each day section was already inserted during the loop, so no separate splice runs here.</land_new_days> Verify the changelog with the lint tooling the target repository itself provides, reading CHANGELOG.md as it stands on disk at this point: an incremental run has just landed its day sections in the single splice above, and a cold build flushed every section during the loop, so both run types inspect the file the run actually wrote. Discover the available tooling in the priority order below and run the first entry that applies, letting the owner of the invocation set the target. A repo entry point runs in the form the repo authored it, whole-repo scope included, while a linter this step invokes itself is pointed at CHANGELOG.md. The step reports its findings and leaves the written CHANGELOG.md in place on every branch; a lint-fix pass that rewrites the file belongs to the target repo's own standing rules. <repo_lint_entry_point>Run the repository's own lint entry point when it has one, in the form the repo authored it: a lint or lint-md Make target where the repo ships one (confirm the target exists with make -n <target> before running it), a package.json lint script, a configured pre-commit hook set, or a lint command the project documents.</repo_lint_entry_point> <project_configured_markdown_linter>Failing that, run a markdown linter the repo or its toolchain already provides and that honors the repo's own configuration, for example a locally available markdownlint or markdownlint-cli2 resolving the repo's .markdownlint* config, pointed at CHANGELOG.md.</project_configured_markdown_linter> <no_linter_available>When the repository provides neither, skip the check and name the reason: report "no repo lint tooling found; skipped markdown verification" and treat the changelog as delivered.</no_linter_available> <authoritative_tooling_only>Keep the verdict authoritative by running only tooling the target repo already provides. Two forms yield a non-authoritative result and stay out: fetching a linter over the network at run time (npx --yes <linter> and equivalents), and applying a linter's default ruleset in place of the repo's own lint config.</authoritative_tooling_only> <report_outcome>Report which branch ran and what it found. Tooling found and clean: name the command and report the changelog as verified against it. Tooling found with findings on CHANGELOG.md: report what the linter said about the changelog and leave the file as written, so the operator decides the follow-up. No tooling found: report the skip with its stated reason. The changelog stands as delivered on all three branches, and verification stays best-effort against whatever the repo offers.</report_outcome> <changelog_scoped_verdict>Answer for CHANGELOG.md alone. Findings on the changelog are this step's verdict; a non-zero exit or a finding in a file this run did not write is pre-existing repo state, reported as such and settling nothing about the changelog.</changelog_scoped_verdict> </update_changelog_skill>

Read the full file on GitHub · 71 lines

Files

What ships with it

1 file beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. yesterday Changed 6348417db524
  2. 8d ago First seen · 71 lines · 61 tokens per session scan A f04b9de6b640

Subscribe to this mod's changes

update_changelog is a skill published in the GitHub repository theafh/ai-modules (38 stars, last pushed today), licensed MIT. It adds 61 tokens to every session and 3,357 once invoked, about $0.0003 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.