---
name: swl:notificaciones
description: Gestiona el sistema de notificaciones Telegram de swl-ses (opt-in). Subcomandos: init (flujo interactivo de configuración), status (estado actual sin mostrar credenciales), disable (quitar hooks SWL de settings global), bot start|stop|status|restart|enable-autostart|disable-autostart (daemon bidireccional con autostart por OS — Windows Scheduled Task, Linux systemd --user, macOS LaunchAgent).
allowed_tools: ["Read", "Bash"]
---

# /swl:notificaciones — Gestión de notificaciones Telegram

Gestiona el hook saliente y el daemon bidireccional de Telegram que swl-ses
instala como feature opt-in. Toda la lógica de credenciales, settings y
baseline la delega a `scripts/lib/notificaciones-telegram.js` — este
comando solo orquesta.

**Seguridad**: el comando NUNCA muestra el token. Solo muestra metadata
(longitud, primeros 3 caracteres, últimos 4 dígitos del chat_id). Las
credenciales viven en `~/.claude/notifications/.env`, fuera del repositorio.

## Cuándo NO invocarme

- Para configurar el gateway bidireccional completo (`/swl:gateway`): ese
  componente gestiona adaptadores Telegram, Discord, Slack y Webhook con
  `node-telegram-bot-api`. Este comando es para el hook saliente zero-deps.
- Para enviar mensajes a Telegram desde código: usar `hooks/lib/telegram-cliente.js`
  directamente.
- Para revisar el estado del gateway: `/swl:gateway status`.
- Para ejecutar el bot daemon: usar los subcomandos `bot start|stop|status|restart`
  o `bot enable-autostart|disable-autostart`. El binario está en `bin/swl-telegram-bot.js`.

## Subcomandos

### `/swl:notificaciones init`

Lanza el flujo interactivo de configuración. Equivalente al paso 9 del
instalador — útil cuando el usuario saltó el opt-in durante la instalación
o quiere reconfigurar.

**Flujo**:
1. Verifica la feature flag `SWL_NOTIFICACIONES_TELEGRAM`. Si vale `0`, sale sin tocar nada.
2. Si ya existe `~/.claude/notifications/.env`, pregunta si reutilizar o sobreescribir.
3. Muestra instrucciones para obtener token (BotFather) y chat_id (`/quien`).
4. Solicita `TELEGRAM_BOT_TOKEN` y `TELEGRAM_CHAT_ID`.
5. Escribe `.env` con permisos 600 en POSIX.
6. Genera `baseline-hooks.json` para auto-restauración de settings.
7. Hace merge de los hooks SWL en `~/.claude/settings.json` global (backup previo).

**Ejemplo**:
```
/swl:notificaciones init
```

**Modo headless** (sin TTY):
```bash
# Usar el instalador directamente con flag
npx @saulwade/swl-ses@latest install --with-notificaciones=<TOKEN>,<CHAT_ID>
```

**Criterio de éxito**: al terminar, el hook `notificacion-telegram.js` está
registrado en `~/.claude/settings.json` y se envía una notificación de prueba.

### `/swl:notificaciones status`

Muestra el estado actual sin revelar credenciales.

**Salida esperada**:
```
Notificaciones Telegram — estado actual
  .env:              existe
  token:             configurado (abc*** — longitud: 46)
  chat_id:           configurado (...4521)
  proyectos mudos:   ninguno
  bot daemon:        detenido (usa `/swl:notificaciones bot start`)
  autostart:         no configurado (usa `bot enable-autostart`)
```

El token nunca aparece completo. El chat_id muestra solo los últimos 4 dígitos.

**Ejemplo**:
```
/swl:notificaciones status
```

### `/swl:notificaciones disable`

Quita los hooks SWL de `~/.claude/settings.json`. Pide confirmación antes
de actuar. Por defecto conserva `.env` (no borra credenciales sin pedirlo).

**Opciones**:
- Sin flags: quita hooks de settings, conserva `.env` y `baseline-hooks.json`.
- Con `--purge`: quita hooks Y elimina `.env` y `baseline-hooks.json`. Pide
  confirmación adicional antes de borrar credenciales.

**Flujo con confirmación**:
```
¿Confirmas deshabilitar las notificaciones Telegram? [s/N]
  s
  [notificaciones] 4 hook(s) SWL eliminados de settings.json (2 preservados).
  [notificaciones] .env conservado. Para eliminarlo usa: /swl:notificaciones disable --purge
```

**Criterio de éxito**: `~/.claude/settings.json` ya no contiene referencias
a `notificacion-telegram.js` ni `auto-restaurar-settings.js`.

**Ejemplo**:
```
/swl:notificaciones disable
/swl:notificaciones disable --purge
```

### `/swl:notificaciones bot start|stop|status|restart`

Gestiona el ciclo de vida del daemon bidireccional `bin/swl-telegram-bot.js`.

