Todos tus agentes están corriendo. Tus cron jobs disparan, tus scripts scrapean, tus modelos infieren. ¿Qué haces ahora que no te distraiga tanto pero sea casi tocar pasto?
CDaily es un poco eso. Un feed reader minimalista que abres en una pestaña y hojeas entre tasks. Lee directo del SQLite de blogwatcher-cli, sin duplicar datos. Sin notificaciones. Sin scroll infinito. Solo una cuadrícula de lo que está pasando afuera mientras tú estás adentro.
- Lista artículos desde la base de
blogwatcher-cli - Filtra por categoría y búsqueda de texto
- Marca leído / no leído
- Marca favoritos / para leer después
- Guarda ratings 1–5 para reordenar el feed
- Genera resúmenes IA bajo demanda
- Extrae y cachea imágenes OG cuando existen
- Expone un servidor MCP (Model Context Protocol) para que agentes (Claude Code, Cursor, Codex CLI) lean, busquen y curen el feed sin pasar por la UI
- Python 3.11+
blogwatcher-cliinstaladoblogwatcher-cli.dben~/.blogwatcher-cli/- SQLite con el schema requerido por blogwatcher-cli
cd cdaily
python -m pip install -r requirements.txt
python -m cdaily.main
# abrir http://localhost:7890El archivo tracked config.yaml usa categorías genéricas y defaults seguros. Para overrides locales, usa variables de entorno o un archivo local ignorado por git.
Variables útiles:
CDAILY_CONFIG— ruta a un YAML alternativoCDAILY_DB_PATH— override del path a la DBCDAILY_AI_ENDPOINT— endpoint OpenAI-compatible para resúmenesCDAILY_AI_API_KEY— API key opcional para el endpoint de IA
Ejemplo rápido:
export CDAILY_AI_ENDPOINT="http://localhost:12345/v1/chat/completions"
export CDAILY_AI_API_KEY="tu_key_si_aplica"También puedes copiar .env.example a .env o config.yaml.example a config.yaml si prefieres empezar desde los defaults públicos. .env, .env.local y config.local.yaml están ignorados por git.
docker compose up --build
# App disponible en http://localhost:7890Si usas Docker con un endpoint IA que vive en tu host, el docker-compose.yml ya deja CDAILY_AI_ENDPOINT apuntando a host.docker.internal.
python -m black cdaily tests
python -m flake8 cdaily testspytest tests/ -vcdaily/main.py— bootstrap mínimo de FastAPIcdaily/routes/— capa HTTPcdaily/services/— scraping, resúmenes, scan y caché de imágenescdaily/repositories/— acceso a SQLite y queriescdaily/database.py— shim de compatibilidad para imports antiguoscdaily/static/— JS y CSS del frontendcdaily/templates/— HTML base
# Agregar
blogwatcher-cli add "Nombre" https://example.com --feed-url https://example.com/feed.xml
# Quitar
blogwatcher-cli remove "Nombre" --yesLos cambios se reflejan en CDaily al siguiente refresh automático o manual.
CDaily incluye un servidor MCP que expone el feed como tools, resources y prompts. Agentes como Claude Code, Cursor o Codex CLI pueden leer y curar el feed por stdio, sin necesidad de que el FastAPI esté corriendo (el MCP accede al SQLite directamente vía la capa de repositorios).
python -m cdaily.mcp_server
# arranca en stdio, espera handshake del cliente MCPAñade en ~/.claude.json (o el mcpServers del proyecto):
{
"mcpServers": {
"cdaily": {
"command": "python",
"args": ["-m", "cdaily.mcp_server"],
"cwd": "/ruta/absoluta/a/cdaily"
}
}
}Variables opcionales: CDAILY_DB_PATH para apuntar a una DB alternativa.
| Categoría | Tools |
|---|---|
| Lectura | feed_read, feed_digest, feed_search, article_open |
Mutación (sufijo _apply) |
article_mark_apply, article_rate_apply, article_summarize_apply, feed_clear_apply |
| Fuentes | sources_list, sources_add_apply, sources_remove_apply |
| Sistema | feed_scan_apply, feed_stats |
Resources (lectura pasiva, attach con @):
cdaily://feed/unread— snapshot JSON de no-leídos (top 50)cdaily://stats— conteos por categoríacdaily://sources— blogs configurados
Prompts (workflows reutilizables):
morning_triage— digest matutino con top 3 a leerweekly_digest— temas dominantes de la semana
- Respuestas slim por defecto (
id, title, blog, published, starred, rating, category);verbose=trueañade url, summary, image, scores - Tools mutantes llevan
[MUTATES]en docstring y sufijo_applypara que agentes distingan side-effects de un vistazo - Descripciones explican cuándo usar cada tool, no solo qué hace
cdaily/
├── mcp_server.py # entry point (FastMCP + stdio)
└── mcp/
├── tools.py # 13 tools agent-native
├── resources.py # 3 resources
├── prompts.py # 2 workflow prompts
└── shaping.py # slim/verbose payload shapers
CDaily is released under the MIT License. See CONTRIBUTING.md for development setup and pull request guidelines.
- No hay secretos hardcodeados en el repo.
- Las credenciales de IA van por variables de entorno, nunca dentro de
config.yaml. - Todas las URLs externas se validan (solo http/https, sin IPs privadas).
- Archivos locales sensibles o personalizados se ignoran con
.gitignore:.env.env.localconfig.local.yaml.venv/
Para exponer CDaily en red o internet, activa auth token vía entorno:
export CDAILY_API_TOKEN="<tu-token-seguro>"Una vez seteado, toda request a /api/* requiere header:
Authorization: Bearer <tu-token-seguro>
La página principal (GET /) y archivos estáticos quedan abiertos.
Si no seteas CDAILY_API_TOKEN, la autenticación está desactivada y todo
funciona como antes — ideal para desarrollo local.
CDaily sirve HTTP en 127.0.0.1:7890. Para producción, ponlo detrás de un
reverse proxy con TLS. El más simple es Caddy:
# Caddyfile
midominio.com {
reverse_proxy 127.0.0.1:7890
}caddy runO con nginx:
# /etc/nginx/sites-available/cdaily
server {
listen 443 ssl;
server_name midominio.com;
ssl_certificate /etc/ssl/certs/midomio.pem;
ssl_certificate_key /etc/ssl/private/midomio.key;
location / {
proxy_pass http://127.0.0.1:7890;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}- Verifica que
~/.blogwatcher-cli/blogwatcher-cli.dbexista - Revisa permisos:
ls -la ~/.blogwatcher-cli/blogwatcher-cli.db
- Verifica el schema de blogwatcher-cli
- Revisa:
sqlite3 ~/.blogwatcher-cli/blogwatcher-cli.db ".schema articles"
- Revisa
CDAILY_AI_ENDPOINT - Si usas Docker, asegúrate de que el endpoint sea alcanzable desde el contenedor
- Revisa si algo usa el 7890:
lsof -i :7890 - Cambia el puerto en
config.yamlo en tu override local
