A simple CLI for agents to send emails. Supports AgentMail, Google Workspace, Proton Mail, and generic SMTP.
curl -fsSL https://raw.githubusercontent.com/tnm/email-cli/main/email/install.sh | bashInstalls email-cli into ~/.local/bin by default. If that directory is not on your PATH:
export PATH="$HOME/.local/bin:$PATH"Or install from a local checkout:
git clone https://github.com/tnm/email-cli
cd email-cli/email
./install.shgo install github.com/tnm/email-cli@latestOr build from source:
git clone https://github.com/tnm/email-cli
cd email-cli/email
go build -o email-cli .Install as a Claude Code plugin for AI agent access:
# Add the marketplace
/plugin marketplace add tnm/email-cli
# Install the plugin
/plugin install email-cli@email-cli
# Or load locally during development
claude --plugin-dir /path/to/email-cliOnce installed, Claude automatically uses email-cli when you ask it to send emails.
# Add a provider (interactive)
email-cli config add mymail
# Send an email
email-cli send -t recipient@example.com -s "Hello" -m "Message body"Config is stored at ~/.config/email-cli/config.json
email-cli follows a pragmatic local-file security model:
- Secrets are stored in plaintext in
~/.config/email-cli/config.jsonby default. - On macOS, you can use
--use-keychainto store secrets in macOS Keychain instead. - File permissions are restricted to owner-only (
0600) when writing config. email-cli config showredacts secrets by default.email-cli config show --show-secretsprints raw secrets and should be treated as sensitive.
On macOS, you can store secrets in the system Keychain instead of the config file:
# Store credentials in Keychain when adding a provider
email-cli config add --name agent \
--type agentmail \
--api-key "am_..." \
--inbox-id "myagent@agentmail.to" \
--use-keychain
# Update a secret and store in Keychain
email-cli config set --use-keychain mymail password "new-password"When using Keychain, the config file stores a reference like keychain:mymail/password instead of the actual secret. The secret is resolved from Keychain at runtime.
Benefits:
- Secrets never appear in the config file
- Protected by macOS Keychain security (Touch ID, password, etc.)
- Secrets survive config file inspection
Note: Keychain support is only available on macOS.
- Avoid passing secrets directly on command lines when possible (
--api-key,--password,--access-token,--refresh-token) because shell history and process inspection may expose them. - Use
--use-keychainon macOS for sensitive credentials. - Prefer app-specific passwords for SMTP providers (for Gmail, use an App Password).
- Rotate credentials immediately if a machine, shell history, or agent transcript is exposed.
- For install safety, prefer reviewing
install.shfrom a pinned version tag before running it.
email-cli config add mymailWalks you through provider selection and credential entry.
email-cli config add --name agent \
--type agentmail \
--api-key "am_..." \
--inbox-id "myagent@agentmail.to" \
--defaultNo OAuth, no app passwords, no local servers. Just an API key from agentmail.to. Free tier: 3 inboxes, 3k emails/month.
email-cli config add --name gmail-smtp \
--type smtp \
--from me@gmail.com \
--host smtp.gmail.com \
--port 587 \
--username me@gmail.com \
--password "$GMAIL_APP_PASSWORD" \
--tls \
--defaultUse this when you want the fastest setup for humans and agents. It avoids Google Cloud OAuth client setup.
email-cli config add --name mymail \
--type smtp \
--from me@example.com \
--host smtp.example.com \
--port 587 \
--username me@example.com \
--password "secret" \
--tlsemail-cli config add --name proton \
--type proton \
--from me@proton.me \
--username me@proton.me \
--password "bridge-password"email-cli config add --name google \
--type google \
--from me@gmail.com \
--client-id "xxx.apps.googleusercontent.com" \
--client-secret "xxx"By default this starts OAuth device flow and prints a verification URL/code in your terminal. To force localhost callback flow instead:
email-cli config add --name google \
--type google \
--from me@gmail.com \
--client-id "xxx.apps.googleusercontent.com" \
--client-secret "xxx" \
--oauth-method local# List providers
email-cli config list
# Show config as JSON (useful for agents)
email-cli config show # full config (secrets redacted)
email-cli config show mymail # specific provider (secrets redacted)
email-cli config show --show-secrets # include secrets/tokens
email-cli config show --show-secrets mymail
# Set individual values
email-cli config set mymail password "new-password"
email-cli config set mymail host smtp.newserver.com
# Set default provider
email-cli config default mymail
# Remove provider
email-cli config remove mymail
# Show config file path
email-cli config path| Provider | Available Keys |
|---|---|
| AgentMail | api-key, inbox-id |
| SMTP | from, host, port, username, password, tls |
| Proton | from, host, port, username, password |
from, client-id, client-secret, access-token, refresh-token |
email-cli send -t user@example.com -s "Subject" -m "Body"| Flag | Short | Description |
|---|---|---|
--to |
-t |
Recipient(s) - required, repeatable |
--subject |
-s |
Subject line - required |
--body |
-m |
Message body |
--cc |
-c |
CC recipient(s) |
--bcc |
-b |
BCC recipient(s) |
--attach |
-a |
File attachment(s) |
--html |
Treat body as HTML | |
--provider |
-p |
Use specific provider |
# Multiple recipients
email-cli send -t a@example.com -t b@example.com -s "Team Update" -m "Hello team"
# With CC/BCC
email-cli send -t user@example.com -c cc@example.com -b bcc@example.com -s "Subject" -m "Body"
# HTML email
email-cli send -t user@example.com -s "Newsletter" -m "<h1>Hello</h1><p>World</p>" --html
# Attachments
email-cli send -t user@example.com -s "Report" -m "See attached" -a report.pdf -a data.csv
# Read body from stdin
cat message.txt | email-cli send -t user@example.com -s "From file"
echo "Quick message" | email-cli send -t user@example.com -s "Piped"
# Use specific provider
email-cli send -p work -t user@example.com -s "Subject" -m "Body"AgentMail is email infrastructure designed for AI agents. No OAuth, no app passwords, no local servers — just an API key.
- Sign up at agentmail.to
- Create an API key in the console
- Create an inbox (or use the API to create one)
- Configure:
email-cli config add --name agent \
--type agentmail \
--api-key "am_..." \
--inbox-id "myagent@agentmail.to" \
--defaultFree tier: 3 inboxes, 3,000 emails/month, no credit card required.
Note: You'll send from @agentmail.to addresses unless you add a custom domain (paid plans).
Use Gmail over SMTP with an App Password.
- Turn on Google 2-Step Verification.
- Create an App Password at Google App Passwords.
- Configure
email-cli:
email-cli config add --name gmail-smtp \
--type smtp \
--from me@gmail.com \
--host smtp.gmail.com \
--port 587 \
--username me@gmail.com \
--password "YOUR_APP_PASSWORD" \
--tls \
--defaultNotes:
- This is the simplest path for agent-driven setup.
- Agents cannot create App Passwords for users; the user must do that account-security step once.
Uses Gmail API with OAuth2.
email-cli defaults to OAuth device flow for Google setup, so you do not need a localhost callback server in the common case.
This path requires Google Cloud OAuth project setup.
- Create a project in Google Cloud Console
- Enable the Gmail API
- Create OAuth2 credentials (Desktop app type)
- Run
email-cli config add googleand complete device auth in terminal - Optional for local callback mode: add
http://127.0.0.1:8089/callbackto authorized redirect URIs and run with--oauth-method local
If you already have tokens, you can set them directly:
email-cli config add --name google \
--type google \
--from me@gmail.com \
--client-id "YOUR_CLIENT_ID" \
--client-secret "YOUR_CLIENT_SECRET" \
--access-token "YOUR_ACCESS_TOKEN" \
--refresh-token "YOUR_REFRESH_TOKEN"Uses Proton Mail Bridge which runs a local SMTP server.
- Install and run Proton Mail Bridge
- Get the bridge password from Bridge settings (not your account password)
- Configure:
# Interactive
email-cli config add proton
# Non-interactive
email-cli config add --name proton \
--type proton \
--from me@proton.me \
--username me@proton.me \
--password "BRIDGE_PASSWORD"Default bridge address: 127.0.0.1:1025
Works with any SMTP server: SendGrid, Mailgun, Fastmail, AWS SES, etc.
# Interactive
email-cli config add smtp
# Non-interactive (SendGrid example)
email-cli config add --name sendgrid \
--type smtp \
--from me@example.com \
--host smtp.sendgrid.net \
--port 587 \
--username apikey \
--password "SG.xxxx" \
--tlsThis CLI is designed to be easily used by AI agents and automation.
Use this order when helping users configure email:
- AgentMail first — easiest, just needs API key + inbox ID
- For existing email accounts, try SMTP
- For Gmail, prefer
smtp.gmail.com+ App Password - Use Google API only if the user explicitly wants Gmail API/OAuth features
- Use Proton Bridge only when the user is on Proton Mail
- Check for an existing provider:
email-cli config list- If no provider exists, recommend AgentMail for simplest setup:
email-cli config add --name agent \
--type agentmail \
--api-key "am_..." \
--inbox-id "myagent@agentmail.to" \
--default- Or for existing email, collect SMTP details and configure:
email-cli config add --name agent-mail \
--type smtp \
--from "$EMAIL_FROM" \
--host "$SMTP_HOST" \
--port "$SMTP_PORT" \
--username "$SMTP_USER" \
--password "$SMTP_PASS" \
--default- Send:
email-cli send -t "$TO" -s "$SUBJECT" -m "$BODY"The easiest way to use email-cli with Claude Code:
/plugin marketplace add tnm/email-cli
/plugin install email-cli@email-cliClaude will automatically invoke the email skill when you ask it to send emails. The skill includes full documentation so Claude knows all available options.
# Predictable, scriptable
email-cli send -t "$TO" -s "$SUBJECT" -m "$BODY"
# Exit codes: 0 = success, non-zero = failure
email-cli send -t user@example.com -s "Test" -m "Hello" && echo "Sent!"# Pipe generated content
echo "$GENERATED_REPORT" | email-cli send -t user@example.com -s "Daily Report"
# From files
cat analysis.txt | email-cli send -t user@example.com -s "Analysis Results"# Set up without prompts
email-cli config add --name agent-mail \
--type smtp \
--from agent@example.com \
--host smtp.example.com \
--port 587 \
--username agent@example.com \
--password "$SMTP_PASSWORD" \
--default
# Update credentials programmatically
email-cli config set agent-mail password "$NEW_PASSWORD"# Get config as JSON for parsing (secrets are redacted by default)
email-cli config show
email-cli config show agent-mail
# Include secrets/tokens only when needed
email-cli config show --show-secrets agent-mailYou can use environment variables in scripts:
email-cli config add --name mymail \
--type smtp \
--from "$EMAIL_FROM" \
--host "$SMTP_HOST" \
--port "$SMTP_PORT" \
--username "$SMTP_USER" \
--password "$SMTP_PASS"~/.config/email-cli/config.json:
{
"default_provider": "agent",
"providers": {
"agent": {
"type": "agentmail",
"name": "agent",
"agentmail": {
"api_key": "am_...",
"inbox_id": "myagent@agentmail.to"
}
},
"work": {
"type": "google",
"name": "work",
"from": "me@company.com",
"google": {
"client_id": "...",
"client_secret": "...",
"access_token": "...",
"refresh_token": "...",
"token_expiry": "2024-01-01T00:00:00Z"
}
},
"personal": {
"type": "smtp",
"name": "personal",
"from": "me@fastmail.com",
"smtp": {
"host": "smtp.fastmail.com",
"port": 587,
"username": "me@fastmail.com",
"password": "app-password",
"use_tls": true
}
}
}
}| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Error (config, auth, send failure, etc.) |
MIT