Summary
In a non-interactive shell, noorm change list and noorm change history produce no output at all — no table, no "no changes found" message — and exit 0. Only --json returns data.
Repro
- Apply a changeset so history is non-empty:
noorm change run <name>
noorm change history; echo "exit=$?"
noorm change history --json
Expected
Step 2 prints the history, or an explicit empty-state message. Either way the caller can tell the difference between "no changesets" and "no output".
Actual
Step 2 prints nothing and exits 0. Step 3 returns the full array.
A CI step that greps the plain-text output for a changeset name reads success from silence — the same result it would get from an empty database.
Related: flag position is load-bearing and unsignalled
--json only works after the leaf subcommand:
noorm change history --json # works
noorm change --json history # silent, exit 0
noorm --json change history # silent, exit 0
The two wrong forms fail the same way as the plain-text case — no output, no error, exit 0 — so a typo in flag placement is indistinguishable from an empty result.
Separately, structured log lines are emitted to stdout ahead of the JSON payload even in --json mode, so consumers have to tail -1 rather than piping stdout straight to a parser. Log output belongs on stderr.
Environment
- noorm CLI
0.0.0, core 1.0.0-alpha.39
- OS: macOS (darwin 25.5.0)
- Runtime: Node v24.13.0
- Dialect: mssql
Context
Found while verifying the changeset loop during a production schema migration. The tracked-migration history is the main reason we adopted noorm over a hand-rolled deploy script, so being unable to read it non-interactively was a blocker until --json was found.
Summary
In a non-interactive shell,
noorm change listandnoorm change historyproduce no output at all — no table, no "no changes found" message — and exit 0. Only--jsonreturns data.Repro
noorm change run <name>noorm change history; echo "exit=$?"noorm change history --jsonExpected
Step 2 prints the history, or an explicit empty-state message. Either way the caller can tell the difference between "no changesets" and "no output".
Actual
Step 2 prints nothing and exits 0. Step 3 returns the full array.
A CI step that greps the plain-text output for a changeset name reads success from silence — the same result it would get from an empty database.
Related: flag position is load-bearing and unsignalled
--jsononly works after the leaf subcommand:The two wrong forms fail the same way as the plain-text case — no output, no error, exit 0 — so a typo in flag placement is indistinguishable from an empty result.
Separately, structured log lines are emitted to stdout ahead of the JSON payload even in
--jsonmode, so consumers have totail -1rather than piping stdout straight to a parser. Log output belongs on stderr.Environment
0.0.0, core1.0.0-alpha.39Context
Found while verifying the changeset loop during a production schema migration. The tracked-migration history is the main reason we adopted noorm over a hand-rolled deploy script, so being unable to read it non-interactively was a blocker until
--jsonwas found.