From 25f3d0857ce5f7f387d19ca2adaf82a20f24a188 Mon Sep 17 00:00:00 2001 From: iacker Date: Mon, 13 Jul 2026 09:55:56 +0200 Subject: [PATCH 1/2] docs: add French translations (README, CONTRIBUTING, SECURITY) Adds French versions of the core documentation following the existing locale-suffix convention (README.es.md, CONTRIBUTING.es.md, SECURITY.es.md): - README.fr.md - CONTRIBUTING.fr.md - SECURITY.fr.md Translated from the current English sources by a native French speaker. Technical identifiers (commands, paths, env vars, provider/model names, URLs, code blocks) are kept verbatim. The English LICENSE remains the authoritative legal version. Closes #60535 Signed-off-by: iacker --- CONTRIBUTING.fr.md | 1022 ++++++++++++++++++++++++++++++++++++++++++++ README.fr.md | 265 ++++++++++++ SECURITY.fr.md | 371 ++++++++++++++++ 3 files changed, 1658 insertions(+) create mode 100644 CONTRIBUTING.fr.md create mode 100644 README.fr.md create mode 100644 SECURITY.fr.md diff --git a/CONTRIBUTING.fr.md b/CONTRIBUTING.fr.md new file mode 100644 index 0000000000000..f6330cba0e906 --- /dev/null +++ b/CONTRIBUTING.fr.md @@ -0,0 +1,1022 @@ +# Contribuer à Hermes Agent + +Merci de contribuer à Hermes Agent ! Ce guide couvre tout ce dont vous avez besoin : mettre en place votre environnement de développement, comprendre l'architecture, décider quoi construire et faire fusionner votre PR. + +--- + +## Priorités de contribution + +Nous valorisons les contributions dans cet ordre : + +1. **Corrections de bugs** — plantages, comportement incorrect, perte de données. Toujours la priorité absolue. +2. **Compatibilité multiplateforme** — macOS, différentes distributions Linux et WSL2 sous Windows. Nous voulons qu'Hermes fonctionne partout. +3. **Durcissement de la sécurité** — injection shell, injection de prompt, traversée de chemins, élévation de privilèges. Voir [Sécurité](#considérations-de-sécurité). +4. **Performance et robustesse** — logique de nouvelle tentative, gestion des erreurs, dégradation contrôlée. +5. **Nouvelles compétences** — mais uniquement celles largement utiles. Voir [Compétence ou outil ?](#compétence-ou-outil-) +6. **Nouveaux outils** — rarement nécessaires. La plupart des capacités devraient être des compétences. Voir plus bas. +7. **Documentation** — corrections, clarifications, nouveaux exemples. + +--- + +## Avant de commencer : cherchez d'abord + +Une recherche rapide avant de vous lancer vous fait gagner du temps et garde la file des PR propre — les doublons sont fréquents ici, alors une minute en amont vaut le coup. + +- **Cherchez dans les PR et issues ouvertes *et* fusionnées** votre sujet ou le symptôme de votre erreur — la vérification de doublons du template de PR n'intervient qu'au moment de la revue, une fois le travail déjà fait : + ```bash + gh search issues --repo NousResearch/hermes-agent "" + gh search prs --repo NousResearch/hermes-agent --state all "" + ``` + Ou passez par l'interface web : [issues](https://github.com/NousResearch/hermes-agent/issues?q=) · [PRs (tous états)](https://github.com/NousResearch/hermes-agent/pulls?q=is%3Apr). +- **Le suivi des issues peut être en retard sur le code.** Beaucoup de fonctionnalités demandées sont déjà implémentées dans l'arborescence ; cherchez donc aussi la capacité dans le code source (`search_files`, ou le grep de votre éditeur) avant de la proposer. +- **Si une PR ouverte traite déjà le sujet**, envisagez de la relire ou de l'améliorer plutôt que d'ouvrir un doublon concurrent. +- **Pour les travaux d'envergure**, commentez l'issue pour signaler que vous vous en occupez, afin que personne d'autre ne démarre la même chose. + +En lien : #38284 couvre le pendant côté agent — Hermes lui-même vérifiant les issues et PR existantes avant de se lancer dans un auto-dépannage approfondi. Cette section en est le complément pour les contributeurs humains. + +--- + +## Compétence ou outil ? + +C'est la question la plus fréquente chez les nouveaux contributeurs. La réponse est presque toujours **compétence**. + +### Faites-en une compétence quand : + +- La capacité peut s'exprimer comme des instructions + des commandes shell + des outils existants +- Elle enveloppe une CLI externe ou une API que l'agent peut appeler via `terminal` ou `web_extract` +- Elle n'a pas besoin d'intégration Python sur mesure ni de gestion de clés API embarquée dans l'agent +- Exemples : recherche arXiv, workflows git, gestion de Docker, traitement de PDF, e-mail via des outils CLI + +### Faites-en un outil quand : + +- Il exige une intégration de bout en bout avec clés API, flux d'authentification ou configuration multi-composants gérée par le harnais de l'agent +- Il nécessite une logique de traitement sur mesure qui doit s'exécuter avec précision à chaque fois (pas du « au mieux » issu de l'interprétation du LLM) +- Il manipule des données binaires, du streaming ou des événements temps réel qui ne peuvent pas passer par le terminal +- Exemples : automatisation de navigateur (gestion de sessions Browserbase), TTS (encodage audio + livraison sur la plateforme), analyse de vision (manipulation d'images en base64) + +### La compétence doit-elle être embarquée ? + +Les compétences embarquées (dans `skills/`) sont livrées avec chaque installation d'Hermes. Elles doivent être **largement utiles à la majorité des utilisateurs** : + +- Traitement de documents, recherche web, workflows de développement courants, administration système +- Utilisées régulièrement par un large éventail de personnes + +Si votre compétence est officielle et utile mais pas universellement nécessaire (par exemple l'intégration d'un service payant, une dépendance lourde), placez-la dans **`optional-skills/`** — elle est livrée avec le dépôt mais n'est pas activée par défaut. Les utilisateurs peuvent la découvrir via `hermes skills browse` (étiquetée « official ») et l'installer avec `hermes skills install` (sans avertissement tiers, confiance intégrée). + +Si votre compétence est spécialisée, issue de la communauté ou de niche, elle a plus sa place sur un **Skills Hub** — téléversez-la sur un registre de compétences et partagez-la sur le [Discord de Nous Research](https://discord.gg/NousResearch). Les utilisateurs peuvent l'installer avec `hermes skills install`. + +--- + +## Fournisseurs de mémoire : à publier comme plugin autonome + +**Nous n'acceptons plus de nouveaux fournisseurs de mémoire dans ce dépôt.** L'ensemble des fournisseurs intégrés sous `plugins/memory/` (honcho, mem0, supermemory, byterover, hindsight, holographic, openviking, retaindb) est clos. Si vous voulez ajouter un nouveau backend de mémoire, publiez-le comme **dépôt de plugin autonome** que les utilisateurs installent dans `~/.hermes/plugins/` (ou via un entry point pip). + +Les plugins de mémoire autonomes : + +- Implémentent la même ABC `MemoryProvider` (`agent/memory_provider.py`) — `sync_turn`, `prefetch`, `shutdown`, et éventuellement `post_setup(hermes_home, config)` pour l'intégration avec l'assistant de configuration +- Utilisent le même système de découverte — `discover_memory_providers()` les récupère dans les répertoires de plugins utilisateur/projet et les entry points pip +- S'intègrent à `hermes memory setup` via `post_setup()` — sans toucher au code du cœur +- Peuvent enregistrer leurs propres sous-commandes CLI via `register_cli(subparser)` dans un fichier `cli.py` +- Bénéficient des mêmes hooks de cycle de vie et de la même plomberie de configuration que les fournisseurs intégrés + +Les PR qui ajoutent un nouveau répertoire sous `plugins/memory/` seront fermées avec un renvoi vers la publication du fournisseur dans son propre dépôt. Les fournisseurs déjà intégrés restent ; les corrections de bugs les concernant sont les bienvenues. + +Ce n'est pas une question de niveau de qualité — c'est une décision de couplage et de maintenance. Les fournisseurs de mémoire sont le type de plugin le plus courant et ils n'ont pas tous vocation à vivre dans cette arborescence. + +--- + +## Intégrations de produits tiers : à publier comme plugin autonome + +La même règle s'étend à **tout plugin qui intègre le produit ou le projet de quelqu'un d'autre** — backends d'observabilité/métriques, connecteurs SaaS d'éditeurs, tableaux de bord d'analytique, intégrations de services payants et autres intégrations tierces similaires. **Elles n'entrent pas dans ce dépôt.** + +La raison est la charge de maintenance, pas la qualité. Chaque produit externe absorbé dans le cœur devient notre responsabilité : le maintenir en état de marche face à une base de code qui évolue vite, pour un backend que nous ne possédons pas et ne contrôlons pas. Hermes publie beaucoup et le cœur avance rapidement ; y coupler des produits tiers crée une charge sans fin pour les mainteneurs. + +Publiez-les plutôt comme **dépôt de plugin autonome** : + +- Implémentez l'ABC concernée et utilisez le chemin de découverte de plugins existant (`~/.hermes/plugins/`, `.hermes/plugins/` du projet, ou un entry point pip) — voir [Build a Hermes Plugin](https://hermes-agent.nousresearch.com/docs/guides/build-a-hermes-plugin) +- Enregistrez les hooks de cycle de vie (`pre_tool_call`, `post_tool_call`, `pre_llm_call`, `post_llm_call`, `on_session_start`, `on_session_end`), les outils (`ctx.register_tool`) et les sous-commandes CLI (`ctx.register_cli_command`) à travers la surface que nous exposons déjà — aucun changement du cœur nécessaire +- Si votre plugin a besoin d'une capacité que le framework n'expose pas, c'est une demande de fonctionnalité pour **élargir la surface générique des plugins** (un nouveau hook ou une méthode `ctx`) — jamais un cas particulier pour votre plugin dans le cœur +- Faites-en la promotion sur le canal `#plugins-skills-and-skins` du [Discord de Nous Research](https://discord.gg/NousResearch) pour que les utilisateurs puissent le trouver et l'installer + +Un plugin de produit tiers bien construit peut passer la revue automatisée et être fermé quand même pour cette raison — c'est une décision de placement, pas un verdict sur le code. Les PR qui ajoutent un tel répertoire sous `plugins/` seront fermées avec un renvoi vers la publication dans un dépôt dédié. + +--- + +## Mise en place de l'environnement de développement + +### Prérequis + +| Prérequis | Notes | +|-------------|-------| +| **Git** | Avec l'extension `git-lfs` installée | +| **Python 3.11–3.13** | uv l'installera s'il manque | +| **uv** | Gestionnaire de paquets Python rapide ([installation](https://docs.astral.sh/uv/)) | +| **Node.js 20+** | Optionnel — nécessaire pour les outils navigateur et le pont WhatsApp (correspond aux engines du `package.json` racine) | + +### Installation avec l'installeur standard + +Pour la plupart des contributeurs, le meilleur amorçage de développement est le même +chemin que celui des utilisateurs : lancer l'installeur standard, puis travailler dans +le dépôt qu'il a cloné. L'installeur crée le venv d'Hermes, câble la commande +`hermes`, enregistre la méthode d'installation pour `hermes update` et clone le +projet git complet dans `$HERMES_HOME/hermes-agent` (généralement +`~/.hermes/hermes-agent`). Votre environnement de développement reste ainsi sur la +même disposition que celle attendue par la CLI, l'outil de mise à jour, l'installeur +paresseux de dépendances, le gateway et la documentation. + +```bash +curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash +cd "${HERMES_HOME:-$HOME/.hermes}/hermes-agent" + +# Add dev/test extras on top of the standard install. +uv pip install -e ".[all,dev]" + +# Optional: browser tools / docs site dependencies. +npm install +``` + +Ensuite, créez vos branches et lancez les tests depuis ce checkout : + +```bash +git checkout -b fix/description +scripts/run_tests.sh +``` + +### Repli : clonage manuel + +À n'utiliser que si vous ne voulez délibérément pas de la disposition d'installation +gérée par Hermes (par exemple un clone jetable dans un conteneur ou un job CI). Si +vous installez de cette manière, veillez à lancer le point d'entrée `hermes` depuis +ce venv ; exécuter le `python3 -m hermes_cli.main` du système peut ramasser des +paquets Python système sans rapport. + +Créez le venv **en dehors** de l'arborescence source clonée. Un venv qui vit dans le +répertoire depuis lequel l'agent opère peut être effacé par une commande à chemin +relatif que l'agent exécute contre son propre checkout (`rm -rf venv`, +`uv venv venv`, etc.), ce qui détruit silencieusement le runtime en cours en pleine +session. Le garder hors de l'arborescence garantit qu'aucun chemin relatif depuis +l'espace de travail ne le résout. + +```bash +git clone https://github.com/NousResearch/hermes-agent.git +cd hermes-agent + +# Create venv with Python 3.11, OUTSIDE the source tree +uv venv ~/.hermes/venvs/hermes-dev --python 3.11 +export VIRTUAL_ENV="$HOME/.hermes/venvs/hermes-dev" +export PATH="$VIRTUAL_ENV/bin:$PATH" + +# Install with all extras (messaging, cron, CLI menus, dev tools) +uv pip install -e ".[all,dev]" + +# Optional: browser tools +npm install +``` + +### Configurer pour le développement + +```bash +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=***" >> ~/.hermes/.env +``` + +### Lancer + +```bash +# The standard installer already put `hermes` on PATH. +hermes doctor +hermes chat -q "Hello" +``` + +Si vous avez utilisé le repli par clonage manuel, lancez `./hermes` depuis le +checkout ou créez explicitement un lien symbolique vers le venv de ce clone : + +```bash +mkdir -p ~/.local/bin +ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes +``` + +### Lancer les tests + +```bash +# Preferred — matches CI (hermetic env, 4 xdist workers); see AGENTS.md +scripts/run_tests.sh + +# Alternative (activate the venv first). The wrapper is still recommended +# for parity with GitHub Actions before you open a PR: +pytest tests/ -v +``` + +--- + +## Structure du projet + +``` +hermes-agent/ +├── run_agent.py # AIAgent class — core conversation loop, tool dispatch, session persistence +├── cli.py # HermesCLI class — interactive TUI, prompt_toolkit integration +├── model_tools.py # Tool orchestration (thin layer over tools/registry.py) +├── toolsets.py # Tool groupings and presets (hermes-cli, hermes-telegram, etc.) +├── hermes_state.py # SQLite session database with FTS5 full-text search, session titles +├── batch_runner.py # Parallel batch processing for trajectory generation +│ +├── agent/ # Agent internals (extracted modules) +│ ├── prompt_builder.py # System prompt assembly (identity, skills, context files, memory) +│ ├── context_compressor.py # Auto-summarization when approaching context limits +│ ├── auxiliary_client.py # Resolves auxiliary OpenAI clients (summarization, vision) +│ ├── display.py # KawaiiSpinner, tool progress formatting +│ ├── model_metadata.py # Model context lengths, token estimation +│ └── trajectory.py # Trajectory saving helpers +│ +├── hermes_cli/ # CLI command implementations +│ ├── main.py # Entry point, argument parsing, command dispatch +│ ├── config.py # Config management, migration, env var definitions +│ ├── setup.py # Interactive setup wizard +│ ├── auth.py # Provider resolution, OAuth, Nous Portal +│ ├── models.py # OpenRouter model selection lists +│ ├── banner.py # Welcome banner, ASCII art +│ ├── commands.py # Central slash command registry (CommandDef), autocomplete, gateway helpers +│ ├── callbacks.py # Interactive callbacks (clarify, sudo, approval) +│ ├── doctor.py # Diagnostics +│ ├── skills_hub.py # Skills Hub CLI + /skills slash command +│ └── skin_engine.py # Skin/theme engine — data-driven CLI visual customization +│ +├── tools/ # Tool implementations (self-registering) +│ ├── registry.py # Central tool registry (schemas, handlers, dispatch) +│ ├── approval.py # Dangerous command detection + per-session approval +│ ├── terminal_tool.py # Terminal orchestration (sudo, env lifecycle, backends) +│ ├── file_operations.py # read_file, write_file, search, patch, etc. +│ ├── web_tools.py # web_search, web_extract (Parallel/Firecrawl + Gemini summarization) +│ ├── vision_tools.py # Image analysis via multimodal models +│ ├── delegate_tool.py # Subagent spawning and parallel task execution +│ ├── code_execution_tool.py # Sandboxed Python with RPC tool access +│ ├── session_search_tool.py # Search past conversations with FTS5 + anchored windows +│ ├── cronjob_tools.py # Scheduled task management +│ ├── skill_tools.py # Skill search, load, manage +│ └── environments/ # Terminal execution backends +│ ├── base.py # BaseEnvironment ABC +│ ├── local.py, docker.py, ssh.py, singularity.py, modal.py, daytona.py +│ +├── gateway/ # Messaging gateway +│ ├── run.py # GatewayRunner — platform lifecycle, message routing, cron +│ ├── config.py # Platform configuration resolution +│ ├── session.py # Session store, context prompts, reset policies +│ └── platforms/ # Platform adapters +│ ├── telegram.py, discord_adapter.py, slack.py, whatsapp.py +│ +├── scripts/ # Installer and bridge scripts +│ ├── install.sh # Linux/macOS installer +│ ├── install.ps1 # Windows PowerShell installer +│ └── whatsapp-bridge/ # Node.js WhatsApp bridge (Baileys) +│ +├── skills/ # Bundled skills (copied to ~/.hermes/skills/ on install) +├── optional-skills/ # Official optional skills (discoverable via hub, not activated by default) +├── tests/ # Test suite +├── website/ # Documentation site (hermes-agent.nousresearch.com) +│ +├── cli-config.yaml.example # Example configuration (copied to ~/.hermes/config.yaml) +└── AGENTS.md # Development guide for AI coding assistants +``` + +### Configuration utilisateur (stockée dans `~/.hermes/`) + +| Chemin | Rôle | +|------|---------| +| `~/.hermes/config.yaml` | Réglages (modèle, terminal, toolsets, compression, etc.) | +| `~/.hermes/.env` | Clés API et secrets | +| `~/.hermes/auth.json` | Identifiants OAuth (Nous Portal) | +| `~/.hermes/skills/` | Toutes les compétences actives (embarquées + installées depuis le hub + créées par l'agent) | +| `~/.hermes/memories/` | Mémoire persistante (MEMORY.md, USER.md) | +| `~/.hermes/state.db` | Base de données de sessions SQLite | +| `~/.hermes/sessions/` | Index de routage du gateway (`sessions.json`), traces de request-dump, transcriptions `*.jsonl` du gateway et (en option) instantanés JSON par session quand `sessions.write_json_snapshots: true` est défini. Les instantanés par session sont désactivés par défaut ; state.db fait foi. | +| `~/.hermes/cron/` | Données des tâches planifiées | +| `~/.hermes/whatsapp/session/` | Identifiants du pont WhatsApp | + +--- + +## Vue d'ensemble de l'architecture + +### Boucle principale + +``` +User message → AIAgent._run_agent_loop() + ├── Build system prompt (prompt_builder.py) + ├── Build API kwargs (model, messages, tools, reasoning config) + ├── Call LLM (OpenAI-compatible API) + ├── If tool_calls in response: + │ ├── Execute each tool via registry dispatch + │ ├── Add tool results to conversation + │ └── Loop back to LLM call + ├── If text response: + │ ├── Persist session to DB + │ └── Return final_response + └── Context compression if approaching token limit +``` + +### Patrons de conception clés + +- **Outils auto-enregistrés** : chaque fichier d'outil appelle `registry.register()` à l'import. `model_tools.py` déclenche la découverte en important tous les modules d'outils. +- **Regroupement en toolsets** : les outils sont regroupés en toolsets (`web`, `terminal`, `file`, `browser`, etc.) qui peuvent être activés/désactivés par plateforme. +- **Persistance des sessions** : toutes les conversations sont stockées dans SQLite (`hermes_state.py`) avec recherche plein texte et titres de session uniques. Les instantanés JSON par session dans `~/.hermes/sessions/` ont été remplacés par le stockage SQLite et sont désactivés par défaut ; réactivez-les avec `sessions.write_json_snapshots: true` si un outillage externe consomme directement les fichiers JSON. +- **Injection éphémère** : les prompts système et les messages de préremplissage sont injectés au moment de l'appel API, jamais persistés dans la base de données ni dans les logs. +- **Abstraction des fournisseurs** : l'agent fonctionne avec n'importe quelle API compatible OpenAI. La résolution du fournisseur a lieu à l'initialisation (OAuth Nous Portal, clé API OpenRouter ou endpoint personnalisé). +- **Routage des fournisseurs** : avec OpenRouter, `provider_routing` dans config.yaml contrôle la sélection du fournisseur (tri par débit/latence/prix, autorisation/exclusion de fournisseurs spécifiques, politiques de rétention des données). Ces réglages sont injectés dans `extra_body.provider` des requêtes API. + +--- + +## Style de code + +- **PEP 8** avec des exceptions pragmatiques (nous n'imposons pas de longueur de ligne stricte) +- **Commentaires** : uniquement pour expliquer une intention non évidente, des compromis ou des bizarreries d'API. Ne racontez pas ce que fait le code — `# increment counter` n'apporte rien +- **Gestion des erreurs** : attrapez des exceptions spécifiques. Loguez avec `logger.warning()`/`logger.error()` — utilisez `exc_info=True` pour les erreurs inattendues afin que les stack traces apparaissent dans les logs +- **Multiplateforme** : ne supposez jamais Unix. Voir [Compatibilité multiplateforme](#compatibilité-multiplateforme) + +--- + +## Ajouter un nouvel outil + +Avant d'écrire un outil, demandez-vous : [ne devrait-ce pas être une compétence ?](#compétence-ou-outil-) + +Les outils s'enregistrent eux-mêmes auprès du registre central. Chaque fichier d'outil regroupe au même endroit son schéma, son handler et son enregistrement : + +```python +"""my_tool — Brief description of what this tool does.""" + +import json +from tools.registry import registry + + +def my_tool(param1: str, param2: int = 10, **kwargs) -> str: + """Handler. Returns a string result (often JSON).""" + result = do_work(param1, param2) + return json.dumps(result) + + +MY_TOOL_SCHEMA = { + "type": "function", + "function": { + "name": "my_tool", + "description": "What this tool does and when the agent should use it.", + "parameters": { + "type": "object", + "properties": { + "param1": {"type": "string", "description": "What param1 is"}, + "param2": {"type": "integer", "description": "What param2 is", "default": 10}, + }, + "required": ["param1"], + }, + }, +} + + +def _check_requirements() -> bool: + """Return True if this tool's dependencies are available.""" + return True + + +registry.register( + name="my_tool", + toolset="my_toolset", + schema=MY_TOOL_SCHEMA, + handler=lambda args, **kw: my_tool(**args, **kw), + check_fn=_check_requirements, +) +``` + +**Câblage dans un toolset (obligatoire) :** les outils intégrés sont découverts +automatiquement : tout fichier `tools/*.py` contenant un appel +`registry.register(...)` au niveau supérieur est importé par +`discover_builtin_tools()` dans `tools/registry.py` au chargement de `model_tools`. +Il n'y a **aucune** liste d'imports manuelle à maintenir dans `model_tools.py`. + +Vous devez néanmoins ajouter le nom de l'outil à la liste appropriée dans +`toolsets.py` (par exemple `_HERMES_CORE_TOOLS` ou un toolset dédié) ; sinon +l'outil s'enregistre mais n'est jamais exposé à l'agent. Si vous introduisez un +nouveau toolset, ajoutez-le dans `toolsets.py` et câblez-le dans les presets de +plateforme concernés. + +Voir `AGENTS.md` (section **Adding New Tools**) pour les chemins sensibles aux +profils et l'arbitrage plugin vs cœur. + +--- + +## Ajouter une compétence + +Les compétences embarquées vivent dans `skills/`, organisées par catégorie. Les compétences optionnelles officielles utilisent la même structure dans `optional-skills/` : + +``` +skills/ +├── research/ +│ └── arxiv/ +│ ├── SKILL.md # Required: main instructions +│ └── scripts/ # Optional: helper scripts +│ └── search_arxiv.py +├── productivity/ +│ └── ocr-and-documents/ +│ ├── SKILL.md +│ ├── scripts/ +│ └── references/ +└── ... +``` + +### Format de SKILL.md + +```markdown +--- +name: my-skill +description: Brief description (shown in skill search results) +version: 1.0.0 +author: Your Name +license: MIT +platforms: [macos, linux] # Optional — restrict to specific OS platforms + # Valid: macos, linux, windows + # Omit to load on all platforms (default) +required_environment_variables: # Optional — secure setup-on-load metadata + - name: MY_API_KEY + prompt: API key + help: Where to get it + required_for: full functionality +prerequisites: # Optional legacy runtime requirements + env_vars: [MY_API_KEY] # Backward-compatible alias for required env vars + commands: [curl, jq] # Advisory only; does not hide the skill +metadata: + hermes: + tags: [Category, Subcategory, Keywords] + related_skills: [other-skill-name] + fallback_for_toolsets: [web] # Optional — show only when toolset is unavailable + requires_toolsets: [terminal] # Optional — show only when toolset is available +--- + +# Skill Title + +Brief intro. + +## When to Use +Trigger conditions — when should the agent load this skill? + +## Prerequisites +Env vars, install steps, MCP setup, API key sourcing. + +## How to Run +Canonical invocation through the `terminal` tool. + +## Quick Reference +Table of common commands or API calls. + +## Procedure +Step-by-step instructions the agent follows. + +## Pitfalls +Known failure modes and how to handle them. + +## Verification +How the agent confirms it worked. +``` + +### Compétences spécifiques à une plateforme + +Les compétences peuvent déclarer les plateformes qu'elles prennent en charge via le champ de frontmatter `platforms`. Les compétences portant ce champ sont automatiquement masquées du prompt système, de `skills_list()` et des commandes slash sur les plateformes incompatibles. + +```yaml +platforms: [macos] # macOS only (e.g., iMessage, Apple Reminders) +platforms: [macos, linux] # macOS and Linux +platforms: [windows] # Windows only +``` + +Si le champ est omis ou vide, la compétence se charge sur toutes les plateformes (rétrocompatible). Voir `skills/apple/` pour des exemples de compétences réservées à macOS. + +### Activation conditionnelle des compétences + +Les compétences peuvent déclarer des conditions qui contrôlent leur apparition dans le prompt système, selon les outils et toolsets disponibles dans la session courante. C'est principalement utilisé pour les **compétences de repli** — des alternatives qui ne doivent apparaître que lorsqu'un outil principal est indisponible. + +Quatre champs sont pris en charge sous `metadata.hermes` : + +```yaml +metadata: + hermes: + fallback_for_toolsets: [web] # Show ONLY when these toolsets are unavailable + requires_toolsets: [terminal] # Show ONLY when these toolsets are available + fallback_for_tools: [web_search] # Show ONLY when these specific tools are unavailable + requires_tools: [terminal] # Show ONLY when these specific tools are available +``` + +**Sémantique :** +- `fallback_for_*` : la compétence est une solution de secours. Elle est **masquée** quand les outils/toolsets listés sont disponibles, et **affichée** quand ils ne le sont pas. À utiliser pour des alternatives gratuites à des outils premium. +- `requires_*` : la compétence a besoin de certains outils pour fonctionner. Elle est **masquée** quand les outils/toolsets listés sont indisponibles. À utiliser pour des compétences qui dépendent de capacités précises (par exemple une compétence qui n'a de sens qu'avec un accès au terminal). +- Si les deux sont spécifiés, les deux conditions doivent être satisfaites pour que la compétence apparaisse. +- Si aucun n'est spécifié, la compétence est toujours affichée (rétrocompatible). + +**Exemples :** + +```yaml +# DuckDuckGo search — shown when Firecrawl (web toolset) is unavailable +metadata: + hermes: + fallback_for_toolsets: [web] + +# Smart home skill — only useful when terminal is available +metadata: + hermes: + requires_toolsets: [terminal] + +# Local browser fallback — shown when Browserbase is unavailable +metadata: + hermes: + fallback_for_toolsets: [browser] +``` + +Le filtrage a lieu au moment de la construction du prompt, dans `agent/prompt_builder.py`. La fonction `build_skills_system_prompt()` reçoit l'ensemble des outils et toolsets disponibles depuis l'agent et utilise `_skill_should_show()` pour évaluer les conditions de chaque compétence. + +### Métadonnées de configuration d'une compétence + +Les compétences peuvent déclarer des métadonnées de configuration sécurisée au chargement via le champ de frontmatter `required_environment_variables`. Des valeurs manquantes ne masquent pas la compétence à la découverte ; elles déclenchent une invite sécurisée (CLI uniquement) au moment où la compétence est réellement chargée. + +```yaml +required_environment_variables: + - name: TENOR_API_KEY + prompt: Tenor API key + help: Get a key from https://developers.google.com/tenor + required_for: full functionality +``` + +L'utilisateur peut ignorer la configuration et continuer à charger la compétence. Hermes n'expose au modèle que des métadonnées (`stored_as`, `skipped`, `validated`) — jamais la valeur du secret. + +L'ancien `prerequisites.env_vars` reste pris en charge et est normalisé vers la nouvelle représentation. + +```yaml +prerequisites: + env_vars: [TENOR_API_KEY] # Legacy alias for required_environment_variables + commands: [curl, jq] # Advisory CLI checks +``` + +Les sessions gateway et de messagerie ne collectent jamais de secrets dans le flux de conversation ; elles demandent à l'utilisateur de lancer `hermes setup` ou de mettre à jour `~/.hermes/.env` en local. + +**Quand déclarer des variables d'environnement requises :** +- La compétence utilise une clé API ou un token qui doit être collecté de manière sécurisée au chargement +- La compétence peut rester utile si l'utilisateur ignore la configuration, quitte à se dégrader proprement + +**Quand déclarer des prérequis de commandes :** +- La compétence repose sur un outil CLI qui peut ne pas être installé (par exemple `himalaya`, `openhue`, `ddgs`) +- Traitez les vérifications de commandes comme des indications, pas comme un masquage à la découverte + +Voir `skills/gifs/gif-search/` et `skills/email/himalaya/` pour des exemples. + +### Normes de rédaction des compétences (NON NÉGOCIABLES) + +Toute compétence nouvelle ou modernisée — embarquée, optionnelle ou contribuée — doit respecter ces normes avant la fusion. Les relecteurs rejettent les PR qui les enfreignent. + +1. **`description` ≤ 60 caractères, une seule phrase, terminée par un point.** Les descriptions longues alourdissent l'interface de listage des compétences et diluent l'attention du modèle quand de nombreuses compétences sont chargées. Énoncez la capacité, pas l'implémentation. Pas de vocabulaire marketing (« powerful », « comprehensive », « seamless », « advanced »). Ne répétez pas le nom de la compétence. Vérifiez avec : + ```python + import re, pathlib + m = re.search(r'^description: (.*)$', + pathlib.Path('skills///SKILL.md').read_text(), + re.MULTILINE) + assert len(m.group(1)) <= 60, len(m.group(1)) + ``` + + Bien : `Search arXiv papers by keyword, author, category, or ID.` + Mal : `A powerful and comprehensive skill that allows the agent to search arXiv for relevant academic papers using various criteria including keywords, authors, and categories.` + +2. **Les outils cités dans la prose de SKILL.md doivent être des outils Hermes natifs ou des serveurs MCP que la compétence attend explicitement.** Quand la compétence a besoin d'une capacité, désignez le bon outil par son nom entre backticks : `` `terminal` ``, `` `web_extract` ``, `` `web_search` ``, `` `read_file` ``, `` `write_file` ``, `` `patch` ``, `` `search_files` ``, `` `vision_analyze` ``, `` `browser_navigate` ``, `` `delegate_task` ``, `` `image_generate` ``, `` `text_to_speech` ``, `` `cronjob` ``, `` `memory` ``, `` `skill_view` ``, `` `todo` ``, `` `execute_code` ``. + + Ne nommez PAS des utilitaires shell que l'agent a déjà enveloppés : + + | À ne pas dire | À dire | + |---|---| + | `grep`, `rg` | `search_files` | + | `cat`, `head`, `tail` | `read_file` | + | `sed`, `awk` | `patch` | + | `find`, `ls` | `search_files` (avec `target='files'`) | + | `curl` pour extraire du contenu | `web_extract` | + | `echo > file`, `cat < Skill`, introduction de 2-3 phrases indiquant ce que la compétence fait et ne fait pas, puis : + - `## When to Use` — conditions de déclenchement + - `## Prerequisites` — variables d'environnement, étapes d'installation, configuration MCP, obtention des clés API + - `## How to Run` — invocation canonique via l'outil `terminal` + - `## Quick Reference` — référence brute des commandes/API + - `## Procedure` — étapes numérotées avec commandes prêtes à copier-coller + - `## Pitfalls` — limites connues, quotas, choses qui semblent cassées mais ne le sont pas + - `## Verification` — une seule commande qui prouve que la compétence fonctionne + + Visez ~200 lignes pour une compétence complexe, ~100 pour une simple. Supprimez les introductions redondantes, la prose marketing et les ré-explications de variables d'environnement déjà documentées dans `## Prerequisites`. + +6. **Les scripts vont dans `scripts/`, les références dans `references/`, les templates dans `templates/`.** N'attendez pas du modèle qu'il réécrive inline des parseurs, des parcours XML ou de la logique non triviale à chaque appel — livrez un script utilitaire. Référencez les scripts depuis SKILL.md par chemin relatif au répertoire de la compétence. + +7. **Les tests vivent dans `tests/skills/test__skill.py`** et n'utilisent que la stdlib + pytest + `unittest.mock`. Aucun appel réseau réel. Lancez-les via `scripts/run_tests.sh tests/skills/test__skill.py -q`. Ils doivent passer dans l'environnement CI hermétique (aucune clé API qui fuite). Utilisez `monkeypatch` et `tmp_path` pour toute dépendance aux variables d'environnement ou au système de fichiers. + +8. **Les ajouts à `.env.example` sont isolés dans un bloc clairement délimité.** Ne touchez pas au reste du fichier — les versions de `.env.example` fournies par les contributeurs sont généralement obsolètes, et les modifications hors du bloc propre à la compétence seront écartées lors de la récupération. Commentez toutes les valeurs avec `#` (c'est de la documentation, pas de la configuration active). + +### Recommandations pour les compétences + +- **Pas de dépendances externes sauf nécessité absolue.** Préférez la stdlib Python, curl et les outils Hermes existants (`web_extract`, `terminal`, `read_file`). +- **Divulgation progressive.** Placez le workflow le plus courant en premier. Les cas limites et l'usage avancé vont en bas. +- **Fournissez des scripts utilitaires** pour le parsing XML/JSON ou la logique complexe — n'attendez pas du LLM qu'il écrive des parseurs inline à chaque fois. +- **Testez-la.** Lancez `hermes --toolsets skills -q "Use the X skill to do Y"` et vérifiez que l'agent suit correctement les instructions. + +--- + +## Ajouter un skin / thème + +Hermes utilise un système de skins piloté par les données — aucun changement de code n'est nécessaire pour ajouter un nouveau skin. + +**Option A : skin utilisateur (fichier YAML)** + +Créez `~/.hermes/skins/.yaml` : + +```yaml +name: mytheme +description: Short description of the theme + +colors: + banner_border: "#HEX" # Panel border color + banner_title: "#HEX" # Panel title color + banner_accent: "#HEX" # Section header color + banner_dim: "#HEX" # Muted/dim text color + banner_text: "#HEX" # Body text color + response_border: "#HEX" # Response box border + +spinner: + waiting_faces: ["(⚔)", "(⛨)"] + thinking_faces: ["(⚔)", "(⌁)"] + thinking_verbs: ["forging", "plotting"] + wings: # Optional left/right decorations + - ["⟪⚔", "⚔⟫"] + +branding: + agent_name: "My Agent" + welcome: "Welcome message" + response_label: " ⚔ Agent " + prompt_symbol: "⚔" + +tool_prefix: "╎" # Tool output line prefix +``` + +Tous les champs sont optionnels — les valeurs manquantes héritent du skin par défaut. + +**Option B : skin intégré** + +Ajoutez-le au dict `_BUILTIN_SKINS` dans `hermes_cli/skin_engine.py`. Utilisez le même schéma que ci-dessus, mais sous forme de dict Python. Les skins intégrés sont livrés avec le paquet et toujours disponibles. + +**Activation :** +- CLI : `/skin mytheme` ou définissez `display.skin: mytheme` dans config.yaml +- Config : `display: { skin: mytheme }` + +Voir `hermes_cli/skin_engine.py` pour le schéma complet et les skins existants en exemples. + +--- + +## Compatibilité multiplateforme + +Hermes tourne sous Linux, macOS et Windows natif (plus WSL2). Quand vous écrivez du +code qui touche à l'OS, partez du principe que *n'importe quelle* plateforme peut +emprunter votre chemin de code. + +> **Avant d'ouvrir votre PR :** lancez `scripts/check-windows-footguns.py` pour +> attraper les pièges Windows courants dans votre diff. C'est du grep, donc peu +> coûteux ; la CI le lance aussi sur chaque PR. + +### Règles critiques + +1. **N'appelez jamais `os.kill(pid, 0)` pour tester si un processus est vivant.** + `os.kill(pid, 0)` est un idiome POSIX standard pour vérifier « ce PID est-il + vivant » — le signal 0 est une simple vérification de permission sans effet. + **Sous Windows, ce n'est PAS sans effet.** Le `os.kill` de Python sous Windows + mappe `sig=0` sur `CTRL_C_EVENT` (ils entrent en collision à la valeur entière + 0) et le fait passer par `GenerateConsoleCtrlEvent(0, pid)`, qui diffuse Ctrl+C + à **tout le groupe de processus de la console** contenant le PID cible. + « Sonder si vivant » devient silencieusement « tuer la cible et souvent des + processus sans rapport partageant sa console ». Voir [bpo-14484](https://bugs.python.org/issue14484) + (ouvert depuis 2012 — ne sera jamais corrigé pour raisons de compatibilité). + + **À privilégier :** utilisez `psutil` (une dépendance de base — toujours disponible) : + + ```python + import psutil + if psutil.pid_exists(pid): + # process is alive — safe on every platform + ... + ``` + + Si vous avez spécifiquement besoin du wrapper hermes (il a un repli stdlib + pour les imports en phase d'amorçage, avant que pip install ne se termine), + utilisez `gateway.status._pid_exists(pid)`. Il appelle d'abord + `psutil.pid_exists` et se rabat sur une danse maison + `OpenProcess + WaitForSingleObject` sous Windows, uniquement si psutil est + introuvable. + + Grep d'audit pour les nouveaux sites d'appel : `rg "os\.kill\([^,]+,\s*0\s*\)"`. + Tout résultat hors code de test est présumé être un bug de kill silencieux sous + Windows. + +2. **Utilisez `shutil.which()` avant de lancer une commande — ne supposez pas que + Windows a les outils de Linux.** `wmic` a été retiré à partir de Windows 10 + 21H1. `ps`, `kill`, `grep`, `awk`, `fuser`, `lsof`, `pgrep` et la plupart des + outils CLI POSIX n'existent tout simplement pas sous Windows. Testez la + disponibilité avec `shutil.which("tool")` et prévoyez un équivalent natif + Windows — généralement PowerShell via `subprocess.run(["powershell", + "-NoProfile", "-Command", ...])`. + + Pour l'énumération des processus : `Get-CimInstance Win32_Process` de + PowerShell est le remplaçant moderne de `wmic process`. Voir + `hermes_cli/gateway.py::_scan_gateway_pids` pour le motif à suivre. + +3. **`termios` et `fcntl` sont réservés à Unix.** Attrapez toujours à la fois + `ImportError` et `NotImplementedError` : + ```python + try: + from simple_term_menu import TerminalMenu + menu = TerminalMenu(options) + idx = menu.show() + except (ImportError, NotImplementedError): + # Fallback: numbered menu for Windows + for i, opt in enumerate(options): + print(f" {i+1}. {opt}") + idx = int(input("Choice: ")) - 1 + ``` + +4. **Encodage des fichiers.** Windows peut enregistrer les fichiers `.env` en + `cp1252`. Gérez toujours les erreurs d'encodage : + ```python + try: + load_dotenv(env_path) + except UnicodeDecodeError: + load_dotenv(env_path, encoding="latin-1") + ``` + Les fichiers de configuration (`config.yaml`) peuvent être enregistrés avec un + BOM UTF-8 par le Bloc-notes et éditeurs similaires — utilisez + `encoding="utf-8-sig"` pour lire les fichiers qui ont pu être touchés par un + éditeur graphique Windows. + +5. **Gestion des processus.** `os.setsid()`, `os.killpg()`, `os.fork()`, + `os.getuid()` et la gestion des signaux POSIX diffèrent sous Windows. Protégez + avec `platform.system()`, `sys.platform` ou `hasattr(os, "setsid")` : + ```python + if platform.system() != "Windows": + kwargs["preexec_fn"] = os.setsid + else: + kwargs["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP + ``` + + **À privilégier :** pour tuer un processus ET ses enfants (ce que fait + `os.killpg` sous POSIX), utilisez `psutil` — il fonctionne sur toutes les + plateformes : + ```python + import psutil + try: + parent = psutil.Process(pid) + # Kill children first (leaf-up), then the parent. + for child in parent.children(recursive=True): + child.kill() + parent.kill() + except psutil.NoSuchProcess: + pass + ``` + +6. **Signaux inexistants sous Windows : `SIGALRM`, `SIGCHLD`, `SIGHUP`, + `SIGUSR1`, `SIGUSR2`, `SIGPIPE`, `SIGQUIT`, `SIGKILL`.** Le module `signal` de + Python lève `AttributeError` à l'import si vous les référencez sous Windows. + Utilisez `getattr(signal, "SIGKILL", signal.SIGTERM)` ou placez tout le bloc + derrière une vérification de plateforme. `loop.add_signal_handler` lève + `NotImplementedError` sous Windows — attrapez-la toujours. + +7. **Séparateurs de chemins.** Utilisez `pathlib.Path` plutôt que la concaténation + de chaînes avec `/`. Les slashs fonctionnent presque partout sous Windows, mais + `subprocess.run(["cmd.exe", "/c", ...])` et d'autres contextes shell peuvent + exiger des antislashs — convertissez avec `str(path)` à la frontière du + subprocess, pas au cœur de la logique Python. + +8. **Les liens symboliques exigent des privilèges élevés sous Windows** (sauf si + le mode développeur est activé). Les tests qui créent des liens symboliques ont + besoin de `@pytest.mark.skipif(sys.platform == + "win32", reason="Symlinks require elevated privileges on Windows")`. + +9. **Les modes de fichiers POSIX (0o600, 0o644, etc.) ne sont PAS appliqués sur + NTFS** par défaut. Les tests qui font des assertions sur + `stat().st_mode & 0o777` doivent être ignorés sous Windows — le concept ne se + transpose pas. Utilisez des ACL (`icacls`, `pywin32`) pour protéger les + fichiers de secrets sous Windows si nécessaire. + +10. **Les démons d'arrière-plan détachés sous Windows exigent `pythonw.exe`, PAS + `python.exe`.** `python.exe` alloue toujours une console ou s'y attache, ce + qui le rend vulnérable aux diffusions de `CTRL_C_EVENT` depuis n'importe quel + processus frère. `pythonw.exe` est la variante sans console. Combinez avec + `CREATE_NO_WINDOW | DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP | + CREATE_BREAKAWAY_FROM_JOB` dans `subprocess.Popen(creationflags=...)`. + Voir `hermes_cli/gateway_windows.py::_spawn_detached` pour l'implémentation + de référence. + +11. **`subprocess.Popen` avec des shims `.cmd` ou `.bat` a besoin de + `shutil.which` pour la résolution.** Passer `"agent-browser"` à `Popen` sous + Windows trouve le shim shebang POSIX sans extension dans + `node_modules/.bin/`, que `CreateProcessW` ne peut pas exécuter — vous + obtiendrez `WinError 193 "not a valid Win32 application"`. Utilisez + `shutil.which("agent-browser", path=local_bin)`, qui honore PATHEXT et + choisit la variante `.CMD` sous Windows. + +12. **N'utilisez pas les shebangs shell pour lancer du Python.** `#!/usr/bin/env + python` ne fonctionne que lorsque le fichier est exécuté à travers un shell + Unix. `subprocess.run(["./myscript.py"])` échoue sous Windows même si le + fichier a une ligne shebang. Invoquez toujours Python explicitement : + `[sys.executable, "myscript.py"]`. + +13. **Commandes shell dans les installeurs.** Si vous modifiez + `scripts/install.sh`, faites la modification équivalente dans + `scripts/install.ps1`. Ces deux scripts sont l'exemple canonique de + « fonctionne sous Linux ne veut pas dire fonctionne sous Windows » et ont + divergé plusieurs fois — gardez-les synchronisés. + +14. **Chemins connus redirigés vers OneDrive sous Windows :** Desktop, + Documents, Pictures, Videos. Le « vrai » chemin quand OneDrive Backup est + activé est `%USERPROFILE%\OneDrive\Desktop` (etc.), et NON + `%USERPROFILE%\Desktop` (qui existe en coquille vide). Résolvez + l'emplacement réel via `ctypes` + `SHGetKnownFolderPath` ou en lisant la clé + de registre `Shell Folders` — ne supposez jamais `~/Desktop`. + +15. **CRLF vs LF dans les scripts générés.** `cmd.exe` et `schtasks` sous Windows + parsent ligne par ligne ; des fins de ligne mixtes ou uniquement LF peuvent + casser des fichiers `.cmd` / `.bat` multilignes. Utilisez `open(path, "w", + encoding="utf-8", newline="\r\n")` — ou `open(path, "wb")` + octets + explicites — pour générer des scripts que Windows exécutera. + +16. **Deux schémas de quoting différents sur une même ligne de commande.** + `subprocess.run(["schtasks", "/TR", some_cmd])` → schtasks parse lui-même + `/TR`, ET la chaîne `some_cmd` est re-parsée par `cmd.exe` quand la tâche se + déclenche. Parseurs différents, règles d'échappement différentes. Utilisez + deux helpers de quoting distincts et ne les croisez jamais. Voir + `hermes_cli/gateway_windows.py::_quote_cmd_script_arg` et + `_quote_schtasks_arg` pour la paire de référence. + +### Tester le multiplateforme + +Les tests qui utilisent des appels système exclusivement POSIX ont besoin d'un marqueur de skip. Les cas courants : +- Liens symboliques → `@pytest.mark.skipif(sys.platform == "win32", ...)` +- Modes de fichiers `0o600` → `@pytest.mark.skipif(sys.platform.startswith("win"), ...)` +- `signal.SIGALRM` → Unix uniquement (voir `tests/conftest.py::_enforce_test_timeout`) +- `os.setsid` / `os.fork` → Unix uniquement +- Tests de régression Winsock réels / propres à Windows → + `@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific regression")` + +Si vous monkeypatchez `sys.platform` pour des tests multiplateformes, patchez aussi +`platform.system()` / `platform.release()` / `platform.mac_ver()` — chacun relit +indépendamment le véritable OS, si bien que des tests à moitié patchés empruntent +quand même la mauvaise branche sur un runner Windows. + +--- + +## Considérations de sécurité + +Hermes a accès au terminal. La sécurité compte. + +### Protections existantes + +| Couche | Implémentation | +|-------|---------------| +| **Passage du mot de passe sudo** | Utilise `shlex.quote()` pour empêcher l'injection shell | +| **Détection des commandes dangereuses** | Motifs regex dans `tools/approval.py` avec flux d'approbation utilisateur | +| **Injection de prompt via cron** | Un scanner dans `tools/cronjob_tools.py` bloque les motifs de contournement d'instructions | +| **Liste de refus en écriture** | Chemins protégés (`~/.ssh/authorized_keys`, `/etc/shadow`) résolus via `os.path.realpath()` pour empêcher le contournement par lien symbolique | +| **Garde des compétences** | Scanner de sécurité pour les compétences installées depuis le hub (`tools/skills_guard.py`) | +| **Sandbox d'exécution de code** | Le processus enfant de `execute_code` tourne avec les clés API retirées de l'environnement | +| **Durcissement des conteneurs** | Docker : toutes les capabilities supprimées, pas d'élévation de privilèges, limites de PID, tmpfs à taille limitée | + +### Contribuer du code sensible côté sécurité + +- **Utilisez toujours `shlex.quote()`** quand vous interpolez une saisie utilisateur dans des commandes shell +- **Résolvez les liens symboliques** avec `os.path.realpath()` avant tout contrôle d'accès fondé sur les chemins +- **Ne loguez pas de secrets.** Les clés API, tokens et mots de passe ne doivent jamais apparaître dans les logs +- **Attrapez des exceptions larges** autour de l'exécution des outils, pour qu'un seul échec ne fasse pas planter la boucle de l'agent +- **Testez sur toutes les plateformes** si votre changement touche aux chemins de fichiers, à la gestion des processus ou aux commandes shell + +Si votre PR touche à la sécurité, signalez-le explicitement dans la description. + +### Politique d'épinglage des dépendances (durcissement de la chaîne d'approvisionnement) + +Après la [compromission de la chaîne d'approvisionnement de litellm](https://github.com/BerriAI/litellm/issues/24512) en mars 2026 et la [campagne du ver Mini Shai-Hulud](https://socket.dev/blog/tanstack-npm-packages-compromised-mini-shai-hulud-supply-chain-attack) en mai 2026, toutes les dépendances doivent suivre ces règles : + +| Type de source | Traitement requis | Justification | +|---|---|---| +| **Paquet PyPI** | `>=floor, # vX.Y.Z` | +| **Installations pip réservées à la CI** | `==exact` | Builds CI hermétiques ; le churn est acceptable. | + +**Toute nouvelle dépendance PyPI dans une PR doit avoir une borne supérieure `=X.Y.Z` sans borne seront rejetées par les relecteurs. Le workflow CI `supply-chain-audit.yml` signale aussi les changements de manifestes de dépendances pour revue manuelle. + +**Comment déterminer le plafond :** +- Si le paquet est en version `1.x.y`, utilisez `<2`. +- Si le paquet est en version `0.x.y` (pré-1.0), utilisez `<0.(current_minor + 2)` — par exemple si la version courante est `0.29.x`, utilisez `<0.32`. Cela donne ~2 versions mineures de marge tout en gardant la fenêtre assez étroite pour qu'une version issue d'une prise de contrôle hostile ait peu de chances d'y atterrir. +- Exception : les paquets aux API très stables (par exemple `aiohttp-socks`) peuvent utiliser `<1` à la discrétion du relecteur. + +**Exemples :** +```toml +# ✅ Correct — post-1.0 +"openai>=2.21.0,<3" +"pydantic>=2.12.5,<3" + +# ✅ Correct — pre-1.0 (tight minor window) +"asyncpg>=0.29,<0.32" +"aiosqlite>=0.20,<0.23" +"hindsight-client>=0.4.22,<0.5" + +# ❌ Rejected — no upper bound +"some-package>=1.2.3" + +# ❌ Rejected — too tight (blocks legitimate patches) +"some-package==1.2.3" + +# ❌ Rejected — too loose for pre-1.0 (allows 80 minor versions) +"some-package>=0.20,<1" +``` + +**PR de référence :** #2796 (retrait de litellm), #2810 (passe sur les bornes supérieures), #9801 (épinglage par SHA + CI supply-chain-audit). + +--- + +## Processus de pull request + +### Nommage des branches + +``` +fix/description # Bug fixes +feat/description # New features +docs/description # Documentation +test/description # Tests +refactor/description # Code restructuring +``` + +### Avant de soumettre + +1. **Lancez les tests** : `scripts/run_tests.sh` (recommandé ; identique à la CI) ou `pytest tests/ -v` avec le venv du projet activé +2. **Testez manuellement** : lancez `hermes` et exercez le chemin de code que vous avez modifié +3. **Vérifiez l'impact multiplateforme** : si vous touchez aux E/S de fichiers, à la gestion des processus ou au terminal, pensez à macOS, Linux et WSL2 +4. **Gardez les PR ciblées** : un seul changement logique par PR. Ne mélangez pas une correction de bug avec un refactoring et une nouvelle fonctionnalité. + +### Description de la PR + +Incluez : +- **Quoi** a changé et **pourquoi** +- **Comment le tester** (étapes de reproduction pour les bugs, exemples d'usage pour les fonctionnalités) +- **Les plateformes** sur lesquelles vous avez testé +- Les références aux issues liées + +### Messages de commit + +Nous utilisons les [Conventional Commits](https://www.conventionalcommits.org/) : + +``` +(): +``` + +| Type | À utiliser pour | +|------|---------| +| `fix` | Corrections de bugs | +| `feat` | Nouvelles fonctionnalités | +| `docs` | Documentation | +| `test` | Tests | +| `refactor` | Restructuration du code (sans changement de comportement) | +| `chore` | Build, CI, mises à jour de dépendances | + +Scopes : `cli`, `gateway`, `tools`, `skills`, `agent`, `install`, `whatsapp`, `security`, etc. + +Exemples : +``` +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 +test(tools): add unit tests for file_operations +``` + +--- + +## Signaler un problème + +- Utilisez les [GitHub Issues](https://github.com/NousResearch/hermes-agent/issues) +- Incluez : OS, version de Python, version d'Hermes (`hermes version`), traceback d'erreur complet +- Incluez les étapes de reproduction +- Vérifiez les issues existantes avant de créer des doublons +- Pour les vulnérabilités de sécurité, merci de les signaler en privé + +--- + +## Communauté + +- **Discord** : [discord.gg/NousResearch](https://discord.gg/NousResearch) — pour poser des questions, présenter vos projets et partager des compétences +- **GitHub Discussions** : pour les propositions de conception et les discussions d'architecture +- **Skills Hub** : téléversez des compétences spécialisées sur un registre et partagez-les avec la communauté + +--- + +## Licence + +En contribuant, vous acceptez que vos contributions soient placées sous la [licence MIT](LICENSE). diff --git a/README.fr.md b/README.fr.md new file mode 100644 index 0000000000000..3cb9b8c80f1a4 --- /dev/null +++ b/README.fr.md @@ -0,0 +1,265 @@ +

