Back to list
jasonkuhrt

notmuch

by jasonkuhrt

Tool configurations

1🍴 0📅 Jan 22, 2026

SKILL.md


name: notmuch description: notmuch email indexer - search, threading, tagging for local Maildir. Use when searching emails, understanding notmuch queries, or integrating with notmuch.

notmuch

notmuch is a system for indexing, searching, reading, and tagging large collections of email messages in Maildir format. It uses Xapian for fast full-text search.

CRITICAL

  • notmuch is local only - indexes your local Maildir, not IMAP directly
  • Thread IDs are internal to notmuch - not portable across systems
  • Tags are per-message, not per-thread
  • Use with mbsync: mbsync -a && notmuch new

Documentation

Local reference: See references/man-pages.md for cached man pages.

Core Concepts

Data Model

Maildir (files)
    │
    ▼
notmuch index (Xapian database)
    │
    ├── Messages (indexed content + metadata)
    │       └── Tags (flat strings per message)
    │
    └── Threads (groupings derived from headers)
  • Message: Indexed email file with full-text content
  • Thread: Logical grouping reconstructed from In-Reply-To and References headers
  • Tag: String label attached to individual messages (not threads)

Threading

notmuch reconstructs threads from email headers:

  • In-Reply-To: Direct parent message
  • References: Chain of ancestor Message-IDs

Thread IDs are opaque internal identifiers (e.g., thread:00000000000001dd).

Note: Threading is heuristic. notmuch considers all references, not just the heuristically chosen parent.

Commands

Basic Operations

# Index new mail
notmuch new

# Search (returns threads)
notmuch search <query>

# Search (returns messages)
notmuch search --output=messages <query>

# Show message content
notmuch show <query>
notmuch show --format=json <query>

# Count matches
notmuch count <query>

# Tag messages
notmuch tag +inbox +unread -- <query>
notmuch tag -unread -- <query>

# List all tags
notmuch search --output=tags '*'

Output Formats

# Thread list (default)
notmuch search tag:unread

# Message IDs only
notmuch search --output=messages tag:unread

# File paths only
notmuch search --output=files tag:unread

# JSON format
notmuch search --format=json tag:unread
notmuch show --format=json tag:unread

# S-expressions
notmuch search --format=sexp tag:unread

Search Syntax

Prefixes

PrefixTypeDescription
from:ProbabilisticSender address or name
to:ProbabilisticRecipient address or name
subject:ProbabilisticSubject line
body:ProbabilisticMessage body
attachment:ProbabilisticAttachment filename
mimetype:ProbabilisticMIME type
tag:BooleanMessage tag
id:BooleanMessage-ID
thread:BooleanThread ID
folder:BooleanMaildir folder
path:BooleanFile path
date:SpecialDate/time range
lastmod:SpecialDatabase modification

Boolean Operators

# AND (implicit with space, or explicit)
notmuch search from:alice subject:meeting
notmuch search from:alice and subject:meeting

# OR
notmuch search from:alice or from:bob

# NOT
notmuch search from:alice and not tag:spam

# XOR
notmuch search from:alice xor from:bob

# Grouping
notmuch search '(from:alice or from:bob) and tag:unread'

Date Queries

# Relative dates
notmuch search date:today
notmuch search date:yesterday
notmuch search date:last_week
notmuch search date:this_month
notmuch search date:7_days_ago..today

# Absolute dates
notmuch search date:2024-01-01..2024-01-31
notmuch search date:2024-01-01..

# Timestamps
notmuch search date:@1234567890..@1234567900

Regex Support (Xapian 1.4+)

# Regex on from/subject
notmuch search 'from:/.*@amazon\./'
notmuch search 'subject:/order.*shipped/'

Thread Queries

# By thread ID
notmuch search thread:00000000000001dd

# Indirect: threads containing messages matching query
notmuch search 'thread:{from:alice}' and 'thread:{subject:crypto}'

Tags

Built-in Tags

TagDescriptionMaildir Sync
inboxDefault for new messagesNo
unreadNot yet readSyncs to Maildir flag
draftDraft messageSyncs to Maildir flag
flaggedStarred/importantSyncs to Maildir flag
repliedReplied toSyncs to Maildir flag
passedForwardedSyncs to Maildir flag

