Skip to main content
twitter-cli loads configuration from config.yaml with automatic fallback to sensible defaults.

Config File Location

The CLI searches for config.yaml in this order:
  1. Current working directory: ./config.yaml
  2. Package root: twitter_cli/../config.yaml
Source: twitter_cli/config.py:69-83
You can specify a custom config path with --config /path/to/config.yaml (if supported by your command).

Default Configuration

If no config.yaml is found, the CLI uses these defaults:
DEFAULT_CONFIG = {
    "fetch": {
        "count": 50,
    },
    "filter": {
        "mode": "topN",
        "topN": 20,
        "minScore": 50,
        "lang": [],
        "excludeRetweets": False,
        "weights": {
            "likes": 1.0,
            "retweets": 3.0,
            "replies": 2.0,
            "bookmarks": 5.0,
            "views_log": 0.5,
        },
    },
    "rateLimit": {
        "requestDelay": 2.5,
        "maxRetries": 3,
        "retryBaseDelay": 5.0,
        "maxCount": 200,
    },
}
Source: twitter_cli/config.py:14-38

Configuration Schema

fetch Section

Controls how many items to retrieve per request:
fetch:
  count: 50  # Number of tweets per fetch (min: 1)
FieldTypeDefaultDescription
countint50Tweets fetched per paginated request
Source: twitter_cli/config.py:104-109

filter Section

Configures tweet filtering and engagement scoring:
filter:
  mode: "topN"              # "topN" | "score" | "all"
  topN: 20                   # Top N tweets to keep (when mode=topN)
  minScore: 50               # Minimum score threshold (when mode=score)
  lang: []                   # Language filter (empty = all languages)
  excludeRetweets: false     # Whether to exclude retweets
  weights:                   # Engagement scoring weights
    likes: 1.0
    retweets: 3.0
    replies: 2.0
    bookmarks: 5.0
    views_log: 0.5
FieldTypeDefaultDescription
modestring"topN"Filter mode: "topN", "score", or "all"
topNint20Number of top tweets to keep (min: 1)
minScorefloat50.0Minimum engagement score threshold
langlist[str][]Language codes (e.g., ["en", "ja"]). Empty = no filter
excludeRetweetsboolfalseExclude retweets from results
weightsdictSee belowEngagement scoring weights
Source: twitter_cli/config.py:111-135

Filter Modes

  • topN: Sort by score and return top N tweets
  • score: Return all tweets with score >= minScore
  • all: Return all tweets, sorted by score
See Filtering for detailed scoring algorithm.

rateLimit Section

Controls request timing and retry behavior:
rateLimit:
  requestDelay: 2.5         # Base delay between requests (seconds)
  maxRetries: 3             # Retry attempts on rate limit (429)
  retryBaseDelay: 5.0       # Base delay for exponential backoff (seconds)
  maxCount: 200             # Hard cap on fetched items
FieldTypeDefaultDescription
requestDelayfloat2.5Seconds between requests (randomized ×0.7–1.5)
maxRetriesint3Retry count for 429 errors (min: 0)
retryBaseDelayfloat5.0Base delay for exponential backoff (min: 1.0)
maxCountint200Maximum items per fetch operation (min: 1)
Source: twitter_cli/config.py:137-146
Lower requestDelay increases ban risk. Values below 1.0 are not recommended.

Example Configurations

Aggressive Filtering

Keep only high-engagement English tweets:
fetch:
  count: 100

filter:
  mode: "score"
  minScore: 100
  lang: ["en"]
  excludeRetweets: true
  weights:
    likes: 1.0
    retweets: 5.0
    replies: 3.0
    bookmarks: 10.0
    views_log: 0.2

rateLimit:
  requestDelay: 3.0
  maxRetries: 5
  maxCount: 500

Conservative (Low Ban Risk)

Slow, safe requests with minimal filtering:
fetch:
  count: 20

filter:
  mode: "all"
  excludeRetweets: false

rateLimit:
  requestDelay: 5.0
  maxRetries: 2
  retryBaseDelay: 10.0
  maxCount: 50

Language-Specific Feed

Japanese tweets only, top 30 by engagement:
filter:
  mode: "topN"
  topN: 30
  lang: ["ja"]
  weights:
    likes: 2.0
    retweets: 4.0
    replies: 1.0
    bookmarks: 8.0
    views_log: 0.3

Configuration Loading

The CLI merges your config.yaml with defaults using deep merge:
def load_config(config_path=None) -> Dict[str, Any]:
    """Load and normalize config from YAML, merged with defaults."""
    config = copy.deepcopy(DEFAULT_CONFIG)
    path = _resolve_config_path(config_path)
    if not path:
        return config

    # Parse YAML
    raw = path.read_text(encoding="utf-8")
    parsed = yaml.safe_load(raw) or {}

    # Deep merge and normalize
    merged = _deep_merge(config, parsed)
    return _normalize_config(merged)
Source: twitter_cli/config.py:41-66

Normalization Rules

The CLI normalizes config values to prevent errors:
  • fetch.count: Coerced to int, minimum 1
  • filter.mode: Must be "topN", "score", or "all" (defaults to "topN")
  • filter.topN: Coerced to int, minimum 1
  • filter.minScore: Coerced to float
  • filter.lang: Coerced to list[str]
  • filter.weights.*: Coerced to float
  • rateLimit.requestDelay: Coerced to float, minimum 0.0
  • rateLimit.maxRetries: Coerced to int, minimum 0
  • rateLimit.retryBaseDelay: Coerced to float, minimum 1.0
  • rateLimit.maxCount: Coerced to int, minimum 1
Source: twitter_cli/config.py:98-148
Invalid values are coerced to defaults rather than causing errors. Check logs for warnings.

Validation

1

Create config.yaml

Create a test configuration:
fetch:
  count: 30
filter:
  mode: "topN"
  topN: 10
2

Test with dry run

Validate by running a command:
twitter feed --max 10 --json
3

Check logs

Look for config warnings in output:
Loaded config from: /path/to/config.yaml

Troubleshooting

Config not loading

Cause: config.yaml in wrong directory or has syntax errors. Solution:
  • Place config.yaml in working directory
  • Validate YAML syntax: yamllint config.yaml
  • Check file permissions: ls -la config.yaml

Filter not applying

Cause: Filter only applies when --filter flag is passed. Solution:
twitter feed --filter  # Enable filtering

Unexpected values

Cause: Config normalization coerced invalid values to defaults. Solution:
  • Check logs for warnings
  • Verify types match schema
  • Use quoted strings for string values

Next Steps

Filtering

Learn about the engagement scoring algorithm

Authentication

Set up cookies and environment variables

Build docs developers (and LLMs) love