Contribution priorities
We value contributions in this order:- Bug fixes — crashes, incorrect behavior, data loss. Always top priority.
- Cross-platform compatibility — Windows, macOS, different Linux distros, different terminal emulators.
- Security hardening — shell injection, prompt injection, path traversal, privilege escalation.
- Performance and robustness — retry logic, error handling, graceful degradation.
- New skills — broadly useful ones only.
- New tools — rarely needed. Most new capabilities should be skills.
- Documentation — fixes, clarifications, new examples.
Development setup
Clone with submodules
mini-swe-agent is a required terminal backend. The --recurse-submodules flag during clone handles it automatically, but the explicit submodule update is useful after pulling new commits.Install dependencies
[all,dev] extras install messaging platform libraries, CLI menus, cron dependencies, and development tools. mini-swe-agent is installed as an editable package so local changes take effect immediately.Running tests
pytest-xdist and completes in about 3 minutes.
Code style
- PEP 8 with practical exceptions (no strict line length enforcement)
- Comments — only when explaining non-obvious intent, trade-offs, or API quirks. Don’t narrate what the code does.
- Error handling — catch specific exceptions. Log with
logger.warning()/logger.error(), useexc_info=Truefor unexpected errors - Cross-platform — never assume Unix. Use
pathlib.Pathfor paths, guardtermios/fcntlimports, test process management on macOS and Windows
PR process
Branch naming
Before submitting
- Run
python -m pytest tests/ -qand ensure all tests pass - Run
hermesmanually and exercise the code path you changed - Consider cross-platform impact for any changes touching file I/O, process management, or terminal handling
- Keep PRs focused — one logical change per PR
Commit messages
We use Conventional Commits:| Type | Use for |
|---|---|
fix | Bug fixes |
feat | New features |
docs | Documentation |
test | Tests |
refactor | Code restructuring (no behavior change) |
chore | Build, CI, dependency updates |
Known pitfalls
_last_resolved_tool_names is a process-global
_last_resolved_tool_names in model_tools.py is a process-global list. _run_single_child() in delegate_tool.py saves and restores this global around subagent execution. If you add code that reads this global, be aware it may be temporarily stale during child agent runs.
Security considerations
Hermes has terminal access. When contributing security-sensitive code:- Always use
shlex.quote()when interpolating user input into shell commands - Resolve symlinks with
os.path.realpath()before path-based access control checks - Don’t log secrets — API keys, tokens, and passwords must never appear in log output
- Catch broad exceptions around tool execution so a single failure doesn’t crash the agent loop
- Test on all platforms if your change touches file paths, process management, or shell commands
Community
- Discord: discord.gg/NousResearch — questions, skill sharing, and project showcases
- GitHub Issues: github.com/NousResearch/hermes-agent/issues
- GitHub Discussions: Design proposals and architecture discussions