/product-update-logger
Tell the skill what your product shipped. It writes a polished dated entry to a living docs/changelog.md and produces a ready-to-use content package: tweet thread, LinkedIn post, email snippet, and one-liner.
$ npx -y skills add Varnan-Tech/opendirectory --skill product-update-logger --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/product-update-logger
Context preview
The summary Claude sees to decide when to auto-load this skill.
Tell the skill what your product shipped. It writes a polished dated entry to a living docs/changelog.md and produces a ready-to-use content package: tweet thread, LinkedIn post, email snippet, and one-liner.
SKILL.md
product-update-logger.SKILL.mdname: product-update-logger
description: "Tell the skill what your product shipped. It writes a polished dated entry to a living docs/changelog.md and produces a ready-to-use content package: tweet thread, LinkedIn post, email snippet, and one-liner."
product-update-logger
Tell this skill what your product shipped. It writes a polished changelog entry to `docs/changelog.md` (a living log, newest entry first) and simultaneously produces a content package: tweet thread, LinkedIn post, email snippet, and one-liner.
Input sources: free text from your message, git commits auto-read from the local repo, or GitHub PRs if you provide a repo. Any combination works.
Reference Files
Read these files before each run:
cat references/changelog-format.md
cat references/content-rules.md
cat references/noise-filter.md
---
Step 1: Setup Check
echo "GITHUB_TOKEN: ${GITHUB_TOKEN:-not set -- GitHub PR fetching disabled}"
echo "Git: $(git rev-parse --is-inside-work-tree 2>/dev/null && echo 'repo detected' || echo 'not a git repo')"
echo "Changelog: $(ls docs/changelog.md 2>/dev/null && echo 'exists' || echo 'will be created')"Note whether git is available and whether a changelog already exists. This determines the version label format.
---
Step 2: Parse Input
Collect from the conversation:
- `items` -- free text description of what shipped (pipe-separated if multiple). Optional if git is available.
- `since` -- how many days back to look. Default: 7. User may say "last 2 weeks" (14) or "since last release."
- `repo` -- GitHub "owner/repo" for PR fetching. Optional.
- `version_label` -- custom label like "v2.1.0" or "The Speed Update." Optional; default is date-based.
**If the user said nothing about items AND there is no git repo:** Ask "What did you ship? List the features, fixes, or improvements -- one per line."
**If git is available and user said nothing specific:** Proceed with git auto-read in Step 3. Show the user what was found and confirm before transforming.
Write parsed input:
python3 << 'PYEOF'
import json, os, re
inp = {
"items": "", # FILL: pipe-separated free text, or "" if none
"since": 7, # FILL: integer days
"repo": "", # FILL: "owner/repo" or ""
"version_label": "" # FILL: "" means auto (date-based), or custom string
}
with open("/tmp/pul-input.json", "w") as f:
json.dump(inp, f, indent=2)
print(f"Since: {inp['since']} days")
print(f"Free text items: {inp['items'] or 'none (will use git/GitHub)'}")
print(f"GitHub repo: {inp['repo'] or 'none'}")
print(f"Version label: {inp['version_label'] or 'auto (date-based)'}")
PYEOF---
Step 3: Run the Gather Script
ls scripts/gather.py 2>/dev/null && echo "script found" || echo "ERROR: scripts/gather.py not found"
GITHUB_TOKEN="${GITHUB_TOKEN:-}" python3 scripts/gather.py \
--since "$(python3 -c "import json; print(json.load(open('/tmp/pul-input.json'))['since'])")" \
--repo "$(python3 -c "import json; print(json.load(open('/tmp/pul-input.json'))['repo'])")" \
--items "$(python3 -c "import json; print(json.load(open('/tmp/pul-input.json'))['items'])")" \
--output /tmp/pul-raw.jsonVerify output:
python3 -c "
import json
with open('/tmp/pul-raw.json') as f:
d = json.load(f)
print(f'Items found: {d[\"total_items\"]}')
print(f'Noise filtered: {d[\"noise_filtered\"]}')
print(f'Git available: {d[\"git_available\"]}')
print(f'GitHub available: {d[\"github_available\"]}')
print(f'Sources: git={sum(1 for i in d[\"items\"] if i[\"source\"]==\"git_commit\")}, '
f'prs={sum(1 for i in d[\"items\"] if i[\"source\"]==\"github_pr\")}, '
f'text={sum(1 for i in d[\"items\"] if i[\"source\"]==\"free_text\")}')
print()
print('Items:')
for item in d['items']:
print(f' [{item[\"source\"]}] {item[\"subject\"]}')
"**If total_items == 0:** Stop. Tell the user: "No shipped items found. Either describe what you shipped, point me to a git repo with recent commits, or add a GitHub repo with `repo: owner/repo` and a GITHUB_TOKEN."
**Show the item list to the user and ask: "These are the items I found. Anything to add or remove before I write the changelog?"**
Wait for confirmation or edits. If the user says "looks good", "proceed", or makes no changes, continue. If the user adds or removes items, update `/tmp/pul-raw.json` accordingly before Step 4.
---
Step 4: Generate Changelog Entry
Print items for context:
python3 -c "
import json
with open('/tmp/pul-raw.json') as f:
d = json.load(f)
print(json.dumps(d['items'], indent=2))
print()
print(f'Existing changelog format: {d[\"existing_changelog\"][\"format\"]}')
print(f'Last label: {d[\"existing_changelog\"][\"last_label\"]}')
print(f'Today: {d[\"date\"]}')
"**AI instructions:** Transform each raw item from technical language to user-facing benefit language. Follow `references/changelog-format.md` for transformation rules and examples.
Rules:
- **Do NOT invent outcomes or metrics.** "40% faster" must come from the source data. If no number is in the commit or PR, do not add one.
- **Use past tense:** "Added", "Fixed", "Improved" -- not "Adds", "Fixes"
- **Assign exactly one category** to each item: New, Improved, Fixed, or Under the hood
- **Under the hood:** Only include if developer-relevant (API changes, breaking changes). Omit empty sections.
- **Omit** anything that maps to: test changes, CI changes, documentation-only commits
Determine version label:
- If user specified one: use it exactly
- If `existing_changelog.format == "semver"`: increment based on changes (patch for fixes only, minor for any new feature)
- Default: `Week of [Month Day, Year]` using today's date
Write the entry to `/tmp/pul-entry.json`:
{
"label": "Week of April 23, 2026",
"date": "2026-04-23",
"new": [
{"title": "Dark mode", "description": "Toggle in Settings > Appearance. WorkRead more
name: product-update-logger description: "Tell the skill what your product shipped. It writes a polished dated entry to a living docs/changelog.md and produces a ready-to-use content package: tweet thread, LinkedIn post, email snippet, and one-liner."
product-update-logger
Tell this skill what your product shipped. It writes a polished changelog entry to `docs/changelog.md` (a living log, newest entry first) and simultaneously produces a content package: tweet thread, LinkedIn post, email snippet, and one-liner.
Input sources: free text from your message, git commits auto-read from the local repo, or GitHub PRs if you provide a repo. Any combination works.
Reference Files
Read these files before each run:
cat references/changelog-format.md cat references/content-rules.md cat references/noise-filter.md
---
Step 1: Setup Check
echo "GITHUB_TOKEN: ${GITHUB_TOKEN:-not set -- GitHub PR fetching disabled}"
echo "Git: $(git rev-parse --is-inside-work-tree 2>/dev/null && echo 'repo detected' || echo 'not a git repo')"
echo "Changelog: $(ls docs/changelog.md 2>/dev/null && echo 'exists' || echo 'will be created')"Note whether git is available and whether a changelog already exists. This determines the version label format.
---
Step 2: Parse Input
Collect from the conversation:
- `items` -- free text description of what shipped (pipe-separated if multiple). Optional if git is available.
- `since` -- how many days back to look. Default: 7. User may say "last 2 weeks" (14) or "since last release."
- `repo` -- GitHub "owner/repo" for PR fetching. Optional.
- `version_label` -- custom label like "v2.1.0" or "The Speed Update." Optional; default is date-based.
**If the user said nothing about items AND there is no git repo:** Ask "What did you ship? List the features, fixes, or improvements -- one per line."
**If git is available and user said nothing specific:** Proceed with git auto-read in Step 3. Show the user what was found and confirm before transforming.
Write parsed input:
python3 << 'PYEOF'
import json, os, re
inp = {
"items": "", # FILL: pipe-separated free text, or "" if none
"since": 7, # FILL: integer days
"repo": "", # FILL: "owner/repo" or ""
"version_label": "" # FILL: "" means auto (date-based), or custom string
}
with open("/tmp/pul-input.json", "w") as f:
json.dump(inp, f, indent=2)
print(f"Since: {inp['since']} days")
print(f"Free text items: {inp['items'] or 'none (will use git/GitHub)'}")
print(f"GitHub repo: {inp['repo'] or 'none'}")
print(f"Version label: {inp['version_label'] or 'auto (date-based)'}")
PYEOF---
Step 3: Run the Gather Script
ls scripts/gather.py 2>/dev/null && echo "script found" || echo "ERROR: scripts/gather.py not found"
GITHUB_TOKEN="${GITHUB_TOKEN:-}" python3 scripts/gather.py \
--since "$(python3 -c "import json; print(json.load(open('/tmp/pul-input.json'))['since'])")" \
--repo "$(python3 -c "import json; print(json.load(open('/tmp/pul-input.json'))['repo'])")" \
--items "$(python3 -c "import json; print(json.load(open('/tmp/pul-input.json'))['items'])")" \
--output /tmp/pul-raw.jsonVerify output:
python3 -c "
import json
with open('/tmp/pul-raw.json') as f:
d = json.load(f)
print(f'Items found: {d[\"total_items\"]}')
print(f'Noise filtered: {d[\"noise_filtered\"]}')
print(f'Git available: {d[\"git_available\"]}')
print(f'GitHub available: {d[\"github_available\"]}')
print(f'Sources: git={sum(1 for i in d[\"items\"] if i[\"source\"]==\"git_commit\")}, '
f'prs={sum(1 for i in d[\"items\"] if i[\"source\"]==\"github_pr\")}, '
f'text={sum(1 for i in d[\"items\"] if i[\"source\"]==\"free_text\")}')
print()
print('Items:')
for item in d['items']:
print(f' [{item[\"source\"]}] {item[\"subject\"]}')
"**If total_items == 0:** Stop. Tell the user: "No shipped items found. Either describe what you shipped, point me to a git repo with recent commits, or add a GitHub repo with `repo: owner/repo` and a GITHUB_TOKEN."
**Show the item list to the user and ask: "These are the items I found. Anything to add or remove before I write the changelog?"**
Wait for confirmation or edits. If the user says "looks good", "proceed", or makes no changes, continue. If the user adds or removes items, update `/tmp/pul-raw.json` accordingly before Step 4.
---
Step 4: Generate Changelog Entry
Print items for context:
python3 -c "
import json
with open('/tmp/pul-raw.json') as f:
d = json.load(f)
print(json.dumps(d['items'], indent=2))
print()
print(f'Existing changelog format: {d[\"existing_changelog\"][\"format\"]}')
print(f'Last label: {d[\"existing_changelog\"][\"last_label\"]}')
print(f'Today: {d[\"date\"]}')
"**AI instructions:** Transform each raw item from technical language to user-facing benefit language. Follow `references/changelog-format.md` for transformation rules and examples.
Rules:
- **Do NOT invent outcomes or metrics.** "40% faster" must come from the source data. If no number is in the commit or PR, do not add one.
- **Use past tense:** "Added", "Fixed", "Improved" -- not "Adds", "Fixes"
- **Assign exactly one category** to each item: New, Improved, Fixed, or Under the hood
- **Under the hood:** Only include if developer-relevant (API changes, breaking changes). Omit empty sections.
- **Omit** anything that maps to: test changes, CI changes, documentation-only commits
Determine version label:
- If user specified one: use it exactly
- If `existing_changelog.format == "semver"`: increment based on changes (patch for fixes only, minor for any new feature)
- Default: `Week of [Month Day, Year]` using today's date
Write the entry to `/tmp/pul-entry.json`:
{
"label": "Week of April 23, 2026",
"date": "2026-04-23",
"new": [
{"title": "Dark mode", "description": "Toggle in Settings > Appearance. WorkAI Agent Skills built for Founders who hate Marketing
Repo: Varnan-Tech/opendirectory
Other skills on opendirectory-gtm-skills.
- /app-store-review-arbitrage
Fetches low-star App Store and Google Play reviews, clusters them into broken-promise patterns, and generates a ranked copy brief with positioning opportunities.
Open skill - /blog-cover-image-cli
Use when the user asks to generate a blog cover image, thumbnail, or article header. Automatically uses modern typography, brand logos, and Google Search grounding to create beautiful 16:9 images with Gemini 3.1 Flash Image Preview.
Open skill - /brand-alchemy
World-class brand strategist and naming expert. Uses an interrogation-led discovery phase to extract your brand's DNA, then applies scientific naming frameworks (Phonosemantics) and automated multi-TLD domain checking.
Open skill - /claude-md-generator
Use when the user asks to generate or update a project's CLAUDE or AGENTS context file from a codebase scan. Writes a focused file under 100 lines containing only the non-obvious build commands, conventions, and gotchas Claude Code needs.
Open skill - /cold-email-verifier
Use when the user wants to verify cold emails, enrich a lead list, or autonomously guess email addresses from a CSV using ValidEmail.co or the open-source Reacher engine.
Open skill - /company-radar
Competitive intelligence orchestrator tracking companies across 8+ platforms (GitHub, Twitter, Reddit, HN, PH, YC Jobs) with heat scores and AI briefings.
Open skill

