Instagram Carousel Skill for Claude Code: Write, Render and Post Carousels From Your Agent A developer released the Instagram Carousel Skill, a free MIT-licensed agent skill that lets Claude Code, Claude, Codex, Cursor and OpenClaw plan, write, render and post Instagram carousels. The skill writes cover and slide copy, renders 1080x1350 JPEGs locally with a Pillow-based Python script, generates alt text and captions, and posts only after user confirmation, requiring no headless browser, image API or credits. The Instagram carousel skill is a free, MIT-licensed agent skill that lets Claude Code, Claude, Codex, Cursor and OpenClaw plan, write, render and post Instagram carousels. It picks a format, writes the cover and the slides, renders 1080x1350 JPEGs on your machine with a small Python script, writes alt text and a caption, and posts the carousel once you say yes. No headless browser, no image API, no credits. Repo: github.com/social-media-skills/instagram-carousel-skill https://github.com/social-media-skills/instagram-carousel-skill Slides from the two example carousels in the repo. The brand "plodd" and its app screenshot are made up. Most carousels that don't get saved fail in the same places, and each one maps to a rule in the skill: npx skills add social-media-skills/instagram-carousel-skill -g -a claude-code -y Other agents: openclaw skills install @social-media-skills/instagram-carousel-skill gh skill install social-media-skills/instagram-carousel-skill instagram-carousel-skill gemini extensions install https://github.com/social-media-skills/instagram-carousel-skill npx skills add social-media-skills/instagram-carousel-skill and pick your agent. Rendering needs Python 3.8+ and Pillow pip install pillow . The fonts ship in the repo. A prompt like "Make an Instagram carousel for my habit tracker about not giving up after a missed day" starts a fixed sequence: covers.md for later tests. carousel.json , runs the renderer, opens every slide and the contact sheet, and fixes each warning. scripts/render carousel.py turns a JSON spec into slides. It uses Pillow only, renders at 2x and downscales for sharp text, and bundles Inter and Instrument Serif under the SIL Open Font License. This is a shortened version of the spec behind the editorial example: { "theme": {"preset": "editorial", "mode": "light", "headline font": "serif", "name": "plodd", "handle": "@plodd.app", "avatar": "avatar.png"}, "slides": {"type": "cover", "title": "Missed a day?\nYour habit is fine .", "kicker": "4 rules for people who restart every Monday", "alt": "..."}, {"type": "step", "number": "1", "title": "One missed day is noise. Two is a pattern.", "body": "Protect one line: never miss twice in a row.", "alt": "..."}, {"type": "myth", "myth": "A habit takes 21 days", "fact": "Closer to 66 days .", "source": "Lally et al., European Journal of Social Psychology, 2010", "alt": "..."}, {"type": "screenshot", "title": "plodd counts your week ", "body": "Miss Wednesday. Still a good week.", "image": "screens/plodd-week.png", "alt": "..."}, {"type": "cta", "title": "Send this to the friend who restarts every Monday.", "alt": "..."} } python3 scripts/render carousel.py carousel.json --out carousel/ word sets a word in the accent colour, ~~words~~ strikes out a myth, and \n places a line break where the headline reads best. Slide types: cover text, photo or screenshot , text , step , list recap or checklist , myth , stat needs a source , tweet , photo , screenshot , beforeafter , cta . Presets: | Preset | Look | Good for | |---|---|---| | editorial light or dark | Paper or near-black background, serif or heavy sans headlines, one accent | Step-by-step, frameworks, lists | | notes light or dark | Plain phone-notes look | Honest lists, lessons, lo-fi posts | | tweet light or dark | Tweet-card thread with your own name, handle and avatar | Opinions, short lessons | Output: slide-01.jpg and onward at 1080x1350 sRGB JPEG, plus: contact-sheet.png : every slide on one image, for review. cover-grid.png : the cover cropped the way the 3:4 profile grid shows it. manifest.json : byte size, alt text and text per slide, plus warnings. The warnings are the part that saves review time: text below the size floor, too many words on a slide, a stat with no source, a missing alt text, and with opencv-python installed text sitting on a face. When text doesn't fit at the floor, the fix is to split the slide, not to shrink it. Meta's content publishing API accepts JPEG only, with an aspect ratio between 4:5 and 1.91:1, and crops every carousel item to the ratio of the first one. So 4:5 at 1080x1350 is the tallest size that posts through the API, and every slide is rendered at exactly that size. The Instagram app has accepted 3:4 1080x1440 since May 2025 but the API still rejects it; set "ratio": "3:4" only for slides you will upload by hand. The type scale is set for phone reading, not for a desktop preview: a 1080 px slide shows at roughly a third of its width on a phone, so body text sits at 54 px with a floor of 40, and slide headlines at 128 px serif or 96 px sans. The renderer has no agent dependency. You can call it from a script, a CI job or a cron task with your own spec. Posting goes through the WoopSocial https://woopsocial.com/?utm source=instagram-carousel-skill&utm medium=devto MCP server, a social media API for AI agents. The skill is maintained by Frank Heijdenrijk and the team behind WoopSocial. The free plan covers 2 social accounts with posting, scheduling and analytics included. Setup for each agent is at woopsocial.com/agents https://woopsocial.com/agents?utm source=instagram-carousel-skill&utm medium=devto . The posting step, in tool calls: social accounts list to check the connection. If Instagram isn't connected, oauth create authorization returns a link for you to approve. media uploads create session with the exact byte size from python3 scripts/upload parts.py session.json carousel/slide-01.jpg , then media uploads complete session . Media IDs stay in slide order. postType: POST , the caption, and PUBLISH NOW , SCHEDULE FOR LATER or DRAFT . posts validate , then the confirmation: contact sheet, caption, account and time with timezone. posts create runs only after your yes, and posts get reports the result. For several Instagram accounts, each account gets its own cover and variant instead of the identical carousel. WoopSocial doesn't write captions, crop media or set alt text, collaborators or music on Instagram. The skill writes the caption and alt text itself, and after posting it tells you to paste each slide's alt text from manifest.json into the app Edit Edit alt text . If you'd rather not connect anything, it hands over the slides, caption and alt text and stops there. After 3 to 7 days the agent calls social account posts list , which returns the stored post metrics Instagram reports views, likes, comments, saves, shares with their collection date. A missing number is logged as "not reported", never as zero. Instagram's API reports per post, not per slide, so per-slide views stay in the app. Each carousel goes into carousels.md with its date, format and cover, and the next step comes from comparing it with the account's own recent posts: | Saves | Shares | Next carousel | |---|---|---| | High | High | Same format, new topic | | High | Low | Useful but not shareable: try a send-style last slide | | Low | High | Shareable but thin: add a step or a checklist slide | | Low | Low | Change the cover first, then the format | The skill is MIT-licensed: github.com/social-media-skills/instagram-carousel-skill https://github.com/social-media-skills/instagram-carousel-skill . More free skills for social media work are at social-media-skills.com https://social-media-skills.com . If you render a carousel with it, which preset did you start with, and what did the warnings catch?