El daemon se inicia en background (desacoplado del proceso padre) con stdout/stderr
redirigidos a `~/.claude/notifications/bot.stdout.log` y `bot.stderr.log`.
El PID se almacena en `~/.claude/notifications/bot.pid` para gestión posterior.

**Ejemplos**:
```
/swl:notificaciones bot start
/swl:notificaciones bot stop
/swl:notificaciones bot status
/swl:notificaciones bot restart
```

### `/swl:notificaciones repair`

Repara una instalación rota de notificaciones copiando los hook files al directorio
`~/.claude/hooks/` y migrando entradas con ruta relativa en `~/.claude/settings.json`
a ruta absoluta.

Úsalo cuando el hook de Stop genera el error:
```
Cannot find module 'D:\...\hooks\notificacion-telegram.js'
```
o cuando `settings.json` contiene `node hooks/notificacion-telegram.js` en lugar
de la ruta absoluta correcta.

**Ejemplo**:
```
/swl:notificaciones repair
```

### `/swl:notificaciones bot enable-autostart|disable-autostart`

Configura el inicio automático del daemon al arrancar la sesión del usuario.
Delega al generador correspondiente según el OS:

- **Windows**: Scheduled Task (Programador de tareas) con RunLevel Limited (sin elevación)
- **Linux**: unit systemd `--user` con `WantedBy=default.target` (sin root)
- **macOS**: LaunchAgent en `~/Library/LaunchAgents/` (sin root, sin LaunchDaemons)

El autostart se configura por usuario — nunca requiere sudo ni privilegios de sistema.

**Rollback manual si algo sale mal**:
- Windows: `schtasks /delete /tn "SWL-Telegram-Bot" /f`
- Linux: `systemctl --user disable --now swl-telegram-bot && rm ~/.config/systemd/user/swl-telegram-bot.service`
- macOS: `launchctl unload -w ~/Library/LaunchAgents/com.swl.telegram-bot.plist && rm ~/Library/LaunchAgents/com.swl.telegram-bot.plist`

**Ejemplos**:
```
/swl:notificaciones bot enable-autostart
/swl:notificaciones bot disable-autostart
```

## Instrucciones de ejecución

Al recibir `/swl:notificaciones [subcomando]`:

### Paso 1 — Identificar subcomando

Parsear el primer argumento: `init`, `status`, `disable`, `repair`, `bot`.

Si no hay argumento o el argumento no es reconocido, mostrar la ayuda:

```
Uso: /swl:notificaciones <subcomando>

Subcomandos disponibles:
  init                       Configurar notificaciones Telegram
  status                     Ver estado actual (sin mostrar credenciales)
  disable [--purge]          Deshabilitar (conserva .env por defecto)
  repair                     Reparar hooks rotos (ruta relativa → absoluta)
  bot start                  Iniciar daemon bidireccional
  bot stop                   Detener daemon
  bot status                 Estado del daemon
  bot restart                Reiniciar daemon
  bot enable-autostart       Configurar inicio automático del bot
  bot disable-autostart      Quitar inicio automático del bot

```

### Paso 2 — Ejecutar según subcomando

**Para `init`**:

```bash
node -e "
const { init } = require('./scripts/lib/notificaciones-telegram');
init({ esTty: true }).then(r => {
  console.log('[resultado]', r.resultado, r.detalle || '');
  process.exit(r.resultado === 'error' ? 1 : 0);
}).catch(e => { console.error(e.message); process.exit(1); });
"
```

Si el proceso no tiene TTY (modo no interactivo en Claude Code), detectarlo
y mostrar instrucciones para ejecutar desde terminal:

```
Este subcomando requiere entrada interactiva (TTY).
Ejecuta desde tu terminal:
  node -e "require('./scripts/lib/notificaciones-telegram').init({ esTty: true })"
O usa el instalador:
  npx @saulwade/swl-ses@latest install
```

**Para `status`**:

```bash
node -e "
const { status } = require('./scripts/lib/notificaciones-telegram');
const s = status();
console.log('');
console.log('Notificaciones Telegram — estado actual');
console.log('  .env:             ', s.envExiste ? 'existe' : 'no existe');
console.log('  token:            ', s.tokenConfigurado ? 'configurado' : 'no configurado');
console.log('  chat_id:          ', s.chatIdConfigurado ? ('configurado (' + s.chatIdParcial + ')') : 'no configurado');
const mudos = s.proyectosSilenciados.length
  ? s.proyectosSilenciados.join(', ')
  : 'ninguno';
console.log('  proyectos mudos:  ', mudos);
const botS = require('./scripts/lib/notificaciones-telegram').botStatus();
console.log('  bot daemon:       ', botS.activo ? ('activo (PID ' + botS.pid + ')') : 'detenido');
const autostartLabel = process.platform === 'win32' ? 'Scheduled Task' : (process.platform === 'linux' ? 'systemd --user' : 'LaunchAgent');
console.log('  autostart:         usar /swl:notificaciones bot enable-autostart (' + autostartLabel + ')');
console.log('');
"
```

