Grabar y Reproducir (navegador + escritorio)
Grabar y Reproducir permite que un agente aprenda un flujo de trabajo demostrado por el usuario y lo convierta en una habilidad reutilizable. Dos modos:
- Modo navegador (predeterminado, evidencia más rica): un navegador Playwright con interfaz gráfica (Google Chrome del sistema si está disponible) registra cada acción del usuario en
events.jsonlcon múltiples candidatos de selectores, más piezas de traza de Playwright (trace-NNN.zip). Funciona en macOS, Windows y Linux. - Modo escritorio (aplicaciones nativas): un grabador ligero de un solo proceso (pynput) captura eventos globales de ratón/teclado, cambios de ventana activa, capturas de pantalla en el momento del clic y el objetivo de accesibilidad de cada clic (macOS AX, Windows UI Automation) en
desktop-events.jsonl+screens/, con campos de contraseña enmascarados — paridad con Codex (Codex también graba un flujo de eventos/contexto, no video), ~1-3% de CPU. Funciona en macOS, Windows y Linux (X11). Consulta "Grabación de escritorio" más abajo.
Elige el modo navegador siempre que el flujo de trabajo sea solo de navegador — sus selectores semánticos producen habilidades mucho mejores que las coordenadas de escritorio.
Configuración (una vez)
cd ~/.agents/skills/grabar-y-reproducir
node setup.mjs # npm install + (Chromium solo si falta Chrome) + autopruebas
node install.mjs # enlazar en los directorios de habilidades del agente (enlace simbólico en macOS/Linux, junction en Windows)
Instala el paquete npm playwright. Los navegadores NO se descargan cuando Google Chrome está instalado (el grabador usa channel: 'chrome'); de lo contrario, el script descarga Chromium. Ambos scripts son multiplataforma (Node).
Flujo de trabajo de grabación
-
Antes de comenzar, dile al usuario que cierre ventanas, archivos y conversaciones que no desea capturar, y que no escriba secretos que no quiera almacenados. Inicia el grabador en segundo plano, de forma separada, solo cuando el usuario esté listo para comenzar. Siempre pasa
--name <slug>para que el directorio de salida se conozca de antemano:cd ~/.agents/skills/grabar-y-reproducir # macOS / Linux: nohup node scripts/recorder.mjs --minutes 30 --name <slug> [--url <startUrl>] \ > ~/.agents/recordings/recorder.log 2>&1 & # Windows (PowerShell): Start-Process node -WindowStyle Hidden -ArgumentList "scripts/recorder.mjs","--minutes","30","--name","<slug>"Los agentes con una función nativa de ejecución en segundo plano (por ejemplo, el Bash de Claude Code con
run_in_background) pueden usarla en su lugar. Las salidas van a~/.agents/recordings/<slug>/. -
Verifica el inicio una vez (~2-3 segundos después de lanzarlo — una sola comprobación, no un bucle de sondeo): confirma que
~/.agents/recordings/<slug>/session.jsonexista con"status": "recording"(el grabador también imprime una línea{"status":"recording",...}en el registro si tiene éxito). Si la comprobación falla, lee el registro:recording_already_active(código de salida 2) significa que otra grabación tiene el bloqueo;launch_failedo un error de módulo faltante significa que se necesita configuración. Informa el problema real en lugar de decirle al usuario que la grabación ha comenzado. -
Después de la comprobación de inicio, no duermas, sondees ni esperes en un bucle. Termina tu turno: dile al usuario que la grabación ha comenzado, cuál es el límite de tiempo y que una pequeña ventana de control flotante (esquina inferior derecha, como los controles de grabación de Codex) tiene un temporizador más botones de Pausa/Reanudar, Detener y Descartar (toca dos veces para confirmar). No se captura nada mientras está en pausa: tanto los eventos como la traza se detienen. Si el usuario cierra la ventana de control por accidente, se reabre sola; cerrar la ventana principal del navegador también finaliza la sesión (evita salir completamente del navegador con Cmd+Q, ya que puede perder el último minuto de la traza). Pasa
--badgeal inicio para usar una insignia en la página en lugar de la ventana de control (alternativa para entornos exóticos). -
Pausa/reanudación (el usuario te pide que pauses, o necesitas saltar un tramo delicado):
touch ~/.agents/recordings/<slug>/PAUSEpausa en menos de 2 segundos; elimina el archivo para reanudar. Los botones de la ventana de control y el archivo PAUSE se mantienen sincronizados;session.jsonlleva el estado actual depaused. Los intervalos en pausa aparecen como marcadorespaused/resumedenevents.jsonly están ausentes de la traza. -
Cuando el usuario dice que ha terminado:
- Si el proceso aún se está ejecutando, detenlo de forma segura:
touch ~/.agents/recordings/<slug>/STOP(el grabador lo nota en menos de 2 segundos y finaliza). - Lee
session.json—status: "recording"significa que sigue activo;"completed"significa que las salidas son finales;"discarded"significa que el usuario presionó Descartar — los archivos de evidencia se eliminaron, reconoce y NUNCA crees una habilidad a partir de ello.endReasones uno deuser_stopped,user_discarded,browser_closed,stop_file,time_limit,signal,event_limit. - Inspecciona los eventos capturados antes de responder: ejecuta
node scripts/summarize.mjs <outDir>para una línea de tiempo compacta, luego leeevents.jsonldirectamente para los pasos que necesiten detalle.
- Si el proceso aún se está ejecutando, detenlo de forma segura:
-
La cancelación se define por contenido, no por endReason: si la grabación contiene pocos o ningún evento
kind: "dom"— independientemente de endReason — considérala cancelada. Reconoce, no crees ni actualices una habilidad. -
Si la grabación contiene suficiente información para identificar un flujo de trabajo reutilizable, crea o refina una habilidad para ello de forma predeterminada — incluso si el usuario no lo pidió explícitamente. No te detengas después de producir solo un resumen o un plan de reproducción. Sigue "Creación de habilidades a partir de una grabación" a continuación: comienza con una breve ronda de aclaración.
-
Si la grabación es demasiado escasa o ambigua para identificar el flujo de trabajo, no adivines. Explica lo que no está claro y pregúntale al usuario las piezas faltantes.
Grabación concurrente
Solo una grabación puede estar activa a la vez (archivo de bloqueo ~/.agents/recordings/.lock). Si el grabador sale con recording_already_active, no fuerces el inicio de otra; dile al usuario que ya hay una grabación en curso y pregúntale si quiere usarla o detenerla primero. Reiniciar con el mismo --name es seguro: el events.jsonl anterior se conserva como un .bak con marca de tiempo, no se añade.
Interpretación de eventos
events.jsonl es la evidencia principal; session.json solo proporciona tiempos/rutas; las piezas trace-NNN.zip son la verdad fundamental a nivel de DOM (npx playwright show-trace <outDir>/trace-*.zip; session.json's traceChunks las enumera en orden). La traza por defecto es en modo ligero: instantáneas completas del DOM por acción pero sin capturas de pantalla continuas (mantiene la CPU baja). Comienza con --trace full cuando el usuario quiera evidencia visual perfecta a nivel de píxel, o --trace off para la huella mínima absoluta.
Cada línea es un evento: {seq, t (ms desde el inicio), kind, type, url, ...}.
kind: "page"— navegaciones, descargas, diálogos, aperturas/cierres de pestañas. Las navegaciones segmentan el flujo de trabajo en etapas.kind: "dom"— acciones del usuario.target.selectorslleva múltiples candidatos de selectores:testId,role({role, name}),id,nameAttr,text,css. Prefiérelos en ese orden al generar código de reproducción;csses el último recurso.type: "input"los eventos están debounced — un evento por campo con el valor final (vaciado en blur, Enter, cambio y envío del formulario). Los campos de contraseña/tarjeta de crédito/OTP (nombres en inglés y turco: password, parola, şifre, kart, kimlik…) llegan pre-enmascarados (***MASKED***,masked: true).- Los eventos
selectionycopyrevelan con qué contenido estaba trabajando el usuario — a menudo la mejor pista cuando el usuario se refiere a "esto" o "lo que seleccioné". Las selecciones con aspecto de secreto (OTP, claves API, tokens) se enmascaran. Los eventospastesolo llevan longitud/recuento de palabras, nunca el contenido. - Datos sensibles: el enmascaramiento es heurístico, no una garantía — y se aplica solo a
events.jsonl. Las piezas de traza NO están enmascaradas: las instantáneas del DOM contienen valores de entrada sin procesar (incluidos valores enmascarados en el JSONL) y las capturas de pantalla capturan todo lo visible en pantalla (tokens revelados, códigos 2FA, saldos). Trata todo el directorio~/.agents/recordings/<name>/como sensible: inspecciónalo solo localmente, nunca lo subas ni lo confirmes, y nunca cites secretos literales de él en resúmenes o habilidades generadas — usa marcadores de posición o descripciones genéricas.
Creación de habilidades a partir de una grabación
Lee references/skill-authoring.md antes de escribir: contiene el banco de preguntas, los límites del frontmatter, el esqueleto de SKILL.md, las reglas para scripts empaquetados y la lista de verificación de calidad. Si una habilidad skill-creator está disponible en tu entorno, su guía también se aplica. Crea una habilidad descubrible real (una carpeta SKILL.md), no solo un manual de Markdown.
Copia esta lista de verificación y márcala:
- [ ] 1. Resume la grabación; anota cada brecha (decisiones, tramos enmascarados, puntos ciegos)
- [ ] 2. Aclara: un mensaje, máximo 6 preguntas, solo sobre las brechas
- [ ] 3. Verifica si existe una habilidad que cubra este flujo de trabajo → actualízala en lugar de duplicar
- [ ] 4. Escribe la habilidad + evals/evals.json (la grabación es el caso de prueba 1)
- [ ] 5. Valida: node scripts/export-skill.mjs <skillDir> --check → corrige errores, vuelve a ejecutar
- [ ] 6. Ofrece la verificación de activación + una ejecución de prueba; incorpora correcciones, incrementa metadata.version
- [ ] 7. Ofrece la exportación ZIP para claude.ai
Paso 2 — aclara antes de escribir. No hay audio: la grabación muestra lo que sucedió, no por qué. Responde desde la grabación lo que muestre, luego pregúntale al usuario — una vez, en un solo mensaje, máximo 6 preguntas — sobre lo que no puede: el resultado y cómo saber si funcionó, qué valores varían entre ejecuciones, por qué eligió X en un momento dado, qué acciones fueron desvíos, qué diría para activar la habilidad (y qué no debería), y qué acciones necesitan confirmación. Cita el momento al que te refieres ("a las 02:14 limpió el filtro de fecha — ¿por qué?"). Usa tu herramienta de preguntas estructuradas si la tienes; chat simple en caso contrario. Omite la ronda solo cuando la grabación más la solicitud del usuario ya respondan todo, y dilo.
Reglas de escritura:
- Trata la grabación como evidencia del resultado deseado por el usuario, no como un guion para reproducir píxel por píxel. Si un conector/API/CLI/herramienta MCP puede lograr el mismo resultado semánticamente (crear un evento de calendario, abrir un PR, publicar un mensaje), prefíérelo sobre la automatización de la interfaz de usuario.
- Cuando la reproducción de la interfaz de usuario sea realmente necesaria, genera un script de Playwright a partir de
scripts/replay-template.mjs: localizadores semánticos (getByTestId>getByRole>getByLabel>getByText), un paso de verificación después de cada acción crítica, secretos desde variables de entorno. Nunca uses coordenadas sin procesar a menos que el flujo de eventos no ofrezca un objetivo mejor. - Los pasos de escritorio nombran el objetivo capturado (rol + nombre + ventana, por ejemplo, Botón "Guardar" en "Factura — Acme") para que una herramienta de árbol de accesibilidad pueda encontrarlo; coordenadas solo cuando no se capturó ningún objetivo.
- El perfil persistente del grabador (
~/.agents/recordings/.browser-profile) mantiene los inicios de sesión entre sesiones, por lo que las habilidades generadas generalmente no necesitan pasos de inicio de sesión. Seguridad: ese directorio contiene material de sesión autenticado activo (cookies/localStorage; Playwright inicia Chrome con un llavero simulado, así que trátalo como credenciales en texto plano). Nunca lo confirmes, compartas ni hagas copias de seguridad sin cifrar — y recuerda que cualquier habilidad de reproducción que lo reutilice se ejecutará con los inicios de sesión del usuario. Para grabaciones en sitios no confiables o de alta sensibilidad, prefiere un perfil desechable (--outmás un perfil temporal) o limpia el perfil después. - Guarda las nuevas habilidades en
~/.agents/skills/<skill-name>/(nombre de carpeta =name, kebab-case) y enlázalas simbólicamente en los directorios de habilidades del agente (consultainstall.mjspara el patrón) para que todos los agentes en esta máquina puedan usarlas. - Parametriza lo que varía (fechas, cantidades, nombres) y codifica lo que no. Indica el propósito del flujo de trabajo y los criterios de verificación en el SKILL.md generado. Nunca copies secretos o valores enmascarados en la habilidad.
Exportar para claude.ai (ofrécelo; ejecuta a petición): node scripts/export-skill.mjs ~/.agents/skills/<name> escribe ~/.agents/exports/<name>.zip (carpeta en la raíz del ZIP; README, evals, cachés y evidencia de grabación excluidos; archivo leído de vuelta antes de confirmar el éxito). Si la habilidad usa frontmatter solo de Claude Code (disable-model-invocation, …) agrega --strip-cc-keys. Dile al usuario dónde está el archivo y que se sube en Personalizar › Habilidades › + › Subir una habilidad (la ejecución de código debe estar habilitada).
Grabación de escritorio (macOS, Windows, Linux/X11)
Configuración: node setup.mjs (crea el entorno Python .venv-desktop mínimo de requirements-desktop.txt — pynput+mss+pillow, más comtypes en Windows, ~50 MB; requiere uv).
Permisos (macOS): el grabador los verifica previamente e informa el estado legible por máquina, así que nunca adivines. start imprime permissions: {inputMonitoring, screenRecording, grantTo} más un warning cuando falta algo, y automáticamente abre el diálogo del sistema y el panel de Configuración adecuado (--no-permission-prompt lo desactiva; node scripts/desktop-record.mjs permissions lo ejecuta a demanda). grantTo nombra la aplicación a la que el usuario debe conceder permiso — un permiso TCC está vinculado al paquete .app que aloja al agente, no a Python, y esa aplicación debe reiniciarse después. Transmite grantTo textualmente; decirle al usuario "concede permiso a tu terminal" generalmente es incorrecto. Windows no necesita permisos ni derechos de administrador.
El motor es un grabador de un solo proceso (~0-3% de CPU): flujo de eventos de entrada + cambios de ventana activa/título + una captura JPEG de media resolución en cada clic (máximo 1/700ms) → desktop-events.jsonl + screens/. Cada clic también lleva la descripción de accesibilidad del elemento bajo el cursor (línea kind: "target", unida al clic por forSeq): role, name, automationId, window, ancestors — un objetivo semántico como Button "Save" en lugar de una coordenada simple (macOS AX, Windows UI Automation; ninguna en Linux). La escritura llega como eventos type: "text" que contienen el valor final de cada ráfaga (correcciones de retroceso aplicadas); los atajos y teclas especiales como eventos press (ctrl+c, enter). Las capturas de pantalla, consultas de objetivos y comprobaciones de enfoque se ejecutan en hilos de trabajo, nunca en el callback de entrada: un callback lento hace que se deshabilite el tap de eventos de macOS y el hook de Windows se elimine silenciosamente (el grabador también vigila esto último y reinstala los hooks).
Esto es paridad con Codex: el Grabado y Reproducción de Codex también graba...
[...truncado para traducción]