This release is a pre-release and may not be stable for production use.
atech
Firmware for Atech boards from one small file, built so a coding agent can drive it.
An Atech board is an ESP32-S3 with numbered ports; modules slide into the ports.
You (or Claude Code, Cursor, any agent that can run a shell) describe the build in
project.yaml. The SDK picks the pins, assembles the drivers, generates the
firmware, compiles it, flashes it, and then lets you talk to the board from your
computer. No cloud account. Nothing in this package phones home.
You: "make the light go red when I press the button"
Agent: atech list-modules → atech info button → writes project.yaml
atech validate → atech build → atech upload → atech check
Install
pip install atech
Python 3.10+. PlatformIO comes with it. The first atech build downloads the
ESP32 compiler, about 2.4 GB on disk, once. After that, builds work offline and
take seconds. A module that needs a library (the light grid, for one) fetches it the
first time a project uses it.
Sixty seconds
atech new blink --board 14port # project.yaml + AGENTS.md / CLAUDE.md for your agent
cd blink
Edit project.yaml:
name: blink
board: 14port
modules:
- {id: button, instance: btn, port: 1}
- {id: neopixel, instance: led, port: 2}
code:
loop: |
if (btn.wasPressed()) { led.setAll(255, 0, 0); led.show(); }
atech describe . # what is placed, each module's API, its events and actions
atech validate .
atech build .
atech upload . # board on USB, data cable
atech check # which modules answered after boot
Then, from the computer:
atech monitor # [button] btn = 1
atech send led_fill r=0 g=0 b=255 # ok: the board carried out led_fill
For coding agents
atech guide # the guide: workflow, rules, what will bite you
atech guide protocol # the wire format: events, actions, acknowledgements
atech new writes the guide into the project as AGENTS.md and CLAUDE.md, so an
agent started in that folder reads it without being told.
Commands
atech guide [protocol] the docs above
atech list-boards [--json] boards, their module ports and UART ports
atech list-modules [--category X] [--json]
atech info <module> [--json] description, cautions, C++ API, events, actions
atech new <name> --board <id>
atech describe [dir] a project's modules, API, events and actions
atech validate [dir]
atech build [dir]
atech upload [dir] [--port X]
atech check reboot the board; which modules answered, and why not
atech monitor [--key K,K] [--type T,T] [--json]
atech send <key> [value] exit 0 only if the board confirmed it (value: r=0 g=255, a number, or JSON)
atech ports USB ports that look like a board
atech free-port release a port another process holds
Every command prints error: … on stderr and exits non-zero when it fails.
Python
import atech
atech.list_boards(); atech.list_modules(category="sensor")
atech.get_module("button").usage # the C++ API of a module
p = (
atech.Project(board="14port", name="blink")
.add("button", port=1, instance="btn")
.add("neopixel", port=2, instance="led")
.set_loop('if (btn.wasPressed()) { led.setAll(255, 0, 0); led.show(); }')
)
print(p.describe()) # modules, API, events, actions, cautions
p.validate() # -> list of placement issues
p.build() # -> BuildResult
p.upload() # -> UploadResult
atech.Project.load("blink") # a folder or a project.yaml
with atech.Board.connect() as board: # NoBoardFoundError if no board is on USB
board.call("led_fill", {"r": 0, "g": 0, "b": 255}) # raises unless the board confirms
for ev in board.events(keys=["btn"]):
print(ev.key, ev.value)
board.call() waits for the board's acknowledgement, and board.query(action, reply=event_key) returns the value the board answers with. board.send() only
writes to the port and tells you nothing. One program holds a board's port at a
time: stop atech monitor before atech send or atech upload.
Robot arm: check the power supply and the arm first
The Robot Arm module passes the board's high-voltage rail (labelled 12 V) straight to the servos. That rail is fed by a power module (the power jack module, or the USB-C PD power module) and carries whatever that module is given. Nothing regulates it, and the standard USB-C module does not feed it.
- SO-101 arms come in a 12 V and a 5 V version.
- The supply must match the arm: a 12 V supply for the 12 V arm, a 5 V supply for the 5 V arm.
- A 12 V supply on a 5 V arm damages the servos.
- Never plug more than 12 V into the jack.
- Check the voltage printed on the supply, and which arm you have, before you connect anything.
- Both versions have been run this way: power jack module and Robot Arm module, nothing outside the Atech stack.
atech validate, atech build and atech upload print this as a CAUTION
whenever a project contains robot_arm.
Bringing your own module
my_project/
├── project.yaml # add: modules_path: ./my_modules
└── my_modules/
└── lidar_v2/
├── module.yaml # id, templates, usage, events, actions, lib_deps
├── lidar_v2.h
└── lidar_v2.cpp
Same shape as the bundled modules, which sit in the installed package under
atech/catalog/data/modules/. A module with the same id as a bundled one
replaces it. Declare only events the loop template really prints, and give
every action a handler:.
How it is put together
atech.Project the spec: board, modules on ports, your code
atech.placement checks ports: reserved, overlap, adjacency, interface
atech.catalog bundled and user modules
atech.codegen templates → main.cpp + platformio.ini (no LLM in this path)
atech.build / upload PlatformIO
atech.runtime.Board serial client for the flashed board
Status
Alpha. atech list-boards and atech list-modules show what this version
contains. Not in the SDK: WiFi, over-the-air updates.
License
MIT.
Metadata
Release files for atech 1.0.0a11
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| atech-1.0.0a11.tar.gz | 109.9 kB | Without provenance | Details for atech-1.0.0a11.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| atech-1.0.0a11-py3-none-any.whl | Python 3 | none | any | Details for atech-1.0.0a11-py3-none-any.whl |
Total release size: 256.7 kB
Release files / atech-1.0.0a11.tar.gz
| Download URL | atech-1.0.0a11.tar.gz |
|---|---|
| Size | 109.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
41f7e44cddca0880a9c3abf171e009b4cb21aeaa3ae996de885f4c236598559c
|
|
BLAKE2b-256 checksum How to use checksums |
4d6b55d38603601a709ec5f0e90d3fea3c2eec31324e5e605ab55147c0a706b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / atech-1.0.0a11-py3-none-any.whl
| Download URL | atech-1.0.0a11-py3-none-any.whl |
|---|---|
| Size | 146.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
47aaa3fe8fd32f39a77ce024651a23edb31dc1abc7756164cda65cd7b58aa8b4
|
|
BLAKE2b-256 checksum How to use checksums |
2453802c0724d3b5bedbeb3bd8d35ecb64dd26cd46db0b10df73c6fe3bac4059
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for atech 1.0.0a11
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.