Skip to content
Open
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6ac221d
feat: add Arduino App specification document
dido18 Nov 3, 2025
72a7e10
docs: update Arduino App specification for clarity and completeness
dido18 Nov 3, 2025
ac95a4d
docs: clarify Arduino App folder structure and reserved names
dido18 Nov 3, 2025
2bc7f89
app
dido18 Nov 3, 2025
e9f058c
Applied linter
cmaglie Nov 18, 2025
d762618
Add a first model draft
martacarbone Nov 19, 2025
ff1ce52
Added the section with changes to the current implementation
martacarbone Nov 19, 2025
6d99d10
Move in a dedicater branch
martacarbone Nov 19, 2025
e2c36ef
Added some details
cmaglie Nov 20, 2025
fdb56a7
update specifaction
mirkoCrobu Jan 29, 2026
45a54ba
resolve some todo
mirkoCrobu Jan 30, 2026
ccf610a
code review fix
mirkoCrobu Feb 2, 2026
65cc7c2
add ports specification
mirkoCrobu Feb 5, 2026
c8d001e
fix brick definition
mirkoCrobu Feb 6, 2026
9aae752
improve app definition and app architecture sections
mirkoCrobu Feb 6, 2026
4cb1699
improve sections
mirkoCrobu Feb 6, 2026
0276dfa
finalize refactoring
mirkoCrobu Feb 6, 2026
7a8a45b
fix minor errors
mirkoCrobu Feb 6, 2026
c4bf603
add broken app section
mirkoCrobu Feb 6, 2026
329f870
minor error
mirkoCrobu Feb 6, 2026
05699d7
Update app.yaml and brick section: required device moved from yaml to…
martacarbone Feb 19, 2026
d613f21
fmt
mirkoCrobu Mar 24, 2026
5b0b2d2
apply code review fixes
mirkoCrobu Mar 27, 2026
7de63cc
apply code review feedbacks
mirkoCrobu Mar 27, 2026
be1522c
apply code review
mirkoCrobu Apr 3, 2026
7a9e5af
refactoring
mirkoCrobu Apr 7, 2026
2634acf
some fixes
mirkoCrobu Apr 8, 2026
7f13d17
fix example app.yaml
mirkoCrobu Apr 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 195 additions & 0 deletions docs/app-specification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
# Arduino App specification

This is the specification for the Arduino App format to be used with `arduino-app-cli` and `Arduino App Lab`.

