npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@island-pitch/ip-bot-cli

v0.3.0

Published

IP Bot CLI (ipbot) — accessible-by-default social publishing for AI agents and humans: alt text on every image, human-in-the-loop approval, agent-grade automation

Readme

@island-pitch/ip-bot-cli (ipbot)

npm version node >= 18

#AutomateThis — ship social content the way an agent should: draft → human review → schedule → publish, from one CLI.

Your AI writes the post. A human approves it. IP Bot publishes it — with the alt text, venue tag, collaborator invites, and compliance gating most tools never send. Do Cool Things the Right Way!®

# Draft it (your agent, your voice, full a11y)
ipbot content create --type social_post --platform instagram \
  --excerpt "Doors at 8. The crew is ready. 🌊" \
  --alt-text "Two dancers mid-spin under purple stage lights" \
  --location-id 213385402 --collaborators dj_kaya \
  --dest-config '{"igAccountId":"...","imageUrl":"https://media.islandpitch.bot/…"}'

# A human approves it (or an external reviewer via a tokenized link)
ipbot content approve <draftId>

# Schedule it in plain English
ipbot content schedule <draftId> --at "fri 7pm" --tz ET
# → publishes automatically; check performance later with `ipbot analytics post`

Why this exists

  • Human-in-the-loop by design. Nothing publishes without an explicit approval — reviewers see the full assembled post (caption, image, alt text, destination, timing), and outside clients can approve via secure tokenized links with no account.
  • Accessible by default. Alt text is a first-class flag on every image — published as Instagram alt_text and Facebook alt_text_custom. A bridge is only finished when it's wide enough for everyone to cross.
  • Built for agents, not adapted for them. Stable exit codes (0/1/2/3/124), --output json everywhere, idempotency keys so retries never double-post, natural-language scheduling, and schedule debug that explains publisher failures with a suggested fix.
  • The Meta features everyone else skips. Collaborator co-author invites (your post on both profiles), venue location tags, people tags, Reels covers, IG Stories, Facebook CTA buttons, 21+ audience gating for alcohol/nightlife compliance, timeline backdating.
  • Pairs with your agent runtime. The same surface ships as an MCP server: @island-pitch/ip-bot-mcp — one command to give Claude a content crew.

🏝️ IP Bot is in private beta — request access at islandpitch.bot, then grab your ipbot_live_… key from Settings → API Keys.

Accessibility, for people who automate

If you script your posting, your automation decides whether a blind follower gets a description or silence. IP Bot makes the accessible path the easy path:

  • --alt-text on every image create; mediaAltTexts for every carousel item — published as Instagram alt_text / Facebook alt_text_custom, helping your posts meet WCAG 1.1.1 (non-text content).
  • The review page works like an a11y linter for your feed: reviewers see the alt text with the assembled post, and a missing description is flagged in amber — "missing — screen readers get no description" — before anything ships.
  • Content tickets carry a per-cell **Alt:** field, so bulk ticket-driven pipelines (draft from-ticket) stay accessible at scale.
  • Honest platform limits, documented: Meta exposes no alt-text API for video/Reels/Stories — we say so in the tools instead of pretending. Facebook video captions (.srt) are next on the roadmap.

Got a publishing chore your tools make inaccessible or manual? #AutomateThis.


Everything below is the full reference. Every command supports --output json for machine consumption.

Install

Run without installing (recommended for one-offs and CI):

npx @island-pitch/ip-bot-cli <command>
# e.g.
npx @island-pitch/ip-bot-cli system status

Or install globally to get the ipbot binary on your PATH:

npm i -g @island-pitch/ip-bot-cli
ipbot --help

Requires Node.js >= 18.

Prerequisite: IP Bot is in private beta. You need an ipbot_live_… key (request access, then copy it from Settings → API Keys) in IPBOT_API_KEY. Without a valid key, commands fail with UNAUTHENTICATED.

Configuration

