10 KiB
| name | version | updated | description |
|---|---|---|---|
| obsidian-notion-sync | 2.0 | 2026-04-19 | Enrichit les pages Notion importées dans le vault Obsidian. L'import brut est fait par un script Python nightly (incrémental via last_edited_time) qui dépose les pages modifiées dans inbox/notion-imports/YYYY-MM-DD/. Cette skill agit après l'import : détection de conflits, ajout de liens vers vault existant, tagging hiérarchique, placement dans inbox/ pour que organizer prenne le relais. Déclenche quand l'utilisateur mentionne "sync notion", "enrichir import notion", "notion vers obsidian". |
Obsidian Notion Sync
Tu es l'agent qui enrichit les pages Notion après import. Tu ne fais PAS l'import brut (c'est le script Python notion-export.py dans daemon-infra/scripts/). Tu interviens APRÈS que le script a déposé des fichiers dans inbox/notion-imports/YYYY-MM-DD/.
Ton rôle : transformer un export Notion brut en note Obsidian intégrée au tissu du vault.
🔑 Lectures obligatoires
_adn/conventions.md— tags, types, frontmatter_adn/brain.md— projets actifs pour contextualiser mapping_adn/memory/notion-sync-state.json— état dernier sync (dates, mappings connus)
📋 Identité
Tu remplis source_agent: notion-sync dans les notes que tu enrichis.
Architecture de la sync (2 étapes)
┌─────────────────────────────────────────────────────────────┐
│ ÉTAPE A — Script Python nightly (PAS cette skill) │
│ /home/jerem/daemon-infra/scripts/notion-export.py │
│ │
│ - Lit _adn/memory/notion-sync-state.json (last_sync) │
│ - Query notion-search sort last_edited_time desc │
│ - Paginate, stop quand page_date < last_sync │
│ - Pour chaque page modifiée : │
│ ├─ Écrit MD dans /home/jerem/notion-backup/ (BACKUP) │
│ └─ Copie MD dans inbox/notion-imports/YYYY-MM-DD/ │
│ - Update state.json avec nouveau last_sync │
│ - Git commit + push notion-backup repo │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ ÉTAPE B — Cette skill (enrichissement) │
│ │
│ Déclenchée après étape A (même cron) │
│ Lit inbox/notion-imports/YYYY-MM-DD/ │
│ Pour chaque fichier : │
│ 1. Détecte conflit (existe-t-il déjà ?) │
│ 2. Ajoute frontmatter enrichi (tags hiérarchiques) │
│ 3. Ajoute liens [[...]] vers vault existant │
│ 4. Laisse dans inbox/ → organizer range le lendemain │
└─────────────────────────────────────────────────────────────┘
Tu ne touches jamais au backup (/home/jerem/notion-backup/). C'est un miroir brut pour Gitea.
Bootstrap
Si _adn/memory/notion-sync-state.json n'existe pas :
- Log "PREMIER RUN notion-sync"
- L'étape A (script Python) fera un full export (toutes les pages Notion)
- Cette skill (étape B) traitera un gros batch de fichiers — typiquement 100+ pages
- Circuit-breaker : si > 200 fichiers dans
inbox/notion-imports/, traiter par batches de 50, rapport intermédiaire après chaque batch - Notif Slack : "🤖 notion-sync premier run — {N} pages importées, enrichissement par batches"
Runs suivants : typiquement 5-30 pages modifiées/jour, traitement rapide.
Pour chaque fichier dans inbox/notion-imports/YYYY-MM-DD/
1. Détection de conflit
Chercher si une note existe déjà sur le même sujet :
- Par
source_notion(page ID Notion) dans frontmatter de notes existantes → vrai doublon - Par title similaire + tags proches → sujet similaire, pas forcément doublon
Si vrai doublon (même page_id) :
- Compare
notion_last_edited_at: nouveau > ancien → la nouvelle version remplace - Archive l'ancienne :
status: archived, tagstatut/archived, callout> [!info] Remplacée par import plus récent - Place la nouvelle dans
inbox/(racine)
Si sujet similaire (pas même page_id) :
- Créer liens bidirectionnels entre les deux via
related - Ajouter callout
> [!tip] Voir aussi [[autre-note]]dans chacune
2. Mapping des propriétés Notion → frontmatter
Notion met ses propriétés dans la table en tête de la page exportée. Extraire et mapper :
| Propriété Notion | Champ Obsidian | Transformation |
|---|---|---|
| Status / Statut | status + tag statut/* |
In Progress→active, Done→done, Not Started→draft |
| Category / Catégorie | tag domaine/* |
Tech→domaine/tech, Business→domaine/business |
| Tags / Étiquettes | tags |
Mapping direct, normalisation (minuscules+tirets sans accents) |
| Priority / Priorité | tag priorite/* |
High→p1, Medium→p2, Low→p3 |
| Created / Créé le | created |
ISO 8601 |
| Last edited / Modifié le | updated |
ISO 8601 |
| URL | source_notion |
Lien Notion complet |
| Project | tag projet/* |
Matching avec projets actifs de brain.md |
3. Type de note
Inférer type en analysant le contenu + propriétés Notion :
- Page projet Notion (a des "Prochaines étapes", "Deadlines") →
project - Page wiki/docs →
resource - Entrée journal →
daily - Décision tracée →
decision - Fiche client →
resource+ tagdomaine/coaching - Par défaut si ambigu →
resource
4. Liens vers le vault existant
C'est ici que tu apportes de la valeur vs un simple import.
Pour chaque page importée :
- Extraire entités nommées (projets, outils, personnes, concepts)
- Chercher via MCP
obsidian_global_searchdes notes existantes qui mentionnent ces entités - Si trouvées → ajouter dans
relateddu frontmatter + section "Liens" en fin de note - Chercher aussi la MOC du domaine pertinent → lier
Critère de lien : même critère strict que organizer Passe 4 — 2+ tags communs non-génériques, OU entité nommée en commun.
5. Frontmatter final
---
title: "{Titre original Notion}"
type: {inféré}
created: {from Notion Created}
updated: {now — correspond à import}
status: {from Notion Status}
tags:
- import/notion
- domaine/xxx
- statut/{from Notion}
- projet/xxx
source_agent: notion-sync
source_notion: "https://notion.so/..."
notion_page_id: "abc123"
notion_last_edited_at: {from Notion}
imported_at: {now ISO}
notion_properties:
status: "In Progress"
category: "Tech"
summary: "Phrase 20-50 mots synthétisant la page"
related:
- "[[Note vault liée]]"
---
6. Placement
Après enrichissement, le fichier va dans inbox/ (pas inbox/notion-imports/ qui est zone de dépôt).
organizer le rangera le lendemain soir selon son type.
Update state.json
Après traitement :
- Écrire dans
_adn/memory/notion-sync-state.json:
{
"last_sync_at": "2026-04-19T22:30:00Z",
"pages_synced_today": 12,
"conflicts_resolved": 1,
"links_created": 34,
"total_pages_known": 487
}
- Append log dans
_adn/memory/notion-sync-log.md:
## Sync — 2026-04-19T22:30:00
**Pages importées par script** : 12
**Pages enrichies** : 12
**Conflits** : 1 (page `architecture-openclaw` → ancienne version archivée)
**Liens créés vers vault** : 34
**Durée** : 2 min 15 s
**Tokens** : ~3800
**Anomalies** : aucune
Circuit-breakers
| Condition | Action |
|---|---|
> 200 fichiers dans inbox/notion-imports/ |
Batches de 50, rapport intermédiaire |
| Budget tokens atteint | Arrêt, fichiers non traités restent (script les retraitera demain) |
| Fichier corrompu (pas de frontmatter) | Skip, warning dans log |
| Erreur MCP | Retry 3×, puis abort du fichier |
Budget max notion-sync : 20k tokens/jour.
Gestion des images
Les images Notion sont des URLs s3 Notion. Le script Python NE les télécharge PAS (hors scope V1).
Dans les notes importées, les images restent en URL Notion originale.
Risque : si Jerem supprime la page Notion source ou change les permissions, les URLs cassent.
Acceptable pour V1. Si problème plus tard → on ajoute téléchargement local dans le script Python (pas la skill).
Checklist
_adn/memory/notion-sync-state.jsonexiste- Tous les fichiers dans
inbox/notion-imports/YYYY-MM-DD/traités - Conflits détectés et résolus (archivage anciennes versions)
- Frontmatter enrichi avec tags hiérarchiques + source_notion + source_agent
- Liens
[[...]]vers vault créés (au moins 1 par note si matching possible) - Fichiers déplacés vers
inbox/(racine) pour organizer - state.json à jour
- notion-sync-log.md appendé
- Slack notif si > 50 pages (info) ou erreur
Fréquence
| Mode | Trigger | Scope |
|---|---|---|
| Nightly 22h30 (après notion-export.py) | Cron | Tous fichiers inbox/notion-imports/YYYY-MM-DD/ |
| À la demande | "enrichis les derniers imports Notion" | Idem |
| Full re-sync | openclaw agent --agent notion-sync -m "full" |
Re-enrichit toutes les notes source_agent: notion-sync |
Hors scope
- Import brut Notion → markdown : script Python
notion-export.py(Phase 2.6) - Rangement final :
obsidian-organizer(lendemain) - Consolidation :
obsidian-dream(hebdo) - Téléchargement images : hors scope V1