Skills¶
Skills are pre-built patterns and workflows that extend the agent's capabilities.
What are Skills?¶
Skills are markdown files with YAML frontmatter that provide specialized knowledge and step-by-step guidance for specific tasks. When you load a skill, the agent gains access to detailed instructions for that domain.
Using Skills¶
List Available Skills¶
# List all skills from the registry
ch skill list
# Filter by tag
ch skill list --tags react
ch skill list --tags python
Install a Skill¶
# Interactive picker (recommended)
ch skill install
# Install specific skill
ch skill install react-forms
Interactive picker:
? Select a skill to install: (Use arrow keys, type to filter)
» react-forms - React form handling with validation
django-auth - Django authentication patterns
fastapi-crud - FastAPI CRUD patterns
Dual-Tool Installation
When both OpenCode and Claude Code are configured, skills are automatically installed to both tool directories.
Installation Options¶
Target specific tool:
# Install to OpenCode only
ch skill install react-forms --tool-target opencode
# Install to Claude Code only
ch skill install react-forms --tool-target claude-code
# Install to both (default)
ch skill install react-forms --tool-target both
Install from HTTP registry:
# Install directly from an HTTP registry URL
ch skill install react-forms --registry http://localhost:8080
View Skill Details¶
List Installed Skills¶
This command searches both .opencode/skill/ and .claude/skills/ directories.
Skill Structure¶
Skills are stored in tool-specific directories:
Each skill has YAML frontmatter:
---
name: react-forms
description: React form handling with validation
tags:
- react
- forms
- validation
---
# React Forms Skill
Instructions for the agent...
Version is NOT in Frontmatter
Skill versions are managed by release-please via version.txt in each skill directory (see Automated Versioning below). Do not add a version field to the SKILL.md frontmatter — the CI validation workflow will flag it as an error.
Creating Custom Skills¶
1. Create the Skill File¶
Create .opencode/skill/my-skill/SKILL.md:
Do Not Add version to Frontmatter
If you plan to publish this skill to a registry with automated versioning, the version field must not appear in the frontmatter. Version is managed via version.txt (see Automated Versioning).
Skill Content is Identical
The skill file content is the same for both tools—only the directory path differs.
2. Extract to Share¶
This generates a JSON file you can submit to a skills repository.
Custom Skills Repository¶
You can host your own skills registry instead of using the default co-labs-co/context-harness-skills repository. This is useful for organizations that want to share private skills across teams.
Creating a Registry Repository¶
The fastest way to get started is with the init-repo command, which creates a properly scaffolded GitHub repository:
# Create a private registry under your personal account
ch skill init-repo my-skills
# Create under an organization
ch skill init-repo my-org/team-skills
# Create a public registry
ch skill init-repo my-org/team-skills --public
# Create and configure as your default in one step
ch skill init-repo my-skills --configure-user
Prerequisite
The GitHub CLI (gh) must be installed and authenticated. Run gh auth login if you haven't already.
The command creates a fully scaffolded repository with CI/CD automation for per-skill semantic versioning:
my-skills/
├── .github/
│ ├── workflows/
│ │ ├── release.yml # release-please per-skill versioning
│ │ ├── sync-registry.yml # Rebuilds skills.json after releases
│ │ └── validate-skills.yml # PR validation + sticky comments
│ ├── ISSUE_TEMPLATE/
│ │ └── new-skill.md # Template for proposing new skills
│ └── PULL_REQUEST_TEMPLATE.md # PR checklist for contributors
├── scripts/
│ ├── sync-registry.py # Parses frontmatter + version.txt → skills.json
│ └── validate_skills.py # Pydantic-based schema validation
├── skill/
│ └── example-skill/
│ ├── SKILL.md # Example skill (no version in frontmatter)
│ └── version.txt # Bootstrapped at 0.1.0
├── skills.json # Registry manifest (auto-updated by CI)
├── release-please-config.json # release-please configuration
├── .release-please-manifest.json # Current versions (managed by CI)
├── .gitignore
├── README.md # Includes Mermaid lifecycle diagram
├── CONTRIBUTING.md # Contributor guide with conventional commits
└── QUICKSTART.md # Quick-start for adding your first skill
16 Files, Zero Manual Setup
The scaffold creates 16 files — a complete GitHub repository with CI/CD that handles versioning, validation, and registry updates automatically. You just write skill content and use conventional commits.
Once created, you can start adding skills to the repository. See Adding Skills to Your Registry below for the complete workflow.
Auto-configuration options:
| Flag | Effect |
|---|---|
--configure-user | Sets the new repo as your default skills-repo in ~/.context-harness/config.json — applies to all projects on your machine |
--configure-project | Sets the new repo as the project's skills-repo in opencode.json — applies to this project only |
If you don't use either flag, the command prints manual config set instructions for both scopes.
Which one should I use?
Use --configure-user if you want every project on your machine to pull skills from this registry by default. Use --configure-project if only the current project should use it. Project-level config takes precedence over user-level config (see Configuration Precedence below).
Configuration¶
Repository Structure¶
A skills registry repository follows this structure:
my-skills-repo/
├── .github/
│ └── workflows/
│ ├── release.yml # Automated per-skill releases
│ ├── sync-registry.yml # Rebuilds skills.json post-release
│ └── validate-skills.yml # PR validation
├── scripts/
│ ├── sync-registry.py # Registry builder script
│ └── validate_skills.py # Validation script
├── skill/ # All skills live here
│ ├── my-skill/
│ │ ├── SKILL.md # Skill content (no version in frontmatter)
│ │ └── version.txt # Current version (managed by release-please)
│ └── another-skill/
│ ├── SKILL.md
│ └── version.txt
├── skills.json # Registry manifest (auto-generated)
├── release-please-config.json # Versioning configuration
├── .release-please-manifest.json # Version state
├── README.md
├── CONTRIBUTING.md
└── QUICKSTART.md
skills.json Format¶
The skills.json file is the registry manifest that the CLI fetches to discover available skills. It is auto-generated by the sync-registry.yml workflow — do not edit it by hand.
{
"schema_version": "1.1",
"registry_version": "0.8.0",
"skills": [
{
"name": "my-skill",
"description": "What this skill does",
"version": "1.2.0",
"author": "your-username",
"tags": ["category"],
"path": "skill/my-skill",
"min_context_harness_version": null,
"content_hash": "a1b2c3d4e5f67890"
}
]
}
| Field | Description |
|---|---|
schema_version | Schema version of the manifest format (currently "1.1") |
registry_version | ContextHarness CLI version that created/updated the registry |
name | Skill identifier (matches directory name) |
description | From SKILL.md frontmatter |
version | From version.txt (managed by release-please) |
author | From SKILL.md frontmatter |
tags | From SKILL.md frontmatter |
path | Directory path in the repository |
min_context_harness_version | From SKILL.md frontmatter (optional) |
content_hash | SHA-256 prefix of SKILL.md for change detection |
Automated Versioning¶
Repositories scaffolded by ch skill init-repo use release-please for fully automated per-skill semantic versioning. Authors never touch version numbers — they write content and use conventional commits, and CI handles everything else.
How It Works¶
┌─────────────────────────────────────┐
│ 1. Author edits SKILL.md │
│ skill/my-skill/SKILL.md │
└──────────────────┬──────────────────┘
▼
┌─────────────────────────────────────┐
│ 2. Commits with conventional msg │
│ "feat: add new examples" │
└──────────────────┬──────────────────┘
▼
┌─────────────────────────────────────┐
│ 3. PR merged to main │
└──────────────────┬──────────────────┘
▼
┌─────────────────────────────────────┐
│ 4. release-please detects change │
│ (path-based: skill/my-skill/*) │
└──────────────────┬──────────────────┘
▼
┌─────────────────────────────────────┐
│ 5. Creates release PR │
│ Bumps version.txt + CHANGELOG │
└──────────────────┬──────────────────┘
▼
┌─────────────────────────────────────┐
│ 6. Release PR merged │
│ → Tag: my-skill@v1.1.0 │
│ → GitHub Release created │
└──────────────────┬──────────────────┘
▼
┌─────────────────────────────────────┐
│ 7. sync-registry.yml fires │
│ Rebuilds skills.json from all │
│ version.txt files │
└──────────────────┬──────────────────┘
▼
┌─────────────────────────────────────┐
│ 8. CLI users see update │
│ ch skill outdated → upgrade │
└─────────────────────────────────────┘
Conventional Commits Drive Versioning¶
The type of commit message determines the version bump for the affected skill:
| Commit Message | Version Bump | Example |
|---|---|---|
fix: correct typo in examples | Patch (1.0.0 → 1.0.1) | Bug fixes, typos |
feat: add error handling patterns | Minor (1.0.0 → 1.1.0) | New content, sections |
feat!: restructure skill format | Major (1.0.0 → 2.0.0) | Breaking changes |
docs: update readme | None | Non-skill documentation |
chore: update CI config | None | Maintenance |
Path-Based Detection
release-please attributes commits to skills based on which files they touch, not the commit scope. If you edit skill/react-forms/SKILL.md, release-please knows the react-forms skill was changed — you don't need to specify a scope in your commit message.
Where Version Lives¶
| Location | Managed By | Purpose |
|---|---|---|
skill/{name}/version.txt | release-please (CI) | Source of truth per skill |
skill/{name}/CHANGELOG.md | release-please (CI) | Auto-generated changelog |
.release-please-manifest.json | release-please (CI) | All current versions |
skills.json | sync-registry.py (CI) | Registry manifest the CLI fetches |
Never Edit version.txt or skills.json by Hand
Both are managed by CI. Manual edits will be overwritten on the next release or sync cycle.
CI/CD Workflows¶
The scaffold includes three GitHub Actions workflows:
release.yml — Automated Releases¶
Runs on every push to main. Uses googleapis/release-please-action@v4 with:
release-type: "simple"— managesversion.txt+CHANGELOG.mdper skillinclude-component-in-tag: true— tags likemy-skill@v1.1.0tag-separator: "@"— separates skill name from versionseparate-pull-requests: true— one release PR per skill
sync-registry.yml — Registry Updates¶
Fires after a release is published. Runs scripts/sync-registry.py to:
- Scan all
skill/*/SKILL.mdfiles and parse frontmatter - Read
version.txtfrom each skill directory - Compute content hashes for change detection
- Write the consolidated
skills.json - Commit with
[skip ci]to prevent infinite loops
validate-skills.yml — PR Validation¶
Runs on every PR that modifies files under skill/. Uses scripts/validate_skills.py (Pydantic-based) to:
- Check every skill has a valid
SKILL.mdwith required frontmatter - Verify
namefield matches directory name - Ensure no
versionfield exists in frontmatter - Confirm
version.txtexists and contains a valid semver string - Check for duplicate skill names
- Post a sticky PR comment with the validation report (updates on each push)
Adding Skills to Your Registry¶
Step 1: Create the Skill Directory¶
Step 2: Create SKILL.md¶
---
name: my-new-skill
description: Brief description of what this skill does
author: your-username
tags:
- category
- subcategory
---
# My New Skill
## When to Use
Use this skill when...
## Instructions
1. Step one
2. Step two
## Examples
```python
# Example code
```
No version Field
Do not include version in the frontmatter. It is managed by version.txt.
Step 3: Create version.txt¶
Bootstrapping Required
release-please will not create version.txt for you — it only bumps an existing file. You must bootstrap it at 0.1.0 (or your preferred starting version) when creating a new skill.
Step 4: Register with release-please¶
Add the skill to both release-please configuration files:
release-please-config.json — add the package entry:
.release-please-manifest.json — add the initial version:
Step 5: Commit and Push¶
Use conventional commits to drive versioning:
git add skill/my-new-skill/ release-please-config.json .release-please-manifest.json
git commit -m "feat: add my-new-skill"
git push
After this PR is merged, release-please will create a release PR to bump the version. When that release PR is merged, the skill gets a scoped tag (my-new-skill@v0.1.0) and skills.json is automatically updated.
Keeping Skills Up to Date¶
Check for Updates¶
See which of your installed skills have newer versions available:
Example output:
┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃ Skill ┃ Installed ┃ Latest ┃ Status ┃
┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ react-forms │ 0.1.0 │ 0.2.0 │ upgrade available │
│ fastapi-crud │ 1.0.0 │ 1.0.0 │ up to date │
└─────────────────┴───────────────┴───────────────┴─────────────────────┘
Upgrade Skills¶
# Upgrade a single skill
ch skill upgrade react-forms
# Upgrade all outdated skills at once
ch skill upgrade --all
Compatibility¶
Skills can declare a minimum ContextHarness version they require via min_context_harness_version in their metadata. If your installed version is too old, the upgrade is blocked:
❌ react-forms requires context-harness >= 4.0.0 (you have 3.9.0)
Run: pipx upgrade context-harness
Or use --force to skip this check
Use --force to bypass the check if needed:
HTTP Registry Hosting¶
Skills registries can be hosted via HTTP (no Git required) using Docker and nginx. This is useful for:
- Air-gapped environments - No GitHub access required
- Private networks - Host on internal infrastructure
- AI agent access - Allow AI coding assistants to discover and install skills
Hosting a Registry¶
Registries created with ch skill init-repo include Docker configuration:
The scaffold includes:
| File | Purpose |
|---|---|
Dockerfile | nginx-based container |
docker-compose.yml | Easy local deployment |
registry/nginx.conf | CORS-enabled configuration |
registry/web/index.html | Skill browser UI |
registry/web/skill.html | Individual skill pages |
llms.txt | AI agent installation instructions |
AI Agent Discovery¶
The registry includes llms.txt at the root - an emerging standard for LLM-specific instructions. AI agents read this file to understand how to install skills:
The file instructs agents to use the CLI:
Installing from HTTP Registry¶
# Point CLI at HTTP registry
ch skill use-registry http://localhost:8080
# Or install directly with --registry flag
ch skill install react-forms --registry http://localhost:8080
Upgrading Registry Infrastructure¶
Keep your registry scaffold up to date with the latest features:
# Check for updates
ch skill upgrade-repo --check
# Preview changes
ch skill upgrade-repo --dry-run
# Apply updates
ch skill upgrade-repo
# Force overwrite all scaffold files
ch skill upgrade-repo --force
The command updates:
- Critical infrastructure - Always updated: Dockerfile, nginx.conf, index.html, skill.html, llms.txt
- Documentation - Only if missing (use
--forceto overwrite) - Workflows - Only if missing (use
--forceto overwrite)
Preserves Your Skills
The upgrade-repo command never modifies files in the skill/ directory - your skill content is safe.
Registry Version Tracking¶
Registries include a .registry-version file for tracking scaffold version:
Legacy registries (without this file) are detected as version 0.0.0 and can be upgraded.
Configuration Precedence¶
Skills repository is resolved in this order:
| Priority | Source | Location |
|---|---|---|
| 1 (Highest) | Environment Variable | CONTEXT_HARNESS_SKILLS_REPO |
| 2 | Project Config | opencode.json → skillsRegistry.default |
| 3 | User Config | ~/.context-harness/config.json |
| 4 (Lowest) | Default | Official skills repository |