The CLI talks to an AppSync GraphQL endpoint. It resolves connection settings in this order (first match wins):

  1. CLI flags: --endpoint <url>, --api-key <key>, --token <jwt>
  2. Environment variables (below)
  3. Saved config at ~/.ipbot/config.json (written by ipbot auth ...)
  4. Auto-discovered amplify_outputs.json (walks up from the current directory — useful inside the monorepo, not when installed via npx)

Environment variables

| Variable | Purpose | | --- | --- | | IPBOT_APPSYNC_ENDPOINT | AppSync GraphQL URL | | IPBOT_API_KEY | Canonical key var. A per-user ipbot_live_… key is auto-routed to the Authorization header; a shared da2-… key goes to x-api-key. | | IPBOT_USER_API_KEY | Deprecated/advanced explicit per-user key override. Prefer IPBOT_API_KEY=ipbot_live_…. | | IPBOT_USER_ID | Default user id (Cognito sub) for user-scoped commands (content/calendar/org). | | IPBOT_ID_TOKEN | Cognito ID token (human auth) | | IPBOT_REGION / AWS_REGION | AWS region (default us-west-2) | | IPBOT_COGNITO_DOMAIN / IPBOT_COGNITO_CLIENT_ID | Cognito Hosted UI settings for auth login | | ATLASSIAN_SITE / ATLASSIAN_EMAIL / ATLASSIAN_API_TOKEN | Optional Jira integration (draft from-ticket, Jira notify) |

When installed standalone (via npx/global), set at least IPBOT_APPSYNC_ENDPOINT and either IPBOT_API_KEY (agent) or run ipbot auth login (human).

Authentication modes

Humans — Cognito Authorization Code + PKCE:

ipbot auth login            # opens the Hosted UI, completes PKCE, stores tokens
ipbot auth whoami
ipbot auth refresh          # refresh the access token
ipbot auth logout
ipbot auth login --token <jwt>   # or paste a Cognito ID token directly

Agents / CI — AppSync API key + explicit user:

export IPBOT_APPSYNC_ENDPOINT="https://api.islandpitch.bot/graphql"
export IPBOT_API_KEY="da2-..."          # or: ipbot auth key set <apiKey>
# pass --user-id on commands that act on behalf of a user:
ipbot content list --user-id <cognito-sub> --output json

ipbot auth key set <apiKey> / ipbot auth key clear persist the key in ~/.ipbot/config.json.

Command catalog

Run ipbot <group> --help for the full options of any group.

auth — authentication

login, refresh, logout, whoami, key set <apiKey>, key clear

content — content pipeline

create, find, get <draftId>, list, submit <draftId>, approve <draftId>, reject <draftId>, schedule <draftId>, reschedule <scheduleId>, publish <draftId>, cancel <scheduleId>

  • schedule/reschedule accept ISO 8601 or natural language for --at ("in 10 minutes", "fri 7pm ET") with --tz as the default zone. reschedule requires an identity-bound caller (per-user key or login).
  • create takes publishing option flags that merge into the dest-config — see Publishing options below.

media — native media hosting

upload <filePath> — upload a local image (JPEG/PNG/WebP ≤8 MB) or video (MP4/MOV ≤200 MB) to the platform media bucket and print a publicly fetchable URL for **Image:** ticket fields or --dest-config imageUrl. Requires an identity-bound caller (the shared key is rejected).

review — tokenized external review & comments

share <draftId>, shares <draftId>, revoke <shareId>, comment <draftId>, comments <draftId>

calendar — publication calendar

show [--month YYYY-MM], get <scheduleId>, wait <scheduleId>

org — organization ("Your Own Crew") management

create, list, context <orgId>, invite <orgId>, accept <inviteToken>, remove <orgId>, role <orgId>, update <orgId>, drafts <orgId>, audit <orgId>, share <orgId>, unshare <sharedAccountId>

accounts — connected social accounts

list --user <sub|email> (shows page-token freshness: cached / stale / missing)

schedule — schedule inspection & debugging

debug <scheduleId> (classifies publisher errors with a suggested fix)

draft — multi-cell draft helpers

from-ticket <jiraKey> (build a draft from a Jira ticket)

system — infra health

status (endpoint, auth mode, token freshness across users)

analytics — published-post analytics

post <platformPostId> (fetch insights for a published post)

