Commit Graph
31 Commits
Author SHA1 Message Date
Peter Steinberger a782ca5d3a fix: search pagination output (#42) (thanks @pjtf93) 2026-01-12 06:30:20 +00:00
Pablo Tovar e23c20a6a2 feat: add pagination support to search command
Adds --all, --max-pages, and --cursor options to search command, enabling users to fetch all search results through automatic pagination. Follows the same pattern as bookmarks pagination for consistency.
2026-01-12 06:29:27 +00:00
Peter Steinberger c96ce5238f fix: tighten news output and parsing (#39) (thanks @aavetis) 2026-01-12 05:37:44 +00:00
aavetisandClaude Sonnet 4.5 fb092f5cec feat: add multi-tab fetching to news command for 5x more headlines
Completely rewrites the news command to fetch from multiple Explore tabs
(For You, News, Sports, Entertainment) using GenericTimelineById GraphQL
API instead of just the ExplorePage initialTimeline. This delivers 15+
AI-curated headlines instead of 3, a 5x improvement in content discovery.

Key Changes:
- Add GenericTimelineById query ID support with auto-refresh capability
- Implement multi-tab fetching with cross-tab headline deduplication
- Add CLI flags for granular tab filtering (--for-you, --news-only,
  --sports, --entertainment, --trending-only)
- Fetch from 4 tabs by default (excludes trending to reduce noise)
- Add early stopping optimization when count is reached
- Handle tab-level errors gracefully without failing entire request

Implementation:
- Added TIMELINE_IDS constant with base64 timeline identifiers
- Created fetchTimelineTab() method for GenericTimelineById requests
- Created parseTimelineTabItems() for new response structure
- Removed old parseNewsItems() and extractNewsItemsFromInstructions()
- Updated all 7 tests to mock GenericTimelineById responses

API Changes:
- NewsFetchOptions: Added `tabs?: ExploreTab[]` option
- ExploreTab type exported for library consumers
- Backward compatible - existing code continues to work

Documentation:
- Added comprehensive "News & Trending" section with examples
- Updated command reference with all new flags
- Added library usage examples with tab filtering
- Updated JSON schema documentation

Testing:
- All 268 tests passing
- Real-world verified: fetches 15+ AI headlines across tabs
- Tab filtering verified: --sports, --entertainment, etc all work

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
2026-01-12 05:33:19 +00:00
aavetisandClaude Sonnet 4.5 57d1498f1d feat: add news command to fetch AI-curated headlines
Add comprehensive news/trending feature that fetches AI-generated news
headlines from Twitter's "For You" page. This feature specifically
targets the AI-curated news items that Twitter displays under "Today's
News" section, not generic trending hashtags.

- Uses Twitter's ExplorePage GraphQL API endpoint to access the Explore
  page timeline data where AI headlines are located
- AI headlines are identified by the explicit `is_ai_trend: true` flag
  in the API response
- Fallback heuristic detection for full-sentence headlines (5+ words)
  with "News" or time indicators in social context
- Headlines are found in "stories-*" modules within the initialTimeline
  structure under a "Today's News" header
- Follows the existing mixin pattern (withNews) for composability
- Supports both AI-only filtering and mixed trending/AI results

- `bird news` - Fetch news and trending topics (mixed results)
- `bird news --ai-only` - Fetch ONLY AI-curated headlines
- `bird news -n <count>` - Limit number of results
- `bird news --json` - Output as JSON
- `bird news --json-full` - Include raw API response
- `bird news --with-tweets` - Enrich with related tweets
- `bird trending` - Alias for news command
- AI headlines are clearly marked with "AI · " category prefix
- Automatic deduplication of duplicate headlines
- Rich formatting with category, time, post count, and URLs

- src/commands/news.ts - CLI command implementation
- src/lib/twitter-client-news.ts - Core news fetching functionality
- tests/commands.news.test.ts - Command validation tests (7 tests)
- tests/twitter-client-coverage.news.test.ts - API coverage tests (7 tests)

- README.md - Added documentation for news command
- src/cli/program.ts - Registered news command
- src/lib/index.ts - Exported news-related types
- src/lib/twitter-client.ts - Integrated withNews mixin
- src/lib/query-ids.json - Added ExplorePage query ID
- src/lib/twitter-client-constants.ts - Added ExplorePage constant
- src/lib/twitter-client-features.ts - Added buildExploreFeatures()
- scripts/update-query-ids.ts - Added ExplorePage to update script

- All 268 existing tests continue to pass
- Added 14 new tests covering command validation and API functionality
- Tested with real Twitter data confirming AI headline detection
- All TypeScript compilation and linting checks pass

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
2026-01-12 05:32:06 +00:00
Peter Steinberger d5a527d5fb refactor: unify pagination helpers 2026-01-12 02:58:00 +00:00
Peter Steinberger 16f21800b5 refactor: align replies/thread pagination (#35) (thanks @crcatala) 2026-01-12 02:41:08 +00:00
cc-vpsandChristian Catalan 90037ce880 feat: add pagination support for thread and replies commands
Add --all, --max-pages, --delay, and --cursor options to both thread
and replies commands, enabling fetching of all conversation content
with rate-limit-friendly pagination.

Changes:
- Modified fetchTweetDetail() to accept optional cursor parameter
- Added getRepliesPaged() and getThreadPaged() methods with pagination loop
- Updated CLI commands with new options (--all, --max-pages, --delay, --cursor)
- Added TweetDetailPaginationOptions interface
- JSON output includes nextCursor for scripting/resumption

Options:
- --all: Fetch all pages (no hard limit)
- --max-pages <n>: Limit number of pages when using --all
- --delay <ms>: Delay between page fetches (default: 1000ms)
- --cursor <string>: Resume from a previous cursor

Follows patterns established by bookmarks command and PR #34 (user-tweets).

Co-authored-by: Christian Catalan <[email protected]>
2026-01-12 02:35:36 +00:00
Peter Steinberger c7acdbd3fd fix: restore build:dist and gate in CI 2026-01-12 02:16:37 +00:00
Peter Steinberger 436d4dfb89 refactor: centralize paged tweet printing 2026-01-12 02:09:47 +00:00
Peter Steinberger 4eac0927c1 fix: paginate user-tweets by --count 2026-01-12 01:35:00 +00:00
cc-vpsandChristian Catalan df98e827f6 feat: add user-tweets command to fetch tweets from a user's profile
Adds new CLI command to fetch tweets from any user's profile timeline.

Usage:
  bird user-tweets @username [-n count] [--pages N] [--json]

Features:
- GraphQL UserByScreenName for username → userId resolution
- Cursor-based pagination with configurable delay (rate-limit safe)
- Hard cap of 10 pages to prevent abuse
- Input validation via normalizeHandle()

Includes 17 unit tests and live smoke test.

Co-authored-by: Christian Catalan <[email protected]>
2026-01-12 01:28:04 +00:00
George Zhang cf78fce646 feat: improve text output with article preview, quote tweets, and media
Enhance the text output format to show more useful information:

- Article tweets: Show 📰 indicator with title + preview text in feeds,
  full body when reading single tweets
- Quote tweets: Display quoted content with ┌─ QT @user formatting
- Media: Show 🖼️/🎬/🔄 indicators with URLs for photos/videos/GIFs

Also refactors single tweet read to use shared printTweets function
for consistent formatting.
2026-01-11 23:35:03 +00:00
George ZhangandClaude Opus 4.5 92742cac38 refactor: rename --latest to --following for clarity
Matches Twitter's UI terminology ("For You" vs "Following" tabs),
making the flag immediately understandable to users.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
2026-01-11 11:35:57 +00:00
George Zhang ba7b00eb29 feat: add home timeline command
Add `bird home` command to fetch the authenticated user's home timeline.

- Supports "For You" feed (default) and "Following" feed (--latest)
- Uses HomeTimeline and HomeLatestTimeline GraphQL operations
- Includes count option (-n), JSON output, and pagination

Usage:
  bird home           # Get "For You" feed
  bird home --latest  # Get "Following" (chronological) feed
  bird home -n 50     # Fetch 50 tweets
2026-01-11 11:35:57 +00:00
Peter Steinberger 6cf177f92f fix: list timeline pagination (#30) (thanks @zheli) 2026-01-11 11:27:46 +00:00
Zhe LiandClaude Sonnet 4.5 ebcd1618f9 feat: make --max-pages imply --all for list-timeline
- Remove requirement for --max-pages to be used with --all
- Update help text to clarify --max-pages implies --all
- Add list-timeline documentation to README with examples

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
2026-01-11 11:17:27 +00:00
Zhe Li 8fc208ca31 Apply suggestions from code review 2026-01-11 11:17:27 +00:00
Zhe LiandClaude Sonnet 4.5 803bd25b0c feat: add pagination support to list-timeline command
Adds --all, --max-pages, and --cursor options to list-timeline command, enabling users to fetch all tweets from a list through automatic pagination. Follows the same pattern as bookmarks pagination for consistency.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
2026-01-11 11:17:27 +00:00
Martin FunkandClaude Opus 4.5 837b09fcad feat: add clickable hyperlinks for URLs in terminal output
Use OSC 8 escape sequences to make tweet and list URLs clickable
in supported terminals (iTerm2, Ghostty, Kitty, WezTerm, VS Code, etc.).

- Add hyperlink() helper function in output.ts
- Apply hyperlinks in printTweets() for tweet URLs
- Apply hyperlinks in printLists() for list URLs
- Add hyperlinks flag to OutputConfig (auto-disabled for non-TTY)
- Automatically falls back to plain text in --plain mode or when piped

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
2026-01-11 11:10:34 +00:00
Peter Steinberger 092be1a782 fix: harden follow pagination output (#28) (thanks @malpern) 2026-01-11 11:02:09 +00:00
Micah AlpernandClaude Opus 4.5 39a477265c feat: add cursor-based pagination for following/followers commands
Add pagination support to `bird following` and `bird followers` commands,
similar to existing pagination in search/bookmarks/likes.

Changes:
- Add `cursor` parameter to `getFollowing()` and `getFollowers()` client methods
- Return `nextCursor` in `FollowingResult` for pagination continuation
- Add `--cursor <cursor>` CLI option for manual pagination
- Add `--all` CLI flag to automatically fetch all pages
- Add `--max-pages <number>` option to limit pages when using --all
- Add input validation for --max-pages (requires --all or --cursor)
- Add deduplication using Set to prevent duplicate users
- Add 1-second delay between pages to avoid overwhelming the API
- Update `-n/--count` description to clarify it's per-page
- Add unit tests for cursor parameter and nextCursor response

Usage examples:
  # Fetch first page (default 20 users)
  bird following

  # Fetch with specific page size
  bird following -n 50

  # Use cursor for next page
  bird following --cursor "CURSOR_FROM_PREVIOUS"

  # Fetch ALL following users automatically (with rate limiting)
  bird following --all --json

  # Limit to first 5 pages
  bird following --all --max-pages 5

  # Same options work for followers
  bird followers --all

Note: REST API fallback does not support cursor pagination.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
2026-01-11 10:59:35 +00:00
Mariano Belinky 04a0c98362 feat: add unbookmark command to remove bookmarks 2026-01-05 02:10:10 +00:00
Peter Steinberger f5402f2b43 feat: add runtime feature overrides 2026-01-05 01:23:32 +01:00
Peter Steinberger f765955116 fix: stabilize bookmark pagination cursors 2026-01-04 23:42:34 +00:00
Leon Ho 3442ba84c6 feat: add cursor-based pagination to bookmarks command
- Add --cursor option to resume pagination from a specific point
- Change --max-pages to enable pagination independently
- Return nextCursor in JSON output for subsequent requests

feat: add cursor param and nextCursor to pagination methods

not modifying max-pages
2026-01-04 23:42:34 +00:00
Harper ReedandClaude Opus 4.5 59e827e153 test(lists): improve test coverage and extract list ID parsing
- Extract extractListId to src/lib/extract-list-id.ts with proper tests
- Add json-full/includeRaw test for list timeline
- Add 404 retry tests for getOwnedLists and getListMemberships
- Add tests for skipping invalid list entries and missing owner handling
- Use shared TwitterClientPrivate type from fixtures

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
2026-01-03 16:55:29 +01:00
Harper ReedandClaude Opus 4.5 7818440d65 feat(lists): add support for Twitter Lists
Add commands to fetch owned lists, list memberships, and list timelines:
- `bird lists` shows lists you own
- `bird lists --member-of` shows lists you're a member of
- `bird list-timeline <id-or-url>` fetches tweets from a list

Includes full --json and --json-full support for list timeline output.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
2026-01-03 16:55:29 +01:00
Haoli 56ca7b9841 Add paged bookmark export with gating and retries 2026-01-03 15:51:49 +01:00
cc-vpsandChristian Catalan 3815ebfa03 feat: add --json-full flag to include raw API response in _raw field
Add a new --json-full flag to tweet-fetching commands that outputs JSON
with an additional _raw field containing the full GraphQL response.

This provides power users access to additional data not exposed in the
curated TweetData interface (media, entities, hashtags, cards, etc.)
while maintaining backward compatibility with --json.

Supported commands:
- read, replies, thread (TweetDetail API)
- search, mentions (SearchTimeline API)
- bookmarks (Bookmarks API)
- likes (Likes API)

Not supported: following, followers (uses mixed GraphQL/REST fallback
with different response structures)

Implementation:
- Add _raw?: GraphqlTweetResult optional field to TweetData type
- Add includeRaw option to mapTweetResult() and parseTweetsFromInstructions()
- Add TweetFetchOptions, SearchFetchOptions, TimelineFetchOptions interfaces
- Update client methods to accept options parameter
- Add --json-full flag to CLI commands
- Update help text to document the new flag
- Add comprehensive test coverage (16 tests)

Co-authored-by: Christian Catalan <[email protected]>
2026-01-03 06:54:36 +01:00
Peter Steinberger 51bf79d9ed refactor(cli): split commands into modules 2026-01-01 13:32:30 +01:00