907 lines · 30.4 KB · Markdown
RawDownload

CLI Spec

Designed with create-cli defaults:

  • humans first
  • scriptable
  • stable --json
  • diagnostics on stderr
  • prompts only on TTY

Name

birdclaw

One-liner

birdclaw imports, syncs, searches, and operates on a local Twitter archive.

Usage

birdclaw [global flags] <subcommand> [args]

Global flags

  • -h, --help
  • --version
  • --json

Config precedence

Command flags > environment overrides > user config

User config:

  • ~/.birdclaw/config.json

Env vars

  • BIRDCLAW_HOME
  • BIRDCLAW_CONFIG
  • BIRDCLAW_ACTIONS_TRANSPORT
  • BIRDCLAW_BIRD_COMMAND
  • BIRDCLAW_BASH_COMMAND
  • BIRDCLAW_MCP_TOKEN
  • BIRDCLAW_MCP_PUBLIC_URL
  • BIRDCLAW_MCP_ACCOUNT

Command tree

birdclaw init [--demo]
birdclaw auth status
birdclaw auth use <transport>
birdclaw import archive [path]
birdclaw import tweet <tweet-id-or-url...> --fxtwitter
birdclaw sync all
birdclaw sync tweets
birdclaw sync authored
birdclaw sync dms
birdclaw sync bookmarks
birdclaw sync likes
birdclaw sync timeline
birdclaw sync mentions
birdclaw sync mention-threads
birdclaw sync followers
birdclaw sync following
birdclaw sync lists
birdclaw lists list
birdclaw lists members [name]
birdclaw import tweet <tweet-id-or-url...> --fxtwitter
birdclaw import thread <tweet-id-or-url> --fxtwitter
birdclaw import conversation <tweet-id-or-url> --fxtwitter
birdclaw import profile <handle> --fxtwitter
birdclaw search tweets <query>
birdclaw search dms <query>
birdclaw discuss <query>
birdclaw today
birdclaw digest [today|24h|yesterday|week]
birdclaw mentions export [query]
birdclaw media fetch
birdclaw dms list
birdclaw mute <handle-or-id>
birdclaw unmute <handle-or-id>
birdclaw mutes list
birdclaw blocks list
birdclaw blocks add <handle-or-id>
birdclaw blocks remove <handle-or-id>
birdclaw ban <handle-or-id>
birdclaw unban <handle-or-id>
birdclaw show tweet <id>
birdclaw show thread <id>
birdclaw show dm <conversation-id>
birdclaw inbox
birdclaw serve
birdclaw graph summary
birdclaw graph events
birdclaw graph top-followers
birdclaw graph unfollowed
birdclaw graph non-mutual-following
birdclaw graph mutuals
birdclaw compose post
birdclaw compose reply <tweet-id>
birdclaw db stats
birdclaw db vacuum
birdclaw backup export --repo <path>
birdclaw backup sync --repo <path> --remote <url>
birdclaw backup import <path>
birdclaw backup validate <path>
birdclaw debug transport

Subcommand semantics

today

  • alias for digest today
  • streams Markdown as model tokens arrive
  • uses gpt-5.5, medium reasoning, and priority service tier by default
  • requires OPENAI_API_KEY
  • excludes DMs unless --include-dms is passed
  • supports --refresh, --model, --language <locale-id>, --max-tweets, and --max-links
  • reads the default report language from BIRDCLAW_DIGEST_LANGUAGE

digest [period]

  • period: today, 24h, yesterday, or week
  • accepts explicit --since <iso> and --until <iso> windows
  • caches the final structured result by local context hash, model, reasoning effort, service tier, and canonical report language
  • accepts the same language tag through GET /api/period-digest?language=zh-CN
  • --json suppresses token streaming and emits the final envelope

init

  • create app dir
  • create an empty DB
  • write default config if absent
  • --demo seeds sample tweets, DMs, profiles, and links without authentication or network access
  • print useful next commands for the selected setup path

Account-capable commands accept --account <username> or a stored account ID. Set accounts.default in config.json for a reversible default; an explicit flag wins.

import tweet <tweet-id-or-url...>

  • disabled unless --fxtwitter is passed on the same invocation
  • sends only requested public tweet IDs to the fixed read-only https://api.fxtwitter.com service
  • rejects custom origins, redirects, noncanonical URLs, and batches larger than 20 tweets
  • stores fxtwitter source markers in tweet_sources and data/tweet_sources.jsonl backups
  • discloses requested IDs plus ordinary network metadata such as IP address and request time to the third-party service

