Centralize CLI output through shared renderers module with get_console() and get_err_console() accessors. Introduce ColumnSpec-based table rendering for plan list, resource list, and actor list commands. Add _FORMAT_HELP constant and fmt= parameter threading for consistent format handling. Includes Behave BDD tests for format output validation, Robot Framework integration tests for CLI formatting consistency, and CHANGELOG entry. ISSUES CLOSED: #210
4.2 KiB
CLI Output Contract
Overview
All CleverAgents CLI commands use a shared output rendering layer that guarantees structural consistency across commands and formats.
Supported Formats
| Format | Description | ASCII-only |
|---|---|---|
rich |
Full Rich terminal markup with colours | No |
color |
ANSI colour codes, no cursor movement | No |
table |
ASCII box-drawing table layout | Yes |
plain |
Key-value pairs, no markup | Yes |
json |
Indented JSON | Yes |
yaml |
YAML document | Yes |
Output Groups
Detail View (render_detail)
Used by show and create commands. Renders a key-value panel.
List View (render_list)
Used by all list commands. Renders a table with stable column order.
Columns are defined once per command in a list[ColumnSpec] and reused
for all formats, guaranteeing identical field names and ordering.
Error Messages (render_error)
All errors use render_error(label, message, recovery=...).
For json / yaml formats, errors are wrapped in a unified envelope:
{
"error": {
"code": "NotFound",
"message": "Resource not found",
"recovery": "Run 'agents resource add' first"
}
}
Success Messages (render_success)
Green checkmark for rich, OK: ... for plain.
Warning Messages (render_warning)
Yellow text for rich, WARNING: ... for plain.
Empty Results (render_empty)
Consistent "No found." with optional recovery hint.
Stable Field Names
JSON and YAML outputs use the same field names as the domain model's
_*_spec_dict() helpers. Column ordering in list views matches the
ColumnSpec declarations.
JSON/YAML Error Envelope
All error output in JSON/YAML format uses:
{
"error": {
"code": "<label>",
"message": "<description>",
"details": {},
"recovery": "<hint>"
}
}
ASCII Compatibility
The plain format guarantees ASCII-only output for log pipeline
compatibility. Non-ASCII characters are replaced with ?.
Migration Status
All command modules now route output through the shared renderers.py
layer via get_console() instead of creating module-level Console()
instances.
| Module | Shared Renderers | get_console() |
Notes |
|---|---|---|---|
action.py |
Full | Yes | list/show/archive |
actor.py |
Full | Yes | list/show |
config.py |
Partial | Yes | render_error/render_empty; Rich panels |
plan.py |
Partial | Yes (+ local) | status/errors/lifecycle; streaming uses local Console for Live/Progress |
project.py |
Partial | Yes | render_error/render_empty/render_success; Rich panels |
project_context.py |
Partial | Yes | render_error/render_success; Rich panels |
resource.py |
Partial | Yes | render_error/render_empty/render_success; Rich panels |
session.py |
Partial | Yes | render_error/render_empty/render_success/render_warning |
skill.py |
Partial | Yes | render_error/render_empty/render_success; Rich panels |
tool.py |
Full | Yes | render_list/render_error/render_success/render_warning/render_empty |
automation_profile.py |
None | No | Legacy; see issue #813 |
context.py |
None | No | Legacy; see issue #813 |
lsp.py |
None | No | Legacy; see issue #813 |
invariant.py |
None | No | Legacy; see issue #813 |
validation.py |
None | No | Legacy; see issue #813 |