Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Invoking the CLI

Selecting JSON

--output human|json is a global option. It defaults to human, is case-sensitive, and may appear at any depth of the command path, with a space or =:

mostro-cli --output json order list
mostro-cli order --output=json list
mostro-cli order list --output json

All three are equivalent. Rules a wrapper must respect:

SituationResult
Exactly one --output jsonJSON mode
No --output, or one --output humanHuman mode
--output given twice, even with the same valueExit 2, empty stdout, one line on stderr
--output with no value or an unknown valueExit 2, empty stdout, one line on stderr
--output json appears inside another option’s value (--currency=--output=json)Not an output selection
--output after --Not an output selection; an earlier --output json still holds
--help / --versionConventional text and exit 0, even with --output json

So: put --output json exactly once, first, and never pass user-controlled text where an option is expected. Build argv as an array, never by string concatenation through a shell.

Confirmation: --yes

Commands that publish a request which changes something (order new, order take-sell, order take-buy, order add-invoice, bond add-invoice, order fiat-sent, order release, order cancel) ask for confirmation in human mode. In JSON mode there is no prompt and stdin is never read; instead --yes is mandatory:

mostro-cli --output json order cancel --order 00000000-0000-0000-0000-000000000001
# exit 2, invalid_arguments: nothing was done

mostro-cli --output json order cancel --order 00000000-0000-0000-0000-000000000001 --yes

--yes is the caller’s statement that the user consented. An agent should only add it after it has obtained that consent (see Guide for AI agents).

order sync writes only local rows and publishes nothing; it does not take --yes.

Streams

With JSON selected, a controlled outcome is:

  • stdout: exactly one UTF-8 JSON object followed by \n. No banner, progress, colour or table before or after it.
  • stderr: optional diagnostics in fixed English prose. With --verbose (-v, a root option) a command adds one line such as verbose: order.take-sell ok or verbose: order.release reply_timeout. Diagnostics never contain keys, invoices, relay URLs or argument values. Do not parse stderr.
  • stdin: never read.

Exit codes

ExitMeaningStdout
0status is okEnvelope
2error.code is invalid_arguments or output_not_supportedEnvelope (when JSON intent was unambiguous)
2Bad or duplicate --outputEmpty; stderr line
1Any other error, and every uncertainEnvelope
1Serialization or write failureAn internal_error envelope if possible, otherwise empty
otherCrash or killedNo guarantee

The exit code is a summary. The envelope is the detail: uncertain exits 1 like an error, but it does not mean “nothing happened”. Always read status.

If stdout is empty or not one JSON object, treat the run as unknown: for a read, retrying is fine; for a write, check before retrying (see Recovering from uncertain outcomes).

Argument errors are still JSON

Once --output json was selected unambiguously, an argument error is reported as an envelope, even if the command itself cannot be recognised:

mostro-cli --output json unknowncmd
{
  "schema_version": "1",
  "command": null,
  "status": "error",
  "data": null,
  "error": {
    "code": "invalid_arguments",
    "message": "The command arguments are invalid."
  },
  "warnings": [],
  "meta": {
    "publication": "not_attempted",
    "daemon_acceptance": "unknown",
    "persistence": "not_attempted",
    "snapshot": null
  }
}

File: examples/general/unknown_command.json · exit 2 · captured

command is null because the command could not be resolved. A recognised command keeps its name even when its arguments are wrong:

mostro-cli --output json order list --side invalid
{
  "schema_version": "1",
  "command": "order.list",
  "status": "error",
  "data": null,
  "error": {
    "code": "invalid_arguments",
    "message": "The command arguments are invalid."
  },
  "warnings": [],
  "meta": {
    "publication": "not_applicable",
    "daemon_acceptance": "not_applicable",
    "persistence": "not_applicable",
    "snapshot": null
  }
}

File: examples/order.list/invalid_side.json · exit 2 · fixture

The error never echoes the offending value; your wrapper knows what it passed.

Removed spellings

The JSON-capable commands replaced old spellings (listorders, neworder, takesell, getdm…). The old names are gone without aliases and fail as an unknown command (command: null, invalid_arguments). See Migration.

Timeouts you should allow for

PhaseBudget
Connect to relays10 s
Node-info probe (protocol version, PoW)3 s, best effort
Public read until every relay sent EOSE15 s
Wait for the node’s reply to a request15 s
Relay cleanup1 s (overrun is only a warning)

A wrapper timeout of 45 seconds per run is comfortably above the worst case. If you kill the process earlier, treat a write as uncertain.

Running several commands

The CLI makes no promise about two write commands running at the same time against one data directory (both may reserve trade indexes and update rows). Run write commands one at a time per data directory; queue them in your wrapper. order list and schema never touch the data directory; order info and message list only read it.