기여
anchor alias
기여
헤르메스 에이전트에 기여해 주셔서 감사합니다! 이 가이드에서는 개발 환경 설정, 코드베이스 이해 및 PR 병합에 대해 다룹니다.
기여 우선순위
우리는 다음 순서로 기여를 평가합니다.
- 버그 수정 — 충돌, 잘못된 동작, 데이터 손실
- 교차 플랫폼 호환성 — macOS, 다양한 Linux 배포판, WSL2
- 보안 강화 — 셸 주입, 프롬프트 주입, 경로 탐색
- 성능 및 견고성 — 재시도 논리, 오류 처리, 점진적 성능 저하
- 새로운 기술 - 광범위하게 유용한 기술(기술 만들기 참조)
- 새로운 도구 — 거의 필요하지 않습니다. 대부분의 능력은 기술이어야 한다
- 문서 — 수정 사항, 설명, 새로운 예
일반적인 기여 경로
- Hermes 코어를 수정하지 않고 사용자 정의/로컬 도구를 구축하시겠습니까? Hermes 플러그인 빌드로 시작하세요.
- Hermes 자체를 위한 새로운 내장 핵심 도구를 구축하시겠습니까? 도구 추가로 시작하세요.
- 새로운 기술을 쌓고 싶으신가요? 스킬 만들기로 시작하세요
- 새로운 추론 제공자를 구축하시겠습니까? 공급자 추가로 시작하세요.
개발 설정
전제 조건
| 요구 사항 | 메모 |
|---|---|
| 기트 | --recurse-submodules 지원 및 git-lfs 확장 설치 |
| 파이썬 3.11+ | 누락된 경우 uv가 설치합니다. |
| uv | 빠른 Python 패키지 관리자(설치) |
| Node.js 20+ | 선택 사항 - 브라우저 도구 및 WhatsApp 브리지에 필요합니다(루트 package.json 엔진과 일치). |
복제 및 설치
git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
# Create venv with Python 3.11
uv venv venv --python 3.11
export VIRTUAL_ENV="$(pwd)/venv"
# Install with all extras (messaging, cron, CLI menus, dev tools)
uv pip install -e ".[all,dev]"
# Optional: browser tools
npm install
개발을 위한 구성
mkdir -p ~/.hermes/{cron,sessions,logs,memories,skills}
cp cli-config.yaml.example ~/.hermes/config.yaml
touch ~/.hermes/.env
# Add at minimum an LLM provider key:
echo 'OPENROUTER_API_KEY=sk-or-v1-your-key' >> ~/.hermes/.env
실행
# Symlink for global access
mkdir -p ~/.local/bin
ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes
# Verify
hermes doctor
hermes chat -q "Hello"
테스트 실행
pytest tests/ -v
코드 스타일
- PEP 8 실제 예외가 있음(엄격한 줄 길이 적용 없음)
- 설명: 명확하지 않은 의도, 장단점 또는 API 문제를 설명하는 경우에만
- 오류 처리: 특정 예외를 포착합니다. 예상치 못한 오류가 발생하면
logger.warning()/logger.error()과exc_info=True을 사용하세요. - 크로스 플랫폼: Unix를 가정하지 마세요(아래 참조).
- 프로필 안전 경로:
~/.hermes을 하드코딩하지 마세요. 코드 경로에는hermes_constants의get_hermes_home()을 사용하고 사용자에게 표시되는 메시지에는display_hermes_home()을 사용하세요. 전체 규칙은 AGENTS.md를 참조하세요.
플랫폼 간 호환성
Hermes는 공식적으로 **Linux, macOS, WSL2 및 기본 Windows(초기 베타 - PowerShell 설치를 통해)**를 지원합니다. 기본 Windows에서는 쉘 명령에 Git Bash(Git for Windows)를 사용합니다. 몇 가지 기능에는 POSIX 커널 기본 요소가 필요하며 제한되어 있습니다. 대시보드의 내장형 PTY 터미널 창(/chat 탭)은 WSL2 전용입니다. 기본 Windows 경로는 새롭고 빠르게 이동합니다. Windows를 많이 사용하는 개발을 수행하는 경우 거친 가장자리에 부딪혀 수정해야 합니다.
코드를 제공할 때 다음 규칙을 염두에 두세요.
- 보호되지 않은
signal.SIGKILL참조를 추가하지 마세요. Windows에서는 정의되지 않습니다.gateway.status.terminate_pid(pid, force=True)(Windows에서는taskkill /T /F, POSIX에서는 SIGKILL을 수행하는 중앙 집중식 기본 요소)을 통해 라우팅하거나getattr(signal, "SIGKILL", signal.SIGTERM)으로 대체합니다. os.kill(pid, 0)프로브에서ProcessLookupError과 함께OSError을 잡으세요. Windows는 대신 이미 사라진 PID에 대해OSError(WinError 87, "매개 변수가 잘못되었습니다")을 발생시킵니다.ProcessLookupError.- 터미널을 POSIX 의미 체계로 강제하지 마십시오.
os.setsid,os.killpg,os.getpgid,os.fork은 모두 Windows에서 발생합니다.if sys.platform != "win32":로 게이트합니다. 또는if os.name != "nt":. - 명시적인
encoding="utf-8"을 사용하여 파일을 엽니다. Windows의 Python 기본값은 라틴어가 아닌 텍스트에서 mojibake 또는 충돌이 발생하는 시스템 로케일(종종 cp1252)입니다. pathlib.Path/os.path.join을 사용하십시오./과 수동으로 연결하지 마십시오. 이것은 OS가 우리에게 돌려주는 문자열에 대해서는 덜 중요하고 우리가 하위 프로세스에 전달하기 위해 구성한 문자열에 대해서는 더 중요합니다.
주요 패턴:
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: ")) - 1
2. 파일 인코딩
일부 환경에서는 .env 파일을 UTF-8이 아닌 인코딩으로 저장할 수 있습니다.
try:
load_dotenv(env_path)
except UnicodeDecodeError:
load_dotenv(env_path, encoding="latin-1")
3. 프로세스 관리
os.setsid(), os.killpg() 및 신호 처리는 플랫폼마다 다릅니다.
import platform
if platform.system() != "Windows":
kwargs["preexec_fn"] = os.setsid
4. 경로 구분자
/과의 문자열 연결 대신 pathlib.Path을 사용하세요.
보안 고려 사항
헤르메스에는 터미널 액세스 권한이 있습니다. 보안이 중요합니다.
기존 보호
| 레이어 | 구현 |
|---|---|
| Sudo 비밀번호 파이핑 | shlex.quote()을 사용하여 쉘 주입을 방지합니다. |
| 위험한 명령 감지 | 사용자 승인 흐름이 포함된 tools/approval.py의 정규식 패턴 |
| 크론 프롬프트 주입 | 스캐너는 명령 재정의 패턴을 차단합니다. |
| 거부 목록 작성 | 심볼릭 링크 우회를 방지하기 위해 os.path.realpath()을 통해 확인된 보호 경로 |
| 스킬 가드 | 허브 설치 스킬에 대한 보안 스캐너 |
| 코드 실행 샌드박스 | API 키가 제거된 상태로 하위 프로세스가 실행됩니다. |
| 컨테이너 경화 | Docker: 모든 기능 삭제, 권한 에스컬레이션 없음, PID 제한 |
보안에 민감한 코드 기여
- 사용자 입력을 쉘 명령에 삽입할 때 항상
shlex.quote()을 사용하십시오. - 액세스 제어 확인 전에
os.path.realpath()을 사용하여 심볼릭 링크를 확인하세요. - 비밀을 기록하지 마세요
- 도구 실행과 관련된 광범위한 예외를 포착하세요.
- 변경 사항이 파일 경로나 프로세스에 영향을 미치는 경우 모든 플랫폼에서 테스트하세요.
풀 요청 프로세스
지점 이름 지정
fix/description # Bug fixes
feat/description # New features
docs/description # Documentation
test/description # Tests
refactor/description # Code restructuring
제출하기 전에
- 테스트 실행:
pytest tests/ -v - 수동 테스트:
hermes을 실행하고 변경한 코드 경로를 실행합니다. - 플랫폼 간 영향 확인: macOS 및 다양한 Linux 배포판 고려
- PR에 집중하세요: PR당 하나의 논리적 변경
홍보설명
포함:
- 변경된 사항 및 이유
- 테스트 방법
- 테스트한 플랫폼
- 관련 문제를 참조하세요.
커밋 메시지
우리는 기존 커밋을 사용합니다.
<type>(<scope>): <description>
| 유형 | 용도 |
|---|---|
fix | 버그 수정 |
feat | 새로운 기능 |
docs | 문서 |
test | 테스트 |
refactor | 코드 재구성 |
chore | 빌드, CI, 종속성 업데이트 |
범위: 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 문제 사용
- 포함: OS, Python 버전, Hermes 버전(
hermes version), 전체 오류 추적 - 재현 단계 포함
- 중복 항목을 만들기 전에 기존 문제를 확인하세요.
- 보안취약점은 비공개로 신고해주세요
커뮤니티
- 디스코드: discord.gg/NousResearch
- GitHub 토론: 디자인 제안 및 아키텍처 토론
- 기술 허브: 전문 기술을 업로드하고 커뮤니티와 공유
라이센스
기여함으로써 귀하는 귀하의 기여가 MIT 라이선스에 따라 라이선스가 부여된다는 데 동의하게 됩니다.