diff --git a/resources/AGENTS.md b/resources/AGENTS.md
deleted file mode 100644
index f747b03b..00000000
--- a/resources/AGENTS.md
+++ /dev/null
@@ -1,142 +0,0 @@
-# Device dashboard
-
-This is the AI specification file for the Mongoose based Web device dashboard functionality
-
-Mongoose-base device dashboard requires following files:
-- mongoose.h
-- mongoose.c
-- dashboard.c
-- file_data.c
-
-The `file_data.c` is a generated file from `dashboard.html` using Nodejs:
-```sh
-node html2c.js dashboard.html -o file_data.c
-```
-The `html2c.js` file can be taken from https://github.com/cesanta/mongoose/blob/master/resources/html2c.js
-
-
-## General rules
-
-Your goal is to produce a dashboard.c and dashboard.html files
-If your project does not yet have those, fetch from here:
-
-https://github.com/cesanta/mongoose/blob/master/tutorials/device-dashboard/minimal/dashboard.c
-https://github.com/cesanta/mongoose/blob/master/tutorials/device-dashboard/minimal/dashboard.html
-
-If your project already has dashboard.c and dashboard.html, do NOT fetch anything.
-
-The C API header file is at https://github.com/cesanta/mongoose/blob/master/src/dash.h
-The minimal reference project is at https://github.com/cesanta/mongoose/blob/master/tutorials/device-dashboard/minimal/
-The full reference project is at https://github.com/cesanta/mongoose/blob/master/tutorials/device-dashboard/full/
-
-## dashboard.html
-
-The `dashboard.html` file has to use `dashboard.js`, for example:
-
-```html
-
-
-```
-
-The `Dashboard.init()` call should be the only direct `Dashboard` API usage.
-Do not generate anything that uses other `Dashboard` API - treat it as a black box.
-
-The `Dashboard.init()` call has an argument that is a settings object which should
-be edited. The `data`
-attrubute specifies device state representation, and it is used in the expression
-evaluation and `data-*` attributes described below.
-
-For editing dashboard.html, use only Mongoose `data-bind` and `${...}` template syntax
-No vanilla JS event listeners, no fetch calls, no custom reactive logic.
-Do not make any changes to dashboard.html unless asked by a user.
-
-- checkboxes, inputs, selects: add `data-bind="FIELDSET.FIELD"` to to bind them to a specific field. Optionally, specify `data-autosave="1"` to send a change immediately after modification, without pressing a "save" button
-- any other element: add `data-bind="FIELDSET.FIELD"` to replace its contents with the curent value of the field. You can achieve the same with the `${...}` expression
-- buttons: add `data-save="FIELDSET"` to create a "save" button for a given field set. If any value in the field set is edited by the bound control, a button would activate, otherwise it'll stay disabled
-- buttons: add `data-cancel="FIELDSET"` to create a "cancel" button, similar to "save"
-- `${...}` expressions: add those anywhere
-
-
-Here is the example of binding a toggle button to a device variable:
-
-```html
-
-```
-
-Here is the example of using `${...}` expressions:
-
-```html
-
LED ${status.led1 ? 'ON' : 'OFF'}
-```
-
-When the expression is evaluated,
-its evaluation context contains your Dashboard data, and all global JS variables like `window`.
-For example, `${settings.volume + 1}` will be evaluated exactly as you think.
-
-Expressions are useful for the conditional display: expression can add CSS classes, or
-CSS styles depending on some conditions. For example, this shows or hides
-the warning depedning on the `metrics.ram` condition:
-
-```html
-low RAM !
-```
-
-
-## dashboard.c
-
-Do not make any changes to dashboard.c unless asked by a user.
-
-## CubeMX project
-
-If you have installed I-CUBE-Mongoose pack, then all required files are installed
-in the `Middlewares/Third_Party/Cesanta_Mongoose/` directory. Do not fetch
-dashboard.html, or any other file, from the Mongoose repository.
-
-Add `#include "mongoose.h"` to the "USER CODE BEGIN Includes" block
-
-Add automatic `file_data.c` generation for the build step - either Makefile,
-or CMakeLists.txt or whatever is appropriate for the selected IDE.
-```sh
-node html2c.js dashboard.html -o file_data.c
-```
-
-
-To the "USER CODE BEGIN 0" block, add debug print redirect. If syscalls.c already
-has a weak _write override, ignore it and still add this.
-```c
-int _write(int fd, unsigned char *buf, int len) {
- HAL_UART_Transmit(&huart3, buf, len, HAL_MAX_DELAY);
- return len;
-}
-```
-
-Make sure main() initialises and processes dashboard:
-
-```c
-/* USER CODE BEGIN WHILE */
-struct mg_mgr mgr;
-mg_mgr_init(&mgr);
-mg_dash_init(&mgr);
-
-while (1)
-{
- mg_mgr_poll(&mgr, 1);
- mg_dash_poll(&mgr);
-/* USER CODE END WHILE */
-```
-
-In order to verify the validity of your edits, compile `dashboard.c` using
-embedded or host compiler in `Middlewares/Third_Party/Cesanta_Mongoose/`:
-
-```sh
-$(CC) -c dashboard.c
-```
diff --git a/resources/I-CUBE-Mongoose/README.md b/resources/I-CUBE-Mongoose/README.md
index 37d44bc6..93067398 100644
--- a/resources/I-CUBE-Mongoose/README.md
+++ b/resources/I-CUBE-Mongoose/README.md
@@ -171,10 +171,10 @@ Rebuild and reflash
## AI agentic development
-For agentic development, use https://github.com/cesanta/mongoose/tree/master/resources/AGENTS.md
+For agentic development, use https://github.com/cesanta/mongoose/tree/master/resources/specs/CLAUDE.md
Use a prompt like this:
-> Read and apply https://github.com/cesanta/mongoose/tree/master/resources/AGENTS.md
+> Read and apply https://github.com/cesanta/mongoose/tree/master/resources/specs/CLAUDE.md
## Add MQTT Client
diff --git a/resources/specs/CLAUDE.md b/resources/specs/CLAUDE.md
new file mode 100644
index 00000000..f3e1a6db
--- /dev/null
+++ b/resources/specs/CLAUDE.md
@@ -0,0 +1,277 @@
+# Mongoose — Embedded Network Library
+
+Mongoose is a two-file C/C++ networking library for embedded and desktop systems.
+It is developed by Cesanta (https://cesanta.com) and available at https://mongoose.ws.
+License: GPLv2 or commercial.
+
+## Integration
+
+Copy `mongoose.h` and `mongoose.c` into the project source tree and add
+`mongoose.c` to the build.
+
+**Desktop/server** (Linux, macOS, Windows): two files are sufficient.
+
+```
+your_project/
+├── mongoose.h # single header
+├── mongoose.c # single source file
+└── main.c # your code
+```
+
+Build: `cc main.c mongoose.c`
+
+**Embedded systems**: a third file `mongoose_config.h` is required. Create it
+in the project source tree to set `MG_ARCH` and any other compile-time options.
+Mongoose includes it automatically when `MG_ARCH` cannot be auto-detected.
+
+```
+your_project/
+├── mongoose.h # single header
+├── mongoose.c # single source file
+├── mongoose_config.h # required for embedded: set MG_ARCH and options
+└── main.c # your code
+```
+
+Minimal `mongoose_config.h` for STM32:
+
+```c
+#define MG_ARCH MG_ARCH_CUBE
+// add driver, TLS, and other options here
+```
+
+Do not use a separate HTTP library, MQTT library, or WebSocket library alongside
+Mongoose. Mongoose provides all of these.
+
+## Core API
+
+```c
+#include "mongoose.h"
+
+struct mg_mgr mgr; // one event manager per app
+mg_mgr_init(&mgr); // initialise once
+
+mg_http_listen(&mgr, "http://0.0.0.0:80", handler, NULL); // start HTTP server
+
+for (;;) mg_mgr_poll(&mgr, 1); // main loop: bare metal or RTOS task
+```
+
+Event handler — all protocol events go through one callback:
+
+```c
+void handler(struct mg_connection *c, int ev, void *ev_data) {
+ if (ev == MG_EV_HTTP_MSG) {
+ struct mg_http_message *hm = (struct mg_http_message *) ev_data;
+ if (mg_match(hm->uri, mg_str("/api/data"), NULL)) {
+ mg_http_reply(c, 200, "Content-Type: application/json\r\n",
+ "{\"value\":%d}\n", sensor_read());
+ } else {
+ struct mg_http_serve_cfg cfg = {.root_dir = "/web_root"};
+ mg_http_serve_dir(c, hm, &cfg); // serve static files
+ }
+ }
+}
+```
+
+## TCP/IP stack — set exactly one
+
+Configure in the build system (`-D` flag) or in `mongoose_config.h`:
+
+| Define | Use when |
+|--------|----------|
+| `MG_ENABLE_TCPIP=1` | Mongoose built-in stack — bare metal or RTOS, no external TCP/IP needed |
+| `MG_ENABLE_LWIP=1` | Project already uses lwIP (ESP-IDF, STM32 CubeIDE, etc.) |
+| `MG_ENABLE_FREERTOS_TCP=1` | Project uses Amazon FreeRTOS+TCP |
+| `MG_ENABLE_RL=1` | ARM MDK / Keil RL-TCPnet |
+| *(none set)* | POSIX BSD sockets — Linux, macOS, Windows, embedded Linux |
+
+For bare-metal STM32, NXP RT, Renesas RA/RZ, TI TM4C, Microchip SAME54,
+Wiznet W5500, or Cypress Wi-Fi targets: use `MG_ENABLE_TCPIP=1`.
+
+## Protocols
+
+Mongoose implements: HTTP/HTTPS server and client, WebSocket server and client,
+MQTT client, DNS resolver, SNTP client, raw TCP, raw UDP, Modbus/TCP.
+
+Key listen/connect calls:
+
+```c
+mg_http_listen(&mgr, "http://0.0.0.0:80", fn, data);
+mg_http_listen(&mgr, "https://0.0.0.0:443", fn, data); // requires TLS config
+mg_mqtt_connect(&mgr, "mqtt://broker:1883", &opts, fn, data);
+mg_connect(&mgr, "tcp://host:port", fn, data);
+```
+
+## TLS
+
+To enable TLS, set `MG_ENABLE_MBEDTLS=1`, `MG_ENABLE_OPENSSL=1`, or
+`MG_ENABLE_WOLFSSL=1` and link the corresponding library.
+Alternatively, Mongoose has a built-in TLS 1.3 stack (ECC only) that requires
+no external library — enable with `MG_ENABLE_SSLTLS=1`.
+
+Server example:
+
+```c
+if (ev == MG_EV_ACCEPT) {
+ struct mg_tls_opts opts = {
+ .cert = mg_str(TLS_CERT), // PEM string
+ .key = mg_str(TLS_KEY), // PEM string
+ };
+ mg_tls_init(c, &opts);
+}
+```
+
+Client example:
+
+```c
+if (ev == MG_EV_ACCEPT) {
+ struct mg_tls_opts opts = {
+ .name = mg_url_host(url), // For hostname verification
+ .ca = mg_str(TLS_CA), // PEM string
+ // .key = mg_str(TLS_KEY), // Enable this
+ // .cert = mg_str(TLS_CERT), // for two-way TLS
+ };
+ mg_tls_init(c, &opts);
+}
+```
+
+## FreeRTOS integration
+
+When using FreeRTOS, set `MG_ENABLE_FREERTOS=1` and run `mg_mgr_poll` from a
+dedicated RTOS task:
+
+```c
+void net_task(void *param) {
+ struct mg_mgr mgr;
+ mg_mgr_init(&mgr);
+ mg_http_listen(&mgr, "http://0.0.0.0:80", handler, NULL);
+ for (;;) mg_mgr_poll(&mgr, 1);
+}
+// In main or app init:
+xTaskCreate(net_task, "net", 8192, NULL, tskIDLE_PRIORITY + 1, NULL);
+```
+
+## Device dashboard
+
+For a web UI with real-time device state over WebSocket, use the Mongoose
+device dashboard.
+
+### Required files
+
+- `mongoose.h` + `mongoose.c` — networking
+- `dashboard.c` — C-side dashboard logic
+- `dashboard.html` — HTML/JS UI (source)
+- `file_data.c` — generated from `dashboard.html` using:
+ ```sh
+ node html2c.js dashboard.html -o file_data.c
+ ```
+ `html2c.js` is at https://github.com/cesanta/mongoose/blob/master/resources/html2c.js
+
+If the project does not yet have `dashboard.c` and `dashboard.html`, fetch the
+minimal reference versions:
+
+```
+https://github.com/cesanta/mongoose/blob/master/tutorials/device-dashboard/minimal/dashboard.c
+https://github.com/cesanta/mongoose/blob/master/tutorials/device-dashboard/minimal/dashboard.html
+```
+
+If the project already has `dashboard.c` and `dashboard.html`, do **not** fetch
+anything from the repository.
+
+### C integration (bare metal or RTOS main loop)
+
+```c
+#include "mongoose.h"
+
+struct mg_mgr mgr;
+mg_mgr_init(&mgr);
+mg_dash_init(&mgr); // starts HTTP + WebSocket listeners
+
+for (;;) {
+ mg_mgr_poll(&mgr, 1);
+ mg_dash_poll(&mgr); // sends pending state updates to browser
+}
+```
+
+### dashboard.html rules
+
+- Use `dashboard.js` from `https://mongoose.ws/resources/dashboard.js`
+- Call `Dashboard.init({ data: { ... } })` once — this is the only direct
+ Dashboard API call. Treat the rest of Dashboard as a black box.
+- Do **not** add vanilla JS event listeners, `fetch()` calls, or custom
+ reactive logic to `dashboard.html`.
+- Do **not** modify `dashboard.html` unless the user explicitly asks.
+- Bind controls to device state using `data-bind` attributes:
+
+```html
+
+
+
+
+
+
+
+
LED is ${status.led1 ? 'ON' : 'OFF'}
+
+
+low RAM!
+
+
+
+
+```
+
+### dashboard.c rules
+
+- Do **not** modify `dashboard.c` unless the user explicitly asks.
+
+## Filesystem
+
+| Define | Use when |
+|--------|----------|
+| `MG_ENABLE_FATFS=1` | FatFS (SD card, flash) |
+| `MG_ENABLE_LFS=1` | LittleFS |
+| *(none)* | POSIX filesystem (Linux/macOS/Windows) |
+
+Packed (embedded) filesystem — bundle files into the binary:
+
+```sh
+node html2c.js index.html -o file_data.c # single file
+# or use Mongoose's pack tool for a whole directory
+```
+
+Serve packed filesystem:
+
+```c
+struct mg_http_serve_opts opts = {.fs = &mg_fs_packed};
+mg_mem_files = mg_packed_files;
+mg_http_serve_file(c, hm, "/dashboard.html", &opts);
+```
+
+## Logging
+
+```c
+MG_INFO(("Hello %s", "world")); // maps to printf-style output
+MG_DEBUG(("val=%d", val));
+MG_ERROR(("errno=%d", err));
+```
+
+Set `MG_ENABLE_LOG=0` to disable all logging (production / size-sensitive builds).
+
+## Key rules for AI code generation
+
+- **Two files only**: always use `mongoose.h` + `mongoose.c`. Never add a
+ separate HTTP, MQTT, or WebSocket library when Mongoose is present.
+- **One event manager**: create one `struct mg_mgr` per application.
+ Never create multiple managers unless explicitly required.
+- **Poll loop**: `mg_mgr_poll` must be called repeatedly — in `main()` loop,
+ a FreeRTOS task, or a Zephyr thread. Never call it only once.
+- **Single task**: call mg_* API function from the same task/thread that
+ runs `mg_mgr_poll` event loop
+- **No blocking inside handlers**: event handler callbacks must return quickly.
+ Do not call `sleep()`, `HAL_Delay()`, or `vTaskDelay()` inside a handler.
+- **String literals**: use `mg_str("literal")` for string constants passed to
+ the Mongoose API, not raw `char *`.
+- **TCP/IP stack**: never mix two TCP/IP stacks. If `MG_ENABLE_LWIP=1`,
+ do not also set `MG_ENABLE_TCPIP=1`.
+- **Dashboard**: do not add fetch calls or event listeners to `dashboard.html`;
+ use only `data-bind`, `data-save`, `data-cancel`, and `${...}` expressions.