Balena CLI Form Interpreter
resin-cli-form is a JavaScript/TypeScript library designed to interpret and execute declarative form definitions within command-line interfaces. It enables developers to construct interactive CLI forms with features like conditional questions using a `when` property, where subsequent questions are only presented if specific conditions based on prior answers are met. The current stable version is 5.0.1, released in February 2026. The project has undergone significant modernization in its recent major releases, notably switching from CoffeeScript to TypeScript, adopting ES Modules, and migrating to `async/await` in version 5.0.0. Its release cadence shows active development and maintenance, with major architectural shifts around 2025-2026. This library is a specialized tool for building structured, interactive CLI experiences, particularly within the Balena.io ecosystem, providing a robust abstraction for complex user input flows.
Common errors
-
ERR_REQUIRE_ESM: require() of ES Module ... not supported. Instead change the require of ... to a dynamic import()
cause Attempting to use CommonJS `require()` to import `resin-cli-form`, which is now an ES Module.fixChange `const form = require('resin-cli-form');` to `import * as form from 'resin-cli-form';` or `import { run, ask } from 'resin-cli-form';`. -
TypeError: form.run is not a function
cause Incorrect import syntax (e.g., trying to use `form.run` after a default import of a non-object, or a CJS import in an ESM context).fixEnsure you are using `import * as form from 'resin-cli-form';` or `import { run, ask } from 'resin-cli-form';` for named exports, and that your file is treated as an ESM module (e.g., `.mjs` extension or `"type": "module"` in `package.json`). -
Error: The 'engines' field in package.json specifies an unsupported Node.js version. Required: '>=20.0.0'. Found: 'v18.17.0'.
cause Running `resin-cli-form` v5.x on an unsupported Node.js version.fixUpgrade your Node.js runtime to version 20.0 or higher. You can use `nvm` (Node Version Manager) to easily switch Node.js versions.
Warnings
- breaking Version 5.0.0 converted the entire library to TypeScript and ES Modules. CommonJS `require()` syntax is no longer supported. All imports must use ESM `import` statements.
- breaking Version 5.0.0 dropped the Bluebird promise library and switched to native `async/await` for asynchronous operations. While the public API still returns Promises, internal code and any direct Bluebird interactions in calling code will need adjustment.
- breaking Node.js version requirements have progressively increased. Version 3.0.0 dropped support for Node.js versions below 18. Version 4.0.0 dropped support for Node.js 18. Version 5.0.0 and above now require Node.js 20.0 or higher.
- gotcha The `when` property for conditional questions expects an object where keys are answer names and values are the required answer for the condition to be true. Complex logical operations (AND, OR) are handled by defining multiple key-value pairs (AND) or structuring forms differently.
- breaking The project updated its GitHub organization from `resin-io-modules` to `balena-io-modules`. While npm package name remains `resin-cli-form`, be aware of updated repository and homepage URLs for contributions or issue reporting.
Install
-
npm install resin-cli-form -
yarn add resin-cli-form -
pnpm add resin-cli-form
Imports
- form
const form = require('resin-cli-form');import * as form from 'resin-cli-form';
- run
import form from 'resin-cli-form'; // then trying form.run()
import { run } from 'resin-cli-form'; - ask
const { ask } = require('resin-cli-form');import { ask } from 'resin-cli-form';
Quickstart
import { run } from 'resin-cli-form';
async function configureDevice() {
try {
const answers = await run([
{
message: 'Network Type',
name: 'network',
type: 'list',
choices: ['ethernet', 'wifi']
},
{
message: 'WiFi SSID',
name: 'wifiSsid',
type: 'input',
when: { network: 'wifi' }
},
{
message: 'WiFi Key',
name: 'wifiKey',
type: 'input',
when: { network: 'wifi' }
}
], {
override: {
// Example: pre-fill a value to skip the question
// wifiSsid: process.env.DEFAULT_WIFI_SSID ?? ''
}
});
console.log('Configuration complete. Answers:', answers);
if (answers.network === 'wifi') {
console.log(`Connecting to WiFi network: ${answers.wifiSsid} with key ${answers.wifiKey ? '*********' : '[no key provided]'}`);
}
} catch (error) {
console.error('Form execution failed:', error);
}
}
configureDevice();