Files
blog/.claude/skills/mt-add-url/SKILL.md
T
tiennm99 baab3d443a refactor(skills): invoke the Node engine and centralise the command reference
Switches every call site to `node scripts/newsletter` and, in the same pass,
fixes three structural problems in the skill layer.

The seven subcommands were spelled out in five files; they are now enumerated
once in docs/newsletter/engine-commands.md, and every other mention is a link
except where a skill inlines the one or two commands it actually invokes. The
shared post mechanics move out of mt-add-url's directory into docs/newsletter/,
so no skill owns another skill's documentation and both runtimes reach it by a
repository-relative path. The Codex adapters become symlinks to their canonical
counterparts, which removes the parallel frontmatter that could drift.

Two skills are renamed for a uniform mt-<verb>-<object> scheme: mt-add-post
becomes mt-add-article, since it adds an article to a post, and mt-webfetch
becomes mt-fetch-url. The other four already conformed. Note that $mt-add-post
and mt-webfetch no longer resolve; no alias directories are left behind, because
two names for one skill is the duplication this change removes.

Trigger wording in the frontmatter descriptions is left alone apart from the
renamed tokens and the corrected fetch-tier summary: those strings are how the
runtimes decide whether to invoke a skill.

Setup documentation now states the npm ci prerequisite. The engine has
dependencies, so unlike its predecessor it does not run on a bare clone.
2026-09-18 16:24:34 +07:00

4.7 KiB

name, description
name description
mt-add-url Meta entry for adding URLs to the Hugo blog newsletter. Use whenever the user provides one or more URLs to add to their newsletter (articles, YouTube videos, images, etc.). Classifies each URL and auto-dispatches to the right handler skill (mt-add-article for articles, mt-add-video for YouTube, mt-add-image for images). For unsupported types it asks the user how to proceed. This is the default entry point for newsletter URL processing.

Overview

mt-add-url is the meta dispatcher: it classifies each URL and auto-invokes the matching handler skill. Handlers (mt-add-article, mt-add-video, mt-add-image) own the actual content writing. The shared engine lives in scripts/newsletter/ — see docs/newsletter/engine-commands.md for every command it offers, and docs/newsletter/post-mechanics.md for shared post mechanics.

Supported routes (this version):

  • article → mt-add-article
  • youtube → mt-add-video
  • image → mt-add-image

Everything else (direct video file, document, or anything unrecognized) is not supported yet → ask the user how to handle it.

Workflow

1. Classify each URL

For every URL the user provides:

node scripts/newsletter add-url "<url>"

Output (JSON): { original_url, clean_url, http_status, accessible, duplicate, route, title?, author? }.

  • route ∈ youtube | image | video | document | article
  • For youtube, clean_url is the canonical https://www.youtube.com/watch?v=ID and title/author come from oEmbed.

2. Skip non-actionable URLs

  • duplicate: true → skip, note in report (already in a newsletter).
  • accessible: false → not an automatic skip. The classifier does a plain fetch, so a bot-blocked host (403, Cloudflare challenge) reports accessible: false even when the page is public and the fallback fetchers can read it. Dispatch on route as normal and let the handler's fetch chain decide; only report the URL as skipped when every fetcher in mt-fetch-url has failed. A 404/dead URL is a genuine skip.

3. Dispatch on route

route Action
article Invoke the mt-add-article skill, passing clean_url
youtube Invoke the mt-add-video skill, passing clean_url
image Invoke the mt-add-image skill, passing clean_url
video (direct file) / document / anything else Fallback — see step 4

Dispatch by calling the Skill tool for the chosen handler with clean_url as the argument. The handler completes the write end-to-end.

Multiple URLs: dispatch sequentially (one handler finishes before the next starts) — handlers edit the same daily index.md, so concurrent edits would clobber each other. Process article(s) and video(s) one at a time.

4. Fallback for unsupported types

When route is not article, youtube, or image, do NOT write anything automatically. Use AskUserQuestion:

  • Question: "URL type <route> isn't supported yet (<clean_url>). How do you want to handle it?"
  • Options:
    • "Add a new skill" — e.g. a handler for this type. (Recommended for a type you'll reuse.)
    • "Update an existing skill" — extend a handler to support this URL type.
    • "Skip this URL" — leave it out of the newsletter.

Act on the user's choice. If they choose add/update, proceed to design that skill change (or hand off to a planning step); do not silently route the URL into a post.

5. Final report

Close with the target post's TL;DR tally, then the per-URL detail. Read the tally from the post itself so it reflects everything the post now holds, not just this batch:

node scripts/newsletter post-stats content/post/YYYY/MM/DD/index.md

Aggregate across all URLs:

✅ Newsletter URL Dispatch Complete

📊 Newsletter #[number]: [articles] articles · [videos] videos · [images] images
   (omit zero counts; documents too when present)

✅ Dispatched: [count]
   - [count] → mt-add-article (articles)
   - [count] → mt-add-video (YouTube)
   - [count] → mt-add-image (images)

⏭️  Skipped: [count]
   - [url]: duplicate / inaccessible

❓ Unsupported: [count]
   - [url] (route: [route]): [user decision]

The tally is report-only — never write it into index.md. See Post tally in docs/newsletter/post-mechanics.md.

Notes

  • Handlers (mt-add-article, mt-add-video, mt-add-image) remain directly invocable for single-purpose use, but mt-add-url is the normal entry point when a user pastes a URL.
  • Shared mechanics (numbering, post find/create, Bonus insertion, language rules) are defined once in docs/newsletter/post-mechanics.md; handlers reference it.