Tag Operations

# Add tags
notmuch tag +important +work -- from:boss@company.com

# Remove tags
notmuch tag -inbox -unread -- tag:archived

# Multiple operations
notmuch tag +archived -inbox -- date:..2023-01-01

# Tag all messages in a thread
notmuch tag +project-x -- thread:00000000000001dd

Maildir Flag Sync

notmuch can sync certain tags to Maildir flags (visible to other clients):

# In notmuch config
[maildir]
synchronize_flags=true

Mapped tags: draft, flagged, passed, replied, unread (S flag)

Configuration

# Show config
notmuch config list

# Set config
notmuch config set user.name "Your Name"
notmuch config set user.primary_email "you@example.com"

# Database path
notmuch config set database.path "/path/to/mail"

Config File Location

  • ~/.notmuch-config (legacy)
  • $XDG_CONFIG_HOME/notmuch/default/config (modern)
  • $NOTMUCH_CONFIG environment variable

New Mail Tags

[new]
tags=unread;inbox
ignore=.mbsyncstate;.strstrignore

Hooks

notmuch supports hooks for automation:

~/.config/notmuch/default/hooks/
├── pre-new      # Before indexing
└── post-new     # After indexing

Example post-new hook:

#!/bin/bash
# Auto-tag based on rules
notmuch tag +newsletter -- from:*@substack.com and tag:new
notmuch tag -new -- tag:new

API & Bindings

C Library (libnotmuch)

Core functions:

  • notmuch_database_open / notmuch_database_create
  • notmuch_query_create / notmuch_query_search_messages
  • notmuch_message_get_tags / notmuch_message_add_tag

Python Bindings

# Modern (notmuch2 - CFFI based)
import notmuch2

with notmuch2.Database() as db:
    for msg in db.messages('tag:unread'):
        print(msg.header('Subject'))

# Legacy (deprecated, removed in 0.39)
import notmuch  # Don't use

Other Bindings

  • Emacs: Full MUA built-in
  • Vim: notmuch-vim plugin
  • Go: go-notmuch
  • Ruby: notmuch gem

Integration with Other Tools

mbsync

# Sync then index
mbsync -a && notmuch new

himalaya

himalaya can use notmuch as a backend for search.

aerc

Terminal MUA with native notmuch support.

Emacs

notmuch ships with a full Emacs interface.

Strengths (Don't Replicate)

CapabilityWhy It's Good
Full-text searchXapian is battle-tested, handles 100k+ messages
ThreadingCorrect reconstruction from headers
Maildir integrationDirect file access, no sync issues
Fast taggingImmediate, lightweight
Incremental indexingnotmuch new only indexes new messages
StableMature, reliable, used by power users for years

Limitations

LimitationImpact
No relational queriesCan't join sender info with thread analysis
Tags are flat stringsNo hierarchy, metadata, or relations
No structured dataCan't store "tracking_number = X"
No computed propertiesThread participant count needs manual query
Thread ID is opaqueCan't query thread properties directly
Local onlyThread IDs not portable across machines
Per-message tagsTagging a "thread" means tagging all messages

Common Patterns

Auto-tagging in post-new hook

#!/bin/bash
# Tag newsletters
notmuch tag +newsletter -inbox -- \
  '(from:*@substack.com or from:*@buttondown.email) and tag:new'

# Tag receipts
notmuch tag +receipt -- \
  'subject:receipt or subject:invoice and tag:new'

# Clear new tag
notmuch tag -new -- tag:new

Export thread as mbox

notmuch show --format=mbox thread:xxx > thread.mbox

Find large threads

# No direct way - must iterate
notmuch search '*' | while read -r line; do
  thread_id=$(echo "$line" | cut -d' ' -f1)
  count=$(notmuch count "thread:$thread_id")
  echo "$count $thread_id"
done | sort -rn | head -10

Backup tags

notmuch dump > tags-backup.txt
notmuch restore < tags-backup.txt

Version Requirements

  • Xapian 1.4.0+ (for regex support)
  • GMime 3.0.3+
  • Python 3.x for notmuch2 bindings

Attribution

Research compiled 2026-01-11 from:

Score

Total Score

55/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon