Skip to content

Component Types

Skills conform to the Agent Skills specification. Each skill is a directory containing a SKILL.md file with YAML frontmatter and Markdown instructions.

Requirements:

  • Each skill directory declared in components.skills MUST contain a SKILL.md file.
  • The SKILL.md file MUST include valid YAML frontmatter with at least name and description fields.
  • The skill name in frontmatter MUST match the directory name.
  • Skills MAY include scripts/, references/, and assets/ subdirectories as defined by the Agent Skills specification.

Progressive disclosure:

Skills support three-tier progressive disclosure to minimize context token usage:

  1. Metadata (~100 tokens): The name and description from frontmatter, loaded at session startup for all installed skills.
  2. Instructions (<5000 tokens recommended): The full SKILL.md body, loaded when the skill is activated.
  3. Resources (as needed): Files in scripts/, references/, and assets/, loaded only when required during execution.

Example SKILL.md:

---
name: openapi-validator
description: Validates OpenAPI specifications against the OpenAPI 3.x standard. Use when the user wants to check an API spec for errors, warnings, or compliance issues.
metadata:
author: example-org
version: "1.0"
---
# OpenAPI Validator
Validate OpenAPI specification files for correctness and compliance.
## Usage
1. Read the target OpenAPI spec file (YAML or JSON).
2. Run the validation script:

scripts/validate.py <spec-file>

3. Report findings grouped by severity (error, warning, info).
## Edge Cases
- If the file is not valid YAML/JSON, report a parse error before validation.
- Specs using `$ref` to external files should be flagged as unsupported.

Agents are specialized personas with defined behavior, context, and capabilities. Each agent is a directory containing an AGENT.md file.

Requirements:

  • Each agent directory declared in components.agents MUST contain an AGENT.md file.
  • The AGENT.md file MUST include valid YAML frontmatter with at least name and description fields.

AGENT.md Frontmatter:

FieldRequiredConstraintsDescription
nameREQUIREDSame constraints as skill name.The agent identifier.
descriptionREQUIREDMax 1024 characters.Describes the agent’s role and when to use it.
licenseOPTIONALLicense name or file reference.License for the agent.
metadataOPTIONALKey-value string mapping.Additional metadata.

The Markdown body of AGENT.md defines the agent’s system instructions, persona, and behavioral guidelines. Hosts load this content when the agent is activated.

Example AGENT.md:

---
name: security-reviewer
description: A security-focused code review agent that identifies vulnerabilities, insecure patterns, and OWASP Top 10 issues in source code.
metadata:
author: example-org
version: "1.0"
---
# Security Reviewer
You are a security-focused code reviewer. Your role is to identify vulnerabilities, insecure patterns, and potential exploits in source code.
## Behavior
- Analyze code for OWASP Top 10 vulnerabilities.
- Flag hardcoded secrets, SQL injection, XSS, and command injection.
- Suggest specific fixes with code examples.
- Prioritize findings by severity (Critical, High, Medium, Low).
## Output Format
For each finding, provide:
1. **Severity**: Critical / High / Medium / Low
2. **Location**: File and line number
3. **Issue**: Description of the vulnerability
4. **Fix**: Recommended remediation with code example

Commands are user-invoked slash commands. When installed, they are namespaced under the package name.

Naming:

Commands are invoked as /{package-name}:{command-name}. For example, a command file run-tests.md in a package named api-testing is invoked as /api-testing:run-tests.

Requirements:

  • Each command file declared in components.commands MUST be a Markdown file.
  • The command file MUST include YAML frontmatter with at least name and description fields.

Command Frontmatter:

FieldRequiredConstraintsDescription
nameREQUIREDSame constraints as skill name.The command identifier (without package prefix).
descriptionREQUIREDMax 256 characters.Short description shown in command listings.
argumentsOPTIONALArray of argument definitions.Positional or named arguments the command accepts.

Argument Definition:

FieldRequiredTypeDescription
nameREQUIREDstringArgument name.
descriptionREQUIREDstringArgument description.
requiredOPTIONALbooleanDefault: false.

The Markdown body defines the command’s execution instructions.

Example command file:

---
name: run-tests
description: Execute API test suites against the configured endpoint.
arguments:
- name: suite
description: Name of the test suite to run. Runs all suites if omitted.
required: false
---
# Run API Tests
Execute the API test suite against ${config.API_BASE_URL}.
## Steps
1. Read the test definitions from `tests/` directory.
2. For each test case, construct the HTTP request.
3. Execute requests and compare responses against expected values.
4. Report results in a summary table.

Hooks are deterministic event handlers that execute shell scripts in response to host events. Hooks do not involve LLM interpretation; they are direct script executions.

Requirements:

  • The hooks configuration file declared in components.hooks MUST be a valid JSON file.
  • All scripts referenced by hooks MUST be included in the archive (typically in the scripts/ directory).
  • Hook scripts MUST NOT reference files outside the package installation directory.

