Files
Alejandro Martinez b86c9f3e3a Add hooks and CLAUDE.md resource types with install/uninstall scripts
Introduces two new resource types (hooks, claude-md) with full CRUD,
   visual hook config editor, section-delimited CLAUDE.md installs,
   uninstall endpoints, and shell injection hardening in sync scripts.
2026-02-16 11:51:33 +01:00

6.2 KiB

Plan: Soporte de Skills en formato carpeta (Folder-based resources)

Contexto

El PDF oficial de Anthropic define que una skill puede ser una carpeta con subdirectorios:

my-skill/
├── SKILL.md          # Requerido
├── scripts/          # Opcional - codigo ejecutable
├── references/       # Opcional - documentacion
└── assets/           # Opcional - plantillas, fuentes, iconos

Actualmente Skillit almacena cada recurso como un unico .md en data/<type>/<slug>.md. Queremos soportar ambos formatos: simple (archivo .md) y carpeta (directorio con SKILL.md + subdirectorios).

Archivos a modificar

Archivo Cambio
src/lib/registry.ts Agregar mainFileName por tipo y constante FOLDER_SUBDIRS
src/lib/resources.ts Reescribir CRUD para detectar/manejar ambos formatos; nuevas funciones para sub-archivos
src/lib/skills.ts Actualizar interfaz Skill con format y files
src/lib/sync.ts Scripts de sync/push con soporte carpeta
src/pages/api/resources/[type]/index.ts Aceptar format en POST
src/pages/api/resources/[type]/[slug].ts Manejar carpeta en GET
src/pages/[type]/[slug].astro Mostrar arbol de archivos
src/pages/[type]/[slug]/edit.astro Pasar format/files al editor
src/pages/[type]/new.astro Soporte selector de formato
src/pages/[type]/[slug]/i.ts Install scripts multi-archivo
src/pages/[type]/[slug]/gi.ts Install global multi-archivo
src/components/ResourceEditor.vue Toggle formato + integrar FileManager

Archivos nuevos

Archivo Proposito
src/pages/api/resources/[type]/[slug]/files/index.ts Listar y subir sub-archivos
src/pages/api/resources/[type]/[slug]/files/[...filePath].ts CRUD individual de sub-archivos
src/components/FileManager.vue Componente Vue para gestionar sub-archivos
src/components/FolderTree.astro Componente Astro para mostrar arbol de archivos en detalle

Fases de implementacion

Fase 1: Registry (registry.ts)

Agregar campo mainFileName a ResourceTypeConfig:

  • skills: SKILL.md
  • agents: AGENT.md
  • output-styles: OUTPUT-STYLE.md
  • rules: RULE.md

Agregar constante FOLDER_SUBDIRS = ['scripts', 'references', 'assets'].

Fase 2: Core CRUD (resources.ts)

Cambios principales:

  1. Nuevos tipos:

    • ResourceFormat = 'file' | 'folder'
    • ResourceFileEntry = { relativePath: string; size: number }
    • Agregar format y files a interfaz Resource
  2. resolveResource(type, slug) (nueva): detecta si el recurso es archivo o carpeta. Carpeta tiene prioridad si ambos existen.

  3. listResources(type): escanear tanto *.md como directorios con el mainFileName.

  4. getResource(type, slug): usar resolveResource, leer mainFile, listar sub-archivos si es carpeta.

  5. createResource(type, slug, content, format?): parametro format opcional (default 'file'). Si 'folder', crear directorio y escribir mainFileName.

  6. updateResource(type, slug, content): auto-detectar formato, escribir en la ruta correcta.

  7. deleteResource(type, slug): auto-detectar. Para carpeta usar fs.rm(dirPath, { recursive: true }).

  8. Funciones nuevas para sub-archivos:

    • listResourceFiles(type, slug) - listar archivos auxiliares
    • getResourceFile(type, slug, relativePath) - leer sub-archivo (Buffer)
    • addResourceFile(type, slug, relativePath, data: Buffer) - escribir sub-archivo
    • deleteResourceFile(type, slug, relativePath) - eliminar sub-archivo
    • convertToFolder(type, slug) - convertir simple a carpeta
  9. Seguridad: validar que relativePath no contenga .., solo permita rutas dentro de FOLDER_SUBDIRS.

Fase 3: API de sub-archivos

/api/resources/[type]/[slug]/files/index.ts:

  • GET: lista sub-archivos (JSON)
  • POST: subir archivo via multipart/form-data

/api/resources/[type]/[slug]/files/[...filePath].ts:

  • GET: descargar sub-archivo
  • PUT: subir/reemplazar sub-archivo
  • DELETE: eliminar sub-archivo

Modificar /api/resources/[type]/index.ts:

  • POST acepta format: 'file' | 'folder' opcional

Fase 4: Pagina de detalle ([type]/[slug].astro)

  • Comprobar resource.format
  • Para carpeta: renderizar seccion "Files" con FolderTree.astro
  • El raw markdown (para curl) sigue devolviendo solo el mainFile

FolderTree.astro: componente que muestra arbol de archivos con links de descarga.

Fase 5: Editor UI

ResourceEditor.vue:

  • Nuevos props: initialFormat, files
  • Toggle formato al crear (Simple / Carpeta)
  • Seccion FileManager al editar recurso tipo carpeta

FileManager.vue (nuevo componente Vue):

  • Lista archivos con boton eliminar
  • Boton subir: selector de subdirectorio (scripts/references/assets) + file input
  • Llamadas fetch a la API de files

Fase 6: Scripts de instalacion

[type]/[slug]/i.ts y gi.ts:

  • Para formato carpeta: generar script que crea estructura de directorios y descarga cada archivo
  • URLs de sub-archivos: ${origin}/api/resources/${type}/${slug}/files/${relativePath}
  • chmod +x para archivos en scripts/

sync.ts:

  • Sync: detectar formato por recurso, generar descarga multi-archivo
  • Push: iterar tanto *.md como directorios; subir main content + sub-archivos

Fase 7: Backward compat (skills.ts)

Actualizar interfaz Skill con format y files. El wrapper sigue delegando a resources.ts.

Orden de implementacion

  1. Fase 1 (registry) - base
  2. Fase 2 (resources.ts CRUD) - critico
  3. Fase 3 (API sub-archivos)
  4. Fase 4 (pagina detalle)
  5. Fase 5 (editor UI)
  6. Fase 6 (scripts instalacion)
  7. Fase 7 (backward compat)

Verificacion

  1. Crear un skill simple (test-simple) via web - verificar que funciona como antes
  2. Crear un skill carpeta (test-folder) via web - verificar que se crea directorio con SKILL.md
  3. Subir archivos a scripts/ y references/ del skill carpeta via FileManager
  4. Ver pagina de detalle - verificar arbol de archivos
  5. Ejecutar script de instalacion (curl .../skills/test-folder/i | bash) - verificar descarga completa
  6. Verificar que listado muestra ambos formatos correctamente
  7. Editar ambos formatos - verificar que se actualizan
  8. Eliminar ambos formatos - verificar limpieza