bird
Original:🇺🇸 English
Translated
Fast X CLI for tweeting, replying, and reading via X/Twitter GraphQL (cookie auth). Supports: read tweets, search, thread/replies, bookmarks, likes, news/trending, user timelines, following/followers, lists. Can be used as a library. Note: Recommended for reading only. Writing will hit blocks quickly.
9installs
Sourceninehills/skills
Added on
NPX Install
npx skill4agent add ninehills/skills birdTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →bird 🐦 — fast X CLI for tweeting, replying, and reading
birdDisclaimer
This project uses X/Twitter’s undocumented web GraphQL API (and cookie auth). X can change endpoints, query IDs,
and anti-bot behavior at any time — expect this to break without notice.
Strong recommendation: Do not use bird to tweet. You will hit blocks very quickly. Use it to read tweets.
Bots are not welcome on X/Twitter. If you absolutely have to, use browser automation instead, or pay for the Twitter API to create tweets.
Install
bash
npm install -g @steipete/bird
# or
pnpm add -g @steipete/bird
# or
bun add -g @steipete/bird
# one-shot (no install)
bunx @steipete/bird whoamiHomebrew (macOS, prebuilt Bun binary):
bash
brew install steipete/tap/birdQuickstart
bash
# Show the logged-in account
bird whoami
# Discover command help
bird help whoami
# Read a tweet (URL or ID)
bird read https://x.com/user/status/1234567890123456789
bird 1234567890123456789 --json
# Thread + replies
bird thread https://x.com/user/status/1234567890123456789
bird replies 1234567890123456789
bird replies 1234567890123456789 --max-pages 3 --json
bird thread 1234567890123456789 --max-pages 3 --json
# Search + mentions
bird search "from:steipete" -n 5
bird mentions -n 5
bird mentions --user @steipete -n 5
# User tweets (profile timeline)
bird user-tweets @steipete -n 20
bird user-tweets @steipete -n 50 --json
# Bookmarks
bird bookmarks -n 5
bird bookmarks --folder-id 123456789123456789 -n 5 # https://x.com/i/bookmarks/<folder-id>
bird bookmarks --all --json
bird bookmarks --all --max-pages 2 --json
bird bookmarks --include-parent --json
bird unbookmark 1234567890123456789
bird unbookmark https://x.com/user/status/1234567890123456789
# Likes
bird likes -n 5
# News and trending topics (AI-curated from Explore tabs)
bird news --ai-only -n 10
bird news --sports -n 5
# Lists
bird list-timeline 1234567890 -n 20
bird list-timeline https://x.com/i/lists/1234567890 --all --json
bird list-timeline 1234567890 --max-pages 3 --json
# Following (who you follow)
bird following -n 20
bird following --user 12345678 -n 10 # by user ID
# Followers (who follows you)
bird followers -n 20
bird followers --user 12345678 -n 10 # by user ID
# Refresh GraphQL query IDs cache (no rebuild)
bird query-ids --freshNews & Trending
Fetch AI-curated news and trending topics from X's Explore page tabs:
bash
# Fetch 10 news items from all tabs (default: For You, News, Sports, Entertainment)
bird news -n 10
# Fetch only AI-curated news (filters out regular trends)
bird news --ai-only -n 20
# Fetch from specific tabs
bird news --news-only --ai-only -n 10
bird news --sports -n 15
bird news --entertainment --ai-only -n 5
# Include related tweets for each news item
bird news --with-tweets --tweets-per-item 3 -n 10
# Combine multiple tab filters
bird news --sports --entertainment -n 20
# JSON output
bird news --json -n 5
bird news --json-full --ai-only -n 10 # includes raw API responseTab options (can be combined):
- — Fetch from For You tab only
--for-you - — Fetch from News tab only
--news-only - — Fetch from Sports tab only
--sports - — Fetch from Entertainment tab only
--entertainment - — Fetch from Trending tab only
--trending-only
By default, the command fetches from For You, News, Sports, and Entertainment tabs (Trending excluded to reduce noise). Headlines are automatically deduplicated across tabs.
Library
birdts
import { TwitterClient, resolveCredentials } from '@steipete/bird';
const { cookies } = await resolveCredentials({ cookieSource: 'safari' });
const client = new TwitterClient({ cookies });
// Search for tweets
const searchResult = await client.search('from:steipete', 50);
// Fetch news and trending topics from all tabs (default: For You, News, Sports, Entertainment)
const newsResult = await client.getNews(10, { aiOnly: true });
// Fetch from specific tabs with related tweets
const sportsNews = await client.getNews(10, {
aiOnly: true,
withTweets: true,
tabs: ['sports', 'entertainment']
});Account details (About profile):
ts
const aboutResult = await client.getUserAboutAccount('steipete');
if (aboutResult.success && aboutResult.aboutProfile) {
console.log(aboutResult.aboutProfile.accountBasedIn);
}Fields:
accountBasedInsourcecreatedCountryAccuratelocationAccuratelearnMoreUrl
Commands
- — post a new tweet.
bird tweet "<text>" - — reply to a tweet using its ID or URL.
bird reply <tweet-id-or-url> "<text>" - — show help (or help for a subcommand).
bird help [command] - — inspect or refresh cached GraphQL query IDs.
bird query-ids [--fresh] [--json] - — fetch your home timeline (For You) or Following feed.
bird home [-n count] [--following] [--json] [--json-full] - — fetch tweet content as text or JSON.
bird read <tweet-id-or-url> [--json] - — shorthand for
bird <tweet-id-or-url> [--json]when only a URL or ID is provided.read - — list replies to a tweet.
bird replies <tweet-id-or-url> [--all] [--max-pages n] [--cursor string] [--delay ms] [--json] - — show the full conversation thread.
bird thread <tweet-id-or-url> [--all] [--max-pages n] [--cursor string] [--delay ms] [--json] - — search for tweets matching a query;
bird search "<query>" [-n count] [--all] [--max-pages n] [--cursor string] [--json]requires--max-pagesor--all.--cursor - — find tweets mentioning a user (defaults to the authenticated user).
bird mentions [-n count] [--user @handle] [--json] - — get tweets from a user's profile timeline.
bird user-tweets <@handle> [-n count] [--cursor string] [--max-pages n] [--delay ms] [--json] - — list your bookmarked tweets (or a specific bookmark folder); expansion flags control thread context;
bird bookmarks [-n count] [--folder-id id] [--all] [--max-pages n] [--cursor string] [--expand-root-only] [--author-chain] [--author-only] [--full-chain-only] [--include-ancestor-branches] [--include-parent] [--thread-meta] [--sort-chronological] [--json]requires--max-pagesor--all.--cursor - — remove one or more bookmarks by tweet ID or URL.
bird unbookmark <tweet-id-or-url...> - — list your liked tweets;
bird likes [-n count] [--all] [--max-pages n] [--cursor string] [--json] [--json-full]requires--max-pagesor--all.--cursor - — fetch news and trending topics from X's Explore tabs.
bird news [-n count] [--ai-only] [--with-tweets] [--tweets-per-item n] [--for-you] [--news-only] [--sports] [--entertainment] [--trending-only] [--json] - — alias for
bird trendingcommand.news - — list your lists (owned or memberships).
bird lists [--member-of] [-n count] [--json] - — get tweets from a list timeline;
bird list-timeline <list-id-or-url> [-n count] [--all] [--max-pages n] [--cursor string] [--json]implies--max-pages.--all - — list users that you (or another user) follow;
bird following [--user <userId>] [-n count] [--cursor string] [--all] [--max-pages n] [--json]requires--max-pages.--all - — list users that follow you (or another user);
bird followers [--user <userId>] [-n count] [--cursor string] [--all] [--max-pages n] [--json]requires--max-pages.--all - — get account origin and location information for a user.
bird about <@handle> [--json] - — print which Twitter account your cookies belong to.
bird whoami - — show which credentials are available and where they were sourced from.
bird check
Bookmarks flags:
- : expand threads only when the bookmark is a root tweet.
--expand-root-only - : keep only the bookmarked author's connected self-reply chain.
--author-chain - : include all tweets from the bookmarked author within the thread.
--author-only - : keep the entire reply chain connected to the bookmarked tweet (all authors).
--full-chain-only - : include sibling branches for ancestors when using
--include-ancestor-branches.--full-chain-only - : include the direct parent tweet for non-root bookmarks.
--include-parent - : add thread metadata fields to each tweet.
--thread-meta - : sort output globally oldest to newest (default preserves bookmark order).
--sort-chronological
Global options:
- : set the
--auth-token <token>cookie manually.auth_token - : set the
--ct0 <token>cookie manually.ct0 - : choose browser cookie source (repeatable; order matters).
--cookie-source <safari|chrome|firefox> - : Chrome profile name for cookie extraction (e.g.,
--chrome-profile <name>,Default).Profile 2 - : Chrome/Chromium profile directory or cookie DB path for cookie extraction.
--chrome-profile-dir <path> - : Firefox profile for cookie extraction.
--firefox-profile <name> - : cookie extraction timeout for keychain/OS helpers (milliseconds).
--cookie-timeout <ms> - : abort requests after the given timeout (milliseconds).
--timeout <ms> - : max quoted tweet depth in JSON output (default: 1; 0 disables).
--quote-depth <n> - : stable output (no emoji, no color).
--plain - : disable emoji output.
--no-emoji - : disable ANSI colors (or set
--no-color).NO_COLOR=1 - : attach media file (repeatable, up to 4 images or 1 video).
--media <path> - : alt text for the corresponding
--alt <text>(repeatable).--media
Authentication (GraphQL)
GraphQL mode uses your existing X/Twitter web session (no password prompt). It sends requests to internal
X endpoints and authenticates via cookies (, ).
auth_tokenct0Write operations:
- /
tweetprimarily use GraphQL (reply).CreateTweet - If GraphQL returns error (“automated request”),
226falls back to the legacybirdendpoint.statuses/update.json
bird- CLI flags: ,
--auth-token--ct0 - Environment variables: ,
AUTH_TOKEN(fallback:CT0,TWITTER_AUTH_TOKEN)TWITTER_CT0 - Browser cookies via (override via
@steipete/sweet-cookieorder)--cookie-source
Browser cookie sources:
- Safari: (fallback:
~/Library/Cookies/Cookies.binarycookies)~/Library/Containers/com.apple.Safari/Data/Library/Cookies/Cookies.binarycookies - Chrome:
~/Library/Application Support/Google/Chrome/<Profile>/Cookies - Firefox:
~/Library/Application Support/Firefox/Profiles/<profile>/cookies.sqlite- For Chromium variants (Arc/Brave/etc), pass a profile directory or cookie DB via .
--chrome-profile-dir
- For Chromium variants (Arc/Brave/etc), pass a profile directory or cookie DB via
Config (JSON5)
Config precedence: CLI flags > env vars > project config > global config.
- Global:
~/.config/bird/config.json5 - Project:
./.birdrc.json5
Example :
~/.config/bird/config.json5json5
{
// Cookie source order for browser extraction (string or array)
cookieSource: ["firefox", "safari"],
chromeProfileDir: "/path/to/Chromium/Profile",
firefoxProfile: "default-release",
cookieTimeoutMs: 30000,
timeoutMs: 20000,
quoteDepth: 1
}Environment shortcuts:
BIRD_TIMEOUT_MSBIRD_COOKIE_TIMEOUT_MSBIRD_QUOTE_DEPTH
Output
- prints raw tweet objects for read/replies/thread/search/mentions/user-tweets/bookmarks/likes.
--json - When using with pagination (
--json,--all,--cursor, or for--max-pageswhenuser-tweets), output is-n > 20.{ tweets, nextCursor } - returns full text for Notes and Articles when present.
read - Use for stable, script-friendly output (no emoji, no color).
--plain
JSON Schema
When using , tweet objects include:
--json| Field | Type | Description |
|---|---|---|
| string | Tweet ID |
| string | Full tweet text (includes Note/Article content when present) |
| object | |
| string? | Author's user ID |
| string | Timestamp |
| number | Number of replies |
| number | Number of retweets |
| number | Number of likes |
| string | Thread conversation ID |
| string? | Parent tweet ID (present if this is a reply) |
| object? | Embedded quote tweet (same schema; depth controlled by |
When using with /, user objects include:
--jsonfollowingfollowers| Field | Type | Description |
|---|---|---|
| string | User ID |
| string | Username/handle |
| string | Display name |
| string? | User bio |
| number? | Followers count |
| number? | Following count |
| boolean? | Blue verified flag |
| string? | Profile image URL |
| string? | Account creation timestamp |
When using with /, news objects include:
--jsonnewstrending| Field | Type | Description |
|---|---|---|
| string | Unique identifier for the news item |
| string | News headline or trend title |
| string? | Category (e.g., "AI · Technology", "Trending", "News") |
| string? | Relative time (e.g., "2h ago") |
| number? | Number of posts |
| string? | Item description |
| string? | URL to the trend or news article |
| array? | Related tweets (only when |
| object? | Raw API response (only when |
Query IDs (GraphQL)
X rotates GraphQL “query IDs” frequently. Each GraphQL operation is addressed as:
- (e.g.
operationName,TweetDetail)CreateTweet - (rotating ID baked into X’s web client bundles)
queryId
birdsrc/lib/query-ids.jsondist/Runtime cache:
- Default path:
~/.config/bird/query-ids-cache.json - Override path:
BIRD_QUERY_IDS_CACHE=/path/to/file.json - TTL: 24h (stale cache is still used, but marked “not fresh”)
Auto-recovery:
- On GraphQL (query ID invalid),
404forces a refresh once and retries.bird - For /
TweetDetail,SearchTimelinealso rotates through a small set of known fallback IDs to reduce breakage while refreshing.bird
Refresh on demand:
bash
bird query-ids --freshExit codes:
- : success
0 - : runtime error (network/auth/etc)
1 - : invalid usage/validation (e.g. bad
2handle)--user
Version
bird --versionpackage.json0.3.0 (3df7969b)Media uploads
- Attach media with (repeatable) and optional
--mediaper item.--alt - Up to 4 images/GIFs, or 1 video (no mixing). Supported: jpg, jpeg, png, webp, gif, mp4, mov.
- Images/GIFs + 1 video supported (uploads via Twitter legacy upload endpoint + cookies; video may take longer to process).
Example:
bash
bird tweet "hi" --media img.png --alt "desc"