# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Common Commands ### Development ```bash # Install dependencies mix deps.get # Compile the project mix compile # Run in development (non-halt mode) mix run --no-halt # Run tests mix test # Run specific test mix test test/systant_test.exs # Enter development shell (via Nix) nix develop # Run dashboard (Phoenix LiveView) cd dashboard && mix phx.server # or use justfile: just dashboard ``` ### Production ```bash # Build production release MIX_ENV=prod mix release # Run production release _build/prod/rel/systant/bin/systant start ``` ## Architecture Overview This is an Elixir OTP application that serves as a systemd daemon for MQTT-based system monitoring, designed for deployment across multiple NixOS hosts to integrate with Home Assistant. ### Core Components - **Systant.Application** (`lib/systant/application.ex`): OTP application supervisor that starts the MQTT client - **Systant.MqttClient** (`lib/systant/mqtt_client.ex`): GenServer that handles MQTT connection, publishes stats every 30 seconds, and listens for commands - **Dashboard.Application** (`dashboard/lib/dashboard/application.ex`): Phoenix LiveView dashboard application - **Dashboard.MqttSubscriber** (`dashboard/lib/dashboard/mqtt_subscriber.ex`): Real-time MQTT subscriber that feeds data to the LiveView dashboard - **Configuration**: MQTT settings configurable via environment variables or config files ### Key Libraries - **Tortoise**: MQTT client library for pub/sub functionality - **Jason**: JSON encoding/decoding for message payloads ### MQTT Behavior - Publishes "Hello from systant" messages with timestamp and hostname to stats topic every 30 seconds - Subscribes to commands topic for incoming events that can trigger user-customizable actions - Uses randomized client ID to avoid conflicts across multiple hosts - Sends immediate hello message on startup ### Default Configuration - **MQTT Host**: `mqtt.home` (not localhost) - **Stats Topic**: `systant/${hostname}/stats` (per-host topics) - **Command Topic**: `systant/${hostname}/commands` (per-host topics) - **Publish Interval**: 30 seconds ### NixOS Deployment This project includes a complete Nix packaging and NixOS module: - **Package**: `nix/package.nix` - Builds the Elixir release using beamPackages.mixRelease - **Module**: `nix/nixos-module.nix` - Provides `services.systant` configuration options - **Development**: Use `nix develop` for development shell with Elixir/Erlang The NixOS module supports: - Configurable MQTT connection settings - Per-host topic naming using `${config.networking.hostName}` - Environment variable configuration for runtime settings - Systemd service with security hardening - Auto-restart and logging to systemd journal ## Dashboard The project includes a Phoenix LiveView dashboard (`dashboard/`) that provides real-time monitoring of all systant instances. ### Dashboard Features - Real-time host status updates via MQTT subscription - LiveView interface showing all connected hosts - Automatic reconnection and error handling ### Dashboard MQTT Configuration - Subscribes to `systant/+/stats` to receive updates from all hosts - Uses hostname-based client ID: `systant-dashboard-${hostname}` to avoid conflicts - Connects to `mqtt.home:1883` (same broker as systant instances) ### Important Implementation Notes - **Tortoise Handler**: The `handle_message/3` callback must return `{:ok, state}`, not `[]` - **Topic Parsing**: Topics may arrive as lists or strings, handle both formats - **Client ID Conflicts**: Use unique client IDs to prevent connection instability ### Future Plans - Integration with Home Assistant via custom MQTT integration - Expandable command handling for host-specific automation - Multi-host deployment for comprehensive system monitoring