Post content
Skill NovateStudioGit/novate-studio-skills/creative-production/post-content
57 agent skills for Claude Code — creative production, paid growth, copywriting, ecommerce, email marketing & knowledge ops. By Novate Studio.
npx -y skills add NovateStudioGit/novate-studio-skills --skill post-contentAssembled 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
Single-command video distribution. Locates a video on disk, transcribes the audio with Whisper, writes a platform-appropriate caption in the matching creator/brand voice, picks a cover, queues it to Buffer, and schedules to IG Reels + TikTok + YouTube Shorts (LinkedIn/Threads optional). Use this skill whenever the user wants to publish, post, ship, schedule, queue, or cross-post a video to social — including phrases like "post that video", "ship the latest reel", "send to Buffer", "queue for IG", "post to shorts", "publish the Example Creator clip", or any natural-language post request that names a video file, a Downloads target, or a creator/brand folder. Also trigger when the user mentions a specific reel/short by name and asks for it to go live anywhere.
SKILL.md
7.5 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it
/post-content
One command, raw video in → scheduled posts out. The model drives — the scripts do the deterministic parts (find file, transcribe, upload). Will approves before anything ships to Buffer.
Flow
- Parse intent — pull from the user's prompt: which video, which channels, when to post, any caption hints.
- Locate the video —
scripts/find_video.pywith the intent. - Transcribe —
scripts/transcribe.py(local whisper.cpp — no API key, runs on-device. Cached next to the video as.transcript.txt). - Detect voice — from the video's path (see voice map below). Read the matching persona doc(s) before writing.
- Draft caption + hashtags — in that voice, max 5 hashtags.
- Pick cover —
scripts/extract_cover.py. Default: frame at 0.5s. If/viralitywas run on this video, pull the peak-hook frame instead. Offer/thumbnailfor a designed cover. - Approval gate — show Will the caption, cover, channels, scheduled time. Wait for
ship,tweak X, orcancel. Never auto-post. - Publish —
scripts/buffer_post.pyfans out to the selected Buffer channels. - Log — write a one-line confirmation note to the relevant Obsidian project's
sessions/YYYY-MM-DD.md.
Voice detection — read the persona docs, don't infer
The video's parent path determines voice. Always read the persona doc before drafting — caption voice is too easy to get wrong from filename guessing alone.
| Path pattern | Voice source |
|---|---|
STUDIO/1-WillSchwx.io/** | Will's locked voice — see references/voice-will.md AND ~/notes/your-brand/index.md |
STUDIO/[creator]/** (other) | ~/notes/[creator-slug]/ persona/voice docs |
ECOMMERCE/[brand]/** | ~/notes/[brand-slug]/ brand voice docs |
~/Downloads/** or anywhere else | Ask Will which creator/brand this is for — don't guess |
For Will: typographic discipline (command form, parallel structure, one idea per line, memorable metaphor allowed). For Example Creator specifically, the /caption-IG-Example Creator skill already encodes the voice — invoke it instead of recreating it.
Hashtag rule — locked, never override
Max 5 hashtags per caption. Compose them as: 1 niche + 1 broad + 2 thesis + 1 shareability. Never more, regardless of platform best-practice claims. (Will's standing rule.)
Never fabricate
Captions may only reference what's in the transcript or what Will provided in this turn. No invented stats, names, dates, or claims. If a number/quote feels persuasive but isn't sourced, leave it out — don't fill the gap.
Channels — defaults and flags
Default: IG Reels + TikTok + YouTube Shorts.
+linkedin/+threadsto add.only ig/only tiktok/only shortsto restrict.- LinkedIn and Threads use rephrased copy (LinkedIn = pro framing + first-person; Threads = conversational, no hashtags).
Timing
- No timing said → immediate post.
queue→ next available Buffer slot.at 7pm/tomorrow 9am→ specific time (interpret in Will's local tz; today's date is in context).
Cover
- If
~/Desktop/STUDIO/**/virality/[video-stem]/score.jsonexists → pullpeak_hook_timestampand grab that frame viaextract_cover.py --at <ts>. - Else → grab
--at 0.5. - Always offer: "Want me to run /thumbnail for a designed cover instead?" — if Will says yes, invoke
/thumbnailand use that output.
Approval gate format
Show this exact structure before calling Buffer:
Ready to ship:
Video: <basename> (<duration>s, <w>x<h>)
Cover: <path> ← reply "thumbnail" to upgrade
Channels: <ig/tiktok/shorts/...>
Time: <immediate | YYYY-MM-DD HH:MM tz | "next queue slot">
Caption (IG/TikTok primary):
<caption>
#tag1 #tag2 #tag3 #tag4 #tag5
LinkedIn (if selected):
<rephrased copy>
Reply: ship | tweak <what> | cancel
Script contracts
All scripts live in scripts/ and read flags from CLI. None of them call Buffer or Whisper unless invoked — safe to dry-run.
find_video.py <intent-string>→ prints absolute path of the resolved video. Resolution order: 1) explicit path in intent, 2) newest.mp4/.mov/.mkvin~/Downloads(≤ 7 days old), 3) newest in~/Desktop/STUDIO/**/content/, 4) newest in~/Desktop/ECOMMERCE/**/content/. Errors clearly if ambiguous.transcribe.py <video-path>→ writes<video>.transcript.txtand prints the transcript. Skips if cache exists. Uses local whisper.cpp; auto-downloads the small.en model on first run.extract_cover.py <video-path> [--at <seconds>]→ writes<video>.cover.jpgnext to the video.buffer_post.py --video <path> --cover <path> --caption-file <path> --channels ig,tiktok,shorts --when <immediate|ISO8601>→ posts via Buffer's GraphQL API atapi.buffer.com. RequiresBUFFER_ACCESS_TOKENand~/.claude/skills/post-content/config.jsonshaped{"organization_id": "...", "channels": {"ig": "<channelId>", "tiktok": "<channelId>", "shorts": "<channelId>"}}. Buffer's API has no upload endpoint, so the script either spins up acloudflaredtunnel automatically (default) or accepts--public-url-base <https-url>if you host the files yourself.
Run pip install -r ~/.claude/skills/post-content/scripts/requirements.txt the first time.
First-time setup (only if not done)
~/.claude/skills/post-content/config.jsonmust exist withorganization_id+channelsmap. If missing, runpython scripts/buffer_post.py --write-configonce (after channels are connected in Buffer) — it auto-detects the org and maps services to keys (ig,tiktok,shorts,linkedin,threads).BUFFER_ACCESS_TOKENmust be exported (check~/.zshrcor project.env). If missing, stop and tell Will exactly what to set and where.whisper-cppmust be on PATH —brew install whisper-cppif missing. (No API key, no per-minute cost — runs locally.)cloudflaredmust be on PATH —brew install cloudflaredif missing. Used to expose the local video file to Buffer's servers for the duration of the post-creation call. Skip if passing--public-url-base(you host the files yourself).
Composes with
/virality— run BEFORE posting to score the hook; reuse itspeak_hook_timestampfor cover./thumbnail— designed cover overlay; use when Will accepts the upgrade./caption-IG-Example Creator— Example Creator captions live there; defer to it instead of duplicating voice rules./vysionary-carousel— Will's @yourbrand.ai posts that are carousels, not reels — route those over there instead.
When NOT to use this skill
- Carousels / static image posts → use
/vysionary-carouselor post manually. - Editing an already-scheduled Buffer post → ask Will to do it in Buffer's UI; this skill only creates new posts.
- Stories / live streams → out of scope.
What ships with it: 7 files
26.5 KB alongside SKILL.md, 4 of them executable
references/
- buffer-setup.md2.3 KB
- voice-will.md1.2 KB
scripts/
- buffer_post.pyruns14.5 KB
- extract_cover.pyruns1.1 KB
- find_video.pyruns3.7 KB
- requirements.txt16 B
- transcribe.pyruns3.7 KB