CLI client for the X API v2. Pay-per-use, no cookie scraping. Built on the official @xdevplatform/xdk SDK with OAuth 2.0 PKCE.
git clone https://github.com/jalehman/xc.git
cd xc
pnpm install
pnpm build
# Run directly without building:
pnpm dev -- <command>xc uses OAuth 2.0 with PKCE — you need a Client ID from the X Developer Portal.
- Go to developer.x.com (existing apps) or console.x.com (new projects)
- Create or select an app
- Under OAuth 2.0 settings, copy your Client ID (and optionally your Client Secret for confidential clients)
- Set the Callback URL to
http://127.0.0.1:3391/callback - Enable the required scopes (xc requests all of these automatically):
tweet.read,tweet.write— read/write postsusers.read— look up usersfollows.read,follows.write— manage followslike.read,like.write— manage likeslist.read,list.write— manage listsbookmark.read,bookmark.write— manage bookmarksdm.read,dm.write— read/send DMsmedia.write— upload mediaoffline.access— refresh tokens
# Interactive OAuth login (opens browser)
xc auth login --client-id <YOUR_CLIENT_ID>
# With client secret (for confidential apps — enables token refresh)
xc auth login --client-id <YOUR_CLIENT_ID> --client-secret <YOUR_SECRET>
# App-only Bearer token (read-only, no user context)
xc auth token <BEARER_TOKEN>
# Check auth status
xc auth status
# Logout
xc auth logout# Login with a named account
xc auth login --account work --client-id <CLIENT_ID>
# Switch default account
xc auth switch work
# Use a specific account for one command
xc search "query" --account workCredentials are stored in ~/.xc/config.json (or $XC_CONFIG_DIR/config.json). Legacy ~/.config/xc/ configs are auto-migrated.
xc whoami # Show authenticated user
xc whoami --json # JSON outputxc search "typescript" # Search recent posts (last 7 days)
xc search "from:elonmusk" --limit 20
xc search "AI" --archive # Full archive search (if your plan supports it)
xc search "query" --json # Raw JSON outputxc user elonmusk # Look up a user by @username
xc user jlehman_ --jsonxc timeline # Your home timeline
xc timeline --limit 20
xc timeline elonmusk # A specific user's posts
xc timeline elonmusk --jsonxc post "Hello world" # Create a post
xc post "Reply" --reply 123456 # Reply to a post
xc post "Check this" --quote 123 # Quote a post
xc post "First" --thread "Second" "Third" # Post a thread
xc post "Photo" --media photo.jpg # Post with media attachment
xc post "text" --json # Show raw response
xc delete 1234567890 # Delete a postxc like 1234567890 # Like a post by ID
xc unlike 1234567890 # Unlike a postxc bookmarks # List your bookmarks
xc bookmark 1234567890 # Bookmark a post
xc unbookmark 1234567890 # Remove bookmarkxc lists # List your owned lists
xc list 1234567890 # View posts in a listxc followers elonmusk # List followers of a user
xc followers elonmusk --limit 50
xc following elonmusk # List who a user follows
xc follow elonmusk # Follow a user
xc unfollow elonmusk # Unfollow a userxc dm list # List recent DM conversations
xc dm history username # View DM history with a user
xc dm send username "Hello" # Send a DMxc media upload photo.jpg # Upload media, returns media_id
# Then use with post:
xc post "Check this out" --media photo.jpgxc stream rules # List current stream rules
xc stream add "AI OR LLM" # Add a filtered stream rule
xc stream remove <rule-id> # Remove a rule by ID
xc stream clear # Remove all rules
xc stream connect # Connect to stream (outputs posts in real-time)
xc stream connect --json # Raw JSON stream outputEvery API call is logged to ~/.config/xc/usage.jsonl with timestamp, endpoint, method, and estimated cost. A cost footer is appended to every command's output.
xc cost # Cost summary (1h, 24h, 7d, 30d)
xc cost --daily # Day-by-day breakdown
xc cost --json # Machine-readable summary
xc cost log # Raw request log (last 20)
xc cost log --limit 50 # More entries
xc cost log --json # Raw JSON logSuppress the per-command cost footer with --quiet:
xc search "query" --quietxc usage # X API usage stats (tweet caps, etc.)
xc usage --jsonSet daily spending limits to avoid surprise costs. Budget config lives in ~/.config/xc/budget.json.
xc budget set --daily 2.00 # Warn when over $2/day
xc budget set --daily 5.00 --action block # Block requests over $5/day
xc budget set --daily 1.00 --action confirm # Ask for confirmation when overActions:
warn(default) — print a warning but allow the requestblock— reject the request with an errorconfirm— prompt interactively before proceeding
xc budget show
# Budget:
#
# Daily limit: $2.00
# Today spent: $0.45 (22%)
# Remaining: $1.55
# Action: warn
# Locked: noLock your budget so it can't be changed without a password:
xc budget lock --password mysecret
# Now set/reset require --password
xc budget set --daily 10.00 --password mysecret
xc budget reset --password mysecret
# Remove the lock
xc budget unlock --password mysecretshow and cost never require a password — only set and reset do.
xc budget reset # Remove budget config
xc budget reset --password pass # If lockedAll configuration is stored in ~/.xc/ (or $XC_CONFIG_DIR):
| File | Contents |
|---|---|
config.json |
Auth credentials (OAuth tokens, accounts) |
budget.json |
Budget limits and password lock |
usage.jsonl |
API request cost log (append-only) |
Legacy ~/.config/xc/ configs are auto-migrated on first run.
pnpm dev -- <command> # Run without building
pnpm build # Compile TypeScript
pnpm lint # Type check
pnpm test # Run tests (vitest)| Flag | Description |
|---|---|
--quiet |
Suppress cost footer |
--json |
Raw JSON output (most commands) |
--account <name> |
Use a specific named account |
-V, --version |
Show version |
-h, --help |
Show help |
MIT