This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Setup
uv venv && uv pip install -e ".[dev]"
# Run tests
uv run pytest tests/ # all tests
uv run pytest tests/unit/ # unit tests only
uv run pytest -m "unit" # by marker
uv run pytest -m "not e2e and not multipass" # exclude slow tests
uv run pytest tests/unit/lb_runner/test_foo.py::test_bar # single test
# Quick smoke test
uv run python example.py
# Linting & formatting
uv run black .
uv run flake8
uv run mypy lb_runner lb_controller lb_app lb_ui
# Docs
uv pip install -e ".[docs,controller]"
uv run mkdocs serveThe library follows a layered architecture with strict import boundaries:
lb_ui/ → lb_app/ → lb_controller/ → lb_runner/
(CLI/TUI) (Stable facade) (Orchestration) (Execution)
↓
lb_plugins/
(Workloads)
Module responsibilities:
lb_runner/- Core execution: metric collectors (PSUtil, CLI, perf, eBPF), local runnerlb_controller/- Remote orchestration via Ansible, run journaling, state machinelb_app/- Stable API facade for CLI/UI integrationslb_ui/- CLI/TUI implementation (does not import into runner/controller)lb_analytics/- Data aggregation and reporting (Pandas, Matplotlib)lb_plugins/- Workload plugins (stress-ng, fio, dd, hpl, stream, dfaas)lb_provisioner/- Docker/Multipass provisioning helperslb_common/- Shared utilities and logging configuration
Key rules:
- Always use the public
api.pyexports:lb_runner.api,lb_controller.api,lb_app.api - Never import internal modules directly (enforced by flake8-tidy-imports in
.flake8) - Configure logging via
lb_common.api.configure_logging()in entrypoints - Keep stdout clean for
LB_EVENTstreaming when building custom UIs
Workloads are registered via Python entry points in pyproject.toml:
[project.entry-points."linux_benchmark.workloads"]
stress_ng = "lb_plugins.plugins.stress_ng.plugin:PLUGIN"Each plugin in lb_plugins/plugins/<name>/ contains:
plugin.py- Plugin definition andPLUGINconstantgenerator.py- Command generation logicansible/- Optional Ansible playbooks for setup/teardown
Tests live in tests/ with markers for filtering:
tests/unit/- Fast, isolated tests (subdirs:lb_runner/,lb_controller/, etc.)tests/integration/- Service-level tests, no provisioningtests/e2e/- Full end-to-end with Multipass VMs or Dockertests/fixtures/- Static test data
Markers: unit, integration, e2e, docker, multipass, slow, slowest
Generated at runtime (gitignored):
benchmark_results/- Raw metric data per runreports/- Generated text reports and plotsdata_exports/- Exported data files
- Python 3.12+, Black (88 chars), strict MyPy
snake_casefor functions/variables,PascalCasefor classes- Prefer dataclasses for configuration objects
lb_controller must only be imported via lb_controller.api from other packages (lb_app, lb_ui, lb_plugins, etc.).
Direct imports like from lb_controller.services.X import Y or from lb_controller.engine.X import Y are violations when done from outside lb_controller/.
This rule is enforced by flake8-tidy-imports in .flake8.