docs: rewrite readme and changelog
This commit is contained in:
+13
-9
@@ -1,13 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 0.1.0 — 2025-12-05
|
||||
## 0.1.0 — 2025-12-20
|
||||
|
||||
### Added
|
||||
- Core command set: `tweet`, `reply`, `read`, `replies`, `thread`, `search`, `mentions`, and `whoami`.
|
||||
- Dual transports: GraphQL (cookie-based) and Sweetistics (API key); `auto` engine switches to Sweetistics when a key is present.
|
||||
- Sweetistics features: media uploads (images or single video), 15s request timeouts, and conversation fetch with `force=true` so threads/replies are always fresh.
|
||||
- Browser credential sourcing: Firefox (`--firefox-profile`) and Chrome (`--chrome-profile`) alongside env/CLI; JSON5 configs (`~/.config/bird/config.json5`, `./.birdrc.json5`) with `allowChrome`/`allowFirefox` toggles and engine defaults.
|
||||
- `whoami` works with both transports and prefers Sweetistics when available; colorized help banner plus example block.
|
||||
- CI coverage: push/PR workflow (Node 22, pnpm 10, Go stable) running `pnpm test`; test suite expanded (≥70% coverage).
|
||||
- CLI commands: `tweet`, `reply`, `read`, `replies`, `thread`, `search`, `mentions`, `whoami`, `check`.
|
||||
- URL/ID shorthand for `read`, plus `--json` output where supported.
|
||||
- GraphQL engine with cookie auth from Firefox/Chrome/env/flags (macOS browsers).
|
||||
- Sweetistics engine (API key) with automatic fallback when configured.
|
||||
- Media uploads via Sweetistics with per-item alt text (images or single video).
|
||||
- Long-form Notes and Articles extraction for full text output.
|
||||
- Thread + reply fetching with full conversation parsing.
|
||||
- Search + mentions via GraphQL (latest timeline).
|
||||
- JSON5 config files (`~/.config/bird/config.json5`, `./.birdrc.json5`) with engine defaults, profiles, allowChrome/allowFirefox, and timeoutMs.
|
||||
- Request timeouts (`--timeout`, `timeoutMs`) for GraphQL and Sweetistics calls.
|
||||
- Bun-compiled standalone binary via `pnpm run build`.
|
||||
- Query ID refresh helper: `pnpm run graphql:update`.
|
||||
|
||||
@@ -1,23 +1,40 @@
|
||||
# bird 🐦 — fast X CLI for tweeting, replying, and reading
|
||||
|
||||
`bird` is a fast X CLI for tweeting, replying, and reading — powered by cookies or Sweetistics.
|
||||
`bird` is a fast X CLI for tweeting, replying, and reading. It uses either GraphQL cookies or the Sweetistics API.
|
||||
|
||||
It keeps setup minimal while supporting common workflows for automation or scripting.
|
||||
|
||||
## Installation
|
||||
## Install
|
||||
|
||||
```bash
|
||||
cd ~/Projects/bird
|
||||
pnpm install
|
||||
pnpm run binary # Creates the 'bird' executable
|
||||
npm install -g @steipete/bird
|
||||
# or
|
||||
pnpm add -g @steipete/bird
|
||||
```
|
||||
|
||||
## Usage
|
||||
## Quickstart
|
||||
|
||||
```bash
|
||||
# Show the logged-in account
|
||||
bird 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
|
||||
|
||||
# Search + mentions
|
||||
bird search "from:steipete" -n 5
|
||||
bird mentions -n 5
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
### Commands at a glance
|
||||
- `bird tweet "<text>"` — post a new tweet.
|
||||
- `bird reply <tweet-id-or-url> "<text>"` — reply to a tweet using its ID or URL.
|
||||
- `bird read <tweet-id-or-url> [--json]` — fetch tweet content as text or JSON.
|
||||
- `bird <tweet-id-or-url> [--json]` — shorthand for `read` when only a URL or ID is provided.
|
||||
- `bird replies <tweet-id-or-url> [--json]` — list replies to a tweet.
|
||||
- `bird thread <tweet-id-or-url> [--json]` — show the full conversation thread.
|
||||
- `bird search "<query>" [-n count] [--json]` — search for tweets matching a query.
|
||||
@@ -25,196 +42,82 @@ pnpm run binary # Creates the 'bird' executable
|
||||
- `bird whoami` — print which Twitter account your cookies belong to.
|
||||
- `bird check` — show which credentials are available and where they were sourced from.
|
||||
|
||||
### Examples
|
||||
## Engines
|
||||
|
||||
```bash
|
||||
# Show the logged-in account via GraphQL cookies
|
||||
bird whoami
|
||||
- `--engine graphql` (default) — use Twitter/X GraphQL with cookies (Chrome/Firefox/env/flags).
|
||||
- `--engine sweetistics` — use Sweetistics API key (no browser cookies needed).
|
||||
- `--engine auto` — Sweetistics if a key is available, otherwise GraphQL.
|
||||
|
||||
# Use Firefox profile cookies instead of Chrome
|
||||
bird --firefox-profile default-release whoami
|
||||
Global options:
|
||||
- `--timeout <ms>`: abort requests after the given timeout (milliseconds).
|
||||
|
||||
# Send a tweet
|
||||
bird tweet "hello from bird"
|
||||
## Authentication (GraphQL)
|
||||
|
||||
# Check replies to a tweet
|
||||
bird replies https://x.com/user/status/1234567890123456789
|
||||
```
|
||||
`bird` resolves credentials in this order:
|
||||
|
||||
Transport (engine) selection:
|
||||
- `--engine graphql|sweetistics|auto` (default `graphql`).
|
||||
- `sweetistics`: use Sweetistics API key, no browser cookies needed.
|
||||
- `graphql`: use Twitter/X GraphQL with cookies (Chrome/Firefox/env/flags).
|
||||
- `auto`: Sweetistics if an API key is available, otherwise GraphQL.
|
||||
1. CLI flags: `--auth-token`, `--ct0`
|
||||
2. Environment variables: `AUTH_TOKEN`, `CT0` (fallback: `TWITTER_AUTH_TOKEN`, `TWITTER_CT0`)
|
||||
3. Browser cookies (macOS): Firefox or Chrome profiles
|
||||
|
||||
You can set persistent defaults via config files (JSON5):
|
||||
Browser cookie sources:
|
||||
- Firefox (default): `~/Library/Application Support/Firefox/Profiles/<profile>/cookies.sqlite`
|
||||
- Chrome: `~/Library/Application Support/Google/Chrome/<Profile>/Cookies`
|
||||
|
||||
## Config (JSON5)
|
||||
|
||||
Config precedence: CLI flags > env vars > project config > global config.
|
||||
|
||||
- Global: `~/.config/bird/config.json5`
|
||||
- Project: `./.birdrc.json5` (overrides global)
|
||||
- Project: `./.birdrc.json5`
|
||||
|
||||
Example `~/.config/bird/config.json5` (Firefox + GraphQL defaults):
|
||||
Example `~/.config/bird/config.json5`:
|
||||
|
||||
```json5
|
||||
{
|
||||
engine: "graphql",
|
||||
// Prefer Firefox cookies by default
|
||||
firefoxProfile: "default-release",
|
||||
// Optional: Sweetistics defaults if you want fallback/overrides
|
||||
sweetisticsApiKey: "sweet-...",
|
||||
// Allow/deny cookie sources (both default to true)
|
||||
allowFirefox: true,
|
||||
// Disable Chrome cookies entirely (optional)
|
||||
allowChrome: false
|
||||
allowChrome: false,
|
||||
timeoutMs: 20000
|
||||
}
|
||||
```
|
||||
|
||||
Precedence: CLI flags > environment variables > project config > global config.
|
||||
Environment shortcuts:
|
||||
- `SWEETISTICS_API_KEY`, `SWEETISTICS_BASE_URL`
|
||||
- `BIRD_ENGINE`, `BIRD_TIMEOUT_MS`
|
||||
|
||||
### Credential sources (macOS)
|
||||
## Output
|
||||
|
||||
Used only when transport resolves to **graphql**:
|
||||
- **Firefox (default)**: `~/Library/Application Support/Firefox/Profiles/<profile>/cookies.sqlite`. `--firefox-profile <name>` (defaults to `default-release` if present).
|
||||
- **Chrome**: `~/Library/Application Support/Google/Chrome/<Profile>/Cookies` (WAL/SHM copied too). `--chrome-profile <name>`.
|
||||
- **Env/flags** always override browser cookies.
|
||||
- `--json` prints raw tweet objects for read/replies/thread/search/mentions.
|
||||
- `read` returns full text for Notes and Articles when present.
|
||||
|
||||
Transport is chosen first; then, if transport is GraphQL, the cookie source is resolved with the same precedence.
|
||||
## Media uploads (Sweetistics only)
|
||||
|
||||
Config precedence: CLI flags > environment variables > project config (`.birdrc.json5`) > global config (`~/.config/bird/config.json5`).
|
||||
When `allowChrome` or `allowFirefox` is set to `false`, that source is skipped entirely during credential resolution.
|
||||
- Attach media with `--media` (repeatable) and optional `--alt` per item.
|
||||
- Up to 4 images, or 1 video (no mixing). Supported: jpg, jpeg, png, webp, gif, mp4, mov.
|
||||
|
||||
### Post a tweet
|
||||
Example:
|
||||
|
||||
```bash
|
||||
bird tweet "Hello from bird!"
|
||||
bird --engine sweetistics tweet "hi" --media img.png --alt "desc"
|
||||
```
|
||||
|
||||
### Media uploads (Sweetistics only)
|
||||
- Attach images or a single video with `--media` (repeatable) and optional `--alt` (aligned by order):
|
||||
- `bird --engine sweetistics tweet "hi" --media img.png --alt "desc"`
|
||||
- Up to 4 images, or 1 video (no mixing video+images). Supported: jpg, jpeg, png, webp, gif, mp4, mov.
|
||||
- Media uploads currently require the Sweetistics engine (API key). GraphQL-only mode will reject `--media`.
|
||||
- All Sweetistics calls have a 15s timeout so the CLI won’t hang if the API is slow or unreachable.
|
||||
|
||||
⚠️ GraphQL mode uses X’s internal endpoints and is rate‑limited aggressively; expect 429s if you run many reads/writes without Sweetistics.
|
||||
|
||||
### Reply to a tweet
|
||||
|
||||
```bash
|
||||
# Using tweet URL
|
||||
bird reply "https://x.com/user/status/1234567890" "This is my reply"
|
||||
|
||||
# Using tweet ID directly
|
||||
bird reply 1234567890 "This is my reply"
|
||||
```
|
||||
|
||||
### Read a tweet
|
||||
|
||||
```bash
|
||||
# Get tweet content by URL or ID
|
||||
bird read "https://x.com/user/status/1234567890"
|
||||
bird read 1234567890 --json
|
||||
```
|
||||
|
||||
### Search tweets
|
||||
|
||||
```bash
|
||||
# Search for tweets containing a query
|
||||
bird search "claude AI" -n 10
|
||||
|
||||
# Search for mentions of a user
|
||||
bird search "@clawdbot"
|
||||
```
|
||||
|
||||
### Find mentions
|
||||
|
||||
```bash
|
||||
# Shortcut to search for @clawdbot mentions
|
||||
bird mentions -n 10
|
||||
bird mentions --json
|
||||
```
|
||||
|
||||
### Check credentials
|
||||
|
||||
```bash
|
||||
bird check
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
`bird` resolves credentials in the following order of priority:
|
||||
|
||||
1. **CLI arguments** (highest priority)
|
||||
```bash
|
||||
bird --auth-token "xxx" --ct0 "yyy" tweet "Hello"
|
||||
```
|
||||
|
||||
2. **Environment variables**
|
||||
```bash
|
||||
export AUTH_TOKEN="xxx"
|
||||
export CT0="yyy"
|
||||
bird tweet "Hello"
|
||||
```
|
||||
|
||||
Alternative env var names: `TWITTER_AUTH_TOKEN`, `TWITTER_CT0`
|
||||
|
||||
3. **Chrome cookies** (fallback - macOS only)
|
||||
- Automatically extracts from Chrome's cookie database
|
||||
- Requires Chrome to be logged into x.com
|
||||
- May prompt for keychain access on first run
|
||||
|
||||
### Credential sources (macOS)
|
||||
|
||||
Used only when transport resolves to **graphql**:
|
||||
- **Firefox (default)**: `~/Library/Application Support/Firefox/Profiles/<profile>/cookies.sqlite`. `--firefox-profile <name>` (defaults to `default-release` if present).
|
||||
- **Chrome**: `~/Library/Application Support/Google/Chrome/<Profile>/Cookies` (WAL/SHM copied too). `--chrome-profile <name>`.
|
||||
- **Env/flags** always override browser cookies.
|
||||
|
||||
Precedence: CLI flags > env vars > project config > global config. Transport is chosen first; then, if transport is GraphQL, cookie source is chosen.
|
||||
|
||||
### Posting via Sweetistics (API key)
|
||||
|
||||
If you have a Sweetistics API key, `bird` can post through the Sweetistics SaaS instead of using local Twitter cookies:
|
||||
|
||||
```bash
|
||||
export SWEETISTICS_API_KEY="sweet-..."
|
||||
bird tweet "Hello from Sweetistics!"
|
||||
|
||||
# Optional: point to a self-hosted instance
|
||||
bird --sweetistics-base-url "http://localhost:3000" --sweetistics-api-key "sweet-..." tweet "hi"
|
||||
```
|
||||
|
||||
When an API key is present, `bird` will use Sweetistics’ `/api/actions/tweet` endpoint and skip local cookie resolution.
|
||||
All Sweetistics calls have a 15s timeout so the CLI won’t hang if the API is slow or unreachable.
|
||||
|
||||
**Threads/replies freshness (Sweetistics):** conversation calls (`thread`, `replies`) are requested with `force=true`, bypassing Sweetistics cache to ensure the latest tweets are returned.
|
||||
|
||||
⚠️ GraphQL mode uses X’s internal endpoints and is rate‑limited aggressively; expect 429s if you run many reads/writes without Sweetistics.
|
||||
|
||||
### Getting Your Cookies
|
||||
|
||||
1. Open Chrome and log into x.com
|
||||
2. Open DevTools (Cmd+Option+I)
|
||||
3. Go to Application > Cookies > x.com
|
||||
4. Copy the values for `auth_token` and `ct0`
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
# Run in development mode
|
||||
cd ~/Projects/bird
|
||||
pnpm install
|
||||
pnpm run build # dist/ + bun binary
|
||||
pnpm run build:dist # dist/ only
|
||||
pnpm run build:binary
|
||||
|
||||
pnpm run dev tweet "Test"
|
||||
|
||||
# Run tests
|
||||
pnpm test
|
||||
|
||||
# Run linter
|
||||
pnpm run lint
|
||||
|
||||
# Fix lint issues
|
||||
pnpm run lint:fix
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Chrome cookie extraction requires macOS (uses `sqlite3` and `security` CLI tools).
|
||||
- The keychain access may block when running over SSH; use environment variables instead.
|
||||
- Twitter/X rotates GraphQL query IDs; refresh them with `pnpm run graphql:update` (writes `src/lib/query-ids.json`).
|
||||
- GraphQL uses internal X endpoints and can be rate limited (429).
|
||||
- Query IDs rotate; refresh them with `pnpm run graphql:update`.
|
||||
|
||||
Reference in New Issue
Block a user