Search

PythonReactSEOPDF
GitHub Skill

instagram-poster

Posts carousels and Reels to Instagram via Graph API. Use when "post this carousel to Instagram", "publish carousel", "post to Instagram", "post this reel", "publish reel".

Eddale☆ 0 Repository stars0 Repository forks

Installation

Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.

View source ↗Guides

Skill instructions

Instagram Poster

What This Does

Posts carousels and Reels directly to Instagram via the Graph API. Uploads media to Vercel Blob for public URLs, creates containers, and publishes - eliminating manual upload steps.

Supports:

  • Carousels - 2-10 images, swipeable posts
  • Reels - Short-form video (5-90 seconds)

Prerequisites

Before first use, ensure these are configured:

  1. Environment variables (in ~/.zshrc):

    • BLOB_READ_WRITE_TOKEN - Vercel Blob storage token
  2. Config file (~/.config/instagram-poster.yaml):

    • Contains Instagram access token and user ID
    • Created by running auth_setup.py (one-time OAuth)

Instructions - Carousels

Step 1: Locate Carousel Images

Find the most recent carousel folder in ~/Downloads/:

ls -td ~/Downloads/carousel* | head -1

Or use the specific folder if provided by the user.

Verify the images:

  • Should contain 2-10 PNG images
  • Named like CarouselName01.png, CarouselName02.png, etc.
Step 2: Get User Approval (REQUIRED)

Before posting, ALWAYS show this confirmation:

Ready to post carousel to Instagram:
- X images from ~/Downloads/carouselYYMMDD/
- Caption preview: [first 100 chars of caption...]

Post now? (y/n)

DO NOT proceed without explicit user approval.

Step 3: Execute Posting

Run the post_carousel.py script:

Option A: Direct caption

python3 /Users/eddale/Documents/GitHub/powerhouse-lab/skills/instagram-poster/tools/post_carousel.py \
  --folder <carousel_folder_path> \
  --caption "<caption_text>"

Option B: Using a template

python3 /Users/eddale/Documents/GitHub/powerhouse-lab/skills/instagram-poster/tools/post_carousel.py \
  --folder <carousel_folder_path> \
  --template carousel \
  --title "Your Headline Here" \
  --topic "business"

Caption options (in priority order):

  1. If --template flag provided, render caption from template
  2. If user provides --caption, use it directly
  3. If carousel folder contains caption.txt, read it
  4. Otherwise, ask user for caption
Step 4: Report Results

On success, display:

  • Instagram post URL
  • Number of images posted
  • "Carousel is now live!"

On failure:

  • Show error message
  • Suggest checking token expiry if auth-related

Caption Templates

Use templates for consistent, high-performing captions. Templates live in resources/caption-templates.yaml.

Available Templates
Template Best For Emoji Hashtags
carousel Standard educational carousel Minimal 5
educational Deep teaching content None 6
promotional Launch/offer content Minimal 4
story Personal narrative Minimal 5
quicktip Bite-sized actionable tips Moderate 5
Template Variables
Variable Description Example
{title} Main headline "5 Things I Wish I Knew"
{topic} Subject area (becomes hashtag) "saas" or "coaching"
{cta} Call to action (optional) "DM me 'START'"

If {cta} is not provided, the template's default CTA is used.

Using Templates

List available templates:

python3 .../post_carousel.py --list-templates

Post with template:

python3 .../post_carousel.py \
  --folder ~/Downloads/carousel260120 \
  --template educational \
  --title "The One Skill That Changes Everything" \
  --topic "business"

With custom CTA:

python3 .../post_carousel.py \
  --folder ~/Downloads/carousel260120 \
  --template promotional \
  --title "Build Your First SaaS" \
  --topic "saas" \
  --cta "Link in bio - doors close Friday"
When to Use Templates vs Direct Caption
  • Use template: Consistent brand voice, quick posting, following best practices
  • Use direct caption: One-off special posts, very specific messaging, A/B testing

Caption Guidelines (Manual)

When writing captions manually (without templates), keep them concise. The carousel slides do the heavy lifting.

Pattern:

