Use twitter safe relay
CI / test (pull_request) Has been cancelled

This commit is contained in:
2026-06-24 03:39:34 +09:00
parent b771e827aa
commit 1f6e228272
66 changed files with 597 additions and 1720 deletions
+21 -34
View File
@@ -1,11 +1,11 @@
# bird 🐦 — fast X CLI for tweeting, replying, and reading
`bird` is a fast X CLI for tweeting, replying, and reading via X/Twitter GraphQL (cookie auth).
`bird` is a fast X CLI for tweeting, replying, and reading via X/Twitter GraphQL through twitter safe relay.
## Disclaimer
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**.
This project uses X/Twitter’s **undocumented** web GraphQL API through twitter safe relay. X can change endpoints,
query IDs, and anti-bot behavior at any time — **expect this to break without notice**.
## Install
@@ -29,6 +29,9 @@ brew install steipete/tap/bird
## Quickstart
```bash
# Point bird at your running twitter safe relay
export TWITTER_RELAY_BASE_URL=http://localhost:6900
# Show the logged-in account
bird whoami
@@ -127,10 +130,11 @@ By default, the command fetches from For You, News, Sports, and Entertainment ta
`bird` can be used as a library (same GraphQL client as the CLI):
```ts
import { TwitterClient, resolveCredentials } from '@steipete/bird';
import { TwitterClient } from '@steipete/bird';
const { cookies } = await resolveCredentials({ cookieSource: 'safari' });
const client = new TwitterClient({ cookies });
const client = new TwitterClient({
relayBaseUrl: process.env.TWITTER_RELAY_BASE_URL
});
// Search for tweets
const searchResult = await client.search('from:steipete', 50);
@@ -167,24 +171,19 @@ const sportsNews = await client.getNews(10, {
- `bird list-timeline <list-id-or-url> [-n count] [--all] [--max-pages n] [--cursor string] [--json]` — get tweets from a list timeline; `--max-pages` implies `--all`.
- `bird following [--user <userId>] [-n count] [--json]` — list users that you (or another user) follow.
- `bird followers [--user <userId>] [-n count] [--json]` — list users that follow you (or another user).
- `bird whoami` — print which Twitter account your cookies belong to.
- `bird check` — show which credentials are available and where they were sourced from.
- `bird whoami` — print which Twitter account your relay belongs to.
- `bird check` — verify relay configuration and account access.
- `bird likes [-n count] [--json]` — list your liked tweets.
- `bird news [-n count] [--ai-only] [--with-tweets] [--tweets-per-item n] [--for-you] [--news-only] [--sports] [--entertainment] [--trending-only] [--json]` — fetch news and trending topics from X's Explore tabs (fetches from For You, News, Sports, and Entertainment tabs by default).
- `bird trending` — alias for `news` command.
- `bird list-timeline <list-id-or-url> [-n count] [--all] [--max-pages n] [--cursor string] [--json]` — get tweets from a list timeline; `--max-pages` implies `--all`.
- `bird following [--user <userId>] [-n count] [--json]` — list users that you (or another user) follow.
- `bird followers [--user <userId>] [-n count] [--json]` — list users that follow you (or another user).
- `bird whoami` — print which Twitter account your cookies belong to.
- `bird check` — show which credentials are available and where they were sourced from.
- `bird whoami` — print which Twitter account your relay belongs to.
- `bird check` — verify relay configuration and account access.
Global options:
- `--auth-token <token>`: set the `auth_token` cookie manually.
- `--ct0 <token>`: set the `ct0` cookie manually.
- `--cookie-source <safari|chrome|firefox>`: choose browser cookie source (repeatable; order matters).
- `--chrome-profile <name>`: Chrome profile for cookie extraction.
- `--firefox-profile <name>`: Firefox profile for cookie extraction.
- `--cookie-timeout <ms>`: cookie extraction timeout for keychain/OS helpers (milliseconds).
- `--relay-base-url <url>`: twitter safe relay base URL (defaults to `TWITTER_RELAY_BASE_URL`).
- `--timeout <ms>`: abort requests after the given timeout (milliseconds).
- `--quote-depth <n>`: max quoted tweet depth in JSON output (default: 1; 0 disables).
- `--plain`: stable output (no emoji, no color).
@@ -195,23 +194,14 @@ Global options:
## 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_token`, `ct0`).
`bird` does not handle Twitter authentication locally. It sends Twitter API-compatible requests to twitter safe relay,
and the relay handles authentication.
Write operations:
- `tweet`/`reply` primarily use GraphQL (`CreateTweet`).
- If GraphQL returns error `226` (“automated request”), `bird` falls back to the legacy `statuses/update.json` endpoint.
`bird` resolves credentials in this order:
1. CLI flags: `--auth-token`, `--ct0`
2. Environment variables: `AUTH_TOKEN`, `CT0` (fallback: `TWITTER_AUTH_TOKEN`, `TWITTER_CT0`)
3. Browser cookies via `@steipete/sweet-cookie` (override via `--cookie-source` order)
Browser cookie sources:
- Safari: `~/Library/Cookies/Cookies.binarycookies` (fallback: `~/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`
Configure the relay URL with `TWITTER_RELAY_BASE_URL` or `--relay-base-url`.
## Config (JSON5)
@@ -224,18 +214,15 @@ Example `~/.config/bird/config.json5`:
```json5
{
// Cookie source order for browser extraction (string or array)
cookieSource: ["firefox", "safari"],
firefoxProfile: "default-release",
cookieTimeoutMs: 30000,
relayBaseUrl: "http://localhost:6900",
timeoutMs: 20000,
quoteDepth: 1
}
```
Environment shortcuts:
- `TWITTER_RELAY_BASE_URL`
- `BIRD_TIMEOUT_MS`
- `BIRD_COOKIE_TIMEOUT_MS`
- `BIRD_QUOTE_DEPTH`
## Output
@@ -331,7 +318,7 @@ Exit codes:
- Attach media with `--media` (repeatable) and optional `--alt` per item.
- 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).
- Images/GIFs + 1 video supported (uploads via Twitter legacy upload endpoint through the relay; video may take longer to process).
Example: