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 sections are required but may be empty arrays or objects.

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

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

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.

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. Created at install time; the user must populate the keys afterward.

"credentials": [
{
"name": "github-creds",
"description": "GitHub API access for fetching repos",
"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.
requiredKeys[].keystringYesKey name.
requiredKeys[].descriptionstringNoWhat the key is used for.

After install, populate keys with:

Terminal window
wh credential set github-creds github_token --value ghp_...

Executable actions that subscriptions invoke. The only supported kind today is sprite, which is the manifest value for WarmHub’s current managed action runtime.

"actions": [
{
"id": "process-paper",
"kind": "sprite",
"source": {
"kind": "component-repo",
"auth": {
"credentialSet": "github-creds",
"key": "github_token"
}
},
"execution": {
"program": "bash",
"args": ["actions/process/run.sh"]
},
"input": { "mode": "stdin" },
"env": [
{ "to": "WH_AUTH", "from": "warmhubToken" },
{
"to": "API_KEY",
"fromCredential": { "set": "github-creds", "key": "github_token" }
}
],
"runtime": {
"tokenTtlMinutes": 30,
"spriteName": "paper-processor"
}
}
]

Where the action code lives.

FieldTypeRequiredDescription
kind"component-repo"YesClone the component’s GitHub repo.
refstringNoGit ref to checkout (branch, tag, SHA). Defaults to default branch.
checkoutMode"shared" | "isolated"NoReserved in the schema. Current CLI/runtime paths do not apply different checkout behavior yet.
authobjectNoFor private repos.
auth.credentialSetstringYes (if auth)Credential set containing the clone token.
auth.keystringYes (if auth)Key within the credential set.

Private repos: When source.auth is set, the CLI generates an authenticated clone wrapper. The runtime’s built-in clone is disabled (--github-repo none), and the action script handles cloning with the credential.

How to run the action.

FieldTypeRequiredDescription
programstringYesProgram to execute (e.g., bash, node, python3).
argsstring[]NoArguments passed to the program.
cwdstringNoWorking directory relative to the component repo root.

How the action receives its trigger payload.

FieldTypeRequiredDescription
mode"stdin" | "json-file" | "env"YesDelivery mode.
pathstringNoFile path for json-file mode.
  • stdin: Payload piped as JSON to the program’s stdin.
  • json-file: Payload written to a file; the file path is exposed as WARMHUB_ACTION_INPUT_PATH.
  • env: Payload JSON is exposed in a single WARMHUB_ACTION_PAYLOAD environment variable.

If the action binds credentials or a WarmHub token, mode must be stdin.

Environment variables injected into the action runtime.

Each entry maps a source to a target env var name. Two source types:

// From a well-known value
{ "to": "WH_AUTH", "from": "warmhubToken" }
// From a credential set key
{ "to": "API_KEY", "fromCredential": { "set": "my-creds", "key": "api_key" } }

Reserved names that cannot be used as to: WH_TOKEN, WH_TARGET_REPO, WH_COMPONENT_REPO, WH_COMPONENT_REF, WH_COMPONENT_ID, PATH, HOME, USER, SHELL.

Optional runtime container configuration.

FieldTypeDescription
tokenTtlMinutesnumberTime to live (TTL) for the injected WarmHub auth token.
spriteNamestringOverride the auto-generated container name.
spritePoolstringSprite pool to allocate from.
reuseKeystringReserved in the schema. Current CLI/runtime paths do not use it yet.

Subscriptions that trigger actions on events or schedules.

"subscriptions": [
{
"name": "rk/on-paper-add",
"trigger": { "kind": "event", "shape": "Paper" },
"action": "process-paper",
"credentials": ["github-creds"]
},
{
"name": "rk/daily-sync",
"trigger": { "kind": "cron", "cronspec": "0 6 * * *", "timezone": "America/New_York" },
"action": "sync-handler"
}
]
FieldTypeRequiredDescription
namestringYesSubscription name. Convention: <prefix>/<description>.
triggerobjectYesWhat fires the subscription.
actionstringYesAction id to invoke. Must match an action in the manifest.
credentialsstring[]NoCredential sets to bind. Currently limited to one.

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" }]
}
],
"actions": [
{
"id": "echo-handler",
"kind": "sprite",
"source": { "kind": "component-repo" },
"execution": { "program": "bash", "args": ["actions/echo/run.sh"] },
"input": { "mode": "stdin" },
"env": [
{ "to": "ECHO_AUTH_TOKEN", "from": "warmhubToken" },
{ "to": "ECHO_API_KEY", "fromCredential": { "set": "echo-api-creds", "key": "api_key" } }
]
}
],
"subscriptions": [
{
"name": "echo/process-input",
"trigger": { "kind": "event", "shape": "EchoInput" },
"action": "echo-handler",
"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 actions, env references valid credentials, seeds reference valid shapes)
  • Duplicate names within sections
  • Reserved env variable names
  • Local file existence (action scripts, cwd directories)
  • Component ID format (reverse-DNS)
  • Consistency between component.json and manifest.json