sidebar_position: 4 title: "Contributing" description: "How to contribute to Hermes Agent — dev setup, code style, PR process" #
Contributing #
Thank you for contributing to Hermes Agent! This guide covers setting up your dev environment, understanding the codebase, and getting your PR merged.
Contribution Priorities #
We value contributions in this order:
- Bug fixes — crashes, incorrect behavior, data loss
- Cross-platform compatibility — macOS, different Linux distros, WSL2
- Security hardening — shell injection, prompt injection, path traversal
- Performance and robustness — retry logic, error handling, graceful degradation
- New skills — broadly useful ones (see Creating Skills)
- New tools — rarely needed; most capabilities should be skills
- Documentation — fixes, clarifications, new examples
Common contribution paths #
- Building a new tool? Start with Adding Tools
- Building a new skill? Start with Creating Skills
- Building a new inference provider? Start with Adding Providers
Development Setup #
Prerequisites #
| Requirement | Notes |
|---|---|
| Git | With --recurse-submodules support, and the git-lfs extension installed |
| Python 3.11+ | uv will install it if missing |
| uv | Fast Python package manager (install) |
| Node.js 20+ | Optional — needed for browser tools and WhatsApp bridge (matches root package.json engines) |
Clone and Install #
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]"
uv pip install -e "./tinker-atropos"
# Optional: browser tools
npm install
Configure for Development #
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
Run #
# Symlink for global access
mkdir -p ~/.local/bin
ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes
# Verify
hermes doctor
hermes chat -q "Hello"
Run Tests #
pytest tests/ -v
Code Style #
- PEP 8 with practical exceptions (no strict line length enforcement)
- Comments: Only when explaining non-obvious intent, trade-offs, or API quirks
- Error handling: Catch specific exceptions. Use
logger.warning()/logger.error()withexc_info=Truefor unexpected errors - Cross-platform: Never assume Unix (see below)
- Profile-safe paths: Never hardcode
~/.hermes— useget_hermes_home()fromhermes_constantsfor code paths anddisplay_hermes_home()for user-facing messages. See AGENTS.md for full rules.
Cross-Platform Compatibility #
Hermes officially supports Linux, macOS, and WSL2. Native Windows is not supported, but the codebase includes some defensive coding patterns to avoid hard crashes in edge cases. Key rules:
1. termios and fcntl are Unix-only #
Always catch both ImportError and 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. File encoding #
Some environments may save .env files in non-UTF-8 encodings:
try:
load_dotenv(env_path)
except UnicodeDecodeError:
load_dotenv(env_path, encoding="latin-1")
3. Process management #
os.setsid(), os.killpg(), and signal handling differ across platforms:
import platform
if platform.system() != "Windows":
kwargs["preexec_fn"] = os.setsid
4. Path separators #
Use pathlib.Path instead of string concatenation with /.
Security Considerations #
Hermes has terminal access. Security matters.
Existing Protections #
| Layer | Implementation |
|---|---|
| Sudo password piping | Uses shlex.quote() to prevent shell injection |
| Dangerous command detection | Regex patterns in tools/approval.py with user approval flow |
| Cron prompt injection | Scanner blocks instruction-override patterns |
| Write deny list | Protected paths resolved via os.path.realpath() to prevent symlink bypass |
| Skills guard | Security scanner for hub-installed skills |
| Code execution sandbox | Child process runs with API keys stripped |
| Container hardening | Docker: all capabilities dropped, no privilege escalation, PID limits |
Contributing Security-Sensitive Code #
- Always use
shlex.quote()when interpolating user input into shell commands - Resolve symlinks with
os.path.realpath()before access control checks - Don't log secrets
- Catch broad exceptions around tool execution
- Test on all platforms if your change touches file paths or processes
Pull Request Process #
Branch Naming #
fix/description # Bug fixes
feat/description # New features
docs/description # Documentation
test/description # Tests
refactor/description # Code restructuring
Before Submitting #
- Run tests:
pytest tests/ -v - Test manually: Run
hermesand exercise the code path you changed - Check cross-platform impact: Consider macOS and different Linux distros
- Keep PRs focused: One logical change per PR
PR Description #
Include:
- What changed and why
- How to test it
- What platforms you tested on
- Reference any related issues
Commit Messages #
We use Conventional Commits:
<type>(<scope>): <description>
| Type | Use for |
|---|---|
fix |
Bug fixes |
feat |
New features |
docs |
Documentation |
test |
Tests |
refactor |
Code restructuring |
chore |
Build, CI, dependency updates |
Scopes: cli, gateway, tools, skills, agent, install, whatsapp, security
Examples:
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
Reporting Issues #
- Use GitHub Issues
- Include: OS, Python version, Hermes version (
hermes version), full error traceback - Include steps to reproduce
- Check existing issues before creating duplicates
- For security vulnerabilities, please report privately
Community #
- Discord: discord.gg/NousResearch
- GitHub Discussions: For design proposals and architecture discussions
- Skills Hub: Upload specialized skills and share with the community
License #
By contributing, you agree that your contributions will be licensed under the MIT License.