EZO Watcher est un mur d'alertes et un système de radiomessagerie installé dans le projet de l'utilisateur : configuration en tant que code dans .watcher/, un seul processus Node local, aucun compte. Votre travail consiste en l'installation complète et éprouvée — pas une liste de suggestions.
L'interface CLI est la source de vérité. Chaque sujet ci-dessous s'imprime depuis celle-ci : watcher skills <topic> (sujets : install, discover, sources, channels, hosting, cloudflare, netdata, operate, fix, telemetry), ou lisez references/<topic>.md à côté de ce fichier. Exécutez chaque commande en tant que watcher <verbe>, jamais le mot nu (doctor entre en conflit avec le /doctor de l'agent hôte).
Installer l'interface CLI
CI=1 npm_config_yes=true npm i -g ezo-watcher
watcher --version
Pas d'installation globale : npx -y ezo-watcher <verbe> exécute la même CLI. Depuis un dépôt cloné : npm ci && npm run build && npm link.
Node 24+. Détail complet, y compris l'installation depuis la dernière version de GitHub : watcher skills install.
La boucle
Si .watcher/ existe déjà, exécutez d'abord watcher doctor --json et watcher scan --json, puis ajoutez uniquement ce que le classement indique comme manquant ; ne réinitialisez pas une installation fonctionnelle.
- Initialisation.
watcher inità la racine du projet. Idempotent, jamais de questions ; écrit.watcher/config.json,.watcher/.env(0600),.watcher/data/, ignore git des deux derniers, choisit un port libre à partir de 7717, imprime un premier résumé du docteur. - Analyse.
watcher scan --json→{signals, suggestedCommands}. Sur un petit échantillon étiqueté manuellement, son prototype a trouvé 15 des 19 points HTTP/TLS mais seulement 2 des 10 points de silence (watcher skills discover) : traitez ses commandes comme des candidats, puis effectuez le passage prioritaire sur le silence ci-dessous en lisant le code. - Choisissez selon le classement (section suivante). Une source par point réel ; n'inventez jamais de source pour paraître vert.
- Ajout. Pour chaque source choisie :
watcher add <type> --id <id> … --found-at <fichier:ligne> --read "<ce qu'elle prouve>". Les options--found-at/--readsont la provenance etwatcher doctorémet un avertissement sans elles.--dry-runprévisualise. Ensuite, un canal :watcher add channel <type> --id <id> …(voirwatcher skills channels). Si aucune information d'identification n'est disponible — une machine sans tête, aucun compte fournisseur, un utilisateur qui n'a pas choisi de système de radiomessagerie — ajoutez la solution de repli sans information d'identification,watcher add channel file --id local: il écrit une ligne JSON par notification sous.watcher/data/et est un canal réel et testable, pas un simple substitut.watcher add … --replaceréécrit un id existant ;watcher rm <id>en supprime un. - Boucle du docteur.
watcher doctor --json; siok:false, corrigez le premierfailvia sonnextet réexécutez. Sichannel.missingprévient et que l'utilisateur souhaite qu'un téléphone sonne, effectuez le canal de l'étape 8 maintenant et revenez. La sortie 0 est un succès, 1 un échec, 64 une erreur d'utilisation. - Exécution.
watcher run --detach(ouwatcher service installpour qu'il survive au redémarrage). Ensuite,watcher doctor --live --jsonpour lire le serveur en cours d'exécution. - Preuve.
watcher doctor --live --prove --jsonjusqu'à ce qu'il retourne{"ok": true, "live": true}.--provedéplace la lecture de chaque source au-delà de son seuil et échoue sauf si la règle bascule effectivement (source.assertion-not-red; une assertion d'analyse http vide échoue avecsource.assertion-vacuous) : la réponse d'une analyse http est modifiée, un battement de cœur est évalué après une exécution manquée plus son délai de grâce, une lecture d'hôte est déplacée au-delà de ses seuils de disque/mémoire/charge, une connexion TCP échoue, une expiration tombe danspageDays. Un type dont l'alerte est ce que son expéditeur rapporte (grafana, vmalert, sentry, netdata, feed, webhook) est un saut nommésource.prove-unsupported, jamais un échec. Si le projet n'a pas de serveur et pas de tâche planifiée, ajoutezwatcher add host --id host— la machine elle-même, lue localement sans rien installer — et prouvez-la. Seul un projet sans serveur, sans tâche planifiée et sans hôte à surveiller exécutewatcher doctor --no-runtime-surface --json→{"ok": true, "live": false, "reason": "no-runtime-surface"}, rapporté simplement ; une source configurée l'emporte toujours sur--no-runtime-surface(le rapport prévient alorsdoctor.no-runtime-surface-ignored). N'appelez pas une installation non éprouvée comme terminée. - Page. Ajoutez un canal et exécutez
watcher test-alert; confirmez qu'il est arrivé sur l'appareil qui compte. Une information d'identification manquante est un saut nommé, jamais un succès. - Hébergement (optionnel). L'échelle est local → service → Docker/VPS → Cloudflare Tunnel (par défaut pour "héberger avec ma clé Cloudflare") → Conteneurs bêta.
watcher skills hosting,watcher skills cloudflare. - Installer la compétence pour la prochaine fois.
watcher skills install --target all --dir .l'écrit dans le projet. Dans Claude Code, exécutez/reload-skillsensuite — un répertoire de compétences de niveau supérieur créé en milieu de session n'est pas détecté autrement.
Quand quelque chose casse
Un incident est une affirmation avec des preuves, pas une notification. La boucle, en entier, est watcher skills fix :
watcher status --briefpour une ligne, ouwatcher incidents --output jsonpour les clés (MCP :watch_state, puislist_incidents).get_fix_context { clé }(CLI :watcher incident <clé> --fix-context) : l'incident, la configuration de la source et de la cible avec les informations d'identification en tant que noms de variables d'environnement, les assertions de la règle et celle qui a échoué, où le point de terminaison a été trouvé, la dernière bonne observation à côté de la dernière mauvaise observation, la commande exacte qui réexécute la vérification, etnext.- Reproduisez-le à partir de cette commande. Un seuil n'est pas une cause.
- Corrigez la cause, redéployez ou redémarrez pour que la correction soit en ligne.
verify_fix { clé, by }(CLI :watcher recheck <clé> --wait) : il revérifie, attend la réponse fraîche de la source, et enregistre la confirmation lorsque chaque alerte est résolue — ou indique quelle assertion échoue encore, afin que la correction puisse être réparée. Ne marquez jamais un incident comme résolu avant qu'une nouvelle vérification soit verte ;parkest pour une correction qui est fusionnée mais pas encore en ligne,confirm_resolutionpour une que la source a déjà fermée.commentce que vous avez trouvé en cours de route. Une correction silencieuse ne laisse rien à la personne suivante.
Classement : quoi surveiller, dans l'ordre
- La route de préparation la plus profonde du processus de production, affirmant un champ qui change lorsqu'une dépendance est en panne. Jamais un
{"ok": true}/{"status": "ok"}codé en dur — c'est de la vivacité, et cela ne peut pas passer au rouge pour la défaillance qui compte. - Une sonde de préparation que la plateforme déclare déjà :
/readyz,/health/ready, unehealthcheckde compose, unreadinessProbeKubernetes, un chemin de santé fly/railway/render. Miroir de l'extérieur avec le même chemin et le même port. - Pas de serveur → un battement de cœur par tâche planifiée. Le silence est le signal.
- Pas de serveur et pas de tâche planifiée →
watcher add host --id host(charge, mémoire, espace libre, éventuellement un fichier pid ; rien installé) et prouvez-le. Seulement pas de serveur, pas de tâche planifiée et pas d'hôte à surveiller →watcher doctor --no-runtime-surface --json, rapportezNO_RUNTIME_SURFACE, arrêtez. Une source configurée l'emporte toujours sur--no-runtime-surface. N'inventez jamais de source. - Ensuite, les systèmes qui existent déjà — Sentry, Grafana, Netdata, un expéditeur entrant — liés à des informations d'identification. Une information d'identification manquante est un saut nommé avec un code et un
next, jamais un succès silencieux.
Silence en premier (l'analyse les manque)
Lisez le code pour ces six classes ; chacune devient un watcher add heartbeat ou un watcher add webhook --stale-after :
- Plannings générés à l'installation — heredocs dans
install.sh/setup.*qui écrivent un plist, une unité ou une crontab,launchctl load,systemctl enable, écriturescrontab. - launchd/systemd/cron créés à l'exécution — modèles
.plist,OnCalendar=,StartInterval,KeepAlive,node-cron,schedule(,setIntervalautour d'une tâche, celery beat. Un battement de cœur par tâche (--every/--schedule+--grace) ; N tâches signifie N sources. - Travailleurs de files d'attente de type pull —
worker,queue,bullmq,sqs,claim,lease,dequeue. L'échec est la profondeur de la file d'attente ou l'absence de progression, pas un port : envoyez un battement de cœur sur le chemin de réussite, ou poussez une entréechecks.listavecstate: failing. - Obsolescence dans la propre configuration du produit —
staleAfterSec,presenceTtlSec,maxAge,ttl,refreshInterval,lastRunAt. Appliquez la même fenêtre :watcher add webhook --id <expéditeur> --token-env <ENV> --stale-after-sec <sec>. - Accessibilité en écriture du répertoire d'état —
mkdir,state/,data/, sqlite, fichiers de verrouillage. Envoyez seulement après une écriture réussie ; un simpletest -wn'est pas une source. - Points de terminaison de dépendance stockés comme constantes de code —
process.env.X ?? "https://…", littéraux host:port, bases gRPC/ClickHouse/LLM.watcher add http-probe(GET HTTPS) ouwatcher add tcp-probe --host --port, avec--found-atla constante.
Placez le ping sur le chemin de réussite de la tâche — POST /ingest/heartbeat/<id>, avec /fail pour une exécution échouée et /<exit-code> pour un code spécifique. watcher add heartbeat génère le jeton dans .watcher/.env (0600) lorsque la variable nommée n'a pas encore de valeur, ou écrit le --secret-value que vous passez, et imprime les lignes exactes ($NIGHTLY_TOKEN ci-dessous est le nom qu'il choisit pour --id nightly ; un --token-env que vous passez est la variable qu'il imprime à la place) :
set -a; . .watcher/.env
curl -fsS -m 10 "${WATCHER_URL:-http://127.0.0.1:7717}/ingest/heartbeat/<id>?token=$NIGHTLY_TOKEN" # après une exécution réussie
curl -fsS -m 10 "${WATCHER_URL:-http://127.0.0.1:7717}/ingest/heartbeat/<id>/fail?token=$NIGHTLY_TOKEN" # après une exécution échouée
curl -fsS -m 10 "${WATCHER_URL:-http://127.0.0.1:7717}/ingest/heartbeat/<id>/<exit-code>?token=$NIGHTLY_TOKEN" # avec le code de sortie de la tâche
Un collecteur qui n'est pas une seule tâche pousse sa liste entière à la place : POST /ingest/<source> avec {"checks":{"list":[{"id":"…","service":"…","state":"ok","lastRunAt":"…"}]}} — la forme complète et les états se trouvent dans watcher skills sources.
Si une route de santé ne renvoie qu'un littéral, trouvez-en une plus profonde ou ajoutez-en une : GET /readyz → 200 {"db":{"ok":true}} lorsque la dépendance répond, 503 {"db":{"ok":false}} lorsqu'elle ne répond pas. L'édition du projet de l'utilisateur est autorisée — vous êtes l'agent qui écrit le fichier. Affirmez ensuite sur le champ changeant, jamais sur {"ok":true}.
Règles
- Ne pointez jamais une source vers le propre
/healthzdu Watcher —source.self-probele rejette. - Une source doit affirmer quelque chose qui peut basculer. Un simple 200 n'est que de la vivacité (
source.bare-200) ;watcher doctor --live --proveest la porte d'entrée,--found-atest un avertissement (source.untraced). - Les secrets sont des noms de variables d'environnement dans la configuration et des valeurs uniquement dans
.watcher/.env. Ne lisez jamais les valeurs.envpendant l'analyse, ne validez jamais.watcher/.envou.watcher/data/. - Un seul canal fonctionnel bat cinq canaux configurés. Prouvez-le avec
watcher test-alert. Aucune information d'identification du tout ?watcher add channel file --id localet prouvez-le : le fichier est un canal réel, et une information d'identification manquante est un saut nommé, jamais un succès. - Rapportez ce que vous avez prouvé — sources ajoutées, sortie de commande, et chaque saut nommé. Si l'agent ne peut pas terminer une étape (information d'identification manquante, pas de zone), dites lequel et pourquoi en une ligne.
Plus de détails, lorsqu'une étape en a besoin : watcher skills discover (catalogue complet des signaux et la liste de contrôle des silences), watcher skills sources (chaque type, options, exemples), watcher skills channels, watcher skills hosting, watcher skills cloudflare, watcher skills netdata, watcher skills operate (outils MCP et triage des incidents).