Accept and honor `--output` on the v2 CLI as well
- Dominant language
- Python
- Stars
- 670
- Forks
- 183
- Avg merge
- 15h 13m
- Merged PRs (30d)
- 368
Description
### Main idea
`--output` should work on the v2 CLI the same way it works on v1, but v2 cannot honor it today: it has no console renderer, so the flag would have exactly one truthful value.
```console
$ backend.ai service list --output=json # v1, works after #13370
$ backend.ai v2 domain list --output=json # Error: No such option: --output
$ backend.ai --output=json v2 domain list # parses, then is ignored — JSON either way
```
Raised in review of #13370: the v2 CLI is just `backend.ai` with `v2` prefixed, so it should behave identically. That is correct — it is the same CLI, and "works on v1, errors on v2" is not explainable to a user.
### Why it was not simply included in #13370
`--output` becomes behaviour through `set_client_config()` → `get_output_handler()` (`src/ai/backend/client/cli/extensions.py:15-36`), reached via `pass_ctx_obj`. v2 uses neither: `grep -c pass_ctx_obj src/ai/backend/client/cli/v2/` is **0**. v2 commands call `print_result()`, which unconditionally serialises to JSON:
```python
# src/ai/backend/client/cli/v2/helpers.py:214-221
def print_result(data: Any) -> None:
"""Print a Pydantic model or dict as formatted JSON."""
...
sys.stdout.write(json_str + "\n")
```
So injecting the option into v2 as-is would parse `--output=console` and discard it — the flag would advertise a mode that does not exist. #13370 explicitly rejected advertising `--output` where it is not honored, and this would reintroduce that.
### Why this is contained, not a 362-command change
There is a **single choke point**. There are 362 v2 leaf command registrations and **338 `print_result()` call sites**. Giving that one function a console mode covers essentially the whole v2 tree.
| Step | Where |
|---|---|
| Add a console rendering path to `print_result()` | `src/ai/backend/client/cli/v2/helpers.py:214` |
| Resolve the mode (root-level `--output`, or the command-level one) | same file; v2 has no `CLIContext`, so decide whether to read `CliContextInfo` directly or adopt the output framework |
| Attach `--output` to v2 commands | needs a v2 equivalent of `pass_ctx_obj`'s attachment point, or an explicit shared decorator |
| Audit the commands that do not call `print_result()` | `grep -rL print_result src/ai/backend/client/cli/v2 --include='*.py'` — 56 modules |
### Open question
Whether v2 should grow its own console renderer, or route through the existing output framework (`ctx.output.print_item` / `print_list`) that v1 uses. The second gives one renderer for both trees and is what #1925 is converging v1 toward; the first is less work now and less coupling. Worth deciding before writing code, since it determines whether `print_result` survives at all.
### Anything else?
Related: #13370 (`--output` accepted on v1 subcommands), #1925 (consistent use of the output framework).
Contributor guide
Research direction
Start with print_result() in src/ai/backend/client/cli/v2/helpers.py and inspect how v2 commands register options, then compare the existing v1 output framework. Decide whether v2 should share that renderer or add a console path, and audit the 56 modules that do not call print_result(). Done means --output is accepted and honored consistently across v2 commands without advertising an unsupported mode.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli, developer-experience
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100