{"id":47609789,"url":"https://github.com/evgenii-engineer/openlight","last_synced_at":"2026-05-23T13:02:49.104Z","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-05-06T22:06:32.000Z","size":8985,"stargazers_count":25,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-06T22:27:11.133Z","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-05-06T22:06:36.000Z","dependencies_parsed_at":null,"dependency_job_id":"cfb1ff25-7058-4bcc-bf39-750671be1cd6","html_url":"https://github.com/evgenii-engineer/openLight","commit_stats":null,"previous_names":["evgenii-engineer/openlight"],"tags_count":4,"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":33396576,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T04:15:53.637Z","status":"ssl_error","status_checked_at":"2026-05-23T04:15:53.242Z","response_time":53,"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-01T19:59:32.354Z","updated_at":"2026-05-23T13:02:49.094Z","avatar_url":"https://github.com/evgenii-engineer.png","language":"Go","funding_links":[],"categories":[],"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\n**Lightweight local infrastructure agent for homelabs, Raspberry Pi, and personal servers — operated from Telegram.**\n\nYou declare which services, files, and SSH nodes are safe to touch.\nopenLight gives you a Telegram bot that checks status, tails logs,\nrestarts allowlisted services, and pages you when watches fire. One Go\nbinary, one YAML config, SQLite, optional local LLM. No frameworks.\nNo cloud. No hidden execution.\n\n## Why\n\nPlain shell scripts and ad-hoc bots stop scaling once you have more than\none host or more than one watch. Full agent frameworks are too heavy for\na Pi. openLight is the in-between: small enough to read end-to-end,\nopinionated enough to be useful out of the box.\n\n## Architecture in one diagram\n\n```\nTelegram / CLI\n     │\n     ▼\nauth → router  (slash → command → alias → semantic → optional LLM)\n     │\n     ▼\nskill registry  ── system, services, files, watch, notes, memory, chat\n     │\n     ▼\nSQLite     local processes     SSH nodes     optional Ollama / OpenAI\n```\n\nThe router is **deterministic-first**. Slash commands, explicit text, and\nsemantic rules run before the LLM is consulted. The LLM never bypasses\nthe Go-side allowlists — it can only choose among skills that are already\nregistered and resources that are already declared in your config.\n\n## Quick start (60 seconds)\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\nThis pulls the latest tagged release, drops `openlight-compose.yaml` into\n`./openlight`, and starts the bot plus a local Ollama. Open Telegram and\ntry:\n\n```\n/start\n/status\n/enable system\n/chat explain load average\n```\n\nFor deterministic-only mode (no LLM at all), set `LLM_ENABLED=false` before\nrunning the installer.\n\n## Single binary, three subcommands\n\n```\nopenlight agent     # run the Telegram bot (production)\nopenlight cli       # run a one-shot or interactive CLI session\nopenlight doctor    # validate config, allowlists, and dependencies\n```\n\n`openlight doctor` is the fast feedback loop. It loads your config,\nexercises every probe (Telegram, Ollama, SSH nodes, SQLite write), and\nprints OK / WARN / FAIL per check.\n\n## What it can do today\n\n- Check host status from Telegram: `/status`, `/cpu`, `/memory`, `/disk`,\n  `/uptime`, `/hostname`, `/ip`, `/temperature`.\n- Inspect, tail, and restart allowlisted services across local `systemd`,\n  Docker Compose, Docker, and named SSH **nodes**.\n- Create service and metric **watches**, then receive Telegram alerts with\n  `Restart`, `Logs`, `Status`, and `Ignore` action buttons.\n- Enable curated packs: `/enable docker`, `/enable system`, `/enable auto-heal`.\n- Run with local Ollama, deterministic-only, or remote providers like OpenAI.\n- Reuse the same runtime from Telegram, the CLI, and smoke tests.\n\n## Core vs. optional\n\nopenLight is split into a small **core** that defines its identity and a\nset of **optional** modules that you turn on only if you need them.\n\n**Core (always on):** `core`, `system`, `services`, `watch`, `files`,\n`notes`, `memory`.\n\n**Optional (off by default):** `chat`, `accounts`, `workbench`, `browser`,\n`vision`, `ocr`, `voice`, `visual_watch`.\n\nIf you never enable any optional module, openLight stays a deterministic,\nno-LLM, no-extra-deps Telegram bot for safe service ops. That is the\ndefault posture. See [docs/SKILLS.md](./docs/SKILLS.md).\n\n## Nodes\n\nA **node** is any machine openLight can reach over SSH. The local machine\nis implicit; everything else goes in the `nodes:` block:\n\n```yaml\nnodes:\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=node:vps:compose:/opt/matrix/docker-compose.yml:synapse\"\n```\n\nNow `/status matrix`, `/logs matrix`, and `/restart matrix` work against\nthe right backend on the right node, with the same Telegram UX as a local\nservice. See [docs/NODES.md](./docs/NODES.md).\n\n## Watches\n\nA **watch** is a background rule that polls and fires when a condition\nholds longer than a threshold:\n\n```\n/watch add service tailscale ask for 30s cooldown 10m\n/watch add cpu \u003e 90% for 5m cooldown 15m\n/watch list\n```\n\nWhen the condition trips, you get a Telegram alert with action buttons.\nThe buttons reuse the same skill surface as manual commands — one audit\npath for both. See [docs/WATCHES.md](./docs/WATCHES.md).\n\n## Run with Docker / Compose\n\nIf you cloned the repo, the top-level\n[openlight-compose.yaml](./openlight-compose.yaml) is the same bundled\nstack the installer uses:\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\nThe image ships with a minimal embedded config that only sets the SQLite\npath. Anything host-specific (file allowlists, services, nodes, webhook\nmode, OpenAI) needs a mounted config:\n\n```yaml\nservices:\n  openlight:\n    volumes:\n      - ./data:/var/lib/openlight/data\n      - ./agent.yaml:/etc/openlight/agent.yaml:ro\n```\n\n## Run locally\n\nPrerequisites: Go 1.25+, a writable SQLite path, a Telegram bot token.\n\n```bash\ncp configs/agent.example.yaml ./agent.yaml\n# edit ./agent.yaml\n\ngo run ./cmd/openlight agent -config ./agent.yaml\n```\n\nOther example configs:\n\n- [configs/agent.rpi.ollama.example.yaml](./configs/agent.rpi.ollama.example.yaml) — Raspberry Pi + Ollama\n- [configs/agent.macmini.example.yaml](./configs/agent.macmini.example.yaml) — Mac mini local-first\n- [configs/agent.openai.example.yaml](./configs/agent.openai.example.yaml) — OpenAI-backed\n\n`openlight agent` resolves config in this order: `-config`,\n`OPENLIGHT_CONFIG`, `/etc/openlight/agent.yaml`.\n\nFor local Ollama in the repo checkout:\n\n```bash\nmake llm-up\nmake llm-pull\ngo run ./cmd/openlight agent -config ./agent.yaml\n```\n\n## Deploy\n\nRaspberry Pi:\n\n```bash\ncp configs/agent.rpi.ollama.example.yaml ./agent.rpi.yaml\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\nMac mini (M1):\n\n```bash\ncp configs/agent.macmini.example.yaml configs/agent.macmini.yaml\nmake install-macmini-deps\nmake bootstrap-macmini SSH_HOST=100.x.y.z\nmake deploy-macmini SSH_HOST=100.x.y.z\nmake status-macmini SSH_HOST=100.x.y.z\n```\n\nService templates: [systemd](./deployments/systemd/openlight-agent.service),\n[launchd](./deployments/launchd/openlight-agent.plist).\n\n## Configuration reference\n\nTop-level keys:\n\n```yaml\ntelegram:    # bot token, polling/webhook mode\nauth:        # allowed_user_ids, allowed_chat_ids\nstorage:     # sqlite_path\nnodes:       # named SSH-reachable machines (legacy: access.hosts)\nservices:    # allowed targets + log limits\nwatch:       # poll interval + ask TTL\nfilesystem:  # safe local file read/write (legacy: files)\nllm:         # provider, endpoint, model, profiles\nchat:        # history limits for chat skill\nnotes:       # list limit\nmemory:      # persistent kv notes for the LLM\nagent:       # request_timeout\nlog:         # level\n# Optional surfaces, off by default:\naccounts:    # provider-driven user-management commands\nworkbench:   # restricted code/file execution\nbrowser:     # browser skill (Playwright)\nvision:      # VLM-backed image analysis\nocr:         # Tesseract OCR\nvoice:       # ffmpeg + whisper-cpp\nvisual_watch: # screenshot-diff watches (uses browser + ocr)\n```\n\nUseful env overrides: `TELEGRAM_BOT_TOKEN`, `ALLOWED_USER_IDS`,\n`ALLOWED_CHAT_IDS`, `SQLITE_PATH`, `LLM_ENABLED`, `LLM_PROVIDER`,\n`LLM_ENDPOINT`, `LLM_MODEL`, `OPENAI_API_KEY`, `LLM_PROFILE`,\n`TELEGRAM_MODE`, `TELEGRAM_WEBHOOK_URL`, `TELEGRAM_WEBHOOK_LISTEN_ADDR`,\n`TELEGRAM_WEBHOOK_SECRET_TOKEN`.\n\n## Project structure\n\n```\ncmd/openlight/      single binary: agent, cli, doctor subcommands\ninternal/runtime/   wires storage, skills, optional LLM, watch\ninternal/router/    deterministic + optional LLM classification\ninternal/core/      request lifecycle (the Agent type)\ninternal/skills/    built-in skill modules\ninternal/watch/     watch rules, incidents, alert actions\ninternal/storage/   SQLite repository\ninternal/telegram/  bot transport + UI\nconfigs/            example YAMLs\ndeployments/        systemd, launchd, docker\nmigrations/         embedded SQLite migrations\ndocs/               architecture, nodes, watches, skills\nscripts/            install + remote-deploy helpers\n```\n\n## Good fit / Not a fit\n\n**Good fit:**\n\n- Raspberry Pi, homelabs, and small self-hosted Linux boxes\n- Telegram-based status checks, alerts, and light operational actions\n- A small codebase you can read end-to-end and extend in Go\n\n**Not a fit:**\n\n- generic AI assistant\n- autonomous multi-agent platforms\n- enterprise orchestration framework\n- arbitrary shell autonomy\n- a browser-automation framework\n\n## Regression and smoke checks\n\n| Level | When | Command | Covers |\n|-------|------|---------|--------|\n| P0 | every commit | `make test` | unit/router/skill/config/storage/LLM-safety |\n| P0 smoke | every commit | `make smoke-cli` | local CLI flows against `configs/agent.test.yaml` |\n| P1 | before release | `make regression` | `make test` + `make smoke-cli` |\n| P2 | on a real host | `make smoke-macmini SSH_HOST=…` / `make smoke-rpi PI_HOST=…` | host deps, service manager, Telegram, Ollama |\n| Manual | post-deploy | 5-min Telegram sanity | `/start`, `/skills`, `/status`, logs, watches |\n\nCI runs `make test`. CI does not run P2 — those targets SSH into a real host.\nThe full matrix lives in [docs/REGRESSION.md](./docs/REGRESSION.md).\n\n## Contributing\n\nSmall, focused contributions are the best fit here.\n\n```bash\nmake test          # P0\nmake smoke-cli     # P0 deterministic CLI smoke\nmake regression    # P1: both, before release-shaped changes\nmake doctor        # validate ./configs/agent.example.yaml\n```\n\nFor deeper details, see [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md),\n[docs/NODES.md](./docs/NODES.md), [docs/WATCHES.md](./docs/WATCHES.md),\n[docs/SKILLS.md](./docs/SKILLS.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"}