Skip to content
Support

Scripting & Automation

pcu-cli is built to be scripted. Data goes to stdout; prompts, warnings, and errors go to stderr; and every command sets a meaningful exit code. This page covers the flags and output formats you need for unattended use. For the full command list, see the Command Reference.

  • stdout carries the data: the status table, timer values, channel states, and all JSON.
  • stderr carries confirmation prompts, warnings, and error messages.

Because prompts and warnings never touch stdout, you can capture clean data with pcu-cli ... > out.txt while any prompt still appears on the terminal.

FlagDescription
--quietBare values only, one per line. Also skips confirmation prompts.
--jsonJSON output. Supported on status, ign, dio, and version.
--yes, -ySkip write confirmation prompts.
--version, -VPrint version info and exit. Runs without elevation.
-h, --help, /?Print command help and exit.

Notes:

  • --quiet implies --yes: quiet writes never prompt.
  • --json on its own still prompts before a write. Add --yes for unattended writes.
  • --json and --quiet have no effect on driver; its output is always the text form.
  • pcu-cli reads no environment variables and no configuration files. Everything is passed on the command line.

status, ign, dio, and version emit a single indented JSON object on stdout. Errors still go to stderr, and the exit code is unchanged, so a script can branch on either.

status --json on a CQ20:

{
"platform": "In-CarPC CQ20",
"cpu": "Intel Atom x6425E",
"mcu_identity": "CQ20 MCU",
"hardware_rev": "DTB-IGN-MCU VER:10",
"firmware": 12,
"ignition": {
"mode": 1,
"ign_on_delay_s": 6,
"sw_on_delay_s": 3,
"sw_off_delay_s": 3,
"pw_off_delay_s": 900
},
"timers_stored": true
}

ign --json is the timer summary on its own:

{
"mode": 1,
"ign_on_delay_s": 6,
"sw_on_delay_s": 3,
"sw_off_delay_s": 3,
"pw_off_delay_s": 900
}

A single ign get read is { timer, value }, with the value in seconds:

{
"timer": "sw-off-delay",
"value": 3
}

A write reports the requested value, the value read back, whether they match, and whether the value was stored:

{
"timer": "sw-on-delay",
"requested": 3,
"actual": 3,
"verified": true,
"stored": true
}

stored is true when the value is stored. On a CQ20 it is false if the MCU did not confirm the store within 5 seconds, and on a CQ50S it is false if the MCU did not accept the save command. The exit code is then 1. The CQ40 series and CQ40N MCUs save by themselves, so stored is always true there.

status --json on a CQ50S has four timers, all in seconds, and no mode. The CQ50S reports no hardware revision, so hardware_rev is omitted, and firmware is a number (the status text shows a version string instead). ignition_line is the state of the ignition input, true for On:

{
"platform": "In-CarPC CQ50S series",
"cpu": "Intel Core (CQ53S/CQ55S/CQ57S)",
"mcu_identity": "CQ50S Ignition MCU",
"firmware": 1280,
"ignition": {
"ign_on_delay_s": 3,
"ign_off_delay_s": 3,
"pw_off_delay_s": 900,
"ups_off_delay_s": 60
},
"timers_stored": true,
"ignition_line": true
}

ign set ign-off-delay 5 --yes --json on a CQ50S:

{
"timer": "ign-off-delay",
"requested": 5,
"actual": 5,
"verified": true,
"stored": true
}

Every timer key carries the unit it is counted in as a suffix: _s for seconds, _m for minutes. On a CQ20 and a CQ50S every timer is always in seconds, so the keys are always _s and the shapes above never change. The CQ50S keys are ign_on_delay_s, ign_off_delay_s, pw_off_delay_s and ups_off_delay_s.

On a CQ40N or CQ40 series, four of the five timers follow the delay unit, so their key names change with it. The same machine reports ign_off_delay_m while the unit is minutes and ign_off_delay_s after pcu-cli ign unit seconds. Only ign_on_delay_s is fixed, because that timer is always in seconds.

ign --json on a CQ40N (or CQ40 series) with the unit on minutes:

{
"ign_on_delay_s": 7,
"ign_off_delay_m": 1,
"pw_off_delay_m": 15,
"ups_off_delay_m": 5,
"ups_pw_off_delay_m": 2
}

There is no mode key: only the CQ20 has an ignition mode setting, and fields that do not apply are omitted rather than set to null.

ign get and ign set gain a unit property on a timer counted in minutes. It is omitted entirely when the timer is in seconds, so it never appears on a CQ20:

