Communitygithub.com

shenmituzi/img-share

Skill de DSH: comparte capturas de pantalla del navegador / imágenes locales en el chat (miniatura + pantalla completa, visible en el teléfono)

¿Qué es img-share?

Esta skill permite a un agente AI compartir imágenes (capturas de pantalla del navegador o archivos de imagen locales) directamente en el chat, mostrando una miniatura que al hacer clic revela la imagen a tamaño completo, accesible también desde teléfonos móviles u otros dispositivos. Es compatible con múltiples plataformas: Linux, macOS, WSL y Windows nativo. La skill primero determina si el host de la sesión DSH ya es accesible públicamente (por ejemplo, a través de un túnel o dominio público). Si es así, coloca las imágenes en el directorio estático del host para que se carguen bajo el mismo dominio, evitando abrir túneles adicionales. Si el host solo es localhost o no expone una ruta de imágenes estática, la skill solicita permiso al usuario antes de recurrir a un túnel explícito independiente (usando cloudflared) y solo comparte el archivo específico, no todo un directorio. Incluye mecanismos de seguridad como copiar el archivo a un subdirectorio con nombre aleatorio, vincular el servidor solo a 127.0.0.1 y limpiar el túnel inmediatamente después de compartir. También maneja fallos degradando a capturas de pantalla en la nube si el navegador local falla, y realiza verificaciones de extremo a extremo para garantizar que la URL funcione correctamente.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add shenmituzi/img-share

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Skill img-share

Convierte capturas de pantalla del navegador o imágenes locales en imágenes en las que se puede hacer clic para ver a tamaño completo (miniatura + clic para ver la original) dentro del chat, y además accesibles desde el teléfono móvil y otros dispositivos. Multiplataforma (Linux/macOS/WSL/Windows nativo).

CuándoUsar (cuándo activar)

  • El usuario pide "abrir un sitio web/página, capturarla y mostrarla";
  • Pegar una imagen en el chat y desear que "se pueda ver desde el móvil, haciendo clic para ampliar los detalles";
  • Convertir una imagen del espacio de trabajo en una imagine incrustada en el chat en la que se pueda hacer clic para ver a tamaño completo.

Dependencias

DependenciaUsoObtención
skill web-accessCaptura de pantalla (navegador impulsado por CDP)Requiere instalar: https://github.com/eze-is/web-access
python3/pythonOrquestador (serve.py)Incluido en el sistema
cloudflaredTúnel público de respaldoMac: brew install cloudflared; Win: winget install Cloudflare.cloudflared; Linux: consultar su README oficial; o establecer CLOUDFLARED=/ruta
ffmpeg (opcional)Crear cuadrícula de varias imágenesInstalación del sistema (usado por scripts/montage.sh)

