← Back to agents

AGENTS.md from atopile/hivehaus

0 starsLast commit Oct 6, 2025

Agents Guide for hivehaus

This document is for AI coding agents and collaborators working in this repo inside Cursor/Windsurf. It summarizes the project shape, the Ato DSL constraints, and how to use the Atopile MCP server to be productive without breaking things.

What You’re Building

  • Smart home hardware project using Atopile and the Ato DSL.
  • Entry point defined in `ato.yaml` → build `default` targets `main.ato:App`.
  • The editor extension (Cursor/Windsurf) invokes the Atopile CLI to build; you generally don’t run the CLI directly here.

Smart Home Context

  • Scope: Reusable building blocks for common smart home devices (power input/PMIC, processors/MCUs, radios, sensors, and I/O), plus a growing set of complete device examples.
  • Targets: Designs intended to pair with firmware stacks like ESPHome (ESP32/ESP8266) and Zephyr-based projects (e.g., nRF52, ESP32 with Zephyr, etc.). Firmware isn’t authored in Ato; Ato captures the hardware structure so firmware teams can target consistent interfaces.
  • Goals: Hardware reuse, consistent interfaces (I2C/SPI/UART/GPIO/PWM/ADC, power rails), and easy mapping from “device example” → firmware config or application.

Suggested library organization (non-binding; align with maintainers):

  • Building blocks: MCUs, power stages, radio modules, sensor front-ends, IO drivers (relays, MOSFETs, triacs), connectors.
  • Device examples: Concrete products like plugs, light switches, sensor nodes, thermostats, door/window sensors, etc.

Design tips:

  • Keep blocks parameterized (e.g., `input_voltage: V`, `current_limit: A`, `i2c.address`).
  • Expose standard interfaces (e.g., `I2C`, `SPI`, `ElectricPower`, `ElectricLogic`) for easy composition.
  • Add `assert` statements to reflect firmware expectations (supply rails, pull-ups, logic levels, addresses, bus speeds).

Repo Layout

  • `main.ato`: project entry module (`module App`).
  • `ato.yaml`: project config (paths, builds, atopile version).
  • `layouts/`: place PCB layout files if/when generated.
  • `.cursor/`: MCP server config and Ato rules for the editor.
  • `CLAUDE.md`: reference for Ato grammar, examples, and library usage.

If/when the repo splits into libraries and examples, consider top-level folders such as `blocks/` (reusable modules/interfaces) and `examples/` (end devices). Until then, keep modules self-contained and clearly named.

Ato DSL Constraints (very important)

  • No control flow except experimental `for` loops: no `if`, no `while`.
  • No functions, classes, objects, exceptions, or generators.
  • Declarative only: no side effects, no imperative code.
  • Organize code with `module`, `component`, and `interface` blocks.
  • Define pins and signals, assign parameters, connect nets, apply traits, and assert constraints.

See detailed examples and full grammar in `CLAUDE.md` and `.cursor/rules/ato.mdc`.

Productive Patterns

  • Define modules and interfaces with clear pins and typed parameters.
  • Instantiate modules via `new`, optionally with templates like `<int_=1>`.
  • Connect with `~`, and use directed connections with `<~` and `~>` when needed.
  • Use `assert` liberally (voltages, ranges, tolerances) to bound design intent.
  • Use `trait` to annotate behavior/capabilities; prefer composition over retyping.
  • Arrays of submodules are supported (`new Module[10]`); experimental `for` loops can iterate them if feature is enabled.

Smart home specific patterns:

  • Power entry + regulation chain (e.g., AC/DC → DC/DC → rails), then MCU + radio + sensor buses.
  • Standardize sensor busses (I2C for environmental sensors; SPI for high-speed devices) and expose connectors/pads where appropriate.
  • For ESPHome-targeted designs, provide labeled GPIOs and power rails that map cleanly to ESPHome YAML; for Zephyr, align to common devicetree-friendly interfaces.

Things Not To Do

  • Don’t introduce procedural constructs (no conditionals, functions, or runtime state).
  • Don’t write Python/JS inside `.ato` files—Ato is its own declarative language.
  • Don’t depend on side effects; prefer explicit declarations, connections, and assertions.

Using the Atopile MCP Server (inside Cursor)

Configured in `.cursor/mcp.json` as `atopile`. Use it to discover and inspect library building blocks instead of guessing.

  • Discover interfaces: ask the MCP server for `get_library_interfaces`.
  • Discover modules: ask the MCP server for `get_library_modules`.
  • Inspect definitions: use `inspect_library_module_or_interface` to read code before instantiating.

Example agent intents (natural language to MCP):

  • “List common power and logic interfaces.”
  • “Show the API for `Resistor`, `Capacitor`, and `I2C`.”
  • “Inspect `ElectricPower` and `ElectricLogic` to confirm pin naming.”

Reference snippets (from CLAUDE.md):

  • `interface ElectricPower: hv = new Electrical; lv = new Electrical`
  • `module Resistor: resistance: ohm; max_power: W; unnamed = new Electrical[2]`
  • `interface I2C: scl = new ElectricLogic; sda = new ElectricLogic; frequency: Hz; address: dimensionless`

Common Tasks

Add a simple module:

```ato module SensorNode: vcc = new ElectricPower comm = new I2C pullup = new Resistor

pullup.resistance = 4.7kohm

Connect I2C lines to power reference, etc., as needed

comm.scl.reference ~ vcc comm.sda.reference ~ vcc ```

Instantiate and connect in `App`:

```ato module App: power = new ElectricPower node = new SensorNode

node.vcc ~ power assert power.hv within 3.0V to 3.6V ```

Array + experimental for-loop (if enabled via pragma):

```ato #pragma experiment("FOR_LOOP") module App: leds = new Resistor[4] for r in leds: r.resistance = 330ohm ```

Build and Validate

  • Build is driven by Cursor/Windsurf invoking the Atopile CLI.
  • Project declares `requires-atopile: "0.11.1"` in `README.md`/`ato.yaml`.
  • Default build entry is `main.ato:App` as set in `ato.yaml`.
  • If you need a new top module, update `ato.yaml` accordingly.

Firmware pairing notes:

  • ESPHome: After hardware stabilizes, provide a sample YAML (outside Ato) that maps exposed GPIOs, I2C addresses, and power rails to components.
  • Zephyr: Provide guidance or a sample board overlay and Kconfig for the chosen MCU; keep hardware interfaces named to match typical Zephyr drivers.

Conventions

  • Prefer newline-terminated simple statements; use semicolons to group related short ops on one line.
  • Use docstring-style strings at top of modules to explain intent.
  • Keep names clear and typed parameters explicit (e.g., `resistance: ohm`).
  • Put general language references in `CLAUDE.md`; keep `main.ato` tidy and minimal.
  • Prefer names that hint at firmware mapping (e.g., `i2c`, `spi`, `uart`, `pwm`, `led`, `button`, `relay`), and keep power rails explicit (`vbat`, `vcc3v3`, `vcc5v`).

When In Doubt

  • Check `CLAUDE.md` for syntax and grammar details.
  • Query the MCP server to discover correct library usage.
  • Ask the user for electrical requirements (voltages, currents, interfaces) and capture them as `assert` statements.
  • Consider the intended firmware stack (ESPHome or Zephyr) and ensure hardware interfaces and pinouts map cleanly to it.

Quick Checklist

  • Defined pins, signals, and types for every new module.
  • Connected nets intentionally; used traits or retyping when needed.
  • Added assertions for key electrical constraints.
  • Kept to declarative constructs; no forbidden features.
  • Updated `ato.yaml` if the entry point changed.