Custodian
ReferenceCommand line

custodian exec

Resolve a document of tokens and pipe the values into a program over standard input, without ever printing them.

custodian exec resolves a document of tokens the same way custodian resolve does, then pipes the resolved document into a program over standard input — so the real values exist only in that program's memory, and are never printed, written to disk, passed as an argument, or added to the environment. This is the command Custodian is built around: the agent works with tokens, and the values are substituted at the last possible moment on a machine you control. Be signed in first.

Put -- before the program, so its own flags are not read by Custodian:

custodian exec --input filled.json -- fill-liberty-form --template PY01.pdf

The resolved document is written to that program's standard input; the program is run directly, not through a shell, and inherits Custodian's environment unchanged.

Options:

  • --input <file> — the document to resolve; - or omitted reads standard input.
  • --batch-size <n> — the most distinct tokens per request (default 50).
  • --child-timeout <seconds> — terminate the program if it runs longer than this. This bounds the program only; the global --timeout bounds Custodian's own requests, never the program.
  • --capture-output — seal the program's standard output into a record's file field instead of letting it reach the terminal. Needs the next three options. See capturing a program's output.
  • --collection <name> — the collection of the record to store the capture in (only with --capture-output).
  • --record <uuid> — the record to store the capture in, as a hyphenated UUID (only with --capture-output).
  • --field <name> — the record's file field to store the capture in (only with --capture-output).

The last four options only matter for a capture. Without --capture-output, the program's output reaches your terminal as usual.

Resolve first, then run

The program is started only after the whole document has resolved. So a token that fails to resolve means the program is never started, and no half-finished work is produced. The document and the master key are cleared from memory the instant the pipe is written and closed, before the program even exits.

Exit codes and the summary

custodian exec exits with the program's own exit code. A program that cannot be found or run is Custodian's failure and exits 127; a program stopped by --child-timeout exits 124. After the program exits on its own, Custodian writes a one-line summary to standard error — counts only, never a value:

custodian exec: resolved 3 tokens and piped the document to "fill-liberty-form" over standard input; the master key was unwrapped on this device, and no plaintext was written to disk, passed as an argument, or added to the environment.

Capturing a program's output into a file field

Some programs produce a document — a filled form, a report — on standard output. With --capture-output, Custodian takes that output instead of letting it reach your terminal, seals it on this machine, and stores it in a record's file field, the same way custodian file put stores a file. The program still receives the resolved document on standard input as usual.

Before you start, the record must exist, its field must be declared type: file in the schema, your credential needs a --write grant on the collection and a --plaintext grant on the file field (the capture reads the record first, and a write grant does not permit reading), and this machine must be an enrolled device.

custodian exec --input filled.json --capture-output --collection policyholders --record 018f4e2a-7c1b-7a3e-b9d4-2f6c8a1e5b70 --field signed_form -- fill-liberty-form --template PY01.pdf

--capture-output needs all three of --collection, --record and --field. If one is missing, the command refuses and names it:

error: --capture-output needs --field to say where to store the captured output. It stores the child's standard output as a record file field's value.

Each of the three is refused without --capture-output:

error: --collection, --record, --field are only meaningful with --capture-output, which seals the child's standard output into that field. Add --capture-output, or drop the option.

Custodian checks that the field is a file field and that the record exists before it starts the program. It refuses them in the same words as custodian file put.

What is stored, and when

The output is stored only when the program finishes successfully and wrote something. On success, Custodian writes a summary to standard error — the size, never the content — followed by the token:

Captured 412 KB from "fill-liberty-form" into field "signed_form" on record 018f4e2a-7c1b-7a3e-b9d4-2f6c8a1e5b70.
  tok_AOWVT36VNVCIESCL

The retrieval line for the stored file is custodian file get followed by that token. See retrieving a file.

If the field already held a file, the capture replaces it and a third line says so:

  The previous file in field "signed_form" has been replaced; its retrieval line has stopped working.

Nothing is stored in these cases, and each has its own message on standard error:

  • The program exits with a non-zero code. Custodian exits with the same code:

    custodian exec: "fill-liberty-form" exited 2; the capture was abandoned and nothing was stored.
  • The program is interrupted (for example, you press Ctrl-C). Custodian exits non-zero even if the program itself exited with 0:

    custodian exec: "fill-liberty-form" was interrupted; the capture was abandoned and nothing was stored.
  • The program runs past --child-timeout. It is stopped, and the message is the ordinary timeout message:

    error: the child did not finish within the --child-timeout of 60s and was terminated.
  • The program writes nothing to standard output:

    custodian exec: "fill-liberty-form" produced no output; nothing was stored.

If the server refuses the store, its refusal is shown as it worded it. When the capture is too large, the message also gives the captured size on this machine.

A capture never uses an unlocked session

A capture always unwraps the master key on this machine, even when an unlocked session for the vault is live. When you name that vault with --vault and a session is live, Custodian tells you:

note: --capture-output resolves and spawns on this device; the live session for this vault is not used, so this device unwraps the master key for the capture.

On this page