lieer: two-way tag sync between notmuch and GMail
Fast email-fetching, sending, and two-way tag synchronization between notmuch and GMail
At a glance
- What is it?
- lieer pulls and sends mail through the GMail API and keeps a notmuch database in step with it, including pushing local tag changes back to GMail. It is built for people who want offline mail access and fast search, and it makes its boundaries explicit: it will not add or delete messages, and it carries no warranties.
- Who is it for?
- Adopt lieer if you keep a local notmuch maildir and want its tags to stay in step with a GMail account without a full IMAP synchronisation, particularly if you read mail on several machines or want fast local search. Do not adopt it as a general mail client, because it will not add or delete messages on the remote account and it modifies nothing but labels, and do not treat it as a hardened component, since the project states it comes with no warranties.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A sync tool for people who already live in notmuch
lieer pulls and sends email and labels, and changes to labels, from a GMail account and stores them locally in a maildir with the labels synchronized with a notmuch database. Changes to tags in the notmuch database may be pushed back remotely to the GMail account.
That is the whole scope, and the direction of the arrows is the point. A conventional IMAP client keeps a local cache that is a copy of the server, and the server is the source of truth. lieer inverts part of that: the local notmuch database is a first class citizen whose tag changes are meaningful, and they travel back up to GMail. The result is that a tag you add offline, or in a script, or on a second machine, shows up in the GMail web interface.
The two-way part is what distinguishes it from a plain GMail to maildir dumper. The target user is someone with a large archive who wants GMail's storage and search somewhere else, or who wants to keep their own tag vocabulary. The readme mentions that the tool has been used to synchronise millions of messages and tags.
The homepage is lieer.gaute.vetsj.com, the language is Python 3, and the licence file is a GPL 3.0 plus COPYING.GPL-3.0+ pair with a LICENSE.md, with the setup module declaring GPLv3+ and a development status of Beta.
What lieer refuses to do
The disclaimer comes before the installation instructions, and it is worth reading in full because it defines the tool's safety model.
lieer will not and can not add or delete messages on the remote account, with one exception: syncing the trash or spam label to messages, and those messages will eventually be deleted on the GMail side. It also will not modify messages other than their labels.
So the tool is confined to the label axis. A message body is never rewritten, a message is never removed by the tool's own action, and the only path by which something disappears remotely is the one where you or a rule marks it as trash or spam and GMail acts on that. Everything else is metadata.
That is a much stronger guarantee than a tool that can also send, delete and modify, and it is the reason the tool can be pointed at a primary mail account with any confidence. It is also a real limitation, and it means the local maildir is not a full copy of the remote account in the sense of containing everything you have sent.
The second line of the disclaimer is the one that matters for a production deployment: while the tool has been used to synchronise millions of messages and tags, it comes with NO WARRANTIES. It is a volunteer project making no reliability commitment, and the readme is straightforward about that.
Setting up the local repository and the OAuth handshake
The usage section assumes your root mail folder is in ~/.mail and that this folder is already set up with notmuch. Lieer is a tool that joins two things that already exist, not one that sets up a mail system for you.
Installation is a pip install from a cloned repository. Then you make a directory for the storage and state files, which is the local repository for the account:
$ cd ~/.mail
$ mkdir account.gmail
$ cd account.gmail/All commands are run from that local mail repository unless otherwise specified.
There is a notmuch configuration step, because Lieer stores its own state as JSON files in the maildir and notmuch would otherwise index them:
[new]
tags=new
ignore=/.*[.](json|lock|bak)$/The same section explains the new.tags behaviour, which is a subtle point: any tags listed there are added to newly pulled messages, and they are not ignored by default if you do not remove them, but you can stop custom tags being pushed to the remote with a command such as gmi set --ignore-tags-local new.
Initialisation then opens a browser and requests limited access to your email:
$ gmi init [email protected]The access token is stored in.credentials.gmailieer.json in the local mail repository, and the readme notes you can specify your own API key instead.
The requirements are Python 3, notmuch 0.30 or newer for the notmuch2 Python bindings, google_api_python_client, google_auth_oauthlib and tqdm for the progress bar.
Pull, push and the sync routine, and who wins a conflict
The three verbs are simple, and the conflict rules are where the design decisions are.
Pull downloads all remote changes since last time, overwriting any local tag changes of the affected messages:
$ gmi pullThe first pull, or a full synchronisation, takes longer, and there is a --resume option if you get stuck retrieving the metadata and have to abort, which causes local changes made in the interim to be ignored in the next push.
Push goes the other way, uploading all changes since the last push, with conflicting changes ignored unless -f is specified, and those overwritten with the remote changes at the next pull:
$ gmi pushThe normal routine is a push followed by a pull:
$ cd ~/.mail/account.gmail
$ gmi syncConflicts detected with the remote during push are not pushed. After the next pull the conflicts should be resolved, with local changes overwritten by the remote ones, and you can force the local changes to win with push -f.
So the default resolution is remote wins, and the local side only wins when you ask. That is a sensible default for a tool where the remote account is where the mail actually lives, but it means a local tag change can be silently discarded.
The readme also flags the sharp edge directly: if changes are being made on the remote, on a message currently being synced, the changes may be overwritten or merged in weird ways. There is a longer caveats section for this, and it is the part to read before relying on the tool in a busy account.
Sending through the GMail API instead of an MTA
lieer can be used as a simple stand-in for the sendmail MTA, and the configuration for a mail user agent send command is a single flag combination:
gmi send -t -C ~/.mail/account.gmailThat is the piece that makes the tool useful to developers, because it lets tooling that shells out to sendmail use the GMail account without a local MTA. The readme gives the git send-email configuration as the example, pointing the sendemail.sendmailcmd setting at the same command.
Like the real sendmail program, the raw message is read from stdin. The difference is in what is supported. Most sendmail implementations allow passing additional recipients as additional arguments, but the GMail API only supports the -t, or --read-recipients, mode of sendmail, without additional recipients.
lieer tries to support valid combinations anyway. Additional recipients are ignored, but validated. When -t is passed, the CLI-passed recipients must be equal to or a subset of the ones in the headers, and when -t is not passed, all header-passed recipients must also be provided on the command line. That validation exists to avoid two specific failures: silently not sending mail to some recipients while pretending it did, and sending mail to recipients you did not want to send to again.
One consequence is that you must keep a Bcc header in the message when passing it to sendmail, since putting the additional recipient only on the command line is not enough. For mutt, that means setting the write_bcc option. There are also ignored flags for sendmail compatibility: -f, which is ignored so you set the envelope From yourself, -o, and -i, which is always implied.
Settings, and the state that makes the sync work
lieer is configured with gmi set, and running it with no options lists the current settings along with the current history ID and notmuch revision, which are the two pieces of state the whole synchronisation depends on.
The Account setting is the GMail account the repository is synced with, configured during setup. The historyId is the latest synced GMail revision, and anything since that ID is fetched on the next pull, which is what makes a pull partial rather than a full scan. The lastmod setting is the latest synced notmuch database revision, and anything changed after it is pushed on the next push.
The Timeout setting is the timeout in seconds for the HTTP connection to GMail, where 0 means forever or the system error and timeout, whichever occurs first.
The reason this matters is that the tool is not doing a full diff of your account on every run. It asks GMail what has changed since a known point, and asks notmuch what has changed since a known point, and reconciles only those. That is why the readme calls the tool fast, and it is also why the two revision numbers are worth backing up, since they are the state that lets a partial sync continue rather than start over.
The repository has a .ruff.toml for linting, a requirements file listing the Google client libraries, tqdm, notmuch2 and setuptools, a tests directory, a docs directory and a gmi script at the root, and the last push was on 2026-10-16, so the project is being worked on.
Editorial conclusion
Adopt lieer if you keep a local notmuch maildir and want its tags to stay in step with a GMail account without a full IMAP synchronisation, particularly if you read mail on several machines or want fast local search. Do not adopt it as a general mail client, because it will not add or delete messages on the remote account and it modifies nothing but labels, and do not treat it as a hardened component, since the project states it comes with no warranties. Before you commit, back up the maildir, read the caveats section about remote changes made during a sync, and decide whether the default push overwrite behaviour is acceptable for your account.
Frequently asked questions
What does lieer do?
It pulls and sends email and labels, and changes to labels, from a GMail account and stores them locally in a maildir with the labels synchronized with a notmuch database. Tag changes made locally in the notmuch database can be pushed back to the GMail account.
Can lieer delete or modify messages on my GMail account?
No. Lieer will not add or delete messages on the remote account, except that syncing the trash or spam label to messages leads to those messages being deleted on the GMail side. It also will not modify messages other than their labels.
How do I install and set up lieer?
Install it with pip from a cloned repository, create a directory for the account inside your existing notmuch mail folder, add the notmuch ignore rule for the JSON state files, then run gmi init with your email address. That opens a browser to request limited access and stores the token in .credentials.gmailieer.json.
What happens when there are conflicting changes between notmuch and GMail?
A push leaves conflicting changes unpushed, and the next pull overwrites the local changes with the remote ones, so the remote wins by default. You can force the local changes to win with push -f, and the readme warns that changes made on the remote during a sync may be overwritten or merged in unexpected ways.
Can I use lieer to send mail from git send-email?
Yes. Lieer works as a stand-in for the sendmail MTA, reading the raw message from stdin, and the readme shows configuring it with git config sendemail.sendmailcmd. Note that the GMail API only supports the -t read-recipients mode, so a Bcc header must be kept in the message for additional recipients.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gauteh-lieer)Was this useful?