ODS Service Manifest Schema (v1)
This directory contains the JSON Schema for ODS extension manifests: service-manifest.v1.json. Manifests are YAML files (manifest.yaml) in each service under extensions/services/<service-id>/. The schema defines the structure used by the service registry, scripts/validate-manifests.sh, and ods config validate so that extensions work seamlessly for the ODS version you are on.
Schema version
Every manifest must set:
schema_version: ods.services.v1
The validator and compatibility checks use this to ensure they are reading a v1 manifest.
Root-level blocks
compatibility (optional)
Declares which ODS core versions this extension supports. Used by scripts/validate-manifests.sh and the installer summary to report compatible/incompatible extensions.
| Field | Type | Required | Description |
|---|---|---|---|
ods_min |
string | no | Minimum ODS version (semver, e.g. "2.0.0"). If set, the validator compares it to the core version from manifest.json. |
ods_max |
string | no | Maximum ODS version tested (semver). Optional; if set and core is newer, the extension may be marked incompatible or warned. |
Pattern for both: ^\d+\.\d+\.\d+$ (exactly three numeric segments). Pre-release suffixes (e.g. 2.0.0-beta) are not in the schema; the validator may treat them as the base version.
Example:
compatibility:
ods_min: "2.0.0"
# ods_max: "2.1.0" # optional
If compatibility is omitted, the validator reports "ok-no-metadata" (assumed compatible). All bundled extensions in this repo set ods_min: "2.0.0".
service (required for runtime)
Identifies the service and how the registry and compose resolver use it.
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Unique service id (lowercase, digits, hyphens). Used in SERVICE_PORTS, compose selection, and CLI. |
name |
string | yes | Human-readable name (e.g. "Open WebUI (Chat)"). |
aliases |
array | no | Shorthand ids for CLI (e.g. [webui, ui]). |
container_name |
string | no | Docker container name (e.g. ods-webui). |
container_uid |
integer | no | Numeric UID the container process runs as when compose does not declare user. The host agent uses this to prepare bind-mounted data directories. |
host_env |
string | no | Env var for host override. |
default_host |
string | no | Default hostname inside the stack. |
port |
integer | yes | Internal port (0–65535). |
external_port_env |
string | no | Env var for external port (e.g. WEBUI_PORT). |
external_port_default |
integer | no | Default external port; used by registry and health checks. |
health |
string | yes | Health path (e.g. /health, /). Use "" only for non-HTTP or one-shot services whose readiness is represented by container state/startup checks. |
type |
string | no | docker or host-systemd. |
startup_check |
boolean | no | When false, the host agent skips the post-install running-state poll and treats docker compose up's clean exit as success. Set this on one-shot CLI / setup-only extensions whose containers intentionally exit after init (e.g. aider). Default: true. |
startup_timeout |
integer | no | Seconds the host agent polls for the container to reach the running state before declaring install failed. Override the 15-second default for extensions with heavy initialization (postgres, clickhouse, JVM-based services). |
gpu_backends |
array | no | amd, nvidia, apple, all. Used for compose overlay selection. |
compose_file |
string | no | Relative path to compose fragment (e.g. compose.yaml). |
category |
string | no | core, recommended, or optional. Affects default enable/disable. |
depends_on |
array | no | List of service ids this service depends on. |
env_vars |
array | no | List of { key, required?, secret?, description?, default? } for documentation and validation. |
setup_hook |
string | no | Relative path to a setup script run during installation. |
The service registry (lib/service-registry.sh) builds SERVICE_PORTS, SERVICE_HEALTH, and related maps from these fields. The compose resolver includes only enabled services (compose file present) in the stack.
features (optional)
Used by the installer and dashboard to show feature toggles (e.g. "Voice", "Workflows", "RAG"). Each feature has an id, name, description, icon, category, requirements (services, VRAM, disk), and priority.
| Field (per feature) | Type | Description |
|---|---|---|
id |
string | Feature id (e.g. voice). |
name |
string | Display name. |
description |
string | Short description. |
icon |
string | Icon identifier. |
category |
string | Grouping (e.g. voice, creative). |
requirements |
object | services, services_any, vram_gb, disk_gb. |
priority |
integer | Sort order. |
gpu_backends |
array | Same as service. |
Schema allows additional properties on feature objects for future use.
Validation
- Schema validation: If the system has Python with
pyyamlandjsonschema,scripts/validate-manifests.shvalidates each manifest againstservice-manifest.v1.json. Missing modules result in a warning and only compatibility checks run. - Compatibility check: The script reads the core version from
manifest.jsonand compares it to each extension’scompatibility.ods_min/ods_max, then prints a summary (ok, incompatible, ok-no-metadata). - Running validation: From the repo root:
bash scripts/validate-manifests.sh. From an install:./ods-cli config validate(runs both env and manifest validation).
Example minimal manifest
schema_version: ods.services.v1
compatibility:
ods_min: "2.0.0"
service:
id: my-service
name: My Service
port: 9000
health: /health
type: docker
gpu_backends: [amd, nvidia]
category: optional
compose_file: compose.yaml
external_port_env: MY_SERVICE_PORT
external_port_default: 9000
See extensions/services/open-webui/manifest.yaml and the rest of extensions/services/*/manifest.yaml for full examples. The catalog is in ../CATALOG.md.