Skip to content

plugin-harness-kind

Placement compiled-in (in-process)
Source github.com/opencharly/plugin-harness-kind/candy/plugin-harness-kind
Version 2026.218.1200
Candy plugin-harness-kind

This plugin is listed in charly/charly.yml’s compiled_plugins:, so its providers are compiled into the charly binary and register in-process.

The reserved words this plugin serves:

  • hook — kind class
  • marketplace — kind class
  • skill — kind class

The skill / hook / marketplace HARNESS-SURFACE kinds — the plugins→candies migration’s first-class entities. A skill: node is a sibling top-level entity in a candy’s charly.yml carrying the FULL inline skill definition (metadata + markdown content); a hook: node carries a .claude/hooks/* gate script; a marketplace: node carries the single harness/marketplace config (families + settings). All three are FLAT kinds (Structural:false — no deploy members): their self-contained values ride op.Params, are validated at load against this plugin’s served #SkillInput/#HookInput/ #MarketplaceInput schemas (validateAuthoredPluginInput), and fold into uf.PluginKinds[“skill”|“hook”|“marketplace”][name] as opaque JSON.

COMPILED-IN (in the embedded compiled_plugins:) — the plugin-candy-kind placement, because the words must be recognized on every parse (validate/build/deploy) without an out-of-process build. The skill bodies feed BOTH the ai.opencharly.skills OCI label (CollectSkills → charly box labels) and the regenerated marketplace corpus (candy/plugin-marketplace, command:marketplace); hook bodies feed the .claude/hooks/* emission + settings.json wiring; the marketplace body feeds the plugin.json / marketplace.json / profiles.json / settings.json generated surface.

The CUE schema below is the authoritative grammar for this plugin’s input. It is the same single source that generates the plugin’s Go parameter types and answers the runtime Describe RPC, so this page cannot disagree with either.

// schema/docs.cue — the SELF-CONTAINED CUE schema validating the 'docs' KIND's authored
// VALUE (the ONE docs-site generation CONFIG entity per repo: everything 'charly docs
// generate' needs, declared in the repo's charly.yml). Self-contained per the
// skill/hook/marketplace reproduction contract — the same authored wire keys as the core
// #DocsConfig (spec/schema/docs.cue, the single source that generates spec.DocsConfig); the
// host validates against #DocsInput at load (validateAuthoredPluginInput) and this plugin's
// Invoke canonicalises the body back through the core spec.DocsConfig type. Classification
// mirrors skill/hook/marketplace EXACTLY (R3 — no special-casing for docs anywhere).
#DocsInput: close({
sources?: #DocsSourcesInput
marketplace?: #DocsMarketplaceInput
projections?: #DocsProjectionsInput
output?: #DocsOutputInput
landing?: #DocsLandingInput
gates?: #DocsGatesInput
})
// #DocsSourcesInput — where the reference documentation is GENERATED from.
#DocsSourcesInput: close({
// compiled — the plugins compiled into the charly binary (the reference corpus:
// the plugin/kind/verb surfaces they provide are the docs' source material).
compiled?: #DocsCompiledInput
// release_repos — bare candy repo names (e.g. plugin-review, plugin-pipeline)
// resolved like a go.mod require: entry — from the compiled corpus' go.mod when
// present, else the repo's latest CalVer tag at generation time.
release_repos?: [...(string & !="")]
// extra_repos — additional bare repo names fetched + documented OUTSIDE the
// compiled corpus (e.g. plugin-gh), same go.mod-require-else-tag resolution.
extra_repos?: [...(string & !="")]
})
#DocsCompiledInput: close({
enabled?: *true | bool
// compiled_plugins_path — the charly.yml whose compiled_plugins: list + providers:
// manifest declare the binary's in-proc corpus.
compiled_plugins_path?: *"charly/charly.yml" | string & !=""
// go_mod_path — the go.mod require: source for the release_repos resolution.
go_mod_path?: *"charly/charly/go.mod" | string & !=""
})
// #DocsMarketplaceInput — the marketplace repo layout (the 'marketplace generate' input).
#DocsMarketplaceInput: close({
// path — the marketplace repo's root directory (its candy/ + box/ walks source
// the skill:/hook:/marketplace: corpus the reference pages link to).
path?: *"marketplace" | string & !=""
})
// #DocsProjectionsInput — the reference projections the generator emits (all on by
// default; a projection's page set is generated only when its toggle is set).
#DocsProjectionsInput: close({
recipes?: *true | bool
cli?: *true | bool
providers?: *true | bool
candy?: *true | bool
box?: *true | bool
plugin?: *true | bool
landing?: *true | bool
})
// #DocsOutputInput — the hand-authored doc tree the generated pages are spliced into.
#DocsOutputInput: close({
// hand_authored — the hand-written docs roots (start/concepts/guides/…); the
// generator merges the generated reference pages beneath them and leaves the
// trees it does not own untouched.
hand_authored?: [...(string & !="")]
})
// #DocsLandingInput — the landing page source.
#DocsLandingInput: close({
// readme — the repo-root README that anchors the landing page.
readme?: *"README.md" | string & !=""
})
// #DocsGatesInput — the post-generation shape gates (each runs on every generation and
// FAILS the generator when its condition no longer holds).
#DocsGatesInput: close({
// site_links — every generated page link resolves in the built site.
site_links?: *true | bool
// sidebar_links — every sidebar entry resolves on its page.
sidebar_links?: *true | bool
// prune — stale generated pages (projections without a toggle) are removed.
prune?: *true | bool
})
// schema/hook.cue — the SELF-CONTAINED CUE schema validating the `hook` KIND's authored VALUE
// (the harness gate scripts). Self-contained per the group/agent reproduction contract — the
// same authored wire keys as the core #Hook (spec/schema/hook.cue, the single source that
// generates spec.Hook); the host validates against #HookInput at load and this plugin's Invoke
// canonicalises through spec.Hook. trigger/matcher absent ⇒ an AUX file (gitcmd.py, gate_test.py)
// emitted to .claude/hooks/ but not wired into settings.json.
#HookInput: close({
name: string & =~"^[a-z][a-z0-9._-]*$" // file stem incl. extension (.sh/.py)
content: string & !="" // inline script (block scalar)
trigger?: string & !="" // "PreToolUse" … (settings.json hooks.<trigger>)
matcher?: string & !="" // "Bash" … (required iff trigger present)
when?: string & !="" // optional settings.json when clause
mode?: *"0755" | "0644" // emitted file mode (chmod +x for .sh by default)
})
// schema/marketplace.cue — the SELF-CONTAINED CUE schema validating the `marketplace` KIND's
// authored VALUE (the single harness/marketplace config entity per repo). Self-contained per the
// group/agent reproduction contract — the same authored wire keys as the core #Marketplace
// (spec/schema/marketplace.cue, the single source that generates spec.Marketplace); the host
// validates against #MarketplaceInput at load and this plugin's Invoke canonicalises through
// spec.Marketplace.
#MarketplaceInput: close({
name: string & =~"^[a-z][a-z0-9-]*$" // "charly-plugins" (the marketplace name)
version: string & =~"^[0-9]+[.][0-9]+[.][0-9]+$" // marketplace.json metadata.version
description?: string & !="" // marketplace.json metadata.description
families: {[string]: #MarketplaceFamilyInput} // family name → its metadata (plugins/ dir = family)
settings?: #MarketplaceSettingsInput // the harness wiring data
})
#MarketplaceFamilyInput: close({
category?: *"images" | "commands" | "kind" | "development" // the README four-bucket classification
description?: string & !="" // plugin.json + marketplace.json description
keywords?: [...(string & !="")] // marketplace.json keywords
version?: string & =~"^[0-9]+[.][0-9]+[.][0-9]+$" // plugin.json version (default: family candy CalVer)
profiles?: [...("developer" | "user" | "container")] // profiles.json membership
mcp_servers?: [...#MarketplaceMCPServerInput] // plugins/<family>/.mcp.json entries
})
#MarketplaceMCPServerInput: close({
name: string & !=""
type?: *"http" | "stdio"
url?: string & !="" // http type (e.g. http://localhost:8888/mcp)
command?: string & !="" // stdio type (e.g. github-mcp-server)
args?: [...(string & !="")]
})
#MarketplaceSettingsInput: close({
enabled_plugins?: [...(string & !="")] // .claude/settings.json enabledPlugins (charly-*)
source_path?: *"./plugins" | string & !="" // extraKnownMarketplaces.<name>.source.path
hooks?: [...string] // hook entity names to wire into settings.json
})
// schema/skill.cue — the SELF-CONTAINED CUE schema validating the `skill` KIND's authored VALUE.
// Ships over Describe (schema_cue); references NO base def so it compiles standalone
// (BuildCapabilities compiles it alone, failing loudly if broken) AND splices onto the base
// (the base ++ plugin splice detects a def-name collision, not resolves base refs).
//
// It is a FAITHFUL reproduction of the core #Skill (spec/schema/skill.cue — the single source
// that generates spec.Skill via gengotypes), following the group/agent/… externalized-kind
// pattern: the SAME authored WIRE keys, so the host validates a real skill entity against
// #SkillInput (validateAuthoredPluginInput, the load gate) and this plugin's Invoke canonicalises
// the body back through the core spec.Skill type.
#SkillInput: close({
name: string & =~"^[a-z][a-z0-9-]*$" // marketplace-globally-unique skill id (SKILL.md folder name)
family: string & =~"^[a-z][a-z0-9-]*$" // marketplace family → plugins/<family>/
owner: string & =~"^[a-z][a-z0-9-]*$" // owning candy/concept-candy entity name
description: string & !="" // SKILL.md frontmatter description (Skill-tool dispatch keyword)
content: string & !="" // SKILL.md markdown body
type?: *"skill" | "agent" // "agent" ⇒ a sub-agent definition
model?: string & !="" // agent type: frontmatter model
tools?: [...(string & !="")] // agent type: allowed tool set
references?: [...#SkillReferenceInput] // SKILL.md references/<stem>.md split files
triggers?: [...(string & !="")] // R0-dispatcher trigger phrases
category?: *"development" | "commands" | "kind" | "images"
})
#SkillReferenceInput: close({
name: string & =~"^[a-z0-9][a-z0-9-]*$" // file stem (references/<name>.md)
content: string & !=""
})

See also the candy reference for this candy’s install surface.