Skip to content

Manifest Reference

Every component package contains two files in a warmhub/ directory:

  • component.json — Component identity (id, name, version)
  • manifest.json — Declarative resource definitions

Both are validated at install time. You can also validate offline with wh component validate <path>.

Add the $schema field to get IDE autocomplete and inline validation:

{
"$schema": "https://warmhub.dev/schema/component-manifest.v1.json",
"component": { ... },
...
}
{
"id": "com.warmhub.MyComponent",
"name": "my-component",
"version": "1.0.0",
"description": "Optional description",
"author": "Your Name",
"tags": ["research", "ai"]
}
FieldTypeRequiredDescription
idstringYesReverse-DNS identifier (e.g., com.warmhub.MyComponent). Ownership key.
namestringYesDisplay name, typically kebab-case.
versionstringYesSemver version string.
descriptionstringNoHuman-readable description.
authorstringNoAuthor or organization.
tagsstring[]NoDiscovery tags.

The id must match the pattern: one or more lowercase domain segments, followed by one or more PascalCase segments. Examples: com.warmhub.ResearchKnowledge, io.example.MyTool.

All top-level sections except actions are required, but they may be empty arrays or objects. actions is a deprecated legacy field — the CLI still accepts and validates it for older manifests, but install and reconcile ignore it. New components should omit it.

{
"$schema": "https://warmhub.dev/schema/component-manifest.v1.json",
"component": {
"id": "com.warmhub.MyComponent",
"name": "my-component",
"version": "1.0.0"
},
"shapes": [],
"credentials": [],
"subscriptions": [],
"seeds": [],
"health": {},
"teardown": {}
}

The component section must match the corresponding fields in component.json.

Declare the WarmHub runtime scopes the component’s minted runtime token needs at execution time. This is used only for registered-component setup flows that mint tokens; local installs can still include the field for portability.

"runtimeAccess": {
"reads": ["Paper", "ComponentConfig"],
"writes": ["Consensus"]
}
FieldTypeRequiredDescription
readsstring[]YesShape names the runtime token may read.
writesstring[]YesShape names the runtime token may write.

Rules:

  • Every shape must be declared in shapes[] or be a known built-in (ComponentInstall, ComponentConfig).
  • A shape may appear in both reads and writes when the runtime needs read-before-write behavior, such as revising existing component-owned assertions.
  • Omitting runtimeAccess is equivalent to no minted runtime token.

shapes, credentials, and subscriptions support a per-resource provisioning field:

  • manifest — default. The normal manifest installer creates the resource in the target repo.
  • setup — the registered component’s setup endpoint creates the resource. When minted tokens are enabled, WarmHub includes a setup token the endpoint can use for those writes.

This allows a manifest to mix installer-created and setup-created resources in one package.

Shapes the component needs in the target repo. Created at install time if they don’t exist.

"shapes": [
{
"name": "Paper",
"fields": { "title": "string", "url": "string", "score": "number" }
}
]
FieldTypeRequiredDescription
namestringYesShape name.
fieldsobjectYesField definitions mapping names to WarmHub type descriptors.
descriptionstringNoHuman-readable description of the shape.
provisioning"manifest" | "setup"NoWhich side creates the shape. Defaults to manifest.

Field types: string, number, boolean, wref (a WarmHub reference string such as Shape/name or Shape/name@v3), arrays, nested objects. See Shapes for details.

Credential sets the component needs for external API access. With the default provisioning: "manifest", the installer creates the set and the user populates its required keys afterward. With provisioning: "setup", the registered component’s setup endpoint creates and fills the set.

"credentials": [
{
"name": "github-creds-<org-name>-<repo-name>",
"description": "GitHub API access for fetching repos",
"provisioning": "manifest",
"requiredKeys": [
{ "key": "github_token", "description": "Personal access token with repo scope" }
]
}
]
FieldTypeRequiredDescription
namestringYesCredential set name.
descriptionstringNoWhat these credentials are for.
requiredKeysarrayYesKeys that must be set.
provisioning"manifest" | "setup"NoWhich side creates the credential set. Defaults to manifest.
requiredKeys[].keystringYesKey name.
requiredKeys[].descriptionstringNoWhat the key is used for.

Credential names may include the template tokens:

  • <org-name>
  • <repo-name>

These are resolved at install/setup time. For example, veritas-webhook-<org-name>-<repo-name> becomes veritas-webhook-acme-world.

After install, populate keys with:

Terminal window
wh credential set github-creds-acme-world github_token --value ghp_... --repo acme/world

Subscriptions that trigger webhooks on events or schedules.

