Ship feed
Docs + release skill toolkit for Claude Code: versioned user guides, benefit-first changelogs, screenshots, logos, brand kit, help bot, and more — driven by one brand.json + docs/VERSION.
npx -y skills add taskmasterpeace/ship-pack --skill ship-feedAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Turns a project's shipping log into machine-readable data plus an embeddable changelog widget. Parses docs/SHIPPING-LOG.md + docs/VERSION into a structured docs/changelog.json (releases with version, date, and items grouped by category), then emits an RSS/Atom feed (docs/changelog.xml) and a self-contained, brand-themed <ship-changelog> web component + static HTML embed that read that JSON. For a company-page "What's new" section, an in-app "What's new" badge, and a subscribe-able feed. Use when the user wants a changelog API or JSON, an RSS/Atom changelog feed, a "what's new" widget or web component, an embeddable changelog, a release feed, or to make their shipping log machine-readable / syndicatable. Triggers on "changelog as data", "changelog.json", "RSS feed for releases", "what's new widget", "embed the changelog", "release feed", "ship-feed". Part of the /ship-* pack.
SKILL.md
10.2 KB, as published. Nobody here has run it
Ship Feed
Purpose
A shipping log is great prose, but prose can't be embedded, subscribed to, or read by code. This skill makes the same release history machine-readable and embeddable:
docs/changelog.json— structured releases (version, date, title, summary, items by category)docs/changelog.xml— an RSS 2.0 (or Atom 1.0) feed of releases, for feed readers + botsdocs/ship-changelog.js— a self-contained<ship-changelog>web component (full or badge)docs/whats-new.embed.html— a static, data-inlined page for an<iframe>or a no-JS host
All four are static, brand-themed from docs/brand.json, and derive from one source of truth —
your existing shipping log. Write the prose once (with shipping-log); syndicate it everywhere.
Part of the /ship-* pack
ship-feed is the distribution layer of the docs + release pack. It consumes what the other
skills produce; it never invents content.
docs/VERSION ── single semver anchor ──┐
docs/brand.json ── brand as data ───────┤
docs/SHIPPING-LOG.md (← shipping-log) │
│ parse │
▼ ▼
docs/changelog.json ──► docs/changelog.xml (RSS/Atom feed)
│ ──► docs/ship-changelog.js (<ship-changelog> component)
│ ──► docs/whats-new.embed.html (iframe / no-JS embed)
shipping-logwrites/ownsdocs/SHIPPING-LOG.mdand the prosedocs/whats-new.html. Run it first — this skill parses its output. If the log is missing, stop and offer to run it.user-guide-builder+screenshot-captureshare the samedocs/VERSIONanchor so "what changed" and "how it works" stay in lockstep.logo-packand the renderers all read the samedocs/brand.json.
The widget links and the feed point back to whats-new.html#v<version>, so the data layer and
the prose page reinforce each other.
Discovery first (don't act blind)
Before generating anything, inspect what already exists and report it:
- Inputs present?
node <skill>/scripts/version.mjs get→ current semver (or "no anchor").- Read
docs/brand.json(colors + fonts). If absent, the renderers fall back to a neutral slate+blue theme (never purple) — note that in your report and offer to createbrand.json. ls docs/SHIPPING-LOG.md— required. If missing, stop and offer to runshipping-log.
- Prior outputs?
ls docs/changelog.json docs/changelog.xml docs/ship-changelog.js docs/whats-new.embed.html— note what you'll be regenerating so the user knows what changes. - Deploy target? Ask (or infer) the public site URL for absolute feed links and whether they want RSS or Atom, and whether they need the component, the iframe embed, or both.
version.mjs is shared with the pack — call it, don't reinvent version handling.
Workflow
Run scripts from the repo root; reference them by absolute skill path. They are
dependency-free .mjs (Node ≥ 16, cross-platform) — run them, never inline their logic.
-
Parse the log into data.
node <skill>/scripts/parse-changelog.mjs --pretty --site-url https://<your-site>Reads
docs/SHIPPING-LOG.md(+docs/VERSION,docs/brand.json), writesdocs/changelog.json. It printsN release(s), M item(s). Read the printed counts — if it warns "parsed 0 releases", the log isn't in the pack's## v1.2.3 — YYYY-MM-DDshape; fix the headings (or regenerate viashipping-log) rather than hand-editing JSON. -
Emit the feed.
node <skill>/scripts/emit-feed.mjs --format rss --site-url https://<your-site> # Atom instead: --format atom --out docs/changelog.atom.xmlOne
<item>/<entry>per release; categories become<category>tags; the release body is HTML-in-CDATA so readers render it. Pass--site-urlfor portable absolute links. -
Render the widget(s).
node <skill>/scripts/render-widget.mjs --mode bothWrites
docs/ship-changelog.js(the<ship-changelog>component) anddocs/whats-new.embed.html(static embed). Both are themed fromdocs/brand.json. Use--mode componentor--mode pageto emit just one.--src <url>sets the JSON URL the component fetches at runtime (default./changelog.json). -
Verify before declaring done.
node --check docs/ship-changelog.js(valid JS).- Confirm
<item>open/close counts match in the XML and that--site-urlproduced absolute links. - Grep the outputs for
backdrop-filter/feTurbulence— there must be none in real CSS (they hang renderers). - Spot-check
changelog.jsonstatsagainst the log (release + item counts).
-
Wire it up. Read
references/embedding.mdand give the user the exact snippets for their case: company-page component, in-app badge (badge limit="1"+ the unread-dot pattern), the<iframe>embed, and the<link rel="alternate">feed auto-discovery tag. -
Report honestly. State what was generated, the release/item counts, whether
brand.jsonthemed it or defaults were used, whether links are absolute (site URL known) or relative, and which categories appeared. If you regenerated existing files, say so.
Worked example (real input → real output)
Input — docs/SHIPPING-LOG.md (MyFieldTime), heading + first bullet:
## v0.8.0 — 2026-06-17 · Money & decisions
_The homeowner finally sees the money — and signs off without the email chase._
### ✨ New
- **Money & Progress portal for homeowners.** Clients open one page to see how much of the
budget is spent, what's left, and how far along the job is — no spreadsheet, no phone call.
Run: parse-changelog.mjs --pretty --site-url https://myfieldtime.com
Output — docs/changelog.json (excerpt): 3 release(s), 18 item(s), the bold lead split
from its body, the italic line captured as summary:
{
"$schema": "ship-feed/changelog@1",
"product": "MyFieldTime", "tagline": "Run your jobs. Not your inbox.",
"currentVersion": "0.8.0",
"stats": { "releases": 3, "items": 18, "latestVersion": "0.8.0", "latestDate": "2026-06-17" },
"releases": [{
"version": "0.8.0", "date": "2026-06-17", "title": "Money & decisions", "id": "v0.8.0",
"summary": "The homeowner finally sees the money — and signs off without the email chase.",
"items": [{
"category": "new",
"title": "Money & Progress portal for homeowners",
"body": "Clients open one page to see how much of the budget is spent, what's left, and how far along the job is — no spreadsheet, no phone call."
}]
}]
}
Then emit-feed.mjs turns the same release into:
<item>
<title>MyFieldTime 0.8.0 — Money & decisions</title>
<link>https://myfieldtime.com/whats-new.html#v0.8.0</link>
<guid isPermaLink="false">v0.8.0</guid>
<pubDate>Wed, 17 Jun 2026 12:00:00 GMT</pubDate>
<category>new</category> …
</item>
…and render-widget.mjs themes the <ship-changelog> component with MyFieldTime's tokens
(--sc-brand: #2f7dff; --sc-accent: #FFDD00;) — on-brand, never purple.
Quality bar
Hold the output to this standard before you call it done:
- Faithful, not generative. Every datum traces to a line in
SHIPPING-LOG.md. The scripts parse; they never write copy. If the data looks thin, the log is thin — fix it upstream withshipping-log, don't pad the JSON. - The JSON is a real contract. Matches
references/data-contract.md, carries$schema, newest-first releases, canonical category ids. A downstream app can depend on its shape. - Valid, well-formed feeds. XML escapes correctly, dates are RFC-822 (RSS) / RFC-3339 (Atom), links are absolute when a site URL is known. It validates in a feed reader.
- Self-contained, themeable, on-brand. The widget inlines all its CSS/JS (Shadow DOM), pulls
colors + fonts from
brand.json, exposes--sc-*tokens for host overrides, and defaults to a neutral slate+blue — never purple. Nobackdrop-filter, no SVGfeTurbulence. - Honest about freshness + status. The feed reflects the log at parse time; re-run after each
release (or wire into
/ship-release). Don't imply a live API where there's a static file. - Cross-project. Nothing is hardcoded to one app — product name, tagline, colors, version,
and site URL all come from that project's
docs/. Deploy targets are referenced via adapters (any static host / CDN / CI), never assumed.
Reusable contents
scripts/parse-changelog.mjs—SHIPPING-LOG.md(+ VERSION + brand) →changelog.json.scripts/emit-feed.mjs—changelog.json→changelog.xml(RSS 2.0 or Atom 1.0).scripts/render-widget.mjs—changelog.json→ship-changelog.js+whats-new.embed.html.scripts/version.mjs— the shared pack semver anchor manager (get/init/set/bump/date).references/data-contract.md— thechangelog.jsonschema + downstream-stability rules.references/embedding.md— copy-paste snippets: company page, in-app badge, iframe, RSS link, host theming, and the renderer-safety rules.