Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

260 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mmcli

Tests Release

Command-line interface for tinyml-modelmaker.

mmcli is a self-contained native binary (macOS, Linux, Windows) that drives the tinyml-modelmaker training and compilation pipeline entirely from the command line — no YAML config file required (though one can optionally be used as a base).

It ships with one small example dataset built into the binary (generic_audio_classification, 18 KB); the other nine are fetched on first use from this project's own GitHub release mirror (see Datasets below), so mmcli init --dataset still gets you to a running project in a single command whenever the network is reachable. Air-gapped machines can preload every dataset ahead of time via MMCLI_DATASETS.

How it works

mmcli is a single native binary (~31.8 MB, measured on macOS) that does not bundle tinyml_modelmaker, PyTorch, or TVM. Instead it:

  1. Translates your CLI arguments into the config dict that tinyml_modelmaker expects
  2. Writes a temporary YAML file
  3. Calls $MMCLI_PYTHON run_tinyml_modelmaker.py <tempfile> as a subprocess

This means tinyml_modelmaker runs in your existing Python 3.10 environment with all its native dependencies (including MPS/Metal for macOS training).

Compilation on macOS: mmcli compile and mmcli run are fully supported on macOS. Compilation always requires ti_mcu_nnc (TVM) for the NPU stage, plus a device-family compiler that depends on the target:

Target family Devices Compiler Env var
C2000 DSP F28xxx, F29xxx cl2000 C2000_CG_ROOT
ARM Cortex-M / SimpleLink / Sitara MSPM0, CC, AM tiarmclang ARM_LLVM_CGT_PATH

Set the env var to the toolchain root; mmcli resolves the binary at <root>/bin/<compiler>. Falls back to PATH if the env var is not set. Run mmcli diagnose to verify tool detection before running a compile job.

On macOS ARM64, the process may exit with code 245 after the pipeline completes — this is a known crash in the onnxsim C extension during Python shutdown and does not affect output artifacts (compilation/artifacts/mod.a is written before it).


Setup

1. Install tinyml_modelmaker (Python 3.10 environment)

# Create and activate a Python 3.10 venv
python3.10 -m venv ~/.venv-tinyml
source ~/.venv-tinyml/bin/activate

# Install tinyml_modelmaker from the release tag
pip install "tinyml_modelmaker @ git+https://github.com/musicalplatypus/tinyml-tensorlab.git@PlatypusCLI_1.0.0_Release#subdirectory=tinyml-modelmaker"

2. Set the environment variable

Add to your ~/.zshrc (or ~/.bash_profile):

export MMCLI_PYTHON="$HOME/.venv-tinyml/bin/python"

3. Get the binary

Option A — Use the pre-built binary:

cp dist/mmcli /usr/local/bin/mmcli   # or anywhere on your PATH

Option B — Download from GitHub Releases:

Pre-built binaries for macOS (arm64), Linux (x86_64), and Windows (x86_64) are published automatically on the Releases page.

Option C — Build it yourself (requires any Python + PyInstaller in an active venv):

git clone --branch PlatypusCLI_1.0.0_Release https://github.com/musicalplatypus/tinyml-cli.git
cd tinyml-cli
source ~/.venv-ai/bin/activate        # any venv with PyInstaller
pip install pyinstaller -q
pip install -e .
bash build_macos.sh                   # macOS  → dist/mmcli
bash build_linux.sh                   # Linux  → dist/mmcli
powershell build_windows.ps1          # Windows → dist/mmcli.exe

Subcommands

mmcli init — create a project from an example dataset

Create a new project directory pre-populated with a dataset, ready for training.

mmcli init -t TASK --dataset DATASET_NAME -p PROJECT_DIR [-m MODULE]
mmcli init --list [-t TASK] [-m MODULE]
Flag Short Description
--list -l List available datasets (no extraction)
--task -t Task type (required for extraction)
--dataset Name of the example dataset (required for extraction)
--project -p Path for the new project directory (required for extraction)

mmcli analyze — analyze project datasets

Analyze a project's dataset/ directory and report sample count, class distribution, sequence length, and size bucket.