hooks.json Format:

The hooks file is a JSON object where each key is an event type and the value is an array of hook definitions.

Event Types:

EventDescription
PreToolUseFired before a tool is invoked.
PostToolUseFired after a tool invocation completes.
SessionStartFired when a coding session begins.
SessionStopFired when a coding session ends.
NotificationFired on system notifications.

Hosts MAY define additional event types. Hooks for unrecognized event types MUST be silently ignored.

ccpkg defines a canonical (tool-neutral) event vocabulary for portable hook definitions. Authors MAY use canonical names in hooks.json; the installer translates them to the active host’s conventions at install time via the targets.*.hook_events mapping (see Targets Object).

Canonical event names:

Canonical EventDescription
pre-tool-useBefore a tool invocation
post-tool-useAfter a tool invocation completes
session-startWhen a coding session begins
session-endWhen a coding session ends
notificationOn system alerts or notifications
errorOn error during agent execution
pre-compactBefore context/history compression
user-prompt-submitWhen user submits a prompt

Not all hosts support all canonical events. The mapping from canonical names to host-native event names is defined in each host’s adoption specification. Hosts MAY also define additional events beyond the canonical vocabulary; these are documented in the host’s adoption spec.

Usage rules:

  • Authors MAY use either canonical or host-specific names in hooks.json.
  • The installer MUST translate canonical names to the active host’s convention via targets.*.hook_events.
  • Host-specific names work only on that host and are silently ignored by others.

Hook Definition:

FieldRequiredTypeDescription
matcherOPTIONALstringA pattern to filter the event (e.g., tool name for PreToolUse). If omitted, the hook fires for all events of its type.
commandREQUIREDstringThe shell command to execute. Relative paths are resolved from the package installation directory.
timeoutOPTIONALnumberMaximum execution time in milliseconds. Default: 10000.

Example hooks.json:

{
"PostToolUse": [
{
"matcher": "Bash",
"command": "scripts/lint-output.sh",
"timeout": 5000
}
],
"SessionStart": [
{
"command": "scripts/check-env.sh"
}
]
}

Example hooks.json using canonical event names:

{
"post-tool-use": [
{
"matcher": "Bash",
"command": "scripts/lint-output.sh",
"timeout": 5000
}
],
"session-start": [
{
"command": "scripts/check-env.sh"
}
]
}

MCP (Model Context Protocol) server configurations enable packages to provide tools, resources, and prompts via the MCP standard.

Requirements:

  • The MCP configuration file declared in components.mcp MUST be a valid JSON file.
  • The file is a template: it MAY contain ${config.VARIABLE_NAME} substitution markers that are resolved at install time from user-supplied configuration values.

Server Modes:

ccpkg supports three modes for MCP server configuration:

The server is started as an external process. The command, args, and env fields follow the standard MCP server configuration format.

{
"mcpServers": {
"api-testing-server": {
"command": "node",
"args": ["server/index.js"],
"env": {
"API_KEY": "${config.API_KEY}",
"BASE_URL": "${config.API_BASE_URL}"
}
}
}
}

The server is bundled as an .mcpb file inside the archive. The bundle field points to the file path within the archive.

{
"mcpServers": {
"api-testing-server": {
"bundle": "mcp/server.mcpb",
"env": {
"API_KEY": "${config.API_KEY}"
}
}
}
}

The server is referenced by an external URL with checksum verification. The archive does not contain the bundle; it is fetched at install time.

{
"mcpServers": {
"api-testing-server": {
"source": "https://example.com/mcp/server-1.0.0.mcpb",
"checksum": "sha256:a1b2c3d4...",
"env": {
"API_KEY": "${config.API_KEY}"
}
}
}
}

Note: Mode 3 is an exception to the self-contained principle. When using referenced bundles, the installer MUST fetch and verify the bundle at install time, not at runtime. The fetched bundle SHOULD be cached locally so that subsequent loads do not require network access.

The source URL MUST use HTTPS (see Transport Security).

Variable Substitution:

Template variables use the syntax ${config.VARIABLE_NAME}. The variable name MUST correspond to a key in the manifest’s config object.

  • Installers MUST resolve all template variables at install time.
  • If a required config variable is missing, the installer MUST report an error and abort.
  • If an optional config variable is missing and has a default, the default MUST be used.
  • If an optional config variable is missing and has no default, the template variable MUST be replaced with an empty string.

Server Deduplication:

When installing a package that declares an MCP server already present in the host configuration, the installer SHOULD deduplicate rather than creating a duplicate entry.

