rules.pkl
Filter rules tag, move, or forward incoming mail during sync. Rules run sequentially — order matters when matches overlap.
Skeleton
rules {
new { name = "Mailing lists"; match = "header:list-id:"; add_tags { "list" } }
new {
name = "Bulk notifications"
match = "header:precedence:bulk OR header:auto-submitted:auto-generated"
add_tags { "notification"; "ephemeral" }
remove_tags { "inbox" }
}
}Rule fields
| Field | Type | Notes |
|---|---|---|
name | String | Shown in --dry-run output |
match | String | Query expression (see below) |
add_tags | Listing<String>? | Tags to add on match |
remove_tags | Listing<String>? | Tags to remove on match |
accounts | Listing<String>? | Restrict rule to certain account aliases |
Match syntax
The same operators as durian search, with extra header/attachment matchers:
| Term | Matches |
|---|---|
from:value | Sender contains substring (case-insensitive) |
to:value | Any recipient contains substring |
subject:value | Subject contains substring |
header:Name:value | Any header matches |
header:Name: | Header exists (any value) |
has:attachment | At least one attachment |
has:attachment:pdf | Attachment with that extension/MIME |
group:name | Expands to all addresses in the group |
AND (implicit) | Adjacent terms ANDed |
OR / NOT / ( ) | Explicit operators |
Pattern: ephemeral tagging
Mail tagged ephemeral is hidden from the default Inbox and silenced for notifications:
new {
name = "Newsletters"
match = "header:list-unsubscribe: NOT header:list-id:"
add_tags { "newsletter"; "ephemeral" }
remove_tags { "inbox" }
}Sidebar inboxes typically use tag:inbox AND NOT tag:ephemeral to surface only “real” mail.
Pattern: GitHub by reason
GitHub sets X-GitHub-Reason on every notification, letting you split by category:
new { name = "GH mentions"; match = "header:x-github-reason:mention"; add_tags { "gh"; "gh/mention" } }
new { name = "GH reviews"; match = "header:x-github-reason:review_requested"; add_tags { "gh"; "gh/review" } }
new { name = "GH CI noise"; match = "header:x-github-reason:ci_activity"; add_tags { "gh"; "ephemeral" }; remove_tags { "inbox" } }Apply to existing mail
Rules normally run on incoming sync only. To backfill after editing:
durian rules apply --dry-run # preview
durian rules apply # commitValidate
durian validate rules