Files
Kao/CLAUDE.md
Spencer 9291066263 Add TODO.md and reframe CLAUDE.md around REST-push philosophy
Kao is a display, not a monitor — external systems push events via REST
rather than Kao polling things itself. Update CLAUDE.md to reflect this:
- New Design Philosophy section making the REST-first approach explicit
- Architecture diagram updated to show external systems as the push source
- Detectors section demoted to "Legacy Detectors" with a note to prefer push
- TODO.md added with planned REST API improvements (SSE, notify queue,
  sticky notifications, named presets, batch notify, /history endpoint)
  and display improvements (brightness curve, scrolling ticker)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 17:42:21 -06:00

7.3 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Important:

  • When updating this file, always update README.md as well. The README is the main user-facing documentation for the project.
  • On every commit, bump the version number in index.html (the VERSION constant) and update README.md with any relevant changes.

Project Overview

Kao is a minimalist ambient display for an old Pixel phone. It uses ASCII "emotes" to represent system health instead of graphs or dashboards. External systems (Home Assistant, Uptime Kuma, scripts, etc.) push events and notifications to Kao via REST — Kao itself does not poll or monitor anything.

Design Philosophy

Kao is a display, not a monitor. It should not duplicate work that other tools already do. The right pattern is: your existing monitoring stack detects a problem, then POSTs to Kao to show it. This keeps Kao simple and lets each tool do what it's good at.

The bundled detectors/ scripts are legacy and exist for standalone use cases. New work should focus on making the REST API richer, not adding more detectors.

Architecture

REST push model:

┌─────────────────────┐     POST /event      ┌─────────────┐     GET /status     ┌─────────────┐
│  External systems   │ ──────────────────▶  │  Aggregator │ ◀────────────────── │   Emote-UI  │
│  (HA, scripts, etc) │     POST /notify     │   (broker)  │                     │  (display)  │
└─────────────────────┘                      └─────────────┘                     └─────────────┘
  • Aggregator (aggregator.py) — Flask service managing the event queue and priority logic
  • Emote-UI (index.html) — OLED-optimized web frontend
  • Sentry (kao.py) — Unified entry point managing all processes
  • Detectors (detectors/*.py) — Legacy standalone sensors; prefer REST push from existing tools

Quick Start

python -m venv venv
source venv/bin/activate  # or .\venv\Scripts\activate on Windows
pip install -r requirements.txt
python kao.py

UI available at http://localhost:5100

Configuration

Edit config.json to configure detectors:

{
  "aggregator_url": "http://localhost:5100",
  "aggregator": { "script": "aggregator.py" },
  "detectors": [
    {
      "name": "cpu",
      "enabled": true,
      "script": "detectors/cpu.py",
      "env": { "CHECK_INTERVAL": "30", "THRESHOLD_WARNING": "85", "THRESHOLD_CRITICAL": "95" }
    }
  ]
}

Legacy Detectors

These bundled scripts exist for standalone use but are not the preferred approach. Prefer pushing from Home Assistant, Uptime Kuma, or any tool that already monitors what you care about.

Detector Script Required Env Vars
Disk Space detectors/disk_space.py
CPU detectors/cpu.py
Memory detectors/memory.py
Service detectors/service.py SERVICES (comma-separated process names)
Network detectors/network.py HOSTS (comma-separated hostnames/IPs)
Docker detectors/docker.py CONTAINERS (optional, monitors all if empty)

All detectors support: AGGREGATOR_URL, CHECK_INTERVAL, THRESHOLD_WARNING, THRESHOLD_CRITICAL

API Endpoints

Endpoint Method Description
/event POST Register event: {"id": "name", "priority": 1-4, "message": "optional", "ttl": seconds}
/clear POST Clear event: {"id": "name"}
/clear-all POST Clear all active events
/notify POST Notification with optional customization (see below)
/sleep POST Enter sleep mode
/wake POST Exit sleep mode
/status GET Current state JSON
/events GET List active events
/docs GET Interactive API documentation (Swagger UI)

/notify Endpoint

{
  "message": "Someone at the door",
  "duration": 10,
  "emote": "( °o°)",
  "color": "#FF9900",
  "animation": "popping",
  "sound": "chime"
}
Field Required Description
message No Text to display below emote
duration No Seconds before auto-expire (default: 5)
emote No Custom emote to display
color No Custom color (hex, e.g., #FF9900)
animation No One of: breathing, shaking, popping, celebrating, floating, bouncing, swaying
sound No One of: chime, alert, warning, critical, success, notify, doorbell, knock, ding, blip, siren, tada, ping, bubble, fanfare, alarm, klaxon, none

Priority System

Lower number = higher priority. Events with a ttl auto-expire (heartbeat pattern).

Priority State Emote Color Animation
1 Critical ( x_x) Red shaking
2 Warning ( o_o) Yellow breathing
3 Notify ( 'o') Blue popping
4 Optimal varies Green varies

Personality System

The optimal state face is set once per day on /wake (random pick). Each morning a fresh emote is chosen:

Emote Animation Vibe
( ^_^) breathing calm
(◕‿◕) bouncing cheerful
( ・ω・) swaying curious
( ˘▽˘) breathing cozy

Additional states:

  • Idle expressions (15% chance): ( -_^), ( ^_~), ( ᵕ.ᵕ) with blink animation
  • Recovery celebration: \(^o^)/ with bounce for 5 seconds after issues resolve
  • Connection lost: ( ?.?) gray, searching animation
  • Sleep mode: ( -_-)zzZ dim, very slow breathing

Home Assistant Integration

Add REST commands to configuration.yaml:

rest_command:
  kao_notify:
    url: "http://kao-host:5100/notify"
    method: POST
    content_type: "application/json"
    payload: '{"message": "{{ message }}", "duration": {{ duration | default(5) }}}'

  kao_sleep:
    url: "http://kao-host:5100/sleep"
    method: POST

  kao_wake:
    url: "http://kao-host:5100/wake"
    method: POST

Use in automations:

# Doorbell notification
- service: rest_command.kao_notify
  data:
    message: "Someone at the door"
    duration: 10

# Bedtime routine
- service: rest_command.kao_sleep

# Morning routine
- service: rest_command.kao_wake

File Structure

├── kao.py              # Unified entry point
├── aggregator.py       # Event broker/API server
├── index.html          # OLED-optimized frontend
├── kao_tui.py          # Developer TUI for testing sounds/events
├── config.json         # Runtime configuration
├── openapi.yaml        # API documentation (OpenAPI 3.0)
├── detectors/
│   ├── base.py
│   ├── disk_space.py
│   ├── cpu.py
│   ├── memory.py
│   ├── service.py
│   ├── network.py
│   └── docker.py
├── requirements.txt
├── TODO.md             # Planned features and improvements
└── SPEC.md             # Original project specification