- docs
- Reference
- Reference
- Metadata
- Metadata: Integrations
Metadata: Integrations
The integrations field of metadata.json carries vendor-namespaced configuration for tools OCX does not model.
Integrations
Section titled “Integrations”integrations is an optional object mapping a namespace key to an arbitrary JSON payload (an object, array, string, number or null). OCX stores the payload and resolves its own ${...} tokens inside string values.
- Propagation: the whole map is carried through the dependency graph without interpreting, validating or merging it
{ "$schema": "https://ocx.sh/schemas/metadata/v1.json", "type": "bundle", "version": 1, "integrations": { "com.microsoft.vscode": { "extensions": ["rust-lang.rust-analyzer"], "settings": { "rust-analyzer.server.path": "${installPath}/bin/rust-analyzer" } }, "com.jetbrains": { "plugins": ["com.jetbrains.rust"] } }}- An absent
integrationsfield and an explicit{}are the same state. - Any package a composition admits may declare it, including a patch companion.
See Integrations for the design, including why OCX never merges two packages’ blocks.
Namespace Keys
Section titled “Namespace Keys”A namespace key follows the reverse-DNS convention (com.microsoft.vscode), which OCX does not enforce. An invalid key is rejected with exit 65, naming the key, wherever metadata.json is validated: ocx package create / push, and every later read.
| Rule | Rejects |
|---|---|
| Non-empty | "" |
| At most 128 bytes | a 129-byte key |
No control characters (C0, DEL and C1: U+0000-U+001F, U+007F, U+0080-U+009F) | "a\nb", a key containing a raw newline or tab |
No invisible characters: general category Cf and the Default_Ignorable_Code_Point property, since neither contains the other | a key containing U+202E (right-to-left override), U+200B (zero-width space), U+FEFF (byte-order mark) or U+3164 (Hangul filler) |
| No Unicode whitespace, not just ASCII spaces | "com.foo bar", a key containing U+00A0 (no-break space) |
- Everything else is legal:
vscode,VSCode,com.微软,a,x/yand123all pass. Case is preserved, soFooandfooare two distinct namespaces. - The
sh.ocx.prefix is reserved for first-party namespaces by convention only. No rule refuses a third-party key under it.
Size Caps
Section titled “Size Caps”| Cap | Limit |
|---|---|
| One namespace’s payload | 8 KiB |
The whole integrations map | 32 KiB |
- Measured as compact (whitespace-free) JSON, the per-package cap over the whole map including every key and its punctuation.
- A namespace over its own cap is rejected first, then the per-package cap.
- Enforced everywhere
metadata.jsonis validated, with exit 65. - Both caps are raise-only.
Interpolation
Section titled “Interpolation”A payload gets the same interpolation engine as env values, resolved inside every string in the payload at any depth. It never applies to object keys, numbers, booleans or null, and a ${…} outside the closed vocabulary is refused (see Interpolation Tokens).
- A payload that is not an object is legal too. A bare string is interpolated the same way, so
"integrations": { "com.example": "${installPath}/notes.txt" }is valid metadata. ${installPath}and${self.installPath}resolve to the declaring package’s own content directory, never the consuming root’s, even when the payload propagates through the dependency graph. See Aliases.${deps.NAME.installPath}resolves to a direct dependency’s content directory. A${deps.NAME}naming an undeclared dependency is invalid metadata, rejected at publish time.- All three install-path bodies accept the
:native/:posixmodifier. See Render Modifiers. $${installPath}escapes to the literal text${installPath}.- Every other
${...}token (${workspaceFolder}, VS Code’s${env:VAR}, devcontainer’s${localEnv:VAR}/${containerEnv:VAR}) is refused with exit 65, naming the token, byocx package create/pushand again at composition (ocx env,ocx package exec,ocx exec). - Read-only paths (
pull,install,inspect) echo an unrecognised token verbatim instead of refusing it. - Resolved for a package at
/home/u/.ocx/packages/.../content:toolPathbecomes/home/u/.ocx/packages/.../content/bin/tool,literalTokenbecomes${installPath}, andeditorVariablebecomes${workspaceFolder}/config. A bare"${workspaceFolder}/config"is refused at exit 65.
{ "integrations": { "com.example": { "toolPath": "${installPath}/bin/tool", "literalToken": "$${installPath}", "editorVariable": "$${workspaceFolder}/config" } }}