Getting Started β€” Hermes Edition

You've got a team now.
Let's put them to work.

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.

v0.1.6 Β· Hermes-native Β· macOS Β· local-first

Quickstart

Four steps to your first chat

Settings has a 4-step onboarding strip that walks you through this. The first time you open the app, follow it top to bottom.

1

Download & install Hermes

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.

Download for macOS β€” free

macOS only for now. Apple Silicon and Intel both supported. Already have Hermes? CozyLabs auto-detects it β€” skip ahead.

2

Migrate from OpenClaw β€” if you have a legacy install

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.

3

Connect a model provider

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.

Nous Portal β–Ά
Default Β· browser sign-in
  1. In CozyLabs: Settings β†’ Providers β†’ Connect with browser
  2. CozyLabs runs hermes login --provider nous and surfaces the device-code URL in a modal
  3. Open the URL, authorize, return to the app
βœ“ No API key needed
← Connected? Continue to Step 4
LM Studio LM Studio β–Ά
Best for: fully offline
  1. Download LM Studio β†— and pull a model
  2. Press β–Ά Start Server in LM Studio (defaults to 127.0.0.1:1234)
  3. Settings β†’ Providers β†’ LM Studio β†’ confirm endpoint, no key required
http://127.0.0.1:1234/v1
βœ“ No API key needed
← Connected? Continue to Step 4
Claude Anthropic β–Ά
Best for: writing & reasoning
  1. Grab an API key from console.anthropic.com β†—
  2. Settings β†’ Providers β†’ Anthropic β†’ paste key β†’ Connect
  3. CozyLabs shells hermes auth add anthropic --api-key …
API key (env: ANTHROPIC_API_KEY)
← Connected? Continue to Step 4
OpenRouter β–Ά
One key, every model
  1. Get a key at openrouter.ai β†—
  2. Settings β†’ Providers β†’ OpenRouter β†’ paste key β†’ Connect
  3. OpenRouter aggregates Claude, GPT, Gemini, Llama, etc. β€” pick any model name in the per-profile model selector
API key (env: OPENROUTER_API_KEY)
← Connected? Continue to Step 4
Custom (Ollama / vLLM / …) β–Ά
Anything OpenAI-compatible
  1. Run your OpenAI-compatible server (Ollama, vLLM, llama.cpp, your own gateway, …)
  2. Settings β†’ Providers β†’ Custom β†’ name + base URL + (optional) API key
  3. CozyLabs writes it through hermes auth add custom --base-url … --api-key …
your-server.local:port/v1
βœ“ Optional auth
← Connected? Continue to Step 4
+ 8 more β–Ά
Show all providers
  1. Google Gemini (API key) and Google Gemini CLI (browser sign-in)
  2. OpenAI Codex (browser sign-in)
  3. Qwen (browser sign-in)
  4. DeepSeek (API key)
  5. xAI / Grok (API key)
  6. NVIDIA NIM (API key, advanced)
  7. Hugging Face (API key, advanced)
  8. AWS Bedrock (advanced β€” configure via AWS CLI, not in-app)

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.

4

Set up your team & say hello

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

A small Electron wrapper, a real Hermes runtime

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.

Where each layer lives

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.

React renderer contextBridge IPC Electron main Hermes gateway SSE chunks back
👤
One Hermes profile per agent

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.

🌐
Auto-detect or Docker

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.

💾
All persistence is plain JSON

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 & the team brief

"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).

🛡
Hardened by default

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

The stock six

"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.

Sage
Sage
Workflow Manager

Turns plain-English goals into scoped tickets, coordinates specialists, and enforces quality gates. The default project manager when you install a team template.

"Sage, scope a feature for inviting teammates and assign the work."
Pixel
Pixel
Product UX Engineer

Delivers clean, accessible UI and keeps handoffs clear for engineering and QA. Picks one screen or flow each Tuesday in the default proactive schedule.

"Pixel, review the onboarding flow and propose one shippable improvement."
Byte
Byte
Backend Systems Engineer

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.

"Byte, scope a job-queue worker for the cron-fired team standups."
Luna
Luna
Research Strategist

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

"Luna, compare three approaches to background-job scheduling for a desktop app."
Pip
Pip
QA & Release Reviewer

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

"Pip, identify the highest-risk untested behavior and propose one targeted test."
Nova
Nova
DevOps Automation Engineer

Hardens deployment workflows and calls out operational risk early. Reviews CI/build config every Monday morning and flags anything brittle.

"Nova, audit the release pipeline and surface any deploys-without-rollback paths."

