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.
1. Inline JSON with —ops
Section titled “1. Inline JSON with —ops”Pass a JSON array of operations directly:
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.
2. From File with —file / -f
Section titled “2. From File with —file / -f”Load operations from a JSON file:
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.
From a JSONL file
Section titled “From a JSONL file”wh commit create --file dataset.jsonl -m "Bulk ingest" --progressWhere 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}}From stdin
Section titled “From stdin”Pipe operations from any producer:
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"Chunking
Section titled “Chunking”Operations are sent to the backend in chunks (default: 500 ops per chunk, max: 500). Override with --chunk-size:
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.
Interactive progress
Section titled “Interactive progress”Add --progress to see a live progress bar on stderr (TTY only):
wh commit create --file dataset.jsonl --progress -m "10k sensors"# Appending [####------] 4000/10000 (40%) 8 chunks 2.3sFor --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.
Batch tokens across chunks
Section titled “Batch tokens across chunks”$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}}Debug timing
Section titled “Debug timing”Pass --debug to see a detailed timing breakdown (begin, append, finalize, promote) and throughput metrics on stderr.
4. Shorthand Flags
Section titled “4. Shorthand Flags”For single-operation commits, use shorthand flags instead of writing JSON:
Add a thing
Section titled “Add a thing”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.
Add an assertion
Section titled “Add an assertion”When --about is provided, the kind auto-infers to assertion:
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: {...} }
Revise a thing
Section titled “Revise a thing”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: {...} }
Add a shape
Section titled “Add a shape”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:
# Typed field with descriptionwh 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 } } }'Specify kind explicitly
Section titled “Specify kind explicitly”Override the auto-inferred kind with --kind. For example, to explicitly mark an operation as a thing:
wh commit create --add my-item --kind thing --shape Player --data '{"name":"Alice"}'Flag Reference
Section titled “Flag Reference”| Flag | Short | Description |
|---|---|---|
--ops | Operations JSON array (full control) | |
--file | -f | Path to operations file (.json array or .jsonl newline-delimited) |
--stream | Read newline-delimited operations from stdin (staged ingest) | |
--progress | Show interactive progress on TTY stderr (requires --stream or .jsonl --file) | |
--chunk-size | Ops per append chunk for --stream or .jsonl --file (default: 500, max: 500) | |
--add | Name for add operation (shorthand) | |
--revise | Name for revise operation (shorthand) | |
--kind | Kind override: thing, assertion, shape, collection | |
--shape | Shape name (prefixed to --add name) | |
--data | Data payload as JSON string | |
--about | Target wref for assertions | |
--type | Collection type shorthand: pair, triple, set, list | |
--members | Comma-separated member wrefs for collection shorthand | |
--message | -m | Commit message |
--author | -a | Author name (default: "cli") |
--workspace | -w | Target workspace name. When set, the commit is written to the workspace instead of baseline. |
Shorthand Resolution Rules
Section titled “Shorthand Resolution Rules”The shorthand flags are resolved as follows:
--add X --shape Y→ name becomesY/X, kind defaults tothing--add X --about Z→ kind auto-infers toassertion--add X --shape Y --about Z→ name becomesY/X, kind isassertion--revise X→ kind defaults tothing--kindoverrides the auto-inferred kind in all cases
If none of --add, --revise, --ops, or --file are provided, the command prints a usage error.
Output
Section titled “Output”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-v1The + 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.