Pasos de ejecución

  1. Determinación de accesibilidad del host (obligatorio, lo primero) — Decide la URL base de la imagen y si es necesario abrir un túnel público adicional. La dirección de la imagen debe seguir la dirección del host, no se debe abrir por iniciativa propia un túnel con un origen diferente al del host solo para "que funcione":

    DeterminaciónConclusión (acción)
    El host ya tiene túnel / es accesible públicamente (el usuario accede a esta sesión a través de esa dirección desde el móvil), y el host expone una ruta de imágenes estáticas (p. ej., /img/*)Colocar la imagen en el directorio estático del host, incrustar usando la dirección pública del host, no abrir un nuevo túnel
    El host es accesible públicamente pero no expone una ruta de imágenes estáticasNo hacer un respaldo silencioso: primero informar al usuario de que "es necesario configurar un mapeo de imágenes estáticas en el host"; solo si el usuario lo acepta se procede al "respaldo explícito con túnel independiente"
    El host solo es localhost (p. ej., DSH_WEB_URL=http://127.0.0.1:*, sin túnel público)La imagen solo tendrá una dirección local/de red local; el móvil no puede llegar a esta sesión de todos modos — primero indicar al usuario que haga pública la DSH, o con el consentimiento del usuario proceder al respaldo explícito; prohibido incrustar direcciones localhost/127.0.0.1 y afirmar que se puede ver desde el móvil
    No se puede detectar / inciertoNo adivinar, preguntar primero al usuario: "¿Qué dirección utiliza tu móvil para acceder a esta sesión (dominio público o localhost)?" Luego actuar según la tabla anterior

    Método de detección: leer variables de entorno (DSH_WEB_URL, DSH_PUBLIC_BASE, DSH_IMG_BASE, etc.), consultar la configuración de rutas estáticas del host; si no se obtienen, se considera que "el host no lo proporciona", seguir la tabla anterior con "preguntar al usuario / indicar", no degradar silenciosamente a abrir otro túnel.

    Contrato del host (acuerdo anticipado, el host DSH actual aún no lo proporciona): si el host expone DSH_PUBLIC_BASE / DSH_IMG_BASE o declaraciones equivalentes de rutas estáticas, el agente debe priorizar colocar las imágenes bajo el dominio del host; si no se proporciona, no asumir su existencia.

  2. Captura de pantalla (si es necesario): usar la skill web-access, /screenshot para renderizar la página como PNG.

    • Si CDP/Chromium no puede ejecutarse en entornos restringidos (sin conexión a internet / el proceso falla), degradar a captura en la nube: usar thum.io / mshots / microlink, etc., con ?wait=N&width=W, verificar después de recibir que "la proporción de píxeles no blancos supera un umbral, el número de clústeres de color > N", solo si no está en blanco se puede usar.
  3. Guardar imagen: colocarla en el espacio de trabajo (p. ej., img/x.png, nombre de archivo en ASCII / sin espacios).

  4. Compartir (según la conclusión del paso 0, elegir una):

    • Ruta del host (cuando el paso 0 determina que es reutilizable): colocar la imagen en el directorio estático expuesto por el host, incrustar https://<dominio del host>/img/x.png; no abrir un túnel independiente.
    • Respaldo explícito (cuando el paso 0 determina que se necesita respaldo y el usuario lo acepta): compartir solo este archivo, no abrir todo el directorio; iniciar el servidor de imágenes[solo loopback] + túnel público, verificación extremo a extremo, generar PUBLIC_BASE:
      bash <skill>/scripts/setup.sh <img>/x.png        # Unix/WSL
      python <skill>/scripts/serve.py --share <img>/x.png   # Windows nativo
      
  5. Incrustar en la respuesta (miniatura = URL de la imagen original, clic para ver la imagen completa en pantalla completa):

    [![Descripción](https://<base>/x.png)](https://<base>/x.png)
    

    La base debe ser el resultado del paso 0 (dirección pública del host, o la dirección del túnel explícito aceptada por el usuario); prohibido incrustar localhost/127.0.0.1 y afirmar que se puede ver desde el móvil. Informar al usuario: el chat muestra una miniatura, al hacer clic se ve la imagen original; el móvil también puede acceder usando la misma dirección pública (verificado que DSH puede renderizar imágenes markdown públicas).

  6. Compartir finalizado → eliminar túnel (en el escenario de respaldo explícito, para evitar exposición prolongada):

    bash <skill>/scripts/teardown.sh                  # Detener servidor de imágenes + túnel + limpiar
    

Manejo de fallos

  • No se puede determinar la accesibilidad del host: no adivinar, no abrir silenciosamente otro túnel; preguntar primero al usuario la dirección que usa su móvil para acceder a esta sesión (ver paso 0).
  • Host público pero sin ruta de imágenes estáticas: indicar al usuario que configure el mapeo estático, o con su consentimiento proceder al respaldo explícito, explicando que ese túnel tiene un origen diferente al del host.
  • Falta de dependencias: serve.py informa "falta cloudflared/python", instalar según las indicaciones o establecer CLOUDFLARED; si falta web-access para capturas, degradar a captura en la nube (ver arriba) o pedir al usuario que suba la imagen.
  • Puerto ocupado: serve.py selecciona automáticamente un puerto libre.
  • No se puede obtener el dominio del túnel (red lenta / desconexión de Cloudflare): serve.py reintenta con polling; si aún falla, informar "no se puede establecer un túnel de red", retroceder a solo local/red local (proporcionar dirección local y explicar que para el escenario móvil el host/servicio debe ser accesible públicamente primero).
  • Fallo en la verificación extremo a extremo: serve.py hace curl al archivo real para verificar (solo válido si devuelve 200); si falla, eliminar todo, evitando "parece activo pero devuelve 404".
  • Deriva del dominio: los túneles rápidos cambian de dominio al reiniciar, dejando inválidas las URL incrustadas antiguas; la ruta del host no tiene este problema; para estabilidad a largo plazo en escenarios de respaldo, usar túneles con nombre/dominio fijo.

Autocomprobación del entorno (el agente debe hacerla primero)

Antes de comenzar, detectar: si se puede acceder a internet (curl a una dirección pública), si se puede crear un proceso de navegador (CDP), si el host es accesible públicamente (ver paso 0). Si no se puede acceder a internet ni CDP → usar captura en la nube + indicar que se necesitan más permisos, no entregar al usuario una imagen que "parece funcionar pero en realidad está rota".

Seguridad (acciones predeterminadas, no recordatorios)

  • Compartir solo el archivo especificado: serve.py copia el archivo a compartir en un subdirectorio con nombre aleatorio e inicia el servicio, nunca abrir todo el directorio img/ (de lo contrario, la URL del túnel podría listar/descargar todos los archivos de ese directorio); de manera similar, en el directorio estático del host solo colocar el archivo a compartir.
  • El servidor de imágenes se vincula solo a 127.0.0.1 (no accesible desde la red local); la URL del túnel público no tiene autenticación — ejecutar teardown inmediatamente después de compartir.
  • Para mayor seguridad: agregar un token aleatorio a la URL / usar un túnel de corta duración; no compartir imágenes sensibles.
  • No poner todas las imágenes en público: solo permitir que la/las imágenes que se compartirán en esta ocasión aparezcan en el directorio/túnel accesible públicamente.

Prioridad del túnel del host (ver determinación en el paso 0 de los pasos de ejecución)

  • La dirección de la imagen sigue la dirección del host: si el host ya tiene túnel / es accesible públicamente, la imagen debe colocarse bajo el mismo dominio (por ejemplo, ruta estática /img/*) — el usuario la cargará al abrir la sesión desde el móvil, sin necesidad ni conveniencia de abrir otro túnel temporal con origen diferente.
  • Si el host expone reglas estáticas /img/ a través de dsh-trust-proxy, etc., la URL de la imagen tendrá la forma https://<dominio DSH>/img/x.png, accesible desde diferentes dispositivos, evitando abrir múltiples túneles.
  • El túnel cloudflared independiente de serve.py es solo un respaldo portátil (se puede ejecutar en cualquier máquina): se usa únicamente cuando el paso 0 determina que "el host no es reutilizable para acceso público" y con el consentimiento informado del usuario, indicando claramente sus limitaciones (origen diferente al del host, los túneles rápidos cambian de dominio al reiniciar).

Límites

  • El proceso debe ser persistente/poder eliminarse: serve.py registra el PID para que teardown lo use; en una sesión DSH, el servicio debe ser trans-sesiones (se puede usar un backend administrado + teardown explícito para limpiar).
  • Nombre de archivo: usar ASCII, sin espacios; los scripts verifican la existencia del archivo; los caracteres chinos y espacios se manejan mediante codificación URL, pero se recomienda evitarlos.
  • Espacio de trabajo diferente: diferentes sesiones tienen diferentes espacios de trabajo; compartir según la ruta de esa sesión; serve.py usa el directorio temporal del sistema, no depende del espacio de trabajo.

Skills relacionados