{"id":48675750,"url":"https://github.com/evgenii-engineer/openLight","last_synced_at":"2026-04-26T10:00:49.436Z","repository":{"id":344155250,"uuid":"1180666490","full_name":"evgenii-engineer/openLight","owner":"evgenii-engineer","description":"Lightweight AI agent runtime for Raspberry Pi and homelabs, built around deterministic skills and local LLMs.","archived":false,"fork":false,"pushed_at":"2026-04-12T12:37:25.000Z","size":8938,"stargazers_count":25,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-12T14:19:27.463Z","etag":null,"topics":["ai-agent","edge-ai","go","golang","homelab","llm","local-ai","ollama","raspberry-pi","self-hosted","telegram"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/evgenii-engineer.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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-03-13T09:28:18.000Z","updated_at":"2026-04-12T12:37:26.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/evgenii-engineer/openLight","commit_stats":null,"previous_names":["evgenii-engineer/openlight"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/evgenii-engineer/openLight","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evgenii-engineer%2FopenLight","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evgenii-engineer%2FopenLight/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evgenii-engineer%2FopenLight/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evgenii-engineer%2FopenLight/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/evgenii-engineer","download_url":"https://codeload.github.com/evgenii-engineer/openLight/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evgenii-engineer%2FopenLight/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32292958,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T09:34:17.070Z","status":"ssl_error","status_checked_at":"2026-04-26T09:34:00.993Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["ai-agent","edge-ai","go","golang","homelab","llm","local-ai","ollama","raspberry-pi","self-hosted","telegram"],"created_at":"2026-04-10T15:00:32.438Z","updated_at":"2026-04-26T10:00:49.428Z","avatar_url":"https://github.com/evgenii-engineer.png","language":"Go","funding_links":[],"categories":["automation"],"sub_categories":[],"readme":"# openLight\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/output.gif\" width=\"500\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  Synapse went down → Restart → Back online\n\u003c/p\u003e\n\n[![Go](https://img.shields.io/badge/Go-1.25+-00ADD8?logo=go\u0026logoColor=white)](./go.mod)\n[![CI](https://github.com/evgenii-engineer/openLight/actions/workflows/ci.yml/badge.svg)](https://github.com/evgenii-engineer/openLight/actions/workflows/ci.yml)\n[![License](https://img.shields.io/badge/License-MIT-green)](./LICENSE)\n\nSafe Telegram ops for Raspberry Pi, homelabs, and small Linux hosts.\n\n`openLight` is a lightweight self-hosted agent for checking box status, handling safe service actions, and receiving actionable alerts from Telegram. It exists for setups where a full agent framework is too heavy, but plain scripts and ad hoc bots are not enough.\n\n- Deterministic-first routing. Slash commands, explicit commands, aliases, and semantic rules run before LLM fallback.\n- Safe allowlisted operations. Files, services, runtimes, and remote hosts must be declared in config.\n- Local Ollama by default. The bundled Docker path starts `openLight` with Ollama, but the same runtime can also run deterministic-only or with OpenAI.\n\n## Good fit / Not a fit\n\nGood fit:\n\n- Raspberry Pi, homelabs, and small self-hosted Linux boxes\n- Telegram-based status checks, alerts, and light operational actions\n- Users who want a small codebase they can inspect and extend\n\nNot a fit:\n\n- browser agents\n- arbitrary shell autonomy\n- complex multi-agent orchestration\n\n## What it can do today\n\nCore use case: safe Telegram-based status checks, service actions, and alerts for self-hosted boxes.\n\n- Check host status quickly from Telegram with `status`, `cpu`, `memory`, `disk`, `uptime`, `hostname`, `ip`, and `temperature`.\n- Inspect, tail logs, and restart allowlisted services across local `systemd`, Docker Compose, Docker, and named SSH targets.\n- Create service and metric watches, then receive Telegram alerts with `Restart`, `Logs`, `Status`, and `Ignore` actions.\n- Enable built-in packs with `/enable docker`, `/enable system`, and `/enable auto-heal`.\n- Run with local Ollama, deterministic-only mode, or remote providers such as OpenAI.\n- Reuse the same runtime from Telegram and `cmd/cli` for local execution and smoke checks.\n\n## Quick start\n\nRecommended path: use the bundled installer. It resolves the latest tagged release, downloads `openlight-compose.yaml`, and starts `openLight` plus `Ollama` in `./openlight`.\n\n```bash\nexport TELEGRAM_BOT_TOKEN=123456:replace-me\nexport ALLOWED_USER_IDS=111111111\ncurl -fsSL https://raw.githubusercontent.com/evgenii-engineer/openLight/master/scripts/install.sh | bash\n```\n\nAfter it starts, open Telegram and try:\n\n```text\n/start\n/status\n/enable system\n/chat explain load average\n```\n\nTypical first-minute flow with the bundled default stack:\n\n```text\nYou: /status\nopenLight:\nHostname: \u003chost\u003e\nCPU: \u003cusage\u003e\nMemory: \u003cused\u003e / \u003ctotal\u003e\n\nYou: /enable system\nopenLight:\nSystem pack enabled.\nCreated 3 watch(es), updated 0.\nDefaults: CPU \u003e 90%, Memory \u003e 90%, Disk / \u003e 85%.\nSystem alerts will offer quick Status and Ignore actions.\n```\n\nWith allowlisted services configured, a service alert looks like:\n\n```text\nYou: /watch add service tailscale ask for 30s cooldown 10m\nopenLight:\nWatch created:\n#7 service/tailscale down\n\nLater, if the service goes down:\nopenLight:\nAlert #7\ntailscale is down\n[Restart] [Logs] [Status] [Ignore]\n```\n\nThat is the core loop: define a safe watch once, then handle real incidents from Telegram.\n\nIf you want deterministic-only mode, set `LLM_ENABLED=false` before running the installer.\n\n## Architecture overview\n\n```text\nTelegram or CLI\n  -\u003e auth checks\n  -\u003e router\n  -\u003e skill registry\n  -\u003e storage / watch service / optional LLM\n```\n\n- `cmd/agent` runs the Telegram bot in polling or webhook mode.\n- `cmd/cli` runs the same runtime locally and adds one-shot execution plus smoke tests.\n- `internal/app` wires storage, skills, the optional LLM provider, and the watch service.\n- `internal/router` handles slash commands, explicit command text, semantic rules, and optional LLM classification.\n- `internal/skills` contains the built-in modules: `system`, `services`, `files`, `notes`, `watch`, `chat`, `accounts`, and `workbench`.\n- `internal/storage/sqlite` persists messages, skill calls, notes, watches, watch incidents, and settings.\n\n## Run with Docker / Compose\n\nIf you already cloned the repo, the top-level [openlight-compose.yaml](./openlight-compose.yaml) is the same bundled stack used by the installer.\n\n```bash\ngit clone https://github.com/evgenii-engineer/openLight.git\ncd openLight\n\nexport TELEGRAM_BOT_TOKEN=123456:replace-me\nexport ALLOWED_USER_IDS=111111111\ndocker compose up -d\n```\n\nThis stack starts:\n\n- `openlight` from `ghcr.io/evgenii-engineer/openlight:latest`\n- `ollama`\n- `ollama-pull`, which pulls `qwen2.5:0.5b` by default\n\nNotes for the bundled stack:\n\n- It is aimed at the local Ollama path.\n- It only mounts `./data` by default.\n- The image ships with a minimal `/etc/openlight/agent.yaml` that only sets the SQLite path.\n- The bundled Compose env expects `ALLOWED_USER_IDS` for the quick-start path.\n- If you want host file access, host service access, remote SSH hosts, workbench, accounts, webhook mode, or a different provider setup, mount your own config file.\n\nExample mount:\n\n```yaml\nservices:\n  openlight:\n    volumes:\n      - ./data:/var/lib/openlight/data\n      - ./agent.yaml:/etc/openlight/agent.yaml:ro\n```\n\nFor deterministic-only Docker usage:\n\n```bash\nexport LLM_ENABLED=false\ndocker compose up -d\n```\n\n## Run locally\n\nPrerequisites:\n\n- Go `1.25+`\n- a writable SQLite path\n- a Telegram bot token\n\nStart from the closest example config:\n\n- [configs/agent.example.yaml](./configs/agent.example.yaml): deterministic baseline\n- [configs/agent.rpi.ollama.example.yaml](./configs/agent.rpi.ollama.example.yaml): Raspberry Pi plus Ollama\n- [configs/agent.openai.example.yaml](./configs/agent.openai.example.yaml): OpenAI-backed\n\nExample local run:\n\n```bash\ncp configs/agent.example.yaml ./agent.yaml\n# edit ./agent.yaml\n\ngo run ./cmd/agent -config ./agent.yaml\n```\n\nIf you want local Ollama for the repo checkout:\n\n```bash\nmake ollama-up\nmake ollama-pull\ngo run ./cmd/agent -config ./agent.yaml\n```\n\nThe agent binary checks config in this order:\n\n1. `-config`\n2. `OPENLIGHT_CONFIG`\n3. `/etc/openlight/agent.yaml`\n\nFor Raspberry Pi deployment, the repo includes build and deploy helpers:\n\n```bash\ncp configs/agent.rpi.ollama.example.yaml ./agent.rpi.yaml\n# edit ./agent.rpi.yaml\n\nmake deploy-rpi-full PI_HOST=raspberrypi.local PI_USER=pi CONFIG_SRC=./agent.rpi.yaml\nmake smoke-rpi-cli-ollama PI_HOST=raspberrypi.local PI_USER=pi SMOKE_FLAGS='-smoke-all'\n```\n\nThe systemd unit template is [deployments/systemd/openlight-agent.service](./deployments/systemd/openlight-agent.service).\n\n## Configuration\n\nImportant config sections:\n\n- `telegram`: bot token, polling or webhook mode, webhook URL and listen address.\n- `auth`: allowed Telegram user IDs and chat IDs.\n- `storage`: SQLite path.\n- `services`: allowed service targets plus log limits.\n- `files`: allowed file roots plus read and list limits.\n- `access.hosts`: named SSH hosts for remote service targets.\n- `watch`: background polling interval and ask TTL.\n- `llm`: provider, endpoint, model, thresholds, and optional profiles.\n- `accounts`: explicit account-provider commands executed inside already allowed services.\n- `workbench`: optional runtimes, allowed files, and output limits.\n\nUseful env overrides:\n\n- `TELEGRAM_BOT_TOKEN`\n- `ALLOWED_USER_IDS`\n- `ALLOWED_CHAT_IDS`\n- `SQLITE_PATH`\n- `LLM_ENABLED`\n- `LLM_PROVIDER`\n- `LLM_ENDPOINT`\n- `LLM_MODEL`\n- `OPENAI_API_KEY`\n- `LLM_PROFILE`\n- `TELEGRAM_MODE`\n- `TELEGRAM_WEBHOOK_URL`\n- `TELEGRAM_WEBHOOK_LISTEN_ADDR`\n- `TELEGRAM_WEBHOOK_SECRET_TOKEN`\n\nExample service and remote-host config:\n\n```yaml\naccess:\n  hosts:\n    vps:\n      address: \"203.0.113.10:22\"\n      user: \"root\"\n      password_env: \"OPENLIGHT_VPS_PASSWORD\"\n      known_hosts_path: \"/home/pi/.ssh/known_hosts\"\n\nservices:\n  allowed:\n    - tailscale\n    - \"matrix=compose:/home/pi/matrix/docker-compose.yml\"\n    - \"web=host:vps:docker:docker-jitsi-meet_web_1\"\n```\n\nPolling is the default Telegram mode. Webhook mode is supported through `telegram.mode: webhook` and `telegram.webhook.*`.\n\n## Skills, routing, providers\n\nRouting order:\n\n1. slash commands\n2. explicit command text such as `service tailscale`\n3. skill names and aliases\n4. semantic rules\n5. optional LLM route and skill classification\n6. `chat` fallback when LLM is enabled\n\nThe LLM never bypasses the Go-side allowlists. Files, services, remote hosts, accounts, and workbench access still have to be explicitly configured.\n\nBuilt-in LLM providers:\n\n- `generic`\n- `ollama`\n- `openai`\n\nYou can keep multiple LLM profiles in one config file and switch with `LLM_PROFILE`:\n\n```yaml\nllm:\n  enabled: true\n  profile: \"ollama\"\n  profiles:\n    ollama:\n      provider: \"ollama\"\n      endpoint: \"http://127.0.0.1:11434\"\n      model: \"qwen2.5:0.5b\"\n    openai:\n      provider: \"openai\"\n      endpoint: \"https://api.openai.com/v1\"\n      model: \"gpt-4o-mini\"\n```\n\nFor OpenAI, set `OPENAI_API_KEY` or provide `llm.api_key` in your config.\n\nThen switch without editing the file:\n\n```bash\nLLM_PROFILE=openai go run ./cmd/agent -config ./agent.yaml\n```\n\n## Example workflows and commands\n\nBasic Telegram session:\n\n```text\n/start\n/skills\n/status\n/services\n/service tailscale\n/logs tailscale\n/restart tailscale\n```\n\nWatch setup:\n\n```text\n/enable docker\n/enable system\n/watch add service tailscale ask for 30s cooldown 10m\n/watch add cpu \u003e 90% for 5m cooldown 15m\n/watch list\n/watch history\n```\n\nFiles and notes:\n\n```text\n/files\n/read /tmp/openlight/example.txt\n/write /tmp/openlight/example.txt :: hello\n/replace hello with hi in /tmp/openlight/example.txt\n/note rotate backups\n/notes\n```\n\nLocal CLI:\n\n```bash\ngo run ./cmd/cli -config ./agent.yaml -exec \"status\"\ngo run ./cmd/cli -config ./agent.yaml -exec \"watch list\"\ngo run ./cmd/cli -config ./agent.yaml -smoke\ngo run ./cmd/cli -config ./agent.yaml -smoke-all\n```\n\n## Advanced capabilities\n\n- SQLite-backed notes, watches, incidents, messages, and skill-call history\n- Allowlisted file read, write, and replace operations\n- Optional account-provider flows executed through already allowed services\n- Optional workbench runtime for restricted code and file execution\n- Polling and webhook Telegram modes\n- Multiple LLM profiles switched with `LLM_PROFILE`\n\n## Project structure\n\n- [cmd/agent](./cmd/agent): Telegram runtime\n- [cmd/cli](./cmd/cli): local runner and smoke harness\n- [internal/app](./internal/app): runtime wiring\n- [internal/router](./internal/router): deterministic routing and optional LLM classifier\n- [internal/skills](./internal/skills): built-in modules\n- [internal/watch](./internal/watch): watch rules, incidents, and alert actions\n- [internal/storage/sqlite](./internal/storage/sqlite): SQLite storage\n- [configs](./configs): example configs\n- [deployments/docker](./deployments/docker): Docker stack files\n- [deployments/systemd](./deployments/systemd): systemd unit template\n- [scripts](./scripts): install and Raspberry Pi deploy helpers\n- [migrations](./migrations): embedded SQLite migrations\n\n## Current limitations\n\n- Telegram is the primary interface. The CLI is mainly for local execution and smoke tests.\n- Local service control is Linux-oriented and assumes `systemd`, Docker Compose, Docker, or configured SSH targets.\n- Metric watches currently support `notify` only. `ask` and `auto` restart flows apply to service-down watches.\n- Running inside Docker does not automatically expose host services or files. You need an explicit config plus the right mounts or sockets.\n- The bundled Docker path is optimized for local Ollama. If you want OpenAI or another remote provider in Docker, use a mounted config and, if needed, extend the Compose environment.\n\n## Contributing\n\nSmall, focused contributions are the best fit here.\n\nBefore opening a PR:\n\n```bash\nmake test\n```\n\nOptional real Ollama end-to-end run:\n\n```bash\nmake ollama-up\nmake ollama-pull\nmake test-e2e-ollama\nmake ollama-down\n```\n\nFor deeper project details, see [ARCHITECTURE.md](./ARCHITECTURE.md) and [CHANGELOG.md](./CHANGELOG.md).\n\n## License\n\nMIT. See [LICENSE](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevgenii-engineer%2FopenLight","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevgenii-engineer%2FopenLight","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevgenii-engineer%2FopenLight/lists"}