mmcli analyze -i PROJECT_DIR [--format FORMAT] [-o OUTPUT_FILE]

Phase 5 Features:

  • --format json|csv|yaml - Export analysis results in specified format
  • -o FILE - Write output to file instead of stdout

mmcli info — show supported devices, models, and presets

Query the model registry and display available options.

mmcli info -m MODULE [-t TASK_TYPE] [-d DEVICE] [--format FORMAT] [-o OUTPUT_FILE]

Phase 5 Features:

  • --format json|csv|yaml - Export information in specified format
  • -o FILE - Write output to file instead of stdout

mmcli recommend — recommend models and FE presets

Score every tinyml-modelzoo example against your task, device, and variables to recommend the best-matching models.

mmcli recommend -t TASK_TYPE -d DEVICE [--format FORMAT] [-o OUTPUT_FILE] [OPTIONS]

Phase 5 Features:

  • --format json|csv|yaml - Export recommendations in specified format
  • -o FILE - Write output to file instead of stdout

mmcli compare — compare multiple models

Compare model configurations to find the best fit for your needs.

mmcli compare -m MODULE --model1 MODEL1 --model2 MODEL2 [--device DEVICE] [--format FORMAT] [-o OUTPUT_FILE]

Phase 5 Features:

  • --format json|csv|yaml - Export comparison results in specified format
  • -o FILE - Write output to file instead of stdout

mmcli diagnose — run diagnostic checks

Run diagnostic checks to identify common issues.

mmcli diagnose [--full] [--error MESSAGE] [--format FORMAT] [-o OUTPUT_FILE]

Phase 5 Features:

  • --full - Run extended diagnostics (includes disk space, etc.)
  • --error MESSAGE - Get fix suggestion for a specific error message
  • --format json|csv|yaml - Export diagnostic results in specified format
  • -o FILE - Write output to file instead of stdout

mmcli train — train a model and export ONNX

Train a model using the tinyml-modelmaker pipeline.

mmcli train -m MODULE -t TASK_TYPE -d DEVICE [-n MODEL_NAME] -i PROJECT_DIR [--progress]

Phase 5 Features:

  • --progress - Display progress bar during training

mmcli compile — compile an ONNX file

Compile a pre-trained ONNX model for a target microcontroller.

mmcli compile -m MODULE -t TASK_TYPE -d DEVICE [-n MODEL_NAME] -o OUTPUT_FILE [--progress]

Phase 5 Features:

  • --progress - Display progress bar during compilation

mmcli run — full pipeline: train then compile

Run the full tinyml-modelmaker pipeline.

mmcli run -m MODULE -t TASK_TYPE -d DEVICE [-n MODEL_NAME] -i PROJECT_DIR [--progress]

Phase 5 Features:

  • --progress - Display progress bar during training and compilation | --module | -m | AI module (auto-detected from dataset if omitted) |

Examples:

# List all available datasets
mmcli init --list

# List datasets for a specific module
mmcli init --list -m vision

# Create a project for arc fault classification
mmcli init -t arc_fault --dataset arc_fault_classification -p ./my_arc_project

# Then train with it
mmcli train -m timeseries -t arc_fault -d F28P55 -n CLS_1k_NPU -i ./my_arc_project

Tip: Run mmcli init --list to see all available datasets, or mmcli info -m timeseries -t <task> for task-specific details.


mmcli analyze — inspect a dataset

Analyse a project's dataset/ directory and report sample counts, per-class distribution, minimum sequence length, and a size bucket (tiny / small / medium / large). Feed the bucket to mmcli recommend via --dataset-size-bucket to improve model selection accuracy.

mmcli analyze -i PROJECT_DIR
Flag Short Description
--project -i Project directory containing dataset/ (or the dataset folder itself) (required)

Example:

mmcli analyze -i ./my_project
# → reports class counts and emits: dataset size bucket: medium

mmcli recommend — pick a model from the modelzoo

Score every tinyml-modelzoo example against your task, device, and optional dataset characteristics, then print a ranked shortlist of the best-matching models and feature-extraction presets.

