Extension JSONC reference¶
Every package contains hubuum-extension.jsonc. The CLI accepts comments and
trailing commas, while retaining strict JSON strings, keys, numbers, and comma
rules. Use comments to document why a site-specific value or workflow step
exists; the compiler ignores them, so they have no runtime semantics. Unknown
fields are errors. Add the repository's
hubuum-extension.schema.json as
$schema for editor validation and completion.
The schema catches structural mistakes while editing. extension validate
remains authoritative because cross-references, command contracts, effects,
call graphs, configuration, and work limits require the compiler.
Top-level fields¶
| Field | Required | Meaning |
|---|---|---|
$schema |
No | Editor-only URI or relative path to the JSON Schema |
schema_version |
Yes | Manifest language version; currently 1 |
kind |
Yes | portable or executable |
name |
Yes | Pack namespace in lowercase kebab-case |
version |
Yes | Pack semantic version |
requires_cli |
Yes | SemVer requirement checked before registration |
config |
No | Typed, pack-local configuration declarations |
workflows |
Portable | Reusable same-pack workflow declarations |
protocol |
Executable | Exactly hubuum-cli.extension/v1 |
executable |
Executable | Relative program path confined to the package |
commands |
Yes | User-visible command declarations |
Portable packs cannot declare protocol or executable. Executable packs
cannot declare workflows. Pack names reserve all built-in extension
management names.
Names and paths¶
- Pack names, command path segments, and long options use lowercase ASCII
kebab-case:
site-inventory. - Command declaration keys, workflow names, configuration keys, workflow
inputs, and step IDs use lowercase ASCII snake_case:
list_hosts. - Option declaration and binding IDs allow lowercase ASCII letters, numbers, hyphens, and underscores. A portable option matches a snake-case workflow input key exactly.
- Command paths are non-empty arrays such as
["host", "list"]. - One command path cannot prefix another command path in the same pack.
- Short and long aliases share a namespace. Host rendering aliases are reserved.
Value declarations¶
Configuration and workflow inputs use the same fields:
| Field | Default | Meaning |
|---|---|---|
type |
Required | string, integer, number, boolean, or json |
required |
false |
Caller or local configuration must supply a value |
repeatable |
false |
The resolved value is an array of the declared type |
default |
None | Typed value used when omitted |
help |
Empty | User-facing explanation |
required and default are mutually exclusive. A repeatable default is an
array. Unknown local configuration keys and wrong types reject the pack.
Workflows¶
A workflow object has:
| Field | Required | Meaning |
|---|---|---|
inputs |
No | Typed public function inputs |
output |
Yes | Static semantic output declaration |
steps |
Yes | Ordered tagged step array |
capabilities |
No | Include mutate when the expanded graph may write |
result |
Yes | Bounded JQ expression producing the final value |
Workflows are top-level so multiple commands and workflows can reuse them. Only same-pack calls are legal. The compiler expands the complete call graph, detects cycles, propagates effects and replay safety, and checks all static limits before registering any command.
Output shapes¶
shape |
Required JQ result | Typical use |
|---|---|---|
empty |
null or [] |
No semantic value |
lines |
Array of strings | Unstructured display lines |
rows |
Array of JSON objects | Lists and table output |
detail |
JSON object | One structured record or report |
message |
JSON scalar | Status text, number, Boolean, or null |
values |
JSON array | Non-row arrays |
type defaults to json. It validates individual elements for lines and
values, and the complete result for the other shapes; rows and detail
therefore normally use json. columns is an optional unique list of non-empty
display columns for rows or detail. The result is checked before the
caller's pipeline, renderer, and redirect run.
Tagged steps¶
Every step requires a unique snake-case id. Array order is execution order.
| Kind | Required fields | Optional fields | Result |
|---|---|---|---|
run |
run command path |
with, when |
Built-in semantic value |
let |
expr |
None | JQ result |
assert |
condition, message |
None | true, or stops with message |
call |
call workflow |
with, when |
Nested workflow result |
for_each |
items, as, call, max_items |
with, when |
Result array |
when is available only on executable steps: run, call, and for_each.
It must return a Boolean. A false condition records a skipped null value.
for_each is sequential and requires max_items from 1 through 1,000. The
as name binds each item to an input on its target workflow.
Use extension contract <built-in path> to discover the accepted with keys,
types, required state, flags, fixed or repeatable cardinality, effects,
authentication, and replay safety for a run target.
Bindings¶
A with object maps target input IDs to one of these forms:
| Form | Example | Meaning |
|---|---|---|
| Scalar literal | "Hosts" |
String, number, Boolean, array, or null |
| Object literal | { "literal": { "site": "oslo" } } |
Explicit JSON object |
| Input | { "input": "class" } |
Current workflow input |
| Configuration | { "config": "hosts_class" } |
Declared pack configuration |
| Earlier step | { "step": "classes" } |
Normalized earlier step value |
| Selected step | { "step": "classes", "select": ".[0].name" } |
Bounded JQ projection |
Forward references are errors. A plain object is reserved for binding syntax,
so use the explicit literal wrapper for object data. Dynamic step values are
type-checked immediately before invocation.
Commands and options¶
A command requires path. Portable commands require workflow; executable
commands instead inherit the package executable and may declare fixed
arguments and interactive.
Both kinds accept about, long_about, examples, and an options object.
Each examples entry contains only the arguments after this command's path;
the help renderer prepends the complete installed path. Use an empty string to
show the bare command.
An option has kind, and then one of position, long, or short as its
interface. It may also declare required, repeatable, help, and static
values. Supported kinds are string, integer, number, boolean, flag,
and json.
Positional indexes start at one and must be contiguous. Only the last positional may repeat. A portable command's option declarations must exactly match its workflow inputs by declaration key, type, required state, and repeatability. A workflow without a command remains private.
JQ context and limits¶
Expressions see:
.input: resolved typed workflow inputs;.config: resolved typed pack configuration;.steps: normalized step values keyed by ID;.outputs: source and semantic-output metadata keyed by step ID.
The bounded expression profile rejects user definitions and variables,
recursive descent, multiplication, multiple array generators, combinations,
walk, recurse, repeat, range, while, until, foreach, and reduce.
The v1 host limits are mandatory:
| Resource | Limit |
|---|---|
| Expanded call depth | 16 |
| Static and runtime operations | 10,000 |
One for_each |
1,000 items, further reduced by max_items |
| Cumulative workflow output | 4 MiB |
| JQ expression source | 4 KiB |
| JQ expression input | 1 MiB |
| JQ expression results | 128 |
| JQ expression output | 1 MiB |
Mutating expanded graphs require "capabilities": ["mutate"] at every
calling boundary. Workflows do not supply transactions or rollback.
Executable packs¶
Executable packs exist for external I/O or behavior that built-in commands and bounded JQ cannot express. They may use any implementation but must treat that implementation and its dependencies as part of installation.
The CLI executes the declared program directly, without a shell, followed by
fixed command arguments and validated caller arguments. Only a declared
interactive command can inherit a terminal stdin. The child receives the
protocol, pack name, current CLI path, non-secret connection settings, and only
its namespaced configuration. Password and bearer token values are removed.
The child writes diagnostics to stderr and exactly one tagged JSON response to stdout. A success has this form:
{
"protocol": "hubuum-cli.extension/v1",
"status": "ok",
"output": {
"shape": "message",
"value": "done",
"columns": []
},
"warnings": []
}
An error uses nonzero exit status plus status: "error", with a stable
snake-case error.code, user-facing message, and optional JSON details.
A mismatched exit status, malformed JSON, unsupported protocol, or invalid
shape is a protocol error.