See Public tweet import for the full privacy and capability boundary.

import thread|conversation <tweet-id-or-url>

  • disabled unless --fxtwitter is passed on the same invocation
  • imports only positively observed public tweets through the fixed FxTwitter origin
  • accepts --limit <n> up to 1,000 and always reports the collection as partial because the endpoint cannot prove exhaustion
  • preserves the upstream reply count and next cursor as evidence, never as completeness proof

import profile <handle>

  • disabled unless --fxtwitter is passed on the same invocation
  • imports the named public profile object, not its statuses or another timeline
  • rejects URLs, custom origins, private/account data, and write capabilities before network access

auth status

  • show transport availability
  • show active account/profile
  • never print secrets

auth use <transport>

  • set preferred moderation action transport
  • allowed: auto, xurl, bird

backup export

  • writes Git-friendly canonical JSONL text shards
  • removes and rewrites the data/ directory in the backup repo
  • validates the manifest and file hashes by default
  • --commit creates a Git commit in the backup repo
  • --push implies commit and pushes the backup repo
birdclaw backup export --repo ~/Projects/birdclaw-store --commit --push

backup sync

  • clones/configures the backup Git repo when needed
  • pulls the backup repo before reading
  • merge-imports remote backup rows into local SQLite
  • exports the local union back into deterministic text shards
  • commits and pushes the backup repo
birdclaw backup sync --repo ~/Projects/backup-birdclaw --remote https://github.com/steipete/backup-birdclaw.git --json

Shard contract:

  • tweets: data/tweets/YYYY.jsonl
  • tweet provenance: data/tweet_sources.jsonl
  • FxTwitter fetch/completeness metadata: data/fxtwitter/fetches.jsonl
  • FxTwitter positive item observations: data/fxtwitter/observations.jsonl
  • unknown tweet dates: data/tweets/unknown.jsonl
  • tweet revisions: data/tweet_revisions.jsonl
  • subordinate tweet tombstones: data/tweet_subordinate_tombstones.jsonl
  • profiles: data/profiles.jsonl includes bio, follower/following counts, profile URL, location, verification type, structured URL entities, and raw profile JSON
  • affiliations: data/profile_affiliations.jsonl includes X badge/highlighted-label organization edges
  • identity history: data/profile_snapshots.jsonl and data/profile_bio_entities.jsonl preserve profile-change states and extracted bio identity hints
  • collections: data/collections/likes.jsonl, data/collections/bookmarks.jsonl
  • DMs: data/dms/conversations.jsonl plus data/dms/YYYY.jsonl
  • moderation: data/moderation/blocks.jsonl, data/moderation/mutes.jsonl
  • no SQLite WAL/SHM, FTS shadow tables, or transient live cache rows

Backup auto-sync config lives in ~/.birdclaw/config.json:

{
	"backup": {
		"repoPath": "/Users/steipete/Projects/backup-birdclaw",
		"remote": "https://github.com/steipete/backup-birdclaw.git",
		"autoSync": true,
		"staleAfterSeconds": 900
	}
}

Read commands pull + merge only when the last backup check is stale. Data-changing commands run a full backup sync afterward. Set BIRDCLAW_BACKUP_AUTO_SYNC=0 to disable backup auto-sync for one process.

local bird command

Live local likes, bookmarks, DMs, and moderation verification use bird on PATH by default. Override it with BIRDCLAW_BIRD_COMMAND or:

{
	"mentions": {
		"birdCommand": "/absolute/path/to/bird"
	}
}

On Windows, Birdclaw runs the redirect wrapper through Git Bash. Common Git for Windows installations are detected automatically; set BIRDCLAW_BASH_COMMAND to the full path of bash.exe for a portable or non-standard installation.

backup import

  • validates the backup first unless --no-validate is passed
  • merge-imports by default so local-only rows are not deleted
  • --restore restores exactly from backup and deletes local portable rows first (--replace remains a deprecated alias)
  • rebuilds tweet and DM FTS from the JSONL text
birdclaw backup import ~/Projects/birdclaw-store --json

backup validate

  • checks manifest.json
  • checks every listed shard hash, byte count, row count, and JSONL parseability
  • exits non-zero on validation failure
birdclaw backup validate ~/Projects/birdclaw-store --json

