Automatización personal · Claude Code Channels (research preview), plugins MCP, Telegram Bot API
Claude Code Channels + Telegram → Blog privado automático
Un pipeline de input remoto que convierte un bot de Telegram en mi secretario personal: mando un link desde el móvil, Claude Code lo lee, escribe una nota privada deep-dive, commitea y pushea, y Cloudflare Pages despliega. Sin backend propio.
Un pipeline sin fricción para alimentar una knowledge base personal en /private. Mando un link desde el móvil y en menos de un minuto tengo una nota deep-dive en español. Sin backend propio.
Construido sobre Claude Code Channels, una feature en research preview (v2.1.80+) que permite a un plugin MCP empujar eventos directamente a una sesión de Claude Code en ejecución.
Contexto: el problema de la deuda de lectura
Cada día me cruzo con algo que vale la pena leer: un post de LinkedIn, un artículo de investigación de terceros, un blog de ingeniería, un paper. Guardo el link y me digo que volveré a él. Casi nunca lo hago.
Un link guardado no sirve de mucho si no lo lees, si no lo comprendes, si no puedes volver a él fácilmente. Llevaba meses/años acumulando links interesantes en Notion, marcadores del navegador y Saved Messages de Telegram -> un gran "agujero negro" donde los links se apilaban pero al que rara vez volvía a abrir. Cuando sí lo hacía, los mandaba a la trituradora (ChatGPT, que me lo explicaba bien pero a veces muy escueto), y pasados unos meses no era tan fácil de recuperar en un sinfín de chats que tenía.
Esta idea me la inspiró un post de Fran Pastor, "Tu WhatsApp de links no es conocimiento" (link al pie de la página), que diagnostica la misma deuda y construye un agente autónomo para triar un firehose multi-fuente (Gmail, Twitter, newsletters) de miles de señales a un puñado que valga la pena leer.
Mismo diagnóstico, prescripción y stack distintos: yo no tengo un firehose que filtrar, tengo un stream único y ya curado que lo que necesita es profundidad de procesamiento.
- El cuello de botella no es descubrir. En este punto no necesito un filtro, ni un feed, ni una capa de scoring. Para mí eso es un poco el human in the loop... El compartir con los compañeros y debatir... Vamos, que seguimos siendo humanos y la comunicación es clave.
- El cuello de botella es entenderlo. Me gusta que me expliquen las cosas al nivel exacto que me permite comprenderlas bien -> contra mi stack, mis puntos fuertes, mis puntos débiles.
- Quiero poder volver. No solo leerlo una vez -> guardarlo, revisitarlo, construir sobre ello, citarlo en futuros proyectos.
El valor real: un knowledge manager personal
Este proyecto no va realmente de un bot de Telegram. Va de convertir un link capturado en una página dentro de un sitio privado que es mío, explicada de la forma en que mejor aprendo, guardada donde ya busco lo que sé.
- Input -> un solo link mandado a un bot privado desde el móvil.
- Output -> una nota deep-dive en español dentro de mi sitio privado, tras Cloudflare Access, junto al resto de mi knowledge base.
- Por qué funciona -> el sistema ya me conoce.
CLAUDE.mdcodifica mi stack, mi nivel, cómo me gusta que me expliquen las cosas, qué analogías me encajan y qué doy ya por sabido. - Cada post está hecho a medida. El mismo link mandado por otra persona produciría una nota distinta. El sistema no resume -> traduce la fuente a *mi* modelo mental.
- El conocimiento se compone. Las notas viven en git, versionadas, searchables y accesibles con el mismo esquema de URLs que el resto del sitio. El yo del futuro puede encontrarlas.
- La fricción desaparece. Del momento en que veo un link al momento en que existe una página privada que me lo explica a mi nivel: alrededor de un minuto, cero context switch, cero editor abierto.
La idea: push, no pull
Un channel invierte el control flow de MCP. En vez de que Claude salga a buscar una tool, el plugin empuja un evento directamente a la sesión viva.
- MCP tradicional -> Claude es el iniciador. Pregunta, el servidor responde.
- Channel -> el plugin es el iniciador. Empuja un prompt directamente a Claude Code.
- Un DM a un bot privado mío se convierte en un input remoto que aterriza en mi terminal como si lo hubiese tecleado.
- Todo local. El plugin corre junto a Claude Code, nada público queda expuesto.
- El flujo en sí vive en
CLAUDE.md, colocado junto al código del sitio que alimenta.
Arquitectura end-to-end
Tres piezas locales cooperan. Solo dos interacciones cruzan internet pública.
- Telegram Bot API -> plugin channel en Bun (hace
getUpdates). - Plugin channel -> sesión de Claude Code. Empuja el mensaje como prompt
<channel>. - Claude Code ->
WebFetch+Write+npm run build+ git commit/push + reply a Telegram. - GitHub -> build de Cloudflare Pages -> redeploy del sitio tras Cloudflare Access.
- Solo dos cosas salen del portátil: el poll a Telegram y el
git pushfinal.
Infraestructura que colapsa
El diseño ingenuo pediría cinco piezas públicas en movimiento. Los channels lo reducen a tres piezas locales.
- Fuera -> Cloudflare Worker hosteando un webhook de Telegram.
- Fuera -> token del bot viviendo en el edge.
- Fuera -> GitHub App o PAT con permiso de escritura al repo.
- Fuera -> llamada a la Claude API desde el Worker y su API key.
- Fuera -> endpoint HTTPS público que asegurar y monitorizar.
- Dentro -> sesión
claude --channelsde larga duración, plugin de Telegram yCLAUDE.md. Todo local. - Único trade-off -> la sesión tiene que estar viva en alguna parte.
Por qué no Lambda, un Worker o una automatización hosted
Consideré todas las formas obvias antes de elegir channels. Ninguna encajaba en un caso de uso curado, reactivo y con deep-dive por mensaje de manera barata o simple.
- AWS Lambda + API Gateway + Claude API -> montas un servicio entero para un flujo de una sola persona. Pagas invocaciones, pagas el gateway, pagas por token al LLM, y mantienes Terraform para algo al que mandas unos pocos links a la semana.
- Cloudflare Worker + webhook de Telegram -> más barato por invocación, pero sigues hosteando un endpoint HTTPS público, sigues guardando el bot token en el edge, y sigues necesitando un GitHub App o PAT con permiso de escritura para pushear commits.
- Zapier / Make / n8n -> superficial. Te dan pasos de "fetch URL" y "call LLM", pero no un flujo deep-dive-con-diagramas-en-español dirigido por el propio
CLAUDE.mddel repo. No puedes apuntarlo a convenciones del proyecto, así que acabas reescribiendo la mitad de la lógica igualmente. - Un daemon self-hosted -> lo más cercano en espíritu, pero pasas a ser dueño del polling de la Bot API, de la lógica de reconexión, del manejo de secrets, del pipeline de deploy y del alerting. Acabas de reconstruir el plugin de channels a mano.
- Claude Code Channels -> la única forma donde todo colapsa. MCP ya existe, Claude Code ya está corriendo,
CLAUDE.mdya es el system prompt. Añado un plugin y un flag de CLI. El flujo está vivo.
Costes
Este pipeline añade cero euros marginales por post. Ninguna línea nueva en la factura. Todo va sobre herramientas que ya pago o ya uso.
- Bot de Telegram -> gratis. La Bot API no tiene pricing.
- Suscripción a Claude Code -> con el plan básico de ~30€/mes es suficiente. Los channel events consumen del mismo allowance mensual que cualquier otra sesión de Claude Code. A mi volumen (un puñado de posts por semana, unas 2k palabras cada uno) entra cómodamente dentro del plan básico.
- Cloudflare Pages -> free tier (500 builds al mes, sitios ilimitados).
- Cloudflare Access -> gratis en el plan Zero Trust hasta 50 usuarios.
- GitHub -> gratis para repos públicos.
- Bun -> runtime gratuito para el plugin de channel.
- Compara con la forma Lambda: invocaciones de API Gateway + compute de Lambda + Claude API por token + logs de CloudWatch + bucket de estado de Terraform + dominio + TLS + tiempo de mantenimiento. Euros bajos, pero no-cero, y la factura es tuya.
- Mi flujo añade exactamente un artefacto por ejecución: un commit nuevo en git. Nada que monitorizar, renovar o rotar.
Setup y pairing
El happy path es corto y el orden importa. Primero pairing, después lockdown.
- 1. Prerequisitos -> Claude Code v2.1.80+, login de claude.ai (Pro / Max / Team) y Bun.
- 2. Instalar ->
/plugin install telegram@claude-plugins-official. - 3. Configurar ->
/telegram:configure <token>. Token con permisos600en~/.claude/channels/telegram/.env. - 4. Arrancar ->
claude --channels plugin:telegram@claude-plugins-official. - 5. Emparejar -> DM al bot, pegar el código devuelto en
/telegram:access pair <code>. - 6. Bloquear -> inmediatamente después,
/telegram:access policy allowlist. - Nunca dejar el bot en
dmPolicy: "pairing". Cualquiera que lo encuentre puede pedir un código nuevo.
# Dentro de una sesión de Claude Code
/plugin install telegram@claude-plugins-official
/reload-plugins
/telegram:configure <token>
# Reiniciar Claude Code con el channel habilitado
claude --channels plugin:telegram@claude-plugins-official
# Emparejar la cuenta de Telegram y bloquear el bot inmediatamente
/telegram:access pair <code>
/telegram:access policy allowlist Modelo de seguridad
El handle del bot es público, como una dirección de email. Todo lo que de verdad protege el flujo vive debajo.
- Los DMs de paso se descartan en el plugin.
dmPolicy: "allowlist"más una única entrada enallowFromimplica que cualquiersenderIddesconocido se tira antes de llegar a Claude. - Suplantar el
senderIdes inviable. Telegram lo firma del lado del servidor. El único camino realista es el robo de cuenta, que cierra la Two-Step Verification de Telegram. - Amenaza real: prompt injection vía contenido fetcheado. Un "ignore previous instructions" oculto en una página linkeada puede empujar a Claude hacia llamadas no deseadas.
- Mitigación: aprobaciones de tool use por invocación. Cada
Write,Bashogit pushsaca un botón Allow / Deny en el móvil. - El channel no puede ampliar la superficie de tools de Claude ni escapar del sandbox del directorio de trabajo. Solo entrega un prompt.
- El único interruptor que rompería el modelo,
--dangerously-skip-permissions, se queda fuera de este flujo.
CLAUDE.md como system prompt
El flujo no es código. Es una sección corta del CLAUDE.md del propio repo, leída por Claude Code una vez por sesión.
- Idioma -> español.
- Profundidad -> deep dive, lector backend senior.
- Estructura -> TL;DR -> Contexto -> Cómo funciona -> Puntos clave -> Cómo aplica a mi stack -> Opinión crítica.
- Diagramas -> SVG inline, fondo white-poster con paleta fija. Renderiza idéntico en light y dark mode.
- Destino ->
src/content/private/<slug>.md, commiteado y pusheado a master. - El repo que hostea el sitio también define cómo el sitio se alimenta. Sin script wrapper, sin servicio separado.
## Telegram Channel -> Private Blog Posts
When a message arrives via the Telegram channel containing a URL:
1. Fetch the link content (WebFetch)
2. Analyze the content thoroughly
3. Generate a private blog post following the style guide
4. Save as src/content/private/<slug>.md
5. Run `npm run build` to verify
6. Commit & push to master
7. Reply via Telegram with the slug and live URL
Style guide: Spanish, deep dive, inline SVG diagrams on the
white-poster palette, structure TL;DR -> Contexto -> Cómo funciona
-> Puntos clave -> Cómo aplica a mi stack -> Opinión crítica. Trade-offs
- Dependiente de sesión por diseño -> el pipeline solo está vivo mientras corre la sesión de Claude Code. No hay encolado offline por mi parte.
- Por qué aun así me funciona -> tengo el portátil encendido ~24/7 con una sesión
claude --channelsde larga duración, así que el pipeline está siempre alcanzable en la práctica. - Si apago la máquina -> la cola la hace Telegram por mí. Los mensajes enviados al bot se quedan dentro de los servidores de Telegram hasta que vuelvo a abrir el channel. Al reabrirlo el plugin los vuelve a procesar en orden vía
getUpdates. Nada se pierde, y nada llega a Claude hasta que reabro la sesión. - Research preview -> el contrato de
--channelstodavía no está congelado. Espera cambios. - Las aprobaciones de tool use por invocación rompen la ergonomía "mando link y me voy".
- El único escape,
--dangerously-skip-permissions, es exactamente lo que suena y no tiene lugar en un setup compartido. -
git pushdirecto a master es cómodo pero arriesgado. v2 más segura: ramacontent/telegram-<date>con auto-merge solo al pasar el build.