feat(REL-15756): updating agent friendly and improved rich text output#663
Conversation
JackDanger
left a comment
There was a problem hiding this comment.
The before/after screenshots look great — the table format is a significant UX improvement for humans. This is the kind of change that makes the CLI feel polished. A few things:
1. PR title says REL-15756 but the branch is REL-12756
Typo in the title — feat(REL-15756) should be feat(REL-12756).
2. This is a plaintext format breaking change
Any script that parses the old bullet format (* name (key)) will break:
# This pattern stops working for flags, projects, environments, members, segments:
ldcli flags list --project my-proj -o plaintext | grep "^\* "Research shows no known consumers parse plaintext programmatically (everyone uses -o json), so the practical risk is low. But it's still a format change for an existing output mode. Combined with #660's default-output change, this means scripts that neither set output format nor parse JSON get hit twice: different format AND different default.
3. CmdOutput now takes 5 parameters — time to consolidate
CmdOutput(action, outputKind, input, fields, opts)fields should live inside CmdOutputOpts. You already have the opts struct; having fields as a separate parameter alongside it is inconsistent. This would also clean up every call site that currently passes nil, output.CmdOutputOpts{}.
4. Hardcoded column sets create a long tail of inconsistency
You've defined table columns for 5 resource types (flags, projects, environments, members, segments). The CLI has ~375 auto-generated commands. Everything else falls back to the old bullet format. This means ldcli flags list shows a beautiful table but ldcli segments list shows bullets — wait, segments is covered. But ldcli metrics list, ldcli contexts list, ldcli teams list all fall back. Is there a plan to auto-generate column definitions from the OpenAPI spec, or will this be a gradual manual process?
5. formatTimestamp drops the time component
// Parses RFC3339, outputs "2006-01-02"For flags with recent changes, the date alone isn't very useful. "2026-03-17" tells me nothing about whether a flag was changed 2 minutes ago or 23 hours ago. Consider showing relative time for recent changes ("2h ago") and date for older ones, or at minimum including the time.
6. Tag truncation magic number
Tags are truncated at 3 items with .... This is fine UX, but the 3 is a magic number buried in the formatting function. A named constant would help readability.
7. Singular resource key-value format is a nice touch
The switch from Successfully updated name (key) to a proper key-value block with Key:, Name:, etc. is much better for both humans and agents reading plaintext. Good call.
Cross-cutting concern for the whole stack:
These 5 PRs together change: (1) default output format in non-TTY, (2) error JSON shape, (3) plaintext rendering format. The agent-prompts repo and sandbox-data-generator scripts are the two known consumers to validate against. The agent-prompts guide specifically teaches .code == 401 error checking which #661 changes.
Given ldcli uses semver and the v1→v2 bump was for an OpenAPI shape change, this stack probably warrants a v3 discussion — or at minimum a clear "Breaking Changes" section in the release notes.
|
I'm in favor of doing a v3 for these changes as it gives us more flexibility in the design. |
* [feat] adding --fields flag * feat(REL-15756): updating agent friendly and improved rich text output (#663) feat(REL-15756) updating agent friendly and improved rich text output
…lds, table formatting [REL-12752] (#660) * adding agent flag for agent telemtry * (feat) adding TTY detection for auto-JSON output * improvements * addressing pr feedback * feat(REL-12754): Agent friendly error handling (#661) * [feat] Agent friendly error handling * feat(REL-12755): adding --fields flag (#662) * [feat] adding --fields flag * feat(REL-15756): updating agent friendly and improved rich text output (#663) feat(REL-15756) updating agent friendly and improved rich text output * fix: update stale test assertions for key-value plaintext format Three tests in root_test.go still asserted the old `name (key)` bullet format, but the toggle-on command now passes ResourceName: "flags" which triggers key-value output. Update to match the actual output shape. Made-with: Cursor * refactor: move fields into CmdOutputOpts, warn on plaintext --fields Remove the standalone `fields []string` positional parameter from CmdOutput and pass fields exclusively through CmdOutputOpts.Fields. This eliminates the dual-path API and simplifies every call site. Also emit a stderr warning when --fields is used with plaintext output, since the flag is silently ignored in that mode. Made-with: Cursor * docs: document error shape and table format breaking changes in CHANGELOG Add entries for the error JSON shape change (new statusCode/suggestion fields, message casing) and the plaintext table format change. Both are breaking changes that should be called out for v3.0. Made-with: Cursor
…ds (#677) * adding agent flag for agent telemtry * (feat) adding TTY detection for auto-JSON output * improvements * addressing pr feedback * feat(REL-12754): Agent friendly error handling (#661) * [feat] Agent friendly error handling * feat(REL-12755): adding --fields flag (#662) * [feat] adding --fields flag * feat(REL-15756): updating agent friendly and improved rich text output (#663) feat(REL-15756) updating agent friendly and improved rich text output * fix: update stale test assertions for key-value plaintext format Three tests in root_test.go still asserted the old `name (key)` bullet format, but the toggle-on command now passes ResourceName: "flags" which triggers key-value output. Update to match the actual output shape. Made-with: Cursor * refactor: move fields into CmdOutputOpts, warn on plaintext --fields Remove the standalone `fields []string` positional parameter from CmdOutput and pass fields exclusively through CmdOutputOpts.Fields. This eliminates the dual-path API and simplifies every call site. Also emit a stderr warning when --fields is used with plaintext output, since the flag is silently ignored in that mode. Made-with: Cursor * docs: document error shape and table format breaking changes in CHANGELOG Add entries for the error JSON shape change (new statusCode/suggestion fields, message casing) and the plaintext table format change. Both are breaking changes that should be called out for v3.0. Made-with: Cursor * feat: add --dry-run flag to toggle-on, toggle-off, and archive commands The API already supports dryRun as a query parameter on PATCH /api/v2/flags. The auto-generated `flags update` command exposes it, but the hand-rolled toggle and archive commands passed nil for query params. This wires --dry-run through to MakeRequest on all three. Also adds a Query field to MockClient so tests can verify query params. Made-with: Cursor * fix: use toggle-off in TestToggleOff dry-run tests Copy-paste error had both dry-run subtests invoking toggle-on instead of toggle-off, so toggle-off's --dry-run path was never exercised. Made-with: Cursor
* adding agent flag for agent telemtry * (feat) adding TTY detection for auto-JSON output * improvements * addressing pr feedback * feat(REL-12754): Agent friendly error handling (#661) * [feat] Agent friendly error handling * feat(REL-12755): adding --fields flag (#662) * [feat] adding --fields flag * feat(REL-15756): updating agent friendly and improved rich text output (#663) feat(REL-15756) updating agent friendly and improved rich text output * fix: update stale test assertions for key-value plaintext format Three tests in root_test.go still asserted the old `name (key)` bullet format, but the toggle-on command now passes ResourceName: "flags" which triggers key-value output. Update to match the actual output shape. Made-with: Cursor * refactor: move fields into CmdOutputOpts, warn on plaintext --fields Remove the standalone `fields []string` positional parameter from CmdOutput and pass fields exclusively through CmdOutputOpts.Fields. This eliminates the dual-path API and simplifies every call site. Also emit a stderr warning when --fields is used with plaintext output, since the flag is silently ignored in that mode. Made-with: Cursor * docs: document error shape and table format breaking changes in CHANGELOG Add entries for the error JSON shape change (new statusCode/suggestion fields, message casing) and the plaintext table format change. Both are breaking changes that should be called out for v3.0. Made-with: Cursor * feat: add --dry-run flag to toggle-on, toggle-off, and archive commands The API already supports dryRun as a query parameter on PATCH /api/v2/flags. The auto-generated `flags update` command exposes it, but the hand-rolled toggle and archive commands passed nil for query params. This wires --dry-run through to MakeRequest on all three. Also adds a Query field to MockClient so tests can verify query params. Made-with: Cursor * fix: use toggle-off in TestToggleOff dry-run tests Copy-paste error had both dry-run subtests invoking toggle-on instead of toggle-off, so toggle-off's --dry-run path was never exercised. Made-with: Cursor * feat: register markdown as a valid output kind Add "markdown" alongside "json" and "plaintext" as accepted values for the --output flag. Update validation, help text, and related tests. Made-with: Cursor * feat: add markdown rendering for resource output Implement markdown formatting for singular and list responses: - Flags get a rich view with environment status table and metadata - Known resources use GFM tables for lists, key-value bullets for detail - Unknown resources fall back to headings / bullet lists - Extract paginationSuffix helper to share between plaintext and markdown Made-with: Cursor * test: add markdown output tests for flag commands Cover --output markdown through archive, toggle-on, and toggle-off command tests to verify end-to-end markdown rendering. Made-with: Cursor --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: nieblara <17378597+nieblara@users.noreply.github.com>
Replace the minimal plaintext output (* name (key) bullets) with table-formatted output using text/tabwriter. Define column sets per resource type starting with 5-6 high-value resources (flags, projects, environments, members, segments). Everything else falls back to the current bullet format. Singular resources show key-value pairs.
before:



after:


Note
Medium Risk
Medium risk because it changes the CLI’s default plaintext rendering across multiple resource commands, which can impact user workflows and tests that parse human-readable output (JSON output remains unchanged).
Overview
Updates plaintext CLI output to be resource-aware: when
CmdOutputis given aResourceName, list responses render as aligned tables and singular responses render as key/value blocks (with fallback to the existing bullet andname (key)formats for unknown resources).Adds
internal/output/table.gowith per-resource column registries (initiallyflags,projects,environments,members,segments) plus formatting helpers (yes/no booleans, tag truncation, timestamp formatting), and extendsCmdOutputwith optionalCmdOutputOpts(including defaultFields). Commands now passResourceName(e.g.,flags archive/toggle,members invite, and generatedresourcesoperations), and tests are updated/expanded to assert the new plaintext output while keeping JSON behavior the same.Written by Cursor Bugbot for commit 887c614. This will update automatically on new commits. Configure here.