zmail

v0.1.2

Local-first email for agents: IMAP sync to maildir + SQLite (FTS5); CLI search, read, thread, who, attachments. Requires Node 20+, npm install (`npm install...

0· 176·0 current·0 all-time
byLew Cirne@cirne

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for cirne/zmail.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "zmail" (cirne/zmail) from ClawHub.
Skill page: https://clawhub.ai/cirne/zmail
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Required binaries: node, npm, zmail
Config paths to check: ZMAIL_EMAIL, ZMAIL_IMAP_PASSWORD, ZMAIL_OPENAI_API_KEY
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install zmail

ClawHub CLI

Package manager switcher

npx clawhub@latest install zmail
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
medium confidence
Purpose & Capability
The name/description (local-first IMAP sync, SQLite FTS5 index, CLI search/read/ask) match the declared requirements: Node/npm, the zmail CLI, IMAP credentials, and an OpenAI key for 'ask'/'inbox' features. Nothing unrelated is requested.
Instruction Scope
SKILL.md instructs the agent to install and run the zmail CLI, create a local cache under ~/.zmail, and (optionally) send email-derived content to OpenAI or third-party 'enrich' APIs for certain commands. Those network calls are explicitly described as optional, but they do mean email content may leave the device when using those commands—this is within the stated purpose but is a privacy-sensitive action the user/agent must opt into.
Install Mechanism
No install spec in registry (instruction-only), but SKILL.md tells users to run `npm install -g @cirne/zmail` or `npx @cirne/zmail`. That's a standard npm-based install; it also uses native better-sqlite3 which can rebuild a native addon on first run. That build step can execute code during compilation and may require toolchain access—expected for this project but worth noting.
Credentials
Required config/env (ZMAIL_EMAIL, ZMAIL_IMAP_PASSWORD, ZMAIL_OPENAI_API_KEY or OPENAI_API_KEY) are proportionate to an IMAP-sync tool with optional OpenAI features. However, the registry summary at the top lists “Required env vars: none” while the SKILL.md and openclaw.requires declare the three env variables—this metadata mismatch is an incoherence to fix before trusting UI-level permission prompts.
Persistence & Privilege
Skill is instruction-only and not always-enabled; it does not request elevated platform persistence. It stores config and a local mail cache under ~/.zmail (documented) which is appropriate for its functionality.
Assessment
This skill appears to do what it says: a local IMAP sync + SQLite index with a CLI and optional OpenAI-powered commands. Before installing: 1) Decide whether you are comfortable with email-derived content being sent to OpenAI (used by `zmail ask`, `zmail inbox`, and optionally `who --enrich`); sensitive mail should not be sent unless you accept that. 2) Prefer `npx @cirne/zmail` for one-off use or inspect the npm package source at https://github.com/cirne/zmail before global install. 3) Be aware the native better-sqlite3 addon may rebuild/compile on first run (requires build tools and will execute build scripts). 4) Protect ~/.zmail/.env (file permissions, backups) since it stores credentials. 5) Note the registry metadata mismatch: the top-level metadata says no env vars required while SKILL.md clearly needs ZMAIL_EMAIL, ZMAIL_IMAP_PASSWORD, and an OpenAI key—verify the UI will request/secure those values before proceeding.

Like a lobster shell, security has layers — review code before you run it.

Runtime requirements

Binsnode, npm, zmail
ConfigZMAIL_EMAIL, ZMAIL_IMAP_PASSWORD, ZMAIL_OPENAI_API_KEY
latestvk97d42j0ntceryxzx863ttd7y583pbt0
176downloads
0stars
3versions
Updated 1mo ago
v0.1.2
MIT-0

/zmail — agent-first email

What zmail is: Email reimagined for agents and automation—not a human-first inbox UI. It syncs mail over IMAP, stores messages as files (maildir-style) and indexes them in local SQLite with FTS5. The primary surface is the CLI: search, read, thread, who, attachments, and zmail ask for natural-language questions (OpenAI). Same index powers every command—queries stay local and fast so the assistant can treat mail like a repository of communication artifacts (invoices, travel, Zoom summaries, etc.) instead of paging through Gmail.

Why use it: Traditional webmail is slow and awkward for AI workflows. zmail’s promise is local-first, privacy-friendly mail you control, agent-intuitive commands, and room to grow toward “the agent is the interface”—plain-language prompts become searches and reads, not manual digging.

Transparency (registries & security review)

Use this block to keep ClawHub / OpenClaw registry fields aligned with the skill body—avoid “no credentials required” when the CLI clearly needs secrets.

TopicWhat to declare
ProvenanceSource and issues: github.com/cirne/zmail
Installnpm install -g @cirne/zmail or npx @cirne/zmail (Node 20+). Native better-sqlite3; on ABI mismatch, first zmail run rebuilds via ensure-better-sqlite-native (or run npm rebuild better-sqlite3 yourself with the same node that runs zmail).
On PATHGlobal npm bin must be on PATH, or use npx @cirne/zmail for one-off invocations.
Required secrets (after setup)ZMAIL_EMAIL, ZMAIL_IMAP_PASSWORD (IMAP; e.g. Gmail app password). ZMAIL_OPENAI_API_KEY or OPENAI_API_KEY for setup wizard, zmail ask, zmail inbox, and optional zmail who --enrich.
Privacy / data leaving the devicezmail ask, zmail inbox, and who --enrich can send email-derived content (subjects, snippets, bodies, addresses) to OpenAI or other APIs—only use if the mailbox owner accepts that. Primitives search / read / thread / attachment (without enrich) are local index + disk only once mail is synced.
Credentials on diskSecrets live under ZMAIL_HOME/.env (and non-secret settings in config.json). They are used only to talk to your IMAP host and (when configured) OpenAI—not to third-party analytics or the zmail project. Treat .env like any password file (permissions, backups, don’t paste into chats).
IMAP / send postureRead-only today: zmail syncs and indexes mail; it does not implement SMTP send in this release. Normal sync is a local cache of what remains on the server—deleting local data (see below) does not remove server-side mail.
MCP (optional)zmail mcp uses stdio JSON-RPC only (stdin/stdout)—no in-process HTTP server or listening TCP port for MCP.
Persistence & local wipeConfig and a local copy of mail (SQLite index + maildir cache under data/) live under ZMAIL_HOME (default ~/.zmail). zmail setup --clean --yes removes that local tree and rewrites config—it does not delete mail on the IMAP server; after setup, run zmail sync to rebuild the local cache from IMAP. You still lose unsaved local-only state (e.g. extracted-attachment cache, any data not on the server).
Shell safetyInvoke zmail with argument arrays (or careful quoting). Never paste untrusted mail text or chat content into a sh -c "zmail …" string—command-injection risk.

OpenClaw parses metadata.openclaw.requires per Creating skills: bins = executables expected on PATH (zmail exists only after the global install step). config lists environment variables this workflow expects for a configured mailbox (mirror the same in ClawHub package metadata if the UI has separate fields).


Agent checklist

  1. Confirm Node.js 20+ (node -v).
  2. npm install -g @cirne/zmail (see Install).
  3. Choose setup: zmail wizard (TTY) or zmail setup (flags/env, no prompts).
  4. User must have a Gmail app password (or compatible IMAP credentials)—Gmail: app password.
  5. Run zmail sync --since … then zmail refresh / zmail status.
  6. Learn the CLI from the CLI: run zmail, zmail --help, and zmail <command> --help. Read any hint (and truncation fields) in JSON output—zmail uses them to disclose the next capability (Canonical docs & discovery).
  7. For questions over mail, prefer zmail ask first; use search / read / thread / who / attachment when you need fine control (Ask vs primitives).
  8. Never paste secrets into chat logs; use env or flags in the user’s shell.

Install

node -v   # must be v20+
npm install -g @cirne/zmail
  • If better-sqlite3 fails to load (wrong Node ABI), the CLI may rebuild automatically on first run; if not, run npm rebuild better-sqlite3 using the same node binary that runs zmail.
  • Global install note: npm may install to a directory that is not on PATH; ensure that global bin is on PATH, or use npx @cirne/zmail for one-off commands.

Config and data default to ZMAIL_HOME (default ~/.zmail): config.json, .env, and data/ (SQLite + maildir).


Gmail: get an app password

Gmail does not allow normal account passwords for IMAP clients. Use a 16‑character app password.

  1. Turn on 2‑Step Verification (required):
    Google Account → Security → 2‑Step Verification
  2. Create an app password (sign in with Google account):
    App passwords
    • Choose app: Mail (or Other and name it zmail).
    • Google shows a 16‑character password (often shown in groups; enter without spaces).
  3. Use full Gmail address as IMAP user (e.g. you@gmail.com) and the app password as ZMAIL_IMAP_PASSWORD / --password.

If app passwords are disabled (workspace policy, account type), the user must use whatever IMAP credentials their admin allows.


zmail wizard (interactive humans)

  • When: Real terminal with TTY; user is present to answer prompts.
  • Run: zmail wizard
    Optional: --no-validate (skip live IMAP/OpenAI checks), --clean (wipe local config + cached mail under ZMAIL_HOME; IMAP unchanged; may prompt unless --yes).
  • If stdin is not a TTY (agents, CI, pipes): wizard exits with a message to use zmail setup instead.
  • Wizard walks through email, IMAP app password, OpenAI key, default sync window, and can start background sync at the end.

zmail setup (agents & automation)

Non-interactive. No prompts when all inputs are provided via flags and/or environment variables.

Required today (all three):

InputFlagEnvironment variable
Email (IMAP user)--emailZMAIL_EMAIL
IMAP password (e.g. Gmail app password)--passwordZMAIL_IMAP_PASSWORD
OpenAI API key--openai-keyZMAIL_OPENAI_API_KEY or OPENAI_API_KEY

Examples:

zmail setup \
  --email 'user@gmail.com' \
  --password 'abcdefghijklmnop' \
  --openai-key 'sk-...'
export ZMAIL_EMAIL='user@gmail.com'
export ZMAIL_IMAP_PASSWORD='abcdefghijklmnop'
export ZMAIL_OPENAI_API_KEY='sk-...'
zmail setup

Optional flags:

FlagMeaning
--no-validateSkip IMAP and OpenAI validation (faster/offline-ish write of config only).
--default-since <spec>Default sync window in config (e.g. 7d, 1y). Default if omitted: 1y.
--clean --yesDelete existing config.json, .env, and data/ under ZMAIL_HOME, then write new config. Local only—IMAP mailbox unchanged; resync rebuilds the index/cache.

If any required value is missing, zmail setup prints what’s missing and exits—fix env/flags and retry.

OpenAI key: Required for zmail setup / zmail wizard as shipped. It is stored in ~/.zmail/.env. Same key powers zmail ask, zmail inbox, and related features. Search/read/thread/who/attachment do not need the API at query time once mail is indexed.


Secrets and files (after setup)

Secret / fileRequired?Purpose
ZMAIL_IMAP_PASSWORD in .envYes (for sync)IMAP login (Gmail app password).
ZMAIL_OPENAI_API_KEY (or OPENAI_API_KEY) in .envYes at setup; yes for ask / inboxLLM features.
config.jsonYesNon-secret: IMAP host/port/user, sync defaults (no password in this file).
ZMAIL_HOMEOptionalOverride config root (default ~/.zmail).

Security: Treat .env like credentials—don’t commit it, don’t paste into tickets or agent transcripts. Rotate app passwords if exposed.


First sync and daily use

zmail sync --since 30d    # initial backfill (often runs in background; note log path on stdout)
zmail refresh             # fetch new mail since last sync
zmail status              # local sync + index health
zmail ask "your question" # one-shot NL answer (OpenAI); good default for agents
zmail search 'query'      # FTS hits (JSON default; --text for tables)
  • Long sync: Safe to run in background; use zmail status and the sync log file path the CLI prints.
  • Refresh is the habitual “get new mail” command after the first sync.

zmail ask vs primitives

zmail ask "<question>" runs zmail’s answer pipeline in one go: it figures out how to search and pull the right messages, then synthesizes a complete answer for the user. For the calling agent, that usually means fewer steps and a ready-made summary—best when the goal is “answer this question about my mail” rather than “give me raw hits.” Requires ZMAIL_OPENAI_API_KEY (or OPENAI_API_KEY). Optional --verbose if you need to trace what it did.

Primitives (search, read, thread, who, attachment list / attachment read) expose structured, explicit steps: you choose the query, which message IDs to open, whether you need full body or raw, threads, contacts, or extracted attachment text. They do not call OpenAI for the core path—good for scripts, tight filters, verbatim quotes, debugging, or when the outer agent wants to own the reasoning and token budget.

Prefer zmail askPrefer primitives
Broad or fuzzy questions (“what did X say about the launch?”)Exact filters, known IDs, pagination
You want a single synthesized answer quicklyYou need every matching row or full message bodies
User asked in natural language and doesn’t care about IDsAttachments, EML/raw, or who / address-book style lookups

Rule of thumb: Start with ask. If the answer is too shallow, wrong, or you need more detail or accuracy, switch to searchread / thread (and attachment when documents matter). Combine both: e.g. ask for orientation, then read on specific message_ids from search if you must verify.

Full tradeoffs and hybrid patterns: docs/ASK.md at the package/repo root (paths in references/CANONICAL-DOCS.md).


Install this skill folder (hosts)

Copy the zmail directory (this skill) into an end-user location—not into the zmail source repo’s .cursor/skills/ (those are dev-only).

HostTypical path
Cursor~/.cursor/skills/zmail/ or another project’s .cursor/skills/zmail/
Claude Code~/.claude/skills/zmail/
OpenClaw<workspace>/skills/zmail/, ~/.openclaw/skills/zmail/, or from this repo: npm run install-skill:openclaw (OpenClaw creating skills)

Folder name must stay zmail to match frontmatter name (Agent Skills spec). Copy the whole skills/zmail/ directory (includes references/).

OpenClaw: heartbeat + fresh mail

For OpenClaw, use a heartbeat (not a separate cron per mailbox tick) for periodic “anything new in email?” awareness—OpenClaw’s own guide recommends heartbeat for inbox-style checks because it batches with other routine work and can suppress noise when nothing matters. See Cron vs heartbeat and Heartbeat (interval, HEARTBEAT.md, HEARTBEAT_OK, agents.defaults.heartbeat, etc.).

Put zmail on the workspace HEARTBEAT.md checklist, for example:

  1. Ingest new mail: run zmail refresh (forward IMAP sync into the local index), or use zmail inbox <window> --refresh so the forward sync runs immediately before the scan (same sync path as refresh; optional --force if you need to skip STATUS fast-path—see zmail inbox --help).
  2. Surface what’s worth attention: run zmail inbox over a window (e.g. 24h, 3d, or your inbox.defaultWindow in config.json) so the LLM returns notable recent mail in JSON (newMail, …). Requires ZMAIL_OPENAI_API_KEY (or OPENAI_API_KEY). Use --text if you want a human-readable digest. Add --include-noise only if marketing/social should count as “notable.”
  3. If nothing needs a human ping, answer HEARTBEAT_OK so OpenClaw drops the turn quietly (per Heartbeat docs).

Cost / habit: refresh alone does not call OpenAI; inbox does. Keep the checklist short; widen the inbox window only when needed.


More detail

  • references/CANONICAL-DOCS.mdCLI-first discovery (zmail, --help, per-command help), hints in output, and a table of canonical markdown (AGENTS.md, docs/VISION.md, docs/ASK.md, docs/ARCHITECTURE.md, docs/MCP.md, OPP-025).

Comments

Loading comments...