mmcli recommend -t TASK -d DEVICE [options]
Flag Short Description
--task -t Task type (required)
--device -d Target MCU device (required)
--module -m AI module — auto-inferred from --task when omitted
--variables N Sensor channel count — boosts score +2 for an exact match
--dataset-size-bucket tiny / small / medium / large — output of mmcli analyze
--top N Number of ranked matches to display (default: 5)
--modelzoo-path DIR Explicit path to the tinyml-modelzoo repo root

Scoring: task (+1) · device (+1) · module (+1) · variables exact (+2) · size (+1) = max 6.

Examples:

mmcli recommend -t motor_fault -d F28P55 --variables 3 --dataset-size-bucket small
mmcli recommend -t arc_fault   -d F28P55 --top 10
mmcli recommend -t generic_timeseries_forecasting -d MSPM0G5187

Use the recommended model name with mmcli train -n <model> and the feature extraction preset with --feature-extraction <preset>.


mmcli train — train only

Train a model and export model.onnx. Compilation is skipped.

mmcli train -m MODULE -t TASK -d DEVICE -n MODEL -i PROJECT_DIR [options]
mmcli train -m MODULE -t TASK -d DEVICE --nas SIZE -i PROJECT_DIR [options]
Flag Short Description
--module -m timeseries or vision
--task -t Task type (see list below)
--device -d Target device (e.g. F28P55)
--model -n Model name from catalog (optional with --nas)
--project -i Path to project directory containing dataset/
--config -c Optional base YAML file (CLI args override)
--feature-extraction Feature extraction preset name
--epochs Training epochs
--batch-size Batch size
--lr Learning rate
--gpus Number of GPUs (0 = CPU/MPS, default on macOS)
--quantization NO_QUANTIZATION or QUANTIZATION_TINPU
--run-name Output folder name (supports {date-time}, {model_name})
--output Root output directory
--compile-model 0 (default) or 1 to enable torch.compile (CUDA recommended)
--native-amp Enable native mixed precision (CUDA recommended, not for MPS)
--report Generate a live-updating HTML training report (charts + confusion matrix)
--nas NAS model size preset: s, m, l, xl (classification only)
--nas-epochs NAS search epochs (default: 10)
--nas-optimize NAS resource target: Memory (default) or Compute

Example:

mmcli train \
  -m timeseries \
  -t generic_timeseries_classification \
  -d F28P55 \
  -n CLS_1k_NPU \
  -i ./data/my_project \
  --epochs 30 \
  --batch-size 256

mmcli compile — compile only

Compile a pre-trained ONNX file. No training data needed. Supported on Linux, Windows, and macOS. Requires ti_mcu_nnc (TVM) plus a device-family compiler:

  • C2000 targets (F28xxx/F29xxx): cl2000 — set C2000_CG_ROOT
  • ARM targets (MSPM0, CC, AM): tiarmclang — set ARM_LLVM_CGT_PATH

Run mmcli diagnose to verify tool availability.

mmcli compile -m MODULE -t TASK -d DEVICE -n MODEL -o ONNX_FILE [options]
Flag Short Description
--onnx -o Path to existing ONNX model file (required)
--preset Compilation preset (default: default_preset)
(common flags above)

Example:

mmcli compile \
  -m timeseries \
  -t generic_timeseries_classification \
  -d F28P55 \
  -n CLS_1k_NPU \
  -o ./data/projects/my_run/model.onnx

mmcli run — full pipeline

Train then compile. Accepts all flags from both train and compile. Compilation requires ti_mcu_nnc (TVM) plus a device-family compiler (see mmcli compile above). Supported on Linux, Windows, and macOS. Run mmcli diagnose to verify tools before running.

mmcli run \
  -m timeseries \
  -t generic_timeseries_classification \
  -d F28P55 \
  -n CLS_1k_NPU \
  -i ./data/my_dataset \
  --quantization QUANTIZATION_TINPU

mmcli deploy — flash a compiled model to hardware

End-to-end device deployment in five subcommands. Run them in sequence after mmcli run (or mmcli compile) has produced compilation/artifacts/mod.a.

mmcli deploy check-sdk — verify SDK installation

