Skip to content

Latest commit

 

History

History
197 lines (155 loc) · 10.3 KB

File metadata and controls

197 lines (155 loc) · 10.3 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with this repository. Read docs/agents/rules.md first — those constraints are non-negotiable and apply to all agents.

Verification Before Action

  • ALWAYS run tests locally before pushing commits — never push to any remote until local tests are green
  • ALWAYS verify against actual source code/repos before making assumptions about APIs, entity names, or naming patterns
  • NEVER speculate about file contents or behavior - read the file or run the code first
  • Before proposing any fix, show the exact code path and evidence (logs, source) that proves the root cause — do not guess at entity names, prefixes, or discovery logic

Agent Documentation Index

File When to Read
docs/agents/rules.md Always — hard constraints
docs/agents/architecture.md Before any structural change
docs/agents/patterns.md Before writing new code
docs/agents/testing.md Before writing or changing tests
docs/agents/workflow.md Before any commit, PR, or release
docs/agents/skill-architecture.md Before working on skills, the @claude-bot pipeline, or adding an integration
docs/agents/bess-knowledge.md Before answering any question about BESS behavior, savings calculations, optimizer decisions, or schedule logic
docs/agents/memory/ Project-specific memory (beta workflow, release train)

Project Overview

BESS Manager is a Home Assistant add-on for optimizing battery energy storage systems. It provides price-based optimization, solar integration, and a web interface for managing battery schedules and monitoring energy flows.

Development Commands

Backend (Python)

.venv/bin/pytest -m "not slow"           # fast tests (~3s, recommended)
.venv/bin/pytest -m slow                 # algorithm/integration tests (~30min)
.venv/bin/pytest                         # run all tests
.venv/bin/black . && .venv/bin/ruff check --fix .  # format and lint
./scripts/quality-check.sh               # full quality gate

Frontend (React/TypeScript)

cd frontend
npm install
npm run dev          # development server
npm run build        # production build
npm run lint:fix     # fix TypeScript issues
npm run generate-api # regenerate API client from OpenAPI spec

Docker Development

docker-compose up -d                                          # backend + frontend (dev)
docker compose -f docker-compose.ci.yml up -d                 # E2E dev with mock-HA (fast, volume mounts)
docker compose -f docker-compose.prod-test.yml up -d --build  # production image smoke test
docker-compose logs -f

Build Add-on

./package-addon.sh

Architecture in One Paragraph

FastAPI backend (backend/app.py) runs an hourly scheduler. The core optimization engine (core/bess/) uses dynamic programming to generate a 24-hour battery schedule from electricity spot prices and real-time sensor data. The schedule is sent to a Growatt inverter via the Home Assistant API. A React SPA (frontend/) provides the management interface.

Automated Agent Workflow

GitHub issues flow through a four-stage pipeline. Each stage is a separate workflow file with a self-contained prompt — there is no cross-stage routing through CLAUDE.md. All stages run on anthropics/claude-code-action@v1.

Stage Trigger Workflow Cost What it does
1. Triage issues: opened/edited (auto) issue-triage.yml ~$0.05 Classify + label only. Gates on debug log presence.
2. Analyze @claude-bot analyze (manual) issue-analyze.yml ~$0.50–2 Delegates to bess-analyst sub-agent, posts root-cause diagnosis. No code changes.
3. Fix @claude-bot fix (manual) issue-fix.yml ~$1–4 Runs the implement-issue skill in CI mode per the Stage 2 plan, opens draft PR.
4. Review @claude-bot on a PR (manual) pr-review.yml ~$0.50–2 Reviews diff against rules and checklist.
5. Integrate @claude-bot integrate (manual) issue-integrate.yml ~$2–10 Drives a new inverter/provider request through the full experimental→stable lifecycle (feature-lifecycle), one stage per invocation.

Why gated, not auto: Stages 2 and 3 cost real money. The user explicitly triggers each one after reading the previous stage's output.

Label flow:

opened ──► bug + needs-debug-log     (Stage 1: no log)
            │
            └─ user adds log ──► bug + ready-for-analysis  (Stage 1 re-runs on edit)
                                  │
                  @claude-bot analyze
                                  ▼
                                  analyzed                 (Stage 2)
                                  │
                  @claude-bot fix
                                  ▼
                                  has-fix-pr               (Stage 3, draft PR open)

If Stage 2 can't reach a conclusion it applies needs-human-review instead of analyzed.

