Beacon: A self-hosted error tracking and LLM observability in one place Beacon, a self-hosted error tracking and LLM observability tool from developer Tboworst, ingests errors from any service, groups them by root cause, and displays them in a live terminal dashboard or browser dashboard, with no third-party service or data leaving the user's infrastructure. The tool, available on GitHub, supports Node.js and Python SDKs, tracks LLM calls with token usage and cost, and integrates with Slack alerts, requiring Node.js 18+ for the web dashboard and running on port 7000 by default. Self-hosted error tracking and monitoring for developers who want control. Beacon ingests errors from any service, groups them by root cause, and surfaces everything in a live terminal dashboard — no third-party service, no data leaving your infrastructure, no monthly bill. Think lightweight Sentry, built for the terminal, owned by you. Beacon updated WebUI compressed.mp4 git clone https://github.com/Tboworst/beacon.git cd beacon cp .env.example .env add your API key and Slack webhook docker-compose up Server is running at http://localhost:7000 . Open the dashboard in a separate terminal: pip install textual python3 start dashboard.py git clone https://github.com/Tboworst/beacon.git cd beacon pip install -r requirements.txt cp .env.example .env python3 start server.py terminal 1 python3 start dashboard.py terminal 2 Beacon also ships a browser dashboard — same data as the TUI, served straight from the ingest server. Issues, LLM calls, alerts and deploys, with search, environment filters, resolve / reopen, and GitHub issue creation. Build it once, then the server does the rest requires Node.js 18+; Docker users skip this — the image builds it automatically : cd web npm install npm run build Start the server as usual and open http://localhost:7000 : python3 start server.py For frontend development, run the Vite dev server alongside — it proxies /api to the ingest server and hot-reloads: python3 start server.py terminal 1 cd web && npm run dev terminal 2 → http://localhost:5173 The TUI keeps working unchanged — both dashboards read the same beacon.db . macOS note: AirPlay Receiver also listens on port 7000. If http://localhost:7000 misbehaves, use http://127.0.0.1:7000 . Copy sdk/node/ into your project or npm install beacon-monitor once published : js const beacon = require './beacon' ; beacon.init { endpoint: 'http://your-beacon-server:7000/ingest', service: 'my-app', environment: 'production', apiKey: 'your-secret-key-here', } ; Unhandled exceptions and promise rejections are captured automatically. For caught errors: try { riskyOperation ; } catch err { beacon.capture err ; } LLM call tracking: js const t0 = Date.now ; try { const res = await openai.chat.completions.create { model: 'gpt-4o', messages } ; beacon.captureLlm { model: 'gpt-4o', inputTokens: res.usage.prompt tokens, outputTokens: res.usage.completion tokens, latencyMs: Date.now - t0, costUsd: res.usage.prompt tokens 0.000005 + res.usage.completion tokens 0.000015, feature: 'document-summarizer', } ; } catch err { beacon.captureLlm { model: 'gpt-4o', inputTokens: 0, outputTokens: 0, latencyMs: Date.now - t0, costUsd: 0, feature: 'document-summarizer', error: err } ; } Zero dependencies — uses Node's built-in http / https modules only. Install in your app: pip install requests Copy sdk/python/beacon/ into your project, then add two lines to your entry point: python import beacon beacon.init endpoint="http://your-beacon-server:7000/ingest", service="my-app", environment="production", api key="your-secret-key-here" matches BEACON API KEY in .env Every unhandled exception is now automatically captured. For handled exceptions: try: risky operation except Exception as e: beacon.capture e | Variable | Description | |---|---| BEACON API KEY | Secret key required on all ingest requests. If not set, server accepts all requests local dev mode . | SLACK WEBHOOK URL | Slack incoming webhook URL. Alerts fire when an error group crosses the threshold. | raw errors: "NoneType has no attribute 'email'" "NoneType has no attribute 'username'" fingerprint: AttributeError NoneType has no attribute