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.

The user talks to both agents; the project agent writes for the voice agent; the voice agent talks with the user out loud.
RoleSurfacePOV in brief
userHuman. 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

One open exchange. Idempotent re-open from the same slug rewrites header + brief but preserves prior responses.

What the daemon owns vs the user owns

Five surfaces per exchange. Daemon-owned in green; user-written in orange; state files in amber.

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.

PrefixKindMeaning
decision:decisionUser committed to something on the call.
note:noteContext worth keeping; no action implied.
question:questionUser wants the project agent to come back with an answer.
deferred:deferredTalked about, no decision yet — explicit punt to revisit later.
donedoneCloses the exchange. Daemon tears the list down on the next cycle.
(none)freePlain text. Kept as-is on drain.
Why 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

CommandEffect
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 XJSON dump of responses (header + brief excluded). Warns on stderr if a done reminder is present.
rbridge mailbox close --slug XTears down: deletes list, removes mirror, drops state. Returns truthful status (list deleted / was missing / failed).
rbridge mailbox refresh --slug XRe-up header + brief from on-disk brief, no other changes.
rbridge mailbox listEnumerate 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:

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