Reference

CLI Spec

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
  • --plain
  • -q, --quiet
  • -v, --verbose
  • --no-color
  • --no-input
  • --config <path>
  • --profile <name>
  • --db <path>

#Config precedence

Flags > env > project config > user config

User config:

  • ~/.birdclaw/config.json

Project config:

  • ./.birdclawrc.json5

#Env vars

  • BIRDCLAW_DB
  • BIRDCLAW_PROFILE
  • BIRDCLAW_TRANSPORT
  • BIRDCLAW_LOG
  • NO_COLOR

#Command tree

birdclaw init
birdclaw auth status
birdclaw auth use <transport>
birdclaw import archive <path>
birdclaw sync all
birdclaw sync tweets
birdclaw sync dms
birdclaw sync bookmarks
birdclaw sync likes
birdclaw sync timeline
birdclaw sync mention-threads
birdclaw sync followers
birdclaw sync following
birdclaw search tweets <query>
birdclaw search dms <query>
birdclaw mentions export [query]
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 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

#init

  • create app dir
  • create DB
  • write default config if absent
  • optionally detect xurl and bird

#auth status

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

#auth use <transport>

  • set preferred transport for profile
  • allowed: auto, xurl, bird, official, xweb

#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
3 backup 4 0 ~/Projects/5-store 1 2

#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
3 backup sync 0 ~/Projects/backup-4 1 https://github.com/steipete/backup-5.6 2

Shard contract:

  • tweets: data/tweets/YYYY.jsonl
  • unknown tweet dates: data/tweets/unknown.jsonl
  • profiles: data/profiles.jsonl includes bio plus follower/following counts
  • 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:

