CozyLabs is a desktop wrapper around Hermes Agent β Nous Research's local agent runtime. CozyLabs detects your Hermes profiles, scaffolds a stock six-agent team, and gives you a chat UI on top. No daemon, no cloud, no account. Most people are up and running in about 10 minutes.
Quickstart
Settings has a 4-step onboarding strip that walks you through this. The first time you open the app, follow it top to bottom.
Grab CozyLabs for macOS. Open the DMG, drag to Applications, launch.
On first run the app probes for the hermes CLI; if it isn't on your PATH, the Settings hero shows a transparent install command and a one-click button that pipes the canonical Nous Research install.sh into bash. Output streams live so you can watch what's happening.
macOS only for now. Apple Silicon and Intel both supported. Already have Hermes? CozyLabs auto-detects it β skip ahead.
CozyLabs scans ~/.openclaw/, ~/.clawdbot/, and ~/.moltbot/. If any of them are present, a Migrate from OpenClaw card appears above the agents grid. Hermes does the actual lifting β CozyLabs is just a guided wrapper around its native hermes claw migrate subcommand.
The flow is dry-run first, then confirm. Click Preview migration β CozyLabs runs hermes claw migrate --dry-run and streams the plan into a modal. If it looks right, tick Include API keys (off by default) and click Run migration. Hermes auto-zips a pre-migration backup to ~/.hermes/backups/ before touching anything. After the run, an optional Cleanup step renames the legacy directories to .pre-migration/ so they're out of the way but still recoverable.
What gets migrated: SOUL.md / MEMORY.md / USER.md, skills, model + provider config, MCP servers, messaging tokens (Telegram / Discord / Slack / WhatsApp), approvals, command allowlist, gateway tokens. WhatsApp needs to re-pair. Anything Hermes can't safely move is archived under ~/.hermes/migration/openclaw/<ts>/archive/ for manual review.
CozyLabs ships a Providers panel in Settings that wraps Hermes' native hermes auth and hermes login commands. Credentials never leave Hermes' own ~/.hermes/auth.json β CozyLabs only reads back the connection state. Pick at least one provider; a single agent can use any of them.
hermes login --provider nous and surfaces the device-code URL in a modal127.0.0.1:1234)hermes auth add anthropic --api-key β¦hermes auth add custom --base-url β¦ --api-key β¦All visible behind the Show all providers disclosure on the Providers panel.
Per-agent model selection. Once a provider is connected, expand the Model row on any agent card to pick its provider + model name. Each profile's choice writes to ~/.hermes/profiles/<name>/config.yaml. Sage and Pixel can run different models β that's the whole point.
In Settings, click Set up the starter team. CozyLabs scaffolds six Hermes profiles under ~/.hermes/profiles/ β Sage, Luna, Pixel, Byte, Pip, and Nova. Each gets a default SOUL.md persona you can edit later. Then press β1 for Messages, pick an agent, and start typing β streamed responses render live.
Want the full walkthrough? Jump to Your first conversation β
Architecture
CozyLabs has no daemon and no embedded backend. It's a Mac desktop app pointed at the Hermes Agent gateways already running on your machine β one OpenAI-compatible HTTP server per profile.
You talk to a React renderer. Renderer talks to Electron main over a typed contextBridge. Main probes ~/.hermes/profiles/ on disk and scans loopback ports 8642β8670 for live gateways. When you send a message it streams Server-Sent Events from POST /v1/chat/completions straight back to the renderer.
Each stock agent is a separate Hermes home under ~/.hermes/profiles/<name>/ with its own SOUL.md, MEMORY.md, memories, skills, sessions, cron jobs, and .env. Hermes injects SOUL.md as identity on every turn, so editing it in Settings is the canonical way to reshape an agent's persona.
By default CozyLabs scans loopback ports 8642β8670 for any profile gateway you've already started. Toggle Run via Docker in Settings β Advanced and CozyLabs writes ~/.cozylabs/hermes-compose.yml, then runs docker compose up -d β one nousresearch/hermes-agent:latest container per profile.
Conversations live at ~/.cozylabs/conversations/<agent>/<id>.json, multi-agent channels at ~/.cozylabs/channels/<id>.json, teams at ~/.cozylabs/teams.json. Every write goes through tmp+rename atomicity and a per-key lock; corrupt files get quarantined with a .corrupted-<ts> suffix instead of silently overwritten. A sidecar _index.json per directory makes summary lookups ~950Γ faster than a directory walk.
"Teams" is a CozyLabs-only layer on top of Hermes β a project-manager-led group with a stated goal. When a team member takes a turn (DM or channel), CozyLabs prepends a synthesized team brief to its system prompt: team name, goal, full member roster with role + competencies extracted from each SOUL.md, PM identification, and routing rules (1:1 = DM, 3+ = channel, isolated subtask = delegate_task).
contextIsolation, sandbox, and a strict CSP are all on. Every IPC payload that ends up in a filesystem path passes a path-traversal allowlist; message content is byte-capped at 256 KB; the Electron handleIpc wrapper rejects events from non-main frames; loopback gateways are the only network calls. API keys never leave Hermes' own ~/.hermes/auth.json.
Your Team
"Set up the starter team" scaffolds these six profiles under ~/.hermes/profiles/. Each gets a default SOUL.md persona, MEMORY.md, and a port in the 8642β8647 range. DM any of them, or pull two-or-more into a channel.

