Files
repo_Claude/.claude/skills/init-jupyter/SKILL.md
T
egutierrez 66bfdd4ce9 feat: mejorar skill init-jupyter con validaciones robustas
Añade verificaciones y manejo de casos edge para trabajo multi-repo:

- Verificación de puerto desincronizado (PORT_DESYNC)
- Detección y limpieza de instalación global de MCP
- Merge de settings.local.json con jq para preservar MCPs existentes
- Resumen final mejorado con troubleshooting
2026-03-25 23:58:18 +01:00

14 KiB

name, description, argument-hint, disable-model-invocation, user-invocable, allowed-tools
name description argument-hint disable-model-invocation user-invocable allowed-tools
init-jupyter Inicializa entorno Jupyter para exploración de datos con MCP compartido. Autodetecta puerto y configura repo.
ruta-proyecto
true true Bash, Read, Write, Edit, Glob

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

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

PASO 0: Verificar estado actual del repo

Ejecutar estas comprobaciones primero:

# 1. ¿MCP instalado en el venv LOCAL del proyecto?
[ -f .venv/bin/jupyter-mcp-server ] && echo "MCP_OK" || echo "MCP_NO"

# 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"

Resultado: Instalación GLOBAL detectada (GLOBAL_MCP_EXISTS)

Eliminar inmediatamente para evitar conflictos:

# 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

# Verificar eliminación
[ -f ~/.local/bin/jupyter-mcp-server ] && echo "ERROR: No se pudo eliminar" || echo "Instalación global eliminada OK"

Continuar con instalación local.

Resultado: MCP NO instalado

IMPORTANTE: NUNCA instalar jupyter-mcp-server globalmente. Siempre en el venv local.

# Crear venv si no existe
[ -d .venv ] || uv venv

# 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)
# 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

RUTA="${1:-.}"
cd "$RUTA"
pwd

PASO 2: Verificar si Jupyter ya corre en ESTE repo

# 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)

# 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

mkdir -p .claude notebooks

4b. Crear run-jupyter-lab.sh con puerto autodetectado

Crear el archivo con el PUERTO detectado en Paso 3:

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:

# 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:

# 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:

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.

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

# 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