docs: rewrite readme and changelog

This commit is contained in:
Peter Steinberger
2025-12-20 11:29:53 +01:00
parent aa659a6048
commit ddd9802a14
2 changed files with 80 additions and 173 deletions
+13 -9
View File
@@ -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`.
+67 -164
View File
@@ -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`.