mmcli deploy check-sdk -d F28P55
mmcli deploy check-sdk -d CC1312 --sdk-path ~/ti/simplelink_cc13xx_sdk_7.10.00
Flag Description
-d / --device Target MCU device (required)
--sdk-path PATH Explicit SDK root path (skips auto-detection)

mmcli deploy artifacts — locate compiled outputs

Validates that the 4 files needed for CCS (mod.a, tvmgen_default.h, test_vector.c, user_input_config.h) all exist.

mmcli deploy artifacts -t motor_fault --run-id 20240115_143022 --model-id CLS_1k_NPU
# Add --no-quantization for float model artifacts
# Add --tinyml-base <PATH> if checkout is not at ~/tinyml-tensorlab
Flag Description
-t / --task Task type (required)
--run-id RUN_ID Timestamp run directory name (e.g. 20240115_143022) (required)
--model-id MODEL_ID Model name from training config (e.g. CLS_1k_NPU) (required)
--no-quantization Use base (float) golden vectors instead of quantized
--tinyml-base PATH tinyml-tensorlab root (default: ~/tinyml-tensorlab)

mmcli deploy create — create CCS project

mmcli deploy create \
  -d F28P55 -t motor_fault \
  --run-id 20240115_143022 --model-id CLS_1k_NPU \
  --project-name my_motor_fault_project
Flag Description
-d / --device Target MCU device (required)
-t / --task Task type (required)
--run-id RUN_ID Training run timestamp directory name (required)
--model-id MODEL_ID Model name from training artifacts (required)
--project-name NAME Name for the new CCS project folder (required)
--device-type CCS_TYPE CCS device type string — auto-resolved from --device when omitted
--sdk-path PATH Explicit SDK root path (overrides auto-detection)
--ccs-templates-path PATH Explicit AI examples directory (overrides --sdk-path)
--no-quantization Use base (float) golden vectors
--tinyml-base PATH tinyml-tensorlab root (default: ~/tinyml-tensorlab)

CCS device type strings (auto-resolved from --device):

Device CCS type
F28P55 f28p55x
F28P65 f28p65x
F28004 f28004x
MSPM0G3507 mspm0g3507
MSPM0G5187 mspm0g5187
AM263 am263
CC2755 cc2755
CC1312 cc1312
CC1314 cc1314
CC1352 cc1352

mmcli deploy build — headless CCS build (requires CCS 12+)

mmcli deploy build \
  --project-path /path/to/project \
  --ccs-path /opt/ti/ccs1260
Flag Description
--project-path PATH CCS project folder (required)
--ccs-path PATH CCS installation root (required)
--workspace PATH Eclipse workspace directory (default: /tmp/ccs_ws_<pid>)
--build-type full (default) or incremental

mmcli deploy flash — flash to device via dslite

Connect the device via USB/JTAG before running this.

mmcli deploy flash \
  --project-path /path/to/project \
  --ccs-path /opt/ti/ccs1260
Flag Description
--project-path PATH CCS project folder (required)
--ccs-path PATH CCS installation root (required)
--project-name NAME Project binary name (defaults to folder name)
--ccxml PATH Device .ccxml target config file (auto-searched if omitted)
--out-file PATH Explicit path to the .out binary (auto-searched if omitted)

Datasets

mmcli ships with exactly one dataset built into the binary (generic_audio_classification, 18 KB). The other nine are fetched on first use from this project's own GitHub release mirror — releases/download/datasets-<version>/<filename> on musicalplatypus/tinyml-cli — not from TI. TI's original CDN (software-dl.ti.com) moved its paths in production and now 404s, so the nine datasets were mirrored to this project's own release assets from their digest-verified bytes.

