Skip to content

Acting on resources

Beyond reading resources, the CLI can change them. Every state change on the JMA is a hypermedia action: the server lists, on each resource, the actions it currently allows, together with the schema of their parameters and a Destructive marker on the irreversible ones. The CLI reads those actions at run time, so nothing is hardcoded — a new server action is usable the day it ships.

Two layers sit on top of that:

  • Generic verbsactions lists what a resource offers and action executes any of them by name.
  • Typed verbsjob start, wd upload, template run, folder create, and friends. Each one executes exactly one action with proper flags. They are sugar over the generic path and add no capability the server does not offer.

All of these connect the way the read commands do (flags, environment, then pinexq.toml for the endpoint) and run from any directory.

show already tells you what you can do: its table ends with an Actions: footer naming the actions the resource offers right now.

actions <ref> gives the details — the name to pass to action, the HTTP method, markers such as Destructive, and each parameter with its type and whether it is required:

Terminal window
pinexq job actions 3f2b…
pinexq wd actions --root # the creation actions of the WorkData root
pinexq template actions 8a1c… -o json

-o json adds the served name, the URL, the current parameter values, and the full JSON schema. -q prints only the names, one per line.

pinexq <noun> action <ref> <name> [--set KEY=VALUE]... [--json BODY|@FILE|-] [--dry-run] [--yes]
pinexq <noun> action --root <name> ...
  • Name — any spelling works: the served name (StartProcessing), kebab-case (start-processing), or snake_case; matching is case-insensitive.
  • Parameters--set KEY=VALUE sets one property (repeat for several; a repeated key builds an array). --json passes a whole object inline, from a file (@params.json), or from stdin (-). The body starts from the server’s current values, then --json is applied, then --set, so you only pass what changes.
  • Typing and validation — values are typed by the action’s JSON schema (an integer property gets 10, not "10") and the body is validated before anything is sent. A type mismatch or a missing required property is a usage error (exit 2) with no request made.
  • Result — the affected resource is re-fetched and rendered like show (-o json, -o csv, -q for its id). A creation action prints the created resource; folder action <ref> clear prints the report the server returns.
Terminal window
# rename a job
pinexq job action 3f2b… rename --set NewName="nightly-import"
# set a processing step's defaults from a file
pinexq ps action resize@1.2.0 configure-default-parameters --json @defaults.json
# a destructive action, unattended
pinexq job action 3f2b… delete --yes

--dry-run prints the method, URL, markers, and body and sends nothing. Use it to see exactly what an action will do:

Terminal window
$ pinexq job action 3f2b… delete --dry-run
Dry run nothing was sent.
Action: delete (Delete)
Method: DELETE
URL: https://…/JobManagement/Jobs/3f2b…
Markers: Destructive

The server marks irreversible actions — Delete, SetJobToErrorState, Folder Clear, and others — as Destructive. For those, every verb behaves the same:

  • in a terminal, the CLI asks for confirmation first;
  • --yes / -y skips the question;
  • without a terminal (a pipe, CI) and without --yes, the CLI refuses with exit code 1 and asks you to pass --yes;
  • declining exits with code 1 and sends nothing.

There is no hardcoded list: the policy follows the server’s marker, so a non-destructive action never prompts and a newly marked one prompts at once.

Terminal window
pinexq job delete 3f2b… --yes
pinexq folder clear /scratch -y

The typed verbs cover the everyday actions per noun. Run pinexq <noun> --help for the full list and pinexq <noun> <verb> --help for its flags. All of them accept --dry-run, --yes, and the usual output flags.

Verbs that act on “one or more” resources take several references, or - to read one per line from stdin. The whole batch is planned first, one confirmation covers it, failures are reported and the rest continue, and the exit code is 1 if any reference failed. The result is one table, like list.

Terminal window
pinexq job list --state failed -q | pinexq job delete - --yes
pinexq wd tag a1b2… c3d4… --add reviewed --remove draft

Every noun has delete, hide, unhide, rename, and move; all but Folders also have tag:

