feat: mejorar skill init-jupyter con detección inteligente

- Añadir PASO 0 para detectar estado del repo (MCP instalado, repo configurado, Jupyter corriendo)
- Reglas de Jupyter ahora se insertan al PRINCIPIO de CLAUDE.md
- Nuevas conversaciones detectan automáticamente si el repo tiene Jupyter habilitado
- Autodetección de puerto libre (8888-8899)
- Script run-jupyter-lab.sh guarda puerto en .jupyter-port
This commit is contained in:
2026-03-25 23:41:10 +01:00
parent f6702e6371
commit e29eef47f1
+275 -176
View File
@@ -1,138 +1,156 @@
---
name: init-jupyter
description: Inicializa o inicia Jupyter Lab via MCP con kernel compartido. Detecta notebooks existentes automáticamente.
description: Inicializa entorno Jupyter para exploración de datos con MCP compartido. Autodetecta puerto y configura repo.
argument-hint: [ruta-proyecto]
disable-model-invocation: true
user-invocable: true
allowed-tools: Bash, Read, Write, Edit, Glob
---
# Inicializar/Iniciar Proyecto Jupyter via MCP
# Inicializar Entorno Jupyter para Data Science
Este skill gestiona entornos Jupyter Lab integrados con Claude via MCP. Detecta automáticamente si ya existe un proyecto configurado.
Skill para preparar cualquier repo para exploración de datos con Jupyter + Claude colaborando en kernel compartido.
## Modo de Colaboración (Kernel Compartido)
## PASO 0: Verificar estado actual del repo
**IMPORTANTE**: Para que las ejecuciones de Claude sean visibles en Jupyter Lab, se debe usar el **mismo kernel** que el notebook abierto. Esto permite:
- Ver las ejecuciones de Claude en tiempo real en Jupyter Lab
- Compartir variables y estado entre Claude y el usuario
- Colaboración real entre ambos en el mismo notebook
## Flujo de decisión
### 1. Detectar notebooks existentes
Buscar archivos `.ipynb` en:
- Raíz del proyecto
- Carpeta `notebooks/`
- Cualquier subcarpeta
**Ejecutar estas comprobaciones primero:**
```bash
find [ruta] -name "*.ipynb" -type f 2>/dev/null | head -5
# 1. ¿MCP instalado globalmente?
which 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"
```
### 2. Si HAY notebooks existentes → Conectar o Iniciar
### Resultado: MCP NO instalado
**2a. Verificar que MCP está configurado con kernel compartido**
- Comprobar si existe `.claude/settings.local.json` con configuración de jupyter
- Verificar que incluye `--start-new-runtime false` para colaboración
- Si no existe o falta la configuración, crearlo (ver paso 3f)
**2b. Verificar que jupyter-mcp-server está instalado**
```bash
which jupyter-mcp-server || uv tool install jupyter-mcp-server
```
**2c. Verificar si el script run-jupyter-lab.sh existe**
- Si no existe, crearlo (ver paso 3g)
**2d. Detectar si Jupyter ya está corriendo**
```bash
# Verificar si hay un servidor Jupyter activo en el puerto esperado
curl -s http://localhost:8888/api/status 2>/dev/null && echo "Jupyter activo" || echo "Jupyter no detectado"
```
**2e. Si Jupyter YA está corriendo:**
- **NO arrancarlo de nuevo**
- Informar al usuario: "Jupyter Lab detectado en http://localhost:8888"
- Claude puede conectarse directamente via MCP al kernel existente
- El usuario tiene libertad total para gestionar Jupyter manualmente
**2f. Si Jupyter NO está corriendo:**
- Preguntar al usuario si quiere que Claude lo arranque o prefiere hacerlo manualmente con `./run-jupyter-lab.sh`
- Si el usuario quiere arrancarlo:
```bash
source .venv/bin/activate 2>/dev/null || true
jupyter lab --no-browser --NotebookApp.token='' --NotebookApp.password='' --NotebookApp.disable_check_xsrf=True
```
**2g. Informar al usuario** que puede usar las herramientas MCP de Jupyter desde Claude.
### 3. Si NO hay notebooks → Inicializar proyecto completo
Seguir estos pasos:
**3a. Validar ubicación**
- Si se proporciona `$1`, usar esa ruta
- Si no, usar el directorio actual
**3b. Inicializar proyecto con uv** (si no existe pyproject.toml)
```bash
cd [ruta] && uv init
```
**3c. Crear entorno virtual**
```bash
uv venv
```
**3d. Instalar dependencias**
```bash
uv add jupyter jupyter-collaboration
```
**3e. Instalar jupyter-mcp-server**
```bash
uv tool install jupyter-mcp-server
```
**3f. Configurar MCP para Claude (con kernel compartido)**
Crear o actualizar `.claude/settings.local.json`:
```json
{
"mcpServers": {
"jupyter": {
"command": "jupyter-mcp-server",
"args": [
"--jupyter-url", "http://localhost:8888",
"--start-new-runtime", "false"
]
}
}
}
Informar:
```
MCP jupyter-mcp-server instalado.
Ejecuta /exit y vuelve a entrar para recargar.
Después ejecuta /init-jupyter de nuevo.
```
**DETENER AQUÍ**
### 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: Repo NO configurado → Continuar con PASO 1
---
## PASO 1: Detectar ruta de trabajo
```bash
RUTA="${1:-.}"
cd "$RUTA"
pwd
```
**Parámetros clave:**
- `--jupyter-url`: URL del servidor Jupyter (por defecto localhost:8888)
- `--start-new-runtime false`: **CRÍTICO** - Conecta al kernel existente en lugar de crear uno nuevo
---
**3g. Crear script `run-jupyter-lab.sh`**
## 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:
Crear un script ejecutable para que el usuario pueda arrancar Jupyter manualmente:
```bash
cat > run-jupyter-lab.sh << 'SCRIPT'
#!/bin/bash
# Script para iniciar Jupyter Lab con configuración de colaboración
# El usuario puede arrancarlo manualmente y Claude se conectará al kernel existente
# Jupyter Lab para colaboración Claude + Usuario
# Generado por /init-jupyter
PORT=${1:-8888}
# 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 "Iniciando Jupyter Lab en puerto $PORT..."
echo "Abre http://localhost:$PORT en tu navegador"
echo "══════════════════════════════════════════════════════"
echo " Jupyter Lab iniciando en puerto $PORT"
echo "══════════════════════════════════════════════════════"
echo ""
echo "Claude se conectará automáticamente al kernel cuando abras un notebook."
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 \
@@ -140,93 +158,174 @@ jupyter lab \
--NotebookApp.token='' \
--NotebookApp.password='' \
--NotebookApp.disable_check_xsrf=True \
--ServerApp.allow_origin='*'
--ServerApp.allow_origin='*' \
--ServerApp.root_dir="$(pwd)"
SCRIPT
chmod +x run-jupyter-lab.sh
```
**3h. Crear carpeta notebooks** (opcional)
### 4c. Crear/Actualizar `.claude/settings.local.json`
Usar el PUERTO detectado:
```bash
mkdir -p notebooks
```
**3i. Iniciar Jupyter via MCP**
```bash
source .venv/bin/activate
jupyter lab --no-browser --NotebookApp.token='' --NotebookApp.password='' --NotebookApp.disable_check_xsrf=True
```
## Ejemplos de uso
**Iniciar/inicializar en directorio actual:**
```bash
/init-jupyter
```
**Iniciar/inicializar en ruta específica:**
```bash
/init-jupyter ~/proyectos/mi-analisis
```
## Flujo de trabajo colaborativo (Kernel Compartido)
### Cómo funciona la colaboración
1. **Usuario inicia Jupyter Lab** (via este skill)
2. **Usuario abre un notebook** en Jupyter Lab → se inicia un kernel
3. **Claude se conecta al MISMO kernel** via MCP con `--start-new-runtime false`
4. **Ambos comparten**:
- El mismo estado de variables
- El mismo historial de ejecución
- Las salidas son visibles para ambos en tiempo real
### Pasos para colaborar
**Opción A - Usuario arranca Jupyter manualmente (recomendado):**
1. Ejecutar `./run-jupyter-lab.sh` (o `./run-jupyter-lab.sh 8889` para otro puerto)
2. Abrir el navegador en http://localhost:8888
3. Abrir o crear el notebook deseado
4. Ejecutar `/init-jupyter` - Claude detectará Jupyter y se conectará al kernel existente
5. **Claude ya puede ejecutar celdas** y el usuario verá las ejecuciones en su Jupyter Lab
**Opción B - Claude arranca Jupyter:**
1. Ejecutar `/init-jupyter`
2. Si no hay Jupyter corriendo, Claude lo arrancará
3. Abrir el navegador en http://localhost:8888
4. Abrir o crear el notebook deseado
5. **Claude ya puede ejecutar celdas**
### Obtener kernel ID específico (opcional)
Si hay múltiples kernels corriendo, puedes obtener el ID del kernel activo:
```bash
curl -s http://localhost:8888/api/kernels | jq '.[0].id'
```
Y configurar MCP con ese kernel específico:
```json
cat > .claude/settings.local.json << EOF
{
"mcpServers": {
"jupyter": {
"command": "jupyter-mcp-server",
"args": [
"--jupyter-url", "http://localhost:8888",
"--runtime-id", "KERNEL_ID_AQUI"
"--jupyter-url", "http://localhost:PUERTO",
"--start-new-runtime", "false"
]
}
}
}
EOF
```
## Notas importantes
(Reemplazar PUERTO por el valor real detectado)
- **Siempre usa MCP**: Jupyter se ejecuta siempre de forma que Claude pueda interactuar via MCP
- **Kernel compartido por defecto**: Con `--start-new-runtime false`, Claude usa el kernel existente
- **Script `run-jupyter-lab.sh`**: Se crea automáticamente para que el usuario pueda arrancar Jupyter cuando quiera
- **Detección automática**: Claude detecta si Jupyter ya está corriendo y no lo arranca de nuevo
- **Libertad del usuario**: El usuario puede gestionar Jupyter manualmente, Claude se adapta
- Si detecta notebooks existentes, NO reinicializa el proyecto, solo conecta o inicia Jupyter
- Si el proyecto ya tiene `pyproject.toml`, no ejecuta `uv init`
- La configuración MCP se guarda en `.claude/settings.local.json` del proyecto
- El servidor MCP permite a Claude crear, editar y ejecutar celdas de notebooks
- **jupyter-collaboration** ya está incluido en las dependencias para sincronización en tiempo real
### 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:
```bash
source .venv/bin/activate 2>/dev/null || true
uv add jupyter jupyterlab pandas numpy matplotlib 2>/dev/null || pip install jupyter jupyterlab pandas numpy matplotlib
```
---
## PASO 6: Resumen final al usuario
Mostrar:
```
═══════════════════════════════════════════════════════════════
Entorno Jupyter configurado en: [RUTA]
═══════════════════════════════════════════════════════════════
Puerto asignado: [PUERTO]
Para empezar:
1. En otra terminal ejecuta: ./run-jupyter-lab.sh
2. Abre http://localhost:[PUERTO] en tu navegador
3. Crea o abre un notebook
4. Yo me conecto automáticamente al kernel compartido
Archivos creados/actualizados:
- run-jupyter-lab.sh (lanzador)
- .claude/settings.local.json (config MCP)
- .claude/CLAUDE.md (reglas de trabajo)
═══════════════════════════════════════════════════════════════
```
---
## 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