import archive [path]

  • validate archive
  • analyze contents
  • merge selected slices without deleting destination-only rows
  • retain explicit deleted-tweet records as source-attributed tombstones; absence alone is never a deletion
  • use --restore for deliberate exact replacement of the imported slices
  • stream bundled media files from data/tweets_media/, data/direct_messages_media/, data/community_tweet_media/, data/deleted_tweets_media/, data/profile_media/, data/moments_tweets_media/, and data/direct_messages_group_media/ into ~/.birdclaw/media/originals/archive/<kind>/<id>/<filename>
  • extract extended_entities.media[].video_info.variants[] onto each tweet media row for archive video and animated GIFs
  • parse data/follower.js and data/following.js into the local follow graph
  • idempotent
  • path is optional; without one, macOS archive autodiscovery picks the newest likely ZIP

Flags:

  • --select <kinds> — comma-separated subset of tweets,likes,bookmarks,profiles,directMessages,followers,following

--select details:

  • selected re-imports preserve unselected slices
  • valid aliases for directMessages: directmessages, direct-messages, dms
  • duplicate names are ignored
  • empty values and unknown names exit as invalid usage
  • merge imports and selected restores validate that existing acct_primary matches the archive account before writing; only a full --restore may replace it
  • selected imports preserve compatible existing profile rows unless profiles is selected

Examples:

birdclaw import archive --json
birdclaw import archive ~/Downloads/twitter-archive.zip --json
birdclaw import archive ~/Downloads/twitter-archive.zip --select tweets --json
birdclaw import archive ~/Downloads/twitter-archive.zip --select likes,bookmarks --json
birdclaw import archive ~/Downloads/twitter-archive.zip --select dms --json
birdclaw import archive ~/Downloads/twitter-archive.zip --select followers,following --json

sync *

  • fetch deltas
  • update canonical tables
  • refresh cursors
  • refresh FTS incrementally
  • sync likes and sync bookmarks use cached live transport; auto tries xurl, then bird; --early-stop caps at 10 pages unless paired with --all or --max-pages
  • sync authored uses xurl, includes retweets, and resumes from a stored since_id
  • sync timeline stores the live home timeline through bird; it defaults to the chronological Following feed
  • sync mentions ingests recent mentions through xurl (default) or bird and writes kind='mention' rows into the canonical store; this is the cron-friendly ingest path that replaces relying on mentions export --refresh
  • sync mention-threads fetches conversation context for recent mentions through bird thread or xurl; pass --mode xurl when the bird CLI is unavailable, otherwise use --delay-ms and --timeout-ms to stay gentle on live X
  • sync followers and sync following default to dry-run and require --yes for live sync or fresh-cache merge; auto prefers bird, then falls back to xurl
  • sync lists is an explicit read-only walk; it defaults to 20 members, one page, and 1,000 ms pacing per List, and stores complete|inferred|partial|error membership state

Common flags:

  • --since <cursor-or-id>
  • --limit <n>
  • --transport <kind>
  • --dry-run
  • --mode auto|xurl|bird
  • --all
  • --max-pages <n>
  • --early-stop (on sync likes and sync bookmarks)
  • --refresh
  • --cache-ttl <seconds>

Examples:

birdclaw sync authored --mode xurl --limit 100 --json
birdclaw sync likes --mode auto --limit 100 --refresh --json
birdclaw sync likes --mode auto --limit 100 --max-pages 5 --early-stop --refresh --json
birdclaw sync bookmarks --mode auto --limit 100 --refresh --json
birdclaw sync bookmarks --mode auto --limit 100 --max-pages 5 --early-stop --refresh --json
birdclaw sync bookmarks --mode bird --all --max-pages 5 --limit 100 --refresh --json
birdclaw sync timeline --limit 100 --refresh --json
birdclaw sync mentions --mode xurl --limit 100 --max-pages 3 --refresh --json
birdclaw sync mention-threads --mode bird --limit 30 --delay-ms 1500 --timeout-ms 15000 --json
birdclaw sync mention-threads --mode xurl --limit 30 --json
birdclaw sync lists --mode auto --max-lists 20 --member-limit 20 --max-member-pages 1 --delay-ms 1000 --json

Follow graph examples:

birdclaw sync followers --json
birdclaw sync following --json
birdclaw sync followers --yes --json
birdclaw sync following --yes --json
birdclaw sync followers --mode bird --yes --json
birdclaw sync followers --yes --max-pages 1 --allow-partial --json
birdclaw sync followers --yes --refresh --json

Follow graph sync uses a 24-hour cache by default. Repeating the same sync command with --yes reuses fresh cache unless --refresh is passed, which prevents duplicate live reads during agent workflows.

--allow-partial acknowledges capped/incomplete snapshots and suppresses the warning. Incomplete snapshots are still recorded for audit, but they are not used for churn events.

