{"id":50277310,"url":"https://github.com/midudev/github-sentinel","last_synced_at":"2026-06-01T01:01:11.445Z","repository":{"id":360406491,"uuid":"1249343971","full_name":"midudev/github-sentinel","owner":"midudev","description":"Crea un centinela para tu GitHub que te avise de cositas","archived":false,"fork":false,"pushed_at":"2026-05-26T08:51:36.000Z","size":496,"stargazers_count":29,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-31T00:03:11.481Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/midudev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-25T15:47:48.000Z","updated_at":"2026-05-30T06:15:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/midudev/github-sentinel","commit_stats":null,"previous_names":["midudev/github-sentinel"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/midudev/github-sentinel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/midudev%2Fgithub-sentinel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/midudev%2Fgithub-sentinel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/midudev%2Fgithub-sentinel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/midudev%2Fgithub-sentinel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/midudev","download_url":"https://codeload.github.com/midudev/github-sentinel/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/midudev%2Fgithub-sentinel/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33755369,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-27T21:32:20.213Z","updated_at":"2026-06-01T01:01:11.404Z","avatar_url":"https://github.com/midudev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GitHub Sentinel\n\nAgente local que vigila tus repositorios de GitHub, detecta nuevas issues y\nte prepara un resumen + propuesta de solución usando un LLM vía API compatible\ncon OpenAI, todo sin salir de tu red si apuntas a un servidor local.\n\nPensado para correr 24/7 en un MiniPC o servidor (Windows o macOS).\n\n```\n ┌─ cron interno (cada N min) ──────────────────────────────────┐\n │   → GitHub REST API   (issues + metadata)                    │\n │   → SQLite local      (issues vistas, no duplicar)           │\n │   → LLM API compatible OpenAI (resumen + riesgo + propuesta) │\n │   → Dashboard React   (terminal-style, Geist Pixel / Mono)   │\n └──────────────────────────────────────────────────────────────┘\n```\n\n---\n\n## Stack\n\n- **Runtime**: [Bun](https://bun.com) (servidor + bundler + sqlite + .env loader)\n- **Frontend**: React 19 + Tailwind 4 + Geist Pixel / Geist Mono\n- **Base de datos**: `bun:sqlite` (modo WAL)\n- **LLM**: API compatible con OpenAI (endpoint y modelo configurables)\n\nSin dependencias extra de Node.js, Express, dotenv, better-sqlite3 ni nada por el estilo.\n\n---\n\n## Funcionalidades (v0.1)\n\n- ✓ Vigila N repos cada N minutos (configurable).\n- ✓ Detecta issues nuevas y las guarda en SQLite.\n- ✓ Las analiza con LLM local: resumen, tipo (bug/feature/docs/question), riesgo (low/med/high), archivos probables y propuesta de solución.\n- ✓ Dashboard minimalista con filtros y búsqueda.\n- ✓ Health check (`/api/health`) y status (`/api/status`).\n- ✓ Apagado limpio con SIGINT/SIGTERM (cierra SQLite sin corromper el WAL).\n- ✓ Recuperación de errores (un repo que falla no para el resto).\n\n---\n\n## Quick start (desarrollo)\n\nRequisito: [Bun ≥ 1.3](https://bun.com/docs/installation).\n\n```bash\nbun install\ncp .env.example .env       # edita y añade tu GITHUB_TOKEN\nbun dev                    # http://localhost:3741\n```\n\n`bun dev` arranca con HMR activo. Para producción local usa `bun start`.\n\n---\n\n## Variables de entorno\n\nBun carga `.env` automáticamente. Variables:\n\n| Variable | Por defecto | Descripción |\n|---|---|---|\n| `GITHUB_TOKEN` | _(vacío)_ | Fine-grained PAT con permisos read-only de Issues + Metadata sobre los repos a vigilar. **Recomendado**, sin token estás limitado a 60 req/h. |\n| `GITHUB_USER` | _(vacío)_ | Tu usuario, solo para mostrar en el header. Ej: `midudev`. |\n| `LLM_URL` | `http://localhost:1234/v1` | URL base del servidor compatible con OpenAI. Debe exponer `/models` y `/chat/completions`. Puede apuntar a otra máquina de la LAN. |\n| `LLM_MODEL` | `local-model` | Nombre del modelo a usar en las llamadas `chat/completions`. |\n| `LLM_API_KEY` | `sentinel-local` | Bearer token para servidores que lo requieran. Si tu servidor local no valida auth, puede ser cualquier string. |\n| `SENTINEL_INTERVAL_MS` | `1800000` (30 min) | Cada cuánto hacer el barrido. |\n| `SENTINEL_DB_PATH` | `data/sentinel.db` | Ruta al SQLite. Puede ser absoluta. |\n| `PORT` | `3741` | Puerto del servidor. |\n| `HOST` | `0.0.0.0` | Interfaz a la que bindear. Déjalo así para acceder desde la LAN. |\n\n\u003e Token recomendado: [github.com/settings/personal-access-tokens/new](https://github.com/settings/personal-access-tokens/new) → \"Only select repositories\" → solo los que quieras vigilar → permisos `Issues: Read-only` y `Metadata: Read-only`.\n\n---\n\n## Endpoints\n\n| Método | Ruta | Descripción |\n|---|---|---|\n| `GET` | `/api/health` | Healthcheck simple (uptime, pid, plataforma). Útil para monitorización externa. |\n| `GET` | `/api/status` | Estado completo: contadores, LLM, último scan. |\n| `GET` | `/api/repos` | Lista repos vigilados. |\n| `POST` | `/api/repos` | Añadir repo. Body: `{ \"repo\": \"owner/name\" }`. |\n| `DELETE` | `/api/repos/:id` | Dejar de vigilar. |\n| `GET` | `/api/issues?limit=N` | Issues con su análisis. |\n| `POST` | `/api/issues/:id/analyze` | Forzar análisis LLM de una issue. |\n| `POST` | `/api/check` | Disparar un scan inmediato. |\n\n---\n\n## Estructura del proyecto\n\n```\nsrc/\n  server/\n    index.ts        # Bun.serve + rutas + shutdown handler\n    db.ts           # bun:sqlite, schema y queries preparadas\n    github.ts       # cliente GitHub REST (fetch, sin Octokit)\n    llm.ts          # cliente LLM compatible OpenAI, JSON forzado\n    sentinel.ts     # scheduler de polling + analyzer en background\n  client/\n    index.html\n    main.tsx        # entry React\n    App.tsx\n    api.ts          # cliente tipado del API\n    styles.css      # @font-face + @theme Tailwind 4\n    utils.ts\n    fonts/          # Geist Pixel + Geist Mono (.woff2)\n    components/\n      Header.tsx\n      Stats.tsx\n      AddRepoForm.tsx\n      RepoList.tsx\n      IssueCard.tsx\npublic/\n  favicon.svg\nscripts/\n  service.ts             # wrapper cross-platform (Windows/macOS)\n  win/\n    install.ps1          # NSSM install\n    uninstall.ps1        # NSSM uninstall\n  macos/\n    sentinel.plist.template  # plantilla launchd\ndata/                # generado en runtime (sqlite + logs)\n```\n\n---\n\n## Gestionar el servicio (Windows y macOS)\n\nTodo se hace con un único set de scripts de `package.json`. El wrapper\n[`scripts/service.ts`](./scripts/service.ts) detecta la plataforma y delega\nen el backend correcto: **NSSM en Windows**, **launchd en macOS**.\n\n```bash\nbun service:install     # instala y arranca como servicio del sistema\nbun service:uninstall   # detiene, desinstala y opcionalmente borra data/\nbun service:start\nbun service:stop\nbun service:restart\nbun service:status\nbun service:logs        # tail -f del log en data/sentinel.log\n```\n\nEn ambos sistemas, al instalar:\n\n- El servicio queda configurado para **arrancar automáticamente** al iniciar el equipo.\n- Si el proceso cae, se **reinicia solo** (NSSM en Windows, `KeepAlive` en launchd).\n- **Logs** centralizados en `data/sentinel.log`.\n- El stop envía **SIGTERM**, no `kill -9`, así que el shutdown handler cierra SQLite limpio.\n\n### Requisitos en Windows\n\n1. [Bun para Windows](https://bun.com/docs/installation#windows) en el PATH (`%USERPROFILE%\\.bun\\bin\\bun.exe`).\n2. [NSSM](https://nssm.cc/download) en el PATH:\n   - Chocolatey: `choco install nssm`\n   - Scoop: `scoop install nssm`\n3. PowerShell **elevado** (Administrador) para `service:install` y `service:uninstall`.\n\n```powershell\n# Desde la carpeta del proyecto, en PowerShell admin:\nbun install\nbun service:install\n```\n\nEl backend Windows ejecuta [`scripts/win/install.ps1`](./scripts/win/install.ps1)\nque registra el servicio `GitHubSentinel` con NSSM:\n\n- Ejecutable: `bun.exe src/server/index.ts`\n- Logs rotados: `data\\sentinel.log`, max 5 MB o 24 h por archivo.\n- Stop con Ctrl+C con 10 s de gracia, kill del árbol de procesos si no responde.\n- Reinicio automático tras 5 s si cae.\n\n### Requisitos en macOS\n\n1. Bun instalado (lo detecta en `~/.bun/bin/bun`, Homebrew o `/usr/local`).\n2. Nada más. No requiere `sudo` porque el servicio se instala como **LaunchAgent**\n   del usuario (`~/Library/LaunchAgents/com.midudev.github-sentinel.plist`).\n\n```bash\nbun install\nbun service:install\n```\n\nEl backend macOS renderiza el plist desde [`scripts/macos/sentinel.plist.template`](./scripts/macos/sentinel.plist.template),\nsustituye `__PROJECT_DIR__`, `__BUN_PATH__` y `__PATH__`, lo copia a\n`~/Library/LaunchAgents/` y hace `launchctl load -w`. `KeepAlive=true` y\n`RunAtLoad=true` se encargan del resto.\n\n### Personalizar el nombre del servicio (Windows)\n\nSi quieres llamarlo de otra forma:\n\n```powershell\n$env:SENTINEL_SERVICE_NAME = \"MiSentinel\"\nbun service:install\n```\n\n### Comandos avanzados (si los necesitas)\n\nSi prefieres saltarte el wrapper, puedes invocar los scripts directamente:\n\n```powershell\n# Windows\n.\\scripts\\win\\install.ps1   -ServiceName GitHubSentinel\n.\\scripts\\win\\uninstall.ps1 -KeepData\n```\n\n```bash\n# macOS\nlaunchctl list | grep github-sentinel\nlaunchctl unload -w ~/Library/LaunchAgents/com.midudev.github-sentinel.plist\n```\n\n### Otras alternativas en Windows (sin NSSM)\n\nSi no quieres NSSM, tienes dos opciones manuales:\n\n**Tarea Programada**: `taskschd.msc` → crear tarea \"Al iniciar el equipo\" →\nejecutar `C:\\Users\\TU_USUARIO\\.bun\\bin\\bun.exe src/server/index.ts` desde\nla carpeta del proyecto. En propiedades marca \"Ejecutar con los privilegios\nmás altos\" y \"Reiniciar si falla\".\n\n**PM2**:\n```powershell\nnpm i -g pm2 pm2-windows-startup\npm2-startup install\npm2 start \"bun src/server/index.ts\" --name github-sentinel --cwd C:\\ruta\\github-sentinel\npm2 save\n```\n\n---\n\n## Notas para Windows\n\n- **WAL en SSD local**. SQLite usa modo WAL (más rápido y resistente a cortes). No pongas el `data/` en OneDrive, Dropbox ni unidades de red, no es seguro con WAL.\n- **Windows Defender**. Excluye la carpeta `data\\` de escaneo en tiempo real, si no se pondrá a leer el `.db-wal` constantemente y notarás latencia.\n- **Firewall**. Para acceder al dashboard desde otro equipo de la LAN:\n  ```powershell\n  New-NetFirewallRule -DisplayName \"GitHub Sentinel\" -Direction Inbound -Protocol TCP -LocalPort 3741 -Action Allow\n  ```\n  Luego: `http://IP-DEL-MINIPC:3741`.\n- **Suspensión**. Desactívala en Configuración → Sistema → Inicio/apagado → \"Nunca\" para PC y para suspensión.\n- **LLM API**. Si el servidor vive en otra máquina, pon `LLM_URL=http://192.168.x.x:PUERTO/v1` en `.env` y abre ese puerto en su firewall.\n\n---\n\n## Scripts disponibles\n\n```bash\n# Desarrollo\nbun dev                  # servidor con HMR\nbun start                # producción simple\nbun start:prod           # producción con NODE_ENV=production\nbun build                # build estático del cliente (opcional)\n\n# Gestión del servicio (Windows + macOS)\nbun service:install      # instala y arranca como servicio del sistema\nbun service:uninstall    # desinstala (pregunta si borrar data/)\nbun service:start\nbun service:stop\nbun service:restart\nbun service:status\nbun service:logs         # tail -f data/sentinel.log\n```\n\n---\n\n## Roadmap\n\n- v0.2 — clonar repo y aportar contexto real al LLM (ripgrep + heurística)\n- v0.3 — ejecutar tests en Docker para validar propuestas\n- v0.4 — generar patch (`git diff`) en lugar de prosa\n- v0.5 — abrir PR en draft desde el sentinel\n- v0.6 — soporte de webhooks (push-based en vez de polling)\n- v0.7 — notificaciones a Telegram / Discord\n\n---\n\n## Licencia\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmidudev%2Fgithub-sentinel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmidudev%2Fgithub-sentinel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmidudev%2Fgithub-sentinel/lists"}