Dataset Name Task Type Size Description Source
generic_timeseries_classification classification 2.5 MB Synthetic waveforms (sawtooth, sine, square) fetched
generic_timeseries_regression regression 885 KB Synthetic regression data fetched
generic_timeseries_anomalydetection anomaly detection 4.0 MB Amplitude/frequency anomalies fetched
generic_timeseries_forecasting forecasting 69 KB Simulated thermostat temperatures fetched
arc_fault_classification arc_fault 13 MB DC arc fault currents (DSI sensor) fetched
ecg_classification ecg_classification 4.4 MB ECG 2-class heartbeat (normal vs abnormal) fetched
fan_blade_fault motor_fault 54 MB Fan blade vibration (3-axis accelerometer) fetched
pir_detection pir_detection 1.5 MB PIR motion detection (human vs non-human) fetched
mnist_image_classification image_classification 45 MB MNIST handwritten digits (28×28 images) fetched
generic_audio_classification audio_classification 18 KB Synthetic 2-class audio (yes/no), 16kHz sine-wave WAVs bundled

Resolution order

Every dataset lookup (mmcli init --dataset <name>, mmcli datasets path <name>, mmcli datasets pull <name>) resolves in this order:

  1. MMCLI_DATASETS, if set to an existing directory. Setting this variable disables all fetching, unconditionally — it is the offline/air-gapped escape hatch, not a path override with a network fallback. A dataset not found inside MMCLI_DATASETS is treated as unavailable even if it could otherwise be downloaded.
  2. The bundled directory inside the binary — only generic_audio_classification lives here now.
  3. The version-scoped cache, ~/.cache/mmcli/datasets/<version>/ (honours XDG_CACHE_HOME). The version is part of the path deliberately, so bumping the mirrored dataset release can never silently reuse a zip fetched under an older version.
  4. Download from the GitHub release mirror, sha256-verified against the registry before it is written into the cache.

mmcli datasets — list, fetch, and locate

mmcli datasets list                                # human table: name, state, size, description
mmcli datasets list --format json                  # committed JSON interface (name/version/state/bytes/...)
mmcli datasets pull fan_blade_fault                 # download + sha256-verify; cache short-circuits a repeat pull
mmcli datasets path generic_audio_classification    # print the resolved on-disk path, or exit non-zero

state in datasets list is one of bundled, cached, downloadable, or unavailable — computed live against the current machine's disk and environment, not a static registry field.

A corrupted cache entry is repaired automatically, and reported

If a cached zip's on-disk bytes no longer match its recorded sha256 (disk corruption, an interrupted write, manual tampering), datasets pull discards it and re-downloads automatically — it never serves the bad bytes — and reports the repair with a WARNING on stderr and a REPAIRED success line on stdout, rather than silently looking identical to a clean cache hit. The command still exits 0: the repair succeeded.

--progress-json — machine-readable transfer progress

mmcli datasets pull --progress-json <name> emits newline-delimited JSON events on stderr, one object per line, flushed immediately — unaffected by whether stderr is a terminal. It is intended for tools driving mmcli as a subprocess (e.g. PlatypusStudio) that need a determinate byte count instead of an indeterminate spinner. This is a committed interface.

Event shapes (verbatim structure; values below are from a real captured run of generic_timeseries_forecasting, a 71 KB dataset):

{"v":1,"event":"integrity-repair","dataset":"generic_timeseries_forecasting","total_bytes":71053}
{"v":1,"event":"start","dataset":"generic_timeseries_forecasting","total_bytes":71053}
{"v":1,"event":"progress","dataset":"generic_timeseries_forecasting","bytes":65536,"total_bytes":71053}
{"v":1,"event":"result","dataset":"generic_timeseries_forecasting","outcome":"downloaded","total_bytes":71053}

Ordering and content guarantees:

  • Every object carries "v":1 and "dataset".
  • integrity-repair, when it occurs, precedes start (see the corrupted- cache-entry section above — that WARNING and this event report the same condition).
  • At most one start; progress only ever follows a start. progress is throttled (at most every 200 ms or 1 MiB, whichever comes first) so a large transfer does not flood the pipe with one event per read chunk; a final progress at 100% is always emitted before result.
  • result is always the last event, and is emitted only on success. outcome is one of exactly cache-hit, downloaded, forced-redownload, integrity-repair — the same four outcomes as the plain-text success lines above.
  • On a failed transfer, no result is emitted; the existing ERROR: ... line and non-zero exit are unchanged.
  • Events never carry a filesystem path, a URL, or a hostname — only a dataset name and byte counts.