{
"timer": "pw-off-delay",
"value": 15,
"unit": "m"
}

An ign set on a CQ40N or CQ40 series timer counted in minutes reports stored as well:

{
"timer": "ign-off-delay",
"requested": 2,
"actual": 2,
"verified": true,
"stored": true,
"unit": "m"
}

Writing a timer on a CQ40N or CQ40 series can switch the MCU’s settings source from the BIOS to its own settings. When that happens the ign set JSON carries an extra notice string, and it is absent otherwise:

{
"timer": "ign-off-delay",
"requested": 2,
"actual": 2,
"verified": true,
"stored": true,
"unit": "m",
"notice": "The settings source was switched from BIOS to the MCU's own settings."
}

ign unit --json reports the current setting:

{
"unit": "minutes"
}

Changing it reports requested, actual and verified like ign set, but has no stored field, and the key is setting rather than timer, because the delay unit applies to the whole device rather than to one timer:

{
"setting": "delay-unit",
"requested": "seconds",
"actual": "seconds",
"verified": true
}

A write still prompts for confirmation unless you pass --yes.

dio --json on a CQ40 series reports each channel as a boolean (true = High for a channel, On for the ignition line):

{
"platform": "In-CarPC CQ40 series",
"inputs": {
"di1": true,
"di2": false
},
"outputs": {
"do1": false,
"do2": false
},
"ignition": true
}

A dio set write reports the same three fields as booleans, and has no stored field:

{
"channel": "do1",
"requested": true,
"actual": true,
"verified": true
}

version --json is the full inventory record: build stamp, driver and module versions, and the supported-platform catalogue. Use it for fleet inventory without touching the hardware bus.

{
"app": "pcu-cli",
"version": "1.2.1",
"git_commit": "ef9796e2daa7",
"build_date": "2026-10-23 09:32:27 UTC",
"build_config": "Release",
"os": "Windows",
"pawnio_version": "2.2.0",
"pawnio_date": "2026-03-15",
"smbus_module_date": "2025-05-05",
"lpcio_version": "0.2.7",
"lpcio_date": "2026-06-03",
"platforms": [
{
"model": "CQ20",
"description": "In-CarPC CQ20",
"cpu": "Intel Atom x6425E",
"cpu_codename": "Elkhart Lake",
"bus": "PCH SMBus",
"features": "Ignition timers",
"tested_os": [
"Windows 11 25H2 (x64)",
"Ubuntu 24.04 LTS (x64)",
"Windows 11 26H2 (x64)",
"Ubuntu 26.04.1 LTS (x64)"
]
},
{
"model": "CQ40",
"description": "In-CarPC CQ40 series",
"cpu": "Intel (CQ41/CQ43/CQ47)",
"cpu_codename": "Haswell",
"bus": "SuperIO GPIO ports + PCH SMBus",
"features": "Ignition timers, Digital I/O",
"tested_os": [
"Windows 10 22H2 (x64)",
"Ubuntu 24.04 LTS (x64)",
"Ubuntu 26.04 LTS (x64)"
]
},
{
"model": "CQ40N",
"description": "In-CarPC CQ40N series",
"cpu": "Intel (CQ41N/CQ43N/CQ47N)",
"cpu_codename": "Skylake",
"bus": "PCH SMBus",
"features": "Ignition timers",
"tested_os": [
"Ubuntu 24.04 LTS (x64)",
"Ubuntu 24.04.2 LTS (x64)",
"Ubuntu 26.04 LTS (x64)"
]
},
{
"model": "CQ50S",
"description": "In-CarPC CQ50S series",
"cpu": "Intel Core (CQ53S/CQ55S/CQ57S)",
"cpu_codename": "Tiger Lake",
"bus": "PCH SMBus",
"features": "Ignition timers",
"tested_os": [
"Windows 11 26H2 (x64)",
"Ubuntu 26.04.1 LTS (x64)"
]
}
],
"validated_configs": [
"Windows 11 25H2 (x64) - CQ20",
"Ubuntu 24.04 LTS (x64) - CQ20",
"Windows 11 26H2 (x64) - CQ20",
"Ubuntu 26.04.1 LTS (x64) - CQ20",
"Windows 10 22H2 (x64) - CQ40",
"Ubuntu 24.04 LTS (x64) - CQ40",
"Ubuntu 26.04 LTS (x64) - CQ40",
"Ubuntu 24.04 LTS (x64) - CQ40N",
"Ubuntu 24.04.2 LTS (x64) - CQ40N",
"Ubuntu 26.04 LTS (x64) - CQ40N",
"Windows 11 26H2 (x64) - CQ50S",
"Ubuntu 26.04.1 LTS (x64) - CQ50S"
]
}
  • Fields that do not apply are omitted, not set to null. On a CQ20, CQ40N or CQ50S, status --json has no inputs or outputs; on a CQ40N, CQ40 series or CQ50S there is no mode. On Linux, version --json omits the pawnio_*, smbus_module_date, and lpcio_* fields.
  • A platform that has not been validated on hardware yet carries no tested_os list and contributes nothing to validated_configs. Treat an absent tested_os as “not validated”, not as a parsing error. Every platform in this release has at least one entry, but a newly added model may not. The CQ40 series entry covers the ignition timers and digital I/O together, so one operating system can appear for it without both halves being validated.
  • tested_os lists only the operating systems. Each one appears once, even when it was validated on more than one BIOS. The matching BIOS and date are not in the JSON; see Supported Platforms for those.
  • features reports only the capabilities pcu exposes as features. The selectable delay unit of the CQ40N and CQ40 series is not one of them, so a CQ40N features string is Ignition timers even though ign unit works there.
  • ignition_line appears in status --json on a CQ40 series and a CQ50S, which have an ignition input. On a CQ40 series it follows outputs; on a CQ50S it follows timers_stored. It is omitted on a CQ20 and a CQ40N.
  • The CQ50S UPS Mode and UPS Voltage lines of the status text have no status --json fields.
  • Boolean channel values are true for High (inputs and outputs) and true for On (the ignition line).
  • On an ign set write, the exit code is 0 only when verified and stored are both true. It is 1 when the readback differs or a CQ20 or CQ50S store was not confirmed. A dio set or ign unit write has no stored field; its exit code mirrors verified. A script can check the exit code or the fields.
  • git_commit, build_date, and build_config in version --json are stamped at build time and will differ from the example above.
  • timers_stored appears in status --json only when the ignition timers are reachable (CQ20, CQ40 series, CQ40N and CQ50S), straight after the ignition block. It is a fixed fact about the platform, not a live check. It is omitted when the ignition block is.
  • A CQ40 series can connect with only one of its two halves, the SMBus ignition timers or the port I/O digital I/O. When one half is missing, status --json omits that half’s block and adds ignition_unavailable or dio_unavailable with a sentence saying why. Both keys are absent when everything is reachable. On such a connection pcu-cli ign or pcu-cli dio prints the same sentence on stderr and exits 1, because the hardware has the feature and the connection could not reach it. On a platform that never has the feature they exit 2.

