---
sidebar_position: 4
title: "贡献指南"
description: "如何为 Hermes Agent 做贡献 — 开发环境配置、代码风格、PR 流程"
---

# 贡献指南

感谢您为 Hermes Agent 做贡献！本指南涵盖开发环境配置、代码库结构说明以及 PR 合并流程。

## 贡献优先级

我们按以下顺序评估贡献价值：

1. **Bug 修复** — 崩溃、错误行为、数据丢失
2. **跨平台兼容性** — macOS、不同 Linux 发行版、WSL2
3. **安全加固** — shell 注入、prompt（提示词）注入、路径穿越
4. **性能与健壮性** — 重试逻辑、错误处理、优雅降级
5. **新 skill** — 具有广泛用途的 skill（参见 [创建 Skill](creating-skills.md)）
6. **新工具** — 极少需要；大多数能力应以 skill 形式实现
7. **文档** — 修正、说明、新示例

## 常见贡献路径

- 构建自定义/本地工具而不修改 Hermes 核心？从 [构建 Hermes 插件](../developer-guide/plugins/index.md) 开始
- 为 Hermes 本身构建新的内置核心工具？从 [添加工具](./adding-tools.md) 开始
- 构建新的 skill？从 [创建 Skill](./creating-skills.md) 开始
- 构建新的推理提供商？从 [添加提供商](./adding-providers.md) 开始

## 开发环境配置 {#development-setup}

### 前置要求

项目要求 Python 3.14（`>=3.14,<3.15`）。PM 提供固定版本的解释器和工具。
准备 Git 和 git-lfs。JS 构建使用 PM 的 Node/npm，或满足相应 `package.json` engines 的版本。

### PM 开发环境