Without --progress-json, datasets pull output is unchanged: no JSON is ever printed, and the flag has no effect on init --dataset's auto-fetch policy (--progress-json is datasets pull-only).

A first init --dataset on a fetched set needs network

Unlike the old fully-bundled build, a first mmcli init --dataset <name> for one of the nine mirrored datasets needs network access unless it is already cached or MMCLI_DATASETS supplies it. To meet this in the docs rather than as a surprise mid-command:

  • init --dataset only auto-fetches when stderr is an interactive terminal. Pass --fetch to force a fetch, or --no-fetch to refuse and print the exact mmcli datasets pull <name> command to run instead.
  • A non-interactive invocation (piped, scripted, CI) never fetches implicitly — it prints that same refusal and exits non-zero, rather than starting an unnarrated multi-megabyte transfer.
  • MMCLI_DATASETS disables fetching everywhere, including inside init --dataset.

Offline / air-gapped recipe (all ten datasets)

On a machine with network access:

# 1. Pull all nine fetchable datasets into the local cache.
for n in arc_fault_classification ecg_classification fan_blade_fault \
         generic_timeseries_anomalydetection generic_timeseries_classification \
         generic_timeseries_forecasting generic_timeseries_regression \
         mnist_image_classification pir_detection; do
  mmcli datasets pull "$n"
done