"subscriptions": [
{
"name": "rk/on-paper-add",
"trigger": { "kind": "event", "shape": "Paper" },
"kind": "webhook",
"webhookUrl": "https://handler.example.com/on-paper",
"credentials": ["github-creds-<org-name>-<repo-name>"]
},
{
"name": "rk/daily-sync",
"trigger": { "kind": "cron", "cronspec": "0 6 * * *", "timezone": "America/New_York" },
"kind": "webhook",
"webhookUrl": "https://handler.example.com/daily-sync"
}
]
FieldTypeRequiredDescription
namestringYesSubscription name. Convention: <prefix>/<description>.
triggerobjectYesWhat fires the subscription.
kind"webhook" | "cron"NoOptional advisory field retained for readability. The CLI derives the effective subscription kind from trigger.kind and ignores this field at install time.
webhookUrlstringYesDestination URL for deliveries.
credentialsstring[]NoCredential sets to bind. Currently limited to one.
fallbackWebhookUrlstringNoOptional fallback delivery target.
provisioning"manifest" | "setup"NoWhich side creates the subscription. Defaults to manifest.

Event trigger:

FieldTypeRequiredDescription
kind"event"Yes
shapestringYesShape to watch for changes.
filterobjectNoAdditional filter criteria.

Cron trigger:

FieldTypeRequiredDescription
kind"cron"Yes
cronspecstringYesCron expression (e.g., "0 */6 * * *").
timezonestringNoIANA timezone. Defaults to UTC.

Initial data created at install time.

"seeds": [
{
"kind": "thing",
"shape": "ComponentConfig",
"name": "my-component",
"data": { "version": "1.0.0", "enabled": true }
}
]
FieldTypeRequiredDescription
kind"thing"YesCurrently only "thing" is supported.
shapestringYesShape name. Must be declared in shapes or be a built-in (ComponentConfig).
namestringYesThing name within the shape.
dataobjectYesField values. Must conform to the shape’s field definitions.

ComponentConfig is a built-in shared shape — you can seed things into it without declaring it in shapes.

Configuration reserved for richer wh component doctor diagnostics in a future CLI version.

"health": {
"requires": {
"shapes": ["Paper", "PaperSummary"],
"things": ["ComponentConfig/my-component"],
"subscriptions": ["rk/on-paper-add"]
}
}
FieldTypeDescription
requires.shapesstring[]Reserved for future doctor checks.
requires.thingsstring[]Reserved for future doctor checks.
requires.subscriptionsstring[]Reserved for future doctor checks.

All fields are optional. The current CLI accepts this section in the manifest schema, but wh component doctor does not read health.requires.* yet. Today, doctor checks the shapes, subscriptions, credentials, and seeds declared elsewhere in the manifest.

Behavior when the component is disabled. The current CLI teardown flow reads subscriptions.onDisable; onUninstall is schema-valid but not executed yet.

"teardown": {
"subscriptions": {
"onDisable": "pause",
"onUninstall": "delete"
}
}
FieldTypeDescription
subscriptions.onDisable"pause"Action when component is disabled.
subscriptions.onUninstall"pause" | "delete"Reserved for a future uninstall flow.
{
"$schema": "https://warmhub.dev/schema/component-manifest.v1.json",
"component": {
"id": "com.warmhub.E2eEcho",
"name": "e2e-echo",
"version": "1.0.0"
},
"shapes": [
{ "name": "EchoInput", "fields": { "message": "string", "priority": "number" } },
{ "name": "EchoOutput", "fields": { "echo": "string", "processedAt": "string" } }
],
"credentials": [
{
"name": "echo-api-creds",
"description": "API credentials for echo service",
"requiredKeys": [{ "key": "api_key", "description": "Echo API key" }]
}
],
"subscriptions": [
{
"name": "echo/process-input",
"trigger": { "kind": "event", "shape": "EchoInput" },
"kind": "webhook",
"webhookUrl": "https://echo.example.com/process",
"credentials": ["echo-api-creds"]
}
],
"seeds": [
{
"kind": "thing",
"shape": "EchoInput",
"name": "welcome",
"data": { "message": "Hello from e2e-echo component", "priority": 1 }
}
],
"health": {},
"teardown": { "subscriptions": { "onDisable": "pause" } }
}

Run offline validation before installing:

Terminal window
wh component validate ./my-component

This checks:

  • JSON syntax and required fields
  • Cross-references (subscriptions reference valid credentials, seeds reference valid shapes)
  • Duplicate names within sections
  • Subscription trigger and webhook validation
  • Component ID format (reverse-DNS)
  • Consistency between component.json and manifest.json