# changelog

> Generates a single unified changelog from git history, written in plain language for the whole company, defaulting to Slovak and comparing the release branch against develop for unreleased changes.

- Skill: `samuelpatro/changelog` (Agent Skill)
- Install (CLI): `npx skillmds add samuelpatro/changelog`
- Raw SKILL.md: https://api.skillmd.com/api/skills/samuelpatro/changelog/raw
- Safety review: CAUTION (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing, Coding & Dev Tools, Technical Writing
- Tags: Changelog, Documentation, Git, Release Notes
- Author: samuelpatro (https://skillmd.com/u/samuelpatro)
- Updated: 2026-08-22
- Page: https://skillmd.com/skills/samuelpatro/changelog

---


# Changelog generator

Turn git history into one unified changelog that works for everyone in the
company: clear enough for managers and non-tech colleagues, detailed enough for
the developers. There is no "dev vs non-tech" split. Write a single changelog
from both worlds.

## Pre-loaded git context

The data below is injected automatically when the skill loads (the `!` commands
run first, their output is embedded here). Use it directly. Only fall back to the
**Bash** tool for cases this data does not cover: an explicit custom range
(`v2.0.0..HEAD`), a window older than 14 days, or to `git fetch` for freshness.

```!
if git show-ref --verify --quiet refs/heads/main; then base=main; else base=master; fi
work=$(git rev-parse --abbrev-ref HEAD)
echo "release branch: $base | working branch: $work | today: $(date +%Y-%m-%d)"
echo
echo "=== UNRELEASED ($base..$work) ==="
git log "$base..$work" --no-merges --pretty=format:"%h|%ad|%s" --date=format:"%Y-%m-%d %H:%M"
echo
echo "=== LAST 14 DAYS on $work ==="
git log "$work" --since="14 days ago" --no-merges --pretty=format:"%h|%ad|%s" --date=format:"%Y-%m-%d %H:%M"
```

## 1. Pick the commit range from the injected data

- **Default** (no range args, or "unreleased" / "vs main" / "branch"): use the
  **UNRELEASED** block above.
  - **If UNRELEASED is empty** (common here: `master` and `develop` are kept in
    sync with no release tags), fall back to the **last 3 days** from the LAST 14
    DAYS block and tell the user ("master and develop are in sync, showing the
    last 3 days instead").
- **Date ranges**: filter the LAST 14 DAYS block by date using "today" from the
  injected header.
  - "today" → commits dated today
  - "yesterday" → commits dated yesterday only
  - "today and yesterday" → both
  - "last week" / "7 days" → last 7 days
- **Explicit range** (`v1.2.0..HEAD`, two tags/branches, or a window > 14 days):
  the injected data won't cover it. Run the **Bash** tool yourself:
  `git log <range> --pretty=format:"%h|%ad|%s" --date=format:"%Y-%m-%d %H:%M" --no-merges`

If the chosen range is genuinely empty, say so plainly and stop (don't invent entries).

## 2. Decide language

There is only **one** changelog style (see section 3), so the only choice is
language. If the user named it in args ("slovak", "sk", "en", "english"), use it.
Otherwise **default to Slovak** — do not ask. Only produce English when the user
explicitly requests it ("en" / "english").

## 3. Write the changelog

One changelog, for the whole company. Each entry must be understandable by a
manager or non-tech colleague, while still carrying enough detail that a developer
recognizes exactly what shipped. Aim for "plain language first, precise detail
second" on every line.

- Read the commit subjects (and PR titles when a subject is terse) to understand
  what each change does. Translate intent into clear language; don't just reformat
  the raw subject line.
- Map Conventional Commit prefixes: `feat`→new feature, `fix`→fix,
  `perf`→speed/performance, `chore`/`deps`→housekeeping, `revert`→rolled back,
  `docs`→documentation.
- **Plain language, but not baby talk.** Lead with what changed and where, in
  words anyone in the company understands. Don't expose deep code internals (table
  names, function names, query patterns, commit hashes) in the wording. But *do*
  keep the vocabulary people recognize: UI elements (badge, menu, nav, hero,
  banner, filter, checkout, product card, modal, dropdown, tab) and plain
  technical concepts that matter (login, permissions, security, backups, speed).
  Translate the *mechanism*, keep the *meaning*: e.g. "N+1 queries" → "pages load
  faster with less strain on the server".
- **Keep the proper names people recognize.** Code internals get translated
  away, but real names that identify the change must stay: product and section
  names (Exclusive Club, special box, tester kit), campaign and integration
  names (Bloomreach, Packeta, Doklado), badge and page labels ("Skvelé na
  cesty"), and concrete numbers (product IDs, prices, percentages) when they're
  the point of the change. Stripping these out makes the line useless. When in
  doubt whether a name is "internal noise" or "the thing that shipped", keep it.
- **Carry detail for both worlds.** Say specifically what changed and where (which
  page, section, element, or area), not just "something was improved". Where it
  helps a developer trace the change without hurting readability, append a light
  reference in parentheses at the end of the line, e.g. a PR number (`#1234`) or a
  short area tag (`payroll`, `auth`). Keep these unobtrusive: plain meaning first,
  reference last. Never lead with a hash or internal name.
- **Be detailed, don't collapse changes.** Give every meaningful change its own
  line. Do not merge several distinct changes into one fuzzy summary, and do not
  drop a change just because it seems minor. The only things to omit are pure
  internal noise with zero impact on anyone (CLAUDE.md edits, throwaway-script
  cleanup, doc-file deletes, lint/formatting-only commits, CI tweaks with no
  behavior change).
- **Group by what people notice, and use as many sections as the changes
  warrant.** Don't force everything into three buckets. Pick the sections that
  actually fit what shipped, and split a broad area into finer sub-sections when
  it has several distinct changes. A useful palette to draw from (use only the
  ones that apply, add your own when needed):
  - **Shopping experience** — storefront, product pages, cart, checkout, badges,
    navigation, search, filters
  - **Marketing & campaigns** — promos, discount codes, gift cards, newsletter,
    Bloomreach / integration-driven campaigns
  - **Speed** — anything that makes a page or action faster
  - **Back office** — admin lists, widgets, order/parcel management, internal
    tools the team uses
  - **Sign-in & security** — login, permissions, auth, data protection
  - **Under the hood** — refactors, infrastructure, deploy/CI, dependency bumps
    that still matter, written plain-first so a manager gets the gist and a
    developer gets the specifics
  When a section would hold only one line, fold it into the nearest fitting
  section rather than leaving a one-item heading. When a section runs long,
  split it (e.g. "Shopping experience" → "Product pages" + "Cart & checkout").
- **Calibrate length per line: one tight sentence by default.** State what
  changed and where, then stop. Add a second sentence or a nested sub-bullet
  ONLY when it carries information the reader needs (an exact name, number,
  edge case, or who it affects). Don't pad with restated mechanism, and don't
  strip a line down so far it loses its point. If a line reads as a vague
  "something was improved", it's too short; if it explains how the code works,
  it's too long.
- **Link to e-shop pages when you can.** If a change adds a new page or updates
  an existing user-facing page/section, and you know the live URL, link it with a
  Markdown link so the reader can click straight to it:
  `- New [size guide](https://shop.example.com/size-guide) page in the footer`.
  - Find the base URL without guessing: check the repo for it (`.env` `APP_URL`
    / `APP_FRONTEND_URL`, `package.json` `homepage`, a config or constants file,
    or the production domain in deploy config). If you genuinely can't determine
    it, ask the user once for the storefront base URL, or skip the link rather
    than invent a domain.
  - Build the full URL from the base plus the route the change touches (e.g.
    base `https://shop.example.com` + route `/exclusive-club` →
    `https://shop.example.com/exclusive-club`). Only link routes you can see in
    the commit/diff or that the user confirms. Never fabricate a path.
  - Link the most specific page that changed, not the bare homepage. For
    back-office/admin-only pages, link only when it's genuinely useful.
- Respect global doc style: **no em-dashes** and no sentence-joining hyphens;
  rephrase with periods, commas, or parentheses.
- For Slovak output, write natural Slovak (not a literal translation), and keep
  product/section names (Exclusive Club, "looks", special box) as the team uses them.

## 4. Output format (Markdown)

Output clean, standard **GitHub-flavored Markdown**:

- Use a `##` heading for the title (date range / scope). For each
  section/category use a **bold label** on its own line (`**Shopping
  experience**`), NOT a `###` heading.
- Use real Markdown list items: `-` for each change. You can nest up to **3
  levels deep** (two-space indentation per level) when a change has sub-points,
  e.g. a feature with its details and edge cases. Only nest when it adds clarity;
  keep flat lists flat.
- Bold with `**double asterisks**`. Use `inline code` for version numbers or
  literal labels when helpful.
- Use Markdown links `[text](url)` for new or changed e-shop pages when the live
  URL is known (see the linking rule in section 3).
- Put the date range / scope in the title so the reader has context.
- **Always output directly in the chat. Never write it to a file.** Print it
  inside a single fenced code block so the raw Markdown survives copy-paste.

Example shape:

```
## Changelog (unreleased: master → develop)

**Shopping experience**
- New [Exclusive Club](https://shop.example.com/exclusive-club) page, with product cards that match the regular e-shop layout
- Limited editions show in-stock products first
- New "Sale" badge on discounted product cards
  - Shows the exact percentage off
  - Hidden once a product sells out
- Main navigation menu reordered, with a clearer "My account" dropdown
  - Account dropdown now groups orders, wishlist, and settings
    - Wishlist count appears as a small badge next to the icon
- Homepage hero banner now links straight to the active campaign

**Speed**
- Storefront and account pages load faster
- Product listing filters apply without a full page reload

**Under the hood**
- Stronger sign-in security: login sessions expire reliably and sign-in is limited to the approved company domain (auth, #1248)
- Daily backups now exclude session data and secrets, so backups are smaller and safer
- Payroll code consolidated into one shared module, reducing duplication (payroll)
```

## Argument cheatsheet

There is one unified style for everyone, so the only option is language, which
defaults to Slovak.

- `/changelog` → default: main/master vs develop (unreleased), Slovak
- `/changelog sk` → unreleased, Slovak
- `/changelog en` → unreleased, English
- `/changelog today` → today's commits, Slovak
- `/changelog yesterday sk` → yesterday, Slovak
- `/changelog v2.0.0..HEAD` → explicit range (Bash), Slovak

