Shipping Log
Purpose
Turn raw git/GitHub history into a polished, public-facing changelog that reads like a product
update — benefit-first, jargon-free, and framed to signal momentum to users and investors.
The engineering log says "what was coded"; the shipping log says "what you can now do."
Part of the docs + release pack
This skill is one of three that share a single version anchor with
user-guide-builder and
screenshot-capture:
docs/VERSION ← single source of truth (semver, e.g. 1.4.0)
├─ shipping-log → groups releases "## v1.4.0 — 2026-06-17" (this skill OWNS the bump)
├─ user-guide-builder → stamps the guide "Current as of v1.4.0"
└─ screenshot-capture → captures the app screens (feature art, guide images)
A reader can then match what changed (this log) to how it now works (the guide).
After you cut a release here, offer to run user-guide-builder so the guide's stamp matches.
Versioning anchor
A release is one version number over a batch of shipped work. Manage it with the
bundled scripts/version.mjs (dependency-free, cross-platform):
| Action |
Command |
| Read current version |
node <skill-dir>/scripts/version.mjs get |
| Create anchor if absent |
node <skill-dir>/scripts/version.mjs init 0.1.0 |
| Cut a release (pick one) |
node <skill-dir>/scripts/version.mjs bump <minor|patch|major> |
minor — new user-facing features (most releases) · patch — fixes/polish only ·
major — breaking change or headline launch.
- Group the log by version, newest first:
## v{X.Y.Z} — {date}. Everything since the
previous ## v… heading (or git tag) goes under the new version.
- First-time / backfill: reconstruct a few version buckets from history so the log opens
with momentum (pre-GA products stay in
0.x); set the anchor to the newest bucket and
say in your report that early versions were reconstructed.
Workflow
Collect history. From the repo root, run the bundled script:
node <skill-dir>/scripts/collect-history.mjs --days 5
- Use
--since-tag instead of --days N to scope from the latest git tag to HEAD.
- Add
--github to also pull merged PR titles + releases via the gh CLI (best-effort; skipped if gh is unauthenticated).
- Output is JSON: momentum
stats, tags, and commits grouped by day. Read it; do not guess history.
Load the voice guide. Read references/voice-and-format.md for the tone rules, the
commit→section mapping, the omit list, the exact markdown format, and a worked example.
Follow it exactly — the value of this skill is the consistent voice.
Translate, don't transcribe. Group commits by version (default — see
Versioning anchor), or by day/release/tag. For each entry write
a one-line headline + 2–4 benefit bullets + section tags (New / Improved / Fixed /
Security). Merge many small commits into a few user-meaningful bullets.
Compute momentum stats from the JSON for the header strip: updates this week, releases,
last shipped. These are the numbers investors scan first.
Pick the output based on the request:
- Markdown changelog (default) — write
docs/SHIPPING-LOG.md (or CHANGELOG.md),
newest first, grouped by version (## v1.4.0 — 2026-06-17).
- Standalone "What's New" page — copy
assets/whats-new.html for a full-page, premium,
themeable changelog (version-grouped, category filter chips, momentum band, works without
JS). Set the :root brand tokens to the project's real colors — never invent a palette.
- Landing-page section — copy
assets/shipping-log.html, fill in the entries and the
illustration slots, and adapt to the project's stack (convert to React/TSX if the repo is
React; keep the structure and class names).
Be honest about ship status. Clearly mark un-merged/un-deployed work as "rolling out" or
"staged" — never imply staged work is live. Check git status / whether commits are pushed if
in doubt.
Non-negotiable rules
- Benefit-first. Lead with what the user/customer can now do, not the implementation.
- No internal jargon. Translate engineering terms to product impact. "Enabled RLS" → "your
data is now isolated to your account"; "removed @ts-nocheck / refactor / bumped deps" → omit or
fold into one "Behind the scenes" line.
- Never invent. Every entry must trace to a real commit/PR in the collected JSON. If a commit's
user impact is unclear, inspect the diff, ask, or omit it — do not fabricate a feature.
- Sentence case, punchy, scannable. One screenful per release. Two weights, no ALL CAPS.
Portfolio mode (one board across many repos)
To build a "we ship across everything" board (a portfolio ship index), aggregate multiple repos:
- Copy
assets/portfolio.config.example.json and edit the projects list (name, local repo
path, tagline, accent). One entry per app.
- Run
node <skill-dir>/scripts/collect-portfolio.mjs --config <your-config>.json --days 35.
Output JSON has: totals (ships_this_week, ships_30d, active_this_week, busiest_day), a merged
daily heatmap map, per-projects stats, and the latest cross-project recent commits.
- Render the Ship Index: portfolio stat strip + a 5-week activity heatmap (color cells by daily
count) + per-project rows (bar width ∝ 30-day commits) + a cross-project recent-ships feed.
Rewrite
recent[].subject (raw commit messages) into benefit-first copy per the voice spec.
- Data source choice when wiring to a real site:
- Static/generated (repos are local or in CI): run the aggregator on a schedule, write the
JSON into the home-page repo (or an endpoint), and have the page read it. No live git needed.
- GitHub-API live: if every repo is on GitHub, a serverless function can hit the commits API
per repo and aggregate on request — always fresh, no local step. Needs a token + repo list.
- Keep cadence claims truthful; show dormant projects honestly (or feature only active ones).
Reusable contents
scripts/version.mjs — the shared semver anchor manager (get/init/set/bump/date on docs/VERSION).
scripts/collect-history.mjs — single-repo history collector (run, don't reinvent).
scripts/collect-portfolio.mjs — multi-repo aggregator for the portfolio ship index.
assets/portfolio.config.example.json — example portfolio config.
references/voice-and-format.md — the voice + format spec and worked example.
assets/whats-new.html — a standalone, premium, themeable "What's New" page (version-grouped,
category filter chips, momentum band; works without JS). Pairs with docs/SHIPPING-LOG.md.
assets/shipping-log.html — a dark, on-brand landing "shipping log" section (single product)
with metric strip, timeline cards, illustration slots, and notes for adapting to React.
1---2name: shipping-log3description: Generates a public-facing, investor-enticing changelog ("shipping log") from a git or GitHub repository's recent history. This skill should be used when the user wants a changelog, release notes, a "what's new" feed, or a "shipping log" written for end users and investors rather than engineers — grouped by version (or date/release) with New / Improved / Fixed / Security sections, benefit-first copy, momentum stats, and an optional landing-page component. Triggers on requests like "changelog for the last N days", "shipping log", "what's new for the public/investors", "turn my commits into release notes", or "show that we're shipping constantly".4---56# Shipping Log78## Purpose910Turn raw git/GitHub history into a polished, public-facing changelog that reads like a product11update — benefit-first, jargon-free, and framed to signal momentum to users and investors.12The engineering log says "what was coded"; the shipping log says "what you can now do."1314## Part of the docs + release pack1516This skill is one of three that share a single version anchor with17[`user-guide-builder`](../user-guide-builder/SKILL.md) and18[`screenshot-capture`](../screenshot-capture/SKILL.md):1920```21docs/VERSION ← single source of truth (semver, e.g. 1.4.0)22 ├─ shipping-log → groups releases "## v1.4.0 — 2026-06-17" (this skill OWNS the bump)23 ├─ user-guide-builder → stamps the guide "Current as of v1.4.0"24 └─ screenshot-capture → captures the app screens (feature art, guide images)25```2627A reader can then match *what changed* (this log) to *how it now works* (the guide).28After you cut a release here, offer to run `user-guide-builder` so the guide's stamp matches.2930## Versioning anchor3132A **release** is one version number over a batch of shipped work. Manage it with the33bundled `scripts/version.mjs` (dependency-free, cross-platform):3435| Action | Command |36|---|---|37| Read current version | `node <skill-dir>/scripts/version.mjs get` |38| Create anchor if absent | `node <skill-dir>/scripts/version.mjs init 0.1.0` |39| Cut a release (pick one) | `node <skill-dir>/scripts/version.mjs bump <minor\|patch\|major>` |4041- `minor` — new user-facing features (most releases) · `patch` — fixes/polish only ·42 `major` — breaking change or headline launch.43- **Group the log by version**, newest first: `## v{X.Y.Z} — {date}`. Everything since the44 previous `## v…` heading (or git tag) goes under the new version.45- **First-time / backfill:** reconstruct a few version buckets from history so the log opens46 with momentum (pre-GA products stay in `0.x`); `set` the anchor to the newest bucket and47 say in your report that early versions were reconstructed.4849## Workflow50511. **Collect history.** From the repo root, run the bundled script:52 ```bash53 node <skill-dir>/scripts/collect-history.mjs --days 554 ```55 - Use `--since-tag` instead of `--days N` to scope from the latest git tag to HEAD.56 - Add `--github` to also pull merged PR titles + releases via the `gh` CLI (best-effort; skipped if `gh` is unauthenticated).57 - Output is JSON: momentum `stats`, `tags`, and `commits` grouped by day. Read it; do not guess history.58592. **Load the voice guide.** Read `references/voice-and-format.md` for the tone rules, the60 commit→section mapping, the omit list, the exact markdown format, and a worked example.61 Follow it exactly — the value of this skill is the consistent voice.62633. **Translate, don't transcribe.** Group commits by **version** (default — see64 [Versioning anchor](#versioning-anchor)), or by day/release/tag. For each entry write65 a one-line headline + 2–4 benefit bullets + section tags (New / Improved / Fixed /66 Security). Merge many small commits into a few user-meaningful bullets.67684. **Compute momentum stats** from the JSON for the header strip: updates this week, releases,69 last shipped. These are the numbers investors scan first.70715. **Pick the output** based on the request:72 - **Markdown changelog** (default) — write `docs/SHIPPING-LOG.md` (or `CHANGELOG.md`),73 newest first, grouped by version (`## v1.4.0 — 2026-06-17`).74 - **Standalone "What's New" page** — copy `assets/whats-new.html` for a full-page, premium,75 themeable changelog (version-grouped, category filter chips, momentum band, works without76 JS). Set the `:root` brand tokens to the project's real colors — never invent a palette.77 - **Landing-page section** — copy `assets/shipping-log.html`, fill in the entries and the78 illustration slots, and adapt to the project's stack (convert to React/TSX if the repo is79 React; keep the structure and class names).80816. **Be honest about ship status.** Clearly mark un-merged/un-deployed work as "rolling out" or82 "staged" — never imply staged work is live. Check `git status` / whether commits are pushed if83 in doubt.8485## Non-negotiable rules8687- **Benefit-first.** Lead with what the user/customer can now do, not the implementation.88- **No internal jargon.** Translate engineering terms to product impact. "Enabled RLS" → "your89 data is now isolated to your account"; "removed @ts-nocheck / refactor / bumped deps" → omit or90 fold into one "Behind the scenes" line.91- **Never invent.** Every entry must trace to a real commit/PR in the collected JSON. If a commit's92 user impact is unclear, inspect the diff, ask, or omit it — do not fabricate a feature.93- **Sentence case, punchy, scannable.** One screenful per release. Two weights, no ALL CAPS.9495## Portfolio mode (one board across many repos)9697To build a "we ship across everything" board (a portfolio ship index), aggregate multiple repos:98991. Copy `assets/portfolio.config.example.json` and edit the `projects` list (name, local repo100 `path`, `tagline`, `accent`). One entry per app.1012. Run `node <skill-dir>/scripts/collect-portfolio.mjs --config <your-config>.json --days 35`.102 Output JSON has: `totals` (ships_this_week, ships_30d, active_this_week, busiest_day), a merged103 `daily` heatmap map, per-`projects` stats, and the latest cross-project `recent` commits.1043. Render the Ship Index: portfolio stat strip + a 5-week activity heatmap (color cells by daily105 count) + per-project rows (bar width ∝ 30-day commits) + a cross-project recent-ships feed.106 Rewrite `recent[].subject` (raw commit messages) into benefit-first copy per the voice spec.1074. Data source choice when wiring to a real site:108 - **Static/generated** (repos are local or in CI): run the aggregator on a schedule, write the109 JSON into the home-page repo (or an endpoint), and have the page read it. No live git needed.110 - **GitHub-API live**: if every repo is on GitHub, a serverless function can hit the commits API111 per repo and aggregate on request — always fresh, no local step. Needs a token + repo list.112 - Keep cadence claims truthful; show dormant projects honestly (or feature only active ones).113114## Reusable contents115116- `scripts/version.mjs` — the shared semver anchor manager (get/init/set/bump/date on `docs/VERSION`).117- `scripts/collect-history.mjs` — single-repo history collector (run, don't reinvent).118- `scripts/collect-portfolio.mjs` — multi-repo aggregator for the portfolio ship index.119- `assets/portfolio.config.example.json` — example portfolio config.120- `references/voice-and-format.md` — the voice + format spec and worked example.121- `assets/whats-new.html` — a standalone, premium, themeable "What's New" page (version-grouped,122 category filter chips, momentum band; works without JS). Pairs with `docs/SHIPPING-LOG.md`.123- `assets/shipping-log.html` — a dark, on-brand landing "shipping log" section (single product)124 with metric strip, timeline cards, illustration slots, and notes for adapting to React.