Verb Notes
delete <ref>... Destructive; asks once for the batch.
hide / unhide <ref>... Hide from, or return to, the default listings.
rename <ref> <name> For ProcessingSteps this sets the display title; name and version are fixed.
tag <ref>... --add/--remove/--clear Read-modify-write: --clear, then --remove, then --add, written once.
move <ref>... --to <folder> or --root --to takes a /path, UUID, or URL.
Verb What it does
create --name --processing-step Creates a fully configured Job in one request; --param KEY=VALUE, --input INDEX=REF[,REF], --tag, --folder, --start.
create --name Creates an empty Job to configure step by step — see Composing a Job step by step.
create --name --parent <ref> Creates a sub-job of another Job; --inherit-folder files it beside its parent.
start <ref>... Starts configured Jobs. --wait [--timeout S] blocks until they finish — see Waiting for a job to finish.
select-processing <ref> --processing-step Picks the ProcessingStep the Job runs.
configure <ref> --param KEY=VALUE Sets the parameters of the selected ProcessingStep.
set-input <ref> <slot> <wd>... Fills one input DataSlot from WorkData, or from a folder with --folder PATH.
clear-input <ref> <slot> Empties one input DataSlot.
set-error <ref> -m <message> Puts a Job into the Error state.
Terminal window
pinexq job create --name demo --processing-step resize@1.2.0 \
--param width=800 --input 0=a1b2… --tag demo --start

--param values are typed against the ProcessingStep’s own parameter schema, so --param width=800 sends an integer when the function declares one.

--param, --input, --tag, and --start describe a configured Job, so they need --processing-step. Passing them to the empty or sub-job form is a usage error, made before anything is sent. --input here takes the slot’s index only; the set-input verb also accepts its name.

Verb What it does
upload <file> Multipart upload through the WorkData root; --name, --media-type, then --tag and --folder as follow-ups.
download <ref> Writes the content to a file named after the WorkData, to -o <path>, or to stdout with -o -; --force overwrites.
comment <ref> <text> Replaces the comment.
delete <ref>... --force When deletion is not allowed yet, runs AllowDeletion first, then Delete; one confirmation up front.
Terminal window
pinexq wd upload ./data.csv --tag raw --folder /imports -q
pinexq wd download a1b2… -o - | head

If an upload succeeds but a follow-up (tag, move) fails, the CLI reports the created WorkData’s id and the failed step, still shows the WorkData, and exits with code 1.

Verb What it does
deprecate <ref>... [--reason] Deprecates; restore undoes it.
set-defaults <ref> --param KEY=VALUE Sets default parameters, typed against the function’s schema.
clear-defaults <ref> Clears them (Destructive).

References accept name and name@version as show does.

Verb What it does
create --name --description --processing-step Creates a Template; --param and --tag are applied as follow-ups.
run <ref> Executes it now and shows the created Job (-q for its id). --wait [--timeout S] blocks until that Job finishes — see Waiting for a job to finish.
edit <ref> --name/--description Changes either or both; omitted fields keep their value.
tag <ref>... --scope template|job|output Which tag list: the Template’s own, the Jobs it creates, or their output WorkData.
set-params <ref> --param / clear-params Parameters, typed against the function’s schema.
set-input <ref> <slot> <wd>... / clear-input <ref> <slot> Fills or clears an input DataSlot, addressed by index or name.
Terminal window
pinexq template create --name nightly --description "Nightly resize" \
--processing-step resize --param width=800 --tag nightly
pinexq template set-input 8a1c… image a1b2… c3d4…
pinexq template run 8a1c… -q
Verb What it does
create --title --description --cron Creates a cron Trigger; --tz, --on-conflict StackUp|Skip, --enabled/--disabled, --starts-at, --expires-at, --delete-orphaned/--keep-orphaned, and --template (repeatable) to link Templates.
enable / disable <ref>... Toggles the Trigger.
edit <ref> --title/--description Omitted fields keep their value.
set-templates <ref> <template>... Replaces the linked set.
set-cron <ref> <expr> [--tz] [--on-conflict] Changes the schedule.
set-window <ref> --starts-at/--expires-at Only the given fields change.
Terminal window
pinexq trigger create --title nightly --description "Every night" \
--cron "0 2 * * *" --tz Europe/Berlin --template 8a1c…
Verb What it does
create <name> [--parent] One path segment under an existing parent, or at the root.
move <ref>... --to/--root Re-parents Folders.
clear <ref> Deletes everything inside and prints the server’s report (Destructive).

