Skip to content

Improve citydb-tool CLI for machine use #66

Description

@clausnagel

The current citydb-tool CLI works well for interactive human use but is challenging to automate or integrate into other tools. Only a few commands, such as info or connect, provide structured output (JSON or text). And such text output is mixed with log messages, which makes parsing difficult. Similarly, error handling relies on exit codes and log messages, requiring fragile log parsing to extract meaningful details. Structured JSON error messages would improve machine usability.

I propose a consistent CLI design for all commands, with the following principles:

1. Well-defined command output

Every command must produce a clearly defined output, or answer. Some commands already do so—for example, info returns a database report, and connect returns a yes/no result. For all other commands, we must define an answer as well, even if it is simply success/failure or a summary of actions performed (e.g., for the import or delete command).

2. Separation of output channels

The answer always goes to stdout, and nothing else is allowed on stdout. This is already a CLI best practice. Outputs should support multiple formats:

  • Text: human-readable, and unlike log messages without timestamps, log levels or severity—just the command’s answer.
  • JSON/YAML: machine-readable, following a common schema for success, failure, and errors (including exit codes).

3. Logs to stderr

All log messages, regardless of level, must go to stderr. This is partially implemented but some commands currently mix logs with the output or answer, which must be avoided.

4. Consistent exit codes

Exit codes should remain consistent across commands. This is implemented already.

5. Machine vs. human mode

The CLI defaults to human (interactive) mode. Machine mode can be enabled via a --response-format flag (text or json, with YAML and others possible in the future). A quiet flag can suppress logs.

6. Consistency within modes, not across modes

Each mode is internally consistent, but both modes may differ in stdout behavior. Human mode follows CLI conventions (data on stdout for success, empty stdout on error). Machine mode provides structured responses on stdout for both success and error cases. This allows human-friendly behavior in text mode while ensuring predictable API-like behavior for automation. For example, if the info command fails due to errors, then stdout is empty in human mode and all error information can be found in the logs. In machine mode, however, a JSON error message is printed to stdout in this case.

I think this design can be consistently applied to all commands, even those whose answer is just success/failure. A possible exception is the export command: the exported data could be seen as answer but it cannot go to stdout due to large size, multiple files in case of tiling, or formats like ZIP/GZIP. Similar to import and delete, the command’s answer should therefore be an export summary, while the data can only be written to files (as currently implemented).

Redesigning the CLI this way would make it significantly more usable for both humans and machines. But is also requires some implementation work, so feedback is welcome.

Metadata

Metadata

Assignees

Labels

domain: cliCommand-line interface, argument parsing, and terminal interactiontype: featureRequests for new capabilities, enhancements, or additions to existing functionality

Fields

No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions