What I do
Automate Gmail inbox triage with rule-based patterns and AI fallback. It labels, archives, keeps, or escalates emails and can notify the user on Discord.
Core files
emails/check-emails.sh- hourly processoremails/email-patterns.json- sender/subject rules and settingsemails/check.log- run logemails/last-run.txt- last successful run epochemails/processed.json- last 24 hours of processed decisions
Workflow
- Skip quiet hours
- Search inbox using
after:<last_run_epoch>or a quiet-hours catch-up window - Apply rules from
email-patterns.json - If no rule matches, ask AI for a decision
- Apply action (keep, archive, label)
- Notify on Discord if needed
- Record decision in
processed.json
Settings
email-patterns.json contains:
{
"settings": {
"check_interval_hours": 1,
"quiet_hours_start": "22:00",
"quiet_hours_end": "08:00",
"max_emails_per_run": 20
}
}
Pattern rules
Each rule supports:
{
"sender": "example.com",
"subject_match": "receipt|order",
"action": "label|archive|keep|escalate",
"label": "Orders/example.com",
"subject_label": "Orders/example.com",
"notify_user": true,
"reason": "Short explanation"
}
If notify_user is true, a Discord message is sent when the pattern matches.
AI triage
When no pattern matches, the script calls the AI with a strict JSON response format:
{"action": "keep|archive|label", "label": "label_name", "notify_user": true/false, "message": "short explanation"}
Blank or invalid responses are normalized to safe defaults.
Processed log
emails/processed.json keeps the last 24 hours of decisions:
{
"id": "gmail_message_id",
"from": "Sender Name <sender@example.com>",
"subject": "Email subject",
"action": "keep|archive|label",
"label": "label_name",
"notify": "true|false",
"ai_used": "true|false",
"message": "short note",
"processed_at": "2026-02-17T08:00:03-07:00"
}
Common commands
# Run the check manually
./emails/check-emails.sh
# List inbox matches (gog)
gog gmail search "newer_than:24h in:inbox" --max 20
Tips
- Use
after:<epoch>for catch-up across quiet hours. - Keep patterns specific to avoid mislabeling.
- Log decisions to debug missed notifications.
- Add explicit
notify_userfor high-signal senders.