Skip to content

Commit Create Deep-Dive

wh commit create is the primary write command. There are several ways to specify operations: inline JSON, file-based, streaming JSONL for large ingests, and shorthand flags for common single-operation commits.

Pass a JSON array of operations directly:

Terminal window
wh commit create --ops '[
{"operation":"add","kind":"thing","name":"Sensor/temp-1","data":{"location":"Building A","type":"temperature"}},
{"operation":"add","kind":"assertion","name":"Reading/temp-1-v1","about":"Sensor/temp-1","data":{"value":72.5,"unit":"fahrenheit"}}
]' -m "Add sensor with reading" -a "cli"

This is the most flexible form — supports any number of operations with any combination of adds and revises.

Load operations from a JSON file:

Terminal window
wh commit create -f operations.json -m "Batch update"

Where operations.json contains a JSON array:

[
{ "operation": "add", "kind": "thing", "name": "Sensor/temp-1", "data": { "location": "Building A", "type": "temperature" } },
{ "operation": "add", "kind": "thing", "name": "Sensor/humidity-1", "data": { "location": "Building A", "type": "humidity" } }
]

This is useful for moderate-sized pre-generated operation sets. For larger datasets (thousands of operations), use the streaming JSONL format below.

3. Streaming JSONL with —file or —stream

Section titled “3. Streaming JSONL with —file or —stream”

For large commits (hundreds to tens of thousands of operations), the staged ingest protocol streams operations in chunks rather than sending them all at once. This avoids payload size limits and provides interactive progress feedback.

Terminal window
wh commit create --file dataset.jsonl -m "Bulk ingest" --progress

Where dataset.jsonl is a newline-delimited JSON file (one operation per line):

{"operation":"add","kind":"thing","name":"Sensor/temp-1","data":{"location":"Building A","type":"temperature"}}
{"operation":"add","kind":"thing","name":"Sensor/temp-2","data":{"location":"Building B","type":"temperature"}}
{"operation":"add","kind":"assertion","name":"Reading/temp-1-v1","about":"Sensor/temp-1","data":{"value":72.5}}

Pipe operations from any producer:

Terminal window
cat dataset.jsonl | wh commit create --stream -m "Pipe ingest"
# or from a generator:
my-etl-tool --format jsonl | wh commit create --stream -m "ETL ingest"

Operations are sent to the backend in chunks (default: 500 ops per chunk, max: 500). Override with --chunk-size:

Terminal window
wh commit create --file dataset.jsonl --chunk-size 100 -m "Smaller chunks"

All chunks accumulate into a single commit. After all chunks are appended, the CLI finalizes the ingest and polls for completion.

Add --progress to see a live progress bar on stderr (TTY only):

Terminal window
wh commit create --file dataset.jsonl --progress -m "10k sensors"
# Appending [####------] 4000/10000 (40%) 8 chunks 2.3s

For --stream input (where total count is unknown), progress shows running totals without a percentage.

Progress output is stderr-only and suppressed when stderr is not a TTY, so --json stdout remains machine-readable.

$N allocates an opaque identifier (replaced by a unique server-generated suffix), and #N references the value allocated by the matching $N. These tokens work across chunk boundaries — a $1 allocated in chunk 1 can be referenced with #1 in chunk 2+:

{"operation":"add","kind":"thing","name":"Player/player-$1","data":{"score":0}}
{"operation":"add","kind":"assertion","name":"Score/score-$2","about":"Player/player-#1","data":{"value":0}}

Pass --debug to see a detailed timing breakdown (begin, append, finalize, promote) and throughput metrics on stderr.

For single-operation commits, use shorthand flags instead of writing JSON:

Terminal window
wh commit create --add temp-1 --shape Sensor --data '{"location":"Building A","type":"temperature"}' -m "Add sensor"

This produces: { operation: "add", kind: "thing", name: "Sensor/temp-1", data: {...} }

The --shape flag is prefixed to the --add name to form the wref.

When --about is provided, the kind auto-infers to assertion:

Terminal window
wh commit create --add temp-1-v1 --shape Reading --about Sensor/temp-1 --data '{"value":72.5}'

This produces: { operation: "add", kind: "assertion", name: "Reading/temp-1-v1", about: "Sensor/temp-1", data: {...} }

Terminal window
wh commit create --revise Sensor/temp-1 --data '{"location":"Building B","type":"temperature"}' -m "Relocate sensor"

This produces: { operation: "revise", kind: "thing", name: "Sensor/temp-1", data: {...} }

Terminal window
wh commit create --add Location --kind shape --data '{"fields":{"x":"number","y":"number"}}'

Shape data supports an optional top-level description, typed field objects with descriptions, and field constraints:

Terminal window
# Typed field with description
wh commit create --add Location --kind shape --data '{"description":"A point in 2D space","fields":{"x":{"type":"number","description":"Horizontal position"},"y":"number"}}'
# Field constraints (string enum, number range, wref constrained to a shape, array bounds)
wh commit create --add GameState --kind shape \
--data '{
"fields": {
"status": { "type": "string", "enum": ["active", "paused", "ended"] },
"score": { "type": "number", "minimum": 0, "integer": true },
"owner": { "type": "wref", "shape": "Player" },
"tags": { "type": "array", "items": "string", "maxItems": 5 }
}
}'

Override the auto-inferred kind with --kind. For example, to explicitly mark an operation as a thing:

Terminal window
wh commit create --add my-item --kind thing --shape Player --data '{"name":"Alice"}'
FlagShortDescription
--opsOperations JSON array (full control)
--file-fPath to operations file (.json array or .jsonl newline-delimited)
--streamRead newline-delimited operations from stdin (staged ingest)
--progressShow interactive progress on TTY stderr (requires --stream or .jsonl --file)
--chunk-sizeOps per append chunk for --stream or .jsonl --file (default: 500, max: 500)
--addName for add operation (shorthand)
--reviseName for revise operation (shorthand)
--kindKind override: thing, assertion, shape, collection
--shapeShape name (prefixed to --add name)
--dataData payload as JSON string
--aboutTarget wref for assertions
--typeCollection type shorthand: pair, triple, set, list
--membersComma-separated member wrefs for collection shorthand
--message-mCommit message
--author-aAuthor name (default: "cli")
--workspace-wTarget workspace name. When set, the commit is written to the workspace instead of baseline.

The shorthand flags are resolved as follows:

  1. --add X --shape Y → name becomes Y/X, kind defaults to thing
  2. --add X --about Z → kind auto-infers to assertion
  3. --add X --shape Y --about Z → name becomes Y/X, kind is assertion
  4. --revise X → kind defaults to thing
  5. --kind overrides the auto-inferred kind in all cases

If none of --add, --revise, --ops, or --file are provided, the command prints a usage error.

Success output shows the commit ID, message, operation count, and per-operation details:

[a1b2c3d] Add sensor with reading (2 ops)
+ Sensor/temp-1
+ Reading/temp-1-v1

The + prefix indicates adds, ~ indicates revises.

With --json, returns the structured commit result:

{
"commitId": "a1b2c3d4e5f6",
"author": "cli",
"message": "Add sensor with reading",
"operationCount": 2,
"operations": [
{ "name": "Sensor/temp-1", "operation": "add", "version": 1, "dataHash": "abc123" },
{ "name": "Reading/temp-1-v1", "operation": "add", "version": 1, "dataHash": "def456" }
]
}

Each operation result includes the resolved name, operation type, version number, and server-computed data hash.