What you're building
Project Hudson is a multi-agent AI team. The boss is Hermes — an always-on daemon on the Mac mini that receives your Telegram messages and can run on any of 40+ model providers. For project work it acts as a thin relay: each task is dispatched into a headless Claude Code session inside the project-hudson repo, where the orchestration playbook (CLAUDE.md) routes work to the right specialist. Outcomes land in a long-term vector memory store (Postgres + pgvector) and results relay back to your phone.
- 8 engineering
- 4 reliability & ops
- 5 business
- 57 skills
There are two pieces, installed in order: Hermes (the boss gateway), then this repo (the subagents, skills, and memory database). A third short step wires them together.
The model you give Hermes powers only the boss layer — chat, routing, Hermes's own tools. The 17 specialists always run on Claude, via the claude login you set up in step 1. Hermes-on-Qwen (or OpenAI, DeepSeek, a local Ollama model…) works fine as the boss.
Prerequisites
- A Mac mini (or any machine that stays on) for the always-on boss. Any Mac works for a local-only setup.
- Homebrew and Git.
- One database option for the memory store: Docker, native Homebrew Postgres (the setup script installs it for you — recommended on the mini), or a free Neon serverless account.
- A Telegram account, for the bot you'll message.
- A Claude login for Claude Code. If you want Hermes itself on Anthropic without per-token billing, that requires a Claude Max subscription (Pro is not eligible).
Install Hermes — the boss agent
Base tooling
Node runs the Claude Code CLI; uv runs the memory-database MCP server.
brew install node python ripgrep ffmpeg git uv
npm install -g @anthropic-ai/claude-code
claude # log in once; verify with: claude doctor
Hermes itself
The installer is curl-pipe-bash — download it and read it before running it.
curl -fsSL https://hermes-agent.nousresearch.com/install.sh -o /tmp/hermes-install.sh
less /tmp/hermes-install.sh # inspect before running
bash /tmp/hermes-install.sh
source ~/.zshrc
Configuration lives in ~/.hermes/config.yaml; secrets in ~/.hermes/.env. Pin the Hermes version — don't let an unattended machine auto-update.
Pick a model for the boss
Run hermes model to configure and choose. Any of these work:
- Anthropic —
hermes auth add anthropic --type oauthreuses a Claude Max subscription (no per-token billing; Pro is not eligible), or setANTHROPIC_API_KEYin~/.hermes/.env. - Qwen —
DASHSCOPE_API_KEYin~/.hermes/.env, or Qwen Portal OAuth. - OpenAI, OpenRouter, DeepSeek, AWS Bedrock — via API keys.
- Local models — Ollama, vLLM, or LM Studio (any OpenAI-compatible endpoint).
Inside a chat, /model provider:model switches models without losing history or memory.
Create the Telegram bot
This is the abbreviated version — the full walkthrough (signing up, finding your user ID, admitting other people) is the Telegram setup guide.
- Message @BotFather →
/newbot→ copy the token. - Get your numeric Telegram user ID from @userinfobot.
- Add both to
~/.hermes/.env:
TELEGRAM_BOT_TOKEN=<token from BotFather>
TELEGRAM_ALLOWED_USERS=<your numeric user ID>
Always set the user allowlist. Never enable GATEWAY_ALLOW_ALL_USERS=true — a documented fail-open incident exposed gateways to unauthenticated Telegram DMs. Admit new users with Hermes pairing codes (they expire after an hour) instead.
Start the gateway
hermes gateway setup # wizard
hermes gateway start
# logs: ~/.hermes/logs/gateway.log
Install the subagents & memory DB
Cloning is the install — the 17 subagents in .claude/agents/ and the 60 skills in .claude/skills/ register with Claude Code automatically.
git clone https://github.com/lciamp/project-hudson.git ~/repos/project-hudson
cd ~/repos/project-hudson
Start the memory database — pick one
Approve the MCP server
Run claude once inside the repo and approve the project's MCP server from .mcp.json — the postgres server (runs crystaldba/postgres-mcp via uvx, pinned to postgres-mcp==0.3.0, against the local database) for options A/B, or the neon server for option C. This also caches the workspace-trust prompt, so Hermes-spawned headless sessions run friction-free.
Connect Hermes to the subagents
Tell the bot this in your first conversation, so it lands in Hermes's memory:
For any project-hudson work, use the claude-code skill with workdir /Users/<you>/repos/project-hudson, print mode, and resume sessions rather than starting new ones for follow-ups. Don't answer project-hudson questions from your own tools.
This makes Hermes a thin relay: all project work runs inside Claude Code, where the boss playbook and its gates live — security review after auth/input/infra changes, chaos validation for failover claims, approval boundaries — instead of Hermes improvising with its own tools.
Make it always-on
Register the gateway as a launchd LaunchAgent and keep the mini awake:
hermes gateway install # registers login auto-start (launchd)
sudo pmset -a sleep 0 disksleep 0 # prevent sleep
After setup, reboot the mini and confirm the bot responds before trusting it unattended.
Known launchd quirks on macOS
- Exit-78 config errors can leave launchd stuck.
- Restart race: use
hermes gateway stop && sleep 5 && hermes gateway start— avoid a barerestart. - macOS 26+: silent fallback to a detached process — no auto-start or crash restart. Check
hermes gateway statusafter reboots.
Verify
End-to-end, from your phone:
- Ask the bot: "in the project-hudson repo, list your agents" — expect the 17 specialists.
- Send a routed task: "find 5 product ideas in the dev-tools niche" — it should dispatch into Claude Code and come back via
product-researcher+ themarket-niche-scanskill.
Security hardening
Authorization strategy, in order of preference
- Pre-authorize in the repo — commit allow rules to
.claude/settings.jsonso every Hermes session inherits them and remote headless sessions never hit permission prompts. - Per-call flags —
--allowedTools 'Read,Edit,Bash(git status:*),Bash(git diff:*)',--permission-mode acceptEdits. ScopeBashto exact subcommands — never bareBash(git *): git's-c core.pager=…and aliases enable arbitrary shell execution. - Guardrails — always include
--max-turnsand--max-budget-usd.
Never use --dangerously-skip-permissions on an internet-reachable agent — the boundaries in AGENTS.md only hold if enforcement is on.
Hardening checklist
- Keep the bot token out of the repo; revoke via BotFather immediately if it leaks.
- Don't add the bot to public groups — every readable message is injection surface for an agent with shell access.
- Run the gateway under a dedicated macOS user account.
- Rotate the dev database credentials (
project_hudson:project_hudson_dev) outside local development, injected from a secrets manager — never hardcoded. - Ignore third-party "auth bypass" add-ons — they're credential-theft vectors. Use official Max OAuth.
The full walkthrough — launchd caveats, the permission model for headless sessions, and hardening detail — is in docs/hermes-setup.md.
Troubleshooting
| Symptom | Fix |
|---|---|
| Silent after reboot | launchd fell back to a detached process — check hermes gateway status, restart manually. |
Silent after gateway restart | Restart race — use stop && sleep 5 && start. |
| Two machines fighting over the bot | One token per gateway — stop the competing instance. |
--resume fails | Resume must run from the original workdir. |
Session ignores CLAUDE.md | Check the skill's workdir — it must be the repo root. |
| Permission blocked mid-task | Add the tool to .claude/settings.json or --allowedTools. |
Quick reference
| Command | What it does |
|---|---|
claude doctor | Verify the Claude Code install and login. |
hermes model | Configure and switch the boss model. |
hermes gateway setup / start / install | Initialize, run, and auto-start the Telegram gateway. |
/reload-plugins | In Claude Code — pick up agent or skill edits (or start a new session). |
python3 scripts/sync-copilot-agents.py | Regenerate the Copilot agent files after editing agents (--check for CI drift). |
python3 scripts/gen-skills-readme.py | Regenerate the skills index in .claude/skills/README.md after adding or re-describing a skill (--check for CI drift). |
scripts/pack-for-move.sh | Bundle repo + boss memory + DB dump into a zip for migrating machines. |
Using the team without Hermes also works: run claude in the repo and the session itself acts as the boss per CLAUDE.md. The same agents and skills load in GitHub Copilot (VS Code, Copilot CLI, and the cloud agent — which can only reach a Neon database, not a local one).