merge: quick/init-jupyter-bash-automation — automatizar skill con bash script
This commit is contained in:
@@ -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
|
|
||||||
|
|||||||
Executable
+397
@@ -0,0 +1,397 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# setup-jupyter.sh - Automatiza la configuración de Jupyter + MCP para Claude
|
||||||
|
# Uso: ./setup-jupyter.sh [ruta-proyecto]
|
||||||
|
# Generado para el skill /init-jupyter
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colores para output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# FUNCIONES AUXILIARES
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||||
|
log_ok() { echo -e "${GREEN}[OK]${NC} $1"; }
|
||||||
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||||
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# PASO 0: CAMBIAR AL DIRECTORIO DEL PROYECTO
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
RUTA="${1:-.}"
|
||||||
|
cd "$RUTA" || { log_error "No se pudo acceder a: $RUTA"; exit 1; }
|
||||||
|
PROJECT_PATH=$(pwd)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo " SETUP JUPYTER + MCP para Claude"
|
||||||
|
echo " Proyecto: $PROJECT_PATH"
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# PASO 1: VERIFICACIONES DE ESTADO
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
log_info "Verificando estado actual..."
|
||||||
|
|
||||||
|
# Variables de estado
|
||||||
|
MCP_LOCAL=false
|
||||||
|
REPO_CONFIG=false
|
||||||
|
JUPYTER_RUNNING=false
|
||||||
|
RULES_OK=false
|
||||||
|
GLOBAL_MCP=false
|
||||||
|
CURRENT_PORT=""
|
||||||
|
|
||||||
|
# 1. MCP instalado localmente
|
||||||
|
if [ -f .venv/bin/jupyter-mcp-server ]; then
|
||||||
|
MCP_LOCAL=true
|
||||||
|
log_ok "MCP instalado en .venv/bin/"
|
||||||
|
else
|
||||||
|
log_warn "MCP no instalado localmente"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Repo configurado (.mcp.json con jupyter)
|
||||||
|
if [ -f .mcp.json ] && grep -q "jupyter" .mcp.json 2>/dev/null; then
|
||||||
|
REPO_CONFIG=true
|
||||||
|
log_ok "Repo configurado (.mcp.json tiene jupyter)"
|
||||||
|
else
|
||||||
|
log_warn "Repo no configurado para Jupyter"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Jupyter corriendo en este repo
|
||||||
|
if pgrep -af "jupyter" 2>/dev/null | grep -q "$PROJECT_PATH"; then
|
||||||
|
JUPYTER_RUNNING=true
|
||||||
|
CURRENT_PORT=$(pgrep -af "jupyter" | grep "$PROJECT_PATH" | grep -oP 'port[= ]\K\d+' | head -1)
|
||||||
|
[ -z "$CURRENT_PORT" ] && CURRENT_PORT=$(cat .jupyter-port 2>/dev/null || echo "desconocido")
|
||||||
|
log_ok "Jupyter corriendo en puerto $CURRENT_PORT"
|
||||||
|
else
|
||||||
|
log_warn "Jupyter no está corriendo"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Reglas en CLAUDE.md
|
||||||
|
if [ -f .claude/CLAUDE.md ] && grep -q "JUPYTER HABILITADO" .claude/CLAUDE.md 2>/dev/null; then
|
||||||
|
RULES_OK=true
|
||||||
|
log_ok "Reglas Jupyter en CLAUDE.md"
|
||||||
|
else
|
||||||
|
log_warn "Reglas Jupyter no configuradas"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 5. Instalación global (problemática)
|
||||||
|
if [ -f ~/.local/bin/jupyter-mcp-server ]; then
|
||||||
|
GLOBAL_MCP=true
|
||||||
|
log_warn "Existe instalación GLOBAL de jupyter-mcp-server (se eliminará)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# DECISIÓN: ¿Ya está todo configurado?
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
if $MCP_LOCAL && $REPO_CONFIG && $RULES_OK; then
|
||||||
|
if $JUPYTER_RUNNING; then
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
log_ok "TODO LISTO - Jupyter configurado y corriendo en puerto $CURRENT_PORT"
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
echo "STATUS: READY"
|
||||||
|
echo "PORT: $CURRENT_PORT"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
log_ok "CONFIGURADO - Solo falta iniciar Jupyter"
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
echo "Ejecuta en otra terminal:"
|
||||||
|
echo " cd $PROJECT_PATH && ./run-jupyter-lab.sh"
|
||||||
|
echo ""
|
||||||
|
echo "STATUS: CONFIGURED_NOT_RUNNING"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# PASO 2: ELIMINAR INSTALACIÓN GLOBAL SI EXISTE
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
if $GLOBAL_MCP; then
|
||||||
|
log_info "Eliminando instalación global de jupyter-mcp-server..."
|
||||||
|
uv tool uninstall jupyter-mcp-server 2>/dev/null || true
|
||||||
|
pip uninstall -y jupyter-mcp-server 2>/dev/null || true
|
||||||
|
rm -f ~/.local/bin/jupyter-mcp-server
|
||||||
|
|
||||||
|
if [ -f ~/.local/bin/jupyter-mcp-server ]; then
|
||||||
|
log_error "No se pudo eliminar instalación global"
|
||||||
|
else
|
||||||
|
log_ok "Instalación global eliminada"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# PASO 3: DETECTAR PUERTO LIBRE
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
PUERTO=$(find_free_port)
|
||||||
|
log_info "Puerto asignado: $PUERTO"
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# PASO 4: CREAR ESTRUCTURA DE CARPETAS
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
log_info "Creando estructura de carpetas..."
|
||||||
|
mkdir -p .claude notebooks
|
||||||
|
log_ok "Carpetas .claude/ y notebooks/ creadas"
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# PASO 5: CREAR run-jupyter-lab.sh
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
log_info "Creando run-jupyter-lab.sh..."
|
||||||
|
|
||||||
|
cat > run-jupyter-lab.sh << 'SCRIPT'
|
||||||
|
#!/bin/bash
|
||||||
|
# Jupyter Lab para colaboración Claude + Usuario
|
||||||
|
# Generado por /init-jupyter
|
||||||
|
# REQUIERE: jupyter-collaboration instalado para que funcione el MCP
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Verificar que jupyter-collaboration está instalado
|
||||||
|
if ! python -c "import jupyter_collaboration" 2>/dev/null; then
|
||||||
|
echo "ERROR: jupyter-collaboration no está instalado"
|
||||||
|
echo "Instala con: uv add jupyter-collaboration"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "══════════════════════════════════════════════════════"
|
||||||
|
echo " Jupyter Lab + Colaboración iniciando en puerto $PORT"
|
||||||
|
echo "══════════════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
echo " Abre: http://localhost:$PORT"
|
||||||
|
echo ""
|
||||||
|
echo " Claude se conectará al kernel cuando abras un notebook"
|
||||||
|
echo " Colaboración en tiempo real ACTIVADA"
|
||||||
|
echo " Usa Ctrl+C para detener"
|
||||||
|
echo ""
|
||||||
|
echo "══════════════════════════════════════════════════════"
|
||||||
|
|
||||||
|
jupyter lab \
|
||||||
|
--port=$PORT \
|
||||||
|
--no-browser \
|
||||||
|
--ServerApp.token='' \
|
||||||
|
--ServerApp.password='' \
|
||||||
|
--ServerApp.disable_check_xsrf=True \
|
||||||
|
--ServerApp.allow_origin='*' \
|
||||||
|
--ServerApp.root_dir="$(pwd)" \
|
||||||
|
--YDocExtension.ystore_class='ypy_websocket.ystore.TempFileYStore' \
|
||||||
|
--collaborative
|
||||||
|
SCRIPT
|
||||||
|
|
||||||
|
chmod +x run-jupyter-lab.sh
|
||||||
|
log_ok "run-jupyter-lab.sh creado"
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# PASO 6: CREAR/ACTUALIZAR .mcp.json
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
log_info "Configurando .mcp.json..."
|
||||||
|
|
||||||
|
# Crear config temporal
|
||||||
|
cat > /tmp/jupyter-mcp.json << EOF
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"jupyter": {
|
||||||
|
"command": "${PROJECT_PATH}/.venv/bin/jupyter-mcp-server",
|
||||||
|
"args": [
|
||||||
|
"--runtime-url", "http://localhost:${PUERTO}",
|
||||||
|
"--start-new-runtime", "false"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Merge o crear
|
||||||
|
if [ -f .mcp.json ]; then
|
||||||
|
if command -v jq >/dev/null 2>&1; then
|
||||||
|
jq -s '.[0] * .[1] | .mcpServers = (.[0].mcpServers // {}) * (.[1].mcpServers // {})' \
|
||||||
|
.mcp.json /tmp/jupyter-mcp.json > .mcp.json.tmp
|
||||||
|
mv .mcp.json.tmp .mcp.json
|
||||||
|
log_ok ".mcp.json actualizado (merge)"
|
||||||
|
else
|
||||||
|
log_warn "jq no disponible, sobrescribiendo .mcp.json"
|
||||||
|
mv /tmp/jupyter-mcp.json .mcp.json
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
mv /tmp/jupyter-mcp.json .mcp.json
|
||||||
|
log_ok ".mcp.json creado"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f /tmp/jupyter-mcp.json
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# PASO 7: ACTUALIZAR .claude/CLAUDE.md
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
log_info "Configurando reglas en .claude/CLAUDE.md..."
|
||||||
|
|
||||||
|
JUPYTER_RULES='# 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 `.mcp.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
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
'
|
||||||
|
|
||||||
|
if [ -f .claude/CLAUDE.md ]; then
|
||||||
|
if ! grep -q "JUPYTER HABILITADO" .claude/CLAUDE.md; then
|
||||||
|
# Prepend
|
||||||
|
echo "$JUPYTER_RULES" > .claude/CLAUDE.md.tmp
|
||||||
|
cat .claude/CLAUDE.md >> .claude/CLAUDE.md.tmp
|
||||||
|
mv .claude/CLAUDE.md.tmp .claude/CLAUDE.md
|
||||||
|
log_ok "Reglas añadidas al principio de CLAUDE.md"
|
||||||
|
else
|
||||||
|
log_ok "Reglas ya existían en CLAUDE.md"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$JUPYTER_RULES" > .claude/CLAUDE.md
|
||||||
|
log_ok "CLAUDE.md creado con reglas"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# PASO 8: INICIALIZAR ENTORNO PYTHON E INSTALAR DEPENDENCIAS
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
log_info "Configurando entorno Python..."
|
||||||
|
|
||||||
|
# Crear venv si no existe
|
||||||
|
if [ ! -d .venv ]; then
|
||||||
|
log_info "Creando venv..."
|
||||||
|
uv venv 2>/dev/null || python -m venv .venv
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Activar venv
|
||||||
|
source .venv/bin/activate 2>/dev/null || true
|
||||||
|
|
||||||
|
# Instalar dependencias
|
||||||
|
log_info "Instalando dependencias (jupyter, mcp, colaboración)..."
|
||||||
|
if command -v uv >/dev/null 2>&1; then
|
||||||
|
# Inicializar pyproject.toml si no existe
|
||||||
|
[ ! -f pyproject.toml ] && uv init 2>/dev/null || true
|
||||||
|
uv add jupyter jupyterlab jupyter-collaboration jupyter-mcp-server pandas numpy matplotlib 2>/dev/null || \
|
||||||
|
pip install jupyter jupyterlab jupyter-collaboration jupyter-mcp-server pandas numpy matplotlib
|
||||||
|
else
|
||||||
|
pip install jupyter jupyterlab jupyter-collaboration jupyter-mcp-server pandas numpy matplotlib
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verificar instalación
|
||||||
|
echo ""
|
||||||
|
if [ -f .venv/bin/jupyter-mcp-server ]; then
|
||||||
|
log_ok "jupyter-mcp-server instalado en venv local"
|
||||||
|
else
|
||||||
|
log_error "jupyter-mcp-server NO instalado"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if python -c "import jupyter_collaboration" 2>/dev/null; then
|
||||||
|
log_ok "jupyter-collaboration instalado"
|
||||||
|
else
|
||||||
|
log_warn "jupyter-collaboration no instalado"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# RESUMEN FINAL
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo " CONFIGURACIÓN COMPLETADA"
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
echo " Proyecto: $PROJECT_PATH"
|
||||||
|
echo " Puerto: $PUERTO"
|
||||||
|
echo ""
|
||||||
|
echo " Archivos creados/actualizados:"
|
||||||
|
echo " ✓ run-jupyter-lab.sh"
|
||||||
|
echo " ✓ .mcp.json"
|
||||||
|
echo " ✓ .claude/CLAUDE.md"
|
||||||
|
echo " ✓ .venv/bin/jupyter-mcp-server"
|
||||||
|
echo ""
|
||||||
|
echo " ┌─────────────────────────────────────────────────────────┐"
|
||||||
|
echo " │ PASOS SIGUIENTES: │"
|
||||||
|
echo " │ │"
|
||||||
|
echo " │ 1. SALIR de Claude Code: /exit o Ctrl+C │"
|
||||||
|
echo " │ (necesario para cargar el nuevo MCP) │"
|
||||||
|
echo " │ │"
|
||||||
|
echo " │ 2. En OTRA terminal: │"
|
||||||
|
echo " │ cd $PROJECT_PATH && ./run-jupyter-lab.sh │"
|
||||||
|
echo " │ │"
|
||||||
|
echo " │ 3. Volver a entrar a Claude: │"
|
||||||
|
echo " │ cd $PROJECT_PATH && claude │"
|
||||||
|
echo " │ │"
|
||||||
|
echo " │ 4. Abrir en navegador: http://localhost:$PUERTO │"
|
||||||
|
echo " └─────────────────────────────────────────────────────────┘"
|
||||||
|
echo ""
|
||||||
|
echo "STATUS: CONFIGURED"
|
||||||
|
echo "PORT: $PUERTO"
|
||||||
Reference in New Issue
Block a user