A Python CLI tool to sync and manage Gmail filters from a local YAML configuration. Automatically handles Gmail's filter entry limits by splitting large filters across multiple rules.
- Simple 3-command workflow:
init,apply,clean - Smart sync: Auto-detects which direction changes need to go (Gmail → local, local → Gmail, or both)
- Part-level optimization: Only updates changed parts of split filters (saves time on large filters)
- Auto-split: Automatically creates "filter-name", "filter-name-2", etc. when entry count exceeds limits
- Dry-run support: Preview all changes before applying
pip install gmail-filter-botThen run:
gmail-filter-bot --helpUsing uv (recommended):
# Clone the repository
git clone https://github.com/btburton42/gmail-filter-bot.git
cd gmail-filter-bot
# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install the package
uv sync
# Or install with development dependencies
uv sync --extra dev
# Install the package with CLI entry points (required after uv sync)
uv pip install -e .
# Or activate the venv and run directly
source .venv/bin/activate
gmail-filter-bot --helpNote: uv sync installs dependencies but doesn't register the CLI entry points. You must run uv pip install -e . after uv sync to use the gmail-filter-bot command.
Create a .env file (gitignored):
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret
GOOGLE_REDIRECT_URI=http://localhost:8080Or use a credentials file:
# Download from Google Cloud Console
cp client_credentials.json credentials.jsonOption A: Import from Gmail (Recommended)
If you already have filters in Gmail, run init to automatically create filters.yaml from your existing filters:
gmail-filter-bot initThis will:
- Fetch all your existing Gmail filters
- Group them by action and label
- Create
filters.yamlwith everything already configured
Preview first with --dry-run:
gmail-filter-bot init --dry-runOption B: Create manually
Create filters.yaml yourself (this file is gitignored and contains your private filter data):
# Maximum entries per filter (Gmail default is ~50)
max_entries_per_filter: 50
# Filter definitions
filters:
newsletters:
action: label_and_archive
label: Newsletters
entries:
- newsletter1@example.com
- newsletter2@example.com
- updates@company.com
shopping:
action: label_only
label: Shopping
entries:
- orders@amazon.com
- receipts@target.com
social:
action: archive
entries:
- noreply@facebook.com
- notifications@twitter.comAvailable actions:
label_only: Apply label onlylabel_and_archive: Apply label and archivearchive: Archive onlydelete: Delete messagesmark_important: Mark as importantmark_not_important: Mark as not importantstar: Star messages
| Command | Description | Common Flags |
|---|---|---|
init |
Import existing Gmail filters from your account into filters.yaml. Run this first to automatically create your config from Gmail. |
--dry-run: Preview what would be imported |
plan |
Preview what changes would be applied. Shows exactly what would happen during apply without making any changes. | --push: Show push plan only--sync: Show sync plan only |
apply |
Main command - syncs changes between local config and Gmail. Auto-detects direction and applies changes immediately. | --push: Force push local → Gmail only--sync: Force sync Gmail → local only--no-apply-existing: Skip labeling existing conversations |
clean |
Optimize your configuration by removing duplicates and consolidating similar filters. | --dry-run: Preview changes |
# 1. Import existing Gmail filters (one-time setup)
# This automatically creates filters.yaml from your Gmail filters
gmail-filter-bot init
# 2. Preview what would change
gmail-filter-bot plan
# 3. Apply changes (use this daily)
gmail-filter-bot apply
# 4. Optimize configuration (remove duplicates, consolidate)
gmail-filter-bot cleanInitialize from Gmail:
# Import your existing Gmail filters
gmail-filter-bot init
# Preview first (recommended)
gmail-filter-bot init --dry-runPlan changes (preview):
# Preview what would happen without making changes
gmail-filter-bot plan
# Preview specific direction
gmail-filter-bot plan --push # Show what would be pushed
gmail-filter-bot plan --sync # Show what would be syncedApply changes:
# Auto-detect direction and sync (applies immediately)
gmail-filter-bot apply
# Force specific direction
gmail-filter-bot apply --push # Only push local changes
gmail-filter-bot apply --sync # Only pull Gmail changes
# Skip "apply to existing" step (don't label existing conversations)
gmail-filter-bot apply --no-apply-existingClean up configuration:
# Remove duplicates and consolidate
gmail-filter-bot clean
# Preview first
gmail-filter-bot clean --dry-run# Run tests
uv run pytest
# Run linting
uv run ruff check .
uv run ruff format .
# Run type checking
uv run mypy gmail_filter_bot/If a filter has more than 50 entries:
- Original filter:
newsletters(entries 1-50) - Auto-created:
newsletters-2(entries 51-100) - Auto-created:
newsletters-3(entries 101-150) - etc.
When you update a split filter (e.g., add one email to newsletters):
- Before: Deletes and recreates ALL parts (e.g., 8 parts = 8 API calls)
- After: Only updates the changed parts (e.g., 1 part = 1 API call)
This saves significant time when applying labels to existing conversations for large filters.
- Go to Google Cloud Console
- Create a new project or select an existing one
- Enable the Gmail API:
- Navigate to "APIs & Services" > "Library"
- Search for "Gmail API"
- Click "Enable"
- Go to "APIs & Services" > "Credentials"
- Click "Create Credentials" > "OAuth client ID"
- Configure the OAuth consent screen:
- Click "Configure Consent Screen"
- Select "External" (for personal use) or "Internal" (if using Google Workspace)
- Fill in required fields (app name, user support email, developer contact)
- Save and continue
- Create the OAuth client:
- Application type: Desktop app
- Name: "Gmail Filter Bot"
- Click "Create"
- Download the credentials:
- Click "Download JSON"
- Save as
credentials.jsonor extract the values for your.envfile
When you first run the tool, you'll be asked to authorize these scopes:
https://www.googleapis.com/auth/gmail.settings.basic- Manage filtershttps://www.googleapis.com/auth/gmail.labels- Read label names
For personal use (Testing mode):
- In "OAuth consent screen", scroll to "Test users"
- Click "Add users" and add your Gmail address
- This allows you to use the app without verification
Note: You'll see "Google hasn't verified this app" warning. This is normal for personal use. Click "Continue" to proceed.
Create a .env file with your credentials:
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-secret
GOOGLE_REDIRECT_URI=http://localhost:8080Or use the downloaded JSON file directly - the tool will prompt you to authenticate on first run.
# filters.yaml contains your private data and is gitignored
# Only commit the tool and documentation
# Add your filters
echo "filters.yaml" >> .gitignore # Already done
vim filters.yaml
# Run the tool
gmail-filter-bot apply