User Story
As an operator or platform integrator automating OpenShell workflows, I want
every resource-listing command to support the same structured output formats,
so that I can consume typed data without parsing tables intended for humans.
Problem Statement
OpenShell has a shared -o/--output <table|json|yaml> convention for resource
lists such as sandbox list, provider list, gateway list, and workspace list. Four remaining literal list commands expose typed RPC data only as
fixed-width tables:
openshell service list
openshell policy list
openshell sandbox provider list
openshell workspace member list
Their empty states are also prose rather than parseable collections. Callers
must therefore parse column layouts, presentation strings, and abbreviated or
truncated values. This makes automation depend on formatting that is free to
change and gives closely related CLI commands inconsistent interfaces.
Impact / Why This Matters
Integrations that enumerate exposed services, policy revisions, attached
providers, or workspace members cannot use one stable CLI pattern. They must
call lower-level APIs or maintain command-specific table parsers. Table parsing
is especially lossy for policy list, which shortens policy hashes and load
errors for display.
The workaround increases maintenance cost and can silently return incorrect
data after harmless presentation changes. Direct API use also bypasses the
CLI's configured gateway, authentication, workspace selection, and error
handling, so it is not an equivalent replacement.
Proposed Design
Add -o/--output <table|json|yaml> to the four commands, defaulting to table
so existing interactive behavior remains unchanged.
JSON and YAML should emit collections whose records contain the data currently
represented by each table, using typed values and stable field names rather
than rendered columns. Structured policy history should preserve full values
instead of table abbreviations. Attached-provider output must remain
secret-free and expose metadata such as credential and configuration keys, not
their values.
Structured mode should emit an empty collection on stdout when no records
exist. It should never include ANSI styling or human-readable status messages.
This issue covers the four literal list commands only. Related read surfaces
such as service get, provider get, workspace get, provider refresh status, inference get, and rule get/history should be evaluated as
follow-up work after their output contracts are reviewed.
Acceptance Criteria
Alternatives Considered
Continue parsing tables. This keeps the CLI surface smaller but makes column
order, padding, status wording, and truncation part of an accidental automation
contract.
Add a command-specific --json boolean. settings get already has this older
pattern, but extending it would deepen inconsistency with the shared output
format used by resource lists and would omit YAML.
Add structured output to every read command in one change. Several non-list
commands are also candidates, but their schemas and whether they represent a
single object, collection, stream, or review document need separate decisions.
Keeping this issue to literal list commands makes the behavior and acceptance
criteria reviewable.
Agent Investigation
SandboxProviderCommands::List, PolicyCommands::List,
ServiceCommands::List, and WorkspaceMemberCommands::List have no output
argument in crates/openshell-cli/src/main.rs.
- Their handlers in
crates/openshell-cli/src/run.rs receive typed provider,
policy revision, service endpoint, or workspace member messages and render
tables directly.
OutputFormat and the shared collection serializer already implement
table, json, and yaml, including empty collections.
- No gateway API, policy semantics, or sandbox runtime behavior needs to
change.
User Story
As an operator or platform integrator automating OpenShell workflows, I want
every resource-listing command to support the same structured output formats,
so that I can consume typed data without parsing tables intended for humans.
Problem Statement
OpenShell has a shared
-o/--output <table|json|yaml>convention for resourcelists such as
sandbox list,provider list,gateway list, andworkspace list. Four remaining literallistcommands expose typed RPC data only asfixed-width tables:
openshell service listopenshell policy listopenshell sandbox provider listopenshell workspace member listTheir empty states are also prose rather than parseable collections. Callers
must therefore parse column layouts, presentation strings, and abbreviated or
truncated values. This makes automation depend on formatting that is free to
change and gives closely related CLI commands inconsistent interfaces.
Impact / Why This Matters
Integrations that enumerate exposed services, policy revisions, attached
providers, or workspace members cannot use one stable CLI pattern. They must
call lower-level APIs or maintain command-specific table parsers. Table parsing
is especially lossy for
policy list, which shortens policy hashes and loaderrors for display.
The workaround increases maintenance cost and can silently return incorrect
data after harmless presentation changes. Direct API use also bypasses the
CLI's configured gateway, authentication, workspace selection, and error
handling, so it is not an equivalent replacement.
Proposed Design
Add
-o/--output <table|json|yaml>to the four commands, defaulting totableso existing interactive behavior remains unchanged.
JSON and YAML should emit collections whose records contain the data currently
represented by each table, using typed values and stable field names rather
than rendered columns. Structured policy history should preserve full values
instead of table abbreviations. Attached-provider output must remain
secret-free and expose metadata such as credential and configuration keys, not
their values.
Structured mode should emit an empty collection on stdout when no records
exist. It should never include ANSI styling or human-readable status messages.
This issue covers the four literal list commands only. Related read surfaces
such as
service get,provider get,workspace get,provider refresh status,inference get, andrule get/historyshould be evaluated asfollow-up work after their output contracts are reviewed.
Acceptance Criteria
service list,policy list,sandbox provider list, andworkspace member listaccept-o/--output <table|json|yaml>.table, with typed values and without presentation-only truncation.
configuration values.
human-readable empty-state message.
--helpand published CLI documentation describe the new output flag oneach command.
compatibility, and the public field mappings.
Alternatives Considered
Continue parsing tables. This keeps the CLI surface smaller but makes column
order, padding, status wording, and truncation part of an accidental automation
contract.
Add a command-specific
--jsonboolean.settings getalready has this olderpattern, but extending it would deepen inconsistency with the shared output
format used by resource lists and would omit YAML.
Add structured output to every read command in one change. Several non-list
commands are also candidates, but their schemas and whether they represent a
single object, collection, stream, or review document need separate decisions.
Keeping this issue to literal list commands makes the behavior and acceptance
criteria reviewable.
Agent Investigation
SandboxProviderCommands::List,PolicyCommands::List,ServiceCommands::List, andWorkspaceMemberCommands::Listhave no outputargument in
crates/openshell-cli/src/main.rs.crates/openshell-cli/src/run.rsreceive typed provider,policy revision, service endpoint, or workspace member messages and render
tables directly.
OutputFormatand the shared collection serializer already implementtable,json, andyaml, including empty collections.change.