# Integración con Claude Code — Hooks

Este archivo documenta cómo configurar un [hook de Claude Code](https://code.claude.com/docs/en/hooks) para automatizar el flujo de generación de widgets:

- **Disparar la validación después de cada edición sobre un archivo de widget** (`PostToolUse`) — para detectar errores de convenciones de Dynamic UI de forma continua, sin tener que invocarla a mano.

**El hook es opcional.** El módulo Widgets del MCP funciona sin él: las tools `widgets-*` y el Prompt `widgets-init-project` no dependen de hooks. El hook suma automatización, no es un requisito.

Los snippets de esta página están pensados para pegarse directamente en `~/.claude/settings.json` (configuración del usuario) o en `.claude/settings.json` del proyecto. Cada snippet incluye comentarios sobre qué adaptar a tu entorno.

---

## PostToolUse — Disparar validación después de Write/Edit

Hay dos formas de hacerlo. Elegí según cómo tenés configurado tu entorno:

### Opción 1 (preferida) — Invocar la tool MCP `widgets-validate`

Cuando el Modyo MCP server está conectado en tu Claude Code, podés invocar la tool MCP directamente sin pasar por shell. Esta es la forma cliente-nativa.

**Pegá este snippet en `.claude/settings.json` del directorio del widget en el que estás trabajando** (no en el user-global), para que se active solo cuando trabajés ahí:

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "mcp_tool",
            "server": "modyo",
            "tool": "widgets-validate",
            "input": {
              "projectPath": "/absolute/path/to/your/widget/root"
            }
          }
        ]
      }
    ]
  }
}
```

**Adaptá:**
- `"server": "modyo"` — debe coincidir con el nombre con el que registraste el MCP server modyo en `~/.claude.json` (`mcpServers.<key>`). Si tu key es otra, ajustala.
- `"projectPath"` — reemplazá `/absolute/path/to/your/widget/root` por el path absoluto del widget (el directorio que contiene `package.json` del widget generado, por ejemplo `~/Code/dynamic-2.0/generated-widgets/transfer-detail`). La tool `widgets-validate` espera el widget root, no un archivo individual.

**Por qué scoped al directorio del widget:** Claude Code dispara `PostToolUse` en cada `Write`/`Edit`/`MultiEdit`. Si lo configurás user-global, se va a ejecutar también cuando editás archivos fuera del widget, generando ruido. Configurarlo en el `.claude/settings.json` del widget hace que solo se active cuando trabajás en ese directorio.

**Limitaciones:**
- No soporta `${tool_input.file_path}` directamente acá porque la tool `widgets-validate` necesita el widget root, no un archivo. Si querés autodetectar el root desde el path del archivo editado, usá la **Opción 2** que tiene un `sed` que extrae el widget root.
- Requiere que el MCP server modyo esté conectado y activo en tu sesión de Claude Code. Si no, el hook se descarta sin ruido (no es bloqueante).

### Opción 2 (fallback) — Invocar el validator vía `npx @modyo/widget-validator`

Útil cuando (a) no tenés el Modyo MCP server activo en tu Claude Code, o (b) preferís un hook universal que extraiga automáticamente el widget root desde cualquier path de archivo editado.

Pegá este snippet en `~/.claude/settings.json` (user-global):

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(jq -r '.tool_input.file_path // empty'); case \"$FILE\" in *\"/generated-widgets/\"*) WIDGET=$(echo \"$FILE\" | sed -E 's|(.*/generated-widgets/[^/]+).*|\\1|'); npx @modyo/widget-validator \"$WIDGET\" 2>&1 | tail -20 ;; esac"
          }
        ]
      }
    ]
  }
}
```

**Cómo funciona:**
1. `jq -r '.tool_input.file_path // empty'` extrae la ruta del archivo modificado del JSON que Claude Code pasa por stdin al hook.
2. El `case` filtra: solo continúa si el path contiene `/generated-widgets/`. Cualquier otro `Write`/`Edit` (en `docs/`, en repos no-widget, etc.) se descarta sin ruido.
3. `sed` recorta el path hasta la raíz del widget (`.../generated-widgets/<widget>`).
4. `npx @modyo/widget-validator "$WIDGET"` ejecuta el validator publicado en NPM. El `| tail -20` recorta el output a las 20 últimas líneas (resumen + errores) para no saturar la consola.

**Dependencias del snippet:**
- `jq` (en macOS: `brew install jq`).
- `node` y `npx` en el PATH (Node 22+ — lo exige `@modyo/widget-validator@0.1.4`, cuyo `engines` declara `node >=22.0.0`).
- Conexión a NPM en la primera invocación (después queda cacheado).

Si tenés baja conectividad o querés que el hook arranque más rápido, instalá el paquete global una sola vez (`npm install -g @modyo/widget-validator`) y reemplazá `npx @modyo/widget-validator` por `modyo-widget-validator` (o el binario que exponga el paquete).

---

## Ejemplo completo (user-global)

Ejemplo completo de `~/.claude/settings.json` user-global con el hook `PostToolUse` (Opción 2, universal):

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(jq -r '.tool_input.file_path // empty'); case \"$FILE\" in *\"/generated-widgets/\"*) WIDGET=$(echo \"$FILE\" | sed -E 's|(.*/generated-widgets/[^/]+).*|\\1|'); npx @modyo/widget-validator \"$WIDGET\" 2>&1 | tail -20 ;; esac"
          }
        ]
      }
    ]
  }
}
```

Si preferís la Opción 1 para el `PostToolUse`, pegá el snippet de `mcp_tool` en el `.claude/settings.json` del widget en lugar de este `command`.

---

## Otros clientes MCP

Este archivo cubre Claude Code específicamente. Otros clientes (Cursor, Continue, etc.) tienen mecanismos de hooks distintos o no los tienen. Si querés agregar configuración para otro cliente, creá un archivo paralelo (`cursor.md`, etc.) en este mismo directorio siguiendo el patrón. Ver `modyo://docs/widgets/_meta-integration-README` de este directorio para más contexto.
