Command Line (CLI)
Post to X, Bluesky, LinkedIn, Mastodon and Threads from your terminal with the octopost command. One binary for macOS and Linux, browser sign-in or an API key.
octopost posts from your terminal: publish now, schedule, add to your queue, check a post before it goes out, and see what happened. It's one self-contained binary for macOS and Linux, so there's nothing else to install.
Network status (2026-11): X is live. Threads opens after Meta approves the Octopost app. Bluesky, LinkedIn and Mastodon are in testing.
Install
curl -fsSL https://octopost.ink/cli/install.sh | shThe script picks the build for your computer (macOS or Linux, Apple silicon/ARM or Intel/x64), checks its SHA-256 against SHA256SUMS, and puts octopost in ~/.local/bin. It doesn't use sudo. Set OCTOPOST_INSTALL_DIR to install somewhere else.
The macOS builds are signed with Great Work's Developer ID and notarized by Apple.
Prefer to download by hand? The binaries are at https://octopost.ink/cli/<platform>/octopost, where platform is darwin-arm64, darwin-x64, linux-x64 or linux-arm64.
Sign in
octopost loginYour browser opens on Octopost. Sign in, check the account and click Allow. The CLI saves the sign-in to ~/.config/octopost/credentials.json (readable only by you) and refreshes it on its own. It shows up as "Octopost CLI" under Connected apps on the API keys page, where Disconnect ends it.
On a server, in CI, or anywhere without a browser, use an API key instead:
octopost login --key op_...
# or, without saving anything:
OCTOPOST_API_KEY=op_... octopost accountsoctopost whoami shows how you're signed in. octopost logout forgets the saved sign-in.
Post
octopost post "Shipped the new export button today"With no --to, the post goes to every network you have connected. Pick networks with --to (comma-separated or repeated; x means X/Twitter):
octopost post "Hello from the terminal" --to x,blueskyAttach images or a video with --media. Local files are uploaded for you; URLs are used as they are. --alt sets alt text for the --media in the same position:
octopost post "The new dashboard" --to x \
--media ./screenshot.png --alt "Dashboard with a weekly chart" \
--media https://example.com/second.jpgMake a thread with --thread, one per reply. Putting a link in a reply instead of the first post keeps X from showing the post to fewer people:
octopost post "I wrote up how we cut our build time in half" --to x \
--thread "https://example.com/blog/faster-builds"Read the text from a file or another command with -:
cat announcement.txt | octopost post - --to xOther options: --account x=@handle picks the account when a network has several connected, and --allow-duplicate posts the same text again (Octopost refuses the same text to the same network within 7 days without it).
Check before posting
octopost preview "Is this too long for X? ..." --to x,blueskyShows each network's character count against its limit, the X units it would use, media checks and anything that would stop it. Nothing is saved or posted. It exits with status 1 when the post wouldn't go out, so scripts can stop early.
Schedule
octopost schedule "Weekly update is live" --to x --at "2026-11-10 09:00"--at takes:
| You write | Means |
|---|---|
+30m, +2h, +1d | that long from now |
17:30, 9am, 9:30pm | today at that time, or tomorrow if it has passed |
2026-11-10 09:00 | that date and time in your computer's time zone |
2026-11-10T09:00:00-05:00 | an exact ISO 8601 time |
Add --approval to hold it until someone approves it from the email Octopost sends. See Scheduling Posts.
Queue
octopost queue "An evergreen tip about keyboard shortcuts" --to x
octopost queue "Draft from the release script" --to x --approval
octopost queue # how many are queued, when the next one goes outQueued posts go out one at a time during your active hours. See Post Queue.
See your posts
octopost list # newest first
octopost list --status failed # published, scheduled, draft, queued, pending, partial, failed, retrying
octopost list --limit 50
octopost get <post-id> # text, networks, links, errors
octopost retry <post-id> # retry the networks that failed
octopost retry <post-id> --to x # retry only XWhen there are more posts, list prints the --cursor for the next page.
Accounts and usage
octopost accounts # connected accounts, which one is the default per network
octopost usage # plan, X units left this month, accounts usedScripts and agents
Every command takes --json and prints the raw answer, the same JSON the MCP tools return:
octopost list --status scheduled --json | jq -r '.posts[].id'Exit status is 0 on success, 1 when Octopost refused or the post failed (including a partly published post), and 2 for a mistake in the command itself. Error messages go to stderr.
Coding agents (Claude Code, Cursor, Codex) can run octopost like any other command once you've signed in. If your agent supports MCP, connecting https://octopost.ink/mcp directly gives it the same tools without a shell; see Agent Integration.
Reference
octopost login [--key op_...] [--no-browser]
octopost logout | whoami
octopost post "text" [--to x,bluesky] [--media FILE|URL ...] [--alt "text" ...] [--thread "text" ...]
octopost schedule "text" --at TIME [--approval] [post options]
octopost queue ["text"] [--approval] [post options]
octopost preview "text" [post options]
octopost list [--status S] [--limit N] [--cursor C]
octopost get <post-id>
octopost retry <post-id> [--to x]
octopost accounts | usageGlobal options: --json, --key op_... (one command only), --base URL (another Octopost server; also OCTOPOST_URL), --help, --version.
The CLI talks to https://octopost.ink/mcp, which accepts both browser sign-ins and API keys. Your sign-in lives in $XDG_CONFIG_HOME/octopost/credentials.json (default ~/.config/octopost).