Each agent's provider and model is independent β€” pick whichever you like in the per-profile model selector on each agent card.

Providers

Wire up an LLM provider

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:

Settings β†’ Providers

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.
Per-profile model selection

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:

~/.hermes/profiles/<name>/config.yaml

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

What actually happens when you hit Send

Open Messages (⌘1), pick an agent in the sidebar, click New chat, type. No special syntax β€” plain English. Tokens stream back live.

Luna, summarize the top 3 approaches to background-job scheduling for a desktop app. Note the trade-offs for an MIT-licensed Electron context.
1

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.

2

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.

3

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.

4

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

A team channel
Settings β†’ Teams β†’ Install Web App Team. Open the auto-created #team-web-app-team channel and post: "Plan our v1 launch. PM, scope it; specialists weigh in."
A solo deep-dive
"Luna, compare three desktop background-job schedulers. Cite sources."
A drop-an-image moment
Drag an image onto the composer (or paste it). Pixel + a vision-capable model = inline UX critique. Non-vision models silently ignore the attachment.

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

The four tabs

CozyLabs is a small app on purpose. Four tabs, ⌘1β€“βŒ˜4. Everything else lives inside Settings as inline panels.

Messages ⌘1

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/.

DMs channels slash palette image / text attach streamed SSE conversation history
1
Schedule ⌘2

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.

Day / Week / Month per-agent visibility cron-parser expansion baseline install job detail modal
2
Settings ⌘3

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.

onboarding strip install hero OpenClaw migrate providers teams messaging gateways SOUL.md editor Docker mode toggle
3
About ⌘4

A short page: stock roster cards, what Hermes is, where to file issues. Quick reference for handing off to a teammate.

stock roster credits
4

What lives inside Settings

Three panels do the heavy lifting. They render top-to-bottom in this order:

Onboarding strip

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.

4 steps collapses when done dismissal persists
Providers panel

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).

14 providers browser sign-in API key paste custom endpoint disconnect
Teams panel

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.

PM required auto channel standup cron team brief injection 3 templates multi-team channels

For Developers

No backend. Just Electron + Hermes.

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/.

Process model + persistence

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).

Renderer React 19 + Tailwind 4 Preload contextBridge.exposeInMainWorld Main ipcMain.handle (cozy:* + hermes:*) Hermes 127.0.0.1:8642–8670 (per profile) Cozy data ~/.cozylabs/{conversations, channels, teams.json, settings.json} Hermes data ~/.hermes/{profiles, skills, auth.json} Compose ~/.cozylabs/hermes-compose.yml (Docker mode)
IPC surface β€” invoke channels
  • SETUP hermes:probe-install
  • SETUP hermes:scaffold-stock-team
  • SETUP hermes:run-install / cancel-install
  • CHAT hermes:send-message / cancel-message
  • CHAT hermes:list-conversations / get / create / delete
  • CHAN hermes:create-channel / send-channel-message
  • CRON hermes:list-cron-jobs / install-default-schedule
  • CRON cozy:expand-cron-jobs
  • TEAMS cozy:list-teams / create-team / get-team-brief
  • PROV cozy:list-providers / provider-connect / oauth-start
  • CLAW cozy:probe-openclaw / openclaw-migrate / cleanup
  • SOUL hermes:read-profile-file / write-profile-file
  • MODEL cozy:read-profile-model / write-profile-model
  • ~50 channels total β€” see preload bridge
Streaming events (main β†’ renderer)
main β†’ webContents.send(channel, payload)
hermes:message-event β€” DM SSE chunks (chunk / done / error)
hermes:channel-event β€” multi-agent channel run lifecycle
hermes:install-event β€” Hermes install stdout/stderr
hermes:update-event β€” Hermes update stdout/stderr
cozy:openclaw-event β€” claw migrate / cleanup output
cozy:provider-event β€” hermes login device-code stream
switch-tab β€” tray / app menu navigation
Security posture

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.

Tech Stack

App

Electron 35 React 19 TypeScript 5 Tailwind 4 framer-motion cron-parser electron-vite electron-builder

Runtime + tests

Hermes Agent OpenAI-compat HTTP/SSE Docker Compose (opt-in) node:test tsx puppeteer-core (E2E) Playwright (screenshots) eslint 9 flat config

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

Keyboard Shortcuts

Navigation
⌘1 Messages
⌘2 Schedule
⌘3 Settings
⌘4 About
⌘Q Quit CozyLabs
Messages composer
↡ Send message
⇧↡ New line
/ Slash skill palette
Esc Stop streaming
Modals
Esc Close any modal
drag & drop Β· paste image into composer