Skip to content
v0.1.3

ADR-0002: Global Flag Precedence Contract

  • Date: 2025-08-01
  • Status: Accepted
  • Author: Bijan Mousavi

Context

Our Bijux CLI requires a deterministic and testable handling of global flags (--help, --quiet, --debug, --format, --pretty/--no-pretty, --verbose) across all commands to ensure consistency. This prevents ambiguous behaviors in hypothesis-driven fuzz tests, provides a clear "short-circuit" model for scripting and human users, and maintains synchronization between documentation, ADRs, and implementations. Without a formal contract, variations in flag-resolution rules could lead to edge cases and debugging challenges.

Decision

All Bijux CLI commands must enforce global flags in the following strict precedence order, with exact semantics applied uniformly:

  1. Help (-h / --help)
  2. Short-circuits all other processing.
  3. Immediately prints usage information and exits with code 0.
  4. Skips validation or processing of any other flags or arguments.

  5. Quiet (-q / --quiet)

  6. Applies only if help is absent.
  7. Suppresses all normal output on stdout and stderr.
  8. Still performs full validation of flags and arguments, exiting with 0 on success or non-zero on errors.
  9. Overrides debug, format, pretty/no-pretty, and verbose for output suppression, but not for exit codes.

  10. Debug (--debug)

  11. Applies only if neither help nor quiet is present.
  12. Emits diagnostics and full trace information to stderr.
  13. Implicitly enables verbose output (e.g., runtime metadata).
  14. Forces --pretty formatting, overriding any --no-pretty.

  15. Format (-f <fmt> / --format <fmt>)

  16. Applies only if neither help nor quiet is present.
  17. Requires a valid format name (json or yaml, case-insensitive).
  18. Invalid or missing value triggers a structured error payload and exit code 2.

  19. Pretty / No-Pretty (--pretty / --no-pretty)

  20. Applies only if neither help nor quiet is present.
  21. Controls indentation for human-readable structured output.
  22. Defaults to --pretty if neither is specified.
  23. Overridden by debug, which always enforces pretty formatting.

  24. Verbose (-v / --verbose)

  25. Applies only if neither help nor quiet is present.
  26. Appends runtime metadata (e.g., Python version, platform) to structured output.
  27. No-op under quiet; implied by debug.

Error-Handling Rules

  • Under help, always exit 0 with usage displayed, ignoring any invalid flags or arguments.
  • Under quiet, suppress both stdout and stderr and return only an exit code (no JSON/YAML payload).
  • Standard exit codes apply otherwise:
  • 0: Success
  • 1: Internal/fatal errors
  • 2: Bad CLI usage (missing/invalid flags or arguments)
  • 3: ASCII/encoding hygiene failures
  • Every error payload (JSON or YAML) must include:
  • "error": Human-readable message
  • "code": Numeric exit code

Consequences

Pros

  • Ensures deterministic behavior, eliminating flakiness in fuzz tests and user interactions.
  • Provides a single source of truth for flag handling, simplifying documentation and maintenance.
  • Enhances testability by allowing assertions on specific argv patterns (e.g., -h always yields usage and exit 0).

Cons

  • Requires each command's entrypoint to inspect sys.argv (or Typer/Click context) before parsing, adding initial implementation overhead.
  • Contributors unfamiliar with the precedence must adapt, with no flexibility for command-specific variations.

Enforcement

  • No command implementation or pull request is accepted unless it fully adheres to this precedence contract.
  • CI pipelines and reviewers must verify compliance through tests, rejecting any deviations in flag handling or semantics.
  • This policy is binding and non-negotiable to maintain CLI consistency.