Skip to content

Aquinas-Protocol/domo

Repository files navigation

Domo

Domo (short for majordomo) is a personal, Discord-fronted assistant built on Claude Code. You talk to an operator agent in Discord — DMs and a dedicated channel — and it coordinates a small council of specialist agents, each with its own Discord bot identity, persona, and tool allowlist. The operator can spawn isolated per-thread sub-agents for long-running work and delegate to the council. A local Mission Control dashboard gives a web view of agents, the run ledger, scheduled jobs, and the vault. All sessions run with Claude Code's full tool access against a working directory you choose (typically a personal notes vault).

This is the public, standalone extraction of a personal bot. The generic council + infrastructure are here; the owner's personal integrations are intentionally left out (see Not included).

Features

  • Council of agents — an operator (main) that can delegate, plus research (deep web research) and comms (correspondence) specialists. Each agent is a separate Discord bot account with its own channel, persona file, model, and tool allowlist (agents.yaml).
  • Per-thread sub-agentsspawn_thread_agent (operator-only MCP tool) opens a Discord thread and runs a sub-agent there in the background, isolated from the main session.
  • Mission Control dashboard — a localhost FastAPI/SPA app: agent tiles, the task ledger, usage/credit summaries, the cron scheduler, and a read-only vault browser. PIN-gated.
  • Cron scheduler — schedule recurring or one-shot agent runs (mcp__cron__* tools + a dashboard panel); results post to a channel.
  • Calendar — Apple iCloud CalDAV read for the whole council, write for main/comms (mcp__calendar_read__* / mcp__calendar_write__*). Skipped unless iCloud creds are set.
  • Video / watchwatch_video for the research agent (wraps a /watch skill if installed).
  • GPT-5 specialist — an mcp__specialist__query_gpt5 tool that shells out to a local Codex CLI, so the council can consult a non-Claude model. Skipped unless the Codex CLI is found.
  • Admin elevation — an operator-only request_admin_elevation tool with a Discord Approve/Deny flow, executed by a separate elevated broker service. See Security before enabling.
  • Credit governor — tracks Anthropic Agent SDK spend against a monthly ceiling and can refuse new runs when exhausted (observe-only by default).
  • Vault write-guard — a PreToolUse hook that blocks agent writes to protected paths and reads of secret files, even under bypassPermissions.

Not included

This extraction deliberately omits the original owner's personal subsystems. The wiring for them has been removed:

  • Email (Gmail read/draft, inbox categorization).
  • Email cull (bulk promotional-mail review/trash).
  • Reverse recruiter (job-hunt scanning + pipeline tracking).
  • Nightly mission (the long-running autonomous nightly research runner).

The dashboard, council, cron, calendar, video, specialist, and elevation features above are the supported surface.

Architecture

  • Python 3.12, discord.py, claude-agent-sdk, FastAPI.
  • src/bot.py defines BotApp, which owns a shared RunnerRegistry and one discord.Client per agent. Each feature wires in via a _wire_<name>_tools() method that builds a context and registers an in-process MCP server scoped to a set of agents.
  • One ClaudeSDKClient per Discord key (an agent, or thread:<id>), held warm across messages, torn down after idle, resumed from session ID on restart.
  • Authentication runs through Claude Code itself — either a logged-in Claude subscription (claude login~/.claude/.credentials.json) or an ANTHROPIC_API_KEY. Domo requires neither specifically and sets up neither for you; whichever Claude Code is configured with is used (when both are present, the SDK uses ANTHROPIC_API_KEY).

Companion vault

Domo runs on top of a second-brain vault — a Claude-Code-powered, Obsidian-style knowledge base it uses as shared memory: it reads the vault's CLAUDE.md conventions, loads agent personas from <vault>/agents/, and reads & writes wiki/ pages. The vault is a separate, MIT-licensed starter project; Domo is the multi-agent council layer its setup guide refers to as "going further."

Set up a vault first (~30–45 min) by following that repo's GUIDE.md. Then point Domo at it — the wizard asks for the path (VAULT_ROOT, default ~/Documents/second-brain) and installs the council personas into <vault>/agents/.

Setup

py -3.12 -m venv .venv
.\.venv\Scripts\activate
pip install -e .
py wizard.py

