37signals recently released the HEY CLI, and it is perfect for your AI agents. It gives them a command-line interface to your email and calendar. They can search your email, read a thread, draft a reply, move mail between boxes, and manage your calendar on your behalf.
The CLI is also open source on GitHub, and it makes HEY scriptable. One command in particular turns it from a toolbox you call into something that listens: hey watch.
That opens up useful possibilities that HEY itself does not offer today. That malleability is the point. The CLI gives you the pieces; what you do with them is limited mostly by your imagination.
One sender, three kinds of email
Imagine you use a monitoring service called Acme Monitor. It sends everything from the same address: notifications@example.com.
Most of those emails are hourly status updates:
Production API status — all systems operational
Those can arrive in the Imbox with everything else from Acme Monitor, but I do not want every routine update waiting for my attention. I want them marked as seen automatically.
Every so often the status is less reassuring:
Production API status — degraded performance
That one should remain unseen in the Imbox. Something is wrong, and you want to see it.
Once a month, the same address sends this:
Invoice #10482 for Acme Monitor
That belongs in Paper Trail with your other invoices and receipts.
HEY lets you decide where email from a sender should go. That works well until one sender sends three very different kinds of email. I want routine updates marked as seen, degraded alerts left unseen in the Imbox, and invoices moved to Paper Trail.
There is no rule in HEY for “mark routine messages from this sender as seen, leave degraded alerts unseen, and file invoices in Paper Trail.”
But now we can make one.
Let HEY tell your script
First, let notifications@example.com into the Imbox as normal.
Now watch the Imbox for new mail:
hey watch --box imbox --events new --json
When an email arrives, hey watch prints one JSON object. A shortened event looks like this:
{
"change": "added",
"posting_id": 98765,
"posting": {
"name": "Invoice #10482 for Acme Monitor",
"creator": {
"email_address": "notifications@example.com"
}
}
}
The posting’s name is the email subject. It also carries the sender and the posting ID needed to move it or mark it as seen.
This example uses jq to inspect the event. Create ~/bin/file-acme-mail:
#!/usr/bin/env bash
set -euo pipefail
event=$(cat)
action=$(jq -r '
def subject: (.posting.name // "");
if .change != "added"
or .posting.creator.email_address != "notifications@example.com" then
"ignore"
elif (subject | test("^(invoice|receipt|payment received)\\b"; "i")) then
"paper trail"
elif (subject | test("\\b(degraded|outage|incident)\\b"; "i")) then
"attention"
elif (subject | test("\\ball systems operational\\b"; "i")) then
"seen"
else
"attention"
end
' <<<"$event")
case "$action" in
"paper trail")
hey move "$HEY_POSTING_ID" --to "$action"
;;
seen)
hey seen "$HEY_POSTING_ID"
;;
attention|ignore)
;;
*)
echo "Unexpected action: $action" >&2
exit 1
;;
esac
Make it executable:
chmod +x ~/bin/file-acme-mail
Then connect it to the watch:
hey watch \
--box imbox \
--events new \
--run-sync ~/bin/file-acme-mail
Every new Imbox event is handed to the script as JSON on standard input. The script also receives useful environment variables such as HEY_POSTING_ID, HEY_THREAD_ID, and HEY_BOX_NAME. Using --events new prevents ordinary moves from triggering the rule again, while the first check limits it to newly added threads rather than replies.
Known “all systems operational” status threads are marked as seen. A degraded, outage, or incident alert is left unseen in the Imbox. An invoice, receipt, or payment confirmation moves to Paper Trail. Anything unexpected also remains unseen rather than being hidden by an overly broad rule.
That is an attention and filing rule HEY does not offer in its interface, built from three CLI commands and a few lines of shell. Keep hey watch running under launchd, systemd, or your preferred service manager if you want the rule to stay active.
You do not need to write this script yourself. The HEY CLI includes a bundled agent skill for Claude Code and Codex, and today’s coding agents can create, test, and put a watcher like this in place for you. Give the agent the outcome you want:
Use the HEY CLI to create a hey watch rule for notifications@example.com.
For newly added Imbox threads:
- mark known "all systems operational" messages as seen
- leave degraded, outage, incident, and unknown messages unseen
- move invoice, receipt, and payment-confirmation messages to Paper Trail
Make the script fail safely, test it with synthetic events, and show me how
to keep it running.
The generated script is still worth reviewing before you turn it loose on your inbox, but the skill means you do not need to learn every command or write the shell from scratch.
Once HEY is programmable
The subject rule is only the start. The CLI gives scripts and agents access to the same email and calendar you work with in HEY.
With the HEY CLI, you could:
- Build a morning briefing from today’s calendar, new mail, Reply Later, and Set Aside.
- Search years of email before a client call, then summarize the decisions and outstanding commitments.
- Read a long thread and prepare a draft reply for you to approve.
- Review first-time senders in The Screener, read what they sent, and recommend who to let through.
hey watch adds the missing trigger. Instead of running a command yourself, HEY can tell your program that something changed.
With hey watch, you could:
- Mark routine status reports as seen but leave an outage unseen and send a desktop notification.
- Move receipts into Paper Trail only when the message has an attachment or matches a supplier-specific rule.
- Wake an agent to summarize mail from an important customer and prepare the next action.
- Refresh an e-ink household agenda when a shared calendar changes.
A watch event includes the sender, subject, summary, box, whether the posting includes attachments, and other details. When that is not enough, a script or agent can read the full thread with hey thread read.
Rules for the obvious, agents for the ambiguous
The Acme Monitor rule is deterministic. If the sender and subject match, move the email. There is no reason to ask a language model to make that decision.
Real inboxes are not always so tidy. A supplier may use inconsistent subjects, or a message may look routine until you read the body. An agent can wake when hey watch reports new mail, read the complete thread, then summarize it, suggest a destination, apply a label, or prepare a draft reply.
I would still begin conservatively. Give the agent a narrow job and keep sending or destructive actions behind human approval until you trust the workflow.
The WebSocket is only the doorbell
HEY’s live connection acts as a doorbell: it says a box or calendar changed, then the CLI reads an incremental feed to find out what happened. If that connection drops while hey watch remains running, it catches up before continuing. That makes it much safer than treating a transient WebSocket notification as the source of truth.
HEY, watch this
The HEY CLI lets an agent manage your inbox, but you do not need an agent to benefit from it. Sometimes five lines of shell are the better tool.
Start with the annoying rule you cannot express today. Let HEY tell your script when something changed, then make the decision as simple or as sophisticated as it needs to be.