Details of all options available in config.json
When adding a new app to the Companion App Store, you need to create a config.json file in the app’s folder. This file contains all the information needed to run the app. Below you can find all the options available in the config.json file.
Three parts of the manifest end up as environment variables in the running container: form_fields ask the user for values at install time, hub_integration.mcp_client injects Hub’s MCP endpoint, and hub_integration.inference maps Hub’s model settings onto the variable names your app expects:
flowchart TD
C["config.json"] -->|"form_fields"| F["Install form,<br/>validated per type"]
C -->|"hub_integration"| HI["Hub-provided values<br/>mcp_client: HUB_URL, HUB_MCP_URL,<br/>HUB_MCP_API_KEY, HUB_WAKE_SECRET<br/>inference: llm_base_url, chat_model, …<br/>as your own names"]
F -->|"one env_variable<br/>per field"| E["App environment"]
HI --> E
E -->|"${VARIABLE} references"| D["docker-compose.json"]
D --> R["Running app"]| Option | Description | Example value | Required |
|---|---|---|---|
| name | Name of the app | Nextcloud | yes |
| id | This should be the same name as the folder | nextcloud | yes |
| available | If set to false, the app will not be available in the app store | true | yes |
| short_desc | Short description of the app | Nextcloud is a suite of client-server software for creating and using file hosting services. | yes |
| author | Name or URL of the app’s author or maintainer | https://nextcloud.com | yes |
| port | Port used by the app. This port will be exposed to the host. Omit it for apps with no_gui. | 8100 | yes, unless no_gui |
| categories | One or more categories for the app. Valid values: agents, ai, automation, books, companion-intelligence, data, development, featured, finance, gaming, media, mcp, music, network, photography, security, social, utilities | [“utilities”, “network”] | yes |
| description | Long description of the app. The store listing also reads metadata/description.md. | Nextcloud is a suite of client-server software for creating and using file hosting services. | no |
| cihub_app_version | App manifest version. Defaults to 1 when omitted. Increment it when you change compose or config | 10 | no |
| cihub_version | Older spelling of cihub_app_version. Hub still reads it. The Runtipi-era tipi_version is no longer read | 1 | no |
| version | The actual version of the app (not the Companion Hub version) | 1.25.1 | yes |
| source | Link for git repository | https://github.com/nextcloud/docker | yes |
| website | Link to the official website | https://nextcloud.com | no |
| exposable | If set to true, the app will allow the user to expose it via a domain name. Defaults to true. | true | no |
| force_expose | If set to true, the app will require a domain name. | true | no |
| generate_vapid_keys | If set to true, the app will generate VAPID keys for web push notifications. VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY will be available as environment variables | true | no |
| url_suffix | If set, the app will be accessible at https://<your-domain>/<url_suffix> | my-app | no |
| https | If set to true, the app will be accessible via https only. | true | no |
| no_gui | Set to true for apps with no GUI. Open button will be hidden | true | no |
| supported_architectures | If the app is only available for a specific architecture, you can specify it here. If not given, app will be available for all architectures | [“arm64”, “amd64”] | yes |
| uid, gid | These parameters allow you to give a specific set of permission for the app’s data folder. Companion Hub will automatically chown the data directory with the provided gid and uid. Both options need to be specified in order to apply | 1000 | no |
| form_fields | Form fields allow you to prompt the user for input during the install, like a username or a password | See below | no |
| dynamic | Runtipi-era flag. Hub does not read it. Use dynamic_config, which defaults to true. See Dynamic Compose | true | no |
| deprecated | If the app is deprecated it won’t exist in the app store and it will notify users that is no longer maintained. | false | no |
| min_hub_version | Minimum Companion Hub version for this app. Hub records it but does not check it before installing | 0.2.60 | no |
| min_cihub_version | Older spelling of min_hub_version. Hub still reads it. The Runtipi-era min_tipi_version is no longer read | 0.2.60 | no |
| dynamic_config | Use docker-compose.json dynamic compose. Defaults to true and is the only format the store ships | true | no |
| hub_integration | Opt-in Hub features: MCP client, inference variable mapping — see below | { "mcp_client": true } | no |
| created_at | The date the app was created. You can use new Date().getTime() in your browser console to get the current timestamp | 1724134938430 | no |
| updated_at | The date the app was last updated. You can use new Date().getTime() in your browser console to get the current timestamp | 1724134938430 | no |
| replaces | Names of popular proprietary products this app replaces. Store search and the Alternatives view read it | [“Google Drive”, “Dropbox”] | no |
| screenshots | Store-listing gallery images, as absolute URLs or relative paths | [“metadata/screenshots/1.png”] | no |
| demo_video | Store-listing demo video, as an absolute URL or a relative path | metadata/media/demo.mp4 | no |
| force_pull | If set to true, Hub pulls the app’s images again on every install, start, and restart | true | no |
| runtime_platform | Pins every service in the app to one Docker platform, such as linux/amd64 on an Apple Silicon Hub | linux/amd64 | no |
| gpu_requirements | Accelerator the app needs. Hub shows it on the app’s details page. type is cuda, rocm, or oneapi; the last two are Linux only and need host_devices | { "type": "cuda", "optional": false, "host_platforms": ["linux"] } | no |
| mcp | Marketplace listing for a Model Context Protocol server: transport (stdio or http), command, args, env, and a tool manifest | See the marketplace docs | no |
| privacy | The developer’s data-handling declaration: declared_by, declared_at, and a collects list. An absent block means undeclared, not “collects nothing” | See the marketplace docs | no |
Sometimes an app requires additional information to run, such as a username or a password. Use the form_fields property in the config.json file to request that information. Here’s an example:
{
"form_fields": [
{
"type": "text",
"label": "Username",
"max": 50,
"min": 3,
"required": true,
"env_variable": "NEXTCLOUD_ADMIN_USER"
},
{
"type": "password",
"label": "Password",
"max": 50,
"min": 3,
"required": true,
"env_variable": "NEXTCLOUD_ADMIN_PASSWORD"
}
]
}You can choose between different types of fields. The app will automatically validate the user input before submitting.
| Type | Description | Example value |
|---|---|---|
| text | A string of text | username |
| password | Will be hidden on typing | password |
| An email address | test@example.org | |
| number | Any number | 123 |
| fqdn | Fully qualified domain name | example.org |
| ip | Any valid IPv4 address | 192.168.2.100 |
| fqdnip | Combination between IPv4 and FQDN | 192.168.2.100 or example.org |
| url | A URL | https://example.org/path |
| app_base_url | The address people use to reach the app. The install dialog fills it with the URL Hub resolved for the app, and Hub keeps it in step with the app’s exposure settings unless you typed your own | https://nextcloud-mydevice.example.org |
| random | Generate a random value for the user | 2e318419a49b70ad93766a5d6eb54d9ebbcceaeadd57c5f6897dbbe10afbc880 |
| boolean | A checkbox | true or false |
Here is a table of the available form_field properties:
| Name | Description | Example value | Required |
|---|---|---|---|
| type | The type of the form field to use, see above. | text | ✅ |
| label | The label to show the user. | Nextcloud Username | ✅ |
| hint | A small hint to show the user. | The username you want to use for nextcloud | ❌ |
| placeholder | A placeholder for the form field | user | ❌ |
| default | Add a default value, used only if the required option is set to false | user | ❌ |
| regex | Use a regex pattern to verify the user input | ^[0-9]+\.[0-9]+\.[0-9]+$ | ❌ |
| pattern_error | The error to show when the regex pattern validation fails | Invalid username | ❌ |
| min | The minimum length for a text or password input | 5 | ❌ |
| max | The maximum length for a text or password input | 100 | ❌ |
| required | Whether the form field is required or not | true | ✅ |
| env_variable | The name of the variable you’ll use in your docker-compose.yml file. | NEXTCLOUD_USERNAME | ✅ |
| options | Options for multi-select | See below | ❌ |
| encoding | Used only in addition to random type. Specify the random value encoding (base64 or hex) | base64 | ❌ |
| alias_env_variables | Used with app_base_url. Also writes the resolved value to these environment variables | [“APP_URL_ALIAS”] | ❌ |
| trailing_slash | Used with app_base_url. Adds a trailing slash to the values written to the aliases | true | ❌ |
When you use the random field type for a password or secret, the min value
determines the generated string length. If min is omitted, a default length
of 32 characters is used.
Using options in form fields
You can create a form field with options like this in your config.json. It will be rendered as a multi-select dropdown in the UI.
label is what will be shown to the user and value is the actual value the environment variable will be set to when the corresponding option is selected.
{
"label": "Select your favorite fruits",
"type": "text",
"required": true,
"options": [
{ "label": "Apple", "value": "apple" },
{ "label": "Banana", "value": "banana" },
{ "label": "Orange", "value": "orange" }
],
"env_variable": "fruits"
}Use options only when there are only specific pre-defined values for the
field. If a user might want to use a custom value, use a normal text field and
provide common examples in the label.
Hub integration (hub_integration)
Apps can opt in to Hub-provided environment variables and services.
MCP client
First-party agent apps ci-openclaw and ci-hermes ship with hub_integration.mcp_client: true by default so Hub MCP is wired automatically on install. Other agent apps can opt in the same way:
{
"hub_integration": {
"mcp_client": true,
"wake_endpoint": "/hooks/hub-wake",
"wake_port": 3000,
"sse_events": false
}
}wake_endpoint defaults to /hooks/hub-wake. ci-openclaw sets it to /hooks/wake and sets wake_port to its setup and proxy port, 18789. Hermes declares no wake registration.
When enabled, Hub injects HUB_URL, HUB_MCP_URL, HUB_MCP_API_KEY, and HUB_WAKE_SECRET into the app’s environment. HUB_MCP_API_KEY is a key Hub creates for that app alone and revokes when you uninstall it.
An app with mcp_client: true publishes its host port on 127.0.0.1 only, because it holds a key that can drive the Hub. Reach it from another device through Private VPN or the public web.
Inference variables
AI apps map standardized Hub inference keys to their own env variable names:
{
"hub_integration": {
"inference": {
"llm_base_url": "LLM_API_BASE",
"llm_api_key": "LLM_API_KEY",
"chat_model": "LLM_DEFAULT_CHAT_MODEL",
"embedding_model": "LLM_DEFAULT_EMBEDDING_MODEL",
"vision_model": "LLM_DEFAULT_VISION_MODEL",
"ollama_host": "OLLAMA_HOST"
}
}
}| Hub key | Hub resolves to | Description |
|---|---|---|
llm_base_url | OpenAI-compatible base URL | The engine’s /v1, this Hub’s pool proxy, or a cloud provider |
llm_api_key | API key | A placeholder such as "ollama" unless the app calls the engine directly |
chat_model | Chat model ID | From preferences or hardware recommendations |
embedding_model | Embedding model ID | From preferences or recommendations |
vision_model | Vision model ID | From preferences or recommendations |
ollama_host | Native Ollama URL | Direct Ollama API (not OpenAI-compatible) |
ollama_embed_host | Native Ollama URL for embeddings | The server embedding_base_url names, without /v1. Kept for older manifests |
embedding_base_url | Embedding base URL | OpenAI-compatible /v1 URL of the engine that embeds for the app, or this Hub’s pool proxy |
utility_model | Utility model ID | A smaller installed model for background calls, otherwise the chat model |
num_ctx | Context window in tokens | Sized to the model and this machine’s memory |
See AI & Inference for resolution order and setup.
Other options
| Key | What it does |
|---|---|
inference_provider | For apps with a provider switch. Give it { "env": "APP_LLM_PROVIDER", "ollama": "ollama", "openai_compatible": "openai" }. Hub writes the ollama value when Ollama is the chat backend, and the openai_compatible value for any other saved engine (vLLM, Lemonade, or oMLX). A cloud provider on its own doesn’t switch it. |
llm_base_url_strip_v1 | Set to true to remove a trailing /v1 from the resolved llm_base_url, for apps that expect a bare origin. |
oidc | { "issuer_env": "CI_OIDC_ISSUER", "issuer_path": "/api/auth" }. Hub writes the paired CI Account’s identity-provider address into issuer_env, with issuer_path appended if you give one. |
memory | Connects an app to Companion Memory. A consumer, such as an agent, names the variables it reads with url_env and token_env, and Hub fills them when you connect the app. url_style is origin (the default) or api_base. Companion Memory itself declares provider with its service and port. |
readiness | { "service": "app-gateway", "port": 8642, "path": "/health", "bearer_env": "APP_SEED" }. While the app runs, Hub probes this endpoint and shows failing checks in the app’s runtime health. The service must be a service in the app’s own compose file. bearer_env names a variable in the app’s generated environment whose value Hub sends as a bearer token. |
edge_auth | { "default": true } switches the install form’s authentication toggle on by default, for apps with no login of their own. It can turn authentication on, never off. An app that sets it also publishes its host port on 127.0.0.1 only. |