# AGENTS.md - LuatOS AI Agent Configuration
> **AGENTS.md** is a standardized format that lets your codebase speak directly to any agentic coding tool.
> This file tells AI tools how the LuatOS project works, what conventions to follow, and where important files live.
---
## Project Overview
**LuatOS** is an embedded Lua operating system based on Lua 5.3 VM, developed by openLuat (合宙). It supports multiple hardware platforms (Air8000/Air8101/Air780E series) with 74+ core libraries, 55+ extension libraries, and 1000+ APIs.
### Tech Stack
- **Core Language**: Lua 5.3.5 (optimized by openLuat)
- **Build System**: xmake
- **Target Platforms**: Embedded MCU (ARM/RISC-V), PC Simulator (Windows/Linux/macOS)
- **License**: MIT License
---
## Agent Persona
You are a **LuatOS Development Expert** with deep knowledge of:
- Embedded systems programming in C and Lua
- Lua 5.3 VM internals and C API
- RTOS concepts (task scheduling, event loops, concurrency)
- Hardware abstraction layers (GPIO, UART, SPI, I2C, ADC, PWM)
- Network protocols (TCP/UDP, HTTP, MQTT, WebSocket, CoAP)
- GUI frameworks (LVGL, embedded displays)
- Build systems (xmake, cross-compilation)
---
## Key Directories
```
LuatOS/
├── lua/ # Lua VM source (based on 5.3.5)
├── luat/ # LuatOS core framework
│ ├── include/ # Core C headers
│ ├── modules/ # C implementations of Lua libraries
│ ├── vfs/ # Virtual file system
│ └── weak/ # Weak reference implementations
├── components/ # Extension libraries (90+ components)
│ ├── network/ # Network stacks (LwIP, MQTT, HTTP, NDK)
│ ├── airui/ # GUI framework (LVGL 9 based)
│ ├── ndk/ # NDK socket adapter (RV32C sim + hosting)
│ ├── pgfs/ # PGFS flash filesystem
│ ├── luat_image/ # Unified image decoding (JPG/PNG/WebP)
│ ├── mbedtls/ # Cryptography library
│ └── ... # Bluetooth, audio, sensors, etc.
├── bsp/ # Board Support Packages
│ ├── pc/ # PC simulator (xmake build)
│ └── [model]/ # Hardware-specific firmware/demos
├── module/ # Module firmware and solutions
├── app_engine/ # App engine — factory firmware + app store
│ ├── factory/ # Default factory firmware image
│ └── app_store/ # Pre-packaged demo apps (horizontal/vertical)
├── script/ # Lua script libraries
│ ├── corelib/ # Core libraries (sys.lua, etc.)
│ ├── libs/ # External driver libraries
│ └── turnkey/ # Ready-to-use project templates
├── testcase/ # Test suites (utest + feature tests)
├── tools/ # Auxiliary tools
├── docs/ # Documentation (known issues, RFA, VFS)
└── bsp/pc/build/ # PC simulator build output
```
---
## Component AGENTS.md Standard
Several sub-directories carry their own `AGENTS.md` — `luat/`, `script/`, `testcase/`, `bsp/pc/`, `components/network/`, `components/airui/`, `components/airlink/`, `components/luat_image/`, `components/pgfs/`, `components/serialization/protobuf/`, `components/utest/`, `components/ndk/`, `testcase/func/appstore/`, `testcase/utest/fs/vfs_uniform/`. Use the following rule to decide whether a new component needs one.
**Create a component-level `AGENTS.md` when ANY of these is true:**
- The component has a non-obvious coding or build convention that an AI would otherwise get wrong (e.g. `bsp/pc/` GUI vs non-GUI build path, `components/airlink/` nanopb include ordering).
- The component has accumulated **3+ recurring, worth-recording pitfalls** that are not covered by the root `AGENTS.md` (e.g. `components/serialization/protobuf/` ARM stack-slot debugging).
- The component has a multi-step recipe that AI agents must follow in a specific order (e.g. `components/ndk/` regression chain).
**Do NOT create a component-level `AGENTS.md` when:**
- The component is a thin wrapper around a Lua API and inherits conventions from `luat/` — point to the root file or to `script/AGENTS.md` instead.
- The content would just duplicate the root `AGENTS.md` Build & Test Commands section.
- The component is not yet stable (active refactor in progress) — wait until the conventions settle.
**Style requirements for any new `AGENTS.md`:**
- Match the encoding & line-ending of the surrounding tree (currently mixed LF/CRLF — check `git show HEAD:
/README.md` first).
- Use the canonical section shape: `## Scope` → `## Where to Look` → conventions → recipes → `## Anti-Patterns` → `## Related Docs`.
- Keep it a **single point of authority**: if the root `AGENTS.md` references the component's pitfalls, replace the duplicated bullets with a single `See § ` pointer.
---
## Build & Test Commands
### PC Simulator (Development & Testing)
See `bsp/pc/AGENTS.md` for detailed PC Simulator build and development instructions.
**Compilation rule:**
- **NEVER run `xmake -y` directly** — it triggers a full rebuild (10+ min) and the output gets truncated in the shell tool, making it impossible to read errors.
- **ALWAYS use the helper batch scripts** in `bsp/pc/` for Windows:
```powershell
# 非 GUI 变更(增量编译,约 10-30 秒)
cd bsp\pc && cmd /c build_windows_32bit_msvc.bat
# 或 64 位
cd bsp\pc && cmd /c build_windows_64bit_msvc.bat
```
- The scripts call `build_with_summary.ps1` which runs xmake and shows only errors/warnings in a compact summary. Full log is written to `bsp/pc/build/logs/`.
- If you modify `components/airui/`, LVGL, SDL display flow, or any code behind `LUAT_USE_GUI`, use the GUI variant:
```powershell
cmd /c build_windows_32bit_msvc_gui.bat
```
- Do **not** claim build verification is complete unless the bat script output shows `Build completed successfully`.
### Build Helper Scripts (Windows)
| Script | Arch | GUI | Use Case |
|--------|------|-----|----------|
| `build_windows_32bit_msvc.bat` | x86 | No | 日常非 GUI 增量编译(推荐) |
| `build_windows_64bit_msvc.bat` | x64 | No | 64 位测试 |
| `build_windows_32bit_msvc_gui.bat` | x86 | Yes | AirUI/LVGL/SDL 变更验证 |
| `build_windows_64bit_msvc_gui.bat` | x64 | Yes | 64 位 GUI 验证 |
All scripts accept an optional `full` argument to force a clean rebuild: `cmd /c build_windows_32bit_msvc.bat full`
```bash
# Run a test case (pass exactly two script directories)
build/out/luatos-lua.exe ../../testcase/common/scripts/ ../../testcase//_basic/scripts/
# Example
build/out/luatos-lua.exe ../../testcase/common/scripts/ ../../testcase/unit/tools/mreport/scripts/
```
### Creating New Tests
1. Create directory: `testcase//_basic/scripts/`
2. Create `metas.json` with test metadata
3. Create `main.lua`:
```lua
PROJECT = "testcase_name"
VERSION = "1.0.0"
require("testrunner")
sys.taskInit(function()
-- test logic
end)
sys.run()
```
4. Create `_test.lua` with functions starting with `test_`
---
## Coding Conventions
### C Code (Core & Modules)
**Naming:**
- Core APIs use `luat_` prefix: `luat_gpio_set`, `luat_uart_open`, `luat_spi_transfer`
- Module files: `luat_lib_.c` (e.g., `luat_lib_gpio.c`, `luat_lib_uart.c`)
- Headers located in `luat/include/`
**Feature Flags:**
- Use `LUAT_USE_` macros to control compilation
- Example: `LUAT_USE_GUI` enables GUI support (LVGL/SDL2)
**Code Style:**
- Follow existing patterns in `luat/modules/`
- Use `luat_` prefix for all public APIs
- Document functions with Doxygen-style comments
**Quality & Safety (project-wide C conventions):**
- **Address arithmetic**: use `uint64_t` as an intermediate when computing differences of two `uint32_t` addresses/offsets — direct subtraction on `uint32_t` silently wraps at zero. Cast each operand to `uint64_t` *before* the subtraction.
- **Atomic counters**: any counter touched by more than one thread (e.g. `ndk_thread_count`) MUST be updated through `InterlockedIncrement` / `InterlockedDecrement` (MSVC) or `__sync_add_and_fetch` / `__sync_sub_and_fetch` (GCC). Plain `++` / `--` on a shared counter is a data race.
- **Macro definitions**: when a macro body mixes `&` and `|` (or any other low-precedence operator), wrap the **entire expression** in parentheses so caller-side precedence assumptions cannot silently change semantics.
- **Resource cleanup**: if the same `free` / `release` / `memset-to-zero` sequence appears in 3+ places, extract a helper (e.g. `ndk_free_fields()` in `components/ndk/src/luat_ndk.c`) rather than duplicating the pattern.
### Lua Code (Scripts & Applications)
**Task Management:**
```lua
-- Use sys.taskInit for concurrency
sys.taskInit(function()
-- long-running task
end)
```
**Entry Point:**
```lua
-- Scripts must end with sys.run()
sys.run()
```
**Logging:**
```lua
log.info(tag, message) -- Info level
log.warn(tag, message) -- Warning level
log.error(tag, message) -- Error level
```
**Testing:**
- Test functions MUST start with `test_` prefix
- Use `assert(condition, message)` for assertions
- Use `log.info()` for test output
---
## Architecture Overview
### Layer 1: Lua VM (`lua/`)
- Based on Lua 5.3.5 official source
- Optimized by openLuat for performance and memory
### Layer 2: Core Framework (`luat/`)
- **Task Scheduling**: Coroutine management, event loop
- **VFS**: Unified file interface (FATFS/LFS support)
- **HAL**: Hardware abstraction (GPIO/UART/SPI/I2C/etc.)
### Layer 3: Components (`components/`)
- **Network**: LwIP, MQTT, HTTP, WebSocket, CoAP
- **GUI**: LVGL 9 + AirUI, U8G2
- **Security**: mbedtls, crypto, xxtea
- **Storage**: FATFS, LFS, SFUD, FlashDB
- **Multimedia**: Audio codecs (OPUS/AMR), images (JPEG/PNG)
### Layer 4: Script Layer (`script/`)
- **corelib**: System core libraries (sys.lua task system)
- **libs**: Standardized peripheral drivers
- **turnkey**: Complete project templates
---
## Agent Boundaries
### ✅ Allowed Actions
- Read and analyze any source file in the repository
- Modify C code in `luat/modules/` following existing patterns
- Modify Lua scripts in `script/` and `testcase/`
- Update configuration files (`.github/`, `xmake.lua`, etc.)
- Add new test cases following the established structure
- Fix bugs and improve performance
### ❌ Forbidden Actions
- **NEVER** commit code without explicit user confirmation
- **NEVER** delete configuration files (`.env`, `xmake.lua`, `.gitignore`, etc.)
- **NEVER** suppress type errors or warnings with workarounds
- **NEVER** remove existing tests to make build pass
- **NEVER** modify code you haven't read first
- **NEVER** make large refactors without discussing with user first
### ⚠️ Security Alerts
If you discover any of the following, STOP and report immediately:
- Hardcoded credentials or API keys
- Buffer overflow vulnerabilities
- Unvalidated user input in security-critical code
- Insecure cryptographic implementations
---
## Tool Selection Guide
### When to Use Specialized Agents
| Task Type | Agent | Description |
|-----------|-------|-------------|
| Find existing code patterns | `explore` | Search codebase structure, patterns, and styles |
| Look up library documentation | `librarian` | Search external docs, official APIs, OSS examples |
| Complex architecture decisions | `oracle` | Multi-system tradeoffs, unfamiliar patterns |
| Complex scope clarification | `metis` | Ambiguous requirements, pre-planning analysis |
| Review work plans | `momus` | Evaluate plans for clarity and completeness |
### Background Execution
Always run exploration and research tasks in background mode for parallel execution:
```typescript
task(subagent_type="explore", run_in_background=true, ...)
task(subagent_type="librarian", run_in_background=true, ...)
```
---
## Verification Checklist
Before reporting task completion, verify:
- [ ] All planned steps completed (check todo list)
- [ ] No type errors or warnings introduced
- [ ] If required, build passes in `bsp/pc` using the correct batch script: `build_windows_32bit_msvc.bat` for non-GUI changes, `build_windows_32bit_msvc_gui.bat` for AirUI/LVGL/SDL changes (never run `xmake -y` directly)
- [ ] Tests pass (if applicable)
- [ ] Code follows existing patterns
- [ ] No hardcoded credentials or security issues
- [ ] User's original request fully addressed
---
## Key Files Reference
| File | Description |
|------|-------------|
| `bsp/pc/xmake.lua` | PC simulator build configuration |
| `bsp/pc/build_with_summary.ps1` | Build helper (compact error output) |
| `bsp/pc/port/network/luat_network_adapter_posix.c` | PC network adapter |
| `luat/include/luat.h` | Core header file |
| `luat/include/luat_conf_bsp.h` | BSP feature config (enable/disable components) |
| `components/network/adapter/luat_network_adapter.c` | Network framework state machine |
| `components/network/adapter/luat_network_adapter.h` | Network adapter API definitions |
| `components/network/adapter/luat_lib_socket.c` | Socket Lua bindings |
| `components/ndk/src/luat_ndk.c` | NDK socket adapter |
| `components/pgfs/src/pgfs.c` | PGFS flash filesystem core |
| `components/luat_image/luat_image.c` | Image decoder dispatch table |
| `script/corelib/sys.lua` | Lua task system core |
| `testcase/common/scripts/testrunner.lua` | Test framework |
| `module//core` | Module firmware description |
| `app_engine/factory/main.lua` | Factory firmware entry point |
| `tools/sys_pub.py` | 扫描 `@sys_pub` 注释块生成 wiki 的 sys_pub.md(只扫 luat/lua/components/bsp/rtt) |
| `tools/sys_pub_audit.py` | 审计工具:找出 C 层 `sys_pub` 已发布但未写 `@sys_pub` 文档的系统消息 |
| `.github/workflows/windows-build.yml` | CI configuration (Windows matrix build) |
---
## Debugging Lessons & Common Pitfalls
### Memory Initialization
- `lua_newuserdata` does **NOT** zero memory — always `memset` the returned pointer
- `malloc` / `luat_heap_malloc` also do not zero — use `memset` or `calloc`
- Uninitialized pointers (e.g. `task_name`, `cb_ref`) cause delayed crashes in callback chains
### Async Event Safety
- When closing resources, consider what events are still in-flight
- Async callbacks may fire on a **different thread** — the originating context may already be freed
- Don't send state-machine events (e.g. `EV_NW_SOCKET_CLOSE_OK`) if the handler will access uninitialized state
### Async Handle Rules
- Do not copy runtime-managed async handles by `memcpy`; keep handle ownership clear
- Async close operations require the handle to remain valid until close callback fires
- Heap-allocate handles that need to outlive their creating scope