Tools system architecture
How the ./uis tools subsystem is wired and how to add a new optional CLI to the catalogue.
Looking for the user-facing list of what's available and how to install it? See reference/tools.md. This page is for contributors editing the system itself.
Two tiers
The container ships with a small built-in set and a larger installable on demand catalogue.
| Tier | Where it's defined | When it's available |
|---|---|---|
| Built-in | BUILTIN_TOOLS in provision-host/uis/lib/tool-installation.sh:22 | Baked into the image at build time. Always present. |
| Installable | One install-<id>.sh script per tool under provision-host/uis/tools/ | Added on demand by ./uis tools install <id>. Lives in the container's writable layer; lost on docker rm. |
Built-ins are kept intentionally tiny (kubectl k9s helm ansible) — anything every UIS deploy needs. Everything else is opt-in to keep the image small.
Discovery
get_all_tool_ids() in tool-installation.sh:26 is the single entry point that the runtime CLI and the docs generator both use:
- Emit each ID in
BUILTIN_TOOLS. - Glob
provision-host/uis/tools/install-*.shand readTOOL_ID=from each script header.
That's it — there is no manifest file. Adding an install-<id>.sh with the right header makes the tool show up in ./uis tools list automatically.
The install-script contract
Every installable tool is a single bash script under provision-host/uis/tools/ named install-<tool-id>.sh. It has two parts: a metadata header and two functions.
Metadata header
TOOL_ID="opentofu"
TOOL_NAME="OpenTofu"
TOOL_DESCRIPTION="Open-source infrastructure-as-code (Terraform fork)"
TOOL_CATEGORY="CLOUD_TOOLS"
TOOL_CHECK_COMMAND="command -v tofu"
TOOL_SIZE="~30MB"
TOOL_WEBSITE="https://opentofu.org/"
| Field | Required | Used by |
|---|---|---|
TOOL_ID | yes | Discovery, dispatch (./uis tools install <id>) |
TOOL_NAME | yes | ./uis tools list display, docs generation |
TOOL_DESCRIPTION | yes | ./uis tools list display, docs generation |
TOOL_CATEGORY | yes | Grouping (current categories: BUILTIN, CLOUD_TOOLS) |
TOOL_CHECK_COMMAND | yes | is_tool_installed — must succeed only when the tool is actually installed |
TOOL_SIZE | recommended | Sets user expectations on download size |
TOOL_WEBSITE | recommended | Upstream link in docs |
The header is parsed by line-prefix matching (get_tool_value in tool-installation.sh:98), so keep each metadata line as a simple KEY="value" assignment — no shell expansion, no multi-line strings.
Required functions
do_install() {
# Install the tool. Should be idempotent — running it twice must not fail.
# Runs as root inside the container ($EUID -eq 0); the sudo branch is for
# tooling that runs the script outside the container.
...
}
do_uninstall() {
# Reverse do_install. Used by the future ./uis tools uninstall flow.
...
}
Look at provision-host/uis/tools/install-opentofu.sh as the canonical minimal example — it delegates to the upstream installer, handles the root/sudo split, and includes a matching do_uninstall.
install_tool() in tool-installation.sh:184 sources the script in a subshell and calls do_install, then re-runs is_tool_installed to verify. If TOOL_CHECK_COMMAND returns non-zero after a successful install, the install is reported as failed — get the check command right.
How tools.json is generated
reference/tools.md is hand-maintained, but the canonical machine-readable index is website/src/data/tools.json, regenerated by provision-host/uis/manage/uis-docs.sh:329 (generate_tools_json). It walks the same install-*.sh files and emits a JSON array of { id, name, description, category, size, website, check_command }. Run provision-host/uis/manage/uis-docs.sh after adding or changing a tool to refresh it.
Adding a new installable tool
- Create
provision-host/uis/tools/install-<tool-id>.shmodelled oninstall-opentofu.sh(single-file delegation to an upstream installer is the preferred shape — keep it small). - Fill in the metadata header.
TOOL_IDmust match the filename suffix. - Implement
do_install(idempotent) anddo_uninstall. - Make sure
TOOL_CHECK_COMMANDsucceeds only after install —command -v <binary>is usually enough. - Mark it executable:
chmod +x install-<tool-id>.sh. - Run
./uis buildand verify in a fresh container:./uis tools list # new tool shows ❌ Not installed
./uis tools install <tool-id> # do_install runs
./uis tools list # flips to ✅ Installed
./uis exec <binary> --version # smoke test - Run
provision-host/uis/manage/uis-docs.shto regeneratewebsite/src/data/tools.json. - Add a row to the user-facing table in
website/docs/reference/tools.md(and the "When you need a specific tool" section if it ties to a workflow).
Related documentation
- reference/tools.md — User-facing inventory and install commands
- Provision Host Overview — Where the container fits in the stack
- UIS CLI Reference —
./uis toolscommand surface