TikTok skill for Claude Code, free and MIT licensed: TikTok Skill lets your agent turn an idea, notes, your clips or your photos into finished TikTok videos and photo posts, check every file and setting against TikTok's posting rules, show you each post as the For You feed shows it, and schedule them after you say yes. It also works in Codex, Cursor and OpenClaw.

Everything up to posting runs on your own computer with Python, Pillow and ffmpeg. There is no paid API. This post covers what the skill does, how to install it, the example in the repo, and then the parts that are code: the checker, the video tools, inbox drafts, per-account versions and the learning loop.

npx skills add social-media-skills/tiktok-skill -g -a claude-code -y 

Repo: github.com/social-media-skills/tiktok-skill

The example made with the TikTok skill: a video cut from five NASA/JPL shots with the hook "Only 2.5% of Earth's water is fresh", and a photo post asking how big all of Earth's water would be as one drop, in English and Spanish, each shown as the For You feed shows it

The example in the repo, for "Earth in Numbers", a made-up science account. Footage and photos: NASA/JPL-Caltech and NASA; figures: USGS and NASA (no endorsement implied).

What is a TikTok skill?

An agent skill is a folder with a SKILL.md that tells an agent like Claude Code how to do a job, plus the scripts it runs. Most Claude TikTok help stops at text: a hook, a script, some hashtags. Then the upload fails on something nobody checked: a 50 fps export the API refuses, a PNG in a photo post, a video longer than the account may post, or a missing privacy choice, which TikTok requires the user to make every time.

This skill ships the scripts that make and check the posts, so the agent hands you real files:

  • videos at 1080x1920, H.264 and AAC, constant frame rate, with the hook in TikTok's own text style;
  • several shots cut into one 9:16 video, each cropped where its subject is, with timed points on screen;
  • photo posts rendered as 1080x1920 JPEGs, with the payoff on its own slide;
  • a cover taken from the first second, because WoopSocial adds the cover as the video's first frame;
  • a preview of every post as the For You feed shows it, with TikTok's posting panel;
  • a schedule per account in its own time zone, and one validated request per post and account.

Install

Claude Code:

npx skills add social-media-skills/tiktok-skill -g -a claude-code -y 

Codex, Cursor and other agents: npx skills add social-media-skills/tiktok-skill, then pick your agent. OpenClaw: openclaw skills install @social-media-skills/tiktok-skill. Gemini CLI: gemini extensions install https://github.com/social-media-skills/tiktok-skill.

It needs Python 3.9+ with Pillow, and ffmpeg for video. scripts/check_setup.py tells you what's missing and prints the install command for your OS.

The example

examples/fresh-water/ is a full batch for a made-up science account with an English profile (New York) and a Spanish one (Madrid):

  • A video, 15 seconds, cut from five shots of NASA/JPL's Earth Water Budget animation. No NASA narration, no NASA labels: its own points on screen from USGS figures. "Only 2.5% of Earth's water is fresh", "Two thirds of it is ice", "Almost a third is underground", "Lakes, rivers and the rest: about 1%", "That's all the fresh water we can reach". It goes to the TikTok inbox as a draft, so a sound can be added in the app.
  • A photo post: "If all of Earth's water were one drop, how big would it be?" Five swipes later the answer, 860 miles wide, gets a slide of its own, then "less than half as wide as the Moon". The caption repeats the question, not the answer. The Spanish account gets its own slides in km (1.385 km de ancho), not a translation pasted over the English ones.

Every slide, check, preview, schedule and request in that folder was made by the skill's scripts.

The checker: TikTok's posting rules in one file

tt_check.py reads plan.json (the batch: accounts, posts, settings) and checks each file and target. A few rules that cost people uploads:

Rule Why it matters
23 to 60 fps, constant Other frame rates fail with frame_rate_check_failed
H.264 (or H.265, VP8, VP9), 8-bit 10-bit and odd codecs get rejected or re-encoded badly
Length up to the account's own maximum Many accounts may post 3 minutes through the API; it reads the account's limit from WoopSocial
JPEG or WebP photos, up to 1080p and 20 MB PNG is rejected for photo posts
Privacy chosen by the user, no default TikTok's rule for every posting app; the plan records "privacy_from": "user"
Branded content never private TikTok refuses "Paid partnership" with "only me"
Interactions off unless turned on Another of TikTok's posting-app rules

