Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

selfmail

Email yourself from any shell or AI agent — one tiny command, over Resend.

uvx selfmail "the build is green"

selfmail sends an email to a pre-configured "me" address with no ceremony. It runs anywhere — your laptop, a cron job, a cloud runner, or an AI agent — with no GUI and no local mail server. After a one-time selfmail init, sending is a single command.


Install

selfmail is a single pure-Python package on PyPI. The zero-install path is best:

uvx selfmail "hello"                       # run without installing (recommended)
uv tool install selfmail                   # install the `selfmail` command on PATH
pipx install selfmail                       # same, via pipx

For the MCP server, pull the optional extra:

uvx --from 'selfmail[mcp]' selfmail mcp
uv tool install 'selfmail[mcp]'

Requires Python 3.11+.

Quick start

selfmail init      # paste a Resend API key once — it emails you a test message
selfmail "done"    # send yourself a note

init deep-links you to the Resend create-key page, captures the key without echoing it, and proves the whole pipeline by emailing you on the spot — no DNS setup needed (Resend's shared sender delivers to your own account address).


Commands

selfmail [body]     send an email (this is the default command)
selfmail init       configure: paste a Resend key, get a test email
selfmail doctor     check configuration without sending
selfmail mcp        run an MCP server exposing a send_email tool
selfmail --version  print the version

Run selfmail <command> --help for a command's options.

selfmail [body] — send

The default command. With no subcommand, selfmail sends an email.

selfmail [-s SUBJECT] [-a FILE]... [--html] [--to TO] [--from SENDER] [-q] [body]
Argument / flag Description
body The message body. Optional — if omitted and stdin is not a TTY, the body is read from stdin. If neither is given, the body is (no body).
-s, --subject TEXT Subject line. Default: a timestamp like selfmail 2026-06-16 14:05.
-a, --attach FILE Attach a file. Repeatable: -a a.pdf -a b.png.
--html Treat the body as HTML (sets the HTML part instead of plain text).
--to ADDR Override the configured recipient for this send.
--from ADDR Override the configured sender for this send.
-q, --quiet Suppress the sent → … success line.

On success it prints sent → you@example.com (id <message-id>) and exits 0.

Examples

selfmail -s "build finished" "all green on main"      # subject + inline body
echo "$(tail -50 build.log)" | selfmail -s "log tail"  # body from stdin (pipe)
some-command 2>&1 | selfmail -s "cron output"          # capture a command's output
selfmail -s "the report" -a report.html "see attached" # with an attachment
selfmail --html "<h1>Shipped</h1><p>v1.2 is live.</p>"  # HTML body
selfmail --to ops@example.com "heads up"               # one-off different recipient
selfmail -q "silent ping"                              # no stdout on success

selfmail init — configure

Interactive first-run setup. Resend has no OAuth or programmatic key provisioning, so the key is minted in your dashboard and pasted in — init makes that one step painless.

selfmail init [--force] [--domain]
Flag Description
--force Reconfigure even if a working config already exists.
--domain Also print the steps to verify your own sending domain.

What it does:

  1. If you're already configured and the key authenticates, it says so and exits (unless --force).
  2. Deep-links you to https://resend.com/api-keys?new=true (opens the create-key dialog directly), and tells you to create a key with Sending access.
  3. Reads the key with no echo (never shown, never stored in shell history).
  4. Asks for your email — where selfmail should send.
  5. Sends a real test email from the shared sender to that address (works with no domain), which both validates the key and proves delivery. A bad key re-prompts; nothing is saved until a send succeeds.
  6. Asks which address to send from. There is no silent default: you either accept the shared onboarding@resend.dev (self-only) or enter your own verified-domain sender.
  7. Writes the config file with 0600 permissions.

selfmail doctor — check configuration

Validates the resolved configuration without sending. Prints a summary and exits 0 if usable, 2 otherwise. Never prints the secret.

$ selfmail doctor
backend:   resend
from:      onboarding@resend.dev
to:        you@example.com
api key:   present
auth:      ok
config:    /Users/you/.config/selfmail/config.toml

selfmail mcp — MCP server

Runs a Model Context Protocol server over stdio, exposing a single tool so AI agents can email you directly. Requires the mcp extra (selfmail[mcp]); without it, the command exits 2 with an install hint.

uvx --from 'selfmail[mcp]' selfmail mcp

Tool:

send_email(subject: str, body: str, to?: str, html?: bool) -> {"id": str, "to": str}

It uses the same configuration as the CLI — no separate setup.


Configuration

Values are resolved in this order (highest priority first):

command-line flag → environment variable → config file → built-in default

Config file

Written by selfmail init to ~/.config/selfmail/config.toml (or $XDG_CONFIG_HOME/selfmail/config.toml), with mode 600:

to   = "you@example.com"
from = "onboarding@resend.dev"

[resend]
api_key = "re_xxx"

Environment variables

For CI, cron, or cloud boxes, skip the file entirely and set:

Variable Maps to
RESEND_API_KEY the Resend API key
SELFMAIL_TO the recipient ("me")
SELFMAIL_FROM the sender — required (there is no built-in default; init sets it)
SELFMAIL_CONFIG full path to an alternate config file
export RESEND_API_KEY=re_...
export SELFMAIL_TO=you@example.com
selfmail "from CI"

Sending to addresses other than yourself

Resend's shared sender, onboarding@resend.dev, only delivers to your own Resend account address — which is all "email myself" needs, and what init offers by default. To send from your own domain (and to anyone), verify a domain in Resend and set from accordingly. If your DNS is on Cloudflare, selfmail init --domain points you at Resend's one-click Cloudflare integration, which auto-creates the MX/SPF/DKIM records.

Exit codes

Code Meaning
0 Success.
1 The send failed (network error, or Resend rejected the message).
2 Configuration or usage error (no key, bad flag, missing recipient, unreadable attachment).

For agents

selfmail is built to be driven by AI agents two ways:

  • As a shell command — any agent that can run a shell can selfmail -s "…" "…".
  • As an MCP serverselfmail mcp exposes the send_email tool over stdio.

Because it reads config from the environment, an agent in a headless sandbox just needs RESEND_API_KEY and SELFMAIL_TO set to start emailing you.

Agent skill

There's a ready-made agent skill so coding agents (Claude Code, etc.) discover and use selfmail automatically — it bundles the invocation, usage patterns, exit codes, and gotchas:

npx skills add alltuner/skills --skill selfmail

See alltuner/skills (the skill lives at skills/selfmail/SKILL.md).

Development

uv sync                 # install deps (incl. dev group)
uv run ruff check .     # lint
uv run ruff format .    # format
uv run ty check         # type-check
uv run pytest           # tests (unit tests mock the Resend SDK boundary)

There's an opt-in end-to-end test that sends a real email — skipped unless you provide real credentials:

SELFMAIL_LIVE_TEST=1 RESEND_API_KEY=re_... SELFMAIL_LIVE_TO=you@example.com \
SELFMAIL_FROM=you@yourdomain.com uv run pytest -k live

License

MIT

About

Email yourself from any shell or AI agent — one tiny command over Resend. CLI + MCP.

Topics

Resources

Code of conduct

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages