Pular para o conteúdo principal

Documentação oficial desta página · v0.20.6

Contribuir

Obrigado por contribuir com o Hermes Agent! Este guia cobre como montar o seu ambiente de desenvolvimento, entender a base de código e conseguir que o seu PR seja aceito.

Prioridades de contribuição​

Valorizamos as contribuições nesta ordem:

  1. Correções de bug — travamentos, comportamento errado, perda de dados
  2. Compatibilidade entre plataformas — macOS, distribuições Linux variadas, WSL2
  3. Endurecimento de segurança — injeção de shell, injeção de prompt, travessia de caminho
  4. Desempenho e robustez — lógica de repetição, tratamento de erro, degradação suave
  5. Skills novas — as de utilidade ampla (veja Criar Skills)
  6. Ferramentas novas — raramente necessárias; a maioria das capacidades deveria ser skill
  7. Documentação — correções, esclarecimentos, exemplos novos

Caminhos comuns de contribuição​

Preparar o ambiente de desenvolvimento​

Pré-requisitos​

RequisitoObservações
GitCom a extensão git-lfs instalada
Python 3.11–3.13O uv instala se estiver faltando
uvGerenciador rápido de pacotes Python (instalação)
Node.js 26+Opcional — necessário para as ferramentas de navegador e a ponte do WhatsApp (bate com os engines do package.json da raiz)

Instalar com o instalador padrão​

Para a maioria de quem contribui, o melhor caminho de desenvolvimento é o mesmo que os usuários seguem: rode o instalador padrão e trabalhe dentro do repositório que ele clonou. O instalador cria o venv do Hermes, liga o comando hermes, carimba o método de instalação para o hermes update e clona o projeto git inteiro em $HERMES_HOME/hermes-agent (em geral ~/.hermes/hermes-agent). Isso mantém o seu ambiente de desenvolvimento no mesmo layout que a CLI, o atualizador, o instalador preguiçoso de dependências, o gateway e a documentação assumem.

curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
cd "${HERMES_HOME:-$HOME/.hermes}/hermes-agent"

# Acrescente os extras de dev/teste por cima da instalação padrão.
uv pip install -e ".[all,dev]"

# Opcional: ferramentas de navegador / dependências do site de documentação.
npm install

Depois disso, crie branches e rode os testes a partir desse checkout:

git checkout -b fix/descricao
scripts/run_tests.sh

Você também pode rodar uma instância do Hermes totalmente isolada (HERMES_HOME descartável, userData do Electron separado, nome de aplicativo Electron distinto para evitar a trava de instância única):

scripts/dev-sandbox.sh python -m hermes_cli.main
scripts/dev-sandbox.sh --persistent python -m hermes_cli.main desktop # o estado sobrevive a reinícios, mas mora na worktree :)

Plano B: clone manual​

Use isto só se você não quiser mesmo o layout de instalação gerenciado do Hermes (por exemplo, um clone descartável dentro de um contêiner ou de um job de CI). Se você instalar assim, garanta que roda o ponto de entrada hermes deste venv; rodar o python3 -m hermes_cli.main do sistema pode pegar pacotes Python do sistema sem relação nenhuma.

Crie o venv fora da árvore de código clonada. Um venv que mora dentro do diretório de onde o agente opera pode ser apagado por um comando de caminho relativo que o agente rode contra o próprio checkout (rm -rf venv, uv venv venv, etc.), o que destrói em silêncio o runtime em execução no meio da sessão. Mantê-lo fora da árvore significa que nenhum caminho relativo a partir do espaço de trabalho chega até ele.

git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent

# Crie o venv com Python 3.11, FORA da árvore de código
uv venv ~/.hermes/venvs/hermes-dev --python 3.11
export VIRTUAL_ENV="$HOME/.hermes/venvs/hermes-dev"
export PATH="$VIRTUAL_ENV/bin:$PATH"

# Instale com todos os extras (mensagens, cron, menus da CLI, ferramentas de dev)
uv pip install -e ".[all,dev]"

# Opcional: ferramentas de navegador
npm install

Configurar para desenvolvimento​

mkdir -p ~/.hermes/{cron,sessions,logs,memories,skills}
cp cli-config.yaml.example ~/.hermes/config.yaml
touch ~/.hermes/.env

# Acrescente no mínimo uma chave de provedor de LLM:
echo 'OPENROUTER_API_KEY=sk-or-v1-sua-chave' >> ~/.hermes/.env

Rodar​

# O instalador padrão já colocou o `hermes` no PATH.
hermes doctor
hermes chat -q "Olá"

Se você usou o plano B do clone manual, rode ./hermes a partir do checkout ou crie um link simbólico explícito para o venv deste clone:

mkdir -p ~/.local/bin
ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes

Rodar os testes​

scripts/run_tests.sh

Estilo de código​

  • PEP 8 com exceções práticas (sem imposição rígida de comprimento de linha)
  • Comentários: só quando explicam intenção não óbvia, escolhas de projeto ou manias de API
  • Tratamento de erro: capture exceções específicas. Use logger.warning()/logger.error() com exc_info=True para erros inesperados
  • Entre plataformas: nunca assuma Unix (veja abaixo)
  • Caminhos seguros para perfis: nunca fixe ~/.hermes no código — use get_hermes_home() de hermes_constants nos caminhos de código e display_hermes_home() nas mensagens que o usuário vê. Veja o AGENTS.md para as regras completas.

Compatibilidade entre plataformas​

Veja Suporte a plataformas. O Windows nativo usa o Git Bash (do Git for Windows) para os comandos de shell. Alguns recursos exigem primitivos de kernel POSIX e ficam limitados: o painel de terminal PTY embutido no dashboard (aba /chat) precisa de um PTY POSIX (Linux, macOS ou WSL2). Se você faz muito desenvolvimento voltado a Windows, rode o lint de armadilhas do Windows (scripts/check-windows-footguns.py) antes de enviar.

Ao contribuir com código, tenha estas regras em mente:

  • Não acrescente referências a signal.SIGKILL sem proteção. Ele não existe no Windows. Ou passe por gateway.status.terminate_pid(pid, force=True) (o primitivo centralizado que faz taskkill /T /F no Windows e SIGKILL no POSIX), ou recorra a getattr(signal, "SIGKILL", signal.SIGTERM).
  • Capture OSError junto com ProcessLookupError nas sondagens os.kill(pid, 0). O Windows levanta OSError (WinError 87, "parameter is incorrect") para um PID que já sumiu, em vez de ProcessLookupError.
  • Não force o terminal à semântica POSIX. os.setsid, os.killpg, os.getpgid e os.fork levantam erro no Windows — proteja-os com if sys.platform != "win32": ou if os.name != "nt":.
  • Abra arquivos com um encoding="utf-8" explícito. O padrão do Python no Windows é a localidade do sistema (muitas vezes cp1252), que embaralha ou quebra em texto fora do alfabeto latino.
  • Use pathlib.Path / os.path.join — nunca concatene à mão com /. Isso importa menos para as strings que o sistema operacional nos devolve e mais para as strings que construímos para entregar a subprocessos.

Padrões principais:

1. Codificação de arquivo​

Alguns ambientes podem salvar arquivos .env em codificações que não são UTF-8:

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

2. Gerenciamento de processos​

os.setsid(), os.killpg() e o tratamento de sinais variam entre plataformas:

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

3. Separadores de caminho​

Use pathlib.Path em vez de concatenar strings com /.

Considerações de segurança​

O Hermes tem acesso ao terminal. Segurança importa.

Proteções já existentes​

CamadaImplementação
Envio da senha de sudoUsa shlex.quote() para evitar injeção de shell
Detecção de comando perigosoPadrões de regex em tools/approval.py com fluxo de aprovação do usuário
Injeção de prompt no cronO scanner bloqueia padrões de sobrescrita de instrução
Lista de negação de escritaCaminhos protegidos resolvidos por os.path.realpath() para evitar desvio por link simbólico
Guarda de skillsScanner de segurança para skills instaladas pelo hub
Sandbox de execução de códigoO processo filho roda com as chaves de API removidas
Endurecimento de contêinerDocker: todas as capacidades removidas, sem escalada de privilégio, limites de PID

