hermes-desktop-companion
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseHermes Desktop Companion
Hermes桌面配套工具
Skill by ara.so — Hermes Skills collection.
Hermes Desktop is a native Electron-based desktop application for installing, configuring, and interacting with Hermes Agent — a self-improving AI assistant with tool use, multi-platform messaging, and closed learning loop. It provides a GUI alternative to CLI management with streaming chat, session management, profile switching, skill installation, memory editing, and gateway configuration.
由ara.so开发的Skill——Hermes Skills合集。
Hermes Desktop是一款基于Electron的原生桌面应用,用于安装、配置并与Hermes Agent交互——这是一款具备工具调用、多平台消息功能和闭环学习能力的自我改进型AI助手。它提供了CLI管理的GUI替代方案,支持流式聊天、会话管理、配置文件切换、Skill安装、记忆编辑和网关配置。
What It Does
功能介绍
- Guided installation: First-run wizard installs Hermes Agent to with dependency resolution
~/.hermes - Local or remote mode: Run Hermes locally on or connect to remote API server
127.0.0.1:8642 - Multi-provider support: OpenRouter, Anthropic, OpenAI, Google Gemini, xAI Grok, Nous Portal, Qwen, MiniMax, Hugging Face, Groq, and local OpenAI-compatible endpoints
- Streaming chat UI: SSE-based real-time chat with tool progress, markdown rendering, syntax highlighting, token usage tracking
- 22 slash commands: ,
/new,/clear,/fast,/web,/image,/browse,/code,/shell,/usage,/help,/tools,/skills,/model,/memory,/persona,/version,/compact,/compress,/undo,/retry,/debug/status - Profile management: Multiple isolated Hermes environments with separate configs
- 14 toolsets: Web search, browser automation, terminal, file ops, code execution, vision, image gen, TTS, skills, memory, session search, clarify, delegation, MoA, task planning
- Memory system: View/edit entries, user profile memory, capacity tracking, multiple providers (Honcho, Hindsight, Mem0, RetainDB, Supermemory, ByteRover)
- 16 messaging gateways: Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Mattermost, Email, SMS, iMessage, DingTalk, Feishu, WeCom, WeChat, Webhooks, Home Assistant
- Session search: Full-text search (SQLite FTS5) across conversation history
- Scheduled tasks: Cron job builder with 15 delivery targets
- Hermes Office (Claw3d): Visual 3D interface with adapter management
- 引导式安装:首次运行向导会将Hermes Agent安装到,并自动解决依赖问题
~/.hermes - 本地或远程模式:在本地运行Hermes,或连接到远程API服务器
127.0.0.1:8642 - 多提供商支持:支持OpenRouter、Anthropic、OpenAI、Google Gemini、xAI Grok、Nous Portal、Qwen、MiniMax、Hugging Face、Groq以及本地OpenAI兼容端点
- 流式聊天UI:基于SSE的实时聊天,支持工具进度展示、Markdown渲染、语法高亮、Token使用追踪
- 22条斜杠命令:、
/new、/clear、/fast、/web、/image、/browse、/code、/shell、/usage、/help、/tools、/skills、/model、/memory、/persona、/version、/compact、/compress、/undo、/retry、/debug/status - 配置文件管理:多个独立的Hermes环境,各环境配置相互隔离
- 14套工具集:网页搜索、浏览器自动化、终端、文件操作、代码执行、视觉识别、图像生成、TTS、技能、记忆、会话搜索、问题澄清、任务委派、MoA、任务规划
- 记忆系统:查看/编辑条目、用户配置文件记忆、容量追踪、多提供商支持(Honcho、Hindsight、Mem0、RetainDB、Supermemory、ByteRover)
- 16种消息网关:Telegram、Discord、Slack、WhatsApp、Signal、Matrix、Mattermost、邮件、SMS、iMessage、钉钉、飞书、企业微信、微信、Webhooks、Home Assistant
- 会话搜索:基于SQLite FTS5的对话历史全文搜索
- 定时任务:支持15种交付目标的Cron任务构建器
- Hermes Office(Claw3d):带适配器管理的可视化3D界面
Installation
安装方法
Download Pre-built Binaries
下载预构建二进制文件
Download from GitHub Releases:
| Platform | File |
|---|---|
| macOS | |
| Linux (any) | |
| Debian/Ubuntu | |
| Fedora/RHEL | |
| Windows | |
从GitHub Releases下载:
| 平台 | 文件 |
|---|---|
| macOS | |
| Linux(通用) | |
| Debian/Ubuntu | |
| Fedora/RHEL | |
| Windows | |
macOS Installation
macOS安装
bash
undefinedbash
undefinedAfter installing the .dmg, remove quarantine attribute
安装.dmg后,移除隔离属性
xattr -cr "/Applications/Hermes Agent.app"
Or right-click → **Open** → confirm in dialog.xattr -cr "/Applications/Hermes Agent.app"
或右键点击 → **打开** → 在弹窗中确认。Windows Installation
Windows安装
Download from releases. Windows SmartScreen will warn (unsigned) — click "More info" → "Run anyway".
.exeFuture winget support:
powershell
winget install NousResearch.HermesDesktop从发布页面下载文件。Windows SmartScreen会发出警告(未签名)——点击“更多信息”→“仍要运行”。
.exe未来将支持winget:
powershell
winget install NousResearch.HermesDesktopLinux Installation
Linux安装
AppImage (universal):
bash
chmod +x hermes-desktop-*.AppImage
./hermes-desktop-*.AppImageDebian/Ubuntu:
bash
sudo dpkg -i hermes-desktop-*.deb
sudo apt-get install -f # Fix dependencies if neededFedora/RHEL:
bash
sudo dnf install ./hermes-desktop-*.rpm --nogpgcheckAppImage(通用):
bash
chmod +x hermes-desktop-*.AppImage
./hermes-desktop-*.AppImageDebian/Ubuntu:
bash
sudo dpkg -i hermes-desktop-*.deb
sudo apt-get install -f # 如有需要,修复依赖Fedora/RHEL:
bash
sudo dnf install ./hermes-desktop-*.rpm --nogpgcheckWSL Passwordless Sudo (if installer stalls)
WSL免密码sudo(若安装器停滞)
bash
echo "$USER ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/hermes-installbash
echo "$USER ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/hermes-installRe-run installer, then:
重新运行安装器,完成后执行:
sudo rm /etc/sudoers.d/hermes-install
undefinedsudo rm /etc/sudoers.d/hermes-install
undefinedFirst-Run Setup
首次运行设置
-
Choose deployment mode:
- Local: Installs Hermes to , runs on
~/.hermes127.0.0.1:8642 - Remote: Connect to existing Hermes API server (requires URL + API key)
- Local: Installs Hermes to
-
Local mode: Installer checks for Git, uv, Python 3.11+, then runs official Hermes install script
-
Configure provider: Select from OpenRouter, Anthropic, OpenAI, Google, xAI, Nous Portal, Qwen, MiniMax, Hugging Face, Groq, or custom local endpoint
-
Enter credentials: API keys are saved to Hermes config files (not stored by desktop app)
-
Launch workspace: Main UI opens with Chat, Sessions, Agents, Skills, Memory, Tools, etc.
-
选择部署模式:
- 本地:将Hermes安装到,在
~/.hermes运行127.0.0.1:8642 - 远程:连接到已有的Hermes API服务器(需要URL + API密钥)
- 本地:将Hermes安装到
-
本地模式:安装器会检查Git、uv、Python 3.11+,然后运行官方Hermes安装脚本
-
配置提供商:从OpenRouter、Anthropic、OpenAI、Google、xAI、Nous Portal、Qwen、MiniMax、Hugging Face、Groq或自定义本地端点中选择
-
输入凭证:API密钥会保存到Hermes配置文件中(不会被桌面应用存储)
-
启动工作区:主UI打开,包含聊天、会话、Agent、Skills、记忆、工具等模块
Configuration
配置说明
Provider Configuration
提供商配置
Settings → Provider Config:
typescript
// Example: OpenRouter setup
{
provider: "openrouter",
apiKey: process.env.OPENROUTER_API_KEY,
model: "anthropic/claude-3.5-sonnet",
baseUrl: "https://openrouter.ai/api/v1"
}
// Example: Local Ollama
{
provider: "openai",
apiKey: "not-needed",
model: "llama3.1:8b",
baseUrl: "http://localhost:11434/v1"
}设置 → 提供商配置:
typescript
// 示例:OpenRouter配置
{
provider: "openrouter",
apiKey: process.env.OPENROUTER_API_KEY,
model: "anthropic/claude-3.5-sonnet",
baseUrl: "https://openrouter.ai/api/v1"
}
// 示例:本地Ollama
{
provider: "openai",
apiKey: "not-needed",
model: "llama3.1:8b",
baseUrl: "http://localhost:11434/v1"
}Remote Mode Configuration
远程模式配置
First run:
- Choose "Remote" mode
- Enter API URL:
https://your-hermes-server.com - Enter API key (from remote Hermes )
/api/keys - App validates connection before proceeding
首次运行:
- 选择“远程”模式
- 输入API URL:
https://your-hermes-server.com - 输入API密钥(来自远程Hermes的)
/api/keys - 应用会先验证连接,再继续下一步
Profile (Agent) Management
配置文件(Agent)管理
Agents screen:
- Create new profile: Creates isolated directory
~/.hermes/profiles/<name> - Switch profile: Restarts Hermes with new profile context
- Delete profile: Removes profile directory and data
bash
undefinedAgent界面:
- 创建新配置文件:创建独立的目录
~/.hermes/profiles/<name> - 切换配置文件:使用新配置文件上下文重启Hermes
- 删除配置文件:移除配置文件目录及数据
bash
undefinedProfiles stored at:
配置文件存储路径:
~/.hermes/profiles/
├── default/
│ ├── config.yaml
│ ├── SOUL.md
│ ├── memory.db
│ └── sessions.db
└── work/
└── ...
undefined~/.hermes/profiles/
├── default/
│ ├── config.yaml
│ ├── SOUL.md
│ ├── memory.db
│ └── sessions.db
└── work/
└── ...
undefinedMemory Provider Configuration
记忆提供商配置
Memory screen → Configure Providers:
typescript
// Example: Honcho
{
provider: "honcho",
apiKey: process.env.HONCHO_API_KEY,
appId: "hermes-desktop",
userId: "user-123"
}
// Example: Mem0
{
provider: "mem0",
apiKey: process.env.MEM0_API_KEY,
userId: "user-123"
}记忆界面 → 配置提供商:
typescript
// 示例:Honcho
{
provider: "honcho",
apiKey: process.env.HONCHO_API_KEY,
appId: "hermes-desktop",
userId: "user-123"
}
// 示例:Mem0
{
provider: "mem0",
apiKey: process.env.MEM0_API_KEY,
userId: "user-123"
}Gateway Configuration
网关配置
Gateway screen → Select platform → Configure:
Telegram:
yaml
enabled: true
bot_token: ${TELEGRAM_BOT_TOKEN}
allowed_users: [123456789]Discord:
yaml
enabled: true
token: ${DISCORD_BOT_TOKEN}
channel_ids: [1234567890123456789]Email (IMAP/SMTP):
yaml
enabled: true
imap_server: imap.gmail.com
imap_port: 993
smtp_server: smtp.gmail.com
smtp_port: 587
username: ${EMAIL_USERNAME}
password: ${EMAIL_APP_PASSWORD}WhatsApp (via Baileys):
yaml
enabled: true
session_path: ~/.hermes/whatsapp-session
qr_code_callback: true网关界面 → 选择平台 → 配置:
Telegram:
yaml
enabled: true
bot_token: ${TELEGRAM_BOT_TOKEN}
allowed_users: [123456789]Discord:
yaml
enabled: true
token: ${DISCORD_BOT_TOKEN}
channel_ids: [1234567890123456789]邮件(IMAP/SMTP):
yaml
enabled: true
imap_server: imap.gmail.com
imap_port: 993
smtp_server: smtp.gmail.com
smtp_port: 587
username: ${EMAIL_USERNAME}
password: ${EMAIL_APP_PASSWORD}WhatsApp(通过Baileys):
yaml
enabled: true
session_path: ~/.hermes/whatsapp-session
qr_code_callback: trueChat Interface Usage
聊天界面使用
Basic Chat
基础聊天
Type naturally or use slash commands:
> What's the weather in San Francisco?
[Hermes uses web search tool, returns answer]
> /web latest news on AI regulation
[Forces web search, streams results]
> /image a cyberpunk city at sunset
[Generates image via FAL.ai or configured provider]自然输入或使用斜杠命令:
> 旧金山的天气如何?
[Hermes使用网页搜索工具,返回结果]
> /web AI监管的最新消息
[强制触发网页搜索,流式返回结果]
> /image 日落时分的赛博朋克城市
[通过FAL.ai或已配置的提供商生成图像]Slash Commands
斜杠命令
| Command | Description |
|---|---|
| Start new conversation |
| Clear current chat |
| Switch to faster model |
| Force web search |
| Generate image |
| Browse and extract from URL |
| Execute code task |
| Run shell command |
| Show token usage stats |
| List all commands |
| Show enabled tools |
| List installed skills |
| Get/set current model |
| Search memory |
| Show current persona |
| Show Hermes version |
| Compress chat history |
| Deep compress with MoA |
| Remove last message |
| Retry last message |
| Toggle debug mode |
| Show system status |
| 命令 | 描述 |
|---|---|
| 开始新对话 |
| 清空当前聊天 |
| 切换到更快的模型 |
| 强制网页搜索 |
| 生成图像 |
| 浏览并提取URL内容 |
| 执行代码任务 |
| 运行Shell命令 |
| 显示Token使用统计 |
| 列出所有命令 |
| 显示已启用的工具 |
| 列出已安装的Skill |
| 获取/设置当前模型 |
| 搜索记忆内容 |
| 显示当前角色设定 |
| 显示Hermes版本 |
| 压缩聊天历史 |
| 通过MoA深度压缩 |
| 删除上一条消息 |
| 重试上一条消息 |
| 切换调试模式 |
| 显示系统状态 |
Token Usage Tracking
Token使用追踪
Bottom of chat shows live counts:
📊 Prompt: 1,234 tokens • Completion: 567 tokens • Cost: $0.0123Use for detailed breakdown:
/usage> /usage
Session Usage:
Total Prompt Tokens: 12,345
Total Completion Tokens: 5,678
Total Cost: $0.123
Messages: 15聊天界面底部显示实时统计:
📊 提示词: 1,234 tokens • 回复: 567 tokens • 费用: $0.0123使用查看详细 breakdown:
/usage> /usage
会话使用情况:
总提示词Token: 12,345
总回复Token: 5,678
总费用: $0.123
消息数: 15Skills Management
Skills管理
Installing Skills
安装Skills
Skills screen:
- Browse bundled skills (pre-installed with Hermes)
- Or install from GitHub:
Repository: username/repo-name Branch: main (optional) - Click Install
Skills界面:
- 浏览内置Skill(随Hermes预安装)
- 或从GitHub安装:
Repository: username/repo-name Branch: main(可选) - 点击 安装
Skill Structure
Skill结构
Skills are markdown files with YAML frontmatter:
markdown
---
name: web-search-expert
description: Expert at web searching and information retrieval
triggers:
- "search the web for"
- "find information about"
- "look up"
---Skills是带有YAML前置元数据的Markdown文件:
markdown
---
name: web-search-expert
description: 擅长网页搜索和信息检索
triggers:
- "search the web for"
- "find information about"
- "look up"
---Web Search Expert
网页搜索专家
Use the web_search tool to find current information...
使用web_search工具查找最新信息...
Examples
示例
When user asks: "What's the latest on GPT-5?"
- Use web_search with query "GPT-5 latest news"
- Summarize findings
- Cite sources
undefined当用户提问: "GPT-5的最新动态是什么?"
- 使用web_search工具,查询词为"GPT-5 latest news"
- 总结搜索结果
- 标注来源
undefinedEditing Skills
编辑Skills
Skills screen → Click skill → Edit:
- Modify triggers, description, or content
- Changes saved to
~/.hermes/skills/<name>/SKILL.md
Skills界面 → 点击Skill → 编辑:
- 修改触发词、描述或内容
- 更改会保存到
~/.hermes/skills/<name>/SKILL.md
Memory System
记忆系统
Viewing Memory
查看记忆
Memory screen:
- Memory Entries: List of stored facts/context
- User Profile: Persistent user information
- Capacity: Current usage vs. limit
记忆界面:
- 记忆条目: 已存储的事实/上下文列表
- 用户配置文件: 持久化的用户信息
- 容量: 当前使用量与上限对比
Adding Memory
添加记忆
Chat naturally — Hermes auto-saves important context:
> My name is Alice and I prefer Python over JavaScript
[Hermes stores to memory automatically]
> What's my name?
[Hermes retrieves: "Alice"]Or explicit:
> Remember I'm working on a TypeScript project called Hermes Desktop
[Hermes: ✓ Stored to memory]自然聊天即可——Hermes会自动保存重要上下文:
> 我叫Alice,比起JavaScript我更喜欢Python
[Hermes自动保存到记忆中]
> 我叫什么名字?
[Hermes检索到: "Alice"]或手动添加:
> 记住我正在开发一个名为Hermes Desktop的TypeScript项目
[Hermes: ✓ 已存储到记忆]Editing Memory Entries
编辑记忆条目
Memory screen:
- Click entry to view
- Edit content or delete
- Save changes
记忆界面:
- 点击条目查看详情
- 编辑内容或删除
- 保存更改
Memory Providers
记忆提供商
Configured in Memory screen → Configure Providers:
- Honcho: Managed memory service
- Hindsight: Self-hosted memory
- Mem0: Personalized AI memory
- RetainDB: Vector memory DB
- Supermemory: Context-aware memory
- ByteRover: Local memory store
在记忆界面 → 配置提供商中设置:
- Honcho: 托管式记忆服务
- Hindsight: 自托管记忆
- Mem0: 个性化AI记忆
- RetainDB: 向量记忆数据库
- Supermemory: 上下文感知记忆
- ByteRover: 本地记忆存储
Session Management
会话管理
Searching Sessions
搜索会话
Sessions screen:
- Search bar: Full-text search (SQLite FTS5) across all conversations
- Date groups: Conversations grouped by Today, Yesterday, Last 7 Days, Last 30 Days, Older
typescript
// Example: Search sessions programmatically (if extending app)
import { searchSessions } from './main/database';
const results = await searchSessions('typescript error handling');
// Returns: [{ id, title, timestamp, snippet, profileId }, ...]会话界面:
- 搜索栏: 基于SQLite FTS5的所有对话全文搜索
- 日期分组: 对话按今日、昨日、最近7天、最近30天、更早分组
typescript
// 示例:扩展应用时程序化搜索会话
import { searchSessions } from './main/database';
const results = await searchSessions('typescript error handling');
// 返回: [{ id, title, timestamp, snippet, profileId }, ...]Resuming Sessions
恢复会话
- Sessions screen → Click conversation
- Chat loads with full history
- Continue conversation from last message
- 会话界面 → 点击对话
- 加载完整聊天历史
- 从最后一条消息继续对话
Deleting Sessions
删除会话
Right-click session → Delete or click trash icon.
右键点击会话 → 删除 或点击垃圾桶图标。
Tools Management
工具管理
Tools screen → Enable/disable toolsets:
| Toolset | Capabilities |
|---|---|
| web | Exa/Tavily search, Firecrawl scraping |
| browser | Playwright automation, screenshot, PDF |
| terminal | Shell command execution |
| file | Read, write, list, move files |
| code | Python execution in sandbox |
| vision | Image analysis (GPT-4V, Claude Vision) |
| image | Generation via FAL.ai/DALL-E |
| tts | Text-to-speech synthesis |
| skills | Install/manage skills |
| memory | Store/retrieve context |
| session | Search past conversations |
| clarify | Ask clarifying questions |
| delegation | Multi-agent task delegation |
| moa | Mixture-of-Agents synthesis |
| planning | Break down complex tasks |
Example enabling web tool:
yaml
undefined工具界面 → 启用/禁用工具集:
| 工具集 | 功能 |
|---|---|
| web | Exa/Tavily搜索、Firecrawl爬取 |
| browser | Playwright自动化、截图、PDF生成 |
| terminal | Shell命令执行 |
| file | 文件读写、列出、移动 |
| code | 沙箱中执行Python代码 |
| vision | 图像分析(GPT-4V、Claude Vision) |
| image | 通过FAL.ai/DALL-E生成图像 |
| tts | 文本转语音合成 |
| skills | 安装/管理Skill |
| memory | 存储/检索上下文 |
| session | 搜索过往对话 |
| clarify | 提出澄清问题 |
| delegation | 多Agent任务委派 |
| moa | 多Agent混合合成 |
| planning | 拆解复杂任务 |
启用web工具示例:
yaml
undefined~/.hermes/profiles/default/config.yaml
~/.hermes/profiles/default/config.yaml
tools:
web:
enabled: true
exa_api_key: ${EXA_API_KEY}
tavily_api_key: ${TAVILY_API_KEY}
undefinedtools:
web:
enabled: true
exa_api_key: ${EXA_API_KEY}
tavily_api_key: ${TAVILY_API_KEY}
undefinedScheduled Tasks
定时任务
Schedules screen → Create Task:
yaml
name: "Daily standup summary"
schedule: "0 9 * * 1-5" # 9 AM weekdays
task: "Summarize yesterday's GitHub activity and send to Slack"
delivery:
type: slack
channel: "#standup"Schedule types:
- Minutes: Every N minutes
- Hourly: Every N hours
- Daily: Specific time daily
- Weekly: Specific day/time weekly
- Custom: Full cron expression
Delivery targets:
Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, SMS, Webhook, Home Assistant, File, Terminal, Memory, Chat (in-app), Desktop Notification
计划任务界面 → 创建任务:
yaml
name: "每日站会总结"
schedule: "0 9 * * 1-5" # 工作日上午9点
task: "总结昨天的GitHub活动并发送到Slack"
delivery:
type: slack
channel: "#standup"计划类型:
- 分钟级: 每N分钟执行一次
- 小时级: 每N小时执行一次
- 每日: 每日特定时间执行
- 每周: 每周特定日期/时间执行
- 自定义: 完整Cron表达式
交付目标:
Telegram、Discord、Slack、WhatsApp、Signal、Matrix、邮件、SMS、Webhook、Home Assistant、文件、终端、记忆、聊天(应用内)、桌面通知
Development Setup
开发环境设置
Prerequisites
前置要求
bash
node --version # v18+ recommended
npm --version # v9+bash
node --version # 推荐v18+
npm --version # v9+Clone and Install
克隆并安装依赖
bash
git clone https://github.com/fathah/hermes-desktop.git
cd hermes-desktop
npm installbash
git clone https://github.com/fathah/hermes-desktop.git
cd hermes-desktop
npm installDevelopment Mode
开发模式
bash
npm run devThis starts:
- Vite dev server for React UI
- Electron main process with hot reload
- TypeScript watch compiler
bash
npm run dev该命令会启动:
- 用于React UI的Vite开发服务器
- 带热重载的Electron主进程
- TypeScript监视编译器
Project Structure
项目结构
hermes-desktop/
├── src/
│ ├── main/ # Electron main process
│ │ ├── index.ts # Entry point, IPC handlers
│ │ ├── database.ts # SQLite sessions/memory
│ │ ├── installer.ts # Hermes install logic
│ │ └── updater.ts # Auto-update
│ ├── preload/ # Electron preload script
│ │ └── index.ts # IPC bridge to renderer
│ └── renderer/ # React UI
│ ├── App.tsx
│ ├── screens/ # Chat, Sessions, Tools, etc.
│ ├── components/
│ └── lib/ # SSE parser, utils
├── electron.vite.config.ts
├── package.json
└── resources/ # Icons, installershermes-desktop/
├── src/
│ ├── main/ # Electron主进程
│ │ ├── index.ts # 入口文件,IPC处理器
│ │ ├── database.ts # SQLite会话/记忆数据库
│ │ ├── installer.ts # Hermes安装逻辑
│ │ └── updater.ts # 自动更新
│ ├── preload/ # Electron预加载脚本
│ │ └── index.ts # 渲染进程的IPC桥接
│ └── renderer/ # React UI
│ ├── App.tsx
│ ├── screens/ # 聊天、会话、工具等界面
│ ├── components/
│ └── lib/ # SSE解析器、工具函数
├── electron.vite.config.ts
├── package.json
└── resources/ # 图标、安装器资源IPC Communication Pattern
IPC通信模式
Renderer → Main:
typescript
// src/renderer/lib/api.ts
export async function sendChatMessage(message: string, profileId: string) {
return window.electron.ipcRenderer.invoke('chat:send', { message, profileId });
}Main handler:
typescript
// src/main/index.ts
ipcMain.handle('chat:send', async (event, { message, profileId }) => {
const response = await fetch('http://127.0.0.1:8642/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message, profile: profileId })
});
// Stream SSE events back to renderer
});渲染进程 → 主进程:
typescript
// src/renderer/lib/api.ts
export async function sendChatMessage(message: string, profileId: string) {
return window.electron.ipcRenderer.invoke('chat:send', { message, profileId });
}主进程处理器:
typescript
// src/main/index.ts
ipcMain.handle('chat:send', async (event, { message, profileId }) => {
const response = await fetch('http://127.0.0.1:8642/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message, profile: profileId })
});
// 将SSE事件流式返回给渲染进程
});SSE Streaming Implementation
SSE流式实现
typescript
// src/renderer/lib/sse-parser.ts
export class SSEParser {
private buffer = '';
parse(chunk: string): SSEEvent[] {
this.buffer += chunk;
const lines = this.buffer.split('\n');
this.buffer = lines.pop() || '';
const events: SSEEvent[] = [];
let currentEvent: Partial<SSEEvent> = {};
for (const line of lines) {
if (line.startsWith('event:')) {
currentEvent.event = line.slice(7).trim();
} else if (line.startsWith('data:')) {
currentEvent.data = line.slice(6).trim();
} else if (line === '') {
if (currentEvent.event) {
events.push(currentEvent as SSEEvent);
}
currentEvent = {};
}
}
return events;
}
}Usage in Chat:
typescript
// src/renderer/screens/Chat.tsx
const parser = new SSEParser();
fetch('http://127.0.0.1:8642/chat', {
method: 'POST',
body: JSON.stringify({ message })
}).then(async (response) => {
const reader = response.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const events = parser.parse(chunk);
for (const event of events) {
if (event.event === 'content') {
appendContent(JSON.parse(event.data).text);
} else if (event.event === 'tool_start') {
showToolProgress(JSON.parse(event.data));
} else if (event.event === 'usage') {
updateTokenCount(JSON.parse(event.data));
}
}
}
});typescript
// src/renderer/lib/sse-parser.ts
export class SSEParser {
private buffer = '';
parse(chunk: string): SSEEvent[] {
this.buffer += chunk;
const lines = this.buffer.split('\n');
this.buffer = lines.pop() || '';
const events: SSEEvent[] = [];
let currentEvent: Partial<SSEEvent> = {};
for (const line of lines) {
if (line.startsWith('event:')) {
currentEvent.event = line.slice(7).trim();
} else if (line.startsWith('data:')) {
currentEvent.data = line.slice(6).trim();
} else if (line === '') {
if (currentEvent.event) {
events.push(currentEvent as SSEEvent);
}
currentEvent = {};
}
}
return events;
}
}聊天中的使用:
typescript
// src/renderer/screens/Chat.tsx
const parser = new SSEParser();
fetch('http://127.0.0.1:8642/chat', {
method: 'POST',
body: JSON.stringify({ message })
}).then(async (response) => {
const reader = response.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const events = parser.parse(chunk);
for (const event of events) {
if (event.event === 'content') {
appendContent(JSON.parse(event.data).text);
} else if (event.event === 'tool_start') {
showToolProgress(JSON.parse(event.data));
} else if (event.event === 'usage') {
updateTokenCount(JSON.parse(event.data));
}
}
}
});Building for Production
生产环境构建
Build All Platforms (current OS)
构建所有平台(当前操作系统)
bash
npm run buildOutput: directory with installers
dist/bash
npm run build输出目录: ,包含安装器
dist/Platform-Specific Builds
特定平台构建
bash
npm run build:win # Windows .exe
npm run build:mac # macOS .dmg
npm run build:linux # .AppImage, .deb, .rpmbash
npm run build:win # Windows .exe
npm run build:mac # macOS .dmg
npm run build:linux # .AppImage, .deb, .rpmBuild Configuration
构建配置
Edit :
electron-builder.ymlyaml
appId: com.nousresearch.hermesdesktop
productName: Hermes Agent
directories:
output: dist
buildResources: resources
mac:
target:
- dmg
- zip
category: public.app-category.productivity
icon: resources/icon.icns
win:
target:
- nsis
icon: resources/icon.ico
linux:
target:
- AppImage
- deb
- rpm
category: Utility
icon: resources/icon.png编辑:
electron-builder.ymlyaml
appId: com.nousresearch.hermesdesktop
productName: Hermes Agent
directories:
output: dist
buildResources: resources
mac:
target:
- dmg
- zip
category: public.app-category.productivity
icon: resources/icon.icns
win:
target:
- nsis
icon: resources/icon.ico
linux:
target:
- AppImage
- deb
- rpm
category: Utility
icon: resources/icon.pngTroubleshooting
故障排除
Installer Stalls on "Installing dependencies"
安装器在“安装依赖”步骤停滞
WSL: Grant temporary passwordless sudo (see Installation section)
General: Check logs in :
~/.hermes/logs/install.logbash
tail -f ~/.hermes/logs/install.logWSL: 授予临时免密码sudo权限(见安装部分)
通用方法: 查看日志:
~/.hermes/logs/install.logbash
tail -f ~/.hermes/logs/install.log"Connection refused" on 127.0.0.1:8642
127.0.0.1:8642
连接被拒绝
127.0.0.1:8642Hermes not running. Start manually:
bash
cd ~/.hermes
source venv/bin/activate
python -m hermes.serverOr restart from Settings → Restart Hermes.
Hermes未运行。手动启动:
bash
cd ~/.hermes
source venv/bin/activate
python -m hermes.server或从设置 → 重启Hermes重启。
Remote mode connection fails
远程模式连接失败
- Verify URL is reachable:
curl https://your-hermes-server.com/health - Check API key in remote Hermes:
hermes keys list - Ensure firewall allows traffic
- 验证URL可访问:
curl https://your-hermes-server.com/health - 检查远程Hermes中的API密钥:
hermes keys list - 确保防火墙允许流量
Memory provider not connecting
记忆提供商连接失败
Check API keys in Memory → Configure Providers:
typescript
// Test Honcho connection
const response = await fetch('https://api.honcho.dev/apps', {
headers: { 'Authorization': `Bearer ${process.env.HONCHO_API_KEY}` }
});检查记忆 → 配置提供商中的API密钥:
typescript
// 测试Honcho连接
const response = await fetch('https://api.honcho.dev/apps', {
headers: { 'Authorization': `Bearer ${process.env.HONCHO_API_KEY}` }
});Gateway fails to send messages
网关无法发送消息
- View logs: Settings → View Logs → Select gateway
- Telegram: Verify bot token with , check allowed_users IDs
@BotFather - Discord: Ensure bot has permission in channel
SEND_MESSAGES - Email: Test SMTP credentials with
telnet smtp.server.com 587
- 查看日志: 设置 → 查看日志 → 选择网关
- Telegram: 通过验证机器人令牌,检查allowed_users ID
@BotFather - Discord: 确保机器人在频道中拥有权限
SEND_MESSAGES - 邮件: 使用测试SMTP凭证
telnet smtp.server.com 587
Skills not triggering
Skills未触发
- Check triggers in skill YAML frontmatter are specific
- Ensure skill is enabled: Skills screen → Check toggle
- Restart profile: Agents → Switch away and back
- 检查Skill的YAML前置元数据中的触发词是否明确
- 确保Skill已启用: Skills界面 → 检查开关
- 重启配置文件: Agent → 切换到其他配置文件再切回
Auto-update fails (Fedora RPM)
自动更新失败(Fedora RPM)
RPM builds don't support auto-update. Download new and reinstall:
.rpmbash
sudo dnf install ./hermes-desktop-<new-version>.rpm --nogpgcheckRPM构建不支持自动更新。下载新的文件并重新安装:
.rpmbash
sudo dnf install ./hermes-desktop-<new-version>.rpm --nogpgcheckChat stuck on "Thinking..."
聊天卡在“思考中...”
- Check network:
curl -I http://127.0.0.1:8642/health - Check model provider API status (OpenRouter, Anthropic, etc.)
- View debug logs: in chat or Settings → View Logs → Agent
/debug
- 检查网络:
curl -I http://127.0.0.1:8642/health - 检查模型提供商API状态(OpenRouter、Anthropic等)
- 查看调试日志: 在聊天中输入或设置 → 查看日志 → Agent
/debug
Session search returns no results
会话搜索无结果
Database index corrupt. Rebuild FTS5 index:
bash
cd ~/.hermes/profiles/default
sqlite3 sessions.db "DELETE FROM sessions_fts; INSERT INTO sessions_fts SELECT * FROM sessions;"数据库索引损坏。重建FTS5索引:
bash
cd ~/.hermes/profiles/default
sqlite3 sessions.db "DELETE FROM sessions_fts; INSERT INTO sessions_fts SELECT * FROM sessions;"macOS "App is damaged" error
macOS提示“应用已损坏”错误
Remove quarantine:
bash
xattr -cr "/Applications/Hermes Agent.app"移除隔离属性:
bash
xattr -cr "/Applications/Hermes Agent.app"Windows SmartScreen blocks installer
Windows SmartScreen阻止安装器
Click "More info" → "Run anyway" (app is not code-signed).
点击“更多信息”→“仍要运行”(应用未签名)。
Environment Variables
环境变量
bash
undefinedbash
undefinedLLM Providers
LLM提供商
OPENROUTER_API_KEY=sk-or-...
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...
GOOGLE_API_KEY=...
XAI_API_KEY=...
OPENROUTER_API_KEY=sk-or-...
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...
GOOGLE_API_KEY=...
XAI_API_KEY=...
Search/Web Tools
搜索/网页工具
EXA_API_KEY=...
TAVILY_API_KEY=...
FIRECRAWL_API_KEY=...
EXA_API_KEY=...
TAVILY_API_KEY=...
FIRECRAWL_API_KEY=...
Image Generation
图像生成
FAL_API_KEY=...
REPLICATE_API_TOKEN=...
FAL_API_KEY=...
REPLICATE_API_TOKEN=...
Memory Providers
记忆提供商
HONCHO_API_KEY=...
MEM0_API_KEY=...
HONCHO_API_KEY=...
MEM0_API_KEY=...
Messaging Gateways
消息网关
TELEGRAM_BOT_TOKEN=...
DISCORD_BOT_TOKEN=...
SLACK_BOT_TOKEN=...
TWILIO_ACCOUNT_SID=...
TWILIO_AUTH_TOKEN=...
TELEGRAM_BOT_TOKEN=...
DISCORD_BOT_TOKEN=...
SLACK_BOT_TOKEN=...
TWILIO_ACCOUNT_SID=...
TWILIO_AUTH_TOKEN=...
邮件
EMAIL_USERNAME=...
EMAIL_APP_PASSWORD=...
EMAIL_USERNAME=...
EMAIL_APP_PASSWORD=...
Analytics
分析
WANDB_API_KEY=...
Store in `~/.hermes/.env` or OS-level environment.WANDB_API_KEY=...
存储在`~/.hermes/.env`或操作系统级环境变量中。Testing
测试
Run Tests
运行测试
bash
npm testTest suites:
- SSE parser: Validates event parsing, incomplete chunks, malformed data
- IPC handlers: Mock Electron IPC, test chat/session/profile handlers
- Preload API: Ensures all main process APIs are safely exposed
- Installer utils: Dependency checking, path resolution
- Constants: Validates config schema, provider definitions
bash
npm test测试套件:
- SSE解析器: 验证事件解析、不完整块处理、格式错误数据处理
- IPC处理器: 模拟Electron IPC,测试聊天/会话/配置文件处理器
- 预加载API: 确保所有主进程API安全暴露
- 安装器工具: 依赖检查、路径解析
- 常量: 验证配置 schema、提供商定义
Example Test
测试示例
typescript
// src/__tests__/sse-parser.test.ts
import { describe, it, expect } from 'vitest';
import { SSEParser } from '../renderer/lib/sse-parser';
describe('SSEParser', () => {
it('parses complete events', () => {
const parser = new SSEParser();
const events = parser.parse('event: content\ndata: {"text":"Hello"}\n\n');
expect(events).toHaveLength(1);
expect(events[0].event).toBe('content');
expect(JSON.parse(events[0].data).text).toBe('Hello');
});
it('buffers incomplete events', () => {
const parser = new SSEParser();
const events1 = parser.parse('event: content\n');
const events2 = parser.parse('data: {"text":"Hi"}\n\n');
expect(events1).toHaveLength(0);
expect(events2).toHaveLength(1);
});
});typescript
// src/__tests__/sse-parser.test.ts
import { describe, it, expect } from 'vitest';
import { SSEParser } from '../renderer/lib/sse-parser';
describe('SSEParser', () => {
it('解析完整事件', () => {
const parser = new SSEParser();
const events = parser.parse('event: content\ndata: {"text":"Hello"}\n\n');
expect(events).toHaveLength(1);
expect(events[0].event).toBe('content');
expect(JSON.parse(events[0].data).text).toBe('Hello');
});
it('缓冲不完整事件', () => {
const parser = new SSEParser();
const events1 = parser.parse('event: content\n');
const events2 = parser.parse('data: {"text":"Hi"}\n\n');
expect(events1).toHaveLength(0);
expect(events2).toHaveLength(1);
});
});Resources
资源
- Documentation: https://hermes-agent.nousresearch.com/docs/
- GitHub Repository: https://github.com/fathah/hermes-desktop
- Releases: https://github.com/fathah/hermes-desktop/releases
- Telegram Community: https://t.me/hermes_agent_desktop
- Issue Tracker: https://github.com/fathah/hermes-desktop/issues
- Hermes Agent Core: https://github.com/NousResearch/hermes-agent
- 文档: https://hermes-agent.nousresearch.com/docs/
- GitHub仓库: https://github.com/fathah/hermes-desktop
- 发布版本: https://github.com/fathah/hermes-desktop/releases
- Telegram社区: https://t.me/hermes_agent_desktop
- 问题追踪: https://github.com/fathah/hermes-desktop/issues
- Hermes Agent核心: https://github.com/NousResearch/hermes-agent