NOTMUCH-SEARCH(1)

okay bestie, this is the notmuch-search page β€” it lives in the notmuch manual, section 1 (user commands, iykyk). let's get into it 🫢


🌸 NAME 🌸

notmuch-search β€” search for messages matching the given search terms


πŸŽ€ SYNOPSIS πŸŽ€

notmuch search [option ...] <search-term> ...

πŸ¦‹ DESCRIPTION πŸ¦‹

so like. you search for messages that match the search terms you gave it, and then it shows you the threads that contain the matched messages. that's the whole vibe πŸ’…

the output is one line per thread, and each line gives you:

  • the thread ID
  • the date of the newest (or oldest β€” depends on the sort option, we'll get there) matched message in the thread
  • the number of matched messages and total messages in the thread
  • the names of all the participants in the thread
  • the subject of the newest (or oldest) message

and if you wanna know what syntax is even allowed in <search-terms>, go peek at notmuch-search-terms (section 7), it's all there ✨

the supported options for search include:

  • --format=(json|sexp|text|text0) β€” serves the results up as JSON, S-Expressions, plain-text separated by newline characters (this is the default, no cap), or plain-text separated by null characters (which plays nice with the -0 option of xargs(1) where that's available).
  • --format-version=N β€” use the structured output format version you specify. this one is intended for programs that invoke notmuch internally, so like, if that's not you, you're probably fine. if you leave it out, the latest supported version gets used πŸ‘‘
  • --output=(summary|threads|messages|files|tags) β€” pick what actually comes out the other side:
    • summary (this is the default) β€” output a summary of each thread that has any message matching the search terms. the summary includes the thread ID, the date, the number of messages in the thread (both the number matched and the total number), the authors of the thread, and the subject. and in the case where a thread has multiple files for some messages, the total number of files gets printed in parentheses β€” there's an example further down, don't worry πŸ“
    • threads β€” output the thread IDs of all threads with any message matching the search terms. either one per line (--format=text), separated by null characters (--format=text0), as a JSON array (--format=json), or as an S-Expression list (--format=sexp).
    • messages β€” output the message IDs of all messages matching the search terms, either one per line (--format=text), separated by null characters (--format=text0), as a JSON array (--format=json), or as an S-Expression list (--format=sexp).
    • files β€” output the filenames of all messages matching the search terms, either one per line (--format=text), separated by null characters (--format=text0), as a JSON array (--format=json), or as an S-Expression list (--format=sexp).
heads up bestie: each message may have multiple filenames associated with it, and all of them are included in the output (unless you limit it with the --duplicate=N option). this can get particularly confusing for folder: or path: searches in a specified directory, because the messages may have duplicates in other directories that are included in the output β€” even though those files alone wouldn't have matched the search. it's giving chaos but it's fine 😭
  • tags β€” output all tags that appear on any message matching the search terms, either one per line (--format=text), separated by null characters (--format=text0), as a JSON array (--format=json), or as an S-Expression list (--format=sexp).
  • --sort=(newest-first|oldest-first) β€” presents results either in chronological order (oldest-first) or reverse chronological order (newest-first).
note: the thread order will be distinct between these two options β€” beyond just being simply reversed, like actually different. when sorting by oldest-first, the threads get sorted by the oldest message in each thread. but when sorting by newest-first, the threads get sorted by the newest message in each thread. the way that works is so real.

by default, results are displayed in reverse chronological order β€” that is, the newest results show up first ✨

  • --offset=[-]N β€” skip displaying the first N results. with a leading -, start at the Nth result from the end πŸ‘€
  • --limit=N β€” limit the number of displayed results to N. that's it, that's the option.
  • --exclude=(true|false|all|flag) β€” okay so a message is called "excluded" if it matches at least one tag in search.exclude_tags that does not appear explicitly in the search terms. this option decides whether excluded messages get omitted during the search process:
    • true (the default) β€” prevent excluded messages from matching the search terms.
    • all β€” additionally prevent excluded messages from appearing in displayed results, which in effect behaves as though the excluded messages literally do not exist πŸ’€
    • false β€” allow excluded messages to match search terms and appear in displayed results. excluded messages are still marked in the relevant outputs though.
    • flag β€” only has an effect when --output=summary. the output is almost identical to false, but the "match count" is the number of matching non-excluded messages in the thread, rather than the number of matching messages. subtle but iconic.
  • --duplicate=N β€” for --output=files, output the Nth filename associated with each message matching the query (N is 1-based, so we're counting from 1 bestie). if N is greater than the number of files associated with the message, don't print anything. nothing. silence. πŸ¦‹

for --output=messages, only output message IDs of messages matching the search terms that have at least N filenames associated with them.

note that this option is orthogonal with the folder: search prefix. the prefix matches messages based on filenames. this option filters filenames of the matching messages. two different jobs, both valid πŸ’…

🌈 EXAMPLE 🌈

here's an example of the summary output format, with one message having multiple filenames:

% notmuch search date:today.. and tag:bad-news
thread:0000000000063c10 Today [1/1] Some Persun; To the bone (bad-news inbox unread)
thread:0000000000063c25 Today [1/1(2)] Ann Other; Bears (bad-news inbox unread)
thread:0000000000063c00 Today [1/1] A Thurd; Bites, stings, sad feelings (bad-news unread)

see that [1/1(2)]? that's the multiple-filenames thing. ate πŸ’…


⭐ EXIT STATUS ⭐

this command supports the following special exit status codes:

  1. 20 β€” The requested format version is too old.
  2. 21 β€” The requested format version is too new.

🧚 SEE ALSO 🧚

notmuch, notmuch-address, notmuch-config, notmuch-count, notmuch-dump, notmuch-hooks, notmuch-insert, notmuch-new, notmuch-reply, notmuch-restore, notmuch-search-terms, notmuch-show, notmuch-tag


πŸ‘‘ AUTHOR πŸ‘‘

Carl Worth and many others


2009-2026, Carl Worth and many others


and that's the whole page bestie, you're basically a notmuch search expert now 🫢

version 0.40, dated Jan 31, 2026 β€” notmuch manual, NOTMUCH-SEARCH(1). go search something, you've earned it ✨🌸

πŸ“¦ where this page comes from