Skip to content
neuralSPOT-X
User guide
HELIA HUB

The app model

An NSX app is a self-contained CMake project. It owns its source, its manifest, its pinned dependency set and the vendored copy of every module it builds against. Nothing about it depends on state elsewhere on your machine except the nsx CLI itself and your compiler.

That is the whole model. The rest of this page is why it is built that way and what it means for how you work.

There is no workspace, no global project registry and no shared build directory. You create an app, you work in it, and you can delete it without leaving anything behind.

Two apps on the same machine can pin different revisions of the same module and neither notices the other. An app you cloned from a colleague builds from its own nsx.lock rather than from whatever your machine happens to have cached.

Commands that act on an app find it by walking up from your working directory until they see an nsx.yml. That is why the examples throughout these guides just say nsx build with no path. Use --app-dir when you want to act on an app somewhere else.

Module sources land in modules/ inside the app. Board definitions land in boards/. Neither is a reference to a shared location; they are real directories with real files you can open, grep and step through in a debugger.

This costs disk space and buys three things:

  • The build is inspectable. When a link fails, the source that failed to link is in a directory you can read, not behind a package manager.
  • The build is reproducible. nsx.lock pins every module to a commit and a content hash. nsx sync --frozen will refuse to proceed if what is on disk no longer matches.
  • The app outlives NSX. The generated tree is ordinary CMake and Ninja. If you want to graduate an app into your own build system, you already have all the sources.

build/ and .nsx/ are gitignored by the generated .gitignore, and modules/ by the modules/.gitignore that nsx configure writes, because nsx.lock is enough to reconstruct them. Commit nsx.yml and nsx.lock; let NSX re-fetch the rest.

Create your first app is the walkthrough. This section is about the decisions that walkthrough makes for you.

--board fixes the SoC, the startup and linker behavior, the flash and SWO settings and the SDK provider for the app. It defaults to apollo510_evb. Everything else NSX resolves follows from it, which is why there is no meaningful way to create an app without one.

--soc overrides the SoC that the board would otherwise imply. You need it only for a board NSX cannot map to an SoC on its own, which it tells you about directly:

Unable to infer --soc for board 'my_board'. Pass --soc explicitly.

See Boards and targets for how target selection works after the app exists, including building one app for several boards.

The template decides what the first build does

Section titled “The template decides what the first build does”
Template What you get
default A minimal app: initialize the runtime core, then print to SWO in a loop.
npu-tflm TFLite Micro inference on the Ethos-U85 NPU. Seeds nsx-helia-rt and nsx-npu, and ships a Vela model harness plus a tools/tflite_to_header.py converter.

npu-tflm declares atomiq110 as its SoC, so it needs a board on that family. Anything else is rejected with the list of templates NSX knows:

Unknown app template 'tflite'. Known templates: default, npu-tflm

By default create-app clones the starter modules the board’s profile calls for and writes boards/<board>/. --no-bootstrap skips both: you get the app skeleton, an empty modules/, no boards/ directory, and baseline: none recorded in nsx.yml.

Use it when you have no network, or when you intend to choose the module set yourself rather than start from the board’s baseline.

Writing into a directory that is not empty

Section titled “Writing into a directory that is not empty”

create-app refuses by default:

App directory already exists and is not empty: /home/you/my_app

--force allows it. It overwrites the generated files it owns; it does not clean the directory first.

The remaining flags are on the nsx create-app reference page, which is generated from the CLI itself.

You own NSX regenerates
src/, and any other source you add cmake/nsx/
CMakeLists.txt boards/<board>/
nsx.yml modules/
nsx.lock, by running nsx lock build/<board>/

Editing anything in the right-hand column works until the next nsx configure, nsx sync or nsx lock overwrites it. If you need to change how a module builds, change the module, not the vendored copy. Custom modules covers how to point an app at a module you control.

CMakeLists.txt is the interesting exception. NSX writes it once and then leaves it alone, so adding source files, compile options or your own targets is normal CMake work.