General bot rules

  • Only the repo owner can trigger bot commands.
  • Always use gh CLI for all GitHub operations (issues, PRs, labels).
  • Never push directly to main. PRs are always opened as drafts.
  • The bot identity is bess-manager-claude-bot (a custom GitHub App). The official Anthropic Claude App is suspended to avoid collisions — do not unsuspend it.
  • Stage 2 must invoke the bess-analyst sub-agent. Skipping that step is the failure mode the previous design suffered from.

Release Workflow

  • Always release through a PR so CI runs — never push directly to a branch bypassing CI
  • Always check the current published version before tagging (e.g., check GitHub releases) to avoid version collisions
  • Confirm the target remote and branch BEFORE pushing releases (beta vs main, origin vs beta remote)
  • Run the full test suite locally before any release tag or beta push
  • Never skip the CHANGELOG.md update or version bump
  • beta/main only ever advances by fast-forward from origin/main — never commit directly to the beta repo. If a fix is needed on the currently-published stable version while main has moved on, use the hotfix procedure (short-lived release-X.Y branch cherry-picking from main), never a direct beta commit.
  • CHANGELOG.md is authored once, on origin/main, under ## [Unreleased]. Beta and stable releases both consume that section (copy for beta, rename for stable) — never hand-write a beta-specific or duplicate changelog entry.

Scope Discipline

  • Do NOT modify, remove, or 'clean up' items the user hasn't asked you to change
  • When doing cleanup, list what you plan to change and confirm before editing
  • Do not revert intentional linter changes or simplifications without explicit instruction
  • After editing, list every file and symbol changed so the user can confirm nothing unrelated was touched
  • Never add speculative fallbacks, defensive error handling, or "robustness" improvements beyond what was asked
  • Never add a parameter, flag, default-fallback, second construction site, or extra trigger whose only job is to route around an ordering/timing/dependency problem — fix that problem directly (reorder, or reuse/expose what already exists); see docs/agents/rules.md Debugging Protocol step 8

Cost Discipline

The user pays per token. A long Opus session that re-reads a large context after every multi-minute wait is what runs up the bill — not the work itself.

  • Default to Sonnet (set in .claude/settings.json). Use Opus only for a genuinely hard reasoning step, say so, and drop back. Don't run routine coordination, iteration, CI-watching, or file edits on Opus.
  • Never spawn Opus subagents, and avoid agents for long-running watches entirely; if delegation is truly needed, use a cheap model.
  • Don't hold one big session across many long CI/test waits. The prompt cache expires after ~5 min, so each long wait forces a full uncached re-read of the entire context. Prefer /clear between unrelated chunks, or let the session sit idle rather than re-engaging every few minutes.
  • Don't re-dump large files or logs into context.
  • Treat implement-issue Step 8 (verify, podman-compose/mock-HA E2E) as a session boundary. Kick it off, then either let the session sit idle until it completes or /clear and resume fresh once it's done — don't stay engaged re-touching the diagnosis/TDD context through the wait.

Worktree Conventions

Both layouts are first-class — either way the worktree is a normal git checkout, so per-agent inspect / test / run (./deploy.sh, pytest, the app) works the same. Choose by how you want to reach an agent's work:

  • Sibling folders (e.g. ../bess-manager-feature/) — open cleanly in their own VS Code window; this is the go-to when you actively inspect code and run scripts per agent. They work with Agent View too: start the background session inside the sibling (it's a linked git worktree, so Claude won't relocate it). Caveat: a sibling only appears in unscoped claude agents (or --cwd ~/GitHub), not in the project-scoped claude agents --cwd <repo> view.
  • Native .claude/worktrees/ (claude agents / --worktree / EnterWorktree) — auto-created for background sessions and visible in the project-scoped Agent View. Still a real checkout: code <repo>/.claude/worktrees/<name> or cd into it to run tests/scripts.

Find any session's worktree path by peeking/attaching it in Agent View, or via claude agents --json (the cwd field).

Home Assistant Integration

  • Sensors: battery SOC/power, solar production, grid import/export, pricing
  • Device: Growatt inverter (TOU schedule control)
  • Add-on config: bess_manager/config.yaml (version field, HA schema)
  • Pricing sources: Nordpool and Octopus Energy

Configuration Files

  • pyproject.toml — Black, Ruff, mypy settings
  • frontend/package.json — React/TypeScript dependencies
  • docker-compose.yml — development environment
  • bess_manager/config.yaml — HA add-on schema and current version (single source of truth)