Email interface for TaskYou. Send emails to create tasks, reply to provide input, receive status updates.
# Build
cd extensions/ty-email
go build -o ty-email ./cmd
# Setup (interactive wizard)
./ty-email init
# Run
./ty-email serve- You email
yourname+ty@gmail.comfrom your phone/computer - Gmail filter routes it to a
ty-emaillabel - ty-email polls that label via IMAP
- Claude classifies your intent (create task, provide input, query status)
- ty-email executes the appropriate
tycommand - You get a reply email with confirmation
You ──email──▶ Gmail ──IMAP──▶ ty-email ──▶ Claude (classify)
│
▼
ty CLI (execute)
│
▼
You ◀──reply── Gmail ◀──SMTP── ty-email
Run the interactive wizard:
./ty-email initThis walks you through:
- Gmail address - Your email, generates a
+tyalias for tasks - App password - Create one at https://myaccount.google.com/apppasswords
- Gmail filter - Routes emails to the
ty-emaillabel - Claude API key - For intent classification
- TaskYou CLI - Path to
tybinary
The wizard explains this, but here's the summary:
- Go to Gmail Settings > Filters
- Create filter:
To: yourname+ty@gmail.com - Actions: Skip Inbox, Apply label
ty-email
Now emails to yourname+ty@gmail.com go to that label, and ty-email processes them.
./ty-email serveCreate ~/Library/LaunchAgents/com.ty-email.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://schemas.apple.com/dtds/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.ty-email</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/ty-email</string>
<string>serve</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/ty-email.log</string>
<key>StandardErrorPath</key>
<string>/tmp/ty-email.err</string>
<key>EnvironmentVariables</key>
<dict>
<key>ANTHROPIC_API_KEY</key>
<string>sk-ant-...</string>
</dict>
</dict>
</plist>Then:
launchctl load ~/Library/LaunchAgents/com.ty-email.plist
launchctl start com.ty-email
# Check status
launchctl list | grep ty-email
# View logs
tail -f /tmp/ty-email.log
# Stop
launchctl stop com.ty-email
launchctl unload ~/Library/LaunchAgents/com.ty-email.plistCreate ~/.config/systemd/user/ty-email.service:
[Unit]
Description=ty-email daemon
After=network.target
[Service]
ExecStart=/path/to/ty-email serve
Restart=always
RestartSec=10
Environment=ANTHROPIC_API_KEY=sk-ant-...
[Install]
WantedBy=default.targetThen:
systemctl --user daemon-reload
systemctl --user enable ty-email
systemctl --user start ty-email
# Check status
systemctl --user status ty-email
# View logs
journalctl --user -u ty-email -f# Interactive setup
ty-email init
# Run daemon (polls every 30s)
ty-email serve
# Process once and exit
ty-email process
# Test classification with sample email
echo -e "Subject: Fix the bug\n\nThe login is broken" | ty-email test
# Check status
ty-email status
# Send an email (for tasks to report results)
ty-email send --to user@example.com --subject "Results" --body "Task completed!"
# Send with body from stdin
echo "Task results" | ty-email send --to user@example.com --subject "Results"Email to yourname+ty@gmail.com:
Subject: Fix the checkout page
Users are seeing 500 errors when checking out
Reply you'll receive:
Created task: Fix the checkout page
Project: personal
Status: backlog
I've created this task for you. Run `ty execute` when ready.
Subject: Fix the checkout page and run it
Users are seeing 500 errors
The "and run it" triggers immediate execution.
When a task needs input, you get an email. Just reply:
Go with option 1, that's the root cause.
ty-email routes your input to the correct task.
Subject: What's happening with the checkout fix?
You'll get a status update on matching tasks.
Tasks can send results back via email using the send command:
# Send a simple email
ty-email send --to user@example.com --subject "Task complete" --body "Results here"
# Pipe content from a command
cat output.log | ty-email send --to user@example.com --subject "Build results"
# Include task ID for email threading
ty-email send --to user@example.com --subject "Task #123 done" --task 123 --body "Done!"This is useful for:
- Notifying users when long-running tasks complete
- Sending task output/results back to the original requester
- Maintaining email thread context with
--taskflag
Enable dangerous mode to allow tasks to perform destructive operations (like git push --force):
taskyou:
cli: ty
dangerous: trueWhen enabled, tasks created via email will have the --dangerous flag set. Use with caution.
Config lives at ~/.config/ty-email/config.yaml:
adapter:
type: imap
imap:
server: imap.gmail.com:993
username: you@gmail.com
password_cmd: echo 'your-app-password'
folder: ty-email
poll_interval: 30s
smtp:
server: smtp.gmail.com:587
username: you@gmail.com
password_cmd: echo 'your-app-password'
from: you@gmail.com
classifier:
provider: claude
model: claude-sonnet-4-20250514
api_key_cmd: echo $ANTHROPIC_API_KEY
taskyou:
cli: ty
dangerous: false # Enable dangerous mode for tasks
routing:
default_project: personal # Project for email-created tasks
auto_execute: false # true = queue email-created tasks for execution immediately
security:
allowed_senders:
- you@gmail.com # Only process emails from these exact addresses
notify: you@gmail.com # Where blocked-task notifications go (default: first allowed sender)
max_tasks_per_hour: 20 # Rate limit (-1 to disable)- Sender allowlist (exact match) - Only emails whose From address exactly matches an entry in
security.allowed_sendersare processed (case-insensitive). Display names and substrings are ignored, so"you@gmail.com" <evil@attacker.com>andyou@gmail.com.attacker.comare rejected. - Auto-reply detection - Inbound mail with
Auto-Submitted,Precedence: bulk/junk/auto_reply,X-Autoreply, or ty-email's ownX-TY-Emailheader is ignored. Outbound replies carryAuto-Submitted: auto-replied,X-Auto-Response-Suppress: All, andX-TY-Emailheaders. Together these break mail loops with vacation responders, bounces, and ty-email itself. - Rate limiting - At most
security.max_tasks_per_houremails (default 20) are processed per hour. Excess mail is deferred (stays unread) and picked up when the window clears, so an inbox flood can't fan out into unbounded task creation. - Bounded LLM retries - An email that repeatedly fails classification (API outage, malformed response) is abandoned after 3 attempts instead of retrying every poll cycle forever.
- No code execution in ty-email - ty-email only calls
tyCLI commands. The LLM just classifies intent. - Local credentials - Email passwords and API keys stay local, never sent to LLM.
- State tracking - Processed emails are tracked in
~/.local/share/ty-email/state.dbto avoid duplicates.
Residual risks to be aware of:
- From spoofing: the allowlist trusts the From header. Gmail-to-Gmail this is protected by DKIM/SPF filtering, but a sufficiently motivated attacker who can land a spoofed email in your labeled folder can create tasks. Keep
dangerous: false(the default) so executed tasks still go through Claude's permission prompts inside an isolated worktree. - Prompt injection: email subject/body become the task prompt executed by an agent. Treat the +ty address like you treat your terminal.
To get agent@yourdomain.com → TaskYou, you don't need any new infrastructure — just forward the address into the +ty pipeline:
- Set up forwarding from
agent@yourdomain.comtoyourname+ty@gmail.com(Cloudflare Email Routing, Fastmail rules, or your registrar's forwarding all work). - Your existing Gmail filter (
To: yourname+ty@gmail.com→ labelty-email, skip inbox) catches the forwarded mail. - Add the addresses you'll send from to
security.allowed_senders. - To have emailed tasks start executing immediately (instead of landing in backlog), set:
routing:
default_project: personal
auto_execute: trueReplies still come from the +ty alias, and blocked-task notifications go to security.notify (default: the first allowed sender).
Your ANTHROPIC_API_KEY env var isn't set in the shell running ty-email. Either:
- Run
source ~/.zshrcbeforety-email serve - Add the env var to your launchd/systemd config
- Use
api_key_cmdwith a command that outputs the key
The smtp section in config is missing or incomplete. Re-run ty-email init.
- Check the Gmail filter is correct (
To: yourname+ty@gmail.com→ labelty-email) - Check ty-email can connect:
ty-email serveshould show "connected to IMAP server" - Check the email is from an allowed sender (see
security.allowed_senders)
echo -e "Subject: Test task\n\nThis is a test" | ty-email test