Skip to content

Manifest

capability.yaml structure, every field, validation rules, and auto-discovery behavior.

A capability is a directory with a capability.yaml at the root. The manifest declares the capability’s identity and points at its components; everything else is convention-driven.

schema: 1
name: threat-hunting
version: 0.1.0
description: Triage and report on threat indicators.
agents:
- agents/triage.md
tools:
- tools/intel.py
skills:
- skills/report/
mcp:
servers:
intel-server:
command: node
args: [mcp/intel.js]
flags:
verbose:
description: Emit extra diagnostic output
default: false
workers:
bridge:
path: workers/bridge.py
dependencies:
python: [requests]
scripts: [scripts/setup.sh]
checks:
- name: python-available
command: python --version

Unknown top-level keys are ignored silently — useful for future-proofing, but a typo in an optional key won’t error.

FieldTypeRule
schemaintegerMust equal 1. Any other value is a validation error.
namestringMatches ^[a-z0-9][a-z0-9-]*$. Becomes the capability’s registry name.
versionstringSemver X.Y.Z. Prereleases not accepted at publish time.
descriptionstringNon-empty. Shown in the catalog and TUI.

The conventional layout mirrors the manifest sections:

threat-hunting/
capability.yaml
agents/ # *.md files with frontmatter
tools/ # *.py files exporting @tool functions
skills/ # subdirectories with SKILL.md
workers/ # *.py files defining Worker instances
mcp/ # scripts or configs for inline MCP servers
scripts/ # setup scripts referenced by dependencies.scripts
.mcp.json # optional file-based MCP server config

None of these directories is required. The loader only cares about what the manifest references or auto-discovers.

Component fields follow three states:

ValueBehavior
OmittedAuto-discover from the conventional directory.
Explicit listLoad exactly what’s listed; skip auto-discovery.
Empty []Disable the component type entirely.
# Auto-discover agents/, tools/, skills/
agents: # (omit entirely)
tools: # (omit entirely)
# Load only these files
agents:
- agents/triage.md
- agents/responder.md
# Disable tools even if tools/ exists
tools: []
FieldAuto-discovery sourceEntry type
agentsagents/*.mdPath to markdown file
toolstools/*.pyPath to Python file
skillsskills/*/SKILL.mdPath to skill directory
mcp.mcp.json or mcp.jsonSee mcp below
workersno auto-discoveryNamed map — see workers

Each component has its own page covering behavior and authoring. The schema fields below define what you put under that key in capability.yaml.

SectionCompanion page
agentsAgents
toolsTools
skillsSkills
mcpMCP servers
flagsFlags
workersWorkers
dependencies, checksDependencies & checks
mcp:
files: # list of .mcp.json / mcp.json files
- .mcp.json
servers: # inline server definitions
<name>:
command: string # stdio transport
args: [string]
env: { <key>: string }
cwd: string
url: string # streamable-http transport
headers: { <key>: string }
timeout: number # seconds
init_timeout: number # seconds
when: [string] # flag names

Rules:

  • Exactly one of command or url per server. Both is an error, neither is an error.
  • when: is valid on inline servers only. File-loaded servers cannot use when:.
  • ${CAPABILITY_ROOT} resolves at parse time. ${VAR} and ${VAR:-default} resolve at connect time.
  • On name conflicts between file and inline, inline wins.
flags:
<name>:
description: string # required, non-empty
default: bool # optional, defaults to false

Rules:

  • Flag names match ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$.
  • Max 16 flags per capability.
  • Unknown fields on a flag entry are a validation error.
workers:
<name>:
# in-process
path: string # path to .py file relative to capability root
# subprocess
command: string
args: [string]
env: { <key>: string }
# gating
when: [string] # flag names

Rules:

  • Exactly one of path: or command:. Both is a validation error.
  • <name> matches ^[a-z0-9][a-z0-9-]*$.
  • In-process: path must point to a file exporting a module-level Worker instance.
  • Subprocess: command is the executable; args and env are optional.
dependencies:
python: [string] # pip requirement strings
packages: [string] # apt package names
scripts: [string] # shell scripts, paths relative to capability root

Sandbox-only. Local installs ignore this section.

checks:
- name: string
command: string

Rules:

  • Runs at capability load time.
  • 5-second timeout per check.
  • Exit 0 = pass, non-zero = fail.
  • Failed checks surface in the TUI capability manager but do not block load.

Optional fields that affect the registry listing but nothing at runtime:

author: Security Team
license: MIT
repository: https://github.com/acme/threat-hunting
keywords: [dfir, triage, indicators]
FieldTypeNotes
authorstringFree-form attribution.
licensestringSPDX identifier or free-form.
repositorystringURL.
keywords[string]Searchable tags.

Common errors:

  • name contains invalid characters — must match ^[a-z0-9][a-z0-9-]*$
  • Referenced path doesn’t exist (agents/triage.md missing)
  • Flag name referenced in when: not declared in flags:
  • Worker has both path: and command: set (mutually exclusive)
  • File-loaded MCP server uses when: (not allowed — inline only)

Validation errors name the offending field and the rule it broke.