[PM 开发工作流](../reference/package-management.md#developer-workflow) 包含首次准备、激活、日常使用、依赖更新和当前 bootstrap 限制。
请在准备环境前选择独立的开发 `HERMES_HOME`，避免实验代码迁移生产数据。

成功准备后，每次在仓库根目录的新 shell 中激活已有环境。

Bash：

```bash
source ./activate
hermes --version
```

PowerShell：

```powershell
. .\activate.ps1
hermes --version
```

PowerShell 开头的点和空格用于 dot-source，不能省略。
激活通过 PM 准备工具并同步依赖，但不创建 JS workspaces，也不设置常规 venv 提示符。
激活把 `hermes` 定义成当前 worktree 的函数，因此会盖住全局命令和 MSIX 别名，
并在离开该 worktree 时拒绝运行。
`deactivate` 恢复激活前的环境，不卸载依赖或停止已启动的进程。

### 独立开发和测试环境 {#manual-development-and-test-environment}

先按 [PM 开发工作流](../reference/package-management.md#developer-workflow) 准备 Python 3.14。
在该 checkout 中使用准备好的 Python，并保持相同的开发 `HERMES_HOME`。
PM 必须能够启动，才能构建独立测试环境：

```bash
python -m pm.build_env --source . --out .venv --group dev --group test
```

此命令使用提交的锁文件，创建新环境并检查依赖一致性。输出路径必须不存在。
如需重新生成，请先停止使用该环境的进程，再明确删除该可丢弃的环境。
PM 不会自动删除已有目录。不要通过原始 pip 或 uv 命令修改 Hermes 环境。

测试 runner 自动发现仓库的 `.venv`。它会清除 `PYTHONPATH`，因此 pytest 必须安装在解释器自身的环境中。
也可将 `--out` 指向仓库外的新路径，再将 `HERMES_PYTHON` 设为该环境的解释器。
Windows 上通过 Bash 运行 `scripts/run_tests.sh`，并预先准备本机 C++ 编译环境。

独立测试环境不替代 PM 工具存储或应用的依赖选择。不要修改签名应用的载荷。
运行开发实例前，选择临时的 `HERMES_HOME`，再使用 `hermes setup` 配置它。
不要把生产凭据复制到 checkout。

从仓库根目录运行 `npm ci` 安装 JS workspaces。网站单独使用：

```bash
npm ci --prefix website
npm run build:fast --prefix website
```

图标从 `assets/nous-girl-*.svg` 和 `assets/backgrounds/` 生成。
`node scripts/generate-icons.mjs` 使用 Hermes 运行时 Python（`HERMES_PYTHON`，否则为 PATH 上的 `python`）渲染图标：Pillow 和 resvg-py 是核心依赖。不要提交生成的 PNG/ICO/ICNS 文件。

### 运行测试

```bash
scripts/run_tests.sh
```

该脚本清除凭据环境、设置 UTC 和临时 `HERMES_HOME`，并使用独立子进程运行各测试文件。
不同文件可并行，单个文件内的测试串行执行。不要绕过脚本直接运行 pytest。

## 代码风格

- **PEP 8**，允许合理例外（不强制限制行长度）
- **注释**：仅在解释非显而易见的意图、权衡取舍或 API 特殊行为时添加
- **错误处理**：捕获具体异常。对于意外错误，使用 `logger.warning()`/`logger.error()` 并设置 `exc_info=True`
- **跨平台**：不得假设 Unix 环境（见下文）
- **Profile 安全路径**：不得硬编码 `~/.hermes` — 代码路径使用 `hermes_constants` 中的 `get_hermes_home()`，面向用户的消息使用 `display_hermes_home()`。完整规则参见 [AGENTS.md](https://github.com/NousResearch/hermes-agent/blob/main/AGENTS.md#profiles-multi-instance-support)。

## 跨平台兼容性

Hermes 支持 Linux、macOS、WSL2 和原生 Windows。Windows shell 由 PM 解析 Git Bash。Dashboard 聊天通过 pywinpty/ConPTY 支持原生 Windows，并非仅限 WSL2。平台和依赖限制见[平台支持](../getting-started/platform-support.md)。

贡献代码时，请遵守以下规则：

- **不得添加未加保护的 `signal.SIGKILL` 引用。** Windows 上未定义该信号。请通过 `gateway.status.terminate_pid(pid, force=True)`（集中式原语，Windows 上执行 `taskkill /T /F`，POSIX 上发送 SIGKILL）路由，或使用 `getattr(signal, "SIGKILL", signal.SIGTERM)` 回退。
- **不要在 Windows 上用 `os.kill(pid, 0)` 检查存活。** 使用 `psutil.pid_exists()`；信号调用不是安全的只读检查。
- **不得强制终端使用 POSIX 语义。** `os.setsid`、`os.killpg`、`os.getpgid`、`os.fork` 在 Windows 上均会抛出异常 — 使用 `if sys.platform != "win32":` 或 `if os.name != "nt":` 进行条件判断。
- **打开文件时显式指定 `encoding="utf-8"`。** Windows 上 Python 默认使用系统区域设置（通常为 cp1252），处理非拉丁字符时会出现乱码或崩溃。
- **使用 `pathlib.Path` / `os.path.join`，不得手动用 `/` 拼接路径。** 这对我们构造后传给子进程的字符串尤为重要，而非 OS 返回给我们的字符串。

关键模式：
### 1. 文件编码

某些环境可能以非 UTF-8 编码保存 `.env` 文件：

```python
try:
    load_dotenv(env_path)
except UnicodeDecodeError:
    load_dotenv(env_path, encoding="latin-1")
```

### 2. 进程管理

`os.setsid()`、`os.killpg()` 以及信号处理在各平台间存在差异：

```python
import platform
if platform.system() != "Windows":
    kwargs["preexec_fn"] = os.setsid
```

### 3. 路径分隔符

使用 `pathlib.Path` 代替用 `/` 进行字符串拼接。

## 安全注意事项

Hermes 拥有终端访问权限，安全至关重要。

### 现有保护措施

| 层级 | 实现方式 |
|-------|---------------|
| **sudo 密码管道** | 使用 `shlex.quote()` 防止 shell 注入 |
| **危险命令检测** | `tools/approval.py` 中的正则表达式模式，配合用户审批流程 |
| **Cron prompt 注入** | 扫描器阻断指令覆盖模式 |
| **写入拒绝列表** | 受保护路径通过 `os.path.realpath()` 解析，防止符号链接绕过 |
| **Skill 守卫** | 对 hub 安装的 skill 进行安全扫描 |
| **代码执行沙箱** | 子进程运行时剥离 API 密钥 |
| **容器加固** | Docker：删除所有 capability，禁止权限提升，限制 PID 数量 |

### 贡献安全敏感代码

- 将用户输入插入 shell 命令时，始终使用 `shlex.quote()`
- 访问控制检查前，使用 `os.path.realpath()` 解析符号链接
- 不得记录密钥信息
- 在工具执行周围捕获宽泛异常
- 若您的变更涉及文件路径或进程，请在所有平台上测试

## Pull Request 流程

### 分支命名

```
fix/description        # Bug 修复
feat/description       # 新功能
docs/description       # 文档
test/description       # 测试
refactor/description   # 代码重构
```

### 提交前检查

1. **运行测试**：`scripts/run_tests.sh` 以确保 CI 一致性。仅当 wrapper 不可用或您有意在 wrapper 之外调试时，才使用直接 `python -m pytest ...`。
2. **手动测试**：运行 `hermes` 并验证您修改的代码路径
3. **检查跨平台影响**：考虑 macOS、Linux、WSL2 和原生 Windows。如果您修改了文件 I/O、进程管理、终端处理、子进程或信号相关代码，请运行 `scripts/check-windows-footguns.py`。
4. **保持 PR 聚焦**：每个 PR 只包含一个逻辑变更

### PR 描述

请包含：
- **变更内容**及**变更原因**
- **测试方法**
- **测试平台**
- 关联 issue 引用

### Commit 消息

我们使用 [Conventional Commits](https://www.conventionalcommits.org/)：

```
<type>(<scope>): <description>
```

| 类型 | 适用场景 |
|------|---------|
| `fix` | Bug 修复 |
| `feat` | 新功能 |
| `docs` | 文档 |
| `test` | 测试 |
| `refactor` | 代码重构 |
| `chore` | 构建、CI、依赖更新 |

Scope 范围：`cli`、`gateway`、`tools`、`skills`、`agent`、`install`、`whatsapp`、`security`

示例：
```
fix(cli): prevent crash in save_config_value when model is a string
feat(gateway): add WhatsApp multi-user session isolation
fix(security): prevent shell injection in sudo password piping
```

## 报告问题

- 使用 [GitHub Issues](https://github.com/NousResearch/hermes-agent/issues)
- 请包含：操作系统、Python 版本、Hermes 版本（`hermes --version`）、完整错误堆栈
- 包含复现步骤
- 创建前请检查是否已有重复 issue
- 安全漏洞请私下报告

## 社区

- **Discord**：[discord.gg/NousResearch](https://discord.gg/NousResearch)
- **GitHub Discussions**：用于设计提案和架构讨论
- **Skills Hub**：上传专业 skill 并与社区共享

## 许可证

提交贡献即表示您同意您的贡献将以 [MIT 许可证](https://github.com/NousResearch/hermes-agent/blob/main/LICENSE) 授权。