The CLI has two optional developer environments, the same ones the Editor has:
| Environment | Label | For | Tools |
|---|---|---|---|
embedded | firmware | Cortex-M firmware built with CMake presets (Arm GCC, Arm Compiler 6, IAR) | fw_toolchain, fw_build, fw_size, fw_test, fw_flash, fw_serial, fw_fault, fw_debug, fw_import |
hdl | hardware | FPGA and ASIC designs in Verilog, SystemVerilog and VHDL described by hdl.json | hdl_project, hdl_lint, hdl_sim |
none | Everything else (the default) | None |
Selecting an environment adds its tools and a short section of the system prompt that tells the agent how to use them; none removes both. The welcome screen shows an Environment cell, and the status bar shows firmware or hardware while one is active.
Maturity
The CLI's firmware and HDL tools reuse the Editor's embedded and HDL modules (tool definitions, CMake presets reader, size report, fault decoder, CTest and Unity parsing, project importer, OpenOCD arguments, GDB/MI layer). Those modules' own records state:
- Embedded: nothing has been run on a board yet. Flashing through J-Link, ST-LINK (STM32CubeProgrammer) or OpenOCD, and debugging, have integration tests written but not yet run. IAR and Keil projects are not yet run against IAR or Keil.
- HDL: the open tools are verified on Linux. No vendor path is verified, nothing is verified on Windows, and no board was programmed in the repository's tests.
The CLI's own documentation records no runs against hardware. Do not rely on flashing, debugging or serial tools for production work until they are verified for your probe, target, tools and operating system. See Domain modules for the Editor's state.
Switch an environment on
An environment is a project setting, chosen by hand:
/environment # picker in the interactive interface
/environment embedded # or: firmware, hdl, hardware, none
neuralinverse env # show the current environment
neuralinverse env set hdl # set it from a shell (writes .neuralinverse/settings.json)
Or edit .neuralinverse/settings.json:
{ "environment": "embedded" }
Rules:
- It is never switched on automatically. A folder full of CMake presets, Keil projects or
hdl.jsonstill starts withnone. - It is never stored in user-level settings.
~/.neuralinverse/settings.jsoncannot set it, and/environment --userandneuralinverse env set --userrefuse. Managed policy does not set it either. - It applies only in a project folder: a repository, a folder with a build manifest (
CMakeLists.txt,Makefile,package.jsonand similar), or a folder withhdl.json. Not your home folder. Outside a project the setting is ignored and/environmentsays why. - The Editor's switches count. When the CLI setting is absent,
neuralInverse.embedded.enabledorneuralInverse.hdl.enabled(orneuralInverse.environment) in the project's.vscode/settings.jsonselect the environment, so a project set up in the Editor works unchanged. An explicit"environment": "none"in.neuralinverse/settings.jsonturns them off for the CLI.
Settings
The tool settings use the Editor's names: embedded.X.Y in .neuralinverse/settings.json is neuralInverse.embedded.X.Y in .vscode/settings.json, and hdl.X.Y is neuralInverse.hdl.X.Y. Both files are read; the CLI's values win.
| Setting | Meaning |
|---|---|
embedded.paths.<tool> | Path to a tool or its folder: armGcc, cmake, ninja, openocd, gdb, armCompiler6, iarArm, jlinkCommander, jlinkGdbServer, stm32Programmer, stlinkGdbServer; CLI only: qemu, stFlash |
embedded.cmake.sourceDirectory | Folder with CMakePresets.json (default: the project root) |
embedded.cmake.configurePreset, buildPreset, testPreset | CLI only: presets used when a call names none |
embedded.elfFile, embedded.linkerScript | Image to measure, flash or debug, and the script with the MEMORY regions |
embedded.probeServer | openocd (default), jlink or stlink |
embedded.openocd.board, interface, target, adapterSerial, adapterSpeed, arguments | OpenOCD scripts; board defaults to board/stm32f4discovery.cfg |
embedded.jlink.device, interface, speed, serial | SEGGER J-Link |
embedded.stlink.serial, frequency, connectUnderReset | ST-LINK through STM32CubeProgrammer |
embedded.debug.gdbPort | GDB server port (3333 OpenOCD, 2331 J-Link, 1234 QEMU) |
embedded.serial.port (CLI only), embedded.serial.baudRate | Serial console |
embedded.qemu.machine, cpu | CLI only: QEMU machine for fw_debug without hardware |
hdl.projectFile | HDL project file (default hdl.json) |
hdl.paths.<tool> | verilator, iverilog, vvp, ghdl |
hdl.lint.verilatorArguments, ghdlArguments | Extra lint arguments; the CLI adds -Wall for Verilator when unset |
hdl.simulation.icarusArguments, verilatorArguments, ghdlArguments, ghdlWaveform | Simulation arguments; GHDL writes a VCD by default |
hdl.simulation.failPatterns, passPatterns | CLI only: extra regular expressions that fail or mark a run |
Settings that name programs or arguments to run (paths.*, openocd.arguments, the lint and simulation arguments) are "restricted": the Editor honours them only in a trusted workspace. In the CLI, when the project's own files set any of them, the otherwise read-only tools (fw_toolchain, fw_size, hdl_lint) ask before running, since a cloned repository could point them anywhere.
Firmware tools
Every tool runs programs from argument arrays, never through a shell, and answers with a short structured result and, on failure, the next step to take.
| Tool | What it does |
|---|---|
fw_toolchain | Finds Arm GCC, armclang, IAR iccarm, CMake, Ninja, OpenOCD, J-Link, ST-LINK (STM32CubeProgrammer, st-flash), GDB and QEMU: configured paths, then PATH, then the vendors' usual install folders. Reports versions, tools older than the minimums, and install hints. Read-only |
fw_build | Runs cmake --preset <configure> and cmake --build --preset <build>. Compiler and linker output becomes file:line:col findings (GCC, armclang, IAR, GNU ld, armlink). After linking, reports Flash and RAM per MEMORY region and the largest symbols. Writes only into the preset's build folder and is treated like an edit |
fw_size | Analyses an ELF the same way, or a GNU ld map file when the binutils are missing |
fw_test | Runs ctest --output-junit, parses the JUnit report and extracts Unity failure lines; can also parse a saved Unity log |
fw_flash | Programs .elf or .hex (or .bin with an address) through OpenOCD (program <image> verify reset exit), J-Link Commander, or STM32CubeProgrammer (-w -v -rst; st-flash as a fallback). Always asks; see below |
fw_serial | Reads a serial port for N seconds or until a regular expression matches, optionally sending a line first. Uses stty on macOS and Linux and PowerShell's System.IO.Ports on Windows. Opening a port asks for approval |
fw_fault | Decodes CFSR, HFSR, MMFAR, BFAR, EXC_RETURN and the stacked frame, explains the cause, and maps the stacked PC and LR to function and line with arm-none-eabi-addr2line when given the ELF. Read-only |
fw_debug | A short GDB/MI session against OpenOCD, the J-Link GDB Server, QEMU (started halted on the ELF) or a running server: registers, backtrace, memory at an address, or an expression. Connecting halts the target, so it asks for approval |
fw_import | Reads Keil (.uvprojx), IAR (.ewp) and STM32CubeIDE (.cproject) projects and returns a proposed CMakeLists.txt, CMakePresets.json, toolchain file and, when needed, a GNU linker script. Nothing is written; the agent writes what you agree with through the normal edit tools |
Flashing always asks
Flashing hardware always needs a person's approval:
- in every permission mode, including
full-auto; - even when an allow rule matches (
fw_flash,fw_*) or atool.beforehook approves; - "always allow" answers are treated as "once", and no rule is saved.
Policy can still deny it ("deny": ["fw_flash"]), and read-only mode denies it. Non-interactive runs (-p, CI, schedules, helper agents without a person) cannot flash: the call is denied and the agent is told why.
The approval card shows the probe, the target, the image path, its size and its SHA-256. The image is hashed again just before programming; if it changed after you approved (for example, a rebuild in between), nothing is flashed.
Hardware tools
hdl.json is the Editor's project file:
{
"name": "blinky",
"sources": ["rtl/**/*.sv"],
"includeDirs": ["rtl/include"],
"defines": { "WIDTH": 8, "SIM": true },
"top": "top",
"vhdlStandard": "08",
"buildDirectory": "build/hdl",
"testbenches": [{ "name": "tb_top", "top": "tb_top", "sources": ["tb/tb_top.sv"], "simulator": "icarus", "timeout": 60 }],
"targets": [{ "name": "icebreaker", "family": "ice40", "device": "up5k", "package": "sg48", "constraints": "icebreaker.pcf" }]
}
Comments and trailing commas are allowed; unknown keys are errors.
| Tool | What it does |
|---|---|
hdl_project | Validates hdl.json, expands the source globs, lists the testbenches and targets, prints the design hierarchy, and reports which HDL tools are installed |
hdl_lint | Runs Verilator --lint-only -Wall on Verilog and SystemVerilog (Icarus -t null when Verilator is missing) and GHDL on VHDL, with the project's include folders, defines, top and VHDL standard. Findings come back as file:line:col: severity: message [CODE] |
hdl_sim | Builds and runs a testbench with Icarus Verilog (iverilog -g2012 and vvp -n), Verilator (--binary --timing --assert --trace) or GHDL (with a VCD), into <buildDirectory>/sim/<testbench>. A run passes when it exits 0 within its timeout and reports no $error or $fatal, failed assertion, or VHDL error or failure report, and matches no failPatterns. Waveform files the run wrote are listed |
Troubleshooting
/environment(orneuralinverse env) prints where the current value came from and why an environment is off (not a project folder, or both Editor switches on).fw_toolchainandhdl_projectlist every tool with its version or an install hint.- Probe problems:
fw_flashnames the probe software's error and suggests checking cables, USB permissions (udev rules on Linux) and power.