Updating objects
The update command applies a JMAP patch to one object (or a singleton). The patch shape mirrors JMAP’s Foo/set update argument: only the changed fields are sent.
Synopsis
Section titled “Synopsis”stalwart-cli update <object> [<id>] ( --field key=value... | --json '<json>' | --file <path> | --stdin )<object>: object type name (with or withoutx:prefix). The slash form is rejected here (it is acreatefeature).<id>: required for normal objects; optional for singletons (defaults tosingleton). Passing any non-singletonid for a singleton is rejected.- The four input forms are mutually exclusive.
Field paths and JSON pointers
Section titled “Field paths and JSON pointers”For --field keys, two forms are supported:
- Top-level property name:
--field name=foosets the entire property. - JSON pointer path:
--field 'aliases/2/name=foo'patches a sub-element. The first segment is matched against the schema (case-insensitive, rewritten to canonical case). Deeper segments (map keys, list indices, nested object properties) are passed through verbatim.
This makes targeted edits cheap. For example, adding one entry to a set:
stalwart-cli update domain b --field 'aliases/extra.example.com=true'And removing one entry from a set or map:
stalwart-cli update domain b --field 'aliases/extra.example.com=null'The JSON pointer model is the same one JMAP uses internally:
- Sets are encoded as a map of
value -> true. Set the value totrueto add, tonullto remove. - Object lists are encoded as a map of stringified positional indices to objects. Use a new index to add, set the index to
nullto remove. - Maps are plain JSON objects: set a key’s value to update, set it to
nullto delete.
Quoted keys
Section titled “Quoted keys”When a JSON-pointer path contains characters that would otherwise be misparsed (for example a literal = in a CIDR or header name), quote the entire key:
stalwart-cli update systemsettings --field '"proxyTrustedNetworks/127.0.0.1"=true'Without quotes, the parser splits on the first =, which would land inside the path. With quotes, everything between the matching quote characters is the key, and the first = after the closing quote separates key from value.
Updating singletons
Section titled “Updating singletons”Singletons accept (or default to) the literal id singleton:
stalwart-cli update systemsettings --field allowRelaying=truestalwart-cli update systemsettings singleton --field allowRelaying=trueBoth are equivalent. Passing any other id for a singleton is rejected with a clear error.
Input sources
Section titled “Input sources”Identical to create:
| Source | When to use |
|---|---|
--field key=value | Quick targeted edits from the shell |
--json '<json>' | A small structured patch composed inline |
--file <path> | A patch generated by another tool or template |
--stdin | A patch piped from another command |
For the JSON forms, the document is the patch object sent to JMAP, not the full object. Setting a sub-key with the JSON forms uses the JSON-pointer convention (the keys may contain /):
stalwart-cli update domain b --json '{"description": "Renamed", "aliases/extra.example.com": true}'Repeating the same key with --field is an error. Mixing input sources is also an error (only one may be supplied).
Examples
Section titled “Examples”Change a description:
stalwart-cli update domain b --field description='Primary domain'Toggle a singleton flag:
stalwart-cli update systemsettings --field allowRelaying=falseReplace a structured field:
stalwart-cli update domain b \ --field 'certificateManagement={"@type":"Automatic","acmeProviderId":"a"}'Add a new alias to an object list (next available index):
stalwart-cli update account/user b --field 'aliases/3={"name":"hello","domainId":"b"}'Add an item to a set (using set-of-id semantics):
stalwart-cli update account/user b --field 'memberGroupIds/g1=true'Remove the same item:
stalwart-cli update account/user b --field 'memberGroupIds/g1=null'Apply a patch generated by another tool:
generate-domain-patch.sh | stalwart-cli update domain b --stdinVariant changes
Section titled “Variant changes”For multi-variant objects, changing the variant requires patching the entire sub-object atomically (JMAP cannot mix @type/... JSON pointer keys with sibling property changes when the type itself changes). Send the new variant’s full body in one go:
stalwart-cli update domain b \ --field 'certificateManagement={"@type":"Automatic","acmeProviderId":"a"}'The CLI does not validate variant changes (the server does). For complex variant transitions, prefer a JSON file built by a configuration tool.
Output
Section titled “Output”A success line is printed:
Updated Domain bIf the server returns server-set fields after the update (rare; mostly for fields that are recomputed), they are rendered below in the same form-driven view as get.
See also
Section titled “See also”- Fetching a single object to verify changes.
- Creating objects for the corresponding create flow.
- Declarative bulk operations for atomic multi-object updates with cross-references.