jobs sync-account

  • refreshes home timeline, mentions, mention threads, likes, bookmarks, and DMs for one account
  • appends one JSONL audit entry per run to ~/.birdclaw/audit/account-sync.jsonl
  • records each step independently with count, source, and error
  • uses ~/.birdclaw/locks/account-sync.lock to skip overlapping runs
  • requires --allow-bird-account before Bird-backed steps write to a non-default --account
  • exits non-zero when any step failed

Examples:

birdclaw --json jobs sync-account --account acct_openclaw --limit 100 --max-pages 3 --refresh --allow-bird-account
tail -n 20 ~/.birdclaw/audit/account-sync.jsonl | jq .

jobs install-account-launchd

  • writes ~/Library/LaunchAgents/com.steipete.birdclaw.account-sync.plist
  • runs jobs sync-account every 30 minutes by default
  • uses launchctl load -w unless --no-load is passed
  • --steps <steps> narrows the scheduled surfaces
  • --env-path <path> sources account-specific bird cookies for launchd
  • --allow-bird-account asserts those cookies match --account for Bird-backed timeline, mentions, and DM steps
birdclaw --json jobs install-account-launchd --account acct_openclaw --program /opt/homebrew/bin/birdclaw --env-path ~/.config/bird/openclaw.env --allow-bird-account

jobs sync-bookmarks

  • runs a live bookmark refresh with scheduler-friendly defaults
  • appends one JSONL audit entry per run
  • records host, timestamps, duration, before/after bookmark counts, transport source, fetched count, backup sync result, and errors
  • uses ~/.birdclaw/locks/bookmarks-sync.lock to skip overlapping runs
  • exits non-zero when the sync failed

Default audit log:

~/.birdclaw/audit/bookmarks-sync.jsonl

Examples:

birdclaw --json jobs sync-bookmarks --mode auto --limit 100 --max-pages 5 --refresh
tail -n 20 ~/.birdclaw/audit/bookmarks-sync.jsonl | jq .

jobs install-bookmarks-launchd

  • writes ~/Library/LaunchAgents/com.steipete.birdclaw.bookmarks-sync.plist
  • runs jobs sync-bookmarks every 3 hours by default
  • uses launchctl load -w unless --no-load is passed
  • writes launchd stdout/stderr to ~/.birdclaw/logs/bookmarks-sync.*.log
  • --env-path <path> sources an export-only shell env file inside the scheduled process, useful when bird needs AUTH_TOKEN/CT0 outside an interactive browser session
birdclaw --json jobs install-bookmarks-launchd --program /opt/homebrew/bin/birdclaw

search tweets <query>

Flags:

  • --author <handle-or-id>
  • --account <accountId>
  • --list <name>
  • --list-id <id>
  • --since <date>
  • --until <date>
  • --originals-only
  • --hide-low-quality
  • --liked
  • --bookmarked
  • --fxtwitter (explicit public-service opt-in)
  • --max-pages <n> (FxTwitter only, maximum 10)
  • --feed latest|top|media (FxTwitter only)
  • --limit <n>

Examples:

birdclaw search tweets --liked --limit 20 --json
birdclaw search tweets --bookmarked --limit 20 --json
birdclaw search tweets "sqlite" --list Builders --limit 50 --json
birdclaw search tweets "local-first" --fxtwitter --limit 50 --max-pages 3 --json

search dms <query>

Flags:

  • --participant <handle-or-id>
  • --min-followers <n>
  • --max-followers <n>
  • --min-influence-score <n>
  • --max-influence-score <n>
  • --sort recent|followers
  • --context <n>
  • --resolve-profiles
  • --expand-urls
  • --refresh-profile-cache
  • --refresh-url-cache
  • --no-xurl-fallback
  • --replied
  • --unreplied
  • --limit <n>

Profile resolution reads the local profile row first, then the persistent lookup cache, then bird user, then xurl unless --no-xurl-fallback is set. Failed lookups are cached briefly so repeated searches do not keep spending live calls. Resolved profile rows store bio, profile URL, location, verification type, structured X URL entities, raw profile JSON, and affiliation badge metadata when the live transport exposes it.

discuss <query>

Fetch live keyword matches through bird or xurl, store them as local search tweets, then stream an OpenAI Markdown summary and discussion. DMs stay out unless explicitly requested.

Flags:

  • --account <account-id>
  • --source all|search|home|mentions|authored|likes|bookmarks
  • --mode auto|bird|xurl|local
  • --include-dms
  • --since <date> / --until <date>
  • --question <prompt>
  • --originals-only
  • --hide-low-quality

Lines 1–500 of 907.