Cadeno
Enregistreur de flux navigateur · Chrome MV3

Tu l'as fait une fois.
Pourquoi tu le fais encore ?

Skill Recorder est une extension Chrome qui te regarde accomplir une tâche dans le navigateur une fois — puis écrit un SKILL.md, une spécification en markdown pur que Claude Code (ou n'importe quel agent sur la CLI browse) rejoue sans sélecteurs, sans glue code, sans surveillance.

v0.4.14.5 MB bundleMV3 service worker21 fixtures12 locales
~/Downloads/recordings/2026-03-create-po.jsonrecording
RAW EVENTS23 captured · 4.6s elapsed
01navigate "/orders/new" // 304 → 200
02click "button.tabs__new" // data-tab=create
03focus "#sku"
04type "SKU-1029" // 8 keystrokes, 1.2s
05blur "#sku"
06type "50" // into #qty
07click "button.submit" ⚠ inside dynamic list
… 16 more (scroll · focus · mousemove · blur · resize)
distilled in 30s ↓
SKILL.md4 steps · 2 inputs · 1 precondition
01# create-purchase-order
02
03// precondition: signed in to supplier portal
04
05## inputs
06- {{sku}} // auto-detected · 8 chars · alphanumeric
07- {{quantity}} // auto-detected · int · 1–999
08
09## steps
101. navigate "/orders/new"
112. fill "#sku" with {{sku}}
123. fill "#qty" with {{quantity}}
134. click submit row matching {{sku}}
↑ un flux de bon de commande de cinq minutes,
enregistré une fois et rejoué à l'infini.
Anatomie

Trois étapes, à un clic d'écart.

Ce que nous livrons, c'est une petite extension Chrome MV3 et un pipeline de distillation de 4 Ko. L'enregistreur s'accroche à chrome.debugger pour la fidélité au niveau DOM ; la distillation tourne entièrement dans le service worker ; la rejouabilité lit le SKILL.md résultant via la CLI browse. Aucun serveur. Aucun glue code.

i.

Capturer

Panneau latéral
Skill RecorderREC
00:01click nav.Orders
00:02click btn.New
00:04focus #sku
00:05type "SKU-1029"
00:06blur #sku
00:08type "50" → #qty
00:09click btn.Submit

Un port par frame dans le content script transmet chaque évènement DOM au service worker. Le Shadow DOM et les iframes de même origine sont traversés de manière transparente.

  • Résolveur de sélecteurs à 6 niveaux (testid → id → aria → text → css → xpath)
  • tabPorts: Map<tabId, Map<frameId, Port>>
  • Tampon d'entrée conscient de l'IME · paste · drag
23 évènements →
ii.

Distiller

Service worker · 30 s
dedupe consecutive clicks23 → 16
fold keystrokes into type()16 → 11
detect inputs as {{params}}conf 0.94
mark auth boundary+1 precondition
parameterize URL segments2 swapped
flag dynamic-list clicks1 ⚠ note

Six petites passes transforment un journal d'évènements bruyant en spécification déterministe. L'auto-paramétrage ne se déclenche qu'au-dessus de 0,7 de confiance ; en dessous, l'enregistreur demande au lieu de deviner.

  • paramConfidence(step) — échelle heuristique
  • détection d'auth-boundary — token opaque + cookies
  • UUID · ID numérique · email · date ISO · monnaie
SKILL.md →
iii.

Rejouer

browse CLI
~/work $ claude
> create POs for these 50 rows
Reading ~/.claude/skills/create-purchase-order/SKILL.md Loaded 4 steps · 2 params · 1 precondition ▸ resolving precondition: signed in to supplier portal cookie present, expires 2026-08-04 ▸ running batch [50 rows] 50/50 in 3m 11s 0 retries, 0 manual rescues

La CLI browse lit SKILL.md comme du markdown pur — pas de schéma, pas de runtime, pas d'échappatoire. Chaque étape est auditable.

  • réexécutions idempotentes · pause + reprise d'auth
  • logs structurés ↦ historique JSONL
  • fonctionne avec Claude Code, Cline, shell plat
Spécification

Que survit à un enregistrement ? Treize cas durs, de bout en bout.

Le navigateur est plein de pièges pour les enregistreurs — classes hashées, modales paresseuses, Shadow DOM, flux multi-onglets, composition IME, glisser-déposer. Chaque ligne ci-dessous est une fixture réelle du playground ; clique sur n'importe laquelle pour enregistrer toi-même contre.

point vert = livré · bleu = automatique
CatégorieTechniqueCe qu'on en faitFixture
Sélecteurs
Rotation des hash de classe & ID

Les classes façon Tailwind comme btn__primary--ab3f9c tournent à chaque déploiement ; le résolveur traverse 6 niveaux (testid → id → aria → text → css → xpath), donc un bouton re-hashé touche quand même.

A2
Sélecteurs
Lignes frères identiques

Six lignes avec des boutons "Pick" littéralement identiques — seule la position distingue. On ancre chaque clic par fingerprintIndex, donc la bonne ligne est cliquée, même après réordonnancement.

A3
Sélecteurs
Identifiants stables aux locales

"Continue" / "继续" / "Weiter" mappent tous au même data-i18n-key="action.continue". L'enregistreur préfère les attributs indépendants de la locale, donc un skill enregistré en anglais rejoue en chinois.

A4
Async
Transitions de route SPA

Les transitions pushState et hashchange sont suivies sans rechargement ; la rejouabilité attend le montage du nouveau contenu plutôt que de sonder un conteneur vide.

B1
Async
Modales montées tardivement

Le bouton Confirm n'existe pas quand le déclencheur est cliqué. elementVisible interroge jusqu'à ce que la cible apparaisse avant de déclencher l'étape suivante — sans timeouts fragiles.

B3
Surfaces
iframes même origine

all_frames: true injecte par frame ; les actions sont étiquetées avec la frameId d'origine, puis ré-résolues par URL entre re-rendus, donc une frameId obsolète ne bloque jamais la rejouabilité.

C1
Surfaces
Masquage des champs sensibles

Les entrées password / phone / carte / SSN sont détectées par type + autocomplete + name et remplacées par *** avant d'atteindre le stockage. Les octets ne quittent jamais la page.

C2
Surfaces
Perçage du Shadow DOM

Un type de sélecteur shadow personnalisé encode le chemin en segments { host, inner } ; le résolveur traverse shadowRoot.querySelector à chaque frontière, donc les Web Components sont de première classe.

C3
Surfaces
Passage entre onglets

Quand un flux ouvre un nouvel onglet — aperçu d'impression, OAuth, génération de devis — l'enregistrement suit via chrome.tabs.onCreated. La rejouabilité recrée l'onglet via chrome.tabs.create.

C4
Entrée
Drag & drop natif

Une chaîne dragstart → dragover → drop avec un DataTransfer partagé est fusionnée en une étape drag (source + cible + types observés). Pas de coordonnées de pixels fragiles.

D1
Entrée
Combinaisons de touches

Un "k" seul est du bruit d'entrée texte ; avec metaKey: true c'est un raccourci Cmd-K. L'enregistreur garde le combo, jette le bruit, préserve l'état de modificateur pour la rejouabilité.

D3
Entrée
Blocs contenteditable

change ne se déclenche jamais sur contenteditable. On accroche input + compositionend, debounce de 300 ms, et émet une étape change avec l'innerText final — même forme qu'un champ texte.

D4
Entrée
Combobox ARIA & typeahead

Chaque étape de clic est enrichie de comboboxContext (texte d'option, sélecteur racine) ; si le clic direct échoue en rejouabilité, le repli tape le texte, ArrowDown jusqu'à correspondance aria-activedescendant, puis Enter.

D6

Treize sur seize. Plus quatre fixtures composites — Notion, Linear, Jira, Salesforce — qui enchaînent douze à quinze de ces techniques en un flux cohérent. Voir le playground →

Exemple travaillé

Un rituel navigateur de cinq minutes, distillé en trente secondes.

Carnet de terrainEnregistré 2026-02-19, 16:42 UTCRejoué 50× sans intervention

Chaque lundi matin, une ingénieure ops d'un petit fournisseur ouvre le même portail, clique sur Nouveau bon de commande, colle un SKU depuis un CSV, tape une quantité et clique sur Soumettre. Puis recommence. Et recommence. Deux cents lignes par semaine, chaque semaine, depuis quatorze mois. Un rituel de cinq minutes répété jusqu'à la fin de la feuille.

C'est exactement le type de tâche pour laquelle on pitche un enregistreur — et exactement le type sur laquelle la plupart échouent. Le portail fournisseur tourne ses hash de classe Tailwind à chaque déploiement. Le bouton Soumettre vit dans une ligne de table dynamique qui se re-rend après chaque enregistrement. Le cookie d'auth expire à midi. Les scripts Selenium contre cette page survivent deux semaines en moyenne, puis commencent à échouer en silence.

L'enregistrement

L'ingénieure épingle l'extension à sa barre d'outils, ouvre le portail, clique sur Démarrer l'enregistrement et exécute la tâche exactement une fois. Huit clics, deux valeurs tapées, une soumission. Le panneau latéral affiche un flux en direct des évènements — bruit inclus : scroll, focus, blur, mouvements de souris accidentels sur l'icône d'aide. Vingt-trois évènements capturés en 4,6 secondes.

raw events · 23écoulé 4,6 s
01 navigate "/orders/new" // 304 → 200 02 click "button.tabs__new" // data-tab=create 03 focus "#sku" 04 type "SKU-1029" // 8 keystrokes 05 blur "#sku" 06 focus "#qty" 07 type "50" 08 click "button.submit" inside .row[data-id=r9]16 more (scroll · focus · mousemove · blur · resize)
Le log brut garde tout ; la distillation décide ce qui compte.

La distillation

main.example.p4

before / after23 évènements → 4 étapes
— BEFORE (raw)
type "S" → #sku
type "K" → #sku
type "U" → #sku
type "-" → #sku
type "1" → #sku
type "0" → #sku
type "2" → #sku
type "9" → #sku
+ AFTER (distilled)
fill "#sku" with {{sku}}
+ AUTO-DETECTED
// 8 chars · alphanumeric · prefix SKU-
// confidence 0.94
Huit frappes deviennent un fill paramétré — même forme à chaque rejouabilité.

Le passage de relais

L'ingénieure dépose le markdown obtenu dans ~/.claude/skills/create-purchase-order/SKILL.md et tape une phrase à Claude Code. L'agent trouve le skill par son nom, résout la précondition (le cookie sauvegardé est valide jusqu'à midi), itère sur les cinquante lignes du CSV et rend compte. Trois minutes onze secondes plus tard, le boulot est fait. Personne ne l'a regardé tourner.

claude code · stdout3 m 11 s · 0 réessai
> create purchase orders for the rows in ~/Desktop/feb-orders.csv Reading ~/.claude/skills/create-purchase-order/SKILL.md 4 steps · 2 params · 1 precondition Resolving precondition: signed in to supplier portal cookie present (expires 2026-02-19 12:00 UTC) Running batch (50 rows) 50/50 submitted 0 retries · 0 manual rescues median 3.8s per row · longest 5.1s
Une phrase en entrée, cinquante bons de commande en sortie. L'agent n'a posé aucune question.
Post-scriptum
Le coût d'un rituel de cinq minutes,
amorti sur une année de travail.
4:18min
médiane manuelle
3.8sec
médiane agent
~187hrs/yr
récupéré, juste cette tâche
Tu veux le voir sur des fixtures plus dures ? Essaie le playground →
Récupère l'enregistreur

main.cta.title

Gratuit pendant la bêta ouverte. Aucun compte, aucun upload, aucune télémétrie. Le bundle complet fait 4,5 Mo ; les enregistrements vivent sur ta machine jusqu'à ce que tu choisisses de les exporter.

SKILL.md — un contrat en markdown pur entre humains et agents.v0.4.1 · Updated 2026-02-19