[Hook - what's the one thing?]

[1-2 sentences expanding]

Save this for later.

#hashtag1 #hashtag2 #hashtag3

Instructions - Reels

Step 1: Locate Video File

Find the Reel video file. Typically in a reels-builder output folder:

ls -td ~/Downloads/reels-builder-* | head -1

The video should be final.mp4 in that folder.

Video requirements:

  • Duration: 5-90 seconds
  • Format: MP4 or MOV
  • Aspect ratio: 9:16 (portrait)
  • Max size: 300MB
Step 2: Get User Approval (REQUIRED)

Before posting, ALWAYS show this confirmation:

Ready to post Reel to Instagram:
- Video: ~/Downloads/reels-builder-xxx/final.mp4 (X.X MB)
- Caption preview: [first 100 chars of caption...]

Post now? (y/n)

DO NOT proceed without explicit user approval.

Step 3: Execute Posting

Run the post_reel.py script:

python3 /Users/eddale/Documents/GitHub/powerhouse-lab/skills/instagram-poster/tools/post_reel.py \
  --video <video_file_path> \
  --caption "<caption_text>"

Caption options:

  • If user provides caption, use it
  • If reel folder contains caption.txt, read it
  • Otherwise, ask user for caption
Step 4: Report Results

On success, display:

  • Instagram Reel URL
  • "Reel is now live!"

On failure:

  • Show error message
  • Video processing takes longer than images - if timeout, suggest checking Instagram directly

Caption Guidelines (Reels)

Reels captions can be longer since the video is the hook.

Pattern:

[Hook question or statement]

[Context about what they're watching]

[CTA - follow for more, link in bio, etc.]

#hashtag1 #hashtag2 #hashtag3

Error Handling

Error Meaning Action
"Token expired" Access token > 60 days old Run refresh_token.py
"Rate limited" Too many API calls Wait 1 hour, retry
"Container processing failed" Image/video issue Check format/size/duration
"Video container failed to process" Video encoding issue Check codec (use H264), duration (5-90s)
"No config file" First time use Run auth_setup.py

One-Time Setup Commands

Initial OAuth (creates config file):

python3 /Users/eddale/Documents/GitHub/powerhouse-lab/skills/instagram-poster/tools/auth_setup.py

Refresh token (before 60-day expiry):

python3 /Users/eddale/Documents/GitHub/powerhouse-lab/skills/instagram-poster/tools/refresh_token.py

Examples

User asks to post recent carousel
User: "post the carousel I just made"

1. Find: ls -td ~/Downloads/carousel* | head -1
2. Read images: Bonsai01.png through Bonsai08.png
3. Ask: "Ready to post 8-image Bonsai carousel. Caption?"
4. User provides caption
5. Confirm: "Post these 8 images with that caption?"
6. User: "yes"
7. Execute post_carousel.py
8. Return: "Posted! https://instagram.com/p/xxx"
User provides specific folder and caption
User: "publish carousel from ~/Downloads/carousel260114 with caption 'The one skill that changes everything'"

1. Verify folder exists, count images
2. Confirm: "Post 8 images with caption 'The one skill...'?"
3. User: "yes"
4. Execute and return URL
User asks to post a Reel
User: "post that reel I just made"

1. Find: ls -td ~/Downloads/reels-builder-* | head -1
2. Locate: final.mp4 in that folder
3. Check size: 3.1MB, duration looks good
4. Ask: "Ready to post Reel (3.1MB). Caption?"
5. User provides caption
6. Confirm: "Post this Reel with that caption?"
7. User: "yes"
8. Execute post_reel.py
9. Return: "Reel is live! https://instagram.com/reel/xxx"
User provides specific video path
User: "post reel from ~/Downloads/reels-builder-meta-reel/final.mp4"

1. Verify video exists, check size
2. Ask: "Caption for this Reel?"
3. User: "The future of content creation..."
4. Confirm: "Post this Reel with caption 'The future...'?"
5. User: "yes"
6. Execute and return URL

Examples

Read the usage examples in the source repository.

View source ↗

Source history

Indexed on
2026-01-20
Index updated
2026-01-26
Branch
main

Index and sync dates describe this directory. View the source repository for code history.

GitHub ↗

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!