zele
Every time you use zele, you MUST fetch the latest README:
curl -s https://raw.githubusercontent.com/remorses/zele/main/README.md # NEVER pipe to head/tail, read the full output
Then run the CLI help once — it already includes every subcommand, option, and flag:
zele --help # NEVER pipe to head/tail, read the full output
The README and zele --help output are the source of truth for commands, options, flags, the Google vs IMAP feature matrix, search operators, and the headless login flow.
Rules
- Never use the TUI. Running
zele with no subcommand launches a human-facing TUI. Agents must use the CLI subcommands (zele mail list, zele cal events, etc.) which output structured YAML.
- Always run
zele whoami first when the user asks to operate on a specific account. Pick the exact email from the output and pass it with --account. Never guess account emails.
- Never truncate
--help or README output with head, tail, sed, awk, or less. Critical rules are spread throughout. Read them in full.
- Parse YAML output with
yq, not regex. Pipe IDs through xargs for bulk actions. Always use --limit 100 (or higher) so you don't miss threads:# read all unread emails
zele mail list --filter "is:unread" --limit 100 | yq '.[].id' | xargs zele mail read
# bulk archive
zele mail list --filter "is:unread" --limit 100 | yq '.[].id' | xargs zele mail archive
- Google-only features (labels, Gmail filters,
zele cal *, full profile) fail on IMAP accounts with a clear error. Check zele whoami output for account type before using them.
- Headless Google login requires a tmux wrapper because
zele login is interactive. See the README "Remote / headless login" section for the exact pattern.
- Waiting for emails with
zele mail watch. It polls for new emails matching a filter and exits as soon as one arrives. Use this to wait for replies, verification codes, or any expected email:# wait for a reply from alice (no timeout, blocks until match)
zele mail watch --filter "is:unread from:alice@example.com"
# wait for a verification code with a 5-minute timeout
zele mail watch --filter "is:unread subject:verification" --timeout 300
# send an email then wait for the reply
zele mail send --to bob@example.com --subject "Question" --body "Hey, can you check this?"
zele mail watch --filter "is:unread from:bob@example.com subject:Re:Question" --timeout 600
If the matched email wasn't the expected one, call zele mail watch again with a more specific filter. Exit code 0 means a match was found, exit code 1 means timeout.
- Check reply recipients before sending with
zele mail reply <thread-id> --dry-run. Recipients are inferred from the thread, not from the sender of the last message, so a thread whose last message you sent still replies to the other person. If a reply would only reach the account's own address, zele refuses to send:# see to / cc / subject / In-Reply-To without sending
zele mail reply <thread-id> --dry-run
# override the inferred recipient
zele mail reply <thread-id> --to paul@acme.com --body "..."
# deliberately reply to yourself (normally refused)
zele mail reply <thread-id> --allow-self --body "..."
Never work around a SelfRecipientError by switching to zele mail send; pass --to to zele mail reply instead, so threading headers stay correct.
- Read a thread before replying.
zele mail reply and zele mail send --thread-id fail with UnseenLatestError unless zele mail read <thread-id> already showed the live last message. mail watch and mail list do not count. If a new reply arrives after you read, read again before sending:zele mail read <thread-id>
zele mail reply <thread-id> --body "..."
Never pass --force to skip this unless the user explicitly asks to send without reading.
- Send into an existing thread with
zele mail send --thread-id <thread-id> when you need full control of recipients and subject but still want correct In-Reply-To/References headers. Recipients and subject are inferred from the thread when omitted. The same read-before-reply rule applies.
1---2name: zele3description: zele is a multi-account email and calendar CLI for Gmail, IMAP/SMTP (Fastmail, Outlook, any provider), and Google Calendar. It reads, searches, sends, replies, forwards, archives, stars, and trashes emails, manages drafts, labels, attachments, and Gmail filters, and creates, updates, and deletes calendar events with RSVP and free/busy support. Output is YAML so commands can be piped through yq and xargs. ALWAYS load this skill when the user asks to check email, read/send messages, reply or forward, archive or trash threads, manage drafts or labels, download attachments, schedule meetings, check their calendar, RSVP to events, or when they run any `zele` command. Load it before writing any code or shell commands that touch zele so you know the correct subcommand structure, the Google vs IMAP feature matrix, the headless login flow, and the agent-specific rules.4---56# zele78Every time you use zele, you MUST fetch the latest README:910```bash11curl -s https://raw.githubusercontent.com/remorses/zele/main/README.md # NEVER pipe to head/tail, read the full output12```1314Then run the CLI help once — it already includes every subcommand, option, and flag:1516```bash17zele --help # NEVER pipe to head/tail, read the full output18```1920The README and `zele --help` output are the source of truth for commands, options, flags, the Google vs IMAP feature matrix, search operators, and the headless login flow.2122## Rules23241. **Never use the TUI.** Running `zele` with no subcommand launches a human-facing TUI. Agents must use the CLI subcommands (`zele mail list`, `zele cal events`, etc.) which output structured YAML.252. **Always run `zele whoami` first** when the user asks to operate on a specific account. Pick the exact email from the output and pass it with `--account`. Never guess account emails.263. **Never truncate `--help` or README output** with `head`, `tail`, `sed`, `awk`, or `less`. Critical rules are spread throughout. Read them in full.274. **Parse YAML output with `yq`**, not regex. Pipe IDs through `xargs` for bulk actions. Always use `--limit 100` (or higher) so you don't miss threads:28 ```bash29 # read all unread emails30 zele mail list --filter "is:unread" --limit 100 | yq '.[].id' | xargs zele mail read3132 # bulk archive33 zele mail list --filter "is:unread" --limit 100 | yq '.[].id' | xargs zele mail archive34 ```355. **Google-only features** (labels, Gmail filters, `zele cal *`, full profile) fail on IMAP accounts with a clear error. Check `zele whoami` output for account type before using them.366. **Headless Google login** requires a tmux wrapper because `zele login` is interactive. See the README "Remote / headless login" section for the exact pattern.377. **Waiting for emails** with `zele mail watch`. It polls for new emails matching a filter and exits as soon as one arrives. Use this to wait for replies, verification codes, or any expected email:38 ```bash39 # wait for a reply from alice (no timeout, blocks until match)40 zele mail watch --filter "is:unread from:alice@example.com"4142 # wait for a verification code with a 5-minute timeout43 zele mail watch --filter "is:unread subject:verification" --timeout 3004445 # send an email then wait for the reply46 zele mail send --to bob@example.com --subject "Question" --body "Hey, can you check this?"47 zele mail watch --filter "is:unread from:bob@example.com subject:Re:Question" --timeout 60048 ```49 If the matched email wasn't the expected one, call `zele mail watch` again with a more specific filter. Exit code 0 means a match was found, exit code 1 means timeout.508. **Check reply recipients before sending** with `zele mail reply <thread-id> --dry-run`. Recipients are inferred from the thread, not from the sender of the last message, so a thread whose last message you sent still replies to the other person. If a reply would only reach the account's own address, zele refuses to send:51 ```bash52 # see to / cc / subject / In-Reply-To without sending53 zele mail reply <thread-id> --dry-run5455 # override the inferred recipient56 zele mail reply <thread-id> --to paul@acme.com --body "..."5758 # deliberately reply to yourself (normally refused)59 zele mail reply <thread-id> --allow-self --body "..."60 ```61 Never work around a `SelfRecipientError` by switching to `zele mail send`; pass `--to` to `zele mail reply` instead, so threading headers stay correct.629. **Read a thread before replying.** `zele mail reply` and `zele mail send --thread-id` fail with `UnseenLatestError` unless `zele mail read <thread-id>` already showed the live last message. `mail watch` and `mail list` do **not** count. If a new reply arrives after you read, read again before sending:63 ```bash64 zele mail read <thread-id>65 zele mail reply <thread-id> --body "..."66 ```67 Never pass `--force` to skip this unless the user explicitly asks to send without reading.6810. **Send into an existing thread** with `zele mail send --thread-id <thread-id>` when you need full control of recipients and subject but still want correct `In-Reply-To`/`References` headers. Recipients and subject are inferred from the thread when omitted. The same read-before-reply rule applies.