Arduino Apps are designed to run on `dual-brain` Arduino Boards (e.g., [Arduino Uno Q](https://store.arduino.cc/pages/uno-q)).
An Arduino App leverages the board's operating system and the integrated microcontroller to perform a wide range of tasks, from high-level logic, data processing, executing AI models and more.

An Arduino App is composed of two main software components that work together as a single application:

- [**Arduino Sketch**](https://docs.arduino.cc/arduino-cli/sketch-specification/). It runs on the integrated Microcontroller (MCU). It is responsible for low-level hardware interaction, sensors, and actuators.
- **Python and containers**. They run on the board's Linux OS.

The Sketch and the Python communicate using an RPC-based messaging (see [arduino-router](https://github.com/arduino/arduino-router)).

An App can be extended through **Bricks**: modular software components that add ready-to-use functionality (e.g. databases, computer vision services). An App may include multiple Bricks.

## Arduino App folders and files

An Arduino App is a self-contained folder that includes a descriptor file (app.yaml), other sub-folders and files.

### Arduino App root folder

The root folder containing the Arduino App files and subfolders.

#### `app.yaml` file

The `app.yaml` file contains the metadata of the App. It is mandatory and must be located in the root folder.
See the [App Descriptor (`app.yaml`)](#app-descriptor-appyaml) section for details.

#### `python` subfolder

Contains the python code of the App.

- **Status**: Mandatory.
- **Required File**: `main.py` (The entry point of the application).
- **Optional File**: `requirements.txt` (Standard Python dependency list).
- **Constraint**: must be located specifically in the `root-app-folder/` path.

#### `sketch` subfolder

Contains the Arduino sketch to be flashed on the integrated microcontroller.

- **Status**: Optional, Reserved.
- **Required Files**: If present, must include both `sketch.ino` and `sketch.yaml`.
- **Constraint**: The folder content must comply with the official [Sketch specification](https://arduino.github.io/arduino-cli/1.3/sketch-specification/).

#### `README.md` file

A markdown file located in the root folder.

- **Status**: Optional.
- **Arduino App Lab** renders this file to provide documentation to the user.
- **Constraint**: If the `description` field in `app.yaml` is absent or empty, the system derives the app description from `README.md` by parsing the first non-title paragraph and stripping all markdown syntax.

#### Reserved Folders

The following folders are reserved for specific uses:

##### `data` subfolder

- **Status**: Optional.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **Status**: Optional.
- **Status**: Reserved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could put: - **Status**: Optional, Reserved.?

- **Constraints**:
- It contains volumes and other data generated by the App and its dependencies (e.g., database storage).
- The content is accessible to the user to allow backups or deletion to reset the App state.
- This folder should be emptied before sharing the App to avoid leaking personal data.
- Located in `root-app-folder/`.

##### `.cache` subfolder

- **Status**: Optional.
- **Constraints**:
- It contains volatile data needed to run the App (e.g., the Python `venv` folder or Docker Compose support files).
- The content is transient and might change in the future.
- It can be safely deleted at any time when the App is not running.
- Located in `root-app-folder/`.

#### Extra files/folders

**Extra Files**: Any other file or folder is allowed. The runtime preserves these files and makes them accessible to your Python logic, but performs no automated action on them. They are bundled with the App during Import and Export operations.

### A complete example

A hypothetical App named "SmartGarden" that adheres to the specification follows. Note that the root folder name (my-garden-project) differs from the App name defined in YAML.

```
my-garden-project/
├── app.yaml # Mandatory metadata (strict naming)
├── README.md # Documentation (Optional)
├── python/ # Mandatory source folder
│ ├── main.py # Mandatory entry point
│ └── requirements.txt # Python dependencies (Optional)
├── sketch/ # Arduino sketch folder (Optional)
│ ├── sketch.yaml # Arduino sketch dependency
│ └── sketch.ino # Arduino sketch
├── .cache/ # Reserved
└── data/ # Reserved
```

## App Descriptor (`app.yaml`)

The `app.yaml` file (also referred to as the **App Descriptor**) is the manifest of the Arduino App. It allows the host system to identify, configure, and orchestrate the App and its dependencies.

### File Format

- **Filename**: must be exactly `app.yaml`(not `.yml`).
- **Location**: Root of the App folder.
- **Syntax**: Standard YAML.

### Configuration Fields

- **`name`** (Optional): Human-readable name.
- Constraints: alphanumeric, underscores, dashes, and spaces. Cannot start with a dash.

- **`icon`** (Optional): A single emoji character used in the App Lab UI.
- **`description`** (Optional): A short summary of the app's purpose. If omitted, it is retrieved from the first paragraph of README.md (see the README.md file paragraph for details).
- **`ports`** (Optional): A list of integers representing the network ports exposed by the Python logic (e.g., for a web dashboard).
- **`bricks`** (Optional): A list of Brick Object. Additional bricks needed by the app to perform specific tasks (see the next section for details).

### Brick Object Definition

Bricks are Python-first modular dependencies that encapsulate both application logic and infrastructure configurations (such as Docker Compose files) to extend an App's capabilities.
While the App folder holds the application logic and local resources, the App may depend on Bricks. These dependencies are declared in the App's description, but the Bricks themselves are not stored inside the App folder. They are downloaded and managed externally by the host system.

This section describes the structure of a single item within the bricks list in `app.yaml`.

- **`id`** (Mandatory): The unique identifier string of the Brick (e.g., web_ui, image_classification).
- TODO: Update the spec after custom bricks validation rules are defined.
- **`model`** (Optional): The model id to load within the Brick.
- **`variables`** (Optional): A map of key-value pairs (both must be strings) representing configuration parameters or environment variables passed to the Brick container.
- **`ports`** (Optional): A list of integers representing the network ports that the Brick must expose to interact with the User(e.g., exposing web interfaces).
- Default Behavior: If ports are not explicitly defined in the app.yaml file, the system automatically uses the default ports specified in the Brick's metadata (if any).
- Collision: If two or more Bricks attempt to use the same port, a network collision occurs. This conflict will prevent one of the Bricks from starting, potentially causing the application to fail or remain in a partial state.
- **`required_devices`** (Optional): A list of "class" of devices, required by the app (e.g., `camera`, `remote_camera`, `microphone`, `remote_microphone`).

#### Handling Secrets in Variables

The `app.yaml` supports the use of **Secrets** within the Brick `variables` map to handle sensitive information, such as database passwords.

Comment on lines +137 to +138
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how to define a secret variable ? we could give example

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

variables:
  - name: API_KEY
    description: API Key 
    secret: true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this struct just for the brick-list?
and in the app.yaml is:
arduino-app-cli/internal/orchestrator/app/testdata/complex-app.yaml at main · arduino/arduino-app-cli

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you think?
looking at the code it seems works like this:
Some Bricks define certain variables as secrets. This is declared in the Brick's own definition, not in the app.yaml.
In the app.yaml, the user sets the value of a secret variable exactly like any other variable, using the standard variables map.
Automatic Redaction: When an App is exported, the values of variables marked as secret in the Brick definition (within app.yaml) are automatically redacted (set to empty). This ensures that the App bundle can be safely shared without leaking credentials or private keys.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, to make it clear that the "secret" variable is defined in the brick definition. Based on this indo, the variable defined in the app-yaml is redacted

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened a PR to remove the secret value from the app-yaml testing file that can cause confusion
https://github.com/arduino/arduino-app-cli/pull/346/changes

- **Automatic Redaction**: When an App is **exported**, the values of these secrets are automatically **redacted**. This ensures that the App bundle can be safely shared without leaking personal credentials or private keys.

### Example `app.yaml`

```yaml
name: Smart-Garden-Pro
description: AI-powered irrigation and monitoring system
icon: 🌿
ports:
- 5000

bricks:
- id: arduino/dbstorage
variables:
PASSWORD: password
ports: "8080"
Comment on lines +152 to +154
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not true, secret is a boolen field

Suggested change
variables:
secret: "secret.db_password"
ports: "8080"
variables:
secret: true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from tests:
[arduino-app-cli/internal/orchestrator/app/testdata/complex-app.yaml at main · arduino/arduino-app-cli](https://github.com/arduino/arduino-app-cli/blob/main/internal/orchestrator/app

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, it is misleading to have an example with the name of the variable equal to "secret" that is also the field used in the brick definition to mark the variable secret.

I would use a more variable name like "MY_ROOT_PASSWORD" and also show the snippet of the bricks that define the variable as secret

- id: arduino/objectdetection
model: yolo-v8
ports:
- 8001
```

## Broken App Definition

A **Broken App** is a directory that the system has successfully identified as an Arduino App but which fails to meet the operational requirements. Unlike a generic folder, a Broken App is an entity recognized by the `arduino-app-cli` and `Arduino App Lab`, but it is flagged as non-functional.

### The Primary Identifier

The presence of the `app.yaml` file is the **sole requirement** for a directory to be promoted from a "generic folder" to an "Arduino App" entity.

- If `app.yaml` is present: The system must attempt to parse it and register the App.
- If `app.yaml` is missing: The directory is ignored and must not be treated as an App.

### Broken State Criteria

An Arduino App entity is classified as **Broken** if it falls into one of the following categories:

- **Invalid Descriptor**: The `app.yaml` file exists but contains syntax errors (invalid YAML) or violates the schema constraints (e.g., invalid characters in the `name` field).
- **Structural Incompleteness**: The App lacks the mandatory internal components defined in the Project Structure:
- Missing `python/` directory.
- Missing `python/main.py` file.

- **Incomplete Sketch folder**: The `sketch/` folder exists, but it is missing the mandatory `sketch.ino` or `sketch.yaml` files.

### System Behavior for Broken Apps

The existence of a Broken App entity allows the system to provide feedback rather than silent failure:

- **Discovery**: The `arduino-app-cli` must include Broken Apps in its list, clearly marking their status.

### Static Validation vs. Runtime Errors

The classification of an App (as Valid or Broken) is determined solely through **Static Validation**. This process checks the presence and organization of files and the integrity of the `app.yaml` descriptor.

- **Scope of Static Validation**: The system only verifies that the required folders and files exist and that the manifest is readable.
- **Exclusion of Execution Errors**: Static validation **does not** include code analysis. For example, a `main.py` file that contains Python syntax errors, or a `sketch.ino` that fails to compile due to logic errors, will **not** cause the App to be flagged as "Broken" during the discovery phase.
- **Failure Mode**: Such issues will only emerge during the **Orchestration & Deployment** phase (Runtime), at which point the system will report an execution or compilation failure.
Loading