Skip to content

UDE v2.0 CLI Reference Manual

Command Overview

The UDE v2.0 CLI provides a set of subcommands for parsing, rendering, auditing, and compiling documentation, built on top of the ude entrypoint (python -m ude.cli or the installed ude script — both invoke the same ude.cli.main()). Note that the runtime environment expects PYTHONPATH: engine to be correctly scoped.

Four subcommands exist: compile, parse, render, audit. If you invoke ude with no subcommand at all, it falls back to legacy flat-flag mode, which is functionally identical to ude compile (see Legacy Flat-Flag Mode below).

Every successful ude compile run (and every equivalent flat-flag invocation) unconditionally prints a full Documentation Coverage Audit table to stdout after rendering completes — this is not something you opt into, and it is not exclusive to ude audit. See Documentation Coverage Audit Table below.

Legacy Flat-Flag Mode (No Subcommand)

For backward compatibility with v1.0, the top-level parser accepts the same flags as compile directly, without any subcommand:

FlagShortRequiredDefaultAccepted values
--global-config-gNoNonePath to a global config JSON file
--sdk-config-sNoNonePath to an SDK/product config JSON file
--doc-config-dNo*NonePath to the target's doc config JSON file
--config-cNo*NoneLegacy alias for --doc-config (path to the same kind of JSON file)
--input-iNoNone (falls back to the doc config's src_dir)Source directory path
--output-oNoNoneOutput directory path
--format-fNoNoneExactly one of hugo_markdown or html — enforced by argparse choices, so an invalid value causes argparse itself to exit before any UDE code runs

* At least one of --doc-config/--config is required. If both are omitted, the flat-flag handler errors with Error: --doc-config is required. and returns exit code 1. If only --config is given, its value is used as the doc-config path. If both are given, --doc-config wins (the handler checks args.doc_config or args.config, in that order).

Running ude --doc-config X behaves identically to ude compile --doc-config X — the code comment at engine/ude/cli.py cites requirement IMP-01.7 ("byte-identical output... holds between them"), backed by a real test, test_compile_and_flat_flags_output_identical. The only difference between the two paths is the exact wording of the missing-doc-config error message ("...required." vs. "...required for compile.").

Example — flat-flag compile:

bash
python -m ude.cli --global-config ../../ude_global_config.json --sdk-config ../ude_sdk_config.json --doc-config ude_doc_config.json --format html

This is byte-identical to the ude compile example shown below, including the coverage table.

Example — missing doc config:

bash
python -m ude.cli --global-config ../../ude_global_config.json
text
Error: --doc-config is required.

Exit code: 1.

ude compile

Executes the full pipeline: parse, then render, then (unconditionally) run and print the documentation coverage audit. Requires --doc-config or --config.

FlagShortRequiredDefaultAccepted values
--global-config-gNoNonePath to a global config JSON file
--sdk-config-sNoNonePath to an SDK/product config JSON file
--doc-config-dNo*NonePath to the target's doc config JSON file
--config-cNo*NoneLegacy alias for --doc-config
--input-iNoNone (falls back to the doc config's src_dir)Source directory path
--output-oNoNoneOutput directory path
--format-fNoNonehugo_markdown or html

* Same requirement as flat-flag mode. If neither is given: Error: --doc-config is required for compile., exit code 1.

Exit codes: 0 on success, 1 on any pipeline/config error (missing config file, JSON parse failure, an unsupported renderer format string inside the target config, etc.). This includes the case where a documentation coverage gate failure occurs while GlobalConfig.coverage_mode is reject-undocumented: inside compile, that failure is just another pipeline-stage exception, caught by the same generic handler and reported as exit code 1not exit code 2. Exit code 2 for coverage rejection is exclusive to the separate ude audit subcommand (see below).

Example — real, verified run (from ude_projects/mock/mock_api_py/):

bash
python -m ude.cli --global-config ../../ude_global_config.json --sdk-config ../ude_sdk_config.json --doc-config ude_doc_config.json --format html

Exit code: 0. Stdout contains no other output before the coverage table, which begins:

text
# Documentation Coverage Audit

**Total Entities:** 713
**Documented Entities:** 13
**Overall Coverage:** 1.82%

| Type | Entity Name | Documented |
| :--- | :--- | :--- |
| Class | `core_modeler::Box` | PASS |
| Method | `core_modeler::Box.getVolume` | FAIL |

This table continues for all 713 parsed entities (one row per class, method, or field/variable counted for coverage) — the row count above is truncated for readability in this document only; the real table has no ellipsis or omitted rows, it simply runs long.

Example — using the legacy --config alias with ude compile:

bash
ude compile --config ude_doc_config.json --format hugo_markdown

Behaves exactly as if --doc-config ude_doc_config.json had been passed.

Example — missing doc config:

bash
ude compile --global-config ../../ude_global_config.json
text
Error: --doc-config is required for compile.

Exit code: 1.

ude parse

Executes only the parsing phase: parses the source tree into an in-memory catalog, writes it as a gzip-compressed Intermediate Representation (IR) file to --output-ir, and prints a one-line JSON summary to stdout. Does not render, and does not print a coverage table.

FlagShortRequiredDefaultAccepted values
--global-config-gNoNonePath to a global config JSON file
--doc-config-dNo*NonePath to the target's doc config JSON file
--config-cNo*NoneLegacy alias for --doc-config
--output-ir(none)YesPath to write the gzip-compressed IR file

* At least one of --doc-config/--config is required, else Error: --doc-config is required for parse., exit code 1.

Note: ude parse has no --sdk-config flag — it is absent from _add_parse_subparser in engine/ude/cli.py. It also has no --input, --output, or --format flags; those only apply to the full pipeline (compile) or to render.

Exit codes: 0 on success, 1 on any error (config resolution failure, parse failure, IR write failure), printed as Error: {e}.

Example (illustrative — namespace/class counts below are representative, not measured from a real run; only the JSON shape and key names are guaranteed):

bash
ude parse --doc-config ude_doc_config.json --output-ir catalog_ir.gz
text
{"namespaces": 4, "classes": 12}

Exit code: 0. The catalog_ir.gz file is written alongside this stdout line.

Example — missing doc config:

bash
ude parse --output-ir catalog_ir.gz
text
Error: --doc-config is required for parse.

Exit code: 1.

ude render

Executes only the rendering phase, loading a previously generated IR file and writing rendered output (Markdown or HTML, depending on config/--format) to --output. Does not parse source, and does not print a coverage table.

FlagShortRequiredDefaultAccepted values
--global-config-gNoNonePath to a global config JSON file
--doc-config-dNoNonePath to the target's doc config JSON file
--config-cNoNoneLegacy alias for --doc-config
--input-ir(none)YesPath to the gzip-compressed IR file produced by ude parse
--output-oYesOutput directory path
--format-fNoNonehugo_markdown or html

Notes:

  • ude render has no --sdk-config flag, same as parse.
  • Unlike every other subcommand, --doc-config/--config is optional for render. If neither is given, rendering proceeds with an empty {} config and Path.cwd() as the config directory (no error is raised) — this only works if the referenced renderer/template setup does not actually need resolved config values.
  • If --format is given, it overrides config["renderer"]["type"] in-place before rendering, taking precedence over whatever format the resolved doc/sdk/global config cascade specified.

Exit codes: 0 on success, 1 on any error (IR load failure, config resolution failure, render failure), printed as Error: {e}.

Example:

bash
ude render --input-ir catalog_ir.gz --output ./build --doc-config ude_doc_config.json --format html

Exit code: 0. No stdout on success; rendered files are written under ./build.

Example — decoupled pipeline (parse, then render from the IR):

bash
ude parse --doc-config ude_doc_config.json --output-ir catalog_ir.gz && ude render --input-ir catalog_ir.gz --output ./build --format html

ude audit

Parses the target (no rendering) and enforces the documentation coverage gate, printing the same coverage audit table described above. This is the only subcommand with a three-way exit code contract.

FlagShortRequiredDefaultAccepted values
--global-config-gNoNonePath to a global config JSON file
--doc-config-dNo*NonePath to the target's doc config JSON file
--config-cNo*NoneLegacy alias for --doc-config
--mode(none)NoFalls back to GlobalConfig.coverage_mode ("allow-undocumented" by default)reject-undocumented or allow-undocumented
--threshold(none)NoFalls back to GlobalConfig.coverage_threshold as-is (a 0.0-1.0 fraction, default 1.0)A plain number string, 0-100 (a percentage, e.g. 98 for 98%)

* At least one of --doc-config/--config is required, else Error: --doc-config is required for audit., exit code 1.

--threshold unit warning: unlike GlobalConfig.coverage_threshold in JSON config (a 0.0-1.0 fraction), the CLI --threshold flag takes a 0-100 percentage and divides it by 100 internally before comparing. --threshold 98 means "require 98% coverage," not "require 9800% coverage." A non-numeric value errors Error: --threshold must be a number, got '{value}'. (exit 1); a value outside the 0-100 range errors Error: --threshold must be between 0 and 100 (got {value}). (exit 1).

No --sdk-config, --input, --output, or --format flags exist on audit.

Exit codes:

  • 0 — the coverage gate passed, or --mode/GlobalConfig.coverage_mode resolved to allow-undocumented (in which case the gate is purely informational and never fails).
  • 1 — a pipeline/parsing/config error occurred before the gate could even run (missing config file, JSON parse failure, source parse failure, or a malformed --threshold).
  • 2specifically when reject-undocumented mode is active and measured coverage falls below the threshold. This is the one place in the whole CLI where a coverage-gate failure (UdeException, raised by apply_coverage_gate()) is caught and mapped to its own dedicated exit code, distinct from the generic 1.

Example — real, verified numbers, gate fails:

bash
ude audit --doc-config ude_doc_config.json --mode reject-undocumented --threshold 98

Against the same mock project referenced above (713 total entities, 13 documented, 1.82% actual coverage), this prints the same coverage table shown in the compile example, then:

text
Error: Documentation coverage gate failed: 1.82% < required 98.00%.

Exit code: 2.

Example — same target, default mode (gate passes because it's informational-only):

bash
ude audit --doc-config ude_doc_config.json

Prints the identical coverage table (713 / 13 / 1.82%) but exits 0, because --mode was omitted and GlobalConfig.coverage_mode defaults to allow-undocumented.

Documentation Coverage Audit Table (printed by compile)

This is the single most important behavior to understand about the engine: ude compile (and therefore legacy flat-flag mode, and ude audit) always computes and prints a documentation coverage audit table to stdout after its respective pipeline stage(s) complete successfully — this happens in apply_coverage_gate() (engine/ude/coverage.py), called from engine/ude/orchestrator.py:797-809 for every compile sweep, and directly from the audit subcommand handler. It is not gated behind a flag, and it is not exclusive to ude audit.

Format:

text
# Documentation Coverage Audit

**Total Entities:** <int>
**Documented Entities:** <int>
**Overall Coverage:** <float, 2 decimals>%

| Type | Entity Name | Documented |
| :--- | :--- | :--- |
| Class | `<fully::qualified::Name>` | PASS or FAIL |
| Method | `<fully::qualified::Name.method>` | PASS or FAIL |
| Variable | `<fully::qualified::Name.field>` | PASS or FAIL |

One row is printed per counted class, method, and field/variable (private _foo/dunder __foo__ names and internal parser artifacts are excluded from the count entirely, not scored as FAIL).

Whether this table is purely informational or can fail your build depends entirely on GlobalConfig.coverage_mode:

  • allow-undocumented (the default): the table is printed, but nothing fails because of it — neither compile nor audit will error out due to low coverage.
  • reject-undocumented: coverage below GlobalConfig.coverage_threshold (or --threshold for audit) raises UdeException. In ude audit, this is caught and mapped to exit code 2. In ude compile / flat-flag mode, this same exception is just another pipeline-stage failure, caught generically and reported as "Compilation error: {e}" with exit code 1compile never returns 2 for this or any other reason.

Exit Codes Table

Exit CodeDescriptionScope
0SuccessExecution completed cleanly (for audit, includes allow-undocumented mode regardless of measured coverage).
1Pipeline/config errorAny subcommand: missing/invalid config, JSON parse failure, parsing/rendering failure. For compile/flat-flag mode specifically, this also covers a reject-undocumented coverage-gate failure.
2Audit coverage rejectionude audit only: reject-undocumented mode and measured coverage below the threshold.

Footnote: argparse itself (an invalid flag, a missing required argument, or an invalid --format/--mode choices value) exits the process directly via SystemExit, using argparse's own conventional exit code (2, by argparse convention) before any UDE subcommand handler ever runs. This is a coincidental overlap with audit's exit code 2 for coverage rejection — the two are unrelated; one is argparse's own usage-error convention, the other is ude audit's specific coverage-gate contract described above.

(Paths below are repository-root-relative.)

  • user-docs/docs/migration-v2.md — v1.0 -> v2.0 CLI architecture decoupling background
  • user-docs/docs/changelog.md — release notes for the subcommands documented here