From ddd9802a14ccded509a8a0e63887cfd68fa1ee0c Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 20 Dec 2025 11:29:53 +0100 Subject: [PATCH] docs: rewrite readme and changelog --- CHANGELOG.md | 22 +++-- README.md | 231 +++++++++++++++------------------------------------ 2 files changed, 80 insertions(+), 173 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ee3c1e..32262ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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`. diff --git a/README.md b/README.md index e2f9779..22f5d30 100644 --- a/README.md +++ b/README.md @@ -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 ""` — post a new tweet. - `bird reply ""` — reply to a tweet using its ID or URL. - `bird read [--json]` — fetch tweet content as text or JSON. +- `bird [--json]` — shorthand for `read` when only a URL or ID is provided. - `bird replies [--json]` — list replies to a tweet. - `bird thread [--json]` — show the full conversation thread. - `bird search "" [-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 `: 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//cookies.sqlite` +- Chrome: `~/Library/Application Support/Google/Chrome//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//cookies.sqlite`. `--firefox-profile ` (defaults to `default-release` if present). -- **Chrome**: `~/Library/Application Support/Google/Chrome//Cookies` (WAL/SHM copied too). `--chrome-profile `. -- **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//cookies.sqlite`. `--firefox-profile ` (defaults to `default-release` if present). -- **Chrome**: `~/Library/Application Support/Google/Chrome//Cookies` (WAL/SHM copied too). `--chrome-profile `. -- **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`.