···11# Binary (root-level compiled binary only, not cmd/neomd/ source dir)
22/neomd
33+/neomd-freebsd
34/neomd-android
4556# Go build cache
+4
CHANGELOG.md
···11# Changelog
2233+# 2026-04-18
44+- **Headless daemon mode (`--headless`)** — run neomd as a background daemon on a server (NAS, VPS, always-on device) to continuously screen emails without launching the TUI; daemon fetches inbox and auto-screens every `bg_sync_interval` minutes (configurable in config); watches screener list files (`~/.config/neomd/lists/*.txt`) and reloads when they change (designed for Syncthing multi-device sync); graceful shutdown on SIGTERM/SIGINT; structured logging to stdout with `log/slog`; use case: run daemon on NAS with `bg_sync_interval = 5`, disable background sync on laptop/Android with `bg_sync_interval = 0`, classify senders in TUI, Syncthing syncs lists to NAS, daemon auto-screens incoming emails so mobile IMAP apps see correctly filtered folders; perfect for using neomd's screener with native mobile email clients; daemon only reads screener lists and moves emails (never modifies lists), all sender classification happens in TUI; includes comprehensive tests for classification logic and daemon lifecycle; documented in `docs/configurations/headless.md` with Syncthing setup guide, systemd service example, and multi-device workflow; `make daemon` target for testing
55+- **Cross-compile FreeBSD binary on build** — `make build` now automatically creates `neomd-freebsd` static binary alongside Linux binary; FreeBSD binary can be copied to FreeBSD/OpenBSD servers without needing Go installed; `make sync-headless` target copies to remote server via scp
66+37# 2026-04-17
48- **GitHub/Obsidian-style callouts in emails** — compose emails with callout syntax `> [!note]`, `> [!tip]`, `> [!warning]` for styled alert boxes in HTML emails; rendered with colored left borders, subtle backgrounds, and emoji icons using Kanagawa theme colors (crystalBlue, springGreen, carpYellow, oniViolet, autumnRed); compact spacing with emoji and title matching body text size (15px) for minimal visual intrusion; supports custom titles (`> [!note] Custom Title`), multiple paragraphs, and nested callouts; always expanded (no collapsible behavior), no JavaScript required; works in both syntaxes: `> [!note]` (with space) or `>[!note]` (without space); plain text emails format callouts as emoji text without blockquote markers (readable in neomd reader and plain text clients); uses local fork of goldmark-obsidian-callout with email-optimized rendering; same syntax used in neomd's README now works in your composed emails
59- **Timer-based mark-as-read** — emails are no longer marked as read immediately when opened; instead, a configurable timer (default 7 seconds) starts when you enter the reader; if you stay for the full duration, the email is marked as `\Seen`; if you exit early (quick peek), it stays unread; prevents accidental marking when browsing through emails
+8-2
Makefile
···44VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
55LDFLAGS := -ldflags "-X main.version=$(VERSION)"
6677-.PHONY: build run install clean test test-integration send-test vet fmt tidy release docs help check-go demo demo-reset demo-hp demo-hp-reset benchmark
77+.PHONY: build run install daemon clean test test-integration send-test vet fmt tidy release docs help check-go demo demo-reset demo-hp demo-hp-reset benchmark
88991010.DEFAULT_GOAL := install
···2929## build: compile ./neomd (version from git tag)
3030build: check-go docs
3131 go build $(LDFLAGS) -o $(BINARY) $(CMD)
3232-3232+ CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -o neomd-freebsd ./cmd/neomd # Build static binary for FreeBSD
3333## run: build and run
3434run: build
3535 ./$(BINARY) $(ARGS)
···3939 install -Dm755 $(BINARY) $(INSTALL)/$(BINARY)
4040 @echo "Installed to $(INSTALL)/$(BINARY)"
41414242+## daemon: run in headless daemon mode
4343+daemon: build
4444+ ./$(BINARY) --headless
42454346## demo: run neomd with demo account (~/.config/neomd-demo/config.toml)
4447demo: build
···139142## docs-clean: remove generated Hugo files
140143docs-clean:
141144 $(MAKE) -C docs clean
145145+146146+sync-headless:
147147+ scp neomd-freebsd ti:~/neomd
142148143149## help: print this list
144150help:
+1
README.md
···159159- **Multi-select** — `m` marks emails, then batch-delete, move, or screen them all at once [[more](https://ssp-data.github.io/neomd/docs/keybindings/#multi-select--undo)]
160160- **Auto-screen on load** — screener runs automatically every time the Inbox loads (startup, `R`); keeps your inbox clean without pressing `S` (configurable, on by default) [[more](https://ssp-data.github.io/neomd/docs/screener/#auto-screen-and-background-sync)]
161161- **Background sync** — while neomd is open, inbox is fetched and screened every 5 minutes in the background; interval configurable, set to `0` to disable [[more](https://ssp-data.github.io/neomd/docs/screener/#auto-screen-and-background-sync)]
162162+- **Headless daemon mode** — run `neomd --headless` on a server to continuously screen emails in the background without the TUI; watches screener list files for changes via Syncthing; emails are auto-screened every `bg_sync_interval` minutes so mobile apps see correctly filtered IMAP folders; perfect for running on a NAS while using the TUI on laptop/Android [[more](https://ssp-data.github.io/neomd/docs/configurations/headless/)]
162163- **Kanagawa theme** — colors from the [kanagawa.nvim](https://github.com/rebelot/kanagawa.nvim) palette
163164- **IMAP + SMTP** — direct connection via RFC 6851 MOVE, no local sync daemon required and keeps it in sync if you use it on mobile or different device [[more](https://ssp-data.github.io/neomd/docs/configuration/)]
164165
+23-10
cmd/neomd/main.go
···11111212 tea "github.com/charmbracelet/bubbletea"
1313 "github.com/sspaeti/neomd/internal/config"
1414+ "github.com/sspaeti/neomd/internal/daemon"
1415 goIMAP "github.com/sspaeti/neomd/internal/imap"
1516 "github.com/sspaeti/neomd/internal/oauth2"
1617 "github.com/sspaeti/neomd/internal/screener"
···2324func main() {
2425 cfgPath := flag.String("config", "", "path to config.toml (default: ~/.config/neomd/config.toml)")
2526 showVersion := flag.Bool("version", false, "print version and exit")
2727+ headless := flag.Bool("headless", false, "run in headless daemon mode (no TUI)")
2628 flag.Parse()
27292830 if *showVersion {
···119121 os.Exit(1)
120122 }
121123122122- ui.Version = version
123123- model := ui.New(cfg, imapClients, sc)
124124+ // Fork: run either headless daemon or TUI
125125+ if *headless {
126126+ // Headless daemon mode: run background screening loop
127127+ d := daemon.New(*cfg, imapClients[0], sc)
128128+ if err := d.Run(ctx); err != nil {
129129+ fmt.Fprintf(os.Stderr, "neomd: daemon error: %v\n", err)
130130+ os.Exit(1)
131131+ }
132132+ } else {
133133+ // TUI mode: run interactive interface
134134+ ui.Version = version
135135+ model := ui.New(cfg, imapClients, sc)
124136125125- p := tea.NewProgram(
126126- model,
127127- tea.WithAltScreen(),
128128- tea.WithMouseCellMotion(),
129129- )
130130- if _, err := p.Run(); err != nil {
131131- fmt.Fprintf(os.Stderr, "neomd: %v\n", err)
132132- os.Exit(1)
137137+ p := tea.NewProgram(
138138+ model,
139139+ tea.WithAltScreen(),
140140+ tea.WithMouseCellMotion(),
141141+ )
142142+ if _, err := p.Run(); err != nil {
143143+ fmt.Fprintf(os.Stderr, "neomd: %v\n", err)
144144+ os.Exit(1)
145145+ }
133146 }
134147}
135148
+30-28
docs/content/docs/_index.md
···8282*all colored boxes represent neomd folders*
83838484**Key principles:**
8585-- **Screener first**: Unknown senders never clutter your Inbox — they wait in ToScreen for classification
8686-- **One-time decision**: Once you classify a sender (`I/O/F/P`), all future emails from them are automatically routed
8787-- **GTD processing**: Emails in Inbox are processed once — if < 2 min, do it or keep it in inbox as doing *Next* otherwise move to Waiting, Someday, or Scheduled
8888-- **Minimal filing**: Only Archive when done; no complex folder hierarchies — use search to find old emails
8989-- **Separate contexts**: Feed for newsletters (read when you want), PaperTrail for receipts (search when needed)
8585+- **Screener first**: Unknown senders never clutter your Inbox — they wait in ToScreen for classification [[more](https://ssp-data.github.io/neomd/docs/screener/)]
8686+- **One-time decision**: Once you classify a sender (`I/O/F/P`), all future emails from them are automatically routed [[more](https://ssp-data.github.io/neomd/docs/screener/#how-classification-works)]
8787+- **GTD processing**: Emails in Inbox are processed once — if < 2 min, do it or keep it in inbox as doing *Next* otherwise move to Waiting, Someday, or Scheduled
8888+- **Minimal filing**: Only Archive when done; no complex folder hierarchies — use search to find old emails
8989+- **Separate contexts**: Feed for newsletters (read when you want), PaperTrail for receipts (search when needed)
9090+- See full features list below.
909191929293## Screenshots
···143144144145## Features
145146146146-- **Write in Markdown, send beautifully** — compose in `$EDITOR` (defaults to `nvim`), send as `multipart/alternative`: raw Markdown as plain text + goldmark-rendered HTML so recipients get clickable links, bold, headers, inline code, and code blocks
147147-- **Pre-send review** — after closing the editor, review To/Subject/body before sending; attach files, save to Drafts, or re-open the editor — no accidental sends
148148-- **Attachments** — attach files from the pre-send screen via yazi (`a`); images appear inline in the email body, other files as attachments; also attach from within neovim via `<leader>a`; the reader lists all attachments (including inline images) and `1`–`9` downloads and opens them
149149-- **Link opener** — links in emails are numbered `[1]`-`[0]` in the reader header; press `space+digit` to open in `$BROWSER`
150150-- **CC, BCC, Reply-all** — optional Cc/Bcc fields (toggle with `ctrl+b`); `R` in the reader replies to sender + all CC recipients
151151-- **Emoji reactions** — press `ctrl+e` from inbox or reader to react with emoji (👍 ❤️ 😂 🎉 🙏 💯 👀 ✅); instant send with proper threading and quoted message history, no editor needed; reactions appear in conversation threads with neomd branding
152152-- **GitHub/Obsidian-style callouts in emails** — compose emails with callout syntax `> [!note]`, `> [!tip]`, `> [!warning]` for styled alert boxes in HTML emails; rendered with colored left borders, subtle backgrounds, and emoji icons
153153-- **Drafts** — `d` in pre-send saves to Drafts (IMAP APPEND); `E` in the reader re-opens a draft as an editable compose; compose sessions are auto-backed up to `~/.cache/neomd/drafts/` so you never lose an unsent email (`:recover` to reopen)
154154-- **HTML signatures** — configure separate text and HTML signatures; text signature appears in editor and plain text part, HTML signature in HTML part only; use `[html-signature]` placeholder to control inclusion per-email
155155-- **Multiple From addresses** — define SMTP-only `[[senders]]` aliases (e.g. `s@ssp.sh` through an existing account); cycle with `ctrl+f` in compose and pre-send; sent copies always land in the Sent folder
156156-- **Undo** — `u` reverses the last move or delete (`x`, `A`, `M*`) using the UIDPLUS destination UID
157157-- **Search** — `/` filters loaded emails in-memory; `space /` or `:search` runs IMAP SEARCH across all folders (only fetching header capped at 100 per folder) with results in a temporary "Search" tab; supports `from:`, `subject:`, `to:` prefixes
158158-- **Address autocomplete** — To/Cc/Bcc fields autocomplete from screener lists; navigate with `ctrl+n`/`ctrl+p`, accept with `tab`
159159-- **Everything view** — `ge` or `:everything` shows the 50 most recent emails across all folders; find emails that were screened out, moved to spam, or otherwise hard to locate
160160-- **Threaded inbox** — related emails are grouped together in the inbox list with a vertical connector line (`│`/`╰`), Twitter-style; threads are detected via `In-Reply-To`/`Message-ID` headers with a subject+participant fallback; newest reply on top, root at bottom; `·` reply indicator shows which emails you've answered
161161-- **Conversation view** — `T` or `:thread` shows the full conversation across folders (Inbox, Sent, Archive, etc.) in a temporary tab with `[Folder]` prefix; see your replies alongside received emails
162162-- **Glamour reading** — incoming emails rendered as styled Markdown in the terminal
163163-- **HEY-style screener** — unknown senders land in `ToScreen`; press `I/O/F/P` to approve, block, mark as Feed, or mark as PaperTrail; reuses your existing `screened_in.txt` lists from neomutt
164164-- **Folder tabs** — Inbox, ToScreen, Feed, PaperTrail, Archive, Waiting, Someday, Scheduled, Sent, Trash, ScreenedOut
165165-- **Multi-select** — `m` marks emails, then batch-delete, move, or screen them all at once
166166-- **Auto-screen on load** — screener runs automatically every time the Inbox loads (startup, `R`); keeps your inbox clean without pressing `S` (configurable, on by default)
167167-- **Background sync** — while neomd is open, inbox is fetched and screened every 5 minutes in the background; interval configurable, set to `0` to disable
147147+- **Write in Markdown, send beautifully** — compose in `$EDITOR` (defaults to `nvim`), send as `multipart/alternative`: raw Markdown as plain text + goldmark-rendered HTML so recipients get clickable links, bold, headers, inline code, and code blocks [[more](https://ssp-data.github.io/neomd/docs/sending/)]
148148+- **Pre-send review** — after closing the editor, review To/Subject/body before sending; attach files, save to Drafts, or re-open the editor — no accidental sends [[more](https://ssp-data.github.io/neomd/docs/sending/#pre-send-review)]
149149+- **Attachments** — attach files from the pre-send screen via yazi (`a`); images appear inline in the email body, other files as attachments; also attach from within neovim via `<leader>a`; the reader lists all attachments (including inline images) and `1`–`9` downloads and opens them [[more](https://ssp-data.github.io/neomd/docs/sending/#attachments)]
150150+- **Link opener** — links in emails are numbered `[1]`-`[0]` in the reader header; press `space+digit` to open in `$BROWSER` [[more](https://ssp-data.github.io/neomd/docs/reading/#links)]
151151+- **CC, BCC, Reply-all** — optional Cc/Bcc fields (toggle with `ctrl+b`); `R` in the reader replies to sender + all CC recipients [[more](https://ssp-data.github.io/neomd/docs/sending/#cc-bcc-reply-all-and-forward)]
152152+- **Drafts** — `d` in pre-send saves to Drafts (IMAP APPEND); `E` in the reader re-opens a draft as an editable compose; compose sessions are auto-backed up to `~/.cache/neomd/drafts/` so you never lose an unsent email (`:recover` to reopen) [[more](https://ssp-data.github.io/neomd/docs/sending/#drafts)]
153153+- **HTML signatures** — configure separate text and HTML signatures; text signature appears in editor and plain text part, HTML signature in HTML part only; use `[html-signature]` placeholder to control inclusion per-email [[more](https://ssp-data.github.io/neomd/docs/configuration/#html-signatures)]
154154+- **Multiple From addresses** — define SMTP-only `[[senders]]` aliases (e.g. `s@ssp.sh` through an existing account); cycle with `ctrl+f` in compose and pre-send; sent copies always land in the Sent folder [[more](https://ssp-data.github.io/neomd/docs/sending/#multiple-from-addresses)]
155155+- **Undo** — `u` reverses the last move or delete (`x`, `A`, `M*`) using the UIDPLUS destination UID [[more](https://ssp-data.github.io/neomd/docs/keybindings/#multi-select--undo)]
156156+- **Search** — `/` filters loaded emails in-memory; `space /` or `:search` runs IMAP SEARCH across all folders (only fetching header capped at 100 per folder) with results in a temporary "Search" tab; supports `from:`, `subject:`, `to:` prefixes [[more](https://ssp-data.github.io/neomd/docs/keybindings/#leader-key-mappings-space-prefix)]
157157+- **Address autocomplete** — To/Cc/Bcc fields autocomplete from screener lists; navigate with `ctrl+n`/`ctrl+p`, accept with `tab`
158158+- **Everything view** — `ge` or `:everything` shows the 50 most recent emails across all folders; find emails that were screened out, moved to spam, or otherwise hard to locate [[more](https://ssp-data.github.io/neomd/docs/keybindings/#folders)]
159159+- **Threaded inbox** — related emails are grouped together in the inbox list with a vertical connector line (`│`/`╰`), Twitter-style; threads are detected via `In-Reply-To`/`Message-ID` headers with a subject+participant fallback; newest reply on top, root at bottom; `·` reply indicator shows which emails you've answered [[more](https://ssp-data.github.io/neomd/docs/reading/#threaded-inbox)]
160160+- **Conversation view** — `T` or `:thread` shows the full conversation across folders (Inbox, Sent, Archive, etc.) in a temporary tab with `[Folder]` prefix; see your replies alongside received emails [[more](https://ssp-data.github.io/neomd/docs/reading/#conversation-view)]
161161+- **Glamour reading** — incoming emails rendered as styled Markdown in the terminal [[more](https://ssp-data.github.io/neomd/docs/reading/)]
162162+- **HEY-style screener** — unknown senders land in `ToScreen`; press `I/O/F/P` to approve, block, mark as Feed, or mark as PaperTrail; reuses your existing `screened_in.txt` lists from neomutt [[more](https://ssp-data.github.io/neomd/docs/screener/)]
163163+- **Folder tabs** — Inbox, ToScreen, Feed, PaperTrail, Archive, Waiting, Someday, Scheduled, Sent, Trash, ScreenedOut [[more](https://ssp-data.github.io/neomd/docs/keybindings/#folders)]
164164+- **Emoji reactions** — press `ctrl+e` from inbox or reader to react with emoji (👍 ❤️ 😂 🎉 🙏 💯 👀 ✅); instant send with proper threading and quoted message history, no editor needed; reactions appear in conversation threads with neomd branding [[more](https://ssp-data.github.io/neomd/docs/sending/#emoji-reactions)]
165165+- **GitHub/Obsidian-style callouts in emails** — compose emails with callout syntax `> [!note]`, `> [!tip]`, `> [!warning]` for styled alert boxes in HTML emails; rendered with colored left borders, subtle backgrounds, and emoji icons [[more](https://ssp-data.github.io/neomd/docs/sending/#callouts-admonition)]
166166+- **Multi-select** — `m` marks emails, then batch-delete, move, or screen them all at once [[more](https://ssp-data.github.io/neomd/docs/keybindings/#multi-select--undo)]
167167+- **Auto-screen on load** — screener runs automatically every time the Inbox loads (startup, `R`); keeps your inbox clean without pressing `S` (configurable, on by default) [[more](https://ssp-data.github.io/neomd/docs/screener/#auto-screen-and-background-sync)]
168168+- **Background sync** — while neomd is open, inbox is fetched and screened every 5 minutes in the background; interval configurable, set to `0` to disable [[more](https://ssp-data.github.io/neomd/docs/screener/#auto-screen-and-background-sync)]
169169+- **Headless daemon mode** — run `neomd --headless` on a server to continuously screen emails in the background without the TUI; watches screener list files for changes via Syncthing; emails are auto-screened every `bg_sync_interval` minutes so mobile apps see correctly filtered IMAP folders; perfect for running on a NAS while using the TUI on laptop/Android [[more](https://ssp-data.github.io/neomd/docs/configurations/headless/)]
168170- **Kanagawa theme** — colors from the [kanagawa.nvim](https://github.com/rebelot/kanagawa.nvim) palette
169169-- **IMAP + SMTP** — direct connection via RFC 6851 MOVE, no local sync daemon required and keeps it in sync if you use it on mobile or different device
171171+- **IMAP + SMTP** — direct connection via RFC 6851 MOVE, no local sync daemon required and keeps it in sync if you use it on mobile or different device [[more](https://ssp-data.github.io/neomd/docs/configuration/)]
170172171173## Install
172174
+271
docs/content/docs/configurations/headless.md
···11+---
22+title: Headless Daemon Mode
33+weight: 4
44+---
55+66+Neomd can run in headless daemon mode to continuously screen emails in the background without launching the TUI. This is useful for running neomd on a server (like a NAS) that screens emails automatically, while you use the TUI on your laptop or mobile device.
77+88+## Overview
99+1010+When running in headless mode, neomd:
1111+- **Screens emails automatically** every `bg_sync_interval` minutes
1212+- **Watches screener list files** and reloads when they change (via Syncthing)
1313+- **Runs in the background** as a standard process
1414+- **Logs to stdout** for monitoring
1515+1616+## Quick Start
1717+1818+```sh
1919+# Run in foreground (for testing)
2020+neomd --headless
2121+2222+# Run in background
2323+neomd --headless &
2424+2525+# Run in background with logging
2626+nohup neomd --headless > /var/log/neomd.log 2>&1 &
2727+2828+# Or redirect to a file
2929+neomd --headless >> ~/.local/share/neomd/daemon.log 2>&1 &
3030+```
3131+3232+## Multi-Device Setup with Syncthing
3333+3434+The headless daemon is designed to work with [Syncthing](https://syncthing.net/) to keep screener lists synchronized across multiple devices.
3535+3636+### Architecture
3737+3838+1. **NAS/Server**: Runs `neomd --headless` continuously, screening emails every 5 minutes
3939+2. **Laptop**: Runs TUI with `bg_sync_interval = 0` (disabled), classifies senders manually
4040+3. **Android/Mobile**: Runs TUI with `bg_sync_interval = 0` (disabled), classifies senders manually
4141+4. **Syncthing**: Syncs screener list files across all devices
4242+4343+### Benefits
4444+4545+- **Automatic screening**: Emails are screened on the server even when your laptop/phone is offline
4646+- **Mobile email apps work**: Your phone's native email app sees screened emails in the correct IMAP folders
4747+- **No conflicts**: Only the daemon moves emails; TUI instances only classify senders
4848+- **Instant sync**: Classification decisions propagate to all devices via Syncthing
4949+5050+## Configuration
5151+5252+### Server Config (Daemon)
5353+5454+On your NAS/server, set `bg_sync_interval` to enable periodic screening:
5555+5656+```toml
5757+# ~/.config/neomd/config.toml (server)
5858+[ui]
5959+bg_sync_interval = 5 # Screen inbox every 5 minutes
6060+```
6161+6262+### Laptop/Mobile Config (TUI)
6363+6464+On devices where you run the TUI, **disable background sync** to avoid duplicate moves:
6565+6666+```toml
6767+# ~/.config/neomd/config.toml (laptop/mobile)
6868+[ui]
6969+bg_sync_interval = 0 # Disable background screening (daemon handles it)
7070+```
7171+7272+## Syncthing Setup
7373+7474+### Files to Sync
7575+7676+Configure Syncthing to sync the following files across all your devices:
7777+7878+1. **Screener list directory**: `~/.config/neomd/lists/`
7979+ - `screened_in.txt`
8080+ - `screened_out.txt`
8181+ - `feed.txt`
8282+ - `papertrail.txt`
8383+ - `spam.txt`
8484+8585+2. **Config file** (optional): `~/.config/neomd/config.toml`
8686+ - Useful for keeping settings consistent across devices
8787+ - Be careful with account-specific settings (passwords, paths)
8888+8989+### Syncthing Folder Setup
9090+9191+1. **Install Syncthing** on all devices (NAS, laptop, Android)
9292+2. **Create a shared folder** named "neomd-lists"
9393+3. **Set folder path** to `~/.config/neomd/lists/` on each device
9494+4. **Connect devices** and wait for initial sync
9595+9696+Example Syncthing folder configuration:
9797+- **Folder ID**: `neomd-lists`
9898+- **Folder Path**: `/home/user/.config/neomd/lists/`
9999+- **Folder Type**: Send & Receive
100100+- **File Versioning**: Simple File Versioning (keep 5 versions)
101101+102102+### Conflict Handling
103103+104104+- **File-level conflicts**: Syncthing creates `.sync-conflict` files if two devices modify the same file simultaneously
105105+- **Email-level**: IMAP is the source of truth; no local email state to conflict
106106+- **Screener lists**: Append-only operations are safe; duplicates are harmless (normalized automatically)
107107+108108+The daemon watches for file changes and reloads screener lists automatically when Syncthing updates them.
109109+110110+## Systemd Service (Optional)
111111+112112+For servers with systemd, you can create a service unit for automatic startup and logging:
113113+114114+```ini
115115+# /etc/systemd/user/neomd.service
116116+[Unit]
117117+Description=Neomd Headless Email Screener
118118+After=network.target
119119+120120+[Service]
121121+Type=simple
122122+ExecStart=%h/.local/bin/neomd --headless
123123+Restart=on-failure
124124+RestartSec=10
125125+StandardOutput=journal
126126+StandardError=journal
127127+128128+[Install]
129129+WantedBy=default.target
130130+```
131131+132132+Enable and start the service:
133133+134134+```sh
135135+# Install neomd to ~/.local/bin
136136+make install
137137+138138+# Reload systemd
139139+systemctl --user daemon-reload
140140+141141+# Enable auto-start on login
142142+systemctl --user enable neomd
143143+144144+# Start now
145145+systemctl --user start neomd
146146+147147+# Check status
148148+systemctl --user status neomd
149149+150150+# View logs
151151+journalctl --user -u neomd -f
152152+```
153153+154154+## Monitoring
155155+156156+### View Logs
157157+158158+If running with `nohup` or redirected output:
159159+160160+```sh
161161+tail -f /var/log/neomd.log
162162+```
163163+164164+If running as systemd service:
165165+166166+```sh
167167+journalctl --user -u neomd -f
168168+```
169169+170170+### Log Format
171171+172172+The daemon logs structured output with timestamps:
173173+174174+```
175175+time=2025-04-18T10:00:00Z level=INFO msg="neomd daemon starting" version=headless
176176+time=2025-04-18T10:00:00Z level=INFO msg="screening interval configured" minutes=5
177177+time=2025-04-18T10:00:00Z level=INFO msg="watching directory for changes" dir=/home/user/.config/neomd/lists
178178+time=2025-04-18T10:00:00Z level=INFO msg="daemon running" interval=5m0s
179179+time=2025-04-18T10:00:05Z level=INFO msg="running initial screening"
180180+time=2025-04-18T10:00:05Z level=INFO msg="fetched inbox emails" count=42
181181+time=2025-04-18T10:00:05Z level=INFO msg="emails to screen" count=12
182182+time=2025-04-18T10:00:05Z level=INFO msg="screened email" index=1 total=12 from="newsletter@example.com" subject="Weekly Update" dst=Feed
183183+...
184184+time=2025-04-18T10:00:06Z level=INFO msg="screening complete" moved=12 total=12
185185+```
186186+187187+### Graceful Shutdown
188188+189189+Send SIGTERM or SIGINT to stop the daemon:
190190+191191+```sh
192192+# If running in foreground
193193+Ctrl+C
194194+195195+# If running in background
196196+kill <pid>
197197+198198+# With systemd
199199+systemctl --user stop neomd
200200+```
201201+202202+The daemon will finish the current screening operation before exiting.
203203+204204+## Troubleshooting
205205+206206+### Daemon exits immediately
207207+208208+Check that `bg_sync_interval` is set to a value > 0:
209209+210210+```sh
211211+grep bg_sync_interval ~/.config/neomd/config.toml
212212+```
213213+214214+### Screener lists not reloading
215215+216216+Check file watcher logs:
217217+218218+```sh
219219+tail -f /var/log/neomd.log | grep "watching directory"
220220+```
221221+222222+Verify Syncthing is running and syncing:
223223+224224+```sh
225225+# Check Syncthing web UI (usually http://localhost:8384)
226226+```
227227+228228+### Emails not being screened
229229+230230+1. Check daemon is running: `ps aux | grep neomd`
231231+2. Check IMAP connection in logs
232232+3. Verify screener list files exist and contain email addresses
233233+4. Check folder configuration in config.toml
234234+235235+### Duplicate screening
236236+237237+If emails are being moved twice (once by daemon, once by TUI):
238238+239239+- Set `bg_sync_interval = 0` on TUI devices
240240+- Only run one daemon instance per account
241241+242242+## Android Termux Example
243243+244244+>[!NOTE]
245245+> See Android Termux Setup at [Android Docs](android.md)
246246+247247+On Android, you can run the daemon in a Termux session:
248248+249249+```sh
250250+# Install Termux:Boot from F-Droid to auto-start on device boot
251251+pkg install termux-boot
252252+253253+# Create boot script
254254+mkdir -p ~/.termux/boot
255255+cat > ~/.termux/boot/neomd-daemon.sh <<'EOF'
256256+#!/data/data/com.termux/files/usr/bin/bash
257257+cd ~/neomd
258258+nohup ./neomd --headless >> ~/neomd-daemon.log 2>&1 &
259259+EOF
260260+chmod +x ~/.termux/boot/neomd-daemon.sh
261261+262262+# Reboot device to auto-start daemon
263263+```
264264+265265+## Notes
266266+267267+- The daemon only **reads** screener list files and **moves** emails via IMAP
268268+- All sender classification (adding to lists) happens in the TUI
269269+- File watching requires the screener list directory to exist
270270+- The daemon uses the first configured account from `config.toml`
271271+- IMAP connection is kept alive and automatically reconnects on failures