Borrowing it
Nothing to install: this file belongs to gug007/lpm. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.
curl -O https://raw.githubusercontent.com/gug007/lpm/main/.claude/skills/lesson-publish/SKILL.mdgit clone --depth 1 https://github.com/gug007/lpmWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/gug007/lpm/lesson-publish)<a href="https://agentmods.dev/skills/gug007/lpm/lesson-publish"><img src="https://agentmods.dev/badge/skills/gug007/lpm/lesson-publish/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/gug007/lpm/lesson-publish"><img src="https://agentmods.dev/badge/skills/gug007/lpm/lesson-publish.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00102 | $0.01743 |
| Opus 5.5 | $0.00041 | $0.00697 |
| Sonnet 5.5 | $0.00020 | $0.00349 |
| Haiku 4.5 | $0.00010 | $0.00174 |
Grade A, and why
lesson-publish scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 14d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 22 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Upload a lesson video to YouTube and publish it.
- run
node scripts/prepare.js <slug or lesson folder> <scratchpad-dir>first. It refuses a lesson whose checks failed or are older than the MP4 (qa/report.json, written by lesson'smake.js); show the user the FAIL lines, and only with their go-ahead pass--accept "<their reason>". It copies the MP4 into the scratchpad under the video title (the file name becomes the initial title in Studio; it warns when that dropped a ":" to retype), the thumbnail (the opening card, rendered bymake.js), the captions (<slug>.srt), and writes<slug>-description.txtand<slug>-tags.txt, and prints the chapters. Chrome'sfile_uploadonly accepts files inside the scratchpad and under 10,000,000 bytes; when the master is larger, prepare.js writes a 1080p HEVC two-pass copy that fits instead (H.264 at that bitrate smears terminal text). YouTube gets the smaller copy; the master stays in the lesson folder. - the description and tags come from
lesson.json"youtube": { "hook": [two lines], "learn": [...], "sections": [...], "tags": [...], "hashtags": [...] }: write that block first when the lesson has none (prepare.js says so), then run prepare.js again, so a replacement upload reuses the same words. - captions: in the Details step's "Subtitles" (or later under Subtitles in Studio), Add language → English → Add subtitles → Upload file → With timing → the
.srtfrom the scratchpad → Publish. They carry the script's own words (lpm,Claude Code,Codex), which YouTube's auto-captions get wrong. In the current dialog Subtitles sits under Video elements and its Add stays greyed until Details → Show more → Video language is set (English); after "With timing", do not press Continue (it opens the macOS file picker):file_uploadthe.srtinto the#captions-file-loaderinput, then Done. - thumbnail: the lesson's own
thumbnail.jpg, never YouTube's auto-pick: with acoverinlesson.jsonit is that cover (words beside a crop of the take on the card canvas, approved 2026-09-30), otherwise the opening title card; prepare.js copies it and it is uploaded in the Thumbnail step. A new channel gets a few custom thumbnails a day; past that the upload answers "Build your channel history" and nothing is set: leave the video a private draft (untick the playlist so no private row shows) and publish the next day with the thumbnail, unless the user says otherwise. - title: the lesson title from
lesson.json, nothing appended (no "(Mac Tutorial)"), brand is lowercaselpm, 100 characters max. - description: prepare.js assembles it in this order: a two-line keyword hook (what the video shows, for whom), one line on what lpm is (starts, stops, duplicates and switches between local dev projects on a Mac, with a built-in terminal for AI coding agents such as Claude Code and Codex), the link
https://lpm.cx(never the demo linklpm.cx/demo, user rule 2026-09-19), "What you'll learn" bullets, anysections([{ "heading", "lines" }]: what a viewer needs first, what to do when a step doesn't match), "Chapters" (first at 0:00, at least three, each 10 s or longer: topic cards and"chapter"narration lines in lesson.json), one series line, 5–6 hashtags (#lpm #macOS #devtools …). No@anywhere (it opens a mention popup) and no next-lesson teaser. - tags: 15–20 comma-separated (lpm, lpm.cx, the lesson's own verbs and nouns, Claude Code, Codex, mac dev tools, tutorial), under 500 characters. Category Science & Technology. Audience "No, it's not made for kids". Visibility Public. Playlist: the one in
YOUTUBE_PLAYLIST.md(repo root: heading = playlist title, then its URL, then the lesson titles in series order). - browser (Claude in Chrome MCP on the user's logged-in Chrome; channel "LPM"):
navigate https://www.youtube.com/upload→findthe file input →file_uploadthe MP4 → wait ~5 s →findthe title and description textboxes, click +type→ Thumbnail "Upload file" input →file_uploadthe JPEG → Audience radio → "Show more" → Tags textbox (type a comma after every tag) → Category: open the menu, take a full-scale screenshot, click the option by coordinate andzoomto verify (a click byfindref lands on the hovered row) → Playlists box (coordinate click) → tick the playlist → Done → Next ×3 → Public radio → Publish → copy the link from the "Video published" dialog. - replacing a published lesson: YouTube cannot swap the file on an existing video, so upload the new cut as a new video (same title, description recipe and thumbnail), then set the old one to Private on
studio.youtube.com/video/<id>/edit(Visibility box → Private → Done → Save; the Save button stays active until the change is saved). Deleting the old video is the user's call. - never press Escape inside the upload dialog: it closes the dialog. The upload is already saved as a private draft; reopen it with "Edit draft" on the row. Later edits go through
studio.youtube.com/video/<id>/edit, then Save. - playlist, after Publish: the video must end up in the playlist from
YOUTUBE_PLAYLIST.md, at the position its title has in that list. Preferred path is inside the upload dialog's Details step: the Playlists box ("Select") sits under the description; open it with a coordinate click (a ref click afterscroll_todid not open it), tick the playlist, Done. If it was skipped, usestudio.youtube.com/video/<id>/edit→ Playlists → tick → Done → Save. The playlist is manually sorted and a new video is appended last, so uploading in series order needs nothing more; otherwise openhttps://www.youtube.com/playlist?list=<id>on the logged-in account, and use the row's ⋮ menu (Move to top / Move to bottom) or drag the ≡ handle until the order matches the file. Then runnode scripts/register.js <slug> <youtu.be link>: it records the upload in the lesson folder (published.json), puts the link on the lesson's line inYOUTUBE_PLAYLIST.md(appending the line when it is missing; move it to its series position if needed) — that file is the order of record — and prints the entry forwebsite/lib/youtube-lessons.ts; add it there and link it from the page about that feature. Studio's playlist page (studio.youtube.com/playlist/<id>/videos) lists and removes videos but cannot reorder them. - verify before reporting: the row in Channel content shows Public, the thumbnail is the beige title card, the title has no suffix, and the playlist page shows the video in the right position. Report the youtu.be link, the title, the description text and the playlist position. External links stay plain text until the channel completes YouTube's one-time verification (a phone step only the user can do); say so once.
What ships with it
2 files beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 14d ago Changed 8706168359ec
- 23d ago First seen · 22 lines · 102 tokens per session scan A 490def42c67a
lesson-publish is a skill published in the GitHub repository gug007/lpm (145 stars, last pushed today), licensed MIT. It adds 102 tokens to every session and 1,743 once invoked, about $0.0004 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-10-01.
Other skills, from other repositories
orca-emulator-android
Android device and emulator control from inside Orca over adb, with the live device view in Orca's emulator pane. Use when driving an adb-connected emulator or phone on Windows, Linux, or macOS: booting AVDs, taps, swipes, typing, hardware buttons, rotation, app install and launch, runtime permissions, the…
ralplan
Consensus planning entrypoint that auto-gates vague ralph/autopilot/team requests before execution.
remember
Review reusable project knowledge and decide what belongs in project memory, notepad, or durable docs.
test-warp-ui
Guides testing Warp UI features and changes using the computer use tool. Use this skill only when computer-use testing was requested (explicit request or accepted offer) and the computeruse tool is available to the agent. Covers launching Warp and verifying UI behavior.
tui-migrate-setup
Migrates the supported subset of an existing Warp GUI setup into Warp Agent CLI without exposing credentials or application state. Use in Warp Agent CLI when a user wants to copy or move compatible settings or global file-based MCP servers from the desktop app, set up Warp Agent CLI from an existing GUI installation…
blueprint-cloudflare-scaffold
Lay out a Worker with D1 and static Vue assets, with tests that run inside the Workers runtime.