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>.
JSON Schema
Section titled “JSON Schema”Add the $schema field to get IDE autocomplete and inline validation:
{ "$schema": "https://warmhub.dev/schema/component-manifest.v1.json", "component": { ... }, ...}component.json
Section titled “component.json”{ "id": "com.warmhub.MyComponent", "name": "my-component", "version": "1.0.0", "description": "Optional description", "author": "Your Name", "tags": ["research", "ai"]}| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Reverse-DNS identifier (e.g., com.warmhub.MyComponent). Ownership key. |
name | string | Yes | Display name, typically kebab-case. |
version | string | Yes | Semver version string. |
description | string | No | Human-readable description. |
author | string | No | Author or organization. |
tags | string[] | No | Discovery 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.
manifest.json
Section titled “manifest.json”Top-level structure
Section titled “Top-level structure”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
Section titled “shapes”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" } }]| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Shape name. |
fields | object | Yes | Field 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.
credentials
Section titled “credentials”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" } ] }]| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Credential set name. |
description | string | No | What these credentials are for. |
requiredKeys | array | Yes | Keys that must be set. |
requiredKeys[].key | string | Yes | Key name. |
requiredKeys[].description | string | No | What the key is used for. |
After install, populate keys with:
wh credential set github-creds github_token --value ghp_...actions
Section titled “actions”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" } }]action.source
Section titled “action.source”Where the action code lives.
| Field | Type | Required | Description |
|---|---|---|---|
kind | "component-repo" | Yes | Clone the component’s GitHub repo. |
ref | string | No | Git ref to checkout (branch, tag, SHA). Defaults to default branch. |
checkoutMode | "shared" | "isolated" | No | Reserved in the schema. Current CLI/runtime paths do not apply different checkout behavior yet. |
auth | object | No | For private repos. |
auth.credentialSet | string | Yes (if auth) | Credential set containing the clone token. |
auth.key | string | Yes (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.
action.execution
Section titled “action.execution”How to run the action.
| Field | Type | Required | Description |
|---|---|---|---|
program | string | Yes | Program to execute (e.g., bash, node, python3). |
args | string[] | No | Arguments passed to the program. |
cwd | string | No | Working directory relative to the component repo root. |
action.input
Section titled “action.input”How the action receives its trigger payload.
| Field | Type | Required | Description |
|---|---|---|---|
mode | "stdin" | "json-file" | "env" | Yes | Delivery mode. |
path | string | No | File 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_PAYLOADenvironment variable.
If the action binds credentials or a WarmHub token, mode must be stdin.
action.env
Section titled “action.env”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.
action.runtime
Section titled “action.runtime”Optional runtime container configuration.
| Field | Type | Description |
|---|---|---|
tokenTtlMinutes | number | Time to live (TTL) for the injected WarmHub auth token. |
spriteName | string | Override the auto-generated container name. |
spritePool | string | Sprite pool to allocate from. |
reuseKey | string | Reserved in the schema. Current CLI/runtime paths do not use it yet. |
subscriptions
Section titled “subscriptions”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" }]| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Subscription name. Convention: <prefix>/<description>. |
trigger | object | Yes | What fires the subscription. |
action | string | Yes | Action id to invoke. Must match an action in the manifest. |
credentials | string[] | No | Credential sets to bind. Currently limited to one. |
Event trigger:
| Field | Type | Required | Description |
|---|---|---|---|
kind | "event" | Yes | |
shape | string | Yes | Shape to watch for changes. |
filter | object | No | Additional filter criteria. |
Cron trigger:
| Field | Type | Required | Description |
|---|---|---|---|
kind | "cron" | Yes | |
cronspec | string | Yes | Cron expression (e.g., "0 */6 * * *"). |
timezone | string | No | IANA 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 } }]| Field | Type | Required | Description |
|---|---|---|---|
kind | "thing" | Yes | Currently only "thing" is supported. |
shape | string | Yes | Shape name. Must be declared in shapes or be a built-in (ComponentConfig). |
name | string | Yes | Thing name within the shape. |
data | object | Yes | Field 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.
health
Section titled “health”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"] }}| Field | Type | Description |
|---|---|---|
requires.shapes | string[] | Reserved for future doctor checks. |
requires.things | string[] | Reserved for future doctor checks. |
requires.subscriptions | string[] | 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.
teardown
Section titled “teardown”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" }}| Field | Type | Description |
|---|---|---|
subscriptions.onDisable | "pause" | Action when component is disabled. |
subscriptions.onUninstall | "pause" | "delete" | Reserved for a future uninstall flow. |
Complete example
Section titled “Complete example”{ "$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" } }}Validation
Section titled “Validation”Run offline validation before installing:
wh component validate ./my-componentThis 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.jsonandmanifest.json