API Reference
Managers
- class apatchy.managers.config_manager.ConfigManager(build_mode='fuzz', config_name='fuzz.conf', asan=False, ubsan=False, ubsan_ignorelist=None, intsan=False, truncsan=False)[source]
Generate compiler flags and resolve httpd config paths for a build.
ConfigManageris the central place that translates high-level build intentions (fuzzing, coverage, debugging) and sanitizer choices into the concreteCFLAGS,LDFLAGS, andCCvalues thatBuildManagerpasses to Apache’s./configure. It also resolves the path to the Apache config file (e.g.fuzz.conf) that other managers pass to the harness at runtime.Build modes (mapped to tree types):
"vanilla"- root tree. Plain debug build (-O0 -g) for running a real Apache server to manually verify bugs."libfuzzer"-lfbranch. Adds-fsanitize=fuzzer-no-link(SanCov instrumentation) for LibFuzzer coverage-guided fuzzing."coverage"-covbranch. Adds-fprofile-instr-generateand-fcoverage-mappingfor coverage reports and triage."fuzz"- legacy mode (-O2), used byBugManager.
Sanitizers are orthogonal to the build mode and can be freely combined:
asan- AddressSanitizer (heap/stack buffer overflows, use-after-free).ubsan- UndefinedBehaviorSanitizer (signed overflow, null deref, etc.).intsan- unsigned-integer-overflow checks. A compile-time ignorelist (configs/intsan.ignorelist) is applied automatically to suppress false positives in APR internals.truncsan- implicit-unsigned-integer-truncation checks. Noisy on Apache internals, best used for targeted module auditing.
When a known httpd version is passed to
generate_build_config(), version-specific compatibility flags fromapatchy.compatare appended automatically.- Parameters:
build_mode (
str) – Build profile."fuzz"(default),"coverage", or any other string for a plain debug build.config_name (
str) – Filename of the httpd config to resolve at runtime. Defaults to"fuzz.conf".asan (
bool) – Enable AddressSanitizer.ubsan (
bool) – Enable UndefinedBehaviorSanitizer.intsan (
bool) – Enable unsigned-integer-overflow sanitizer.truncsan (
bool) – Enable implicit-unsigned-integer-truncation sanitizer.ubsan_ignorelist (str)
CLI usage:
ConfigManageris created implicitly by several CLI commands. Theconfigurecommand exposes the most options:# Fuzz build with ASan + UBSan apatchy configure --mode fuzz --asan --ubsan # Coverage build for triage apatchy configure --mode coverage # Fuzz with all integer sanitizers apatchy configure --mode fuzz --asan --intsan --truncsan
Example
from apatchy.managers.config_manager import ConfigManager # Fuzz build with ASan + UBSan config = ConfigManager(build_mode="fuzz", asan=True, ubsan=True) flags = config.generate_build_config(httpd_version="2.4.58") # flags == {"CFLAGS": "-O2 -fno-omit-frame-pointer ...", # "LDFLAGS": "-no-pie -fsanitize=address ..."} # Coverage build for triage cov_config = ConfigManager(build_mode="coverage") cov_flags = cov_config.generate_build_config()
- generate_build_config(httpd_version=None)[source]
Generate
CFLAGSandLDFLAGSbased on the build mode.Sanitizer flags (ASan, UBSan, IntSan, TruncSan) are orthogonal and can be combined with any mode. When httpd_version is provided, version-specific compatibility flags from
apatchy.compatare appended automatically.When
intsanis enabled, a compile-time ignorelist (configs/intsan.ignorelist) is applied automatically to suppress false positives in APR internals.
- class apatchy.managers.module_manager.ModuleManager(httpd_root)[source]
Build external Apache modules as shared objects (
.so) for runtime loading.ModuleManagercompiles custom C modules (e.g.mod_pwn.c) into position-independent shared objects that Apache can load viaLoadModuleat runtime. Module sources live in the external modules directory and are compiled against the Apache build tree’s headers.The compiler defaults to
clang, falling back togccif unavailable. A custom compiler can be specified via theccargument.Sanitizer flags (
-fsanitize=...) are automatically extracted from the Apache build’sconfig_vars.mkand propagated to the module build, so modules are instrumented identically to the main binary.Built
.sofiles are placed in<WORK_DIR>/modules/and can be referenced from an httpd config viaLoadModule.- Parameters:
httpd_root (
Path) – Path to the Apache HTTPD source directory whose headers and build config are used for compilation.
CLI usage:
# Build all external modules apatchy module build # Build a specific module apatchy module build mod_pwn # Build with a specific compiler apatchy module build mod_pwn --cc clang # List available modules and their build status apatchy module list
Example
from pathlib import Path from apatchy.managers.module_manager import ModuleManager mm = ModuleManager(Path("httpd-2.4.58")) # Build all modules with default compiler mm.build_module() # Build a specific module mm.build_module(name="mod_pwn") # List what is available for m in mm.list_modules(): print(f"{m['name']} {m['built'] or '(not built)'}")
- class apatchy.managers.build_manager.BuildManager(httpd_root, config_manager, verbose=False)[source]
High-level build orchestration for Apache HTTPD and fuzzing harnesses.
BuildManagerdrives the three main build steps:configure,make, andlink. It delegates flag generation toConfigManagerand harness compilation toHarnessBuilder, adding dependency detection (PCRE, Expat), version-specific compat flags, and optionalbearintegration forcompile_commands.jsongeneration.The configure step (
configure_httpd()) runs Apache’s./configurewith a static-only, all-modules build. It automatically detects PCRE and Expat locations, enables APR pool debug mode when ASan is active (so ASan can track individual pool allocations), and appends any version-specific flags from theapatchy.compatregistry.The compile step (
compile_httpd()) runsmakewith parallel jobs (defaults to CPU count). Whenbear=True, it wraps the build withbearto produce acompile_commands.jsonand updates the.clangdconfig for IDE integration.The link step (
build_harness()) compiles and links the fuzzing harness against the Apache build tree:"libfuzzer"- compiled withclangand-fsanitize=fuzzer.
A coverage-instrumented harness (
fuzz_harness_coverage) is built separately byReportManagerfor triage and coverage reports.- Parameters:
httpd_root (
Path) – Path to the Apache HTTPD source directory (e.g.httpd-2.4.58/).config_manager (
ConfigManager) – AConfigManagerinstance that provides the compiler flags and sanitizer settings.verbose (
bool) – Show full build output instead of a progress spinner.
CLI usage:
# Configure Apache for fuzzing with ASan apatchy configure --mode fuzz --asan # Compile with bear for IDE support apatchy compile --bear # Link the harness apatchy link --engine libfuzzer
Example
from pathlib import Path from apatchy.managers.config_manager import ConfigManager from apatchy.managers.build_manager import BuildManager config = ConfigManager(build_mode="fuzz", asan=True) bm = BuildManager(Path("httpd-2.4.58"), config) bm.configure_httpd() bm.compile_httpd(bear=True) bm.build_harness(mode="libfuzzer")
- configure_httpd(extra_flags=None)[source]
Run
./configureon the vanilla root tree.Key flags and why they are needed:
--with-included-apr- build the bundled APR/APR-Util fromsrclib/rather than using a system-installed version. Avoids version mismatches and ensures instrumentation covers APR code.--disable-shared- static-only APR/APR-Util. Combined with--enable-mods-static=all, this makes libtool produce ELF binaries directly instead of wrapper shell scripts.--disable-util-dso- statically links APR-Util’s crypto, dbd, and dbm driver plugins intolibaprutil-1.a. Without it, APR-Util builds these as.sofiles loaded viadlopen().--disable-pie- SanCov instrumentation (used by LibFuzzer) inserts non-PICR_X86_64_32Srelocations. PIE binaries with these relocations fail to link.--with-crypto- enables OpenSSL support in APR-Util for mod_session_crypto. Without it, mod_session_crypto fails at runtime with “Your APR does not include SSL/EVP support”.--enable-pool-debug=yes- (ASan only) makesapr_palloc()callmalloc()directly so ASan can track individual pool allocations instead of sub-allocations from large blocks.
- compile_httpd(jobs=None, clean=True, bear=False)[source]
Compile Apache HTTPD with
make, optionally wrapped bybear.
- class apatchy.managers.dev_manager.DevManager(httpd_root)[source]
Scaffold, build, and manage isolated developer harness projects.
DevManagerlets you create self-contained fuzzing harness projects under thedev/directory. Each project gets its own directory with a templateharness.c, a seed input directory, and acompile_commands.jsonfor IDE auto-completion. Projects can then be compiled against the Apache build tree for LibFuzzer or standalone (stdin-based) execution.A project directory looks like:
dev/ my_harness/ harness.c # your fuzzing harness source fuzz-seeds/ # seed corpus sample.txt compile_commands.json # auto-generated for clangd fuzz_harness_libfuzzer # built binary (after build) fuzz_harness_coverage # coverage binary (after coverage build)
When building in standalone mode,
DevManagerautomatically creates an alternate Apache build tree compiled with plainclang(no instrumentation) to avoid runtime conflicts. This tree is cached and reused across builds.- Parameters:
httpd_root (
Path) – Path to the Apache HTTPD source directory that harnesses will link against.
CLI usage:
# Create a new project from the template apatchy dev init my_harness # Edit dev/my_harness/harness.c, then build apatchy dev build my_harness apatchy dev build my_harness --engine libfuzzer # List all projects and their build status apatchy dev list
Example
from pathlib import Path from apatchy.managers.dev_manager import DevManager dm = DevManager(Path("httpd-2.4.58")) # Create a new project from the template project_dir = dm.init_project("my_harness") # Edit dev/my_harness/harness.c, then build dm.build_project("my_harness", engine="libfuzzer") dm.build_project("my_harness", engine="standalone") # List all projects and their build status for p in dm.list_projects(): print(f"{p['name']} built: {p['built']}")
- init_project(name)[source]
Create a new dev harness project directory with template and compile_commands.json.
- class apatchy.managers.bug_manager.BugManager(bugs_dir=None, verbose=False)[source]
Discover, load, and orchestrate 1day bug reproductions.
BugManagermanages the full lifecycle of known (1day) Apache HTTPD bugs: listing what is available, setting up a reproduction environment, and running the actual triage. Each bug lives in its own subdirectory underbugs/and is described by abug.tomlmanifest. An optionalbug.pycan subclassBugto add custom setup, seed generation, or reproduction logic.A typical bug directory looks like:
bugs/ cve_xxxx_yyyyy/ bug.toml # manifest (id, version, modules, sanitizers, ...) bug.py # optional Bug subclass with custom logic httpd.conf # Apache config that triggers the bug gen_seed.py # optional seed generator script seeds/ # generated seed inputs (created by setup)
The setup flow performed by
setup()is:Download the vulnerable Apache version if not already present.
Configure and build Apache with the sanitizers listed in the manifest.
Link the fuzzing harnesses (LibFuzzer and standalone).
Run any bug-specific setup (e.g. creating files in DocumentRoot).
Generate seed inputs.
- Parameters:
Example
from apatchy.managers.bug_manager import BugManager bm = BugManager() # List all available bugs for bug in bm.list_bugs(): print(f"{bug['id']} {bug['description']}") # Set up a bug (download, build, seed) bm.setup("CVE-2022-23943") # Reproduce it by triaging the generated seeds bm.reproduce("CVE-2022-23943")
- get_bug_instance(cve_id)[source]
Load and return a
Buginstance for the given CVE.- Parameters:
cve_id (
str) – CVE identifier. Accepted formats:CVE-2022-23943,cve-2022-23943, orcve_2022_23943.- Raises:
FileNotFoundError – If no matching bug directory or
bug.tomlis found.- Return type:
- class apatchy.managers.fuzz_manager.FuzzManager(config_manager)[source]
Thin factory that selects and launches the appropriate fuzzing engine.
FuzzManageris the main entry point for starting a fuzzing run. It delegates all engine-specific logic toLibFuzzer, which inherits shared corpus preparation and environment setup fromBaseFuzzer.The workflow is:
Instantiate the engine class matching the
engineargument.Call
prepare_corpus()to create the seed and output directories (fuzz-seeds/,fuzz-output/), write a default seed if the seed directory is empty, and optionally expand a JSON grammar into concrete seed files.Call
start()on the engine instance, forwarding all engine-specific options.
- Parameters:
config_manager (
ConfigManager) – AConfigManagerinstance used to locate the httpd config file. The config path is passed to the harness via theFUZZ_CONFenvironment variable so Apache’s configuration pipeline is active during fuzzing.
CLI usage:
# Basic LibFuzzer run apatchy fuzz --engine libfuzzer # LibFuzzer with grammar seeds apatchy fuzz --engine libfuzzer --grammar grammars/http.json # Resume a previous session apatchy fuzz --engine libfuzzer --resume # Custom output directory apatchy fuzz --engine libfuzzer --output-dir my-output
Example
from apatchy.managers.config_manager import ConfigManager from apatchy.managers.fuzz_manager import FuzzManager config = ConfigManager() fm = FuzzManager(config) fm.start_fuzzer( harness_path=Path("fuzz_harness_libfuzzer"), engine="libfuzzer", )
- class apatchy.managers.toolchain_manager.ToolchainManager(verbose=False)[source]
Detect, install, and configure the external tools needed by apatchy.
ToolchainManagerscans for required dependencies (compilers, fuzzing tools, coverage utilities, libraries) and records their resolved paths in the toolchain config file. Other managers read this config to locate binaries likellvm-profdataandlibtool.The
check()method walks a registry ofToolchainToolplugins, each of which knows how to detect one or more binaries and report their version. Results are written to the toolchain config so that subsequent builds use the correct paths without relying onPATH.The
setup()method delegates to a tool plugin’s installer. Currently supported installers:llvm- locates or installs a specific LLVM version.libtool- installs GNU libtool (needed for Apache’s build system).
- Parameters:
verbose (
bool) – Show detailed output during dependency detection.
CLI usage:
# Check all dependencies and write the toolchain config apatchy setup check # Install / build specific tools apatchy setup llvm --llvm-version 18 apatchy setup libtool
Example
from apatchy.managers.toolchain_manager import ToolchainManager tm = ToolchainManager() # Scan and print all dependencies for dep in tm.check(): status = "OK" if dep.found else "MISSING" print(f"{dep.category} {dep.name} {status} {dep.path or dep.install_hint}") # Install LPM from source tm.setup("lpm")
- class apatchy.managers.report_manager.ReportManager(httpd_root, config_manager)[source]
Generate coverage reports, triage crashes, and profile fuzzing runs.
ReportManageris the post-fuzzing analysis hub. It takes the raw output from a fuzzing session and produces actionable reports:Coverage (
generate_coverage()) - Rebuilds Apache with LLVM source-based coverage instrumentation, replays the fuzzer corpus through the harness, merges the raw profiles withllvm-profdata, and generates an HTML report withllvm-cov. Dark-mode CSS is injected automatically. Optionally chains into introspection.Introspection (
generate_introspect()) - Uses theIntrospectorManagerto extract a call tree and per-function coverage from LLVM bitcode and profdata, producing a JSON file that can be viewed in an interactive web UI.Triage - Replays individual crash files or entire directories through the coverage harness to extract sanitizer reports:
triage_crash()- single filetriage_bulk()- all files in a directory (parallel)
Profiling (
generate_callgrind()) - Replays the corpus throughvalgrind --tool=callgrindto produce callgrind profiles for analysis with tools like KCachegrind.- Parameters:
httpd_root (
Path) – Path to the Apache HTTPD source directory.config_manager (
ConfigManager) – AConfigManagerinstance. For coverage, it should be created withbuild_mode="coverage".
CLI usage:
# Triage a single crash file apatchy triage fuzz-output/default/crashes/id:000000 # Triage all crashes in a directory apatchy triage --bulk fuzz-output/default/crashes/ # Replay numbered crash files as sequential requests apatchy triage --pipeline fuzz-output/ # Generate a coverage report from corpus apatchy coverage report --fuzzer-dir fuzz-output/ # Coverage with introspection chained in apatchy coverage report --fuzzer-dir fuzz-output/ --with-introspect # Generate introspection data with interactive viewer apatchy introspect --entry ap_process_request # Generate callgrind profiles apatchy profile callgrind --fuzzer-dir fuzz-output/
Example
from pathlib import Path from apatchy.managers.config_manager import ConfigManager from apatchy.managers.report_manager import ReportManager # Triage a crash config = ConfigManager(config_name="fuzz.conf") rm = ReportManager(Path("httpd-2.4.58"), config) rm.triage_crash("fuzz-output/default/crashes/id:000000", Path("fuzz_harness_coverage")) # Generate coverage cov_config = ConfigManager(build_mode="coverage") rm = ReportManager(Path("httpd-2.4.58"), cov_config) rm.generate_coverage(corpus_dir="fuzz-output/")
- generate_coverage(corpus_dir='fuzz-output', config_name='fuzz.conf', output_dir='coverage-report', harness_name=None, exclude_file=None, with_introspect=False, with_modules=False)[source]
Full coverage pipeline: build harness, replay corpus, merge, generate report.
- generate_introspect(entry, profdata_path=None, binary_path=None, bitcode_path=None, output_path='introspect.json', fuzzer_dir='fuzz-output', serve=True, port=9000)[source]
Merge call tree analysis with coverage data into a single JSON.
- generate_callgrind(corpus_dir='fuzz-output', config_name='fuzz.conf', output_dir='callgrind-out', harness_name=None)[source]
Replay corpus under callgrind and collect output for kcachegrind.
Automatically builds a dedicated
-profApache tree with debug symbols, no sanitizers, and no coverage instrumentation so that callgrind output is clean and all function names are visible.
- triage_crash(crash_file, harness_binary, no_color=False, suppress=None, timeout=30, is_libfuzzer=False)[source]
Replay crash_file through harness_binary and print the sanitizer output.
suppress is an optional path to a UBSan runtime suppression file (passed via
UBSAN_OPTIONS=suppressions=). timeout controls how long the harness is allowed to run before being killed.
- class apatchy.managers.introspector_manager.IntrospectorManager(httpd_root, work_dir)[source]
Compile Apache C sources into LLVM bitcode and link them for introspection.
IntrospectorManageris used byReportManagerto produce the LLVM bitcode that the introspection pipeline needs for call-tree extraction and per-function coverage analysis.The workflow has two phases:
Emit bitcode - Reads the
compile_commands.jsonfrom the coverage build tree (<httpd_root>-cov). If the file does not exist, it runsbearto trace a freshmakeand generate one. Each.centry is re-compiled with-emit-llvmto produce a.bcfile under<httpd_root>-cov/bitcode/. Test, support, and platform-specific directories are excluded automatically.Link bitcode - All emitted
.bcfiles are linked into a singlecombined.bcwithllvm-link. Before linking,llvm-nmis used to detect and skip files with duplicate global symbols to avoid link errors. The combined bitcode is consumed by the introspector C++ tool to build a call tree and byllvm-covto map coverage back to functions.
IntrospectorManageris not invoked directly from the CLI. It is called internally when the user runs:# Coverage report with introspection chained in apatchy coverage report --fuzzer-dir fuzz-output/ --with-introspect # Standalone introspection (auto-builds bitcode if missing) apatchy introspect ap_process_request_internal
- Parameters:
Example
from pathlib import Path from apatchy.managers.introspector_manager import IntrospectorManager im = IntrospectorManager( httpd_root=Path("httpd-2.4.58"), work_dir=Path("work"), ) # Emit per-file .bc and link into combined.bc im.build_bitcode(cc="clang-18")
Core
- class apatchy.core.process_runner.ProcessRunner(verbose=False)[source]
Execute shell commands with automatic logging.
- Parameters:
verbose (
bool) – When True,run_build()prints raw output to the terminal instead of rendering a Rich scrolling panel.
- static run_command(command, cwd=None, env=None, check=True, stdin=None, capture_output=True, stream=False, label='Building...')[source]
Run a shell command and log output.
- Parameters:
- Return type:
- class apatchy.core.downloader.Downloader[source]
Fetch and unpack Apache HTTPD, APR, APR-Util, and Expat.
- class apatchy.core.harness.HarnessBuilder(httpd_root, verbose=False)[source]
Compile and link a fuzzing harness against an Apache build tree.
- Parameters:
httpd_root (Path) – Root of the configured/compiled Apache HTTPD source tree.
verbose (bool)
- static resolve_harness(name)[source]
Resolve a harness name to a file path.
Resolution order: - Bundled: HARNESSES_DIR/<name>.c - Literal path: <name> as file path
- build(mode='standalone', cflags='', ldflags='', harness_name=None, cc=None, bear=False)[source]
Compile and link the harness for the given fuzzing engine.
- Parameters:
mode (str) – One of
"libfuzzer","standalone","coverage", or"profile".cflags (str) – Extra compiler flags.
ldflags (str) – Extra linker flags.
harness_name (str, optional) – Name of a bundled harness or path to a harness source file. Defaults to
"mod_fuzzy"if not provided.cc (str, optional) – Override the compiler (defaults to
COMPILERSlookup).bear (bool) – Wrap compilation with
bearforcompile_commands.json.
Toolchain
- class apatchy.core.toolchain.base.DepStatus(name, category, found, version='', path='', install_hint='')[source]
- class apatchy.core.toolchain.base.ToolchainTool(toolchain_dir, verbose=False)[source]
Base class for all toolchain tools. Subclasses must implement check().
- class apatchy.core.toolchain.simple.BinaryTool(name, category, install_hint, toolchain_dir, verbose=False, fallback=None, version_args=None, exists_only=False)[source]
- Parameters:
- class apatchy.core.toolchain.simple.PkgOrConfigTool(name, category, install_hint, toolchain_dir, config_binary, pkg_name, verbose=False)[source]
- Parameters:
- class apatchy.core.toolchain.simple.HeaderOrPkgTool(name, category, install_hint, toolchain_dir, header, pkg_name, verbose=False)[source]
- Parameters:
- class apatchy.core.toolchain.llvm.LlvmTool(toolchain_dir, verbose=False)[source]
Misc
- class apatchy.config.Config[source]
Central configuration store for the fuzzer.
All attributes are class-level - there is no need to create an instance. Paths that depend on the current working directory are resolved once at import time.
- class apatchy.bugs.base.Bug(bug_dir, manifest)[source]
Base class for 1day bug reproductions.
- Parameters:
- property suppress_file: str | None
Resolved path to the UBSan suppression file.
Looks in the bug directory first, then
configs/. ReturnsNoneif not specified or not found.
- setup()[source]
Extra setup beyond the standard download/configure/make.
Override for bugs that need special preparation (e.g. creating files in DocumentRoot, generating certificates). Called after Apache is built and harnesses are linked.
- Return type:
- generate_seeds()[source]
Generate seed inputs for this bug.
Override to create seeds programmatically. The default implementation runs
gen_seed.pyif it exists in the bug directory.- Return type:
- reproduce(harness_path, **kwargs)[source]
Reproduce the bug by triaging all seeds.
Override for custom reproduction logic (e.g. multi-step sequences, specific seed ordering). The default delegates to
ReportManager.
- configure_flags()[source]
Extra Apache configure flags needed for this bug.
Override if the bug needs flags beyond the defaults (e.g.
--with-cryptofor session_crypto bugs).
- class apatchy.compat.CompatEntry(id, description, versions, cflags=<factory>, ldflags=<factory>, configure_args=<factory>)[source]
A build compatibility fix applied to HTTPD versions matching a specifier.
The
versionsfield uses PEP 440 version specifiers (viapackaging.specifiers.SpecifierSet). Examples:"<=2.4.58" # all versions up to 2.4.58 ">=2.4.32,<=2.4.51" # versions 2.4.32 through 2.4.51 ">=2.4.0,<2.4.60" # inclusive start, exclusive end
- class apatchy.utils.build_tree.AlternateBuildTree(httpd_root, suffix)[source]
Creates and manages a copy of an Apache build tree with different compiler flags.
- ensure_build(cc, cflags, ldflags)[source]
Create the alternate tree (if needed) and rebuild Apache with the given flags.
Returns the path to the alternate httpd root.
- static rewrite_paths(tree, old_prefix, new_prefix)[source]
Replace hardcoded absolute paths in build-system files.
Apache’s
configurebakes the build directory into Makefiles, libtool scripts,.lafiles,config.status, etc. After copying the tree we must rewrite these somakeoperates on the copy rather than the original.
- static patch_build_flags(cc, cflags, ldflags, httpd_root)[source]
Patch CC, CFLAGS, and LDFLAGS across all build-system files.
The original build bakes compiler paths and sanitizer flags into config_vars.mk, apr_rules.mk, rules.mk, and libtool scripts throughout the tree (including srclib/apr and srclib/apr-util). We must patch ALL of them so the alternate build compiles and links cleanly with the desired flags.
LDFLAGS is patched in config files rather than passed on the make command line because command-line LDFLAGS clobbers the Makefile variable everywhere, which breaks libtool’s transitive dependency resolution (support utilities lose -lcrypt, -lm, etc.).
- class apatchy.utils.ui.UI[source]
Static helpers for formatted terminal output using Rich markup.