← back to Claude Mail

README.md

65 lines

# claude-mail

A back-and-forth **email channel for Claude** at `claude@agentabrams.com`.
Steve (or an allowlisted person) emails the address; a local poller reads it,
runs `claude` headless on this Mac with full local access, and replies in-thread.
Reply to the reply → it keeps the conversation going.

## How it works

```
sender ──▶ claude@agentabrams.com (Purelymail mailbox)
              │  IMAP (imap.purelymail.com)
              ▼
        poller.js  ──▶ [ SENDER GATE ]  ──▶ runClaude(-p)  ──▶ SMTP reply in-thread
                         3 locks, all required          (Max-plan auth, local tools)
```

### The sender gate — 3 independent locks (all must pass)
1. **Allowlist** — `From` must be one of `ALLOWED_SENDERS`.
2. **Secret phrase** — the subject must contain `[ok:<SECRET_PHRASE>]` (or the bare phrase).
3. **Email auth** — inbound mail must pass DKIM/DMARC/SPF (anti-spoof), unless `REQUIRE_AUTH_PASS=false`.

Anything failing the gate is **silently ignored** (marked read, no reply, no `claude` run).
Strangers get total silence and never reach the machine.

### Autonomy rails (injected into every run via `--append-system-prompt`)
- Safe / reversible / local / read-only work runs directly and is reported.
- **Gated** actions (prod writes, sends to third parties, DNS, spend, deletes,
  customer-facing, remote pushes) are **NOT executed** — Claude describes the plan
  and asks for a "go". Default `CLAUDE_PERMISSION_MODE=acceptEdits` also keeps the
  headless run from running unattended `Bash` (Read/Grep/Glob/Edit/Write still work).

## Files
- `poller.js` — one poll pass (run on an interval by launchd). Idempotent.
- `lib.js` — config, sender gate, quote-stripping, claude runner, mailer.
- `send.js` — one-off sender: `node --env-file=.env send.js <to> "<subj>" < body.txt`.
- `imap-check.js` — read-only connectivity check (no claude, no send).
- `run.sh` — wrapper used by the LaunchAgent.
- `.env` — secrets + config (gitignored).
- `~/Library/LaunchAgents/com.steve.claude-mail.plist` — the scheduler (every 120s).

## Activate the always-on poller
```sh
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.steve.claude-mail.plist
launchctl kickstart -k gui/$(id -u)/com.steve.claude-mail   # run once now
```
Stop / disable:
```sh
launchctl bootout gui/$(id -u)/com.steve.claude-mail
```
Logs: `tail -f ~/Projects/claude-mail/poller.log`

## Manual run (no scheduler)
```sh
cd ~/Projects/claude-mail && ./run.sh        # one pass
node --env-file=.env imap-check.js           # read-only inbox peek
```

## Tuning
- **Allowlist / phrase** — edit `.env` (`ALLOWED_SENDERS`, `SECRET_PHRASE`).
- **Let it run Bash unattended** — set `CLAUDE_PERMISSION_MODE=bypassPermissions`
  (more capable, more risk; the gate + rails are then the only guardrails).
- **Deliverability** — `agentabrams.com` may need DKIM enabled (Purelymail +
  Cloudflare DNS) so replies don't land in spam. Gated DNS change — do separately.