Metadata-Version: 2.4
Name: atech
Version: 1.0.0a2
Summary: Open-source Python SDK for Atech motherboards: catalog, codegen, build, flash, and runtime control.
Project-URL: Homepage, https://atech.dev
Project-URL: Repository, https://github.com/atechdotdev/python-sdk
Project-URL: Documentation, https://github.com/atechdotdev/python-sdk#readme
Author: Atech
License: MIT
Keywords: atech,claude-code,esp32,firmware,hardware,iot,platformio,serial
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Embedded Systems
Classifier: Topic :: System :: Hardware
Requires-Python: >=3.10
Requires-Dist: jinja2>=3.1
Requires-Dist: platformio>=6.1
Requires-Dist: pydantic<3.0,>=2.0
Requires-Dist: pyserial>=3.5
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Description-Content-Type: text/markdown

# atech

**The open-source way to write firmware for [Atech](https://atech.dev)
boards — designed for humans + coding agents working together.**

You have an Atech motherboard and you want it to do something. With this
SDK installed, you can ask Claude Code (or any coding agent that can run
Python) — *"make my board light up red when the button is pressed"* — and
the agent has everything it needs: a catalog of available modules, the
public API of each driver, deterministic codegen, a real compiler, and
an upload command. No cloud account, no AI prompts in the SDK, no
proprietary glue.

## Install

```bash
pip install atech
# or
uv add atech
```

PlatformIO is pulled in as a dep, so a single install builds and flashes.

## What it gives a coding agent

A coding agent working in a user's repo gets four things:

1. **A discoverable catalog** of bundled modules with rich metadata.
   ```bash
   atech list-modules
   atech list-modules --category sensor
   python -c "from atech import get_module; print(get_module('button').usage)"
   ```
   Each module's `usage:` field is a short C++ snippet showing the public
   API — no need for the agent to grep through driver headers.

2. **A small declarative project format** (`project.yaml`) that the agent
   writes or edits directly:
   ```yaml
   name: my_thing
   board: 8port
   modules:
     - {id: button,   instance: btn, port: 3}
     - {id: neopixel, instance: led, port: 4}
   code:
     loop: |
       if (btn.wasPressed()) { led.setAll(255, 0, 0); led.show(); }
   ```

3. **Mechanical, deterministic codegen.** `atech build` turns the YAML
   into a vanilla PlatformIO project, compiles it, and produces a
   `firmware.bin`. No LLM in this path — the agent owns the behavior,
   the SDK owns the plumbing.

4. **An upload + monitor flow** that doesn't require the user to know
   PlatformIO internals: `atech upload` / `atech monitor`.

## 60-second example

```bash
atech new thermo --board 8port
cd thermo
# Tell Claude (or write yourself):
#   "edit project.yaml to add a button on port 3 and a neopixel on port 4,
#    and in code.loop, cycle the neopixel through six colours on each press"
atech validate .
atech build .
atech upload .
```

Or, fully programmatic:

```python
from atech import Project

(
    Project(board="8port", name="thermo")
        .add("button",   port=3, instance="btn")
        .add("neopixel", port=4, instance="led")
        .set_loop("""
            if (btn.wasPressed()) {
                static uint8_t hue = 0;
                hue += 60;
                led.setAll(hue, 0, 255 - hue);
                led.show();
            }
        """)
        .build()
        .upload()
)
```

## Bringing your own module

If the bundled catalog doesn't cover what the user has, drop a folder
next to `project.yaml`:

```
my_project/
├── project.yaml          # add `modules_path: ./my_modules`
└── my_modules/
    └── lidar_v2/
        ├── module.yaml   # id, templates, usage, lib_deps
        ├── lidar_v2.h
        └── lidar_v2.cpp
```

Same shape as the SDK's
[`src/atech/catalog/data/modules/`](src/atech/catalog/data/modules/) tree.
The SDK merges your modules with the bundled catalog at build time; you
never have to fork.

## The full Python API

```python
import atech

# Discovery — what the agent should call first
atech.list_boards()
atech.list_modules(category="sensor")
atech.get_board("8port")
atech.get_module("button").usage     # C++ snippet showing the public API

# Project assembly
p = atech.Project(board="8port", name="weather")
p.add("button", port=3, instance="btn")
p.add("dc_motor", ports=(1, 2))            # double-width = adjacent pair
p.set_setup("Serial.println(\"booting\");")
p.set_loop("if (btn.wasPressed()) { Serial.println(\"hi\"); }")
p.use_modules_from("./my_modules")          # custom catalog directory
p.validate()                                # -> list[PlacementIssue]
p.describe()                                # human/agent summary + per-module usage
p.generate(out_dir="./build")               # -> Path to PlatformIO tree
p.build()                                   # -> BuildResult
p.upload(port="/dev/ttyACM0")               # -> UploadResult
p.to_yaml(); atech.Project.from_yaml(text); atech.Project.load(path)

# Runtime — after flashing
with atech.Board.connect() as board:
    for ev in board.events():
        print(ev.key, ev.value)
    board.send("led", {"r": 255, "g": 0, "b": 0})
```

## CLI

```text
atech list-boards
atech list-modules [--category X]
atech new <name> --board <id>          # scaffolds project.yaml + README
atech validate [project-dir]
atech build    [project-dir]
atech upload   [project-dir] [--port X]

atech ports                            # candidate USB devices
atech monitor  [--port X] [--type T,T] [--key K,K] [--json]
atech send <key> <value> [--port X]
```

## How a coding agent should drive it

[`CLAUDE.md`](CLAUDE.md) — drop a copy into your project root and your
coding agent will follow it. It covers: how to discover modules, how to
write the `code:` block, what *not* to do (invent modules, skip
validation, hand-edit generated files, use `delay()` in the loop).

## Architecture (short version)

```
┌────────────────────────────────────────────────────────────────────┐
│ atech.Project          ← agent assembles a hardware spec           │
├────────────────────────────────────────────────────────────────────┤
│ atech.placement        ← validates adjacency / reserved / overlap  │
│ atech.catalog          ← bundled + user-authored modules           │
│ atech.codegen          ← deterministic template stitching          │
│ atech.build / upload   ← `pio run` wrappers                        │
├────────────────────────────────────────────────────────────────────┤
│ atech.runtime.Board    ← serial client for the flashed board       │
└────────────────────────────────────────────────────────────────────┘
            │                                       │
       PlatformIO                              pyserial
            │                                       │
        ESP32 flash                          ESP32 USB-CDC
```

The closed Atech hosted product imports this SDK and layers AI module
selection, OTA, sharing, and signing on top. The open SDK is everything
needed to build firmware locally; nothing in this package phones home.

## Status

`v1.0.0a1` — alpha. Two boards (`8port`, `14port`) and nine bundled
modules: `button`, `rotary_encoder`, `pir` (motion), `aht20`
(temp/humidity), `neopixel`, `st7735_tft` (colour display), `speaker`
(I2S audio), `dc_motor`, and `stepper_motor`. More ship through the
catalog as they're ported in — run `atech list-modules` for the live list.
The runtime serial API is stable and preserves the v0.1.x surface under
`atech.runtime`.

See [`PRD.md`](PRD.md) and [`IMPLEMENTATION_PLAN.md`](IMPLEMENTATION_PLAN.md)
for the longer story.

## License

MIT.