References accept a /path as show does.

job create --name … --processing-step … configures a Job in a single request, which is what you want in a script. When you would rather build one up — try a ProcessingStep, look at the DataSlots it declares, fill them, adjust parameters, then start it — create the Job empty and configure it verb by verb:

Terminal window
# 1. an empty Job
pinexq job create --name experiment -q
# 3f2b…
# 2. pick what it runs; the DataSlots appear with it
pinexq job select-processing 3f2b… --processing-step resize@1.2.0
# 3. parameters, typed against that ProcessingStep's schema
pinexq job configure 3f2b… --param width=800 --param keep_ratio=true
# 4. fill the inputs, by slot index or slot name
pinexq job set-input 3f2b… image a1b2…
pinexq job set-input 3f2b… masks c3d4… e5f6…
# 5. run it
pinexq job start 3f2b… --wait

Each verb shows the Job afterwards, so select-processing is how you discover which DataSlots and parameters the step wants.

set-input and clear-input take a slot: either its 0-based index or its name, matched case-insensitively. job show lists both, so the index column tells you what to pass:

Terminal window
pinexq job show 3f2b… # input_dataslots lists index, name, media type
pinexq job set-input 3f2b… 0 a1b2…
pinexq job set-input 3f2b… image a1b2… # the same slot

Names survive a change in slot order, so prefer them in scripts. An unknown slot names the slots the Job does have, and nothing is sent.

Form What it sends
set-input <ref> <slot> <wd> One WorkData.
set-input <ref> <slot> <wd> <wd>... A collection, in the order given.
set-input <ref> <slot> --folder /path Every WorkData in a folder, and its descendants.
set-input <ref> <slot> --folder /path --no-recursive Only the WorkData directly in that folder.
clear-input <ref> <slot> Empties the slot.

WorkData references are UUIDs or URLs. A folder source is a path, and it replaces item-by-item selection rather than adding to it — the server allows one or the other per slot. set-input with both a folder and WorkData references is a usage error.

Terminal window
pinexq wd upload ./frame.png -q | xargs -I{} pinexq job set-input 3f2b… image {}
pinexq job set-input 3f2b… masks --folder /experiments/masks

A Job that fans out can own sub-jobs, and the CLI creates one directly:

Terminal window
pinexq job create --name shard-1 --parent 3f2b… --inherit-folder -q

--inherit-folder files the sub-job in its parent’s folder; without it the sub-job lands in the context root. --folder puts it somewhere else entirely. Sub-jobs are configured with the same verbs as any other Job, and job list hides them until you pass --sub-jobs.

job start and template run normally return as soon as the server accepts the request — the Job then runs in the background. Pass --wait to block until the Job reaches a terminal state instead:

Terminal window
# start a job and wait for it; exit code reflects the outcome
pinexq job start 3f2b… --wait
# run a template, wait for the job it creates, then act on the result
pinexq template run 8a1c… --wait -q && echo "done"
  • Exit code follows the Job. The command exits 0 only when the Job reaches Completed; Error, Canceled, and DataMissing exit non-zero. So --wait turns a Job into a shell-scriptable step that fails your pipeline when the Job fails.
  • What you see. On a terminal, a spinner on stderr shows the Job’s current state while polling; when piped (or with -q/-o json) nothing is printed until the end. On completion the final Job row is rendered like show.
  • --timeout S gives up after S seconds with the Job still running and exits non-zero. The Job is not cancelled — it keeps running on the server. Without --timeout the command waits indefinitely.
  • Ctrl-C leaves the Job running on the server and exits with code 130.
  • template run waits for the one Job the template creates.
Code Meaning
0 Success.
1 Runtime failure: resource not found, action not offered, authentication, version conflict, refused or declined confirmation, any reference in a batch failed, or a --wait job did not complete (failed or timed out).
2 Usage error: a parameter that fails the schema, malformed --set/--json, missing arguments.
  • Uploading a file straight into a Job’s input DataSlot in one request. Use wd upload and then job set-input.
  • AllowOutputDataDeletion and DisallowOutputDataDeletion on a Job have no typed verb; reach them with job action <ref> allow-output-data-deletion.
  • Output DataSlots are read-only — they advertise no actions.