# 2. Assemble an offline directory from the version-scoped cache. The cached
#    filenames are already the *local* names MMCLI_DATASETS resolves by.
mkdir -p ~/mmcli-offline-datasets
cp ~/.cache/mmcli/datasets/*/*.zip ~/mmcli-offline-datasets/

# 3. The tenth dataset has no download URL — it ships inside the binary and
#    is never fetched. Its bundled copy lives inside a PyInstaller onefile
#    temp directory that is deleted the instant the process exits, so
#    printing its path (`datasets path`) and piping that into a following
#    `cp` does not work — the file is already gone by the time `cp` runs.
#    Materialize it instead by letting `init --dataset` extract it into a
#    throwaway project (extraction happens while mmcli is still running),
#    then re-zip the result under the name MMCLI_DATASETS expects:
mmcli init --dataset generic_audio_classification -t audio_classification \
  -p /tmp/mmcli-audio-seed
(cd /tmp/mmcli-audio-seed/dataset && zip -qr \
  ~/mmcli-offline-datasets/generic_audio_classification.zip .)
rm -rf /tmp/mmcli-audio-seed

Then move ~/mmcli-offline-datasets/ to the air-gapped machine, and there:

export MMCLI_DATASETS=~/mmcli-offline-datasets
mmcli datasets list --format json   # all ten report state "bundled", none "downloadable"

All ten zips must be present in the directory named by MMCLI_DATASETS before exporting it — once set, that variable disables fetching entirely, so a missing zip is not recoverable by falling back to the network. Files resolved via MMCLI_DATASETS are not sha256-checked (that directory is explicitly user-managed), so the re-zipped copy of the tenth dataset — byte- different from, but content-identical to, the original — resolves and extracts correctly.

Fallback for manual/proxied downloads: if you must fetch a zip through a browser or a proxy instead of datasets pull, note that five of the nine mirrored datasets are stored under a different name than the one MMCLI_DATASETS expects (ti_name, the original TI provenance record, vs. the registry's local filename). Rename after downloading:

Local name (what MMCLI_DATASETS expects) Original name
fan_blade_fault.zip fan_blade_fault_dsi.zip
mnist_image_classification.zip mnist_classes.zip
pir_detection.zip pir_detection_classification_dsk.zip
arc_fault_classification.zip arc_fault_classification_dsi.zip
ecg_classification.zip ecg_classification_2class.zip

The remaining four mirrored datasets keep the same name on both sides.

Useful options

mmcli info — query the model registry

Show supported task types, models, devices, feature extraction presets, and available example datasets.

mmcli info -m MODULE [-t TASK] [-d DEVICE]
Flag Short Description
--module -m timeseries or vision (required)
--task -t Task type to show details for. Omit to list all task types.
--device -d Target device to filter models.

Examples:

mmcli info -m timeseries                        # list task types
mmcli info -m timeseries -t arc_fault           # details for arc_fault
mmcli info -m timeseries -t arc_fault -d F28P55 # models for F28P55

Dry run — inspect the generated YAML without running anything

mmcli --dry-run train \
  -m timeseries -t generic_timeseries_classification \
  -d F28P55 -n CLS_1k_NPU -i ./data

Override a base YAML config

mmcli train --config examples/hello_world/config.yaml \
            --epochs 50 --device F29H85

Verbose output (shows subprocess command + debug logs)

mmcli --verbose train ...

Training report

Generate a self-contained HTML report with live-updating accuracy/loss charts and a heatmap confusion matrix:

mmcli train \
  -m timeseries \
  -t generic_timeseries_classification \
  -d F28P55 \
  -n CLS_1k_NPU \
  -i ./data/my_project \
  --report

The report is written to <project_dir>/run/report.html and auto-refreshes every 5 seconds while training is in progress. Once training completes, the auto-refresh is removed and the final report includes the confusion matrix and file-level classification summary (if available).


Neural Architecture Search (NAS)

Instead of picking a model from the catalog (-n), you can let NAS automatically discover an optimal architecture for your dataset. NAS is supported for classification tasks only (timeseries and vision).

When --nas is set, --model/-n becomes optional — a synthetic name like NAS_m is generated automatically.

Feature extraction with NAS

Important: For timeseries tasks, you must specify --feature-extraction with a preset that is appropriate for your dataset when using --nas.

With catalog models (-n), the feature extraction configuration is provided automatically by the model description. NAS has no catalog entry, so the pipeline does not know which feature extraction to apply. Without this flag, training will fail with "Not enough dimensions present" because the raw sensor data has not been transformed into the feature representation that the classification pipeline expects.

To see which feature extraction presets are available for your task:

mmcli info -m timeseries -t generic_timeseries_classification

Common presets for generic timeseries classification include:

  • Generic_256Input_FFTBIN_16Feature_8Frame
  • Generic_1024Input_FFTBIN_32Feature_32Frame

NAS flags

Flag Description
--nas SIZE Enable NAS with a model size preset: s (small), m (medium), l (large), xl (extra-large). Controls the search space complexity and resulting model size.
--nas-epochs N NAS search epochs (default: 10). Higher values explore more architectures but take longer.
--nas-optimize MODE Resource optimization target: Memory (fewer parameters, default) or Compute (fewer MACs, lower latency).
--feature-extraction Feature extraction preset (required for timeseries NAS). Use mmcli info to list available presets.

NAS examples

# Basic NAS — medium-sized model with feature extraction
mmcli train \
  -m timeseries \
  -t generic_timeseries_classification \
  -d F28P55 \
  -i ./data/my_project \
  --nas m \
  --feature-extraction Generic_256Input_FFTBIN_16Feature_8Frame \
  --epochs 50

# NAS with explicit search budget and compute optimization
mmcli train \
  -m timeseries \
  -t motor_fault \
  -d F28P55 \
  -i ./data/motor_project \
  --nas l \
  --nas-epochs 20 \
  --nas-optimize Compute \
  --feature-extraction Generic_256Input_FFTBIN_16Feature_8Frame

# NAS for vision classification (no --feature-extraction needed)
mmcli train \
  -m vision \
  -t image_classification \
  -d F29H85 \
  -i ./data/image_project \
  --nas s

# Dry-run to inspect NAS config without running
mmcli --dry-run train \
  -m timeseries -t generic_timeseries_classification \
  -d F28P55 -i ./data/my_project --nas m \
  --feature-extraction Generic_256Input_FFTBIN_16Feature_8Frame

Supported tasks for NAS

generic_timeseries_classification · arc_fault · ecg_classification motor_fault · blower_imbalance · pir_detection · image_classification


Available task types

Timeseries: generic_timeseries_classification · generic_timeseries_regression generic_timeseries_anomalydetection · generic_timeseries_forecasting arc_fault · motor_fault · blower_imbalance · pir_detection

Vision: image_classification

Available target devices

F280013 F280015 F28003 F28004 F2837 F28P55 F28P65 F29H85 F29P58 F29P32 MSPM0G3507 MSPM0G3519 MSPM0G5187 MSPM33C32 MSPM33C34 AM263 AM263P AM261 AM13E2 CC2755 CC1352 CC1354 CC35X1

Example model names (timeseries)

Classification: CLS_100_NPU CLS_500_NPU CLS_1k_NPU CLS_2k_NPU CLS_4k_NPU CLS_6k_NPU CLS_8k_NPU CLS_13k_NPU CLS_20k_NPU CLS_55k_NPU CLS_ResAdd_3k CLS_ResCat_3k

Regression: REGR_1k REGR_2k REGR_3k REGR_4k REGR_10k REGR_13k REGR_500_NPU REGR_2k_NPU REGR_6k_NPU REGR_8k_NPU REGR_20k_NPU

Anomaly Detection: AD_1k AD_4k AD_16k AD_17k AD_Linear AD_500_NPU AD_2k_NPU AD_6k_NPU AD_8k_NPU AD_10k_NPU AD_20k_NPU

Forecasting: FCST_3k FCST_13k FCST_LSTM8 FCST_LSTM10 FCST_500_NPU FCST_1k_NPU FCST_2k_NPU FCST_4k_NPU FCST_6k_NPU FCST_8k_NPU FCST_10k_NPU FCST_20k_NPU

Application-specific: ArcFault_model_200_t ArcFault_model_300_t ArcFault_model_700_t ArcFault_model_1400_t MotorFault_model_1_t MotorFault_model_2_t MotorFault_model_3_t FanImbalance_model_1_t FanImbalance_model_2_t FanImbalance_model_3_t ECG_55k_NPU PIRDetection_model_1_t

Tip: Run mmcli info -m timeseries -t <task> to see models available for a specific task.


Building the binary

# macOS
bash build_macos.sh              # arm64 (Apple Silicon, default)
ARCH=x86_64 bash build_macos.sh  # Intel Mac
ARCH=universal2 bash build_macos.sh  # fat binary (both)

# Linux / Windows
bash build_linux.sh              # → dist/mmcli
powershell build_windows.ps1     # → dist/mmcli.exe

Copy dist/mmcli anywhere on your PATH. No Python environment needed to run the binary — only MMCLI_PYTHON must point to a Python 3.10 install that has tinyml_modelmaker.


Environment variables

Variable Default Description
MMCLI_PYTHON python or python3 on PATH Python interpreter with tinyml_modelmaker installed
MMCLI_MODELMAKER auto-detected Path to tinyml-modelmaker source dir (only needed if auto-detection fails)
MMCLI_DATASETS unset (fetch from the GitHub release mirror; only generic_audio_classification is bundled) Directory of dataset zips to use instead of fetching. Setting it disables all dataset fetching — see Datasets.
ARM_LLVM_CGT_PATH (none) Root of the ARM LLVM toolchain. When set, mmcli looks for tiarmclang at $ARM_LLVM_CGT_PATH/bin/tiarmclang. Falls back to PATH if unset. Required for compilation when tiarmclang is not on PATH.
C2000_CG_ROOT ~/bin/ti-cgt-c2000_* Root of the TI C2000 CGT installation. Required for compilation of C2000 targets (F28P55, F28P65, etc.) on all platforms. Download from TI's website.

CI / CD

Tests run automatically on every push and pull request via GitHub Actions:

  • test-cli.yml — Tiers 1–4 on Linux and Windows
  • release.yml — Build binaries for macOS, Linux, and Windows on tag push

To create a release:

git tag v1.0.0
git push origin v1.0.0

Security Considerations

Input Validation

All user inputs are sanitized before use:

  • Command arguments are stripped of shell metacharacters (;, $, `, |)
  • File paths are validated to prevent directory traversal
  • Environment variables are cleaned before subprocess calls

Subprocess Security

All subprocess calls use shell=False with argument arrays to prevent command injection.

Path Validation

Project paths must be relative or within safe directories (not absolute paths starting with /).

For more information, see SECURITY.md and docs/SECURITY_MODEL.md.

About

A platypus-friendly CLI for TinyML Model Maker

Resources

Security policy

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages