.claude/skills/newsletter-writer/SKILL.md
Write personal newsletters in a conversational, essay-style format inspired by Ali Abdaal's style. Use when the user wants to write a newsletter issue, draft an email to their list, write a LifeNotes-style essay, or asks for help with newsletter writing. Triggers on requests like "write a newsletter", "draft a newsletter about...", "help me write my weekly email", "newsletter style", or when the user provides a topic and wants it turned into a newsletter format.
npx skillsauth add theramjad/ray-os newsletter-writerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Write newsletters that feel like a friend talking to you over coffee, not a blog post or corporate email.
Never use em dashes (—) or en dashes (–) anywhere in newsletter output. Use commas, periods, parentheses, "like", "such as", or rewrite the sentence instead.
This rule overrides anything else in this skill, including the Ali Abdaal style calibration in references/examples.md which uses em dashes liberally. The examples are for tone and rhythm, not punctuation. Ray doesn't like dashes in his writing and flagged this specifically, so treat it as a hard constraint.
If you're tempted to use a dash for an aside or pivot, that's usually a sign the sentence wants to become two sentences, or that the aside belongs in parentheses. Both options preserve the spoken rhythm without the dash.
Before presenting any draft, mechanically scan the output for — and – and remove every instance. This is non-optional. In past sessions, em dashes kept slipping through during iterative edits because "I know the rule" isn't enough. Run a literal search.
"failing tests", the moment not "failing tests," the moment.For any video-redirect newsletter, a video thumbnail is mandatory, not optional. Every draft in the output must include a [VIDEO THUMBNAIL + LINK] placeholder inside the body (typically after the 2nd or 3rd paragraph, before the "here's what I mean" elaboration). If the user hasn't supplied a thumbnail image, ask for one before presenting the drafts. Do not produce a video-redirect newsletter without a thumbnail, it's the CTA of the entire email.
When you have a thumbnail path, run the bundled script to overlay a YouTube-style play button:
python3 scripts/add-play-button.py <input_thumbnail> [output_path]
By default the script resizes the output to 1280×720 at JPEG quality 80, which produces a ~100KB file suitable for email. You can override with --max-width and --quality if needed, but the defaults are usually correct.
<name>-play.<ext> next to the originalCTA questions close the email with a reply prompt. The framing depends on the newsletter type:
For feature-announcement / product-launch newsletters (where the reader will obviously adopt the feature), CTAs must be forward-looking. Assume adoption. Ask about what they'll do with the feature, not how they were handling things before it.
For evergreen / opinion / reflection newsletters, the traditional "share your experience" framing still works.
Always make CTAs specific to the topic, never generic "what do you think?" prompts.
The typical input is a video transcript that needs to be turned into a short, video-redirect newsletter (not a full essay retelling the video). The output is 5 body variations plus a global pool of 10 subject lines and 10 preview snippets. Ray picks one body, one subject, and one preview, and copies the trio.
5 Newsletter Variations (the bodies), each with a different opening hook/angle. Label each with its hook strategy so Ray can scan quickly. Each variation is a complete, sendable draft (not just the opening paragraph), and each one must include the [VIDEO THUMBNAIL + LINK] placeholder in the body. Hook strategies to mix between:
10 Subject Lines (global pool). One shared set of 10 subject line options that can plausibly pair with any of the 5 body variations. Aim for a spread of angles so there's at least one strong subject for each body's hook, rather than five that only fit one variation. Mix between mystery/curiosity, direct statement, problem/pain point, quotable moment, casual/conversational, and stealth-launch framings.
10 Preview Snippets (global pool). One shared set of 10 one-sentence tease lines that complement the subjects without repeating them. Same logic as the subjects, these should be hook-agnostic enough that Ray can pair any preview with any body.
5 CTA Questions. Close the email with a reply prompt. Apply the CTA framing rules above (forward-looking for feature announcements, experience-sharing for evergreen).
Earlier versions of this skill paired 5 subjects and 5 previews per variation, which meant subjects were tightly coupled to the body's hook. That forced a rigid mental model (pick a body first, then pick from its 5 subjects) and cluttered the email reading view with picker UI. Ray preferred moving subjects and previews onto a dedicated "Headlines" page with one global pool of each, so the email view stays clean and he can mix any subject with any body. When generating the 10, write them broad enough that most of them pair sensibly with at least 2-3 of the 5 body variations.
When presenting in markdown, write the 5 bodies first, then a "Subject line options" list of 10, then a "Preview snippet options" list of 10, then the CTA questions. When presenting in the HTML viewer, the bodies, subjects, and previews all flow into the template (see the HTML Viewer section). The viewer puts subjects and previews on a dedicated "Headlines" tab so they don't clutter the email page.
When Ray asks to see the variations "in an HTML thing", "in a viewer", "as HTML", or similar, render the 5 newsletter variations using the bundled Gmail-style template at references/gmail-viewer-template.html. This is faster to scan than a wall of markdown.
How to use:
references/gmail-viewer-template.html to see the structure<topic>-newsletter-options.html in the working directory)__VARIATIONS_JSON__ placeholder with an array of 5 variation objects, each containing:
hook: the hook strategy label (e.g., "Polling Is Dead")body: an array of paragraph strings (use "[THUMBNAIL]" as a paragraph entry to mark where the video thumbnail goes)__SUBJECTS_JSON__ placeholder with an array of exactly 10 subject line strings (the global pool)__PREVIEWS_JSON__ placeholder with an array of exactly 10 preview snippet strings (the global pool)__THUMBNAIL_PATH__ with the relative path to the play-button thumbnail__VIDEO_URL__ with the YouTube URL__TOPIC__ with a short topic label for the page titleopen the resulting HTML fileThe viewer has three modes in the topbar: Inbox (default, shows the active body variation in a Gmail-style reading pane), Headlines (the dedicated page for the 10 subjects + 10 previews, two columns side by side), and Compare all (horizontal scroll of all 5 body variations side by side). Keyboard shortcuts: 1-5 jump to a variation, i / Escape returns to inbox, h opens Headlines, c opens Compare.
Subject and preview selection is global (one active pair), so whatever Ray picks on the Headlines tab instantly applies to every body variation's header in the inbox and compare views. This keeps the email reading page clean while still letting him mix and match pairs in one click.
Some newsletters include bonus content below the sign-off, like system prompts, code snippets, checklists, or reference material the reader can bookmark. When the content lends itself to this:
--- divider after the sign-offsocials/youtube/transcripts/, fetch one via python3 ~/.claude/skills/supadata/scripts/supadata.py transcript <video_id>. Don't assume the transcript is already on disk, check first.references/examples.md to calibrate tone and structure (remember to ignore its em dash usage, see the hard rule at the top of this file)[VIDEO THUMBNAIL + LINK] placeholder in the body.— and – and remove them. Replace with commas, periods, parentheses, or a rewrite. Do this even if you "know" you didn't add any, they sneak in.scripts/add-play-button.py on it, which auto-resizes to 1280×720 at quality 80.references/gmail-viewer-template.html.references/examples/ for future reference and performance tracking.See references/examples.md for 5 full Ali Abdaal newsletters that demonstrate this style in action. Read this file when writing to calibrate tone and structure, but remember: ignore its em dash usage. The examples are for voice, rhythm, and structure only. Ray's hard rule against dashes overrides anything you see in those examples.
content-media
Edit raw screen recording videos with synced audio. Removes repeated takes, false starts, silence, filler, and [MUSIC] tags to produce a clean final cut. Use when the user provides a raw/unedited MP4 video file and wants it edited down. Triggers on: "edit this video", "cut this video", providing a raw MP4 for editing, or any request to remove bad takes from a recording.
tools
Monitor Twitter/X for trending AI and developer tool discussions, score them, and deliver pre-digested content briefs. Use this skill whenever the user wants to find trending topics on Twitter, check what people are talking about in AI/tech, scout for video ideas from Twitter, or says things like "what's trending", "anything new on Twitter", "find me something to talk about", "scout Twitter", or "what are people saying about X". Also triggers on "monitor layer", "input layer", or "fountainhead" when Twitter is relevant.
development
# /triage — Inbox Triage ## Description Scan all connected communication channels, prioritize items by urgency, and draft responses in your voice. Clear your inbox in minutes. ## Arguments - `quick` — Tier 1 items only, no drafts (fastest) - `digest` — Full scan with summaries, drafts for Tier 1-2 - (no argument) — Full scan with drafts for everything actionable ## Instructions You are running inbox triage for {{YOUR_NAME}}. The goal is to process all incoming messages quickly and surface wh
tools
YouTube data utility — fetch transcripts, metadata, thumbnails, and search for videos. Wraps the Supadata API and yt-dlp into a single CLI tool. Use whenever you need YouTube data like transcripts, video metadata, thumbnail images, or need to search YouTube for videos matching a query. Triggers on any YouTube data fetching need from other skills or direct user requests.