Domo
A household assistant on your Mac that reads your texts and texts back — powered by your own Claude subscription.
What this seed does
Domo is a personal assistant you talk to through ordinary text messages. It runs as a persistent session on your Mac, connected to a real texting conversation — send it a message, and it reasons, checks your Google Calendar, and texts you back. There is no app to open and no dashboard to babysit: just a thread on your phone and an agent on the other end.
Unlike a packaged product, Domo is delivered as a *SEED*: when you install it, an agent interviews you about how you want it to work — just for you, or for a whole household group? What should it be called, what is it allowed to do? — and then writes a custom version built to your exact answers. Solo versus group is not a settings toggle; it is a question the install asks, and the answer shapes the software.
The seed walks through every setup step: verifying required tools are in place, guiding you through signing in to your Claude subscription and enabling the Google Calendar connector in your browser, installing the texting channel that bridges your phone to the session, and starting the background daemon that keeps Domo alive. The result is a small, legible assistant running on hardware and an account you control.
When to use it
- You want to text a question from your phone and have an assistant check your calendar and reply — without opening any app.
- You're setting up a shared household assistant so several family members can all text the same agent.
- You want a personal AI that runs on your own Mac and your own account, with no third-party service sitting in the middle.
- You need an always-on assistant that wakes up when a text arrives, reasons about it, and acts — looking things up, reading the calendar, running a local task — then replies automatically.
- You want a custom-built assistant tailored through an interview rather than a one-size-fits-all product with fixed features.
Source
Version history
1 releaseInitial Seed Release.
Files
›View raw SEED.md
# Purpose
> See [README#Purpose](README.md#purpose).
## Normative Language
The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT,
RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as
described in RFC 2119. Sub-folder `SEED.md` files in this tree inherit this
declaration and MUST NOT re-declare it.
## Dependencies
`seed-domo` describes how to stand up a personalized Domo; it does not silently
install anything system-wide. Each dependency below is **surfaced and verified**,
ordered API first, then software. Two of them — interactive `/login` and the
claude.ai Google Calendar connector — are **user-only (tier-3) steps the agent
MUST NOT and cannot perform for the user** (they require a human at a browser /
account session); the agent surfaces them, waits, and then verifies them.
**API**
- **Claude subscription (interactive `/login`)** — Domo runs on an Anthropic
Claude subscription, signed in interactively via `/login` inside the isolated
Claude config dir. The agent MUST NOT supply an API key: `ANTHROPIC_API_KEY`
MUST be unset so subscription auth is used and billing never silently falls
back to a metered key. This is a **user-only (tier-3) step**: the agent cannot
complete `/login` for the user; it MUST surface the step, then verify the
instance is authenticated and that `ANTHROPIC_API_KEY` is unset.
- **claude.ai Google Calendar connector** — the Google Calendar connector
enabled at the **account** level in claude.ai (browser; account-scoped). Once
enabled it surfaces inside Claude Code as the `mcp__claude_ai_Google_Calendar__*`
tools. This is a **user-only (tier-3) step**: the agent cannot perform the
browser OAuth on the user's behalf, so it MUST surface the step and then verify
the tools are available — it is **verified, not executed**.
- **Plow Chat API, via the external SEED
[seed-plow-chat](https://github.com/plow-pbc/seed-plow-chat)** — the texting
surface (line, chat, auth/activation, WSS inbound, REST post, restart-safe
backfill) is owned by the external SEED at
`https://github.com/plow-pbc/seed-plow-chat`. It MUST be installed
**leaves-first** (the external SEED before this one), because it owns the
channel/auth/WSS/post contract that the Domo channel object speaks. The clone
URL MUST carry no userinfo, query, or fragment.
**Software**
- **macOS** — Domo targets macOS; non-macOS hosts are unsupported (see
Non-Goals). The daemon relies on macOS `/usr/bin/script` for a controlling PTY.
- **Claude Code CLI ≥ 2.1.80** — the `claude` CLI MUST be on `PATH` at version
2.1.80 or newer (the `--channels` research preview).
- **`bun`** — the JavaScript runtime that runs the channel MCP server and the
small JSON/activation helpers. It MUST be on `PATH`.
- **`jq`** — used to render the readable transcript feed. It SHOULD be present;
without it the reference falls back to the raw PTY log.
- **`expect`** — drives the once-per-launch dev-channels confirmation so the
background daemon can start headlessly. It MUST be present for the backgrounded
custom-channel launch.
The reference channel under `ref/channels/plow-chat` needs `bun install` in that
directory only if the agent chooses to run or extend the reference; nothing in
this SEED REQUIRES running `ref/`.
## Objects
A running Domo is composed of the following named entities. This section is
descriptive: it names the parts so Actions and Verify can refer to them.
- **The Domo session** — one persistent `claude --channels` process. It uses
subscription auth (never an API key) and runs with `--permission-mode auto`
(classifier-gated, not `bypassPermissions`). Reference: `ref/domo`.
- **The channel** — an MCP stdio server implementing the `claude/channel`
capability over Plow Chat: inbound over WSS, outbound via REST POST, and
restart-safe backfill that de-dupes by message uid so a daemon restart does
not replay history. It reads its secrets (`base_url`, the Bearer token,
`chat_uid`) from a chmod-600 state file whose absolute path is passed via the
`PLOW_CHAT_STATE` environment variable; it MUST NOT hardcode the path and MUST
NOT log the token. Reference: `ref/channels/plow-chat`.
- **The daemon** — the backgrounded, detached session with **session resume** via
a single pinned session UUID, so the foreground (`shell`) and background
(`start`) launches are one continuous conversation. The once-per-launch
dev-channels confirmation is answered headlessly through a PTY/`expect` driver.
Reference: `ref/domo` plus `ref/bin/spawn-confirm.expect`.
- **The chat** — a Plow chat, in one of two shapes. **Solo** is one member (a 1:1
texting line). **Group** is N members. Each member is verified by texting a
one-time `VERIFY-XXXXXX` code; inbound frames carry
`message.sender.display_name`, so the agent always knows who is talking. Solo
vs group is **not** a runtime toggle or a shipped flag — it is a property the
install interview decides, and it changes the software the agent writes.
- **The workspace** — the agent's working directory plus a `CLAUDE.md` holding
household context: who is in the chat, the persona, and the trust posture.
Runtime state (config, sessions, run dir, channel state) lives gitignored at
the repo root.
- **The calendar tools** — the `mcp__claude_ai_Google_Calendar__*` tools that
appear from the account-level claude.ai connector. They let Domo read and
manage the household calendar.
## Actions
These are the verbs of a Domo's lifecycle. Contracts use RFC 2119 language.
### Domo is installed
The one-shot, interview-driven onboarding. **The SEED does not ship a
configurable product and the agent MUST NOT dictate a shape.** Instead the agent
**interviews the user** (solo / group / whoever / however), then **writes custom
Domo software** tailored to that answer, consulting `ref/` for the mechanics.
`ref/` is **reference only**: it is a working example of how the pieces fit, and
the agent MUST NOT be required to copy it verbatim — it MAY author the Domo any
way the user wants, as long as the security invariants below hold.
The agent MUST complete the following checklist (an agent SHOULD map each item to
its task tracker):
1. **Walk the Dependencies.** Surface every API and software dependency above.
For the two user-only (tier-3) steps — interactive `/login` and enabling the
claude.ai Google Calendar connector — the agent MUST surface them to the user,
wait, and verify them; it MUST NOT attempt to perform them itself.
2. **Confirm the external SEED is installed leaves-first.** Verify that
[seed-plow-chat](https://github.com/plow-pbc/seed-plow-chat) (the channel/auth
contract) is present before standing up the channel.
3. **Interview the user.** Ask how they want to use Domo. Named choices (e.g.
solo vs group) are tier-2 questions; open answers (member names, persona,
trust posture) are tier-3. The agent MUST record the answers as the household
context, and MUST NOT assume a shape the user did not choose.
4. **Author the user's custom Domo software.** Write the Domo to match the
interview, consulting `ref/` for the channel contract, the backgrounded
`claude --channels` daemon with session resume, the dev-channels confirmation,
and `--permission-mode auto`. The authored software MUST keep
`ANTHROPIC_API_KEY` unset, MUST store the Plow Bearer token chmod-600 and
never log/print/commit it, and MUST use clone URLs with no
userinfo/query/fragment.
5. **Activate.** Run the activation handshake (see *Domo is activated*),
surfacing the activation/verification code(s) for the user(s) to text. The
activation secret MUST be passed via stdin, never argv.
6. **Start the daemon.** Launch the persistent session in the background with the
pinned session UUID and the headless dev-channels confirmation.
7. **Verify.** Run the Verify prompts below and confirm each returns its expected
answer before declaring the install complete.
### Domo is activated
The Plow handshake that yields a Bearer token and a chat. It is documented in
**both** shapes so an authoring agent has a concrete example of either; neither
is a shipped toggle.
- **Solo** — use the activation shortcut: `POST /v1/auth/activate
{provision_chat: true}` returns one display code; the user texts it; redeem
yields the user-wide Bearer token plus a 1:1 chat. The token MUST be written
chmod-600 to the state file and MUST NOT be logged, printed, or committed.
- **Group** — activate to obtain the token and a line, then `POST /v1/chats` with
`participants = [{agent, line_id}, {member, display_name}, …]`. Each member
texts their one-time `VERIFY-XXXXXX`; the channel observes `participant_verified`
frames until every participant is `active`.
### Domo runs
The background daemon keeps the session alive: it resumes the pinned session UUID
so `shell` and `start` are one continuous conversation, and it answers the
once-per-launch dev-channels confirmation through the PTY/`expect` driver. The
daemon MUST be reapable by its scoped session signature (so two Domo instances
never reap each other) and MUST NOT print secrets in its logs.
### Domo replies / reads the calendar / reports activity
The runtime verbs. Domo **replies** to texts through the channel `reply` tool
(anything the user should see MUST go through `reply`; transcript output does not
reach them). Domo **reads the calendar** through the
`mcp__claude_ai_Google_Calendar__*` connector tools. Domo **reports activity**
through the transcript-feed logs (a readable 📥/📤/⚙ feed), which MUST NOT contain
the Bearer token or any other secret.
## Verify
Verification is a sequence of natural-language prompts an agent reads and answers;
the Domo is conformant when every prompt returns its expected answer. The
deterministic implementation lives at `ref/verify.sh`.
1. **Tooling present.** Are `bun`, `jq`, and `expect` on `PATH`, and is
`claude --version` ≥ 2.1.80?
2. **Subscription, not API key.** Is the instance authenticated on a Claude
subscription (interactive `/login`), with `ANTHROPIC_API_KEY` **unset**?
3. **Calendar connector.** Are the `mcp__claude_ai_Google_Calendar__*` tools
available from the account-level connector?
4. **Channel + daemon.** Is the channel MCP server registered, and does the
daemon resume the pinned session (e.g. `ref/domo doctor` / `ref/domo status`
reports green)?
5. **Structural conformance.** Do the three SEED structural checks pass?
a. The repo `README.md` contains a `## Purpose` H2 (outside code blocks).
b. The root `SEED.md` has exactly one H1 (`# Purpose`), matches the canonical
H2 grammar, and includes the `## Normative Language` section.
c. Every `SEED.md` in the tree has a `# Purpose` body that is a single line
linking to its sibling-or-ancestor `README#Purpose`, and sub-folder
`SEED.md` files omit `## Normative Language`.
## Feedback
(none)
## Open
- **Morning briefing trigger** — a cron-injected morning message so Domo proactively
briefs the household. Deferred.
- **Reboot survival** — a launchd job so the daemon survives a host reboot.
Deferred.
- **Per-sender gating** — finer-grained authorization per sender. Deferred; the
current trust posture is all-verified-members-equal.
## Non-Goals
- **No headless `claude -p`** — Domo is channels-only; it is not driven by
one-shot `claude -p` prompting.
- **No API key** — `ANTHROPIC_API_KEY` stays unset; Domo is subscription-billed
and MUST NOT fall back to a metered key.
- **No shipped configurable product** — this SEED authors bespoke software per
user (interview, then write); it does not ship a single product with a
solo/group flag.
- **Non-macOS** — non-macOS hosts are unsupported.
›View raw README.md
# Domo A de-Plowed, agent-first household assistant that lives on your Mac, runs on your Claude subscription, reads your texts, reasons, acts, and texts back. ## Purpose **Domo** is a personal household assistant that runs as **one persistent `claude --channels` session** on a Mac, billed against your **Claude subscription** (never a metered API key). It is *de-Plowed* and *agent-first*: a single always-on Claude Code session is wired to a real texting conversation, so you talk to it the way you'd text a person. A message comes in, Domo **reasons** about it, **acts** — checks your Google Calendar, looks something up, runs a local task — and **texts you back**. No app to open, no dashboard to babysit: just a thread on your phone and an agent on the other end. Domo is delivered as a **SEED**, not as a shrink-wrapped product. A SEED is a descriptive knowledge base plus a working reference implementation that an **agent** uses to stand up *your* Domo. You don't run an installer that imposes one fixed shape. Instead you point an agent at [`SEED.md`](SEED.md) and it **interviews you** — how do you want to use Domo? Just you, or a household group? What should it be allowed to do? What persona, what trust posture? — and then it **writes the Domo software that fits your answers**, consulting the reference for the mechanics but free to build it however you want. Nothing is dictated. Solo versus group is not a runtime switch; it is a question the install asks, and the answer changes the software the agent writes. The result is yours: a small, legible, single-session assistant you understand, running on hardware and an account you control, with no third-party product sitting between you and your agent. > `ref/` in this repo is **implementation reference** — a working example of the > moving parts (the texting channel, the backgrounded session daemon, calendar > tools, the activation handshake). It is there to show *how* the pieces fit, not > a product you must run as-is. The agent and you read it to understand the > mechanics; your Domo can reuse, adapt, or replace any of it. ## Install Installing Domo is a one-shot, agent-led conversation. There is no `./install` to run blindly. ```bash git clone https://github.com/plow-pbc/seed-domo cd seed-domo ``` Then **point an agent (Claude Code) at [`SEED.md`](SEED.md)** and let it drive. Working from the SEED, the agent will: 1. **Walk every requirement** with you — the tooling (macOS, Claude Code with the `channels` research preview, `bun`, `jq`, `expect`), an interactive **`/login`** to your Claude **subscription** (no API key), the claude.ai **Google Calendar connector** enabled at the account level, and the **seed-plow-chat** channel that bridges a real texting conversation to the session. 2. **Interview you** about how you want to use Domo — solo or a household group, who the members are, what persona it should have, and what it's allowed to do. 3. **Write your custom Domo software** to match, consulting `ref/` for the proven mechanics but assembling exactly what you asked for. 4. **Activate and start it** — surface the activation code(s) for you to text in, launch the background session, and verify everything is live. A few steps only *you* can do (the agent will pause and ask): the interactive `/login`, and enabling the Google Calendar connector in the browser — an agent can't OAuth on your behalf. The SEED makes those explicit; it never tries to do them for you. ## Usage Once Domo is installed, the reference `ref/domo` CLI shows how the lifecycle is operated. (Your authored Domo may expose its own commands; the surface below is the reference example.) Domo runs as **one pinned, persistent session** — the foreground `shell` (for one-time login/consent/debug) and the background daemon share a single session UUID, so they're one continuous conversation. ```bash ref/domo setup # idempotent bootstrap: isolated dirs, workspace, pinned session UUID ref/domo activate # Plow handshake: print the code to text, poll redeem, write chmod-600 state ref/domo doctor # read-only preflight: tooling, auth, ANTHROPIC_API_KEY unset, channel state ref/domo start # launch the background daemon (the one pinned session) ref/domo status # resolved config + daemon liveness + channel state (no secrets) ref/domo logs # readable transcript feed of what Domo is reading, thinking, and sending ref/domo stop # stop the daemon (tree-kill) + sweep the stray channel child ``` **`ref/domo logs`** is the window into a running Domo: it renders the **readable transcript feed** (inbound texts, Domo's replies, tool activity) rather than raw PTY output. Add `--raw` for the underlying PTY/TUI capture, or `--no-follow` for a one-shot read. ### One-time setup `ref/domo setup` is idempotent. It points `CLAUDE_CONFIG_DIR` at an isolated config dir under the repo root, creates the workspace and runtime dirs, mints and persists the **pinned session UUID**, and verifies the selected channel is loadable. It does **not** log you in or activate anything — those are the interactive steps the SEED walks you through: - **Connect Google Calendar (browser, once).** At [claude.ai/customize/connectors](https://claude.ai/customize/connectors), connect **Google Calendar** using the **same Anthropic account** you'll `/login` with. Connectors are account-scoped, so they surface in the session as `mcp__claude_ai_Google_Calendar__*` tools. - **Log this instance in.** Run `ref/domo shell`, then `/login` with that same subscription account, and accept the channels research-preview consent once (it needs a real TTY, which `shell` provides). A fresh isolated config dir does not inherit your personal Claude Code login. - **Activate the texting channel.** `ref/domo activate` runs the Plow handshake: it prints a code and a number; from the phone you want bound to the chat, text the code in. It then polls until verified and writes a **chmod-600** state file. Re-run with `--force` to re-activate. ### Auth Auth is the interactive `/login` above. For a fully unattended run you can mint a **subscription** token (`claude setup-token`) and let `ref/domo` pick it up from the environment. It is a subscription token, **not** an API key — keep `ANTHROPIC_API_KEY` unset; every launch unsets it and `ref/domo doctor` asserts it. ### Permissions The session runs `--permission-mode auto` — a classifier-gated guard, **not** bypass mode. Read-only ops, the channel reply, and local workspace file ops are auto-approved (so the read-calendar-then-reply loop never stalls); destructive and external-write actions are blocked-but-overridable; exfiltration is always blocked. Auto mode is a *generic* guard, not a Domo policy: it does not stop calendar **writes**, and an always-on agent reading **untrusted inbound texts** is a prompt-injection surface. Add a Domo-specific authorization layer before you let Domo act on others' behalf. ### Security posture - The Plow **Bearer token** is **user-wide**: stored **chmod-600** in the state file (parent dir chmod-700), gitignored, **never logged, printed, or committed**. `status`/`doctor` report only `present`/`missing`. The activation secret is passed via stdin, never on a command line. - `ANTHROPIC_API_KEY` stays **unset** — Domo uses subscription auth only. - One isolation caveat: the Google Calendar **connector is account-scoped**, so this instance inherits every connector on the account you `/login` with. Config, plugins, sessions, and channel state stay isolated; connectors don't. Keep the account's connected surface minimal. ## License No license is declared for this repository yet. Until one is added, treat the contents as all-rights-reserved by the authors.
Dependencies
11 required · 0 optional- SWmacOSrequired
- SWClaude Code CLI (claude)required
- SWcurlrequired
- SWexpectrequired
- SWtmuxrequired
- APIPlow Chat API accountrequired
Contributors
1 contributorComments
0 commentsYou need to be signed in with GitHub to comment.
No comments yet — be the first to share how this seed worked for you.
Similar seeds
Connect your Hermes AI agent to iMessage/SMS by wiring it to the Plow Chat API via a direct-mounted gateway plugin.
by @plow-pbcConnects an AI agent to iMessage/SMS messaging just like Domo, using the same Plow Chat integration for text-based interaction.
Installs the latest production Plow app on macOS — your personal AI assistant for calendars, messages, email, and files.
by @swagatpatelPersonal AI assistant on Mac that reads messages and automates responses, similar use case to Plow's messaging integration.
Specification and reference examples for the Plow Chat API — activate users, send messages, and receive replies over SMS/iMessage via REST and WebSocket.
by @plow-pbcProvides the SMS/iMessage messaging API that powers text-based communication for AI agents like Domo.
Run the Hermes AI agent locally in Docker with a browser dashboard, ChatGPT login, and files you can edit directly from your computer.
by @plow-pbcRuns a local AI agent on your Mac with persistent session management, similar to Domo's architecture and personal-assistant purpose.