nff 0.2.26__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -0,0 +1,539 @@
1
+ Metadata-Version: 2.4
2
+ Name: nff
3
+ Version: 0.2.26
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: Programming Language :: Python :: 3.10
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Topic :: Software Development :: Embedded Systems
11
+ Classifier: Topic :: System :: Hardware
12
+ Requires-Dist: pytest>=7.0 ; extra == 'dev'
13
+ Requires-Dist: pytest-asyncio>=0.23 ; extra == 'dev'
14
+ Requires-Dist: black ; extra == 'dev'
15
+ Requires-Dist: ruff ; extra == 'dev'
16
+ Provides-Extra: dev
17
+ License-File: LICENSE
18
+ Summary: Claude Code IoT Bridge — connect Claude to hardware via USB
19
+ Keywords: arduino,esp32,mcp,claude,iot,serial,embedded
20
+ Author-email: Gauthier Lechevalier <gauthier.lechevalier26@gmail.com>
21
+ License-Expression: MIT
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
24
+ Project-URL: Bug Tracker, https://github.com/GLechevalier/nff/issues
25
+ Project-URL: Homepage, https://github.com/GLechevalier/nff
26
+ Project-URL: Repository, https://github.com/GLechevalier/nff
27
+
28
+ <p align="center">
29
+ <img src="public/images/tumbnail.png" alt="nff" width="640">
30
+ </p>
31
+
32
+ <h1 align="center">nff — LLM bridge to hardware</h1>
33
+
34
+ <p align="center">
35
+ <a href="https://pypi.org/project/nff/"><img alt="PyPI" src="https://img.shields.io/pypi/v/nff?color=2b9348&label=pypi"></a>
36
+ <a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-green"></a>
37
+ <img alt="Built with Rust" src="https://img.shields.io/badge/built%20with-Rust-dea584?logo=rust&logoColor=white">
38
+ <img alt="Boards" src="https://img.shields.io/badge/boards-1000%2B%20(PlatformIO)-orange?logo=platformio&logoColor=white">
39
+ <img alt="MCP" src="https://img.shields.io/badge/MCP-server-8A2BE2">
40
+ <a href="https://nanoforgeflow.com"><img alt="nff platform" src="https://img.shields.io/badge/platform-nanoforgeflow.com-111"></a>
41
+ </p>
42
+
43
+ nff is an MCP server that gives LLMs direct control over physical hardware — on the bench during development, and in the field for maintenance and diagnosis.
44
+
45
+ Connect your board over USB and Claude writes, compiles, flashes, and reads serial output autonomously. Deploy devices with the `nff-sdk-c` library and Claude can reach them remotely: capture crash state, diagnose failures, and push fixes — without physical access.
46
+
47
+ > **nff is the open-source bench CLI of the [nff platform](https://nanoforgeflow.com)** — an end-to-end, agent-driven system for developing, shipping, and operating ESP32-class firmware (bench → OTA → fleet diagnosis). This repo (`nff`) and the device library (`nff-sdk-c`) are the two **MIT-licensed** pieces that run on the engineer's laptop and hardware; the hosted backend (fleet broker, OTA orchestration, crash-analysis engine) is proprietary.
48
+
49
+ ```
50
+ you: "Run the sensor init sequence and assert the calibration values over serial"
51
+ LLM: [writes firmware] → [compiles] → [flashes ESP32] → [reads serial] → returns structured output
52
+
53
+ you: "Why did the unit in the field just hard-fault?"
54
+ LLM: [captures panic over OTA] → [reads registers + backtrace] → "Stack overflow in your sensor ISR at line 47"
55
+ ```
56
+
57
+ **Supported boards:** with the **PlatformIO backend** (now the default in both the shipped Rust binary and the Python implementation) nff is board-universal — **any of PlatformIO's ~1000+ boards across ~40 hardware platforms** (every ESP32 variant, RP2040/Pico, all STM32 families, classic & megaAVR, SAMD/SAM, Teensy, nRF51/nRF52, Renesas RA / Arduino Uno R4, NXP LPC, Kendryte K210, GD32V/RISC-V, MSP430, TIVA, and many more), with the platform toolchain auto-installed on first build. The classic **arduino-cli backend** remains available and covers ESP32 (CP210x / CH340) · ESP8266 (FTDI) · Arduino AVR (Uno, Mega, Nano, Leonardo). See [Build backends](#build-backends) and the full [Supported Boards](#supported-boards) listing.
58
+
59
+ **Shipped as a single Rust binary.** The release artifact is the compiled `nff` binary built from `nff-rs/` — a self-contained executable with no Python runtime required. The Python package under `nff/nff/` remains as the reference/prototyping implementation (features are often prototyped there first, then ported to Rust at parity); both are kept in sync, version for version. The Rust port is at full feature parity (CLI commands, MCP server + OAuth proxy, the bench-loop hardening, the PlatformIO build backend, and the `nff pi` Raspberry-Pi probe).
60
+
61
+ ---
62
+
63
+ ## Two modes, one tool
64
+
65
+ ### Bench development
66
+ nff closes the edit–compile–flash–debug loop. Instead of switching between your editor, terminal, and serial monitor, you stay in one conversation. The LLM iterates on firmware in response to serial output, catches exceptions, and reflashes — handling the logistics so you focus on the problem.
67
+
68
+ ### Field maintenance
69
+ Once a device is deployed, nff becomes your remote window into it. When a bare-metal MCU crashes in the field there is no shell, no SSH, no process table — just a panic on a chip you cannot physically touch. nff captures the crash state (registers, stack, memory, backtrace) and routes it to a cloud AI agent that explains the failure in plain language and drives the recovery. No truck roll. No JTAG probe on-site.
70
+
71
+ This is the gap Mender, balena, and similar OTA tools cannot fill: they require a living network client running inside the firmware. nff's field mode works precisely when the firmware is dead.
72
+
73
+ ---
74
+
75
+ ## Build backends
76
+
77
+ nff can drive the build/flash loop through either of two toolchains, selected per-run or persisted in config. Every `compile`/`flash` path resolves the backend the same way, so the CLI and MCP tools are identical regardless of which one is active.
78
+
79
+ | Backend | Boards | Toolchain | Sketch layout |
80
+ |---|---|---|---|
81
+ | **`platformio`** (default) | board-universal — any [PlatformIO board id](https://docs.platformio.org/en/latest/boards/index.html) (`esp32dev`, `esp32-s3-devkitc-1`, `pico`, `genericSTM32F103C8`, `uno`, …) | PlatformIO Core; the platform + framework + esptool **auto-install on first build** per board family | native `src/main.cpp` + a generated `platformio.ini` |
82
+ | **`arduino`** | the [Supported Boards](#supported-boards) table (FQBN) | arduino-cli + manually installed cores | `.ino` sketch folder |
83
+
84
+ **Selecting a backend** — precedence is env var → config → default (`platformio`):
85
+
86
+ ```bash
87
+ # per-run override (config untouched)
88
+ NFF_BUILD_BACKEND=platformio nff compile sketches/esp32_vitals --board esp32dev
89
+ NFF_BUILD_BACKEND=arduino nff compile sketches/esp32_vitals --board esp32:esp32:esp32
90
+
91
+ # persist a choice (writes build.backend + build.board to ~/.nff/config.json)
92
+ nff init --backend platformio # → no flags needed afterwards
93
+ nff init --backend arduino # opt back into arduino-cli
94
+ ```
95
+
96
+ `--board` is backend-aware: a **PlatformIO board id** under the pio backend, an **arduino-cli FQBN** under the arduino backend. With a board saved via `nff init` you can omit `--board` entirely.
97
+
98
+ > **Status:** both backends ship in the compiled Rust binary (`nff-rs/`) — the artifact `pip install nff` delivers — with **PlatformIO the default**. The Python package (`nff/`) is the reference/prototyping implementation and is kept at parity. `nff init --backend platformio` (or `arduino`) persists the choice.
99
+
100
+ 📄 Full write-up — architecture, internals, requirements, and verification — in [`docs/platformio-backend.md`](docs/platformio-backend.md).
101
+
102
+ ---
103
+
104
+ ## AI crash diagnosis — validated
105
+
106
+ Phase-0 validation on an ESP32 confirmed that Claude can produce specific, correct diagnoses from raw panic output alone — no ELF file, no source access:
107
+
108
+ | Crash type | Panic signature | What Claude identifies |
109
+ |---|---|---|
110
+ | Null pointer write | `EXCCAUSE 0x1d` + `EXCVADDR 0x00000000` | StoreProhibited in `setup()`, stack intact |
111
+ | Stack overflow | `EXCCAUSE 0x01` + repeated PC in backtrace | Unbounded recursion, FreeRTOS canary, depth 11 |
112
+ | Watchdog timeout | IDF task-WDT log, no Guru Meditation | `loopTask` on CPU 1 never yielded, liveness failure |
113
+
114
+ Each failure class produces a different panic format, exception code, backtrace depth, and task snapshot — rich enough signal to distinguish root causes without symbol resolution. With addr2line + the build ELF wired in (next milestone), diagnoses resolve to exact source lines.
115
+
116
+ ---
117
+
118
+ ## MCP Tools
119
+
120
+ ### Bench — hardware & build
121
+
122
+ | Tool | What it does |
123
+ |---|---|
124
+ | `list_devices()` | List all connected USB boards |
125
+ | `compile(sketch?, code?, board?)` | Compile a sketch **only** (no board/port) to verify it builds; returns JSON `{ok, fqbn, elf, image, artifacts, errors, output}` |
126
+ | `flash(sketch?, code?, board?, port?)` | Compile **and** upload a sketch to the connected board |
127
+ | `serial_read(duration_ms?, port?, baud?)` | Capture serial output for N ms |
128
+ | `serial_write(data, port?, baud?)` | Send a string to the device |
129
+ | `reset_device(port?)` | Toggle DTR to hardware-reset the board |
130
+ | `get_device_info(port?)` | Return port, board name, FQBN, baud rate |
131
+
132
+ ### Simulation — Wokwi (CI without a bench)
133
+
134
+ | Tool | What it does |
135
+ |---|---|
136
+ | `wokwi_flash(code, board?, timeout_ms?)` | Compile and simulate a sketch via Wokwi |
137
+ | `wokwi_serial_read(code, board?, duration_ms?)` | Compile, simulate, return serial output |
138
+ | `wokwi_get_diagram(board)` | Return a minimal `diagram.json` stub to extend |
139
+
140
+ ### Field — diagnosis & auth
141
+
142
+ | Tool | What it does |
143
+ |---|---|
144
+ | `repair(serial_output, build_id?, board?)` | Send serial/crash output to the diagnosis server and return a structured diagnosis |
145
+ | `authenticate(email?, password?)` | Log in to the diagnosis server (direct, or omit both for browser OAuth) |
146
+ | `complete_authentication(timeout?)` | Wait for a browser login to finish and store the tokens |
147
+ | `auth_status()` / `auth_logout()` / `auth_clear()` / `auth_reconnect(email?, password?)` | Inspect, end, force-clear, or re-establish the authenticated MCP session |
148
+
149
+ All bench tools fall back to the default device in `~/.nff/config.json` when `port` and `board` are omitted.
150
+
151
+ > **Prefer `sketch=` (a path) over `code=`.** Write the `.ino` file to disk first and pass the sketch path, rather than raw source — it keeps the build artifact lookup deterministic. Use `compile` to check a build with no board attached; use `flash` only when a port is present.
152
+
153
+ ---
154
+
155
+ ## Demo
156
+
157
+ [![nff Demo](https://img.youtube.com/vi/xKaqBuO8Gjg/maxresdefault.jpg)](https://youtu.be/xKaqBuO8Gjg)
158
+
159
+ ### Real Hardware
160
+
161
+ [![Real Hardware Programming](https://img.youtube.com/vi/JoCwczeRfuQ/maxresdefault.jpg)](https://youtu.be/JoCwczeRfuQ)
162
+
163
+ ### Wokwi Simulation
164
+
165
+ [![Wokwi Simulation](https://img.youtube.com/vi/FZ70lQ-VP3g/maxresdefault.jpg)](https://youtu.be/FZ70lQ-VP3g)
166
+
167
+ ---
168
+
169
+ ## Quickstart
170
+
171
+ Get your hardware on the LLM loop in under five minutes.
172
+
173
+ ### 1. Install
174
+
175
+ ```bash
176
+ pip install nff
177
+ ```
178
+
179
+ `pip install nff` fetches a **prebuilt wheel containing the compiled Rust binary** for your platform (Linux x64, Windows x64, macOS arm64/x64) — no Python runtime and no Rust toolchain needed at runtime. pip is just the delivery mechanism; the installed `nff` command is the native binary.
180
+
181
+ ### 2. Install board cores
182
+
183
+ On the **default PlatformIO backend** there is nothing to install here — PlatformIO Core is set up by `nff init`, and the platform/framework/esptool for your board auto-install on the first build. Just make sure your sketch names a PlatformIO board id (`--board esp32dev`, etc.).
184
+
185
+ Only on the **arduino backend** do you install cores manually:
186
+
187
+ ```bash
188
+ # arduino backend only — install the cores you need
189
+ arduino-cli core install esp32:esp32
190
+ arduino-cli core install arduino:avr
191
+ arduino-cli core install esp8266:esp8266
192
+ ```
193
+
194
+ > Both toolchains (`platformio` / `arduino-cli`) are auto-installed by `nff init`/`nff install-deps` for the active backend if not already present.
195
+
196
+ ### 3. Plug in your board and run init
197
+
198
+ ```bash
199
+ nff init
200
+ ```
201
+
202
+ This single command:
203
+ - **Signs you in** to the nff platform (browser login) — required, because the MCP tools are gated behind your account
204
+ - Detects your board by USB vendor/product ID
205
+ - Writes `~/.nff/config.json` (default device + build backend/board)
206
+ - Installs the active backend's toolchain if missing (PlatformIO Core, or arduino-cli)
207
+ - On the arduino backend with an ESP32, optionally enrolls the board on the nff platform (flash bootstrap firmware → claim into your dashboard)
208
+ - Registers the nff MCP server with Claude Code (`claude mcp add --scope user --transport http nff http://127.0.0.1:3010/mcp`)
209
+ - **Starts the MCP server in the background** so Claude Code finds it already running — no manual `nff mcp` needed
210
+
211
+ ```
212
+ ✓ Signed in to the nff platform
213
+ ✓ Found: ESP32 (CP210x) on COM10
214
+ ✓ Config written to ~/.nff/config.json
215
+ ✓ Registered with Claude Code CLI (HTTP MCP on 127.0.0.1:3010)
216
+ ✓ Server running on http://127.0.0.1:3010/mcp
217
+
218
+ ✓ nff configured! Restart Claude Code to pick up the nff MCP server.
219
+ ```
220
+
221
+ > The background server runs until you reboot or stop it. After a reboot, run `nff mcp`
222
+ > (or just re-run `nff init`) to bring it back up — `nff doctor` will tell you if it's down.
223
+
224
+ ### 4. Verify
225
+
226
+ ```bash
227
+ nff doctor
228
+ ```
229
+
230
+ ---
231
+
232
+ ## CLI Reference
233
+
234
+ ### Real hardware
235
+
236
+ | Command | Description |
237
+ |---|---|
238
+ | `nff init` | Sign in, detect board, write config, register + start the MCP server |
239
+ | `nff compile <path>` | Compile a sketch to verify it builds (no board/port needed) |
240
+ | `nff flash <path>` | Compile and upload a sketch directory |
241
+ | `nff monitor` | Stream serial output (Ctrl+C to exit) |
242
+ | `nff connect` | Attach to a device, continuously analyse its logs, autonomously repair detected issues |
243
+ | `nff repair` | Send captured serial/crash output to the diagnosis server for a structured root-cause |
244
+ | `nff auth login` | Authenticate with the diagnosis server (browser OAuth or email/password) |
245
+ | `nff doctor` | Check all dependencies and configuration |
246
+ | `nff mcp` | Start the MCP server (streamable HTTP on `127.0.0.1:3010`; started in the background by `nff init`) |
247
+
248
+ ```bash
249
+ nff flash sketches/sensor_init
250
+ nff flash sketches/sensor_init --board esp32dev --port COM3 # PlatformIO board id (default backend)
251
+ nff flash sketches/sensor_init --board esp32:esp32:esp32 # arduino FQBN (NFF_BUILD_BACKEND=arduino)
252
+ nff flash sketches/sensor_init --manual-reset # for boards without auto-reset
253
+ nff monitor --port COM10 --baud 115200
254
+ nff monitor --port COM10 --baud 115200 --timeout 15
255
+ ```
256
+
257
+ ### nff connect — Autonomous log analysis and repair
258
+
259
+ `nff connect` keeps a live serial connection to your device and routes each batch of output to Claude for analysis. When Claude detects an error, a hang, or a recoverable fault, it rewrites the sketch, recompiles, reflashes, and resumes monitoring — closing the repair loop without manual intervention.
260
+
261
+ ```
262
+ nff connect
263
+ ↓ streams serial from device
264
+ ↓ Claude analyses each log window
265
+ ↓ fault detected → sketch rewritten → nff flash → device reset
266
+ ↓ monitoring resumes automatically
267
+ ```
268
+
269
+ Useful flags:
270
+
271
+ | Flag | Default | Description |
272
+ |---|---|---|
273
+ | `--port PORT` | auto-detect | Serial port to attach to |
274
+ | `--baud BAUD` | 115200 | Baud rate |
275
+ | `--sketch DIR` | last flashed | Sketch directory to rewrite and reflash on a fix |
276
+ | `--window MS` | 2000 | Log window passed to Claude per analysis cycle |
277
+ | `--max-cycles N` | unlimited | Stop after N repair attempts |
278
+
279
+ ### Wokwi simulation (CI without a bench)
280
+
281
+ | Command | Description |
282
+ |---|---|
283
+ | `nff wokwi init` | Scaffold `wokwi.toml` + `diagram.json` in current directory |
284
+ | `nff flash --sim <path>` | Compile sketch and run headless Wokwi simulation |
285
+ | `nff wokwi run` | Run simulation, stream serial output to terminal |
286
+ | `nff wokwi run --gui` | Open `diagram.json` in VS Code and auto-start visual simulation |
287
+ | `nff wokwi run --serial-log FILE` | Save serial output to file |
288
+ | `nff wokwi run --timeout MS` | Set simulation timeout (default 5000 ms) |
289
+
290
+ ---
291
+
292
+ ## Supported Boards
293
+
294
+ **On the default PlatformIO backend, nff is board-universal.** Pass any of PlatformIO's [~1000+ board ids](https://docs.platformio.org/en/latest/boards/index.html) to `--board` and the matching platform toolchain (compiler + framework + uploader) installs itself on first build — there is no fixed allow-list and nothing to pre-install.
295
+
296
+ ### Architectures & platforms covered
297
+
298
+ The PlatformIO backend gives nff every PlatformIO **development platform** — each one a whole family of boards. You don't need any of these in nff's catalog; just pass the PlatformIO board id to `--board` and the toolchain installs on first build. The table below is the full set of platforms (≈40), each spanning dozens-to-hundreds of individual boards.
299
+
300
+ | Platform (`--board` resolves it) | Core / MCU family | Example boards & `--board` ids |
301
+ |---|---|---|
302
+ | `espressif32` | Espressif ESP32 (Xtensa LX6/LX7 + RISC-V) | ESP32, ESP32-S2, ESP32-S3, ESP32-C3/C6/H2, ESP32-P4 — `esp32dev`, `esp32-s3-devkitc-1`, `esp32-c6-devkitc-1` |
303
+ | `espressif8266` | Espressif ESP8266 (Tensilica L106) | NodeMCU, Wemos D1 — `esp01_1m`, `nodemcuv2`, `d1_mini` |
304
+ | `raspberrypi` | Raspberry Pi RP2040 / RP2350 (ARM Cortex-M0+/M33) | Pico, Pico W, Pico 2 — `pico`, `rpipicow`, `rpipico2` |
305
+ | `atmelavr` | Classic 8-bit Atmel AVR | Arduino Uno/Mega/Nano/Leonardo, Pro Mini — `uno`, `megaatmega2560`, `nanoatmega328`, `leonardo` |
306
+ | `atmelmegaavr` | Atmel megaAVR (0-series) | Arduino Uno WiFi Rev2, Nano Every — `uno_wifi_rev2`, `nano_every` |
307
+ | `atmelsam` | Atmel SAM (ARM Cortex-M0+/M3/M4) | Arduino Zero/MKR/Due, Adafruit Feather M0/M4 — `mkrwifi1010`, `adafruit_feather_m4`, `due` |
308
+ | `ststm32` | ST STM32 (ARM Cortex-M0/0+/M3/M4/M7) — F0/F1/F2/F3/F4/F7/G0/G4/H7/L0/L1/L4/L5/U5/WB/WL | Blue Pill, Black Pill, every Nucleo/Discovery — `bluepill_f103c8`, `genericSTM32F103C8`, `nucleo_f401re`, `nucleo_h743zi` |
309
+ | `ststm8` | ST STM8 (8-bit) | STM8S Discovery, sduino — `stm8sdiscovery` |
310
+ | `teensy` | PJRC Teensy (ARM Cortex-M4/M7) | Teensy 3.x / 4.0 / 4.1 / LC — `teensy41`, `teensy40`, `teensy36`, `teensylc` |
311
+ | `nordicnrf52` | Nordic nRF52 (ARM Cortex-M4, BLE) | Adafruit Feather/ItsyBitsy nRF52840, Nano 33 BLE — `nano33ble`, `adafruit_feather_nrf52840` |
312
+ | `nordicnrf51` | Nordic nRF51 (ARM Cortex-M0, BLE) | micro:bit v1, BBC boards — `bbcmicrobit`, `nrf51_dk` |
313
+ | `renesas-ra` | Renesas RA4M1 (ARM Cortex-M4) | **Arduino Uno R4** Minima / WiFi — `uno_r4_minima`, `uno_r4_wifi` |
314
+ | `nxplpc` | NXP LPC (ARM Cortex-M0/M3/M4) | mbed LPC1768, LPC11U24 — `lpc1768`, `lpc11u35` |
315
+ | `nxpimxrt` | NXP i.MX RT (ARM Cortex-M7) | MIMXRT1060/1010 EVK — `mimxrt1060_evk` |
316
+ | `freescalekinetis` | NXP/Freescale Kinetis (ARM Cortex-M0+/M4) | FRDM-K64F, FRDM-KL25Z — `frdm_k64f`, `frdm_kl25z` |
317
+ | `siliconlabsefm32` | Silicon Labs EFM32 (ARM Cortex-M) | EFM32 Giant/Wonder Gecko — `efm32gg_stk3700` |
318
+ | `gd32v` | GigaDevice GD32V (RISC-V) | Sipeed Longan Nano — `sipeed-longan-nano` |
319
+ | `kendryte210` | Kendryte K210 (RISC-V, AI) | Sipeed MAIX — `sipeed-maix-bit` |
320
+ | `microchippic32` | Microchip PIC32 (MIPS) | chipKIT Uno32, Max32 — `chipkit_uno32`, `chipkit_max32` |
321
+ | `timsp430` | TI MSP430 (16-bit) | MSP430 LaunchPads — `lpmsp430g2553`, `lpmsp430fr6989` |
322
+ | `titiva` | TI TIVA C (ARM Cortex-M4) | Tiva C / Stellaris LaunchPad — `lptm4c1230c3pm`, `lplm4f120h5qr` |
323
+ | `infineonxmc` | Infineon XMC (ARM Cortex-M) | XMC2Go, XMC1100 Boot Kit — `xmc1100_xmc2go` |
324
+ | `intel_arc32` | Intel Curie (ARC) | Arduino/Genuino 101 — `genuino101` |
325
+ | `wiznet7500` | WIZnet W7500 (ARM Cortex-M0, Ethernet) | WIZwiki-W7500 — `wizwiki_w7500` |
326
+ | `lattice_ice40` | Lattice iCE40 FPGA | TinyFPGA B2, iCEstick — `icezum`, `tinyfpga_b2` |
327
+
328
+ > Less common platforms PlatformIO also ships (and that nff therefore drives) include `nuclei`, `riscv_gap`, `samd21`, `chipsalliance`, `aceinna_imu`, `shakti`, `samsung_artik`, and others — see the [PlatformIO platforms index](https://docs.platformio.org/en/latest/platforms/index.html) for the live, complete list.
329
+
330
+ ### Curated families (built-in catalog)
331
+
332
+ These are the board ids in nff's built-in catalog. The catalog only supplies sensible defaults (PlatformIO platform + Wokwi sim chip) so you can name a short board id and `nff init` can auto-detect — **every other board above still builds**, you just pass the full PlatformIO id.
333
+
334
+ | Family | PlatformIO platform | Catalogued `--board` ids | Wokwi sim |
335
+ |---|---|---|---|
336
+ | **ESP32** | `espressif32` | `esp32dev`, `esp32-s3-devkitc-1`, `esp32-c3-devkitm-1`, `esp32-c6-devkitc-1`, `esp32-s2-saola-1` | ✅ (S2: ❌) |
337
+ | **ESP8266** | `espressif8266` | `esp01_1m`, `nodemcuv2` | ✅ |
338
+ | **RP2040 / Pico** | `raspberrypi` | `pico`, `rpipicow` | ✅ |
339
+ | **STM32** | `ststm32` | `genericSTM32F103C8`, `bluepill_f103c8`, `nucleo_f401re` | ❌ |
340
+ | **Classic AVR** | `atmelavr` | `uno`, `megaatmega2560`, `nanoatmega328`, `leonardo` | ✅ |
341
+
342
+ Need a board that isn't catalogued (Teensy, SAMD, nRF52, Uno R4, ESP32-P4, …)? Just give its PlatformIO id — e.g. `nff compile sketch.ino --board teensy41`. Adding it to the catalog (for auto-detect + a short default) is a [two-line PR](CONTRIBUTING.md#adding-a-new-board).
343
+
344
+ ### USB auto-detect
345
+
346
+ When you plug a board in, nff resolves it by USB vendor/product ID to a default board id for **both** backends, so `nff init` and `--board`-less commands "just work". A USB-serial chip (CP210x/CH340/FTDI) is shared by many boards, so this is a *default* you can override with `--board`.
347
+
348
+ | Board | Vendor ID | Product ID | FQBN (arduino) | PlatformIO board id |
349
+ |---|---|---|---|---|
350
+ | ESP32 (CP210x) | 10c4 | ea60 | `esp32:esp32:esp32` | `esp32dev` |
351
+ | ESP32 (CH340) | 1a86 | 7523 | `esp32:esp32:esp32` | `esp32dev` |
352
+ | ESP8266 (FTDI) | 0403 | 6001 | `esp8266:esp8266:generic` | `esp01_1m` |
353
+ | Arduino Uno | 2341 | 0043 | `arduino:avr:uno` | `uno` |
354
+ | Arduino Mega 2560 | 2341 | 0010 | `arduino:avr:mega` | `megaatmega2560` |
355
+ | Arduino Leonardo | 2341 | 0036 | `arduino:avr:leonardo` | `leonardo` |
356
+ | Arduino Nano | 2341 | 0058 | `arduino:avr:nano` | `nanoatmega328` |
357
+
358
+ > The **arduino backend** (`NFF_BUILD_BACKEND=arduino`) is limited to the FQBN column above plus whatever cores you `arduino-cli core install`. The PlatformIO backend is the one that makes the rest of the families above available.
359
+
360
+ ---
361
+
362
+ ## Config File
363
+
364
+ `~/.nff/config.json`, written by `nff init` and editable by hand:
365
+
366
+ ```json
367
+ {
368
+ "version": "1",
369
+ "default_device": {
370
+ "port": "COM10",
371
+ "board": "ESP32 (CP210x)",
372
+ "fqbn": "esp32:esp32:esp32",
373
+ "baud": 115200
374
+ },
375
+ "build": {
376
+ "backend": "platformio",
377
+ "board": "esp32dev"
378
+ },
379
+ "wokwi": {
380
+ "api_token": "YOUR_TOKEN",
381
+ "default_timeout_ms": 5000,
382
+ "diagram_path": null
383
+ }
384
+ }
385
+ ```
386
+
387
+ `build.backend` selects the toolchain (`platformio` default, or `arduino`) and `build.board` holds the PlatformIO board id; the arduino backend uses `default_device.fqbn` instead. The `NFF_BUILD_BACKEND` env var overrides `build.backend` per-run. The Wokwi token can also be set via `WOKWI_CLI_TOKEN` (takes precedence over config).
388
+
389
+ ---
390
+
391
+ ## Claude Code Skills
392
+
393
+ nff ships Claude Code skills bundled inside the package:
394
+
395
+ | Skill | When to use |
396
+ |---|---|
397
+ | `/nff` | Full pipeline reference — hardware and simulation workflows, sketch-first rules, debugging checklist |
398
+ | `/wokwi-diagram` | `diagram.json` authoring reference — component types, pin names, wiring patterns |
399
+
400
+ ```
401
+ /nff
402
+ /wokwi-diagram
403
+ ```
404
+
405
+ Skill files live at `nff/skills/` (the source of truth — edit them there) so they ship with every `pip install nff`, and are also mirrored in `.claude/commands/` for project-level use. Copy them into `~/.claude/commands/` to make the slash commands available globally.
406
+
407
+ ---
408
+
409
+ ## Repository Structure
410
+
411
+ ```
412
+ nff/
413
+ ├── nff/ # Python package — the LIVE implementation
414
+ │ ├── cli.py # Click CLI — wires every subcommand
415
+ │ ├── config.py # ~/.nff/config.json read/write
416
+ │ ├── mcp_server.py # streamable-HTTP MCP server (Bearer-authed /mcp)
417
+ │ ├── commands/
418
+ │ │ ├── init.py
419
+ │ │ ├── compile_cmd.py # port-free build check
420
+ │ │ ├── flash.py
421
+ │ │ ├── monitor.py
422
+ │ │ ├── connect.py # autonomous log-analysis + repair loop
423
+ │ │ ├── repair.py # route crash output to the diagnosis server
424
+ │ │ ├── auth_cmd.py # nff auth login / status / logout
425
+ │ │ ├── ota.py
426
+ │ │ ├── provision.py
427
+ │ │ ├── doctor.py
428
+ │ │ ├── clean.py
429
+ │ │ ├── install_deps.py
430
+ │ │ ├── mcp_cmd.py
431
+ │ │ └── wokwi_cmd.py
432
+ │ ├── tools/
433
+ │ │ ├── boards.py # USB ID detection + PlatformIO board catalog
434
+ │ │ ├── serial.py # serial read/write/stream/reset
435
+ │ │ ├── toolchain.py # backend dispatcher + arduino-cli/esptool wrappers
436
+ │ │ ├── backends/
437
+ │ │ │ └── platformio.py # PlatformIO backend (project scaffold, pio run)
438
+ │ │ ├── installer.py # arduino-cli auto-install
439
+ │ │ ├── auth.py # diagnosis-server token handling
440
+ │ │ └── wokwi.py # Wokwi runner + diagram generation
441
+ │ └── skills/ # /nff + /wokwi-diagram skills (ship with the package)
442
+ ├── nff-rs/ # Rust port — the shipped binary (full parity)
443
+ ├── sketches/
444
+ │ ├── blink_esp32/
445
+ │ └── servo_button/
446
+ ├── diagram.json # Wokwi circuit schematic
447
+ ├── wokwi.toml
448
+ └── .claude/
449
+ └── commands/
450
+ ├── nff.md # /nff Claude Code skill
451
+ └── wokwi-diagram.md # /wokwi-diagram Claude Code skill
452
+ ```
453
+
454
+ The Rust crate under `nff-rs/nff/` is the **shipped binary** and is at full feature parity with the Python package — every CLI command and MCP tool runs natively (no Python runtime). Build it with `cargo build --release` (binary at `nff-rs/target/release/nff`). The Python package under `nff/nff/` is the reference/prototyping implementation and is kept in sync version-for-version; when you add a feature, land it in both so the two never drift.
455
+
456
+ ---
457
+
458
+ ## Linux: Serial Port Permissions
459
+
460
+ ```bash
461
+ sudo usermod -aG dialout $USER
462
+ # then log out and back in
463
+ ```
464
+
465
+ `nff doctor` detects this and prints the fix.
466
+
467
+ ---
468
+
469
+ ## Wokwi Simulation
470
+
471
+ Get a free CI token at https://wokwi.com/dashboard/ci, then:
472
+
473
+ ```bash
474
+ nff wokwi init --board esp32dev --token YOUR_TOKEN
475
+ nff flash --sim sketches/my_sketch --board esp32dev
476
+ nff wokwi run # headless
477
+ nff wokwi run --gui # visual simulation in VS Code
478
+ ```
479
+
480
+ (Use the arduino FQBN form — `--board esp32:esp32:esp32` — when running under `NFF_BUILD_BACKEND=arduino`.)
481
+
482
+ Install the [Wokwi VS Code extension](https://marketplace.visualstudio.com/items?itemName=wokwi.wokwi-vscode) for the animated circuit view.
483
+
484
+ ### Wokwi MCP Tools
485
+
486
+ | Tool | What it does |
487
+ |---|---|
488
+ | `wokwi_flash(code, board?, timeout_ms?)` | Compile and simulate a sketch via Wokwi |
489
+ | `wokwi_serial_read(code, board?, duration_ms?)` | Compile, simulate, return serial output |
490
+ | `wokwi_get_diagram(board)` | Return a minimal `diagram.json` stub to extend |
491
+
492
+ ### diagram.json — Circuit Schematic
493
+
494
+ Always include the serial monitor wires:
495
+
496
+ ```json
497
+ ["esp:TX0", "$serialMonitor:RX", "", []],
498
+ ["esp:RX0", "$serialMonitor:TX", "", []]
499
+ ```
500
+
501
+ Common components:
502
+
503
+ ```json
504
+ { "type": "wokwi-led", "id": "led1", "attrs": { "color": "red" } }
505
+ { "type": "wokwi-pushbutton", "id": "btn1", "attrs": { "color": "blue" } }
506
+ { "type": "wokwi-servo", "id": "srv1", "attrs": { "minAngle": "-90", "maxAngle": "90" } }
507
+ { "type": "wokwi-resistor", "id": "r1", "attrs": { "value": "220" } }
508
+ ```
509
+
510
+ ESP32 DevKit V1 pins: `esp:D<gpio>` · `esp:GND.1` · `esp:GND.2` · `esp:3V3` · `esp:VIN` · `esp:TX0` · `esp:RX0`
511
+
512
+ Pushbutton wiring: GPIO side → `btn1:1.l`, GND side → `btn1:2.l`. Use `INPUT_PULLUP` in the sketch.
513
+
514
+ ### ESP32 Servo — No Library Required
515
+
516
+ Use the built-in LEDC peripheral instead of `ESP32Servo`. Wokwi maps its full servo range to 500 µs – 2500 µs pulses.
517
+
518
+ With 50 Hz / 16-bit resolution (period = 20 000 µs):
519
+
520
+ | Angle | Pulse | Duty |
521
+ |---|---|---|
522
+ | −90° (min) | 500 µs | 1638 |
523
+ | 0° (center) | 1500 µs | 4915 |
524
+ | +90° (max) | 2500 µs | 8192 |
525
+
526
+ ```cpp
527
+ ledcAttach(SERVO_PIN, 50, 16);
528
+ ledcWrite(SERVO_PIN, 4915);
529
+ ```
530
+
531
+ Set `"minAngle": "-90", "maxAngle": "90"` in `diagram.json` for correct visual mapping.
532
+
533
+ ---
534
+
535
+ ## License
536
+
537
+ MIT — see [LICENSE](LICENSE).
538
+ Copyright (c) 2026 Gauthier Lechevalier
539
+
@@ -0,0 +1,6 @@
1
+ nff-0.2.26.data/scripts/nff.exe,sha256=2T1-z_BDigLOojzoPg6UKcaFWYCVQKzlrUgdJJOOZm0,11536384
2
+ nff-0.2.26.dist-info/METADATA,sha256=rULyf1MzzEwMR0fIR9Bd7xhEQRgyb5RZZhDE1wRz6XE,29437
3
+ nff-0.2.26.dist-info/WHEEL,sha256=2zDlIYIdD4m4N3p5DVEG3iJhGLdhsBQgdH-FqVkAur8,94
4
+ nff-0.2.26.dist-info/licenses/LICENSE,sha256=d-XXNGJUTyWpl0fUIuFErS40V7rXmXINA8EAAEvSHjw,1097
5
+ nff-0.2.26.dist-info/sboms/nff.cyclonedx.json,sha256=p2vwAVcJKrOIEt3yffKgBycF519l3sJlyl9acxBRgpo,290333
6
+ nff-0.2.26.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.14.1)
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-win_amd64
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GauthierLechevalier
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.