Skip to content

Getting Started with UDE

Welcome to the Universal Document Engine (UDE)! This guide walks you through the real pipeline architecture, environment prerequisites, and a verified "Hello World" compilation using the engine's own mock example project.


📐 Core Pipeline Concept

UDE turns source code into a documentation site through a fixed sequence of stages. Nothing here is a generic black box — every stage is a concrete, named component:

A few concrete details worth knowing up front:

  • UDE never re-implements Doxygen's parsing. A *DoxygenCollector (e.g. PyDoxygenCollector, CsDoxygenCollector, JavaDoxygenCollector) shells out to the real doxygen binary as an external subprocess and reads back its XML output (index.xml plus one XML file per compound).
  • The XML is handed to a language-specific parser (CsharpDoxygenParser, JavaDoxygenParser, PythonDoxygenParser, or a legacy C++ shim), selected by engine/ude/parsers/doxygen_router.py.
  • Parsers normalize everything into a ProjectCatalog — a tree of Pydantic models: ProjectCatalogNamespaceModelClassModelMethodModel / VariableModel / EnumModel / ConstantModel / TypeAliasModel.
  • Rendering is done by one of 16 concrete renderer classes named <Lang><Output><ID>Renderer, where Lang{Cpp, Cs, Java, Py}, Output{Html, Hugo}, and ID{Default, Legacy}. Static HTML renders to a flat directory of files; Hugo Markdown renders to nested directories with YAML front matter.
  • Every successful compile run — not just a separate "audit" step — ends by printing a documentation coverage audit table. This isn't optional or opt-in; it's unconditional pipeline behavior.

:::note There is no "RAG JSON" output format in the engine today. The only two supported renderer families are static HTML and Hugo Markdown (each with a Default and a Legacy variant per language). :::


💻 Environment Prerequisites

Before running UDE, make sure your host machine has the following available:

🐍 Python Runtime (3.11+)

Verify your local Python installation by running:

bash
python --version

The engine's pyproject.toml pins python = ">=3.11,<4.0", so anything older is not supported.

📑 Doxygen

Doxygen does the actual source-code extraction; UDE only ever calls it as an external subprocess. Verify that Doxygen is available on your PATH:

bash
doxygen --version

If not installed, download it from the official Doxygen website or install via your system package manager (e.g., sudo apt-get install doxygen or brew install doxygen).

If you'd rather not modify your system PATH, you can instead point the engine at a directory containing the Doxygen executable via the doxygen_path key in your global config (engine/ude/config.py:188-204). At startup, the engine prepends that directory to the process PATH so the doxygen subprocess can be found — this is the only place in the engine that reads or writes an environment variable. There are no UDE_* environment variables that control engine behavior.

📦 Package Managers

Ensure either pip or poetry is installed and ready to resolve package dependencies.


🚀 Quick Installation

Method 1: install from the project's pyproject.toml via Poetry

bash
git clone https://github.com/Sir-Derryk/universal-document-engine.git
cd universal-document-engine/engine
poetry install

engine/pyproject.toml defines [tool.poetry.scripts] ude = "ude.cli:main", so after poetry install the ude command is available directly on your PATH inside that environment.

Method 2: run without installing, via PYTHONPATH

If you don't want to install the package, you can invoke the CLI as a module as long as the engine directory is importable:

bash
# from anywhere, with the engine checkout on PYTHONPATH
python -m ude.cli --help

On Windows, set PYTHONPATH to include the engine directory first, e.g. set PYTHONPATH=path\to\engine; on macOS/Linux, PYTHONPATH=path/to/engine.

:::note pip install universal-document-engine is not currently a verified install path — there is no confirmation this package is published to PyPI. Use the Poetry or PYTHONPATH methods above, which are directly verifiable from the repository's own pyproject.toml and CLI entry point. :::


⚡ Your First Compilation (Hello World)

The engine repository ships a real, working example project at ude_projects/mock/mock_api_py/, with three layered config files:

  • ude_projects/ude_global_config.json — global settings
  • ude_projects/mock/ude_sdk_config.json — SDK/product-level settings
  • ude_projects/mock/mock_api_py/ude_doc_config.json — the compilation target itself

That project's own generate_docs.bat runs, from inside the mock_api_py directory:

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

On Windows with no virtualenv active, you also need PYTHONPATH pointed at the engine directory first:

bash
set PYTHONPATH=..\..\..\engine

(on macOS/Linux: PYTHONPATH=../../../engine)

IMPORTANT

There is no bare "Hello World" invocation that skips config files. Every real compile run requires at least a doc-config (--doc-config / -d, or the legacy --config / -c alias); global and SDK configs are optional but almost always present in real projects. A command like python -m ude.cli --input ... --output ... --format html with no --doc-config will fail — --input/--output are only overrides layered on top of a resolved config, not a replacement for one.

Expected Output

This exact sequence was actually run against the mock project (exit code 0, success). Contrary to what you might expect, no [INFO]-style progress lines are printed at all. That's because GlobalConfig.log_level defaults to "WARNING" (engine/ude/config.py:117), and the real ude_global_config.json shipped in this repo doesn't actually set it — its "logging": {"level": "INFO", ...} block is not a real GlobalConfig field (see First Config for why), so it's silently ignored.

The only thing printed to stdout is the coverage audit table, which every successful compile run ends with:

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 |
| Method | `core_modeler::Box.renderToScreen` | FAIL |

This is a representative excerpt, not a placeholder — the real table has one row per parsed entity, and for this mock project that's 713 rows in total.

TIP

Why is coverage so low on the mock example? The mock project is a SWIG-wrapped Python binding, so Doxygen picks up a large number of unfiltered SWIG plumbing methods (swigCPtr, swigregister, and similar) as undocumented entities. The engine does have an exclude_swig_internals filter flag, but as of today it is only reachable if you call the parser directly as a Python library — it is not wired to any JSON config key, so a normal ude_doc_config.json-driven run like this one can't turn it on. Low coverage here is expected, not a bug.

Once it finishes, inspect ude_output/mock_api_py/ (resolved from output_base_dir + output_subdir, see First Config). For --format html you'll find a flat directory (no subdirectories) of files named {entity_type}_{fully_qualified_name}.html, with :: in fully-qualified names replaced by __, e.g. class_core_modeler__Box.html. Alongside those you'll also see a couple of static pages sourced from that project's sidebar.toml (api_ref_version.html, api_ref2dg.html), and a .build_cache.json.gz file — the on-disk L2 render cache used for incremental builds.