**Para `disable`**:

Antes de invocar la lib, pedir confirmación al usuario:

```
¿Confirmas deshabilitar las notificaciones Telegram? [s/N]
```

Si responde `n` o vacío: cancelar sin tocar nada.

Si responde `s`:

```bash
node -e "
const { disable } = require('./scripts/lib/notificaciones-telegram');
const r = disable({ confirmar: true, conservarEnv: true });
console.log('[resultado]', r.resultado, r.detalle || '');
process.exit(r.resultado === 'error' ? 1 : 0);
"
```

Si se pasó `--purge`, pedir confirmación adicional:
```
¿Eliminar también las credenciales (~/.claude/notifications/.env)? [s/N]
```
Si confirma, llamar con `conservarEnv: false`.

**Para `repair`**:

```bash
node -e "
const { repair } = require('./scripts/lib/notificaciones-telegram');
repair().then(r => {
  console.log('[repair]', r.resultado, r.detalle || '');
  process.exit(r.resultado === 'error' ? 1 : 0);
}).catch(e => { console.error(e.message); process.exit(1); });
"
```

**Para `bot start`**:

```bash
node -e "
const { botStart } = require('./scripts/lib/notificaciones-telegram');
const r = botStart();
if (r.ok) {
  console.log('[bot]', r.mensaje || 'Bot iniciado.');
} else {
  console.error('[bot] Error:', r.error);
  process.exit(1);
}
"
```

**Para `bot stop`**:

```bash
node -e "
const { botStop } = require('./scripts/lib/notificaciones-telegram');
const r = botStop();
if (r.ok) {
  console.log('[bot]', r.mensaje || 'Bot detenido.');
} else {
  console.error('[bot] Error:', r.error);
  process.exit(1);
}
"
```

**Para `bot status`**:

```bash
node -e "
const { botStatus } = require('./scripts/lib/notificaciones-telegram');
const r = botStatus();
console.log('');
console.log('Bot daemon — estado actual');
console.log('  activo:', r.activo ? 'sí' : 'no');
console.log('  pid:   ', r.pid !== null ? r.pid : 'n/a');
console.log('');
"
```

**Para `bot restart`**:

```bash
node -e "
const { botRestart } = require('./scripts/lib/notificaciones-telegram');
const r = botRestart();
if (r.ok) {
  console.log('[bot]', r.mensaje || 'Bot reiniciado.');
} else {
  console.error('[bot] Error:', r.error);
  process.exit(1);
}
"
```

**Para `bot enable-autostart`**:

```bash
node -e "
const { botEnableAutostart } = require('./scripts/lib/notificaciones-telegram');
const r = botEnableAutostart();
if (r.ok) {
  console.log('[autostart]', r.mensaje || 'Autostart habilitado.');
} else {
  console.error('[autostart] Error:', r.error);
  process.exit(1);
}
"
```

**Para `bot disable-autostart`**:

```bash
node -e "
const { botDisableAutostart } = require('./scripts/lib/notificaciones-telegram');
const r = botDisableAutostart();
if (r.ok) {
  console.log('[autostart]', r.mensaje || 'Autostart deshabilitado.');
} else {
  console.error('[autostart] Error:', r.error);
  process.exit(1);
}
"
```

### Paso 3 — Reportar resultado

Mostrar el resultado al usuario con el estado final. Si el subcomando fue
`init` exitoso, recordar que el hook estará activo en la próxima sesión de
Claude Code.

## Seguridad

- NUNCA mostrar el valor de `TELEGRAM_BOT_TOKEN` en ningún output.
- NUNCA sugerir comandos como `cat ~/.claude/notifications/.env`.
- Los ejemplos de este comando usan placeholders `<TOKEN>` y `<CHAT_ID>`,
  nunca valores reales.
- Al mostrar el chat_id, siempre usar solo los últimos 4 dígitos.
- Si detectas que algún output podría exponer credenciales, truncar o
  enmascarar antes de mostrar.

## Variables de entorno relevantes

| Variable | Efecto |
|----------|--------|
| `SWL_NOTIFICACIONES_TELEGRAM=0` | Desactiva los hooks sin tocar settings. El comando `init` respeta esta variable. |

## Referencias

- Credenciales: `~/.claude/notifications/.env` (fuera del repo, permisos 600)
- Lib de flujo: `scripts/lib/notificaciones-telegram.js`
- Hook saliente: `hooks/notificacion-telegram.js`
- Hook de restauración: `hooks/auto-restaurar-settings.js`
- ADR-0009: excepción a la regla "SWL solo registra hooks a nivel proyecto"
