Custom Script Check Reference
Field-level reference for the Custom Script check — wrapper contract, helpers, input/output schema, status codes, and execution limits.
Written By Erdinc Akay
Last updated 25 days ago
octoja supports two distinct ways to ship a script as a check, and they are not the same plugin under the hood. This reference partitions them clearly so you can configure the right one without surprises.
- Built-in Custom Script check — a stock check plugin you assign to a device through a configuration package. You paste a single PowerShell or bash script into the check definition; the agent runs it as-is and converts the exit code into a status.
- User-defined custom checks — checks you author yourself on the Custom Checks page of the dashboard. Each script is wrapped at distribution time by octoja so it can declare typed inputs, emit typed outputs, and use the bundled SNMP worker.
The two paths share neither the status-mapping mechanism nor the output contract. Read the section that matches the check you are configuring.
Built-in Custom Script check
Plugin identifier octo/custom-script. The agent runs the script in-process via powershell.exe on Windows or /bin/bash -s on Linux and macOS. No wrapper, no helpers, no sentinel markers — the check works entirely off the script's exit code and a small stdout/stderr capture.
Status codes (exit-code mapping)
The exit code drives the result. Each Custom Script check carries a SuccessExitCode, a WarningExitCodes list, and a CriticalExitCodes list:
You can override any list per check — for example, accept both 0 and 3 as Success when wrapping a legacy tool. The critical list is evaluated before the warning list, so an exit code that appears in both maps to Critical. There is no script-side helper for this plugin; the result is always whatever the process returns.
What you get back
The check ships these fields to octoja on every run:
Execution limits
What breaks the check
User-defined custom checks
You author these checks on the dashboard's Custom Checks page — the editor covers scripts per platform, typed inputs, typed outputs, and the execution interval. (Community check repositories, added by name and URL, deliver ready-made checks from an external source; they are not how you author your own.) Each check is wrapped by octoja before it reaches the agent. The wrapper exposes typed inputs to your script, gives you helpers for emitting typed outputs, and delimits the result payload with sentinel markers so anything else you print to stdout cannot corrupt it.
If you provide only a Linux script, the agent runs it on macOS too via osx-x64 / osx-arm64 fallback.
The wrapper contract
The wrapper does three things around your script: it decodes the configured inputs and exposes them ($checkInput / INPUT_JSON), pre-creates the output container with checkResult = 0 ($output / _OCTO_OUTPUT), and after your script runs it serializes the output to base64 and prints it between the result markers. Your job is the middle: read inputs, do work, set output fields and the status. The agent extracts only the bytes between <<<OCTO_RESULT_BEGIN>>> and <<<OCTO_RESULT_END>>>, so Write-Output, Write-Host, echo, or ConvertTo-Json from your script do not break the wrapper.
Status — the checkResult sentinel
Wrapped checks do not use exit-code mapping. Status is the checkResult field on the serialized output payload, which the agent decodes into a CheckResultStatus enum. Set it through the language-appropriate helper:
The bash and macOS wrappers ship set_result 0|1|2 as a convenience shortcut for assigning checkResult. Strings are case-insensitive when decoded.
PowerShell — $checkInput and $output
Anything you put on $output is serialised and shipped to octoja. Map your output keys to the Output fields you declared on the check definition; otherwise the dashboard renderer cannot bind them to UI blocks.
The wrapper also injects two SNMP helpers that shell out to the agent's bundled SNMP worker. Both take named parameters:
Note the parameter name: -TargetHost, not -Host. $Host is a PowerShell automatic variable, so the wrapper avoids it. Both helpers are only available when the agent exposes its SNMP worker via the OCTOJA_WORKER_BIN environment variable; if the variable is unset the helpers throw and your script should fall back gracefully.
Bash (Linux) helpers
The SNMP helpers are flag-based (--host, --community, …), not positional. The output array is _OCTO_OUTPUT (associative). Use the helpers; touching the array directly is not part of the contract.
Bash (macOS) helpers
Same interface as Linux — get_input, set_output, set_result, and the same flag-based snmp_get / snmp_walk when OCTOJA_WORKER_BIN is set — but the implementation uses Python 3 instead of jq. A clean result envelope is still produced even if your script exits or crashes mid-run. If you do not provide a macOS-specific script, the Linux script is reused.
Input schema
Inputs are declared on the check (kind, label, default, required) and reach the script as a JSON object. Supported field kinds match the platform's InputFieldDefinition model — string, number, boolean, list, and so on. Read them via $checkInput.Key (PowerShell) or get_input "key" (bash / macOS).
Output schema
Outputs are declared on the check as a list of OutputFieldDefinition. Each entry has:
checkResult is implicit; declare additional fields you actually use in the dashboard.
Execution limits
What breaks the check
Diagnostic output during development goes to stderr — Write-Error / >&2 echo — and is captured by the agent without breaking the wrapper contract.
Encoding
Both check variants transfer and execute scripts as UTF-8 end to end. You do not need to convert anything or add a byte-order mark yourself — paste the script into the dashboard and octoja handles the encoding.
- What octoja guarantees: the script is transferred character-for-character as UTF-8. On Windows it is executed from a script file that carries a UTF-8 byte-order mark, so both Windows PowerShell 5.1 and PowerShell 7 read it as UTF-8 — umlauts,
°, and other non-ASCII characters arrive in the script exactly as you wrote them and are never reinterpreted in a legacy code page such as Windows-1252. On Linux and macOS the script is delivered as UTF-8 without a BOM, with Windows line endings normalised so the shebang stays valid. - Output: for the built-in Custom Script check the agent forces PowerShell's output encoding to UTF-8 before your script runs and captures stdout/stderr as UTF-8, so non-ASCII output such as
°Cor umlauts reaches the dashboard intact. For user-defined custom checks the result payload is serialised as UTF-8 JSON and travels Base64-encoded between the result markers, which makes it immune to output-encoding issues by construction. - What you still have to watch: octoja never substitutes characters — what you paste is exactly what PowerShell or bash parses. Editors, chat tools, and word processors like to replace straight quotes with typographic ones (
“”) and-or--with en/em dashes (–—). These look right but are different characters; depending on where they sit in the script they cause syntax errors or silently different behaviour. Replace typographic quotes and dashes with their plain ASCII counterparts before saving the check.
Scripts you bring in through the Check Importer can carry the same typographic characters from wherever they were copied — the same advice applies to imported scripts.
Related articles
- Configure a Custom Script Check — step-by-step author guide.