15 KiB
MEMORY.md — Nox 🌑
📋 Règle de mémorisation
| Critère | MEMORY.md | Qdrant | Les deux |
|---|---|---|---|
| Config infra (URL, token, IDs) | ✅ | ❌ | — |
| Préférences & comportements | ✅ | ❌ | — |
| Leçon courte / gotcha technique | ✅ | ✅ | ← les deux |
| Procédure détaillée / code | ❌ | ✅ | — |
| Événement épisodique (ce qu'on a fait) | ❌ | ✅ | — |
| Fait important ET recherchable | ✅ | ✅ | ← les deux |
Résumé :
- MEMORY.md = ce que je dois savoir DÈS le démarrage. Court, dense, stable.
- Qdrant = ce que je dois pouvoir RETROUVER par recherche. Détails, procédures, contexte.
- Les deux = les leçons critiques, les gotchas techniques, tout ce qui est à la fois essentiel ET recharchable.
Toujours ajouter dans Qdrant après toute session de travail significative. Ne pas surcharger MEMORY.md — si c'est long ou procédural, Qdrant suffit.
Christophe
- Habite Montlieu-La-Garde, Charente-Maritime (17), axe Bordeaux-Angoulême N10
- Fuseau horaire : Europe/Paris
- Langue : français
Home Assistant
- URL : http://192.168.1.40:8123
- Lumières :
light.dimmer_2→ Entréelight.bar→ Barlight.bibliotheque→ Bibliothèquelight.dimmer_salon→ Salonlight.nano_dimmer→ Mezzanine (Nano Dimmer Z-Wave)light.mi_light_wifi_ibox1→ Mi-Light WiFi iBox1 (la "lumière wifi")
- Caméras :
camera.onvif_ptz→ Caméra Extérieur (double vue, couleur, parking/cour)camera.fi9821ep→ Caméra Salon (Foscam, intérieur)camera.camera_ndeg7→ Caméra n°7 (intérieur, sous-sol/atelier)camera.camera_jarnac_rdc_7→ Caméra Jarnac RDC 7 (intérieur)camera.foscam→ Foscam (intérieur, entrée/pièce de vie)camera.klipper_webcam→ Ender 3 Webcam (imprimante 3D)camera.predator_predator→ Predatorcamera.nono_none→ Nono
- Media Players :
media_player.shield→ SHIELD CUISINEmedia_player.android_tv_cuisine→ Android TV Cuisinemedia_player.shield_salon→ SHIELD SALONmedia_player.android_tv_salon→ Android TV Salonmedia_player.denon_avr_x3400h→ Denon AVR-X3400H
Proxmox
- URL : https://192.168.1.250:8006
- Token : variable d'env
PVE_TOKEN(formatroot@pam!openclaw=<uuid>) — déjà dans .env + docker-compose override - Accès API :
curl -sk -H "Authorization: PVEAPIToken=$PVE_TOKEN" "$PVE_URL/api2/json/nodes" - Parser JSON avec Node.js (pas jq — permission denied dans le conteneur)
- Nodes : mini-pc, ts-651, pve, z820
Proxmox Backup Server (PBS)
- URL : https://192.168.1.91:8007
- Token : variables d'env
PBS_TOKEN_ID+PBS_TOKEN_SECRET— déjà dans .env + docker-compose override - Accès API :
curl -sk -H "Authorization: PBSAPIToken=$PBS_TOKEN_ID:$PBS_TOKEN_SECRET" "$PBS_URL/api2/json/status/datastore-usage" - Datastore :
backups_on_ts651(1.26 TB total)
Outils & Préférences
- Génération d'images : utiliser fal.ai (FAL_KEY), PAS OpenAI
fal-ai/flux/schnell— génération rapide, bon pour photos/artfal-ai/nano-banana-pro— Gemini 3 Pro Image, bon pour affiches/texte/édition d'images
- Browser OpenClaw (outil
browser) : ✅ OPÉRATIONNEL — headless Chromium Playwright, profilopenclaw- Config :
attachOnly: false,executablePath: /home/node/.openclaw/workspace/chrome-wrapper.sh - Le
chrome-wrapper.shnettoie les lock files résiduels AVANT de lancer Chrome (fix permanent pour le bug SingletonLock après redémarrage) - Chrome réel :
/home/node/.cache/ms-playwright/chromium-1208/chrome-linux64/chrome(appelé par le wrapper) - CDP port : 18800, user-data-dir :
/home/node/.openclaw/browser/openclaw/user-data - Utiliser pour : snapshots ARIA, interactions UI, screenshots, sessions persistantes
- Se lance automatiquement au premier appel
browser action=start profile=openclaw - Toujours sauvegarder les fichiers dans le workspace —
/tmpest bloqué pour l'envoi Telegram - ⚠️ Si le browser ne répond plus : vérifier que Chrome tourne (
curl -sf http://127.0.0.1:18800/json/version) — relancer viabash /home/node/.openclaw/workspace/start-chrome-cdp.sh
- Config :
- Playwright direct (Node.js) : pour interception réseau, scripts sur mesure, scraping avancé
- Installé dans
/home/node/.openclaw/workspace/node_modules/playwright executablePath→/home/node/.cache/ms-playwright/chromium-1208/chrome-linux64/chrome- Les erreurs
dbusen conteneur sont normales et sans impact
- Installé dans
- TTS : Edge, voix fr-FR-VivienneMultilingualNeural — TOUJOURS parler en français, même si la conversation contient de l'anglais
- Transcription audio : Groq Whisper
Anytype
- Instance self-hosted : http://192.168.1.150:31009
- Espace principal : OpenClaw (id:
bafyreigt3wmpnm2qduzijfubftw5ixrhqfrjrc2yi6hq2e4cpw6yer7hqq.25d1im923toai) - Skill custom dans
/home/node/.openclaw/workspace/skills/anytype/ - Utiliser cet espace pour tout ce qui concerne Christophe et moi
- Images : ✅ ÇA MARCHE ! Anytype télécharge et internalise les images depuis une URL externe
- Méthode : inclure
dans lebodymarkdown lors d'un POST (création d'objet) - Anytype récupère l'image, lui donne un ID interne (
bafyrei...) et la sert viahttp://127.0.0.1:47800/image/<id> - L'image doit être accessible depuis le serveur Anytype (même réseau local)
- PATCH : utiliser le champ
"markdown"(PAS"body") pour modifier le contenu existant ! - Le format icon doit être
{"format":"emoji","name":"🧪"}et non une string simple - POST (création) : utiliser
"body"pour le contenu - PATCH (modification) : utiliser
"markdown"pour le contenu
- Méthode : inclure
CopyParty (stockage fichiers)
- URL : http://192.168.1.150:3923
- Upload simple via
curl -X PUT "http://192.168.1.150:3923/<chemin>" --data-binary @fichier - Pas d'authentification requise
- Dossier
/anytype/créé pour les fichiers liés à Anytype - Utilisable pour héberger images, schémas, etc. avec lien direct
- Utile pour Penpot : uploader une image sur CopyParty → l'injecter dans Penpot via
upload_file_media_from_url
Penpot MCP — Workflow & Gotchas
Stack
- Penpot UI : http://192.168.1.150:9001
- MCP HTTP endpoint : http://192.168.1.150:9002/mcp (health: /health)
- MCP = zcube/penpot-mcp-server, image node:22-alpine + npm @zcubekr/penpot-mcp-server
- Token Penpot déjà configuré dans la stack Portainer (stack id=90)
⚠️ Règles critiques MCP zcube
1. Tous les paramètres sont en camelCase (PAS snake_case) :
projectId,fileId,pageId,parentIdfillColor,fontSize,fontWeightisShared,gradientType,borderRadius,cornerRadius→r1/r2/r3/r4
2. Session unique — toujours redémarrer le container avant :
- Le serveur n'autorise QU'UNE session à la fois
initializeéchoue avec "already initialized" si session existante- Solution : inclure le restart Portainer dans le script (container
penpot-penpot-mcp-1)
3. Récupérer IDs depuis get_profile (plus fiable que list_teams) :
profile.defaultProjectId→ projet par défaut (Drafts)profile.defaultTeamId→ team
4. export_shape NON IMPLÉMENTÉ dans zcube — ne pas l'appeler
5. list_teams retourne du texte ("Found 1 teams"), pas du JSON
6. create_text — paramètres corrects :
text(PAScontent) → le contenu du textetextAlign(PASalign) → "left", "center", "right", "justify"fontWeight→ string "100"–"900" ou "bold"fillColor→ couleur HEX- ⚠️
parentIdNON SUPPORTÉ pour create_text — les textes vont toujours au root frame - Width/height auto-calculés (text.length × fontSize × 0.6) — ne pas les spécifier
7. Workflow création fichier :
get_profile → defaultProjectId
create_file { projectId, name } → fileId
list_pages { fileId } → pageId (array[0].id)
create_frame { fileId, pageId, name, x, y, width, height, fillColor } → frameId
create_rectangle { fileId, pageId, parentId: frameId, ... } ← parentId OK pour rect
create_text { fileId, pageId, text, x, y, textAlign, ... } ← PAS de parentId
8. Coordonnées : absolues sur la page. Les textes se placent dans le root frame automatiquement. Pour un poster : mettre frame à (0,0) et textes aux bonnes coords absolues.
Pour générer une image finale
export_shapenon dispo → utiliser HTML/CSS → Playwright screenshot- Script template :
/home/node/.openclaw/workspace/screenshot-poster.mjs - Playwright :
node_modules/playwright, chrome :/home/node/.cache/ms-playwright/chromium-1208/chrome-linux64/chrome - Sauvegarder dans workspace (pas /tmp) pour envoi Telegram
Pour injecter une image dans Penpot
- Uploader sur CopyParty :
curl -X PUT http://192.168.1.150:3923/anytype/image.png --data-binary @image.png - Puis :
upload_file_media_from_url { fileId, url: "http://192.168.1.150:3923/anytype/image.png" }
Podcasts & Vidéos — Transcription
- Je peux récupérer et transcrire des podcasts/vidéos en ligne
- Méthode :
- Utiliser Playwright pour intercepter les requêtes réseau et trouver l'URL du fichier audio (.mp3)
- Télécharger le MP3 avec
curl -sL -A "Mozilla/5.0..." -H "Referer: <site>" <url> -o fichier.mp3 - Transcrire avec Groq Whisper :
curl -X POST https://api.groq.com/openai/v1/audio/transcriptions -H "Authorization: Bearer $GROQ_API_KEY" -F "file=@fichier.mp3" -F "model=whisper-large-v3-turbo" -F "language=fr" -F "response_format=text"
- Testé avec succès sur BFM Business / Simplecast (podcasts hébergés sur simplecastaudio.com)
- Sauvegarder les fichiers dans le workspace, pas dans /tmp
- YouTube : utiliser yt-dlp (binaire dans
/home/node/.openclaw/workspace/yt-dlp)- Transcript via API YouTube (sous-titres auto) :
yt-dlp --write-auto-sub --skip-download --sub-lang fr -o workspace/transcript <url> - Audio pour Whisper :
yt-dlp -x --audio-format mp3 -o workspace/audio.mp3 <url>
- Transcript via API YouTube (sous-titres auto) :
Mémoire Vectorielle (Qdrant)
- Collection :
nox-memorysur Qdrant (http://192.168.1.150:6333) - Stack Portainer :
qdrant(anciennementkilocode-qdrant, renommé 2026-02-22) - Script :
/home/node/.openclaw/workspace/nox-memory.js - Modèle :
text-embedding-3-small(OpenAI, 1536 dims, Cosine) - Accès :
node fetchnatif (Node 22) — curl bloqué par sandbox OpenClaw, mais node fetch fonctionne ✅ - Réseau Docker : le stack doit avoir un réseau
bridgeen plus deswag_lanpour être accessible depuis le LXC - Usage :
node nox-memory.js add "texte" --type fact|semantic|preference|episodic --tags "t1,t2" --importance 1-5 node nox-memory.js search "question naturelle" [--limit 5] [--type fact] node nox-memory.js list [--type fact] [--limit 20] node nox-memory.js stats node nox-memory.js import-md MEMORY.md - MEMORY.md importé (9 chunks, 2026-02-22)
- Utiliser en priorité pour les recherches contextuelles (memory_search reste utile pour le démarrage de session)
- ⚠️ Qdrant charge ~34 collections KiloCode au démarrage → ~30s avant d'être prêt
Home Assistant — Lovelace / Dashboards
Dashboards disponibles
lovelace→ "Aperçu" (dashboard principal, 15+ vues)vue-par-pieces→ "Vue par pièces"mushroom-strategy→ "Mushroom-strategy"map→ Map
Modifier/créer des vues Lovelace via WebSocket API
L'API REST /api/lovelace/config retourne 404 même si HA est en mode storage → utiliser l'API WebSocket à la place.
Méthode (Node.js, WebSocket natif Node 22) :
const ws = new WebSocket(`${HA_URL.replace('http://','ws://')}/api/websocket`);
// Auth
ws.send(JSON.stringify({ type: 'auth', access_token: TOKEN }));
// Lire config
send({ type: 'lovelace/config' }) // → result.views[]
// Sauvegarder config modifiée
send({ type: 'lovelace/config/save', config: modifiedConfig })
// Lister les dashboards
send({ type: 'lovelace/dashboards/list' })
// Pour un dashboard spécifique (url_path)
send({ type: 'lovelace/config', url_path: 'vue-par-pieces' })
Script template : /home/node/.openclaw/workspace/ha_ws_add_lights.mjs
- Lire config → modifier le tableau
views→ sauvegarder - Utiliser le WebSocket natif Node 22 (pas besoin du package
ws) - Timeout de sécurité à 15s
- Le code de sortie 1 (timeout) est normal si
ws.close()ne coupe pas avant le timeout — le succès est dans le log
Astuce : Pour ajouter une vue sans écraser les existantes, lire d'abord la config, push la nouvelle vue, puis sauvegarder le tout.
Portainer
- URL : https://192.168.1.150:9443
- Token : variable d'env
PORTAINER_API_KEY - Endpoint local : id=2 (socket Docker)
- ~38 stacks dont ~25 actives
- Pas de
jqdans le conteneur → utiliser curl + Node.js directement
Proxmox — Inventaire VMs/LXC clés
- VM 138 (
mini-pc) → Home Assistant (192.168.1.40) — pas d'agent QEMU - LXC 145 (
mini-pc) → OpenClaw (ce conteneur) - LXC 139 (
mini-pc) → Frigate (NVR) - VM 109 (
z820) → PBS (Proxmox Backup Server, 192.168.1.91)
Docker — Règles de mise à jour
- Toujours exécuter
docker-backup.jsavant toute mise à jour d'un conteneur Docker- Script :
node /home/node/.openclaw/workspace/docker-backup.js <nom_conteneur> - Exemple :
node docker-backup.js vaultwardenavant de puller une nouvelle image - Services configurés : vaultwarden, vikunja, nocodb, freshrss
- Le cron hebdo a été créé mais désactivé à la demande de Christophe (2026-02-23)
- Réactiver si besoin :
node /app/dist/index.js cron add ...
- Script :
Santé — Christophe
- Profil : Homme, né 12/06/1981 (44 ans), 1m81, ~90 kg, IMC ~27,5
- Appareil tension : Sanitas (poignet, profil 1)
- Suivi tension dans
memory/YYYY-MM-DD.md— tableau SYS/DIA/Pouls - Première mesure : 2026-02-25 12:08 → 145/94 mmHg, pouls 77 bpm (HTA stade 1)
Sites & Flux RSS
- Korben.info : utiliser le flux RSS
https://korben.info/feedpour récupérer les articles (plus propre que scraper la homepage)
Veilles actives
📡 XGS-PON CMTD — Montlieu-la-Garde
- Christophe est sur le réseau CMTD (RIP, géré par Orange) actuellement en GPON → plafond ~1 Gbps
- Migration XGS-PON en cours, prévue fin 2026
- Quand XGS-PON dispo → recommander passage Freebox Ultra grand public (moins cher que FreePro, mêmes features + 8 Gbps sym)
- Vérifier 1x/mois via heartbeat
Leçons apprises
- Toujours prendre un snapshot du LXC 145 (
mini-pc) avant toute modification de config ou installation qui pourrait casser OpenClaw- Commande :
curl -sk -X POST -H "Authorization: PVEAPIToken=$PVE_TOKEN" -H "Content-Type: application/json" -d '{"snapname":"<nom>","description":"<desc>"}' "$PVE_URL/api2/json/nodes/mini-pc/lxc/145/snapshot"
- Commande :
- Toujours vérifier les
friendly_namedans HA pour trouver les entités - Les skills custom sont dans
/home/node/.openclaw/workspace/skills/ - curl est bloqué dans le sandbox OpenClaw pour certaines destinations réseau, mais node fetch (Node 22) fonctionne — utiliser node pour les requêtes HTTP internes quand curl échoue