Merlya
AI-powered infrastructure assistant for DevOps & SysAdmins
Aperçu
Merlya est un assistant CLI autonome qui comprend le contexte de votre infrastructure, planifie des actions intelligentes et les exécute en toute sécurité. Il combine un SmartExtractor (LLM + regex hybride) pour extraire les hosts des requêtes en langage naturel, un pool SSH sécurisé, et une gestion d'inventaire simplifiée.
Fonctionnalités clés
- Commandes en langage naturel pour diagnostiquer et remédier vos environnements
- Architecture spécialistes :
MerlyaAgentdélègue aux spécialistes (diagnostic, exécution, sécurité) selon la demande - Pool SSH async avec MFA/2FA, jump hosts et SFTP
- Inventaire
/hostsavec import intelligent (SSH config, /etc/hosts, Ansible, TOML, CSV) - Modèles brain/fast : brain pour le raisonnement complexe, fast pour les décisions rapides
- Pipelines IaC : Ansible, Terraform, Kubernetes, Bash avec HITL obligatoire
- Élévation explicite : configuration sudo/doas/su par host (pas d'auto-détection)
- Sécurité by design : secrets dans le keyring, validation Pydantic, détection de boucles
- Observabilité : métriques in-memory + circuit breaker / retry (
/metrics) - i18n : français et anglais
- Intégration MCP pour consommer des tools externes (GitHub, Slack, custom) via
/mcp
Architecture
┌─────────────────────────────────────────────────────────────────────────────┐
│ USER INPUT │
│ "Check disk on web-01 via bastion" │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ SMART EXTRACTOR │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Fast Model │───▶│ Regex │───▶│ Hosts │ │
│ │ (semantic) │ │ Patterns │ │ Inventory │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ Output: hosts=[web-01], via=bastion, context injected │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ MERLYA AGENT │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ System prompt guides delegation decision (no separate classifier) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Diagnostic│ │Execution │ │Security │ │ Query │ │
│ │Specialist│ │Specialist│ │Specialist│ │Specialist│ │
│ │read-only │ │HITL+pipes│ │sec audits│ │inventory │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ SECURITY LAYER │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Keyring │ │ Elevation │ │ Loop │ │
│ │ Secrets │ │ Explicit │ │ Detection │ │
│ │ @secret-ref │ │ (per-host) │ │ (5+ repeat) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ SSH POOL │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Connection │ │ Jump Host │ │ MFA │ │
│ │ Reuse │ │ Support │ │ Support │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ PERSISTENCE │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Hosts │ │ Sessions │ │ Audit │ │ Raw Logs │ │ Messages │ │
│ │ Inventory│ │ Context │ │ Logs │ │ (TTL) │ │ History │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ SQLite + Keyring │
└─────────────────────────────────────────────────────────────────────────────┘
Installation (utilisateurs finaux)
pip install merlya
merlya
Installation Docker
# Copier et configurer les variables d'environnement
cp .env.example .env
# Éditer .env avec vos clés API
# Lancer le conteneur
docker compose up -d
# Mode développement (code source monté)
docker compose --profile dev up -d
Configuration SSH pour Docker :
Le conteneur monte votre répertoire SSH local. Par défaut, il utilise $HOME/.ssh.
Dans les environnements CI/CD où $HOME peut ne pas être défini, vous devez explicitement définir SSH_DIR :
# Via variable d'environnement
SSH_DIR=/root/.ssh docker compose up -d
# Ou dans votre fichier .env
SSH_DIR=/home/jenkins/.ssh
Permissions requises :
- Répertoire SSH :
700(rwx pour propriétaire uniquement) - Clés privées :
600(rw pour propriétaire uniquement)
Voir .env.example pour la documentation complète des variables.
Premier démarrage
- Sélection de la langue (fr/en)
- Configuration du provider LLM (clé stockée dans le keyring)
- Scan local et import d’hôtes (SSH config, /etc/hosts, inventaires Ansible)
- Health checks (RAM, disque, LLM, SSH, keyring, web search)
Exemples rapides
> Check disk usage on web-prod-01
> /hosts list
> /ssh exec db-01 "uptime"
> /model show
> /metrics
> /variable set region eu-west-1
> /mcp list
Syntaxe des targets :
@web-01→ lookup inventaire (hostname + username résolus depuis la base)ubuntu@192.168.1.5→ utilisateur SSH explicite + IP192.168.1.5→ IP directe (username depuis l'inventaire si connu)@db-password→ référence secret dans le keyring (résolu à l'exécution)
Sécurité
Secrets — jamais exposés au LLM
Les secrets (mots de passe, tokens, clés API) sont stockés dans le keyring système (macOS Keychain, Linux Secret Service) et référencés par @nom-secret :
> Connect to MongoDB with @db-password
# Le LLM voit "@db-password", jamais la valeur réelle
# Résolution uniquement au moment de l'exécution
# Logs : "mongo -p ***", jamais la vraie valeur
HITL — confirmation obligatoire
Toute opération destructive (restart, écriture fichier, installation) requiert une confirmation explicite avant exécution. L'ExecutionSpecialist ne peut pas contourner ce mécanisme.
Élévation de privilèges
L'élévation (sudo, doas, su) est toujours explicite — jamais auto-détectée. Elle se configure par host et les mots de passe sont stockés dans le keyring sous elevation:hostname:password.
Détection de boucles
Le ToolCallTracker détecte les patterns répétitifs (même commande 3+ fois, alternance A-B-A-B) et stoppe l'exécution automatiquement.
Configuration
- Fichier utilisateur :
~/.merlya/config.yaml(langue, modèle, timeouts SSH, UI). - Clés API : stockées dans le keyring. Fallback en mémoire avec avertissement.
- Variables d'environnement utiles :
| Variable | Description |
|---|---|
OPENROUTER_API_KEY |
Clé OpenRouter (provider par défaut) |
ANTHROPIC_API_KEY |
Clé Anthropic |
OPENAI_API_KEY |
Clé OpenAI |
MISTRAL_API_KEY |
Clé Mistral |
GROQ_API_KEY |
Clé Groq |
MERLYA_ROUTER_FALLBACK |
Modèle LLM de fallback pour le routage |
Installation pour contributeurs
git clone https://github.com/m-kis/merlya.git
cd merlya
python -m venv .venv
source .venv/bin/activate # ou .venv\\Scripts\\activate sous Windows
pip install -e ".[dev]" # Dépendances de dev
merlya --version
pytest tests/ -v
Qualité et scripts
| Vérification | Commande |
|---|---|
| Lint | ruff check merlya/ |
| Format (check) | ruff format --check merlya/ |
| Type check | mypy merlya/ |
| Tests + coverage | pytest tests/ --cov=merlya --cov-report=term-missing |
| Sécurité (code) | bandit -r merlya/ -c pyproject.toml |
| Sécurité (dépendances) | pip-audit -r <(pip freeze) |
Principes clés : DRY/KISS/YAGNI, SOLID, SoC, LoD, pas de fichiers > ~600 lignes, couverture ≥ 80%, commits conventionnels (cf. CONTRIBUTING.md).
CI/CD
.github/workflows/ci.yml: lint + format check + mypy + tests + sécurité (Bandit + pip-audit) sur runners GitHub pour chaque PR/push..github/workflows/release.yml: build + release GitHub + publication PyPI via trusted publishing, déclenché sur tagv*ouworkflow_dispatchpar un mainteneur (pas de secrets sur les PR externes).- Branche
mainprotégée : merge via PR, CI requis, ≥1 review, squash merge recommandé.
Documentation
📚 Documentation complète : https://merlya.m-kis.fr/
Fichiers locaux :
- docs/architecture.md : architecture et décisions
- docs/commands.md : commandes slash
- docs/configuration.md : configuration complète
- docs/tools.md : tools et agents
- docs/ssh.md : SSH, bastions, MFA
- docs/extending.md : extensions/agents
- SECURITY.md : modèle de sécurité et signalement de vulnérabilités
Contribuer
- Lisez CONTRIBUTING.md pour les conventions (commits, branches, limites de taille de fichiers/fonctions).
- Respectez le CODE_OF_CONDUCT.md.
- Les templates d’issues et de PR sont disponibles dans
.github/.
Sécurité
Consultez SECURITY.md. Ne publiez pas de vulnérabilités en issue publique : écrivez à security@merlya.fr.
Licence
MIT avec Commons Clause. La Commons Clause interdit la vente du logiciel comme service hébergé tout en autorisant l’usage, la modification et la redistribution.
Made by M-KIS
Metadata
Release files for merlya 0.8.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| merlya-0.8.5.tar.gz | 1.1 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| merlya-0.8.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.7 MB
Release files / merlya-0.8.5.tar.gz
| Download URL | merlya-0.8.5.tar.gz |
|---|---|
| Size | 1.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c49211e32e494485cbc692695fb9b5c641bbc4473a3008077d7d78afe3372d07
|
|
BLAKE2b-256 checksum How to use checksums |
5e89c27eaff71e98b7538f58e8f7066b91123d829bc7bf3fc7743117dbd35fec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 22, 2026.
Transparency logRelease files / merlya-0.8.5-py3-none-any.whl
| Download URL | merlya-0.8.5-py3-none-any.whl |
|---|---|
| Size | 592.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cd664832f1281718d8901f59c6edda815d0e99caabbba340171f0281bfcf5bd9
|
|
BLAKE2b-256 checksum How to use checksums |
7d50bad815aa1ffa65153f1d6bffa57402f6e5db8ab010cc05b914bc38e0b572
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 22, 2026.
Transparency log