--fix writes fixed copies to fixed/ (frame rate, codecs, shape, PNG to JPEG) and keeps the originals. A landscape video that would lose a lot of its width is an error, not a silent crop: the agent shows you the frames and asks.

The checker also knows things a file probe can't: the same media on two accounts (by content hash, so renaming doesn't hide it), two posts on one account within a week that teach the same fact, and a single clip you didn't film that keeps its own audio, which TikTok treats as reused material.

Footage you didn't film

Public domain means you may use a clip. It doesn't mean TikTok counts it as yours. A hook plate on someone else's single clip is the easiest thing for TikTok to match, especially when the original audio is still there.

So the skill treats such footage as material for an edit of your own:

python3 scripts/video.py montage clips.json --out video/montage.mp4 python3 scripts/video.py text video/montage.mp4 --beats beats.json --out video/fresh-water.mp4 

clips.json lists the shots with a start, an end and x, where the subject sits (0 left, 0.5 middle, 1 right), so each shot is cropped around its subject instead of the middle. beats.json holds the timed points. Each point picks TikTok's classic outlined text or the highlight style, depending on how bright the background behind it is, and stays clear of the buttons and caption.

Sounds and inbox drafts

No posting API can attach a TikTok sound. For photo posts, autoAddMusic lets TikTok add recommended music on a direct post. For anything that needs a chosen sound, the skill sends the post to the account's TikTok inbox as a draft (postMode: MEDIA_UPLOAD).

Two details make drafts usable. A draft lands at its scheduled time, not at the time it should go live, so schedule.py sends it 2 hours early. And video drafts arrive without a caption, so schedule.md lists each draft with the caption to paste. Privacy and autoAddMusic are left out of the draft request: you pick them in the app.

Posting through the TikTok MCP

Posting goes through WoopSocial, a social media API and MCP server for AI agents. Its TikTok MCP server posts videos and photo posts, directly or as inbox drafts, now or scheduled, with a cover, privacy, interaction settings, Promotional content and Paid partnership labels, and the AI label on videos.

This matters for anyone who searched for a TikTok developer API key: TikTok's Content Posting API only lets unaudited apps post "only me", for at most 5 users a day. WoopSocial's app is audited, so posts can be public from the start, and you don't need a developer account. Disclosure: the skill is maintained by Frank Heijdenrijk and the team behind WoopSocial. The free plan covers 2 social accounts.

The agent uploads each file, writes one request per post and account, validates them, and posts only after you say yes on the preview. WoopSocial doesn't write captions or edit media; the skill does that on your computer.

Several accounts

Each account gets its own version of a post: another hook, cut, order or language written for that country (in Spain "grifo", in Mexico "llave"; metric units; decimal commas). Two accounts in the same language get their own idea, not the same slides with new words. Each account posts at its own times in its own time zone.

Learning from your own results

After a few days, log.py results reads the post numbers WoopSocial collects and measures each post at the value nearest to day 7, so posts from different weeks are compared at the same age. It ranks against the same account's posts of the same type:

  1. views against that account's median (on TikTok, views show how far TikTok pushed the post);
  2. retention for videos (average watch time divided by length);
  3. shares, saves and follows per 1,000 views.

It names a best post only after 6 of a type. Saves, follows and watch time that the API doesn't report come from TikTok Studio, via insights.csv. Missing numbers are "not reported", never zero.

What it won't do

  • Invent numbers, results, views or quotes.
  • Post anything without your yes, or pick your privacy for you.
  • Repost someone else's video as is, or crop your landscape video without asking.
  • Add a sound through the API, or give a generic "best time to post".

The repo is social-media-skills/tiktok-skill. Issues and pull requests are welcome, especially when a TikTok limit in references/tiktok-specs.md changes. More free skills from the same team are at social-media-skills.com.