{
	0 {
		1 5,
		2 6,
		3 7,
		4 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.

#backup import

  • validates the backup first unless --no-validate is passed
  • merge-imports by default so local-only rows are not deleted
  • --replace restores exactly from backup and deletes local portable rows first
  • rebuilds tweet and DM FTS from the JSONL text
1 backup import ~/Projects/2-store 0

#backup validate

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

#import archive <path>

  • validate archive
  • analyze contents
  • import selected slices
  • idempotent

Flags:

  • --select <kinds>
  • --dm-mode metadata|full
  • --dry-run
  • --force

Default:

  • DMs import in full mode

#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
  • sync timeline stores the live home timeline through bird; it defaults to the chronological Following feed
  • sync mention-threads fetches conversation context for recent mentions through bird thread; use --delay-ms and --timeout-ms to stay gentle on live X

Common flags:

  • --since <cursor-or-id>
  • --limit <n>
  • --transport <kind>
  • --dry-run
  • --mode auto|xurl|bird
  • --all
  • --max-pages <n>
  • --refresh
  • --cache-ttl <seconds>

Examples:

4 sync likes 0 auto 1 100 2 3
4 sync bookmarks 0 auto 1 100 2 3
6 sync bookmarks 0 7 1 2 5 3 100 4 5
3 sync timeline 0 100 1 2
4 sync mention-threads 0 30 1 1500 2 15000 3

#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:

5 0 jobs sync-bookmarks 1 auto 2 100 3 5 4
1 0 20 ~/.2/audit/bookmarks-sync.jsonl | 3 .

#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-file <path> sources an export-only shell env file inside the scheduled process, useful when bird needs AUTH_TOKEN/CT0 outside an interactive browser session
2 0 jobs install-bookmarks-launchd 1 /opt/homebrew/bin/3

#search tweets <query>

Flags:

  • --author <handle-or-id>
  • --since <date>
  • --until <date>
  • --originals-only
  • --hide-low-quality
  • --liked
  • --bookmarked
  • --limit <n>

Examples:

3 search tweets 0 1 20 2
3 search tweets 0 1 20 2

#search dms <query>

Flags:

  • --conversation <id>
  • --participant <handle-or-id>
  • --min-followers <n>
  • --max-followers <n>
  • --min-influence-score <n>
  • --max-influence-score <n>
  • --sort recent|influence
  • --replied
  • --unreplied
  • --since <date>
  • --until <date>
  • --limit <n>

#mentions export [query]

  • export local mention tweets for scripts and agents
  • always emits JSON
  • supports birdclaw, cached xurl, or cached bird output
  • each item includes:
  • raw text
  • rendered plainText
  • rendered markdown
  • canonical tweet URL
  • author and reply-state metadata

Flags:

  • --account <account-id>
  • --mode birdclaw|xurl|bird
  • --replied
  • --unreplied
  • --refresh
  • --cache-ttl <seconds>
  • --all
  • --max-pages <n>
  • --limit <n>

Examples:

3 mentions 4 0 1 2 10
2 mentions 3 0 4 1 20
2 mentions 3 0 4 1 5
3 mentions 4 0 1 5 2 5
4 mentions 5 0 6 1 2 30 3 5
5 mentions 6 0 7 1 2 3 9 4 100

Notes:

  • --mode xurl mirrors the xurl mentions response shape: data, includes.users, meta
  • --mode bird shells out to your local bird CLI, normalizes the JSON to that same xurl-compatible shape, then caches it in SQLite
  • payload is cached in local SQLite and reused until the cache TTL expires
  • --refresh bypasses the cache and fetches live mentions immediately
  • --all keeps paginating until the retrievable mentions window is exhausted
  • --max-pages limits that paged xurl scan and implies --all
  • in paged xurl mode, --limit is the page size, not the total returned item count
  • query and reply-state filters still work in xurl mode, but the filtered response is rebuilt from the local canonical store after sync
  • default live source can live in ~/.birdclaw/config.json under mentions.dataSource

#profiles replies <handle-or-id>

  • inspect a profile's recent authored replies when one mention feels borderline
  • moderation-first: scans the live authored tweet timeline, excludes retweets, keeps reply tweets only
  • good for spotting templated AI cadence across unrelated conversations
  • supports --json

Flags:

  • --limit <n>

Examples:

2 profiles replies @jpctan 0 12 1

#dms list

  • list DM conversations or events without requiring a full-text query
  • optimized for agent and operator filtering
  • optionally refreshes live DMs through bird before listing

Flags:

  • --refresh
  • --cache-ttl <seconds>
  • --participant <handle-or-id>
  • --min-followers <n>
  • --max-followers <n>
  • --min-influence-score <n>
  • --max-influence-score <n>
  • --sort recent|influence
  • --replied
  • --unreplied
  • --account <name>
  • --limit <n>

#dms sync

  • refresh live direct messages through bird
  • merge conversations/messages into the local SQLite store
  • supports --json

Flags:

  • --account <account-id>
  • --limit <n>
  • --refresh
  • --cache-ttl <seconds>

#inbox

  • show AI-ranked actionable queue
  • supports --json
  • supports --limit
  • supports --kind mentions|dms|mixed
  • supports replied/unreplied filters
  • supports --score to refresh stored OpenAI scores before listing
  • supports --min-score and --hide-low-signal

#blocks list

  • list current local blocked profiles
  • account-scoped
  • supports --json

Flags:

  • --account <account-id>
  • --search <query>
  • --limit <n>

#blocks add <handle-or-id>

  • add a local block entry for one account
  • accepts handle, @handle, Twitter URL, local profile id, or numeric Twitter user id
  • attempts live block transport via xurl when resolvable
  • falls back to the Twitter web cookie session if xurl is rejected for OAuth2 block writes
  • still records the local block if live transport is unavailable

Flags:

  • --account <account-id>

#blocks import <path>

  • import a blocklist file in one call
  • reads newline-delimited handles, ids, or Twitter URLs
  • ignores blank lines and # comments
  • tolerates markdown bullets like - @handle
  • returns per-entry success/failure in --json

Flags:

  • --account <account-id>

#blocks remove <handle-or-id>

  • remove a local block entry for one account
  • attempts live unblock transport via xurl when resolvable
  • falls back to the Twitter web cookie session if xurl is rejected for OAuth2 block writes

Flags:

  • --account <account-id>

#ban <handle-or-id> / unban <handle-or-id>

  • shorthand aliases for blocks add and blocks remove
  • useful when you want one obvious moderation verb from the CLI

Flags:

  • --account <account-id>

#mutes list

  • list current local muted profiles
  • account-scoped
  • supports --json

Flags:

  • --account <account-id>
  • --search <query>
  • --limit <n>

#mute <handle-or-id>

  • add a local mute entry for one account
  • accepts handle, @handle, Twitter URL, local profile id, or numeric Twitter user id
  • resolves remote targets via bird user --json before falling back to xurl /2/users
  • --transport auto tries bird first, then xurl
  • still records the local mute if live transport is unavailable

Flags:

  • --account <account-id>

#unmute <handle-or-id>

  • remove a local mute entry for one account
  • --transport auto tries bird first, then xurl

Flags:

  • --account <account-id>

#serve

  • starts local app server
  • starts background sync automatically by default
  • stdout prints URL in plain mode

Flags:

  • --host <host>
  • --port <port>
  • --open
  • --no-open
  • --sync
  • --no-sync

#graph summary

  • current graph counts
  • inbound/outbound
  • mutuals
  • recent churn

#graph events

  • append-only follow/unfollow history
  • supports date window filters
  • supports --json

#graph mutuals

  • current mutuals
  • sortable by recency / follower size / interaction hints later

#I/O contract

stdout:

  • primary data
  • URLs
  • JSON output

stderr:

  • progress
  • warnings
  • diagnostics
  • auth hints

#Output modes

  • default human output
  • --json stable machine-readable envelopes
  • --plain stable line-oriented text, no color

#Exit codes

  • 0 success
  • 1 runtime failure
  • 2 invalid usage / validation
  • 3 auth unavailable
  • 4 transport unavailable
  • 5 partial sync failure

#Examples

0 init
0 auth status
1 import archive ~/Downloads/twitter-archive.zip 0 tweets,directMessages
1 sync all 0 2
3 search tweets 0 1 2024-01-01 2 20
5 search tweets 0 2020-01-01 1 2021-01-01 2 3 4 500
3 search dms 0 1 @someone 2 1000
4 dms list 0 1 500 2 90 3 influence
1 inbox 0
1 serve 0
1 graph events 0
0 compose reply 1891234567890