Voice mailboxes
Hand off a Claude Code conversation to the voice agent on the phone,
walk while talking, get structured responses back. One open exchange =
one Reminders list = one entry in ~/.claude/voice-mailboxes/.
Three roles
The vocabulary matters because the brief addresses one role and refers to the other two — getting POV wrong makes the brief unreadable to the voice agent.
| Role | Surface | POV in brief |
|---|---|---|
| user | Human. Types in the terminal, speaks on the phone. | Third person ("the user", "they"). Never addressed directly in writing. |
| project agent | Claude Code session that composes the brief. | First person ("I"). |
| voice agent | Claude Voice on the phone. Reader of the brief. | Second person ("you"). The reader. |
Lifecycle
What the daemon owns vs the user owns
Response kinds
The brief's writeback contract lists five optional title prefixes the
voice agent can use when writing a response. Anything without a prefix is
classified as free on drain.
| Prefix | Kind | Meaning |
|---|---|---|
decision: | decision | User committed to something on the call. |
note: | note | Context worth keeping; no action implied. |
question: | question | User wants the project agent to come back with an answer. |
deferred: | deferred | Talked about, no decision yet — explicit punt to revisit later. |
done | done | Closes the exchange. Daemon tears the list down on the next cycle. |
| (none) | free | Plain text. Kept as-is on drain. |
deferred and not just question? A deferral is a conversational outcome — the user already heard the
options and chose not to choose yet. Tracking it separately lets the
project agent re-raise it as a discussion item next session, instead of
treating it as a fresh unanswered question.CLI surface
| Command | Effect |
|---|---|
rbridge mailbox open --slug X --kind REMINDERS --brief - | Idempotent. Reads brief from stdin, creates / refreshes the exchange list, mirror, state file. |
rbridge mailbox read --slug X | JSON dump of responses (header + brief excluded). Warns on stderr if a done reminder is present. |
rbridge mailbox close --slug X | Tears down: deletes list, removes mirror, drops state. Returns truthful status (list deleted / was missing / failed). |
rbridge mailbox refresh --slug X | Re-up header + brief from on-disk brief, no other changes. |
rbridge mailbox list | Enumerate active exchanges. |
None of these require the daemon to be running — they all hit EventKit directly. The daemon only adds GC + drift correction on top.
Discoverability — silent by design
No alarms, no notifications, no "Today" due dates. The signals an open exchange leaves are:
- The exchange list itself in the sidebar.
- A high-priority breadcrumb reminder
Voice exchange open: <slug>in the user's default list. rbridge mailbox listfor the agent itself.
This is intentional: agents may open exchanges overnight, during meetings, or while the user is AFK. Pushing alerts in those scenarios is worse than silence. The user discovers the exchange the next time they glance at Reminders.app, which on iOS happens naturally.
Disable the breadcrumb with RBRIDGE_MAILBOX_MIRROR=false.
Slug rules
- Grammar:
[a-z0-9][a-z0-9-]{0,47}. Kebab-case, 2-5 words. - Topic-first, not action-first:
wallgen-shipping-decision, notdecide-wallgen-shipping. - Skip filler verbs (
figure-out-,talk-about-,discuss-). - If the conversation has a project name, lead with it (
pimpelmees-shopify-cutover). - Slug collision on
openis non-destructive — header + brief are rewritten, prior responses preserved.