+ Hermes Agent +

+ +# Hermes Agent ☤ +

+ Hermes Agent | Hermes Desktop +

+

+ Documentation + Discord + Licence : MIT + Créé par Nous Research + English + 中文 + اردو + Español +

+ +**L'agent d'IA auto-améliorant conçu par [Nous Research](https://nousresearch.com).** C'est le seul agent doté d'une boucle d'apprentissage intégrée : il crée des compétences à partir de son expérience, les améliore à l'usage, se pousse lui-même à pérenniser ses connaissances, fouille ses propres conversations passées et construit, session après session, un modèle de plus en plus fin de qui vous êtes. Faites-le tourner sur un VPS à 5 $, un cluster GPU ou une infrastructure serverless qui ne coûte presque rien à l'arrêt. Il n'est pas rivé à votre ordinateur portable — parlez-lui depuis Telegram pendant qu'il travaille sur une VM dans le cloud. + +Utilisez le modèle de votre choix — [Nous Portal](https://portal.nousresearch.com), OpenRouter, OpenAI, votre propre endpoint et [bien d'autres](https://hermes-agent.nousresearch.com/docs/integrations/providers). Changez de modèle avec `hermes model` — pas de modification de code, pas de verrouillage. + + + + + + + + + +
Une vraie interface de terminalTUI complète avec édition multiligne, autocomplétion des commandes slash, historique des conversations, interruption et redirection à la volée, et sortie des outils en streaming.
Il vit là où vous vivezTelegram, Discord, Slack, WhatsApp, Signal et CLI — le tout depuis un seul processus gateway. Transcription des mémos vocaux, continuité des conversations d'une plateforme à l'autre.
Une boucle d'apprentissage ferméeMémoire organisée par l'agent, avec des rappels périodiques. Création autonome de compétences après les tâches complexes. Les compétences s'améliorent d'elles-mêmes à l'usage. Recherche de sessions FTS5 avec résumé par LLM pour retrouver des informations d'une session à l'autre. Modélisation dialectique de l'utilisateur via Honcho. Compatible avec le standard ouvert agentskills.io.
Automatisations planifiéesPlanificateur cron intégré avec livraison sur n'importe quelle plateforme. Rapports quotidiens, sauvegardes nocturnes, audits hebdomadaires — le tout en langage naturel, sans aucune surveillance.
Il délègue et paralléliseLancez des sous-agents isolés pour mener plusieurs chantiers en parallèle. Écrivez des scripts Python qui appellent les outils via RPC, condensant des pipelines à plusieurs étapes en tours sans aucun coût de contexte.
Tourne partout, pas seulement sur votre laptopSix backends de terminal — local, Docker, SSH, Singularity, Modal et Daytona. Daytona et Modal offrent une persistance serverless : l'environnement de votre agent hiberne quand il est inactif et se réveille à la demande, pour un coût quasi nul entre les sessions. Faites-le tourner sur un VPS à 5 $ ou un cluster GPU.
Prêt pour la rechercheGénération de trajectoires par lots, compression de trajectoires pour entraîner la prochaine génération de modèles d'appel d'outils.
+ +--- + +## Installation rapide + +### Linux, macOS, WSL2, Termux + +```bash +curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash +``` + +### Windows (natif, PowerShell) + +> **Attention :** sous Windows natif, Hermes fonctionne sans WSL — la CLI, le gateway, la TUI et les outils tournent tous nativement. Si vous préférez passer par WSL2, la commande Linux/macOS ci-dessus y fonctionne aussi. Vous avez trouvé un bug ? Merci d'[ouvrir un ticket](https://github.com/NousResearch/hermes-agent/issues). + +Exécutez ceci dans PowerShell : + +```powershell +iex (irm https://hermes-agent.nousresearch.com/install.ps1) +``` + +L'installateur s'occupe de tout : uv, Python 3.11, Node.js, ripgrep, ffmpeg, **et un Git Bash portable** (MinGit, décompressé dans `%LOCALAPPDATA%\hermes\git` — aucun droit administrateur requis, complètement isolé de toute installation Git du système). Hermes utilise ce Git Bash embarqué pour exécuter les commandes shell. + +Si Git est déjà installé, l'installateur le détecte et l'utilise à la place. Sinon, un téléchargement MinGit d'environ 45 Mo suffit — il ne touchera pas au Git du système et n'interférera pas avec lui. + +> **Android / Termux :** le chemin d'installation manuel testé est documenté dans le [guide Termux](https://hermes-agent.nousresearch.com/docs/getting-started/termux). Sur Termux, Hermes installe un extra `.[termux]` restreint, car l'extra complet `.[all]` tire actuellement des dépendances vocales incompatibles avec Android. +> +> **Windows :** Windows natif est entièrement pris en charge — la commande PowerShell ci-dessus installe tout. Si vous préférez WSL2, la commande Linux y fonctionne aussi. L'installation Windows native se trouve dans `%LOCALAPPDATA%\hermes` ; sous WSL2, elle s'installe dans `~/.hermes` comme sous Linux. + +Après l'installation : + +```bash +source ~/.bashrc # reload shell (or: source ~/.zshrc) +hermes # start chatting! +``` + +### Dépannage + +#### Windows Defender ou un antivirus signale `uv.exe` comme malveillant + +Si votre antivirus (Bitdefender, Windows Defender, etc.) met en quarantaine `uv.exe` depuis le dossier `bin` de Hermes (`%LOCALAPPDATA%\hermes\bin\uv.exe`), il s'agit d'un **faux positif**. Ce fichier est `uv` d'Astral — le gestionnaire de paquets Python écrit en Rust qu'Hermes embarque pour gérer son environnement Python. Les moteurs antivirus à base de ML signalent couramment les binaires Rust non signés qui téléchargent et installent des paquets. + +**Pour vérifier que votre copie est authentique :** + +```powershell +# Install GitHub CLI if needed +winget install --id GitHub.cli + +# Login to GitHub +gh auth login + +# Run verification +$uv = "$env:LOCALAPPDATA\hermes\bin\uv.exe" +$ver = (& $uv --version).Split(' ')[1] +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$zip = "$env:TEMP\uv.zip" +Invoke-WebRequest "https://github.com/astral-sh/uv/releases/download/$ver/uv-x86_64-pc-windows-msvc.zip" -OutFile $zip -UseBasicParsing +gh attestation verify $zip --repo astral-sh/uv +Expand-Archive $zip "$env:TEMP\uv_x" -Force +(Get-FileHash "$env:TEMP\uv_x\uv.exe").Hash -eq (Get-FileHash $uv).Hash +``` + +Si l'attestation affiche « Verification succeeded » et que la dernière ligne renvoie `True`, tout est en ordre. + +**Pour mettre Hermes en liste blanche :** +- **Windows Defender :** lancez PowerShell en administrateur → `Add-MpPreference -ExclusionPath "$env:LOCALAPPDATA\hermes\bin"` +- **Bitdefender :** ajoutez une exception dans la console Bitdefender (Protection > Antivirus > Paramètres > Gérer les exceptions) +- Mettez le **dossier** en liste blanche, pas le hash du fichier — Hermes met `uv` à jour et le hash change à chaque version + +Pour plus de contexte, consultez les rapports upstream chez Astral : [astral-sh/uv#13553](https://github.com/astral-sh/uv/issues/13553), [astral-sh/uv#15011](https://github.com/astral-sh/uv/issues/15011), [astral-sh/uv#10079](https://github.com/astral-sh/uv/issues/10079). + +--- + +## Premiers pas + +```bash +hermes # Interactive CLI — start a conversation +hermes model # Choose your LLM provider and model +hermes tools # Configure which tools are enabled +hermes config set # Set individual config values +hermes gateway # Start the messaging gateway (Telegram, Discord, etc.) +hermes setup # Run the full setup wizard (configures everything at once) +hermes claw migrate # Migrate from OpenClaw (if coming from OpenClaw) +hermes update # Update to the latest version +hermes doctor # Diagnose any issues +``` + +📖 **[Documentation complète →](https://hermes-agent.nousresearch.com/docs/)** + +--- + +## Fini la collection de clés API — Nous Portal + +Hermes fonctionne avec le fournisseur de votre choix — ça ne changera pas. Mais si vous préférez ne pas accumuler cinq clés API distinctes pour le modèle, la recherche web, la génération d'images, le TTS et un navigateur cloud, **[Nous Portal](https://portal.nousresearch.com)** couvre tout cela avec un seul abonnement : + +- **Plus de 300 modèles** — choisissez n'importe lequel avec `/model ` +- **Tool Gateway** — recherche web (Firecrawl), génération d'images (FAL), synthèse vocale (OpenAI), navigateur cloud (Browser Use), le tout routé via votre abonnement. Aucun compte supplémentaire. + +Une seule commande depuis une installation vierge : + +```bash +hermes setup --portal +``` + +Elle vous connecte via OAuth, définit Nous comme fournisseur et active le Tool Gateway. Vérifiez à tout moment ce qui est branché avec `hermes portal info`. Tous les détails sur la [page de documentation du Tool Gateway](https://hermes-agent.nousresearch.com/docs/user-guide/features/tool-gateway). + +Vous pouvez toujours apporter vos propres clés, outil par outil — le gateway se configure backend par backend, pas en tout ou rien. + +--- + +## Référence rapide : CLI vs messagerie + +Hermes a deux points d'entrée : lancez l'interface de terminal avec `hermes`, ou démarrez le gateway et parlez-lui depuis Telegram, Discord, Slack, WhatsApp, Signal ou par e-mail. Une fois la conversation engagée, beaucoup de commandes slash sont communes aux deux interfaces. + +| Action | CLI | Plateformes de messagerie | +| ----------------------------------------- | --------------------------------------------- | -------------------------------------------------------------------------------- | +| Commencer à discuter | `hermes` | Lancez `hermes gateway setup` + `hermes gateway start`, puis envoyez un message au bot | +| Repartir d'une conversation vierge | `/new` ou `/reset` | `/new` ou `/reset` | +| Changer de modèle | `/model [provider:model]` | `/model [provider:model]` | +| Définir une personnalité | `/personality [name]` | `/personality [name]` | +| Réessayer ou annuler le dernier tour | `/retry`, `/undo` | `/retry`, `/undo` | +| Compresser le contexte / voir la consommation | `/compress`, `/usage`, `/insights [--days N]` | `/compress`, `/usage`, `/insights [days]` | +| Parcourir les compétences | `/skills` ou `/` | `/` | +| Interrompre le travail en cours | `Ctrl+C` ou envoyer un nouveau message | `/stop` ou envoyer un nouveau message | +| Statut propre à la plateforme | `/platforms` | `/status`, `/sethome` | + +Pour la liste complète des commandes, consultez le [guide CLI](https://hermes-agent.nousresearch.com/docs/user-guide/cli) et le [guide du gateway de messagerie](https://hermes-agent.nousresearch.com/docs/user-guide/messaging). + +--- + +## Documentation + +Toute la documentation se trouve sur **[hermes-agent.nousresearch.com/docs](https://hermes-agent.nousresearch.com/docs/)** : + +| Section | Contenu | +| --------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | +| [Démarrage rapide](https://hermes-agent.nousresearch.com/docs/getting-started/quickstart) | Installation → configuration → première conversation en 2 minutes | +| [Utilisation de la CLI](https://hermes-agent.nousresearch.com/docs/user-guide/cli) | Commandes, raccourcis clavier, personnalités, sessions | +| [Configuration](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) | Fichier de configuration, fournisseurs, modèles, toutes les options | +| [Gateway de messagerie](https://hermes-agent.nousresearch.com/docs/user-guide/messaging) | Telegram, Discord, Slack, WhatsApp, Signal, Home Assistant | +| [Sécurité](https://hermes-agent.nousresearch.com/docs/user-guide/security) | Approbation des commandes, appairage par DM, isolation en conteneur | +| [Outils et toolsets](https://hermes-agent.nousresearch.com/docs/user-guide/features/tools) | Plus de 40 outils, système de toolsets, backends de terminal | +| [Système de compétences](https://hermes-agent.nousresearch.com/docs/user-guide/features/skills) | Mémoire procédurale, Skills Hub, création de compétences | +| [Mémoire](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) | Mémoire persistante, profils utilisateur, bonnes pratiques | +| [Intégration MCP](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) | Connectez n'importe quel serveur MCP pour étendre les capacités | +| [Planification cron](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) | Tâches planifiées avec livraison sur les plateformes | +| [Fichiers de contexte](https://hermes-agent.nousresearch.com/docs/user-guide/features/context-files) | Un contexte de projet qui façonne chaque conversation | +| [Architecture](https://hermes-agent.nousresearch.com/docs/developer-guide/architecture) | Structure du projet, boucle de l'agent, classes principales | +| [Contribuer](https://hermes-agent.nousresearch.com/docs/developer-guide/contributing) | Environnement de développement, processus de PR, style de code | +| [Référence CLI](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) | Toutes les commandes et tous les flags | +| [Variables d'environnement](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) | Référence complète des variables d'environnement | + +--- + +## Migration depuis OpenClaw + +Si vous venez d'OpenClaw, Hermes peut importer automatiquement vos réglages, vos mémoires, vos compétences et vos clés API. + +**Lors de la première configuration :** l'assistant de configuration (`hermes setup`) détecte automatiquement `~/.openclaw` et propose la migration avant de commencer la configuration. + +**À tout moment après l'installation :** + +```bash +hermes claw migrate # Interactive migration (full preset) +hermes claw migrate --dry-run # Preview what would be migrated +hermes claw migrate --preset user-data # Migrate without secrets +hermes claw migrate --overwrite # Overwrite existing conflicts +``` + +Ce qui est importé : + +- **SOUL.md** — fichier de persona +- **Mémoires** — entrées de MEMORY.md et USER.md +- **Compétences** — compétences créées par l'utilisateur → `~/.hermes/skills/openclaw-imports/` +- **Liste blanche de commandes** — motifs d'approbation +- **Réglages de messagerie** — configuration des plateformes, utilisateurs autorisés, répertoire de travail +- **Clés API** — secrets en liste blanche (Telegram, OpenRouter, OpenAI, Anthropic, ElevenLabs) +- **Assets TTS** — fichiers audio de l'espace de travail +- **Instructions d'espace de travail** — AGENTS.md (avec `--workspace-target`) + +Voir `hermes claw migrate --help` pour toutes les options, ou utilisez la compétence `openclaw-migration` pour une migration interactive guidée par l'agent, avec prévisualisation en dry-run. + +--- + +## Contribuer + +Les contributions sont les bienvenues ! Consultez le [Guide de contribution](CONTRIBUTING.fr.md) pour l'environnement de développement, le style de code et le processus de PR. + +Démarrage rapide pour les contributeurs — utilisez l'installateur standard, puis +travaillez depuis le checkout git complet qu'il crée dans `$HERMES_HOME/hermes-agent` +(généralement `~/.hermes/hermes-agent`). C'est la disposition attendue par +`hermes update`, le venv managé, les dépendances chargées à la demande, le gateway +et l'outillage de la documentation. + +```bash +curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash +cd "${HERMES_HOME:-$HOME/.hermes}/hermes-agent" +uv pip install -e ".[all,dev]" +scripts/run_tests.sh +``` + +Solution de repli avec clone manuel (pour les clones jetables ou la CI, quand vous +ne voulez volontairement pas de la disposition d'installation managée) : + +Créez le venv en dehors de l'arborescence clonée — un venv placé dans le répertoire +depuis lequel l'agent opère peut être effacé par une commande en chemin relatif que +l'agent exécute contre son propre checkout, détruisant le runtime en pleine session. + +```bash +curl -LsSf https://astral.sh/uv/install.sh | sh +uv venv ~/.hermes/venvs/hermes-dev --python 3.11 +source ~/.hermes/venvs/hermes-dev/bin/activate +uv pip install -e ".[all,dev]" +scripts/run_tests.sh +``` + +--- + +## Communauté + +- 💬 [Discord](https://discord.gg/NousResearch) +- 📚 [Skills Hub](https://agentskills.io) +- 🐛 [Issues](https://github.com/NousResearch/hermes-agent/issues) +- 🔌 [computer-use-linux](https://github.com/avifenesh/computer-use-linux) — Serveur MCP de contrôle du bureau Linux pour Hermes et d'autres hôtes MCP, avec arbres d'accessibilité AT-SPI, entrée Wayland/X11, captures d'écran et ciblage des fenêtres du compositeur. +- 🔌 [HermesClaw](https://github.com/AaronWong1999/hermesclaw) — Passerelle WeChat communautaire : faites tourner Hermes Agent et OpenClaw sur le même compte WeChat. + +--- + +## Licence + +MIT — voir [LICENSE](LICENSE). + +Conçu par [Nous Research](https://nousresearch.com). diff --git a/SECURITY.fr.md b/SECURITY.fr.md new file mode 100644 index 0000000000000..e63ca1566fab6 --- /dev/null +++ b/SECURITY.fr.md @@ -0,0 +1,371 @@ +# Politique de sécurité de Hermes Agent + +Ce document décrit le modèle de confiance de Hermes Agent, identifie +l'unique frontière de sécurité que le projet considère comme structurelle +et définit le périmètre des signalements de vulnérabilités. + +## 1. Signaler une vulnérabilité + +Signalez de manière privée via les [GitHub Security Advisories](https://github.com/NousResearch/hermes-agent/security/advisories/new) +ou **security@nousresearch.com**. N'ouvrez pas d'issues publiques pour +des vulnérabilités de sécurité. **Hermes Agent n'opère pas de programme +de bug bounty.** + +Un signalement utile comprend : + +- Une description concise et une évaluation de la gravité. +- Le composant affecté, identifié par chemin de fichier et plage de + lignes (ex. `path/to/file.py:120-145`). +- Les détails de l'environnement (`hermes version`, SHA du commit, OS, + version de Python). +- Une reproduction sur `main` ou la dernière release. +- Une indication de la frontière de confiance du §2 qui est franchie. + +Merci de lire le §2 et le §3 avant d'envoyer. Les signalements qui +démontrent les limites d'une heuristique intra-processus que cette +politique ne considère pas comme une frontière seront fermés comme hors +périmètre au titre du §3 — mais voyez le §3.2 : ils restent les +bienvenus sous forme d'issues ou de pull requests classiques, simplement +pas via le canal de sécurité privé. + +--- + +## 2. Modèle de confiance + +Hermes Agent est un agent personnel mono-utilisateur. Sa posture est en +couches, et ces couches n'ont pas toutes le même poids. Les rapporteurs +et les opérateurs doivent raisonner à leur sujet dans les mêmes termes. + +### 2.1 Définitions + +- **Processus de l'agent.** L'interpréteur Python qui exécute Hermes + Agent, y compris tout module Python qu'il a chargé (skills, plugins, + gestionnaires de hooks). +- **Backend de terminal.** Une cible d'exécution enfichable pour + l'outil `terminal()`. Le backend par défaut exécute les commandes + directement sur l'hôte. D'autres backends les exécutent dans un + conteneur, une sandbox cloud ou un hôte distant. +- **Surface d'entrée.** Tout canal par lequel du contenu entre dans le + contexte de l'agent : saisie de l'opérateur, requêtes web, e-mails, + messages du gateway, lectures de fichiers, réponses de serveurs MCP, + résultats d'outils. +- **Enveloppe de confiance.** L'ensemble des ressources auxquelles un + opérateur a implicitement donné accès à Hermes Agent en le lançant — + typiquement, tout ce que le compte utilisateur de l'opérateur peut + atteindre sur l'hôte. +- **Position.** Une déclaration explicite dans la documentation ou le + code de Hermes Agent sur la façon dont une couche consommatrice + (adaptateur, UI, écriture de fichiers, shell) doit traiter la sortie + de l'agent — ex. « le dashboard rend la sortie de l'agent comme du + HTML inerte ». + +### 2.2 La frontière : l'isolation au niveau de l'OS + +**La seule frontière de sécurité face à un LLM adverse est le système +d'exploitation.** Rien à l'intérieur du processus de l'agent ne +constitue un confinement — ni le portail d'approbation, ni la rédaction +des sorties, ni aucun scanner de motifs, ni aucune liste d'outils +autorisés. Tout composant intra-processus qui filtre la sortie du LLM +est une heuristique opérant sur une chaîne influencée par l'attaquant, +et cette politique le traite comme tel. + +Hermes Agent prend en charge deux postures d'isolation au niveau de +l'OS. Elles répondent à des menaces différentes et un opérateur doit +choisir en connaissance de cause. + +#### Isolation par le backend de terminal + +Un backend de terminal autre que celui par défaut exécute les commandes +shell émises par le LLM dans un conteneur, un hôte distant ou une +sandbox cloud. Les outils de fichiers (`read_file`, `write_file`, +`patch`) passent aussi par ce backend, puisqu'ils sont implémentés +au-dessus du contrat du shell — ils ne peuvent pas atteindre de chemins +que le backend n'expose pas. + +Ce que cela confine : tout ce que l'agent fait en émettant des +opérations shell ou fichiers. Ce que cela ne confine **pas** : tout ce +que l'agent fait dans son propre processus Python. Cela inclut l'outil +d'exécution de code (lancé comme sous-processus sur l'hôte), les +sous-processus MCP (lancés depuis l'environnement de l'agent), le +chargement des plugins, le déclenchement des hooks et le chargement des +skills (tous importés dans l'interpréteur de l'agent). + +L'isolation par le backend de terminal est la bonne posture lorsque le +risque redouté est l'émission par le LLM de commandes shell +destructrices ou d'écritures indésirables via les outils de fichiers, +et que l'opérateur est par ailleurs de confiance. + +#### Encapsulation du processus complet + +L'encapsulation du processus complet exécute l'intégralité de l'arbre +de processus de l'agent dans une sandbox. Chaque chemin de code — +shell, exécution de code, MCP, outils de fichiers, plugins, hooks, +chargement des skills — est soumis à la même politique de système de +fichiers, de réseau, de processus et (le cas échéant) d'inférence. + +Hermes Agent le permet de deux façons : + +- **L'image Docker et la configuration Compose de Hermes Agent.** Plus + légère ; l'agent tourne dans un conteneur standard avec des montages + et une politique réseau configurés par l'opérateur. +- **[NVIDIA OpenShell](https://github.com/NVIDIA/OpenShell)**. + OpenShell fournit des sandboxes par session avec une politique + déclarative couvrant le système de fichiers, le réseau (egress L7), + les processus/syscalls et le routage d'inférence. Les politiques + réseau et d'inférence sont rechargeables à chaud. Les identifiants + sont injectés depuis un magasin Provider et ne touchent jamais le + système de fichiers de la sandbox. + +Sous une encapsulation du processus complet, les heuristiques +intra-processus de Hermes Agent (§2.4) jouent le rôle de prévention +des accidents, par-dessus une véritable frontière. C'est la posture +prise en charge lorsque l'agent ingère du contenu provenant de surfaces +que l'opérateur ne contrôle pas — le web ouvert, les e-mails entrants, +les canaux multi-utilisateurs, les serveurs MCP non fiables — ainsi que +pour les déploiements en production ou partagés. + +Les opérateurs qui exécutent le backend local par défaut avec des +surfaces d'entrée non fiables, ou qui exécutent une sandbox de backend +de terminal en s'attendant à ce qu'elle confine des chemins de code qui +ne passent pas par le shell, opèrent en dehors de la posture de +sécurité prise en charge. + +### 2.3 Portée des identifiants + +Hermes Agent filtre l'environnement qu'il transmet à ses composants +intra-processus de moindre confiance : sous-processus shell, +sous-processus MCP, scripts de tâches cron et processus enfant +d'exécution de code. Les identifiants comme les clés API des providers +et les tokens du gateway sont retirés par défaut ; les variables +explicitement déclarées par l'opérateur ou par une skill chargée sont +transmises. + +Cela réduit l'exfiltration opportuniste. Ce n'est pas du confinement. +Tout composant s'exécutant dans le processus de l'agent (skills, +plugins, gestionnaires de hooks) peut lire tout ce que l'agent lui-même +peut lire, y compris les identifiants en mémoire. La parade contre un +composant intra-processus compromis est la revue par l'opérateur avant +installation (§2.4, §2.5), pas le nettoyage de l'environnement. + +### 2.4 Heuristiques intra-processus + +Les composants suivants filtrent le comportement du LLM ou alertent à +son sujet. Ils sont utiles. Ce ne sont pas des frontières. + +- Le **portail d'approbation** détecte les motifs shell destructeurs + courants et demande confirmation à l'opérateur avant exécution. Le + shell est Turing-complet ; une liste noire sur des chaînes shell est + structurellement incomplète. Le portail attrape les erreurs en mode + coopératif, pas les sorties adverses. +- La **rédaction des sorties** supprime de l'affichage les motifs + ressemblant à des secrets. Un producteur de sorties déterminé la + contournera. +- **Skills Guard** analyse le contenu des skills installables à la + recherche de motifs d'injection. C'est une aide à la revue ; la + frontière pour les skills tierces est la revue par l'opérateur avant + installation. Passer une skill en revue signifie lire son code Python + et ses scripts, pas seulement sa description SKILL.md — les skills + exécutent du Python arbitraire au moment de l'import. + +### 2.5 Modèle de confiance des plugins + +Les plugins se chargent dans le processus de l'agent et s'exécutent +avec tous ses privilèges : ils peuvent lire les mêmes identifiants, +appeler les mêmes outils, enregistrer les mêmes hooks et importer les +mêmes modules que n'importe quel code livré dans le dépôt. La frontière +pour les plugins tiers est la revue par l'opérateur avant installation +— la même règle que pour les skills (§2.4), mentionnée à part parce que +les plugins sont architecturalement plus lourds et embarquent souvent +leurs propres services d'arrière-plan, écouteurs réseau et dépendances. + +Un plugin malveillant ou bogué n'est pas une vulnérabilité de Hermes +Agent en soi. Les bugs dans le chemin d'installation ou de découverte +des plugins de Hermes Agent qui empêchent l'opérateur de voir ce qu'il +installe sont dans le périmètre au titre du §3.1. + +### 2.6 Surfaces externes + +Une **surface externe** est tout canal extérieur au processus local de +l'agent par lequel un appelant peut déclencher du travail de l'agent, +résoudre des approbations ou recevoir la sortie de l'agent. Chaque +surface a son propre modèle d'autorisation, mais les règles ci-dessous +s'appliquent uniformément. + +**Surfaces dans Hermes Agent :** + +- **Adaptateurs de plateforme du gateway.** Les intégrations de + messagerie dans `gateway/platforms/` (Telegram, Discord, Slack, + e-mail, SMS, etc.) et les adaptateurs analogues livrés sous forme de + plugins. +- **Surfaces HTTP exposées au réseau.** L'adaptateur du serveur API, le + plugin du dashboard, les endpoints HTTP du plugin kanban, et tout + autre plugin qui ouvre un socket d'écoute. +- **Adaptateurs éditeur / IDE.** L'adaptateur ACP (`acp_adapter/`) et + les intégrations équivalentes qui acceptent des requêtes d'un + processus client local. +- **Le gateway TUI (`tui_gateway/`).** Backend JSON-RPC de l'interface + terminal Ink, joint via IPC local. + +**Règles uniformes :** + +1. **Une autorisation est requise à chaque surface qui franchit une + frontière de confiance.** Pour les surfaces de messagerie et HTTP + réseau, la frontière est le réseau : l'autorisation prend la forme + d'une liste d'appelants autorisés configurée par l'opérateur. Pour + les surfaces éditeur et IPC local (ACP, gateway TUI), la frontière + est le compte utilisateur de l'hôte : l'autorisation consiste à + s'appuyer sur le contrôle d'accès de l'OS (permissions de fichiers, + liaisons loopback uniquement) et à ne pas exposer la surface au-delà + de l'utilisateur local sans une couche d'authentification réseau + explicite. +2. **Une liste d'autorisation est requise pour chaque adaptateur exposé + au réseau qui est activé.** Les adaptateurs doivent refuser de + déclencher du travail de l'agent, de résoudre des approbations ou de + relayer des sorties tant qu'aucune liste d'autorisation n'est + définie. Les chemins de code qui laissent passer par défaut + lorsqu'aucune liste n'est configurée sont des bugs de code dans le + périmètre au titre du §3.1. +3. **Les identifiants de session sont des poignées de routage, pas des + frontières d'autorisation.** Connaître l'ID de session d'un autre + appelant ne donne pas accès à ses approbations ni à ses sorties ; + l'autorisation est toujours revérifiée contre la liste + d'autorisation (ou son équivalent au niveau de l'OS). +4. **Au sein de l'ensemble autorisé, tous les appelants bénéficient de + la même confiance.** Hermes Agent ne modélise pas de capacités par + appelant au sein d'un même adaptateur. Les opérateurs qui ont besoin + d'une séparation des capacités doivent exécuter des instances + d'agent distinctes avec des listes d'autorisation distinctes. +5. **Lier une surface locale à une interface autre que loopback est une + décision d'opérateur de dernier recours (§3.2).** Le dashboard et + les autres serveurs HTTP de plugins écoutent en loopback par + défaut ; les exposer via `--host 0.0.0.0` ou équivalent fait du + durcissement pour exposition publique (§4) la responsabilité de + l'opérateur. + +--- + +## 3. Périmètre + +### 3.1 Dans le périmètre + +- L'échappement d'une posture d'isolation OS déclarée (§2.2) : un + chemin de code contrôlé par l'attaquant atteignant un état que la + posture prétendait confiner. +- L'accès non autorisé à une surface externe : un appelant hors de + l'ensemble d'autorisation configuré (liste d'autorisation, ou + équivalent au niveau de l'OS pour les surfaces IPC locales) qui + déclenche du travail, reçoit des sorties ou résout des approbations + (§2.6). +- L'exfiltration d'identifiants : fuite d'identifiants de l'opérateur + ou de matériel d'autorisation de session vers une destination hors de + l'enveloppe de confiance, via un mécanisme qui aurait dû l'empêcher + (bug de nettoyage de l'environnement, journalisation d'un adaptateur, + erreur de transport qui déverse des identifiants vers un amont, + etc.). +- Les violations de la documentation du modèle de confiance : du code + qui se comporte contrairement à ce que cette politique, la propre + documentation de Hermes Agent ou les attentes raisonnables d'un + opérateur laisseraient prévoir — y compris les cas où Hermes Agent a + documenté une position sur la façon dont sa sortie doit être rendue + par une couche consommatrice (dashboard, adaptateur de gateway, + écriture de fichiers, shell) et où un chemin de code enfreint cette + position. + +### 3.2 Hors périmètre + +« Hors périmètre » signifie ici « pas une vulnérabilité de sécurité au +sens de cette politique ». Cela ne signifie pas « pas digne d'être +signalé ». Les améliorations des heuristiques intra-processus, les +idées de durcissement et les corrections d'UX sont les bienvenues sous +forme d'issues ou de pull requests classiques — le portail +d'approbation peut toujours attraper plus de motifs, la rédaction peut +toujours devenir plus fine, le comportement des adaptateurs peut +toujours être resserré. Ces éléments ne passent simplement pas par le +canal de divulgation privé et ne donnent pas lieu à des avis de +sécurité. + +- **Les contournements des heuristiques intra-processus (§2.4)** — + contournements des regex du portail d'approbation, contournements de + la rédaction, contournements des motifs de Skills Guard, et + signalements analogues visant de futures heuristiques. Ces composants + ne sont pas des frontières ; les déjouer n'est pas une vulnérabilité + au sens de cette politique. +- **L'injection de prompt en soi.** Amener le LLM à émettre une sortie + inhabituelle — via du contenu injecté, une hallucination, des + artefacts d'entraînement ou toute autre cause — n'est pas en soi une + vulnérabilité. « J'ai réussi une injection de prompt » sans + enchaînement vers un résultat du §3.1 n'est pas un signalement + exploitable au sens de cette politique. +- **Les conséquences d'une posture d'isolation choisie.** Les + signalements indiquant qu'un chemin de code opérant dans le périmètre + de sa posture peut faire ce que cette posture permet ne sont pas des + vulnérabilités. Exemples : des outils shell ou fichiers atteignant + l'état de l'hôte sous le backend local ; des sous-processus + d'exécution de code ou MCP atteignant l'état de l'hôte sous une + isolation par backend de terminal qui ne sandboxe que le shell ; des + signalements dont les préconditions exigent un accès en écriture + préexistant à des fichiers de configuration ou d'identifiants + appartenant à l'opérateur (ceux-ci sont déjà à l'intérieur de + l'enveloppe de confiance). +- **Les réglages de dernier recours documentés.** Les compromis choisis + par l'opérateur qui désactivent explicitement des protections : + `--insecure` et les flags équivalents sur le dashboard ou d'autres + composants, approbations désactivées, backend local en production, + profils de développement qui contournent la sécurité de hermes-home, + et similaires. Les signalements contre ces configurations ne sont pas + des vulnérabilités — c'est précisément le rôle du flag. +- **Les skills et plugins issus de la communauté.** Les skills tierces + (y compris le dépôt de skills de la communauté) et les plugins tiers + relèvent de la surface de revue de l'opérateur, pas de la surface de + confiance de Hermes Agent (§2.4, §2.5). Une skill ou un plugin qui + fait quelque chose de malveillant est le mode de défaillance attendu + d'un élément qui n'a pas été passé en revue, pas une vulnérabilité de + Hermes Agent. Les bugs dans le chemin d'installation des skills ou + des plugins de Hermes Agent qui empêchent l'opérateur de voir ce + qu'il installe sont dans le périmètre au titre du §3.1. +- **L'exposition publique sans contrôles externes.** Exposer le gateway + ou l'API à l'internet public sans authentification, VPN ni pare-feu. +- **Les restrictions de lecture/écriture au niveau des outils dans une + posture où le shell est permis.** Si un chemin est atteignable via + l'outil terminal, les signalements indiquant que d'autres outils de + fichiers peuvent l'atteindre n'apportent rien. + +--- + +## 4. Durcissement du déploiement + +La décision de durcissement la plus importante est de faire +correspondre l'isolation (§2.2) au niveau de confiance du contenu que +l'agent va ingérer. Au-delà de cela : + +- Exécutez l'agent en tant qu'utilisateur non root. L'image de + conteneur fournie le fait par défaut. +- Conservez les identifiants dans le fichier d'identifiants de + l'opérateur avec des permissions strictes, jamais dans la + configuration principale, jamais sous contrôle de version. Sous + OpenShell, utilisez le magasin Provider plutôt qu'un fichier + d'identifiants sur disque. +- N'exposez pas le gateway ou l'API à l'internet public sans VPN, + Tailscale ou protection par pare-feu. Sous OpenShell, utilisez la + couche de politique réseau pour restreindre l'egress. +- Configurez une liste d'appelants autorisés pour chaque adaptateur + exposé au réseau que vous activez (§2.6). +- Passez en revue les skills et plugins tiers avant installation + (§2.4, §2.5). Pour les skills, cela signifie lire le Python et les + scripts, pas seulement SKILL.md. Les rapports de Skills Guard et le + journal d'audit d'installation constituent la surface de revue. +- Hermes Agent inclut des garde-fous de chaîne d'approvisionnement pour + le lancement des serveurs MCP et pour les changements de dépendances + / paquets embarqués en CI ; voir `CONTRIBUTING.md` pour les détails. + +--- + +## 5. Divulgation + +- **Fenêtre de divulgation coordonnée :** 90 jours à compter du + signalement, ou jusqu'à la publication d'un correctif, selon la + première échéance. +- **Canal :** le fil GHSA ou la correspondance par e-mail avec + security@nousresearch.com. +- **Crédit :** les rapporteurs sont crédités dans les notes de version, + sauf demande d'anonymat. From d47613e88deeb661fbbc0a093af57799b0c65cea Mon Sep 17 00:00:00 2001 From: Billard <82095453+iacker@users.noreply.github.com> Date: Fri, 17 Jul 2026 07:20:12 +0200 Subject: [PATCH 2/2] docs(i18n): fix French cross-refs and add README language badge Address hermes-sweeper review on #63660: - SECURITY.fr.md: point security-policy cross-reference to CONTRIBUTING.fr.md (matching SECURITY.es.md localization convention) - README.md: add README.fr.md language badge so the French translation is discoverable from the primary entry point Signed-off-by: Billard <82095453+iacker@users.noreply.github.com> --- README.md | 1 + SECURITY.fr.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ba1322a389207..f39e0f322c7a2 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ 中文 اردو Español + Français

**The self-improving AI agent built by [Nous Research](https://nousresearch.com).** It's the only agent with a built-in learning loop — it creates skills from experience, improves them during use, nudges itself to persist knowledge, searches its own past conversations, and builds a deepening model of who you are across sessions. Run it on a $5 VPS, a GPU cluster, or serverless infrastructure that costs nearly nothing when idle. It's not tied to your laptop — talk to it from Telegram while it works on a cloud VM. diff --git a/SECURITY.fr.md b/SECURITY.fr.md index e63ca1566fab6..c09b90c0a085a 100644 --- a/SECURITY.fr.md +++ b/SECURITY.fr.md @@ -356,7 +356,7 @@ l'agent va ingérer. Au-delà de cela : journal d'audit d'installation constituent la surface de revue. - Hermes Agent inclut des garde-fous de chaîne d'approvisionnement pour le lancement des serveurs MCP et pour les changements de dépendances - / paquets embarqués en CI ; voir `CONTRIBUTING.md` pour les détails. + / paquets embarqués en CI ; voir `CONTRIBUTING.fr.md` pour les détails. ---