From e38f100189d4b95079aad314025a3580e71c55a0 Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Thu, 26 Mar 2026 00:21:34 +0100 Subject: [PATCH] refactor: simplificar SKILL.md delegando trabajo al script bash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce SKILL.md de ~450 líneas a ~60 líneas. El agente ahora solo ejecuta setup-jupyter.sh e interpreta el STATUS. Elimina instrucciones manuales redundantes que el bash ya maneja. --- .claude/skills/init-jupyter/SKILL.md | 438 ++------------------------- 1 file changed, 31 insertions(+), 407 deletions(-) diff --git a/.claude/skills/init-jupyter/SKILL.md b/.claude/skills/init-jupyter/SKILL.md index 128685e..d5fd749 100644 --- a/.claude/skills/init-jupyter/SKILL.md +++ b/.claude/skills/init-jupyter/SKILL.md @@ -4,431 +4,55 @@ description: Inicializa entorno Jupyter para exploración de datos con MCP compa argument-hint: [ruta-proyecto] disable-model-invocation: true user-invocable: true -allowed-tools: Bash, Read, Write, Edit, Glob +allowed-tools: Bash, Read --- # Inicializar Entorno Jupyter para Data Science Skill para preparar cualquier repo para exploración de datos con Jupyter + Claude colaborando en kernel compartido. -## ⚠️ REGLA CRÍTICA: MCP SIEMPRE LOCAL +## Instrucciones para el agente -**NUNCA instalar jupyter-mcp-server globalmente.** Siempre: -- Instalar en `.venv/bin/` del proyecto con `uv add jupyter-mcp-server` -- Usar ruta ABSOLUTA en `.claude/settings.local.json` -- Si existe instalación global (`~/.local/bin/jupyter-mcp-server`), eliminarla con `uv tool uninstall jupyter-mcp-server` +**Todo el trabajo está automatizado en `setup-jupyter.sh`.** Solo ejecuta el script y comunica el resultado. -## PASO 0: Verificar estado actual del repo - -**Ejecutar estas comprobaciones primero:** +### Paso único: Ejecutar el script ```bash -# 1. ¿MCP instalado en el venv LOCAL del proyecto? -[ -f .venv/bin/jupyter-mcp-server ] && echo "MCP_OK" || echo "MCP_NO" +# Obtener ruta del script (está junto a este SKILL.md) +SKILL_DIR="$HOME/DataProyects/repo_Claude/.claude/skills/init-jupyter" -# 2. ¿Repo ya configurado para Jupyter? -[ -f .claude/settings.local.json ] && grep -q "jupyter" .claude/settings.local.json && echo "REPO_CONFIG_OK" || echo "REPO_NO_CONFIG" - -# 3. ¿Jupyter corriendo en este repo? -pgrep -af "jupyter" | grep "$(pwd)" && echo "JUPYTER_RUNNING" || echo "JUPYTER_STOPPED" - -# 4. ¿CLAUDE.md tiene reglas Jupyter? -[ -f .claude/CLAUDE.md ] && grep -q "JUPYTER HABILITADO" .claude/CLAUDE.md && echo "RULES_OK" || echo "RULES_NO" - -# 5. ¿Puerto guardado está sincronizado con Jupyter real? -if [ -f .jupyter-port ]; then - PORT=$(cat .jupyter-port) - if lsof -i:$PORT 2>/dev/null | grep -q jupyter; then - echo "PORT_SYNC_OK" - else - echo "PORT_DESYNC (archivo dice $PORT pero no hay Jupyter ahí)" - fi -fi - -# 6. ¿Existe instalación GLOBAL de jupyter-mcp-server? (problemática) -[ -f ~/.local/bin/jupyter-mcp-server ] && echo "GLOBAL_MCP_EXISTS (eliminar)" || echo "NO_GLOBAL_MCP" +# Ejecutar con la ruta del proyecto (argumento del skill o directorio actual) +bash "$SKILL_DIR/setup-jupyter.sh" "${1:-.}" ``` -### Resultado: Instalación GLOBAL detectada (GLOBAL_MCP_EXISTS) +### Interpretar el resultado -**Eliminar inmediatamente para evitar conflictos:** +El script imprime una línea `STATUS:` al final: -```bash -# Eliminar instalación global -uv tool uninstall jupyter-mcp-server 2>/dev/null || pip uninstall -y jupyter-mcp-server 2>/dev/null -rm -f ~/.local/bin/jupyter-mcp-server +| STATUS | Significado | Qué decir al usuario | +|--------|-------------|---------------------| +| `READY` | Todo configurado y Jupyter corriendo | "Jupyter ya está listo. Puedes empezar a trabajar con notebooks via MCP." | +| `CONFIGURED_NOT_RUNNING` | Configurado pero Jupyter no corre | "Todo configurado. Ejecuta `./run-jupyter-lab.sh` en otra terminal para iniciar Jupyter." | +| `CONFIGURED` | Recién configurado | Mostrar los pasos siguientes que imprime el script | -# Verificar eliminación -[ -f ~/.local/bin/jupyter-mcp-server ] && echo "ERROR: No se pudo eliminar" || echo "Instalación global eliminada OK" -``` +### Si hay errores -Continuar con instalación local. +- Si el script falla, leer el error y ayudar al usuario +- Problemas comunes: + - `jq` no instalado → el merge de `.mcp.json` puede fallar + - `uv` no disponible → usa pip como fallback + - Puerto ocupado → el script autodetecta otro -### Resultado: MCP NO instalado +## Archivos que crea el script -**IMPORTANTE: NUNCA instalar jupyter-mcp-server globalmente. Siempre en el venv local.** +| Archivo | Propósito | +|---------|-----------| +| `run-jupyter-lab.sh` | Lanzador de Jupyter con autodetección de puerto | +| `.mcp.json` | Config MCP con ruta absoluta al ejecutable local | +| `.claude/CLAUDE.md` | Reglas para que Claude use MCP en lugar de bash | +| `.jupyter-port` | Puerto actual (creado al ejecutar Jupyter) | -```bash -# Crear venv si no existe -[ -d .venv ] || uv venv +## Regla crítica: MCP siempre local -# Instalar MCP en el venv local del proyecto -source .venv/bin/activate -uv add jupyter-mcp-server || pip install jupyter-mcp-server - -# Verificar instalación local exitosa -[ -f .venv/bin/jupyter-mcp-server ] && echo "MCP instalado localmente OK" || echo "ERROR: MCP no instalado" -``` - -Continuar con los siguientes pasos para configurar el MCP local. - -### Resultado: Repo YA configurado + Jupyter corriendo - -Informar: -``` -Este repo ya tiene Jupyter configurado y está corriendo. -Puedes empezar a trabajar directamente con notebooks via MCP. -``` -**DETENER AQUÍ** (no hace falta reconfigurar) - -### Resultado: Repo YA configurado + Jupyter NO corriendo - -Informar: -``` -Este repo tiene Jupyter configurado pero no está corriendo. -Ejecuta ./run-jupyter-lab.sh en otra terminal para iniciarlo. -``` -**DETENER AQUÍ** - -### Resultado: Puerto DESINCRONIZADO (PORT_DESYNC) - -El archivo `.jupyter-port` dice un puerto pero Jupyter no está corriendo ahí. - -**Opciones:** -1. Si Jupyter está corriendo en otro puerto → actualizar `.jupyter-port` y `.claude/settings.local.json` -2. Si Jupyter no está corriendo → ejecutar `./run-jupyter-lab.sh` (actualizará el puerto automáticamente) - -```bash -# Buscar en qué puerto está Jupyter realmente -pgrep -af "jupyter" | grep -oP 'port[= ]\K\d+' || echo "Jupyter no está corriendo" -``` - -### Resultado: Repo NO configurado → Continuar con PASO 1 - ---- - -## PASO 1: Detectar ruta de trabajo - -```bash -RUTA="${1:-.}" -cd "$RUTA" -pwd -``` - ---- - -## PASO 2: Verificar si Jupyter ya corre en ESTE repo - -```bash -# Buscar proceso jupyter con el directorio actual -REPO_PATH=$(pwd) -pgrep -af "jupyter" | grep -E "(lab|notebook)" | grep "$REPO_PATH" || echo "NO_JUPYTER" -``` - -- Si encuentra proceso → Informar "Jupyter ya está corriendo en este repo" y saltar a Paso 6 -- Si NO encuentra → Continuar - ---- - -## PASO 3: Detectar puerto libre (autodetección) - -```bash -# Encontrar primer puerto libre entre 8888-8899 -for port in 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899; do - if ! lsof -i:$port >/dev/null 2>&1; then - echo $port - break - fi -done -``` - -Guardar el puerto detectado para usarlo en los siguientes pasos. - ---- - -## PASO 4: Crear/Actualizar archivos del proyecto - -### 4a. Crear estructura si no existe - -```bash -mkdir -p .claude notebooks -``` - -### 4b. Crear `run-jupyter-lab.sh` con puerto autodetectado - -Crear el archivo con el PUERTO detectado en Paso 3: - -```bash -cat > run-jupyter-lab.sh << 'SCRIPT' -#!/bin/bash -# Jupyter Lab para colaboración Claude + Usuario -# Generado por /init-jupyter - -# Autodetectar puerto libre -find_free_port() { - for port in 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899; do - if ! lsof -i:$port >/dev/null 2>&1; then - echo $port - return - fi - done - echo 8888 -} - -PORT=${1:-$(find_free_port)} - -# Guardar puerto para que Claude lo lea -echo $PORT > .jupyter-port - -# Activar entorno si existe -source .venv/bin/activate 2>/dev/null || true - -echo "══════════════════════════════════════════════════════" -echo " Jupyter Lab iniciando en puerto $PORT" -echo "══════════════════════════════════════════════════════" -echo "" -echo " Abre: http://localhost:$PORT" -echo "" -echo " Claude se conectará al kernel cuando abras un notebook" -echo " Usa Ctrl+C para detener" -echo "" -echo "══════════════════════════════════════════════════════" - -jupyter lab \ - --port=$PORT \ - --no-browser \ - --NotebookApp.token='' \ - --NotebookApp.password='' \ - --NotebookApp.disable_check_xsrf=True \ - --ServerApp.allow_origin='*' \ - --ServerApp.root_dir="$(pwd)" -SCRIPT -chmod +x run-jupyter-lab.sh -``` - -### 4c. Crear/Actualizar `.claude/settings.local.json` (con MERGE) - -**IMPORTANTE: Usar ruta ABSOLUTA al ejecutable del venv local.** -**IMPORTANTE: Hacer MERGE para preservar otros MCPs existentes.** - -Usar el PUERTO detectado y la ruta absoluta: - -```bash -# Obtener ruta absoluta del proyecto -PROJECT_PATH=$(pwd) -PUERTO=8888 # Reemplazar con el puerto detectado en Paso 3 - -# Crear config de jupyter como JSON temporal -cat > /tmp/jupyter-mcp.json << EOF -{ - "mcpServers": { - "jupyter": { - "command": "${PROJECT_PATH}/.venv/bin/jupyter-mcp-server", - "args": [ - "--jupyter-url", "http://localhost:${PUERTO}", - "--start-new-runtime", "false" - ] - } - } -} -EOF - -# Merge: si existe settings.local.json, combinar; si no, crear nuevo -if [ -f .claude/settings.local.json ]; then - # Merge profundo: preserva otros MCPs, actualiza/añade jupyter - jq -s '.[0] * .[1] | .mcpServers = (.[0].mcpServers // {}) * (.[1].mcpServers // {})' \ - .claude/settings.local.json /tmp/jupyter-mcp.json > .claude/settings.local.json.tmp - mv .claude/settings.local.json.tmp .claude/settings.local.json - echo "settings.local.json actualizado (merge con config existente)" -else - # No existe, crear nuevo - mv /tmp/jupyter-mcp.json .claude/settings.local.json - echo "settings.local.json creado" -fi - -rm -f /tmp/jupyter-mcp.json -``` - -**NOTA:** La ruta absoluta es crítica. Si usas solo `jupyter-mcp-server`, Claude buscará en PATH global y fallará. - -### 4d. Añadir/Actualizar instrucciones en `.claude/CLAUDE.md` - -**IMPORTANTE**: Las reglas de Jupyter deben ir AL PRINCIPIO del archivo para que nuevas conversaciones las vean inmediatamente. - -**Lógica de inserción:** - -1. Verificar si existe `.claude/CLAUDE.md` -2. Si existe: - - Leer contenido actual - - Si NO contiene "JUPYTER HABILITADO" → prepend (añadir al principio) - - Si YA contiene → no modificar -3. Si no existe → crearlo con las reglas - -**Contenido a insertar AL PRINCIPIO:** - -```markdown -# JUPYTER HABILITADO EN ESTE REPO - -Este repositorio está configurado para exploración de datos con Jupyter + Claude. - -## Estado del entorno -- **Lanzador**: `./run-jupyter-lab.sh` -- **Puerto config**: ver `.jupyter-port` o `.claude/settings.local.json` -- **MCP**: jupyter-mcp-server configurado - -## Reglas OBLIGATORIAS para Claude - -### 1. SIEMPRE usar MCP jupyter para ejecutar código Python -- Las ejecuciones se ven en tiempo real en Jupyter Lab del usuario -- Compartimos variables y estado del kernel -- **NUNCA usar bash para ejecutar Python en este repo** - -### 2. Verificar Jupyter activo ANTES de ejecutar -```bash -pgrep -af "jupyter" | grep "$(pwd)" || cat .jupyter-port 2>/dev/null -``` -- Si no está activo → pedir al usuario: "Ejecuta `./run-jupyter-lab.sh` en otra terminal" - -### 3. Gestión de notebooks -- Si un notebook tiene >50 celdas → crear uno nuevo -- Nombrar descriptivamente: `01_exploracion.ipynb`, `02_limpieza.ipynb` -- Mantener notebooks enfocados en una tarea - -### 4. Antes de código pesado -- Avisar al usuario -- Usar `%%time` o `tqdm` para progreso - ---- - -``` - -**Comando bash para prepend:** - -```bash -# Si CLAUDE.md existe y NO tiene las reglas -if [ -f .claude/CLAUDE.md ]; then - if ! grep -q "JUPYTER HABILITADO" .claude/CLAUDE.md; then - # Prepend: crear temp con reglas + contenido original - cat > .claude/CLAUDE.md.tmp << 'JUPYTER_RULES' -[CONTENIDO DE REGLAS AQUÍ] -JUPYTER_RULES - cat .claude/CLAUDE.md >> .claude/CLAUDE.md.tmp - mv .claude/CLAUDE.md.tmp .claude/CLAUDE.md - fi -else - # Crear nuevo - cat > .claude/CLAUDE.md << 'JUPYTER_RULES' -[CONTENIDO DE REGLAS AQUÍ] -JUPYTER_RULES -fi -``` - ---- - -## PASO 5: Inicializar entorno Python si no existe - -### 5a. Si no existe `pyproject.toml`: - -```bash -uv init 2>/dev/null || true -uv venv 2>/dev/null || true -``` - -### 5b. Instalar dependencias de Jupyter (incluyendo MCP): - -**IMPORTANTE: jupyter-mcp-server SIEMPRE se instala en el venv local, NUNCA global.** - -```bash -source .venv/bin/activate 2>/dev/null || true -uv add jupyter jupyterlab jupyter-mcp-server pandas numpy matplotlib 2>/dev/null || pip install jupyter jupyterlab jupyter-mcp-server pandas numpy matplotlib - -# Verificar que MCP quedó instalado localmente -[ -f .venv/bin/jupyter-mcp-server ] && echo "MCP instalado en venv local OK" || echo "ERROR: MCP no instalado" -``` - ---- - -## PASO 6: Resumen final al usuario - -Mostrar: - -``` -═══════════════════════════════════════════════════════════════ - Entorno Jupyter configurado en: [RUTA] -═══════════════════════════════════════════════════════════════ - - Puerto asignado: [PUERTO] - MCP: .venv/bin/jupyter-mcp-server (LOCAL al proyecto) - - ┌─────────────────────────────────────────────────────────┐ - │ PASOS PARA ACTIVAR (orden importante): │ - │ │ - │ 1. SALIR de Claude Code: /exit o Ctrl+C │ - │ (necesario para que cargue el nuevo MCP) │ - │ │ - │ 2. En OTRA terminal, ejecuta: │ - │ cd [RUTA] && ./run-jupyter-lab.sh │ - │ │ - │ 3. Volver a entrar a Claude: │ - │ cd [RUTA] && claude │ - │ (ahora detectará el MCP de Jupyter) │ - │ │ - │ 4. Abre en navegador: http://localhost:[PUERTO] │ - │ │ - │ 5. Crea o abre un notebook y empieza a trabajar │ - └─────────────────────────────────────────────────────────┘ - - Archivos creados/actualizados: - ✓ run-jupyter-lab.sh (lanzador con autodetección de puerto) - ✓ .claude/settings.local.json (config MCP - merge con existente) - ✓ .claude/CLAUDE.md (reglas de trabajo al principio) - ✓ .venv/bin/jupyter-mcp-server (ejecutable MCP local) - - Verificación rápida del MCP: - $ ls -la .venv/bin/jupyter-mcp-server - - Si el MCP no funciona después de reiniciar Claude: - 1. Verifica que Jupyter está corriendo: pgrep -af jupyter - 2. Verifica puerto: cat .jupyter-port - 3. Verifica MCP existe: ls .venv/bin/jupyter-mcp-server - 4. Revisa config: cat .claude/settings.local.json - -═══════════════════════════════════════════════════════════════ -``` - ---- - -## Comandos útiles post-inicialización - -```bash -# Ver puerto actual -cat .jupyter-port - -# Verificar Jupyter corriendo -pgrep -af jupyter - -# Listar kernels activos -curl -s http://localhost:$(cat .jupyter-port)/api/kernels | jq - -# Listar notebooks abiertos -curl -s http://localhost:$(cat .jupyter-port)/api/sessions | jq -``` - ---- - -## Notas para uso frecuente - -- El script `run-jupyter-lab.sh` autodetecta puerto cada vez que se ejecuta -- El archivo `.jupyter-port` siempre tiene el puerto actual -- Si cambias de puerto, actualiza `.claude/settings.local.json` o recarga Claude -- Las reglas en `CLAUDE.md` se mantienen entre sesiones +El script instala `jupyter-mcp-server` en `.venv/bin/` del proyecto, NUNCA globalmente. +Si detecta instalación global, la elimina automáticamente.