Contribuir com código sensível a segurança​

  • Sempre use shlex.quote() ao interpolar entrada do usuário em comandos de shell
  • Resolva links simbólicos com os.path.realpath() antes das checagens de controle de acesso
  • Não registre segredos em log
  • Capture exceções amplas ao redor da execução de ferramentas
  • Teste em todas as plataformas se a sua mudança encosta em caminhos de arquivo ou em processos

Processo de pull request​

Nomes de branch​

fix/descricao # Correções de bug
feat/descricao # Recursos novos
docs/descricao # Documentação
test/descricao # Testes
refactor/descricao # Reestruturação de código

Antes de enviar​

  1. Rode os testes: scripts/run_tests.sh para ficar igual à CI. Use python -m pytest ... direto só quando o wrapper não estiver disponível ou quando você estiver depurando fora dele de propósito.
  2. Teste na mão: rode o hermes e exercite o caminho de código que você mudou
  3. Confira o impacto entre plataformas: pense em macOS, Linux, WSL2 e Windows nativo. Se você encostar em E/S de arquivo, gerenciamento de processos, tratamento de terminal, subprocessos ou sinais, rode o scripts/check-windows-footguns.py.
  4. Mantenha os PRs focados: uma mudança lógica por PR

Descrição do PR​

Inclua:

  • O que mudou e por quê
  • Como testar
  • Em quais plataformas você testou
  • Referência a qualquer issue relacionada

Mensagens de commit​

Usamos Conventional Commits:

<type>(<scope>): <description>
TipoUse para
fixCorreções de bug
featRecursos novos
docsDocumentação
testTestes
refactorReestruturação de código
choreBuild, CI, atualização de dependência

Escopos: cli, gateway, tools, skills, agent, install, whatsapp, security

Exemplos:

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

Listas de revisão locais do repositório: .agents/checks/*.md​

Projetos construídos sobre (ou revisados pelo) Hermes podem manter listas de verificação de revisão dentro do repositório, em .agents/checks/. Cada arquivo é uma lista focada, em markdown puro, que um agente carrega antes de revisar uma mudança que encoste na área correspondente:

.agents/
checks/
security.md # ex.: "procure interpolação de shell no diff; confira se as chamadas de subprocesso citam os argumentos"
migrations.md # ex.: "toda mudança de esquema vem com backfill e nota de reversão"
public-api.md # ex.: "assinaturas exportadas mudaram? marque para revisão de semver"

Convenções que fazem isso funcionar bem:

  • Uma preocupação por arquivo, com o nome da preocupação. Arquivos pequenos são lidos por inteiro; um checklist.md monolítico é lido por cima.
  • Escreva as checagens como ações verificáveis ("rode X e confirme Y"), não como aspirações ("o código deve ser seguro").
  • Diga o gatilho logo no começo — a quais caminhos ou tipos de mudança a lista se aplica — para que um agente (ou uma pessoa) possa pular barato as que não interessam.
  • Mantenha-as no controle de versão ao lado do código que elas guardam: assim evoluem junto com a base de código, e um PR que muda as regras muda a lista no mesmo diff.

Quando você pedir ao Hermes para revisar um PR em um repositório que tem .agents/checks/, diga a ele (ou ensine por uma skill) para ler primeiro as listas relevantes e relatar em relação a elas. Isso dá aos agentes de revisão o critério específico do projeto que os prompts genéricos de revisão deixam passar.

Relatar problemas​

  • Use as GitHub Issues
  • Inclua: sistema operacional, versão do Python, versão do Hermes (hermes --version), traceback completo do erro
  • Inclua os passos para reproduzir
  • Confira as issues existentes antes de criar duplicatas
  • Para vulnerabilidades de segurança, relate em privado, por favor

Comunidade​

  • Discord: discord.gg/NousResearch
  • GitHub Discussions: para propostas de projeto e discussões de arquitetura
  • Skills Hub: publique skills especializadas e compartilhe com a comunidade

Licença​

Ao contribuir, você concorda que as suas contribuições serão licenciadas sob a Licença MIT.