| name | ec2-remote-access |
| description | Conecta una máquina nueva (Mac, Linux, Windows/WSL) a tu stack de Claude Code corriendo
en un EC2 vía SSH + Tailscale + tmux persistente. Te guía paso a paso: detecta tu OS,
instala Tailscale, configura SSH keys, crea aliases, verifica la conexión. Una vez
configurado, el comando "ec2" desde cualquier terminal te conecta a Claude Code remoto
exactamente igual que si estuviera local. Funciona incluso si tu Mac se cae o cambias
de WiFi (tmux mantiene la sesión viva en EC2). Incluye runbook de persistencia
server-side que DETECTA el patrón de la máquina (systemd system-level vs user-level +
lingering) en vez de asumir, idempotente y multi-proyecto.
|
| triggers | ["/ec2-remote-access","/ec2-setup","conectar a mi EC2","configurar máquina nueva para EC2","remote claude code","tailscale ssh setup","abrir claude en otra compu","terminal permanente en antigravity","conectar antigravity al ec2","terminal del ec2 en vscode/cursor"] |
| tools | ["exec","read","write"] |
| distribute-to | ["claude"] |
/ec2-remote-access — guía interactiva (modo CLIENTE)
Tu trabajo cuando se invoca este skill: acompañar al usuario paso a paso desde una máquina nueva hasta poder abrir Claude Code corriendo en su EC2 con un solo comando (ec2-tmux).
SCOPE de este skill — IMPORTANTE
- ✅ Cubre el lado CLIENTE (Mac/Linux/Windows que se conecta vía SSH a un EC2)
- ✅ Incluye el runbook de persistencia server-side (sección "Persistencia del Control Remote") — DOS patrones (system-level vs user-level) que el skill DEBE detectar, no asumir
- ❌ El bootstrap inicial completo del EC2 sigue en
bootstrap.sh en el mismo repo
- 🔧 Para auto-diagnóstico/healing post-instalación:
verify.sh --fix en el EC2
Antes de empezar, pregunta al usuario:
"¿Ya tienes el EC2 servidor configurado con Claude Code? Si NO → debes correr primero bootstrap.sh EN el EC2 (no este skill). Si SÍ, o si solo quieres SSH directo además del Pinned en Desktop, sigamos."
Si el usuario solo quiere la sesión <NAME>-Permanent pinned en Claude Code Desktop (sin SSH manual), no necesita este skill — solo necesita bootstrap.sh ejecutado en el EC2. Aclara esto si parece confundido.
No leas todos los pasos y los ejecutes en bloque. Ve paso por paso, verificando que cada uno funcionó antes de pasar al siguiente. Si algo falla, ve directo a la sección de troubleshooting.
Persistencia del Control Remote en el EC2 — DETECTAR patrón, no asumir
Aprendido en el EC2 de JPC (2026-06-22). Esto es lado-SERVIDOR: cómo dejar el control remote de Claude corriendo en el EC2 de forma permanente y multi-proyecto. Complementa a bootstrap.sh. Regla central: existen DOS patrones válidos de persistencia; el skill DEBE detectar cuál usa la máquina y adaptarse — nunca asumir ni imponer uno.
PATRÓN 1 — system-level (ej. jarvis-v3): claude-headless.service de sistema, Restart=always, RestartSec=15, WantedBy=multi-user.target. Requiere root (sudo).
PATRÓN 2 — user-level (ej. EC2 de JPC): servicios systemd --user + loginctl enable-linger <user> para sobrevivir reboot sin login. Type=forking, envuelve tmux, WantedBy=default.target. No requiere root, más limpio.
Runbook (control remote permanente, multi-proyecto, idempotente)
0. Cuenta correcta. Verifica que la cuenta de Anthropic logueada sea la de ESE EC2. Si no coincide, PARA y avisa.
1. DETECTAR estado (antes de crear nada — crítico):
systemctl list-units | grep -i claude
systemctl --user list-units | grep -i claude
tmux ls
loginctl show-user "$(whoami)" | grep Linger
Identifica qué patrón (system o user) ya usa la máquina, y qué control-remotes / sesiones existen.
2. RAMIFICAR según lo detectado:
- Máquina limpia (nada corriendo) → usa patrón user-level + lingering por default (más limpio, sin root).
- Máquina con servicios existentes → REUSAR su patrón. Si usa
--user, sigue con --user. Si usa system, sigue system. NUNCA mezclar system + user.
3. Detectar huecos: sesiones tmux sueltas sin servicio systemd (mueren en reboot) → crea solo el servicio faltante, con el patrón que ya usa la máquina.
4. Idempotencia: nunca dupliques services ni sesiones. Reusa nombres existentes. Cubre claude-remote, claude-headless, claude-<proyecto>.
5. Detectar drift: si un .service no refleja el comando real corriendo (ej. le falta --resume <sessionId>), avísalo y ofrece alinearlo — no lo cambies en silencio.
6. TTY + red: envuelve en tmux (--remote-control requiere pseudo-TTY). Solo conexión saliente al relay; NUNCA abras puertos de entrada.
7. Verificar + reportar: systemctl [--user] status, confirma supervivencia a reboot (lingering si es user-level), y reporta nombres de service/sesión + comando de reconexión.
REGLA DE ORO: default no-destructivo. Pregunta antes de tocar sesiones con trabajo activo. Detecta y adáptate al patrón de la máquina en vez de imponer uno.
Plantillas de service
Patrón 1 — system (requiere sudo): /etc/systemd/system/claude-headless.service
[Unit]
Description=Claude Code headless control-remote
After=network-online.target
[Service]
Type=simple
User=ec2-user
ExecStart=/usr/bin/tmux new-session -d -s claude '<comando claude --remote-control>'
Restart=always
RestartSec=15
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload && sudo systemctl enable --now claude-headless
Patrón 2 — user (sin root, PREFERIDO en máquina limpia): ~/.config/systemd/user/claude-<proyecto>.service
[Unit]
Description=Claude Code control-remote (<proyecto>)
After=default.target
[Service]
Type=forking
ExecStart=/usr/bin/tmux new-session -d -s claude-<proyecto> '<comando claude --remote-control>'
ExecStop=/usr/bin/tmux kill-session -t claude-<proyecto>
Restart=always
RestartSec=15
[Install]
WantedBy=default.target
loginctl enable-linger "$(whoami)"
systemctl --user daemon-reload
systemctl --user enable --now claude-<proyecto>
Multi-proyecto: una sesión tmux con N ventanas (una por proyecto), o un service claude-<proyecto> por proyecto — pero siempre dentro del MISMO patrón detectado.
Concepto que debes explicarle al usuario primero
Antes de empezar pasos, dile (1-2 frases):
"Claude Code NO se va a instalar aquí. Va a correr en tu EC2. Esta máquina solo será un control remoto vía SSH a través de Tailscale. Al final, tecleando ec2 desde cualquier terminal de aquí, te conectas a Claude Code remoto con todo tu stack (GBrain, OpenClaw, Hermes) intacto."
Si confirma que entendió, procede al Paso 0.
Paso 0 — Recolectar info crítica (antes de tocar nada)
Pregúntale al usuario las 4 cosas siguientes ANTES de ejecutar cualquier comando. Sin estos datos no podemos seguir.
1. ¿Qué OS está corriendo esta máquina? (Mac / Linux / Windows-WSL)
2. ¿Cuál es el hostname Tailscale de tu EC2? (ej: jarvis-v3, mi-servidor, prod-1)
3. ¿Cuál es el usuario SSH del EC2? (default: ec2-user — confirma)
4. ¿Cuál es el directorio inicial donde quieres que arranque Claude Code? (default: /home/ec2-user)
Guarda estos valores en variables internas (OS, EC2_HOST, EC2_USER, EC2_HOME). Vas a usarlos en todos los pasos siguientes y al final en ~/.config/ec2-remote-access/config.env.
Si el usuario no sabe el hostname Tailscale, dile que entre a https://login.tailscale.com/admin/machines desde el navegador y copie el "Machine name" del EC2.
Paso 1 — Instalar Tailscale
Adapta el comando según OS:
Mac:
which tailscale >/dev/null 2>&1 && echo "✅ Tailscale ya instalado" || \
(echo "Instalando..." && brew install --cask tailscale && open -a Tailscale)
Linux (Ubuntu/Debian/Amazon Linux):
which tailscale >/dev/null 2>&1 && echo "✅ Tailscale ya instalado" || \
(curl -fsSL https://tailscale.com/install.sh | sh && sudo tailscale up)
Windows/WSL: Dile que descargue desde https://tailscale.com/download/windows (es GUI, no automatizable). Espera a que confirme antes de seguir.
Ejecuta el comando. Si el resultado es "ya instalado", pasa al Paso 2. Si lo acabas de instalar, dile que haga login con la cuenta del usuario (la misma cuenta de Tailscale que usa en su Mac/EC2 actual). Espera confirmación.
Paso 2 — Verificar que Tailscale ve al EC2
tailscale status | grep -E "${EC2_HOST}|$(echo ${EC2_HOST} | tr '[:upper:]' '[:lower:]')" || \
echo "❌ ${EC2_HOST} no aparece en tu tailnet"
Si NO aparece:
NO sigas hasta que el grep encuentre el EC2.
Si SÍ aparece: guarda el IP Tailscale del EC2 (tailscale status | grep ${EC2_HOST} | awk '{print $1}'). Lo vas a necesitar como fallback.
Paso 3 — Generar / verificar SSH key
ls ~/.ssh/id_ed25519.pub 2>/dev/null && echo "✅ SSH key ya existe" || \
(echo "Generando nueva SSH key..." && ssh-keygen -t ed25519 -C "$(whoami)@$(hostname)-$(date +%Y%m%d)" -f ~/.ssh/id_ed25519 -N "")
Importante: -N "" crea la key SIN passphrase. Si el usuario prefiere passphrase (más seguro pero más fricción), pregúntale antes y ejecuta sin -N "".
Después muestra la public key:
cat ~/.ssh/id_ed25519.pub
Dile al usuario: "Copia esa línea entera. Ahora la vamos a autorizar en el EC2."
Paso 4 — Autorizar la SSH key en el EC2
El usuario tiene 2 opciones para hacer esto, dependiendo de si ya tiene otra máquina conectada al EC2.
Opción A — Ya tiene otra máquina con acceso al EC2 (más fácil)
Dile que abra terminal en su Mac existente (o donde ya tenga acceso), conecte por SSH al EC2, y agregue la nueva key:
ssh ${EC2_USER}@${EC2_HOST}
echo 'ssh-ed25519 AAAA... TU_KEY_NUEVA_AQUI' >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
exit
Espera confirmación de que lo hizo.
Opción B — Es su primera máquina conectada al EC2
Necesita autorizar la key vía AWS Console. Dile:
- AWS Console → EC2 → Instances → seleccionar el EC2 → "Connect" → "EC2 Instance Connect"
- Una vez en la terminal web del EC2:
echo 'ssh-ed25519 AAAA... TU_KEY_NUEVA_AQUI' >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
- Cerrar la terminal web
Espera confirmación.
Paso 5 — Configurar SSH config local
mkdir -p ~/.ssh && chmod 700 ~/.ssh
Verifica si ya hay entry para el EC2:
grep -q "Host ${EC2_HOST}" ~/.ssh/config 2>/dev/null && echo "Entry existe, lo actualizo" || echo "Creando nueva entry"
Agrega (o reemplaza) la entry. Usa Edit/Write para añadir a ~/.ssh/config:
Host ec2 ${EC2_HOST}
HostName ${EC2_HOST}
User ${EC2_USER}
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 60
ServerAliveCountMax 3
# Fallback si MagicDNS de Tailscale falla:
# HostName <IP_TAILSCALE_DEL_PASO_2>
El alias Host ec2 permite que el usuario teclee ssh ec2 sin escribir el hostname completo. Host ${EC2_HOST} es el alias largo.
Paso 6 — Test de conexión
Ahora prueba SSH crudo (sin claude):
ssh -o BatchMode=yes -o ConnectTimeout=5 ec2 'echo "✅ SSH funciona desde $(hostname) → $(uname -n)"' 2>&1
Si funciona: sigue al Paso 7.
Si falla con Permission denied: la SSH key no quedó autorizada. Vuelve al Paso 4 y verifica.
Si falla con Could not resolve hostname: Tailscale MagicDNS no está activo. Edita ~/.ssh/config y reemplaza HostName ${EC2_HOST} por HostName <IP_TAILSCALE> (que guardaste en Paso 2).
Si falla con Connection refused: el sshd del EC2 no escucha en el IP Tailscale. Verifica que el security group de AWS permita Tailscale (usualmente no requiere abrir nada porque Tailscale es WireGuard interno).
Paso 7 — Configurar aliases en shell del usuario
Detecta shell del usuario:
SHELL_RC="$HOME/.zshrc"
[ -f "$HOME/.bashrc" ] && [ ! -f "$HOME/.zshrc" ] && SHELL_RC="$HOME/.bashrc"
echo "Editando: $SHELL_RC"
Agrega los siguientes aliases (usa Edit con append) si no existen ya:
alias ec2='ssh -t ec2 "cd ${EC2_HOME} && claude"'
alias ec2-tmux='ssh -t ec2 "tmux new-session -A -s claude \"cd ${EC2_HOME} && claude\""'
alias ec2-continue='ssh -t ec2 "cd ${EC2_HOME} && claude --continue"'
alias ec2-resume='ssh -t ec2 "cd ${EC2_HOME} && claude --resume"'
alias ec2-shell='ssh ec2'
alias ec2-tmux-2='ssh -t ec2 "tmux new-session -A -s claude-2 \"cd ${EC2_HOME} && claude\""'
alias ec2-tmux-3='ssh -t ec2 "tmux new-session -A -s claude-3 \"cd ${EC2_HOME} && claude\""'
Guarda y recarga:
source $SHELL_RC
Paso 7.5 — (OPCIONAL) Terminal permanente en Antigravity / VS Code / Cursor
Este paso es OPCIONAL. PREGÚNTALE primero al cliente:
"¿Usas un editor tipo Antigravity, VS Code o Cursor? Si sí, puedo configurar su terminal integrada para que cada vez que la abras caigas directo en una sesión permanente dentro del EC2 — cierras el editor, duermes la laptop o cambias de WiFi, y al reabrir sigues exactamente donde te quedaste. ¿Lo configuramos? (si no usas ninguno, saltamos este paso)"
Si dice que NO → salta directo al Paso 8. Si dice que SÍ, continúa:
a) Pregúntale cuál editor (Antigravity / VS Code / Cursor) y ubica su settings.json según el OS:
| Editor | Mac | Linux | Windows |
|---|
| Antigravity | ~/Library/Application Support/Antigravity/User/settings.json | ~/.config/Antigravity/User/settings.json | %APPDATA%\Antigravity\User\settings.json |
| VS Code | ~/Library/Application Support/Code/User/settings.json | ~/.config/Code/User/settings.json | %APPDATA%\Code\User\settings.json |
| Cursor | ~/Library/Application Support/Cursor/User/settings.json | ~/.config/Cursor/User/settings.json | %APPDATA%\Cursor\User\settings.json |
b) Agrega un perfil de terminal que se engancha al tmux persistente del EC2 (reutiliza el alias SSH ec2 del Paso 5). Sustituye osx por linux/windows según el OS del cliente. Haz merge con jq, NO sobrescribas el archivo:
SETTINGS="<ruta de la tabla de arriba>"
mkdir -p "$(dirname "$SETTINGS")"
[ -f "$SETTINGS" ] || echo '{}' > "$SETTINGS"
cp "$SETTINGS" "$SETTINGS.bak-$(date +%Y%m%d%H%M%S)"
jq '. + {
"terminal.integrated.profiles.osx": ((."terminal.integrated.profiles.osx" // {}) + {
"EC2 Permanente": { "path": "ssh", "args": ["-t", "ec2", "tmux new-session -A -s antigravity"] }
}),
"terminal.integrated.defaultProfile.osx": "EC2 Permanente"
}' "$SETTINGS" > "$SETTINGS.tmp" && mv "$SETTINGS.tmp" "$SETTINGS"
echo "✅ Perfil 'EC2 Permanente' agregado. Respaldo en $SETTINGS.bak-*"
Si el cliente NO tiene jq, dale el bloque para pegar a mano dentro de su settings.json (mismo contenido). Pegar a mano es más seguro si el archivo ya tiene config compleja.
c) Dile que reinicie el editor y abra una terminal nueva (Ctrl+ñ / Ctrl+\``). Debe caer directo en el EC2, dentro de la sesión tmux antigravity`.
Por qué funciona (explícaselo en 1 frase): la permanencia la da tmux new-session -A -s antigravity (engancha-o-crea la misma sesión); el EC2 la mantiene viva aunque cierres el editor. El alias ec2 del Paso 7 te sirve igual desde cualquier otra terminal como respaldo.
Paso 8 — Persistir la configuración del skill
Guarda los valores que recolectaste para que futuras invocaciones del skill no pregunten de nuevo:
mkdir -p ~/.config/ec2-remote-access
cat > ~/.config/ec2-remote-access/config.env <<EOF
EC2_HOST=${EC2_HOST}
EC2_USER=${EC2_USER}
EC2_HOME=${EC2_HOME}
OS=${OS}
CONFIGURED_AT=$(date -u +%Y-%m-%dT%H:%M:%SZ)
EOF
chmod 600 ~/.config/ec2-remote-access/config.env
echo "✅ Config guardada en ~/.config/ec2-remote-access/config.env"
Paso 9 — Smoke test final
Pide al usuario que abra una nueva terminal (para que cargue el .zshrc/.bashrc actualizado) y teclee:
ec2-tmux
Si todo está bien, ve el prompt de Claude Code en EC2. Le confirma:
"Listo. Para usarlo en cualquier momento: abre cualquier terminal, teclea ec2-tmux, y estás dentro de Claude Code en tu EC2. Si se cae el WiFi o cierras la laptop, vuelve a teclear ec2-tmux y retomas exactamente donde quedaste."
Comandos cheat-sheet (muéstrale la tabla):
| Comando | Qué hace |
|---|
ec2 | Sesión Claude nueva (no persistente) |
ec2-tmux | Sesión Claude persistente vía tmux (recomendada) |
ec2-continue | Reanuda la sesión más reciente |
ec2-resume | Menú con todas las sesiones previas |
ec2-shell | Solo terminal en EC2, sin Claude |
ec2-tmux-2/3 | Sesiones tmux paralelas independientes |
Troubleshooting
"Permission denied (publickey)"
- La SSH key no quedó autorizada en
~/.ssh/authorized_keys del EC2. Vuelve al Paso 4.
- O el archivo tiene permisos incorrectos:
chmod 600 ~/.ssh/authorized_keys en EC2.
"Could not resolve hostname"
- Tailscale MagicDNS no está activo. Soluciones:
"claude: command not found" tras hacer SSH
Sesión tmux muere o no se re-adjunta
- Verifica que tmux esté instalado en EC2:
ssh ec2 'which tmux'
- Si no:
ssh ec2 'sudo dnf install -y tmux' (Amazon Linux) o sudo apt install -y tmux (Ubuntu)
"Connection refused"
- El sshd del EC2 no acepta conexiones desde la IP de Tailscale.
- Verifica que sshd esté corriendo:
sudo systemctl status sshd (desde otra forma de acceso al EC2)
- AWS Security Group no necesita cambios si usas Tailscale (es WireGuard, no SSH normal).
"claude --continue" da "session locked"
- Otra terminal ya tiene esa sesión abierta. Cierra la otra o usa
claude --resume para elegir una diferente.
Notas de mantenimiento
-
Si el hostname Tailscale del EC2 cambia (ej: renombras a prod-2): edita 3 lugares en orden:
~/.config/ec2-remote-access/config.env → EC2_HOST=nuevo-nombre
~/.ssh/config → Host ec2 nuevo-nombre + HostName nuevo-nombre
- Los aliases en
~/.zshrc siguen funcionando automáticamente porque referencian ssh ec2 (el alias corto)
-
Para añadir OTRO EC2 al mismo setup (multi-instancia): copia el bloque de aliases con prefijo distinto: ec2-staging, ec2-prod, etc.
-
Para revocar acceso desde una máquina antigua: borra la línea correspondiente de ~/.ssh/authorized_keys en el EC2.
Para Claude que ejecuta este skill
Reglas operativas críticas:
- Verifica antes de avanzar. Cada paso tiene un check (grep, ls, ssh -o BatchMode). Si el check falla, NO avances — diagnostica.
- Nunca asumas valores. Si el usuario no respondió a una pregunta del Paso 0, pregúntala antes de seguir.
- No bloques si la máquina ya está configurada. Si
~/.config/ec2-remote-access/config.env ya existe, ofrece "ya está configurado, ¿re-verificar o re-configurar?" en vez de re-correr todo.
- Sé conversacional, no recitar. Después de cada paso, dile 1 frase corta sobre qué hiciste y qué viene. No leas el SKILL.md textual al usuario.
- Si el usuario está en Windows nativo (no WSL): explícale que Claude Code se recomienda corra en WSL. Si insiste en PowerShell crudo, el flujo es similar pero los paths cambian (
%USERPROFILE%\.ssh\config).
- NUNCA modifiques
~/.ssh/authorized_keys del EC2 desde la máquina nueva. El Paso 4 se hace desde una máquina YA autorizada o desde AWS Console — nunca desde la máquina nueva (porque por definición todavía no tiene acceso).