Conversation
Introduces FormatAuto/FormatJSON/FormatHuman constants and a ResolveOutputFormat helper that picks an effective format from --format flag, OMNI_OUTPUT_FORMAT env, the config file's defaultOutputFormat field, or auto(TTY). This is the foundation for a human-readable default output mode — the renderer and CLI wiring land in follow-up commits. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Renders JSON responses in a terminal-friendly way, similar to the
gh CLI. List-wrapper objects (records/connections/bare arrays)
become aligned tables with capitalized headers. Single resources
become key: value blocks. Mixed objects — e.g. AI endpoints that
return both an `answer` string and a `sources` array — render each
top-level field under its own uppercase heading so nothing gets
silently dropped. Timestamps are formatted as relative ages
("2h ago"), and pageInfo becomes a cursor footer.
No new dependencies: columns are hand-aligned by rune width.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds -o/--format as a persistent flag on the root command and dispatches API responses to the human renderer when chosen. Default is auto: human when stdout is a TTY, JSON when piped, so existing pipelines like `omni models list | jq ...` keep working unchanged. Users who prefer human output everywhere can set it once with `omni config set-format human`, which persists to config.json and is surfaced by `omni config show`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Convert API field names like `modelKind` or `MODEL_KIND` into `Model Kind`, and add a blank line between the header row and data rows so tables are easier to scan. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Swap the hand-rolled space-aligned table renderer for lipgloss/table: normal box-drawing borders, bold headers, dim identifier columns, grey timestamp columns. Color is auto-disabled when stdout isn't a TTY via termenv. Picked lipgloss over go-pretty so this investment carries into any future bubbletea work on the nate/tui branch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
An API response with `"error": null` (e.g. the ai/generate-query shape) was rendering as `Error: -`, which looks like a failure even though the request succeeded. Null scalars carry no information to a human reader, so skip them in both the key-value and mixed scalar/array renderers. JSON mode is unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Long-running endpoints (ai/generate-query, model compilation, etc.) left the terminal silent for seconds. Add a small briandowns/spinner on stderr while the HTTP request is pending. Only runs when stderr is a TTY and the output format is human — piped/scripted invocations stay quiet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The static "waiting for Omni…" suffix was fine for fast calls
but got boring on slow endpoints. Rotate through a short list
of playful BI-flavored phrases ("consulting the warehouse…",
"aligning facts and dimensions…", etc.) every 3 seconds so the
wait feels less monolithic.
Spinner logic moves to cmd/omni/spinner.go.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
"warming up the cache…" and "polishing the dashboard…" could read as "the CLI is touching your data or clearing caches," which it is not. Replace with two phrases that leave that implication off the table: "squinting at the query plan…" and "summoning rows…". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Author
|
@claude review this |
n8agrin
commented
Apr 21, 2026
|
|
||
| func configSetFormatCmd() *cobra.Command { | ||
| return &cobra.Command{ | ||
| Use: "set-format <json|human|auto>", |
Contributor
Author
There was a problem hiding this comment.
sets the format default
n8agrin
commented
Apr 21, 2026
| // pickColumns selects up to 6 scalar columns across the given records. | ||
| // Priority: id, name, then keys observed in insertion-ish order (alphabetical | ||
| // since we walked JSON), skipping complex types. | ||
| func pickColumns(records []map[string]any) []string { |
Contributor
Author
There was a problem hiding this comment.
This might be brittle. Something to watch out for.
cmruderman
approved these changes
Apr 21, 2026
Contributor
Author
|
@cmruderman this one is interesting:
I've gotten a request to generally abstract all the api responses behind a uniform data structure / format. We can talk about it in the next couple of weeks. Not sure it needs to be at the API layer, but I was surprised that OpenAPI didn't require one. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a human-readable output format alongside JSON, modeled after
ghCLI. Lists become stylized lipgloss tables; single resources becomekey: valueblocks; mixed objects (e.g. AI search →answer+sources) render each section under its own heading. A spinner runs on stderr for long requests. JSON mode stays the default when piped soomni … | jq …pipelines keep working.Highlights
-o/--formatflag >OMNI_OUTPUT_FORMATenv >defaultOutputFormatinconfig.json>auto(human on TTY, JSON when piped).modelKind→Model Kind,MODEL_KIND→Model Kind,created_at→Created At. No more SHOUTING headers.{records, pageInfo}lists, resource-named arrays ({connections: […]}), success envelopes ({success, message, <resource>}), bare arrays, single resources, and mixed scalar+array."error": nulldoesn't render as a scaryError: -line."consulting the warehouse…","aligning facts and dimensions…","squinting at the query plan…", …). Only shown when stderr is a TTY and format is human; piped/scripted invocations stay quiet.omni config set-format <json|human|auto>subcommand to persist a preference.Example output
./bin/omni models list --modelkind SHARED:./bin/omni ai search-omni-docs "how to add a format to field?"— mixed scalar+array shape renders the answer body (including nested markdown code fences) and the sources table side by side. The outer fence below is four backticks so the inner yaml block stays intact:Commits
--formatflag andomni config set-formatsubcommandTest plan
make test— resolver precedence,humanizeKey, shape heuristics (records list, resource-named list, bare array, single resource, success envelope, empty body, non-JSON passthrough, mixed scalar+array, null-skip regression)make build./bin/omni models list --format humanrenders a bordered table;| catdrops ANSI (termenv auto-downgrade)./bin/omni ai search-omni-docs "…"rendersAnswerblock +Sourcestable./bin/omni ai generate-query <id> "…"hides nullError, shows theResulttableOMNI_OUTPUT_FORMAT=human ./bin/omni models list | catforces human./bin/omni config set-format humanpersists the preference toconfig.json2>/dev/nulland--format json)🤖 Generated with Claude Code