The wizard checks your Claude auth (subscription login or API key), points Domo at your companion vault (and installs the council personas into it), validates each agent's Discord bot token + channel, optionally wires Groq voice transcription / Apple Calendar / the GPT-5 specialist / a dashboard PIN, writes .env (ACL'd to your user), creates the bot's working-directory junction, and points you at the service-install scripts.

Copy .env.example to .env to see every variable the included features read. The wizard fills in the core ones; the rest are optional per-feature.

Run

py -m src.bot

Or install as a Windows service via NSSM for always-on operation (see install_service.ps1 and the wizard output).

Security

Read this before enabling the elevation broker.

Domo ships an optional second service — the elevation broker (broker/elevation_broker.py, installed by broker/install_broker.ps1 as the Windows service domo-elevation-broker). It runs as LocalSystem, i.e. with full Administrator privileges and no UAC prompt. Its job is to execute commands that the operator agent requested and that you explicitly approved with a Discord button click.

What this means concretely:

  • When the broker is installed, an approved request_admin_elevation call runs a shell command as SYSTEM. A mistaken or manipulated approval is a full-privilege command on your machine.
  • The bot process itself stays at your normal user trust level. Only the broker is elevated, and it only ever runs the canonical command stored for an approved request — the bot passes the broker only a request UUID over a named pipe, never the command text, so the bot can't bypass the approval gate.
  • The broker has a small, non-overridable deny list (e.g. format X:, Remove-Item C:\Windows, reg delete HKLM\SYSTEM), but that is a backstop, not a sandbox. You are the security boundary — every Approve click is you authorizing admin code.

Only install the broker if you understand and accept this. The main bot runs fine without it: request_admin_elevation simply returns "broker not reachable" until the broker is installed and started.

Other security notes:

  • The PreToolUse hook (hooks/pretooluse_guard.py) blocks agent writes to protected directories and blocks reads of secret files (.env, OAuth tokens, the credential dir under ~/.config/domo). It is a mechanical floor, not a complete sandbox.
  • .env holds Discord bot tokens and other secrets. The wizard ACLs it to your user; never commit it. .env.example is the committed template and contains only placeholders.
  • Agents run with permission_mode="bypassPermissions" — they do not prompt before tool use. Scope each agent's enabled_tools in agents.yaml accordingly.

Two-service layout (admin elevation)

domo main service (your user)              domo-elevation-broker (LocalSystem)
  ─── operator agent                         ─── named-pipe server
       ├── request_admin_elevation                ├── reads elevation_requests row
       ├── posts Discord Approve/Deny embed        ├── re-validates: status, sha256, deny list
       ├── awaits the Approve button               ├── spawns elevated subprocess
       └── pipe.write({"request_id": uuid}) ───>   └── pipe.write({exit_code, stdout, stderr})

The two services share data/sessions.sqlite. On bot startup, every pending elevation row is mass-flipped to expired and persistent views are re-bound, so stale embeds resolve to "request expired" rather than Discord's generic "interaction failed".

Install both from an elevated PowerShell:

.\install_service.ps1            # main bot, runs as your user
.\broker\install_broker.ps1      # broker, runs as LocalSystem (see Security)

Layout

  • src/config.py — constants, env loading, the agent registry loader.
  • src/agent_runner.pyAgentRunner + RunnerRegistry (lifecycle, lock, resume, backpressure, credit governor).
  • src/bot.py — Discord clients, routing, streaming, chunking, feature wiring, OAuth sanity loop.
  • src/spawner.pyspawn_thread_agent + delegation MCP tools + multimodal attachment intake.
  • src/cron_scheduler.py / src/cron_store.py / src/cron_tools.py — scheduler loop, store, MCP tools.
  • src/calendar_*.py — CalDAV client + read/write MCP tools.
  • src/specialist_*.py — GPT-5-via-Codex specialist tool + store.
  • src/elevation_*.py / broker/ — Discord-approved admin elevation (operator tool + elevated broker service).
  • src/web/ — FastAPI dashboard (routes, auth, vault browser, static SPA).
  • hooks/pretooluse_guard.py — write/read guard hook.
  • agents.yaml — agent roster. agents/*.md — persona files.
  • wizard.py — interactive first-run setup.

License

MIT — see LICENSE. Builds on the second-brain vault (also MIT).

About

Personal Discord-fronted Claude Code assistant: an operator agent plus a council of specialists, a Mission Control dashboard, cron, calendar, video, a GPT-5 bridge, and admin elevation — runs on top of a second-brain vault.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors