感谢你为 Hermes Agent 做出贡献!本指南涵盖如何设置开发环境、理解代码库,以及让你的 PR 被合并。
我们按以下顺序重视贡献:
- Bug 修复 —— 崩溃、错误行为、数据丢失
- 跨平台兼容性 —— macOS、不同 Linux 发行版、WSL2
- 安全加固 —— shell injection、prompt injection、path traversal
- 性能和健壮性 —— retry logic、error handling、graceful degradation
- 新 skills —— 广泛有用的 skills(参见 Creating Skills)
- 新 tools —— 很少需要;大多数能力应该通过 skills 实现
- 文档 —— 修复、澄清、新示例
常见贡献路径
Section titled “常见贡献路径”- 不修改 Hermes core,构建自定义 / 本地 tool?从 Build a Hermes Plugin 开始
- 为 Hermes 本身构建新的内置核心 tool?从 Adding Tools 开始
- 构建新的 skill?从 Creating Skills 开始
- 构建新的 inference provider?从 Adding Providers 开始
开发环境设置
Section titled “开发环境设置”| 要求 | 说明 |
|---|---|
| Git | 支持 --recurse-submodules,并已安装 git-lfs 扩展 |
| Python 3.11+ | 如果缺失,uv 会安装它 |
| uv | 快速 Python 包管理器(安装) |
| Node.js 20+ | 可选 —— browser tools 和 WhatsApp bridge 需要(与根目录 package.json 的 engines 匹配) |
git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.gitcd hermes-agent
# Create venv with Python 3.11uv venv venv --python 3.11export VIRTUAL_ENV="$(pwd)/venv"
# Install with all extras (messaging, cron, CLI menus, dev tools)uv pip install -e ".[all,dev]"
# Optional: browser toolsnpm install为开发进行配置
Section titled “为开发进行配置”mkdir -p ~/.hermes/{cron,sessions,logs,memories,skills}cp cli-config.yaml.example ~/.hermes/config.yamltouch ~/.hermes/.env
# Add at minimum an LLM provider key:echo 'OPENROUTER_API_KEY=sk-or-v1-your-key' >> ~/.hermes/.env# Symlink for global accessmkdir -p ~/.local/binln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes
# Verifyhermes doctorhermes chat -q "Hello"pytest tests/ -v- PEP 8,但有实际例外(不强制严格行长度)
- 注释:只在解释非显而易见的意图、权衡或 API 特性时使用
- 错误处理:捕获具体异常。对于意外错误,使用
logger.warning()/logger.error()并设置exc_info=True - 跨平台:永远不要假设 Unix(见下文)
- Profile-safe paths:永远不要硬编码
~/.hermes—— 代码路径使用hermes_constants中的get_hermes_home(),面向用户的消息使用display_hermes_home()。完整规则见AGENTS.md。
跨平台兼容性
Section titled “跨平台兼容性”Hermes 官方支持 Linux、macOS、WSL2,以及原生 Windows(早期 beta —— 通过 PowerShell 安装)。原生 Windows 使用 Git Bash(来自 Git for Windows)来执行 shell 命令。少数功能需要 POSIX 内核原语,因此会被限制:dashboard 的嵌入式 PTY terminal pane(/chat tab)仅支持 WSL2。原生 Windows 路径是新的,并且变化很快 —— 如果你进行大量 Windows 相关开发,预期会遇到并修复一些粗糙边角。
贡献代码时,请记住这些规则:
- 不要添加未保护的
signal.SIGKILL引用。它在 Windows 上未定义。要么通过gateway.status.terminate_pid(pid, force=True)(集中式 primitive,在 Windows 上执行taskkill /T /F,在 POSIX 上执行SIGKILL),要么使用getattr(signal, "SIGKILL", signal.SIGTERM)回退。 - 在
os.kill(pid, 0)探测中,除了ProcessLookupError,也要捕获OSError。Windows 会对已经不存在的 PID 抛出OSError(WinError 87,“parameter is incorrect”),而不是ProcessLookupError。 - 不要强制 terminal 使用 POSIX 语义。
os.setsid、os.killpg、os.getpgid、os.fork在 Windows 上都会抛错 —— 请使用if sys.platform != "win32":或if os.name != "nt":进行门控。 - 打开文件时显式使用
encoding="utf-8"。Windows 上 Python 默认使用系统 locale(通常是cp1252),这会导致非拉丁文本乱码或崩溃。 - 使用
pathlib.Path/os.path.join—— 永远不要手动用/拼接路径。对于 OS 返回给我们的字符串来说影响较小,但对于我们构造后传给 subprocesses 的字符串来说更重要。
关键模式:
1. termios 和 fcntl 仅限 Unix
Section titled “1. termios 和 fcntl 仅限 Unix”始终同时捕获 ImportError 和 NotImplementedError:
try: from simple_term_menu import TerminalMenu menu = TerminalMenu(options) idx = menu.show()except (ImportError, NotImplementedError): # Fallback: numbered menu for i, opt in enumerate(options): print(f" {i+1}. {opt}") idx = int(input("Choice: ")) - 12. 文件编码
Section titled “2. 文件编码”某些环境可能会用非 UTF-8 编码保存 .env 文件:
try: load_dotenv(env_path)except UnicodeDecodeError: load_dotenv(env_path, encoding="latin-1")3. 进程管理
Section titled “3. 进程管理”os.setsid()、os.killpg() 和 signal handling 在不同平台上有所不同:
import platformif platform.system() != "Windows": kwargs["preexec_fn"] = os.setsid4. 路径分隔符
Section titled “4. 路径分隔符”使用 pathlib.Path,而不是用 / 进行字符串拼接。
安全注意事项
Section titled “安全注意事项”Hermes 拥有 terminal 访问权限。安全很重要。
现有保护措施
Section titled “现有保护措施”| 层级 | 实现 |
|---|---|
| Sudo password piping | 使用 shlex.quote() 防止 shell injection |
| Dangerous command detection | tools/approval.py 中的 Regex patterns,并带有用户 approval flow |
| Cron prompt injection | Scanner 会阻止 instruction-override patterns |
| Write deny list | 通过 os.path.realpath() 解析受保护路径,防止 symlink 绕过 |
| Skills guard | 针对 hub-installed skills 的 security scanner |
| Code execution sandbox | 子进程运行时会剥离 API keys |
| Container hardening | Docker:移除所有 capabilities、禁止 privilege escalation、设置 PID limits |
贡献安全敏感代码
Section titled “贡献安全敏感代码”- 将用户输入插入 shell commands 时,始终使用
shlex.quote() - 在进行 access control checks 之前,使用
os.path.realpath()解析 symlinks - 不要记录 secrets
- 在 tool execution 周围捕获 broad exceptions
- 如果你的变更涉及 file paths 或 processes,请在所有平台上测试
Pull Request 流程
Section titled “Pull Request 流程”Branch 命名
Section titled “Branch 命名”fix/description # Bug fixesfeat/description # New featuresdocs/description # Documentationtest/description # Testsrefactor/description # Code restructuring- 运行测试:
pytest tests/ -v - 手动测试:运行
hermes,并执行你修改过的代码路径 - 检查跨平台影响:考虑 macOS 和不同 Linux 发行版
- 保持 PR 聚焦:每个 PR 只做一个逻辑变更
包含:
- 变更了什么,以及为什么
- 如何测试
- 你在哪些平台上测试过
- 引用任何相关 issues
Commit Messages
Section titled “Commit Messages”我们使用 Conventional Commits:
<type>(<scope>): <description>| Type | 用途 |
|---|---|
| fix | Bug 修复 |
| feat | 新功能 |
| docs | 文档 |
| test | 测试 |
| refactor | 代码重构 |
| chore | 构建、CI、依赖更新 |
Scopes:cli、gateway、tools、skills、agent、install、whatsapp、security
示例:
fix(cli): prevent crash in save_config_value when model is a stringfeat(gateway): add WhatsApp multi-user session isolationfix(security): prevent shell injection in sudo password piping报告 Issues
Section titled “报告 Issues”- 使用 GitHub Issues
- 包含:OS、Python 版本、Hermes 版本(
hermes version)、完整错误 traceback - 包含复现步骤
- 创建重复 issue 前,请先检查已有 issues
- 对于安全漏洞,请私下报告
- Discord:
discord.gg/NousResearch - GitHub Discussions:用于设计提案和架构讨论
- Skills Hub:上传专用 skills,并与社区分享
通过贡献,你同意你的贡献将基于 MIT License 授权。