Turns plain-English goals into scoped tickets, coordinates specialists, and enforces quality gates. The default project manager when you install a team template.
Delivers clean, accessible UI and keeps handoffs clear for engineering and QA. Picks one screen or flow each Tuesday in the default proactive schedule.

Builds reliable backend systems with tests and concrete validation notes. Runs a weekly health check on Wednesdays scanning for missing tests, error paths, and race conditions.

Finds facts quickly, summarizes decisions, and removes uncertainty before build work starts. Files a weekly research digest every Friday.

Verifies functionality, security basics, and regression risk before approval. Sweeps the last week of merged commits every Thursday for the highest-risk untested behavior.

Hardens deployment workflows and calls out operational risk early. Reviews CI/build config every Monday morning and flags anything brittle.
Each agent's provider and model is independent β pick whichever you like in the per-profile model selector on each agent card.
Providers
CozyLabs ships a Providers panel that wraps Hermes' native hermes auth + hermes login. Connect once for the whole team; each agent can opt into any connected provider via its per-profile model selector.
Open CozyLabs and navigate to:
Two kinds of cards: browser sign-in (OAuth β opens a device-code URL in your browser) and API key (paste-and-connect). Hermes stores credentials at ~/.hermes/auth.json; CozyLabs only reads back connection state.
| Provider | Auth | Hermes ID / env var | Notes |
|---|---|---|---|
| Nous Portal | Browser sign-in | nous |
Default. Hermes' own portal β recommended starting point. |
| OpenAI Codex | Browser sign-in | openai-codex |
Reuses your ChatGPT login. |
| Anthropic | API key | anthropic Β· ANTHROPIC_API_KEY |
Direct Claude access. |
| Google Gemini | API key | gemini Β· GOOGLE_API_KEY |
Google AI Studio key. |
| Google Gemini CLI | Browser sign-in | google-gemini-cli |
If you prefer gcloud auth flow. |
| Qwen | Browser sign-in | qwen-oauth |
Alibaba Qwen via DashScope OAuth. |
| LM Studio | Local, optional | lmstudio Β· LM_API_KEY (optional) |
Defaults to http://127.0.0.1:1234/v1. |
| OpenRouter | API key | openrouter Β· OPENROUTER_API_KEY |
Aggregator β one key, every model. Hermes' implicit fallback. |
| DeepSeek | API key | deepseek Β· DEEPSEEK_API_KEY |
DeepSeek-V3, R1, etc. |
| xAI / Grok | API key | xai Β· XAI_API_KEY |
Grok models via xAI. |
| NVIDIA NIM | API key | nvidia Β· NVIDIA_API_KEY |
Advanced (hidden behind "Show all providers"). |
| Hugging Face | API key | huggingface Β· HF_TOKEN |
Advanced. |
| AWS Bedrock | AWS SDK | bedrock |
Configure via AWS CLI; CozyLabs links out. |
| Custom (OpenAI-compatible) | Optional | custom |
Ollama, vLLM, llama.cpp, your own gateway. Set name + base URL + (optional) key. |
Each Hermes profile picks its own provider + model. The model selector is inline on every agent card in Settings β Your team. Click a card's Model row to expand a small form: provider dropdown, model name, optional base URL for custom.
Save writes to:
Mix providers freely β Sage on Anthropic, Pixel on OpenRouter, Byte on local LM Studio for private code work. Hermes restarts the profile's gateway after a save so changes take effect on the next turn.
Your First Conversation
Open Messages (β1), pick an agent in the sidebar, click New chat, type. No special syntax β plain English. Tokens stream back live.
Renderer to main. The send button fires window.electronAPI.sendMessage(β¦). Main validates the agent id and conversation UUID against an allowlist, caps the content at 256 KB, and persists your turn atomically to ~/.cozylabs/conversations/luna/<id>.json under a per-conversation lock.
Main to Hermes gateway. Main resolves Luna's port (8643 by default), opens POST /v1/chat/completions with stream: true. If Luna's on a team, CozyLabs prepends the team brief as a system message. Hermes injects SOUL.md as identity on its own side.
SSE chunks back. Each delta event hits hermes:message-event, the renderer appends, the bubble grows live. Hit Stop to abort the in-flight controller β main keeps whatever was streamed and tags it as cancelled.
Persist + update sidecar. When the stream ends, main appends the assistant turn to the conversation JSON and updates _index.json for the agent's directory. The sidebar reflects the new last message at immediately because the index lookup is ~25 ms instead of a directory walk.
Things to Try
#team-web-app-team channel and post: "Plan our v1 launch. PM, scope it; specialists weigh in."Two-or-more agents on a thread? Use a channel β pick participants in order, each agent reads the prior turns. PM speaks first when it's a team channel.
Feature Reference
CozyLabs is a small app on purpose. Four tabs, β1ββ4. Everything else lives inside Settings as inline panels.
DMs with each agent and multi-agent channels. Pick a profile in the sidebar, hit New chat, type. Streamed responses render live. Drag & drop or paste to attach images (sent as multimodal content) and text files (folded in as fenced code blocks). Hit / to open a slash palette of installed Hermes skills β /help, /cron, /cozy-team-delegate, plus anything you've added under ~/.hermes/skills/.
A calendar of every cron job each profile owns. Day / Week / Month modes; toggle individual agents off to focus. Click a chip to see the prompt, the next run, and last status. Empty state offers to install a baseline proactive schedule β Sage's MonβFri 8:30 AM standup briefing plus one role-tuned weekly check-in per other agent. Read-only view; create, pause, or delete jobs through any agent's /cron command.
The control surface. A 4-step onboarding strip at the top walks first-runners through install β migrate β providers β team. Below it: the install hero, the per-agent grid (with the inline model selector on each card), the OpenClaw Migrate card when detected, the Providers panel, the Teams panel (PM-led groups with shared goal + auto-created home channel + standup cron), the Messaging gateways panel (Telegram / Discord / Slack / Email), and the Hermes version + update card.
A short page: stock roster cards, what Hermes is, where to file issues. Quick reference for handing off to a teammate.
Three panels do the heavy lifting. They render top-to-bottom in this order:
A 4-step pinned strip at the top of Settings: Install Hermes β Migrate from OpenClaw (only renders when detected) β Connect a model provider β Set up your team. Each step shows a number, a checkmark when done, and a "Do this now" button while it's the next pending step. After all four are complete, the strip shrinks to an "All set β" pill you can dismiss permanently β dismissal persists in ~/.cozylabs/settings.json.
14 providers from the curated catalog. Browser sign-in cards run hermes login --provider <id> in a streaming modal that surfaces the device-code URL. API-key cards take a paste-and-connect input that shells hermes auth add <id> --api-key β¦. Custom providers get name + base URL + optional key. "Show all providers" disclosure exposes the advanced entries (NVIDIA, Hugging Face, Bedrock).
CozyLabs-only group concept layered on top of Hermes profiles. Pick a name, write a goal, choose 2+ members, mark one as project manager β CozyLabs auto-creates a #team-<name> channel with a kickoff system message, seeds a weekday 9 AM team standup cron on the PM, and installs the cozy-team-delegate Hermes skill that teaches members how to route work (1:1 = DM, 3+ = channel, isolated subtask = delegate_task). Three install-once templates: Web App Team, Research Pod, Ship-It Squad. Members can belong to multiple teams; the team brief at turn-time aggregates only teams attached to the current channel.
For Developers
CozyLabs runs zero processes of its own beyond the Electron main process. Everything you'd call "the backend" is the Hermes gateway you (or our compose file) spin up. App data is plain JSON under ~/.cozylabs/; agent state lives where Hermes already keeps it under ~/.hermes/.
Three Electron processes: a React renderer (no global store, hooks only), a typed contextBridge preload, and the Electron main that owns IPC, port scanning, JSON persistence, Docker Compose lifecycle, and the chat-stream bridge.
Every JSON write is atomic (tmp-file + rename) and serialized through a per-key lock. Corrupt files get quarantined to .corrupted-<ts> instead of overwritten. Sidecar _index.json per directory keeps summary lookups O(1).
contextIsolation, sandbox, deny-all permission handler, strict CSP, no webview, deny-window-open. Every IPC handler verifies event.senderFrame === mainWin.webContents.mainFrame. Profile names + UUIDs validated against an allowlist before any join(). Errors pass through a secret-redacting filter before crossing the IPC boundary.
App
Runtime + tests
Source: github.com/shiftedx/CozyLabs-Electron β β clone and npm run dev for hot-reload, npm test for the smoke + integration suites, npm run dist:dmg for a notarized macOS DMG.
Quick Reference