Extensions are self-contained JARs that Universe loads at startup from theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ohemilyy/universe/llms.txt
Use this file to discover all available pages before exploring further.
./extensions/ directory. They allow you to add new container runtimes, remote template storage backends, and custom template variables without touching the core orchestrator. Two production-ready extensions ship alongside Universe: runtime-docker and storage-s3.
How extensions load
On startup, Universe’s extension loader scans every.jar file inside ./extensions/. Each JAR must contain exactly one class that implements the Extension interface. Universe instantiates that class through Guice, injects its dependencies, and calls onLoad().
Extensions discovered at startup are loaded in arbitrary order. Do not rely on load ordering between extensions.
Extension lifecycle
Every extension implements three lifecycle hooks defined in theExtension interface:
| Hook | When it is called |
|---|---|
onLoad() | Once at startup, after Guice injection is complete. Register providers here. |
onUnload() | On graceful shutdown, or when extension reload is issued before re-loading. |
onReload() | When the extension reload console command is run. Typically calls onUnload() then onLoad(). |
Built-in extensions
Universe ships two extensions that cover the most common deployment needs:Docker Runtime
Run instances as isolated Docker containers with port bindings, volume mounts, and resource limits.
S3 Storage
Store and retrieve template zips from AWS S3 or any S3-compatible object store.
Building Extensions
Implement your own runtime, storage backend, or template variable provider.
Extension isolation rule
Extensions must only depend on:api and :extensions:extension-api. Depending on :app is prohibited — the app module contains orchestrator internals that are not part of the stable extension surface.
Use runtimeDownload for any external libraries your extension needs (AWS SDK, Docker Java, etc.) so that Universe can resolve them at runtime without bundling them into the fat JAR.
Key registries
Extensions interact with three Guice-injected registries. Inject whichever registries your extension needs and callregister() inside onLoad().
RuntimeRegistry
Holds all availableRuntimeProvider implementations keyed by a technology string (e.g., "docker", "screen", "tmux"). When a new instance is deployed, the wrapper looks up the provider whose key matches the "runtime" field in the instance’s configuration file.
TemplateStorageRegistry
Holds all availableTemplateStorageProvider implementations keyed by a storage string (e.g., "s3", "local"). When a template reference specifies "storage": "s3", the template manager delegates download and upload to the matching provider.
TemplateVariableRegistry
Aggregates custom placeholder-to-value mappings contributed by extensions. During instance deployment,collectVariables() is called across all registered providers and the results are merged with the built-in variables (%PORT%, %INSTANCE_ID%, %MASTER_IP%, etc.).