Instagram CLI
SkillDev toolsAnswer questions about Instagram posts and reels, including links the user shares, using post context, media descriptions, and visual inspection when needed. Read profiles, followers, posts, comments, likes, stories, feed, saved content, and insights. Manage feed interests and profile details, and publish stories, reels, posts, or carousels when requested.
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the Instagram CLI skill
What this skill tells your AI
The instructions your AI receives, as published by win4r/museai-skills in opt/hatch/skills/instagram/SKILL.md and read by ahel’s review.
Purpose
Read and manage authenticated Instagram data using the instagram-cli companion CLI.
Use the separate instagram_messages skill for inbox, thread/message reads, filtered inbox, top recipients, and DM search.
Questions about a post or reel
For questions about a supplied Instagram post or reel, read Instagram content questions with muse.read before investigating. Use available post evidence, inspect unresolved visual details, and finish the user's task with the relevant skill. Don't sound more certain than you are: say plainly what you checked, call a guess a guess, and admit what you couldn't verify.
Account Linking
Before running any other command, verify the user's Instagram account is connected by running instagram-cli accounts. If the command returns account info (one or more accounts with user_fbid), the account is connected — proceed normally. Cache this result for the rest of the conversation; do not re-run the check before every command. If any subsequent command fails with an auth or account error, re-run instagram-cli accounts to recheck account linking status.
If the command fails or returns an empty result indicating no account is linked, the account is not connected. Get the connect URL by running instagram-cli connect-url (it outputs JSON with a connect_url field), then tell the user, substituting that URL:
Your Instagram account is not connected. To connect it, visit Meta Accounts Center and link your Instagram account.
If the user asks to disconnect their Instagram account, run instagram-cli disconnect-url (it outputs JSON with a disconnect_url field) and direct them to that URL:
To disconnect your Instagram account, visit Meta Accounts Center and remove the linked account.
Always read these URLs from the command output rather than hardcoding them.
Operating rules
- Use this skill for authenticated Instagram non-messaging data, location lookup for Story stickers, and content questions about specific user-supplied Instagram posts or reels. Use
social.searchfor general post discovery; use attributed public sources to research people, not identification from their faces. - Always call
accountsfirst to obtain theuser_own_fbidfor--account-id. Cache this value for subsequent commands in the same conversation. Ifaccountsreturns no entries, direct the user to Meta Accounts Center to link an Instagram account (refer to the "Account Linking" section for details). - Never expose FBIDs, opaque IDs, or implementation terminology to the user. Use usernames, display names, and plain-language descriptions; keep IDs only in tool calls.
- Budget your API calls against the task at hand. The Instagram API enforces rate limits, and excessive calls will result in
429 Too Many Requestserrors that are not retried. As a rule of thumb:- If the task you're doing can be completed in the low hundreds of API calls, that's fine — proceed normally.
- If the task looks like it would require more than ~1,000 API calls (for example, paginating through every follower of a large account, or fanning out per-post comment/liker fetches across a huge set of posts), stop and be careful: confirm with the user that the scope is worth it, narrow the work (date ranges, top-N only, specific IDs), or propose a smaller approximation before continuing.
- Apply common sense in between: batch your information gathering, reuse data from earlier responses (e.g. IDs and usernames from
accountsorprofile), and don't re-run the same command with identical arguments unless the previous call failed or the user explicitly asks for a refresh. - Only paginate (
--after/--max-id) when the user explicitly needs more results. Don't automatically fetch all pages. - When you stop early, say so. If a response carries
has_next_page: true,has_more: true, or similar and you are not fetching the rest, tell the user how much you saw and that more remains, then offer to continue. Never report a paginated read as complete on the strength of one page.
- Avoid requests to persistently / frequently poll these commands.
Tooling
Use exec to run account-scoped commands:
instagram-cli <target> --account-id <user_own_fbid> [options]
Use instagram-cli accounts only to discover available account IDs.
For every write action—including interest updates, publishing, and profile changes—act only when the user explicitly asks for that change.
Targets:
accountsprofilecurrent-interestspostsfollowersfollowingclose-friendsfeedactivity-notificationsuser-profiletagged-postspostfetch-post-commentsfetch-post-likerssaved-postssaved-collectionscreate-saved-collectionrename-saved-collectionsave-postunsave-postown-storiesown-stories-archivestories-traystory-medialocation-searchmedia-understandingaccount-insightsrecently-liked-postsrecently-commented-postsupdate-interestspost-feedpost-storyset-profile-pictureupdate-bio
Post output
posts, feed, and post return the same compact post collection used by
social search. Read posts[] directly; do not guess a provider GraphQL path or
pipe these commands through jq:
{
"format": "social_posts_v1",
"count": 1,
"posts": [{
"rank": 1,
"post_id": "...",
"url": "https://www.instagram.com/...",
"platform": "instagram",
"created_at": "2026-08-04T19:03:58+00:00",
"post_created_at": {"utc":"...","user_local":"...","user_timezone":"..."},
"username": "account",
"post_caption": "..."
}],
"next_cursor": "...",
"has_next_page": true
}
created_at remains for compatibility; prefer post_created_at.user_local
when presenting a post time. Fields unavailable in the provider response are omitted. A feed item can omit
url or created_at; for a selected item that will be quoted, dated, or linked,
run post --id <post_id> and use the hydrated record. A valid partial response
includes the provider's reason in optional provider_error; do not describe it
as a complete page. If required post data is absent, the CLI fails and includes
that reason when the provider supplied one. Without a provider reason, it
reports the schema mismatch rather than returning an empty post list.
Global options
--account-id <user_own_fbid>(required for all commands exceptaccounts) — select which Instagram account to operate on. The value must be the authenticated user's ownuser_fbidfield from theaccountscommand response — do not use any other user's ID. Always callaccountsfirst to obtain this value. Ifaccountsreturns multiple entries, ask the user which account to use before proceeding.--retries <N>— retry transient failures (default: 0).--after <cursor>— pagination cursor from the previous response. Omit to fetch the first page. Available on all paginated commands.
Commands
Accounts
List Instagram accounts associated with the currently authenticated user.
instagram-cli accounts
Profile
Fetches Instagram profile bio, including follower/following counts. Omit --username and --profile-url to fetch the user's own profile. Otherwise, provide a username/handle or a profile URL to fetch another user's profile. If you just want counts instead of the actual list of followers/following, use this (it's cheaper/faster).
instagram-cli profile --account-id <user_own_fbid>
instagram-cli profile --account-id <user_own_fbid> --username <username>
instagram-cli profile --account-id <user_own_fbid> --username @<username>
instagram-cli profile --account-id <user_own_fbid> --profile-url https://instagram.com/<username>
Update bio
Update the user's Instagram profile bio. --bio is required and may contain at
most 150 characters. Pass an empty string to clear the bio.
instagram-cli update-bio --account-id <user_own_fbid> --bio "Photographer and traveler"
Current interests
Returns topics the user is interested in or uninterested in. Do not distinguish between inferred and explicit interests when presenting results to the user — just show the topic and its type.
instagram-cli current-interests --account-id <user_own_fbid>
Update interests
Mark a topic as "interested" so the user sees more of it on Instagram, or as "not interested" so the user sees less of it.
instagram-cli update-interests --account-id <user_own_fbid> --text "cooking" --interested true
instagram-cli update-interests --account-id <user_own_fbid> --text "politics" --interested false
Posts
Omit --username and --user-id to fetch the user's own posts. Otherwise, provide one or more usernames or one or more user IDs to fetch other users' posts. Do not mix usernames and user IDs in the same command.
Use the previous response's page_info.end_cursor as --after. Omit on first request.
Available filters mirror the shared Clippy post query where supported: --since, --until, --sort-order asc|desc, --limit, and repeated/comma-separated --post-types values such as POST, REEL, STORY, or HIGHLIGHT.
instagram-cli posts --account-id <user_own_fbid>
instagram-cli posts --account-id <user_own_fbid> --after <cursor>
instagram-cli posts --account-id <user_own_fbid> --username <username>
instagram-cli posts --account-id <user_own_fbid> --username <username>,<username>
instagram-cli posts --account-id <user_own_fbid> --user-id <FBID>
instagram-cli posts --account-id <user_own_fbid> --user-id <FBID>,<FBID>
instagram-cli posts --account-id <user_own_fbid> --username <username> --since 2026-01-01 --until 2026-02-01 --sort-order asc --limit 25 --post-types POST,REEL
Followers
Fetch the user's own follower list. --count is optional and defaults to 200.
Use the previous response's page_info.end_cursor or next_max_id as --after. Omit on first request.
instagram-cli followers --account-id <user_own_fbid>
instagram-cli followers --account-id <user_own_fbid> --count 25
instagram-cli followers --account-id <user_own_fbid> --after <cursor>
Following
Fetch the user's own following list. Other users' following lists are not supported. --count is optional and defaults to 200.
Use the previous response's page_info.end_cursor or next_max_id as --after. Omit on first request.
instagram-cli following --account-id <user_own_fbid>
instagram-cli following --account-id <user_own_fbid> --count 25
instagram-cli following --account-id <user_own_fbid> --after <cursor>
Close friends
Returns the user's current Instagram close friends list.
This is the user's own curated Close Friends list on Instagram. It is not ranked or inferred. To get an inferred list of people the user interacts with most, use the top-recipients command from the instagram_messages skill instead.
instagram-cli close-friends --account-id <user_own_fbid>
Feed
Following feed:
instagram-cli feed --account-id <user_own_fbid> --variant following
Close-friends feed:
instagram-cli feed --account-id <user_own_fbid> --variant favorites
--variant is REQUIRED and only following and favorites are supported; the ranked home timeline is not readable through this surface (omitting the variant fails fast with this rule).
For all feed variants, use the previous response's page_info.end_cursor as --after. Omit on first request.
instagram-cli feed --account-id <user_own_fbid> --variant following --after <cursor>
Activity notifications
Returns notifications and priority_notifications without marking them seen.
Paginate with page_info.end_cursor as --after.
instagram-cli activity-notifications --account-id <user_own_fbid> [--after <cursor>]
Other user's profile
Fetch another user's profile by user ID, username, or profile URL. Prefer --user-id when you already have a user FBID from prior tool output.
instagram-cli user-profile --account-id <user_own_fbid> --user-id 18841401449726893
instagram-cli user-profile --account-id <user_own_fbid> --username @<username>
instagram-cli user-profile --account-id <user_own_fbid> --profile-url https://instagram.com/<username>
Tagged posts
Fetch posts a user has been tagged in. Omit --user-id to fetch the user's own tagged posts. Otherwise, --user-id should be the target user's FBID.
Use --since, --until, --sort-order, and --limit to narrow the shared engagement query.
instagram-cli tagged-posts --account-id <user_own_fbid>
instagram-cli tagged-posts --account-id <user_own_fbid> --after <cursor>
instagram-cli tagged-posts --account-id <user_own_fbid> --user-id 18841401449726893
instagram-cli tagged-posts --account-id <user_own_fbid> --user-id 18841401449726893,18841401449726894 --since 2026-01-01 --until 2026-02-01 --sort-order asc --limit 25
Post by ID or URL
Fetch a single post by its media ID or full Instagram post/reel URL. Provide
exactly one of --id or --url.
instagram-cli post --account-id <user_own_fbid> --id 3599891547851922338_14631749
instagram-cli post --account-id <user_own_fbid> --id 3599891547851922338
instagram-cli post --account-id <user_own_fbid> --url https://www.instagram.com/p/SHORTCODE/
instagram-cli post --account-id <user_own_fbid> --url https://www.instagram.com/reels/anfiurkjnwed
Post comments
Fetch comments for one or more posts by media ID. Pass a comma-separated list to --post-ids; batch multiple IDs into a single call instead of calling this command per post.Use --since, --until, --sort-order, --limit, and repeated/comma-separated --author-ids filters when needed.
instagram-cli fetch-post-comments --account-id <user_own_fbid> --post-ids 3599891547851922338
instagram-cli fetch-post-comments --account-id <user_own_fbid> --post-ids 3599891547851922338,3599891547851922339
instagram-cli fetch-post-comments --account-id <user_own_fbid> --post-ids 3599891547851922338 --limit 25 --after <cursor>
instagram-cli fetch-post-comments --account-id <user_own_fbid> --post-ids 3599891547851922338 --since 2026-01-01 --until 2026-02-01 --author-ids 18841401449726893
Post likers
Fetch likers for one or more posts by media ID. Pass a comma-separated list to --post-ids; batch multiple IDs into a single call instead of calling this command per post.Use --since, --until, --sort-order, --limit, and repeated/comma-separated --reactor-ids filters when needed.
instagram-cli fetch-post-likers --account-id <user_own_fbid> --post-ids 3599891547851922338
instagram-cli fetch-post-likers --account-id <user_own_fbid> --post-ids 3599891547851922338,3599891547851922339
instagram-cli fetch-post-likers --account-id <user_own_fbid> --post-ids 3599891547851922338 --limit 25 --after <cursor>
instagram-cli fetch-post-likers --account-id <user_own_fbid> --post-ids 3599891547851922338 --since 2026-01-01 --until 2026-02-01 --reactor-ids 18841401449726893
Saved posts
Fetch the user's saved posts. Include an optional collection_id to fetch posts saved within a particular collection (you can get the collection_id from the saved-collections command).
Without --collection-id, saved-posts uses the shared engagement query and supports --since, --until, --sort-order, and --limit.
instagram-cli saved-posts --account-id <user_own_fbid>
instagram-cli saved-posts --account-id <user_own_fbid> --after <cursor>
instagram-cli saved-posts --account-id <user_own_fbid> --since 2026-01-01 --until 2026-02-01 --sort-order asc --limit 25
instagram-cli saved-posts --account-id <user_own_fbid> --after <cursor> --collection-id "2949392323392323"
Saved collections
Fetch the user's saved collections (folders/categories of saved posts).
instagram-cli saved-collections --account-id <user_own_fbid>
instagram-cli saved-collections --account-id <user_own_fbid> --after <cursor>
Manage saved posts and collections
instagram-cli create-saved-collection --account-id <user_own_fbid> --name "Travel"
instagram-cli rename-saved-collection --account-id <user_own_fbid> --collection-id 2949392323392323 --name "Japan"
instagram-cli save-post --account-id <user_own_fbid> --media-ids 3599891547851922338
instagram-cli save-post --account-id <user_own_fbid> --media-ids 3599891547851922338,3599891547851922339 --collection-id 2949392323392323
instagram-cli unsave-post --account-id <user_own_fbid> --media-ids 3599891547851922338 --collection-id 2949392323392323
instagram-cli unsave-post --account-id <user_own_fbid> --media-ids 3599891547851922338
Saving with a collection both saves the post and adds it to that collection. Unsaving with a collection only removes it from that collection; omitting --collection-id unsaves it globally.
Own stories
Fetch the user's own currently posted Instagram stories.
instagram-cli own-stories --account-id <user_own_fbid>
Stories archive
Fetch the user's own Instagram story archive. Use the previous response's next_max_id as --max-id to paginate. Omit on first request. If an item in the response has a non-empty video url, select that over the image url.
instagram-cli own-stories-archive --account-id <user_own_fbid>
instagram-cli own-stories-archive --account-id <user_own_fbid> --max-id <cursor>
Stories tray
Fetch the user's stories tray (currently available stories posted by people the user follows). --count is optional and defaults to 200. The response contains only media IDs — no links, images, or video. To get an actual media permalink for a specific story, pass its ID to story-media.
instagram-cli stories-tray --account-id <user_own_fbid>
instagram-cli stories-tray --account-id <user_own_fbid> --count 25
Be judicious about following up with story-media: do not eagerly fetch media for every story in the tray. Only fetch media for IDs the user explicitly asks about, or a small subset they've clearly requested.
Story media
Fetch media metadata (permalink, posted-at time, expires-at time) for one or more story items by ID. Pass a comma-separated list to --ids; batch multiple IDs into a single call instead of calling this command per item.
instagram-cli story-media --account-id <user_own_fbid> --ids 18103150772488230
instagram-cli story-media --account-id <user_own_fbid> --ids 18103150772488230,55858390399494949
Location search
Search Instagram locations with required --search-query. Optionally pass
both --latitude and --longitude to narrow the results.
instagram-cli location-search --account-id <user_own_fbid> --search-query "Central Park"
instagram-cli location-search --account-id <user_own_fbid> \
--search-query "Central Park" --latitude 40.7829 --longitude -73.9654
Before passing media to post-story, post-feed, or set-profile-picture,
ensure that every media and cover file is in the workspace path. If it is not,
copy it to the workspace. Never use a /tmp path.
Publish story
Publish one JPEG, PNG, static WebP, MP4, or MOV file, preferably vertical 9:16
at 1080 x 1920 px. Strongly avoid letterboxing. --file is required and
limited to 100 MB. Directly posted videos require a matching JPEG, PNG, or
static WebP --cover; videos edited with stickers or text generate their cover
automatically.
Use post-story --draft with --file and --editor-json for all visible Story
text and supported native stickers. First run
instagram-cli post-story --help and follow its detailed parameter, text, sticker,
geometry, and media contract. Draft mode renders under
workspace/instagram/stories without posting. Always render from the same clean
media for revisions, show the returned media inline, and ask the user to confirm
it before posting. Record every returned draft output and cover path. After
confirmation, rerun the same command without --draft; it renders the approved
edit in the same directory and posts that output. Once publishing succeeds,
delete every earlier draft and draft cover by its exact recorded path. Keep the
last user-approved draft and the final published render, and never use a glob.
Only mention, location, and link native stickers are supported; refuse all
others. For a location sticker, select a result with location-search and
include its location_id in the location object passed to --editor-json.
Mention objects require user_fbid; link objects require url.
The final command automatically uploads the rendered output and its video cover:
EDITOR_JSON='[
{"type":"text","text":"SUMMER IN NYC","style":"poster","x":0.5,"y":0.2},
{"type":"mention","text":"@friend","user_fbid":"123","style":"default","x":0.5,"y":0.4},
{"type":"location","text":"Central Park","location_id":"456","style":"default","x":0.5,"y":0.65},
{"type":"link","text":"Learn more","url":"https://example.com","style":"default","x":0.5,"y":0.82}
]'
instagram-cli post-story --draft --account-id <user_own_fbid> \
--file <clean-media> --editor-json "$EDITOR_JSON"
instagram-cli post-story --account-id <user_own_fbid> --file <clean-media> \
--editor-json "$EDITOR_JSON"
Publish feed post
Publish media to the user's feed. post-feed selects the post type from the
files supplied:
- One JPEG or PNG image or static WebP image publishes a regular image post. Prefer portrait 4:5 at 1080 x 1350 px; square 1:1 at 1080 x 1080 px is also suitable.
- One MP4/MOV publishes a reel shared to the feed and profile grid. Use vertical
9:16 video, preferably 1080 x 1920 px, and pass a matching JPEG, PNG, or
static WebP
--cover. - Two or more JPEG, PNG, static WebP, MP4, or MOV files publish a carousel in the order supplied. Image, video, and mixed image/video carousels are supported. Keep all items at the same aspect ratio and dimensions, preferably 4:5 at 1080 x 1350 px.
Each file may be at most 100 MB. --caption is optional, may include hashtags
and textual @mentions, and is limited to 2,200 characters. Whitespace-only
captions are treated as absent. --mentions takes a JSON array of user tags.
Each tag requires user_fbid; optional x and y coordinates run from 0 to 1
and default to 0.5. On a carousel, the CLI applies the supplied user tags to
every item.
For video media, --video-thumbnail-playback-offset-ms optionally selects a
non-negative video frame for the final thumbnail. Each video requires a JPEG,
PNG, or static WebP --cover, shown until frame extraction finishes. For a
carousel, repeat --cover once per video in the same order as the video files;
image items do not take covers. Do not pass either video option for an
image-only post or carousel.
# Image post
instagram-cli post-feed --account-id <user_own_fbid> \
--file /path/to/post.jpg --caption 'A feed caption' \
--mentions '[{"user_fbid":"<tagged_user_fbid>","x":0.5,"y":0.5}]'
# Reel shared to feed
instagram-cli post-feed --account-id <user_own_fbid> \
--file /path/to/reel.mp4 --cover /path/to/cover.jpg \
--video-thumbnail-playback-offset-ms 1200 \
--caption 'A caption with #hashtags and @mentions'
# Mixed carousel; file order is display order and cover order follows videos
instagram-cli post-feed --account-id <user_own_fbid> \
--file /path/to/first.jpg --file /path/to/second.mp4 \
--cover /path/to/second-cover.jpg \
--caption 'A carousel caption'
Do not use --retries for posting because an automatic retry could publish a
duplicate. Instagram also enforces a per-account daily publish limit.
Set profile picture
Pass exactly one square (1:1) JPEG or PNG, preferably at least 320 x 320 px and no larger than 1080 x 1080 px. The file may be at most 100 MB.
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 293
- Forks
- 93
- Last commit
- Sep 2026
Advanced
- Item type
- skill
- Key
instagram-win4r- Source
- github.com/win4r/museai-skills