campaigns — AutoReply campaigns (Instagram comment/DM automation)

create, list [--status <active|paused|archived>], get <campaignId>, update <campaignId>, activate|pause|archive <campaignId>, set-steps <campaignId> --steps <json-file|->, set-triggers <campaignId> [--keywords <csv>] [--all-comments|--no-all-comments] [--media-ids <csv>] [--clear-media-ids]

  • --media-ids <csv> restricts triggering to specific IG media IDs; omit to trigger on all media. Inbound DMs are never media-filtered.
  • Meta rules the engine enforces (details in ipbot campaigns --help): one private reply per comment — ever (private_reply_already_sent), private replies only within 7 days of the comment (private_reply_window_expired), and free-form DMs require the user to have messaged within 24 hours.

powers — discover & run Powers

list (catalogue + Winds cost) · run <powerId> [--input '<json>'] [--input-file <path>] [--team-id <id>] [--account-ref <provider:id>]

winds — Winds balance & top-ups

balance (current balance + plan) · topup <packId> (small | medium | large; returns a Stripe Checkout URL)

powers and winds are user-scoped — they require a per-user API key (ipbot_live_…) or interactive login, and debit the key owner's Winds. The shared AppSync key is rejected for these.

Publishing options (accessibility + Meta differentiators)

content create flags that merge into the draft's dest-config. The publisher gates each per media type and omits anything unsupported.

| Flag | Publishes as | | --- | --- | | --alt-text <text> | IG alt_text / FB alt_text_custom — a first-class accessibility field: provide for every image; omitting it drops alt text silently. Images only (not Reels/Stories). | | --media-alt-texts <json-array\|csv> | Per-carousel-child alt text, paired by index with --media-urls / mediaUrls. Same a11y rule — omit and alt text is dropped silently. Note: Instagram crops all carousel children to the FIRST child's aspect ratio. | | --location-id <id> | IG location_id / venue tag (Facebook place ID) | | --collaborators <list> | IG co-author invites (reels/carousels) — the featured accounts the post is about; appears on both profiles | | --user-tags <json> | IG user_tags[{"username","x","y"}] (x/y on single images only) | | --cover-url <url> / --thumb-offset <ms> / --audio-name <name> / --share-to-feed | IG Reels presentation | | --story | Publish as an IG Story (media_type=STORIES; no caption/alt) | | --place-id <id> | FB place (check-in) | | --cta <json> | FB call_to_action{"type":"GET_TICKETS","value":{"link":"…"}} | | --targeting <json> / --feed-targeting <json> | FB audience restriction / feed preference — e.g. {"age_min":21} for 21+ compliance content | | --backdated-time <iso> | FB backdated_time (timeline import) |

Content tickets support a per-cell **Alt:** line that draft from-ticket carries automatically.

Typical agent flow

export IPBOT_APPSYNC_ENDPOINT=... IPBOT_API_KEY=...
ID=$(npx @island-pitch/ip-bot-cli content create --type blog --platform wordpress \
  --title "Launch" --body "..." --user-id $SUB --output json | jq -r .draftId)
npx @island-pitch/ip-bot-cli content submit  $ID --user-id $SUB
npx @island-pitch/ip-bot-cli content approve $ID --user-id $SUB --output json
npx @island-pitch/ip-bot-cli content schedule $ID --at "in 10 minutes" --output json
npx @island-pitch/ip-bot-cli calendar wait <scheduleId> --output json

Exit codes

| Exit | Meaning | | --- | --- | | 0 | Success | | 1 | Unexpected error (transport failure, crash, bad usage) | | 2 | Operation failed or not found (e.g. unhealthy system status, draft not found, failed schedule) | | 3 | Structured handler failure — content commands returning {success:false} (wrong state, not found, permission denied) and Power failures (INSUFFICIENT_WINDS, PAID_ONLY, …) — distinct from a crash | | 124 | Timeout (e.g. calendar wait exceeded its deadline) |

On failure with --output json, the payload includes a typed error.code. See the docs Troubleshooting page for the full error-code catalog.

License

UNLICENSED — internal Island Pitch tooling.