refactor: simplificar SKILL.md delegando trabajo al script bash

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.
This commit is contained in:
2026-03-26 00:21:34 +01:00
parent 3ae6268e4c
commit e38f100189
+31 -407
View File
@@ -4,431 +4,55 @@ description: Inicializa entorno Jupyter para exploración de datos con MCP compa
argument-hint: [ruta-proyecto] argument-hint: [ruta-proyecto]
disable-model-invocation: true disable-model-invocation: true
user-invocable: true user-invocable: true
allowed-tools: Bash, Read, Write, Edit, Glob allowed-tools: Bash, Read
--- ---
# Inicializar Entorno Jupyter para Data Science # Inicializar Entorno Jupyter para Data Science
Skill para preparar cualquier repo para exploración de datos con Jupyter + Claude colaborando en kernel compartido. 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: **Todo el trabajo está automatizado en `setup-jupyter.sh`.** Solo ejecuta el script y comunica el resultado.
- 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 ### Paso único: Ejecutar el script
**Ejecutar estas comprobaciones primero:**
```bash ```bash
# 1. ¿MCP instalado en el venv LOCAL del proyecto? # Obtener ruta del script (está junto a este SKILL.md)
[ -f .venv/bin/jupyter-mcp-server ] && echo "MCP_OK" || echo "MCP_NO" SKILL_DIR="$HOME/DataProyects/repo_Claude/.claude/skills/init-jupyter"
# 2. ¿Repo ya configurado para Jupyter? # Ejecutar con la ruta del proyecto (argumento del skill o directorio actual)
[ -f .claude/settings.local.json ] && grep -q "jupyter" .claude/settings.local.json && echo "REPO_CONFIG_OK" || echo "REPO_NO_CONFIG" bash "$SKILL_DIR/setup-jupyter.sh" "${1:-.}"
# 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) ### Interpretar el resultado
**Eliminar inmediatamente para evitar conflictos:** El script imprime una línea `STATUS:` al final:
```bash | STATUS | Significado | Qué decir al usuario |
# Eliminar instalación global |--------|-------------|---------------------|
uv tool uninstall jupyter-mcp-server 2>/dev/null || pip uninstall -y jupyter-mcp-server 2>/dev/null | `READY` | Todo configurado y Jupyter corriendo | "Jupyter ya está listo. Puedes empezar a trabajar con notebooks via MCP." |
rm -f ~/.local/bin/jupyter-mcp-server | `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 ### Si hay errores
[ -f ~/.local/bin/jupyter-mcp-server ] && echo "ERROR: No se pudo eliminar" || echo "Instalación global eliminada OK"
```
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 ## Regla crítica: MCP siempre local
# Crear venv si no existe
[ -d .venv ] || uv venv
# Instalar MCP en el venv local del proyecto El script instala `jupyter-mcp-server` en `.venv/bin/` del proyecto, NUNCA globalmente.
source .venv/bin/activate Si detecta instalación global, la elimina automáticamente.
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