Server Identity. An MCP server’s identity is a tuple of (key_name, origin):

  • key_name: The key in the mcpServers object (e.g., "context7").
  • origin: Derived from the server mode:
    • Mode 1 (command+args): command::{command} {args_joined}, where {args_joined} is all elements of the args array joined with a single space. If args is empty or omitted, the origin is command::{command} (no trailing space). For example, command: "npx", args: ["-y", "@anthropic/context7-mcp"] yields command::npx -y @anthropic/context7-mcp.
    • Mode 2 (embedded mcpb): bundle::{bundle_path} normalized to the archive-relative path.
    • Mode 3 (referenced mcpb): the source URL verbatim.

Two servers are considered the same when both key_name and origin match.

Version Resolution. Version is extracted from the origin where possible (npm package version, URL path segment, mcpb metadata).

  • Same identity, incoming version higher: replace. Re-render MCP config from the incoming package’s template.
  • Same identity, incoming version equal or lower: skip rendering. Track in lockfile only.
  • When comparing versions, treat null/unknown as lower than any concrete semver version. If both are null/unknown, keep the existing server (treat as equal).
  • Same key_name, different origin: conflict. In interactive mode, the installer MUST warn the user and offer to keep the existing server, replace it, or install both under distinct keys. In non-interactive mode, the installer MUST fail with a descriptive error (implementations MAY support a preconfigured conflict policy).

User Override. Deduplication is the default behavior. Installers MUST provide a mechanism for users to override deduplication:

  • A global flag (e.g., --no-dedup) that bypasses all MCP deduplication for the current install operation.
  • A per-server override stored in the lockfile’s shared_mcp_servers entry ("dedup": false). When dedup is disabled for a server, each package gets its own independent copy.

LSP (Language Server Protocol) server configurations enable packages to provide language intelligence features such as diagnostics, completions, and code actions.

Requirements:

  • The LSP configuration file declared in components.lsp MUST be a valid JSON file.
  • The file is a template with the same ${config.VARIABLE_NAME} substitution syntax as MCP templates.

Example .lsp.json:

{
"lspServers": {
"openapi-lsp": {
"command": "node",
"args": ["lsp/server.js", "--stdio"],
"languages": ["yaml", "json"],
"env": {
"SCHEMA_PATH": "${config.SCHEMA_PATH}"
}
}
}
}

Instructions are documentation files that provide guidance to the AI coding assistant. The components.instructions field declares the instruction content to be assembled and installed.

When components.instructions is a string, it is a path to a single instructions file. The installer copies it to the filename defined in targets.*.instructions_file.

"instructions": "instructions/base.md"

When components.instructions is an object, it declares a base file and optional per-host overlays. The installer assembles the output by combining base content with the active host’s overlay.

"instructions": {
"base": "instructions/base.md",
"hosts": {
"claude-code": "instructions/hosts/claude-code.md",
"copilot-cli": "instructions/hosts/copilot-cli.md",
"gemini-cli": "instructions/hosts/gemini-cli.md"
}
}
FieldRequiredTypeDescription
baseREQUIREDstringPath to the base instructions file within the archive.
hostsOPTIONALobjectMap of host identifiers to overlay file paths within the archive. Keys match identifiers used in the targets manifest field.

Overlay files are Markdown files with YAML frontmatter that declares how the overlay content is positioned relative to the base content.

Frontmatter fields:

FieldRequiredTypeDescription
positionOPTIONALstringOne of append, prepend, or insert. Default: append.
markerConditionalstringName of the insertion marker in the base file. REQUIRED when position is insert.

Example overlay — append (default):

---
position: append
---
## Claude-Specific Guidelines
Use Claude Code's native subagent spawning for parallel research tasks.

Example overlay — prepend:

---
position: prepend
---
> This package requires Copilot agent mode. Enable it in VS Code settings.

Example overlay — insert at marker:

---
position: insert
marker: host-tools
---
When using Gemini CLI, prefer the built-in extension system for tool management.

Where the base file contains a named marker at the desired insertion point:

## Tool Usage
General tool guidelines here...
<!-- ccpkg:host-tools -->
## Error Handling
...
positionmarkerBehavior
appendignoredOverlay content appended after base content
prependignoredOverlay content prepended before base content
insertREQUIREDReplaces <!-- ccpkg:{marker} --> in base with overlay content
  • If no overlay exists for the active host, the base content is used as-is.
  • If position is insert but the marker <!-- ccpkg:{marker} --> is not found in the base file, the installer MUST report an error.
  • The overlay’s YAML frontmatter MUST be stripped before assembly — only the Markdown body is included in the output.
  • The assembled output is written to the host-specific filename defined in targets.*.instructions_file.
  • If the active host is not present in either hosts or targets, the installer SHOULD write the base content as INSTRUCTIONS.md and emit a warning.
  • If components.instructions is declared (in either form), the referenced base file MUST exist in the archive.
  • All overlay files declared in hosts MUST exist in the archive.
  • Marker names MUST match the pattern [a-z0-9]+(-[a-z0-9]+)* (lowercase alphanumeric with hyphens).