Advanced features¶
Fields and patterns beyond the basics — container declarations, groups, constraints, and the various separator knobs.
Container images¶
container-image declares how the tool should be executed under a
container runtime:
"container-image": {
"type": "docker",
"image": "brainlife/fsl:6.0.4-patched2",
"index": "docker.io"
}
| Field | Description |
|---|---|
type |
"docker", "singularity", or "rootfs". |
image |
Image name (for docker / singularity types). |
url |
URL of the rootfs image (rootfs type). |
index |
Optional registry override. Example: "docker.io". |
entrypoint |
True if the container defines an entrypoint. |
working-directory |
Location from which the task must be launched inside the container. |
container-hash |
Hash of the image for reproducibility. |
container-opts |
Extra container-level arguments. Example: ["--privileged"]. |
When bosh exec launch runs with -r docker it uses these fields to
construct the docker run invocation. With -r singularity it
constructs a singularity exec docker://<image> (or, for rootfs
type, points directly at the rootfs URL).
Why declare a container?¶
The toolkit also lints descriptors without a container-image. It's
not required by the v0.5 spec, but a descriptor without one cannot be
reproducibly launched in a container runtime — the consumer has to
supply the image themselves.
Groups¶
Groups define cross-input constraints on the top-level inputs array:
"groups": [
{
"id": "exclusive_options",
"name": "Processing options",
"description": "Choose only one processing option.",
"members": ["fast_mode", "accurate_mode", "balanced_mode"],
"mutually-exclusive": true
},
{
"id": "logging",
"name": "Logging flags",
"members": ["verbose", "debug", "trace"],
"one-is-required": false
}
]
| Field | Description |
|---|---|
id |
Unique identifier. |
name |
Human-readable name. |
description |
Free-form description. |
members |
IDs of inputs belonging to the group. |
mutually-exclusive |
At most one member may be active. |
one-is-required |
At least one member must be active. |
all-or-none |
Either all members are active or none. |
Group members must reference real input IDs; the toolkit's semantic validation rejects descriptors where they don't.
When to use groups vs. sub-commands
Use groups for simple toggle-style constraints across inputs of the same shape. Reach for sub-commands when each option carries its own parameter set.
Command-line flag separator¶
By default a flag and its value become two argv tokens. Set
command-line-flag-separator to "=" (or any non-whitespace string)
to glue them into one:
{
"id": "threshold",
"type": "Number",
"command-line-flag": "--threshold",
"command-line-flag-separator": "=",
"value-key": "[THRESHOLD]"
}
Resolved: --threshold=0.5 (one token) instead of --threshold 0.5
(two).
List separator¶
For list inputs, items are joined with a single space by default. Use
list-separator to glue them into one token:
{
"id": "coordinates",
"type": "Number",
"list": true,
"list-separator": ",",
"value-key": "[COORDS]"
}
Resolved with [1, 2, 3]: 1,2,3 (one argv token) instead of 1 2 3
(three argv tokens).
Value constraints¶
Numeric¶
{
"id": "threshold",
"type": "Number",
"integer": false,
"minimum": 0,
"maximum": 1,
"exclusive-minimum": false,
"exclusive-maximum": false
}
integer— restrict to integer values (defaults to false: floats).minimum/maximum— bounds (inclusive by default).exclusive-minimum/exclusive-maximum— make the bound strict. Each requires the corresponding non-exclusive bound to be set.
String¶
value-choices defines a closed set of permitted values. Available on
String and Number inputs.
Dependencies between inputs¶
| Field | Effect |
|---|---|
requires-inputs |
IDs of inputs (or groups) that must be active for this input to be available. |
disables-inputs |
IDs of inputs that are disabled when this input is active. |
value-requires |
Per-value-choice IDs of inputs that must be active when that choice is selected. |
value-disables |
Per-value-choice IDs of inputs that are disabled when that choice is selected. |
value-requires / value-disables are only meaningful when
value-choices is set; the toolkit's semantic validation enforces
that.
Environment variables¶
Variables to set in the execution environment:
"environment-variables": [
{ "name": "FSLOUTPUTTYPE", "value": "NIFTI_GZ" },
{ "name": "OMP_NUM_THREADS", "value": "4" }
]
bosh exec launch passes these to the subprocess (local runtime) or as
-e NAME=VALUE / --env NAME=VALUE flags (docker / singularity).
Suggested resources¶
Soft hints for downstream schedulers:
The toolkit reads these but does not enforce them.
Error codes¶
Document the tool's exit-code semantics:
"error-codes": [
{ "code": 1, "description": "I/O error." },
{ "code": 2, "description": "Invalid input." }
]
Tests¶
Embedded test cases with assertions:
"tests": [
{
"name": "basic",
"invocation": { "input": "tests/in.nii", "output": "out.nii" },
"assertions": {
"exit-code": 0,
"output-files": [{ "id": "output", "md5-reference": "abc123…" }]
}
}
]
A bosh test runner is on the roadmap.
Tags and custom fields¶
tags— open key/value pairs for categorisation. Example:{ "domain": "neuroimaging", "modality": "MRI" }.custom— escape hatch for tool-specific metadata that doesn't fit the spec.
Neither field has spec-defined semantics; both are passed through verbatim.