--quiet prints just the value, with no labels or headers, one per line. It is the simplest form to parse and it never prompts. Reads:

Terminal window
$ pcu-cli ign get sw-off-delay --quiet
3
Terminal window
$ pcu-cli dio get di1 --quiet
0

Writes print the value read back, and still set the exit code. The number is printed even when the exit code is 1, so always check the exit code:

Terminal window
$ pcu-cli dio set do1 1 --quiet
1

On ign set the exit code is also 1 when a CQ20 or CQ50S does not confirm the store. --quiet prints nothing about it, so the exit code is the only signal. The one exception is the settings-source notice on a CQ40 or CQ40N series, which --quiet writes to stderr, so stdout stays the bare value.

Assert a digital output at boot. On Linux, run this from a systemd unit or an @reboot cron job:

Terminal window
pcu-cli dio set do1 1 --yes

On Windows, run the same command from a Task Scheduler task set to trigger “At startup”:

Terminal window
pcu-cli.exe dio set do1 1 --yes

Collect a fleet inventory without touching the hardware bus:

Terminal window
pcu-cli version --json > inventory.json

Change the shutdown delay across a fleet and fail loudly if the write did not verify or was not stored:

Terminal window
pcu-cli ign set sw-off-delay 120 --yes --quiet
if ($LASTEXITCODE -ne 0) { Write-Error "timer not verified or not stored" }

Extract a single value with jq:

Terminal window
pcu-cli ign get sw-off-delay --json | jq '.value'

pcu-cli handles Ctrl+C gracefully: an in-flight bus transfer is allowed to finish and the transport is cleaned up before the tool exits, so a cancel never leaves a transfer half-done.

pcu accesses the hardware bus directly. To avoid clashing with other low-level tools, every transfer is serialized on the standard system-wide bus mutexes also used by tools like HWiNFO (Access_SMBUS.HTP.Method for SMBus, Access_ISABUS.HTP.Method for SuperIO port I/O). Each access waits up to 5 seconds for the bus, then fails cleanly.