Adding Skills to Dockyard
August 14, 2026 · View on GitHub
This guide walks you through packaging and contributing an agent skill to Dockyard.
Overview
Unlike MCP servers (built from an npm/PyPI/Go package into a container),
skills are packaged directly from a git repository: Dockyard clones the
upstream repo at a pinned commit, validates the SKILL.md at the given
path, and repackages that directory as an OCI artifact.
Adding a skill is simple:
- Create a
spec.yamlconfiguration file - Submit a pull request
- CI/CD automatically validates, scans, and publishes the skill artifact
Directory Structure
skills/{skill-name}/spec.yaml
There is a single skills/ directory (no protocol subdirectories like
npx//uvx//go/ — those apply only to MCP servers).
Naming
Pick {skill-name} to be collision-safe in a single flat namespace shared
by 150+ skills from many upstream sources:
- If the upstream skill's own name is already specific (
claude-api,gh-stack), use it as-is. - If the upstream repo ships several skills whose names are generic on
their own (e.g.
provider-docs,windows-builder), prefix all of them with a short vendor tag, e.g.hashicorp-provider-docs,dd-apm(Datadog),hf-cli(Hugging Face). Prefer a single flat prefix over splitting by upstream sub-project — it avoids awkward stutter when a skill's own name already contains the sub-project name (e.g.hashicorp-terraform-test, nothashicorp-terraform-terraform-test). - Check for an existing name collision before picking one:
ls skills/ | grep -x '{candidate-name}'.
Licensing
Before packaging a third-party skill, verify that an explicit license covers
the skill content and permits copying, modification, and redistribution in a
public OCI artifact. Check both the skill directory and repository root for a
LICENSE/COPYING file, plus any SPDX-style license: field in SKILL.md.
Publicly accessible source is not automatically open source. Do not package a repository with no license unless the copyright holder has separately granted the required redistribution rights. A link to product, API, developer, or website terms is not enough unless those terms explicitly license the repository content for redistribution. If the license is missing, ambiguous, or non-redistributable, stop and resolve that before creating the spec.
Include the license and its location in the PR description. When the repository
has a root license but the individual SKILL.md does not, skill-scanner may
report MANIFEST_MISSING_LICENSE; an allowlist reason should cite the verified
repository license.
spec.yaml Reference
# {Skill Name} Skill
# Source: {source-repository-url}
# Will publish as: ghcr.io/stacklok/dockyard/skills/{name}:{version}
metadata:
name: {skill-name} # Required: must match the directory name
description: "{brief description}" # Optional but recommended: copy from the
# upstream SKILL.md frontmatter `description`
spec:
repository: "{https-git-clone-url}" # Required: HTTPS clone URL
ref: "{commit-sha}" # Required: pinned commit (not a moving
# branch/tag — see "Pinning the ref" below)
path: "{path-to-skill-dir}" # Optional: subdirectory containing
# SKILL.md; omit if SKILL.md is at repo root
version: "0.1.0" # Required: Dockyard-owned semver —
# see docs/skill-versioning.md
provenance:
repository_uri: "{https-git-clone-url}"
repository_ref: "refs/heads/{branch}" # Branch Renovate should follow
security:
allowed_issues:
- rule_id: "{RULE_ID}" # From the skill-scanner report
reason: "FP: ..." # Why this finding is a false positive
# or an accepted risk — see "Security
# Scanning" below
Pinning the ref
spec.ref must be a commit SHA, not a branch or tag — this is what makes
the build reproducible. Resolve the exact branch named by
provenance.repository_ref:
git ls-remote https://github.com/{org}/{repo} refs/heads/{branch}
Renovate reads that branch name from provenance.repository_ref and keeps
spec.ref current automatically once the skill is added (see
renovate.json); you generally only need to pin it once, at creation time.
version
Dockyard owns the semver for every vendored skill independently of
upstream — most upstream skill repos don't tag individual skills, and even
when they cut a repo-wide release, it doesn't map cleanly onto one skill's
changes. Start a new skill at 0.1.0 regardless of any upstream version or
release tag. See Skill Versioning for the full
policy and the tooling that bumps this automatically as spec.ref
advances.
Local Testing
Build the CLI once:
task build-setup
Then, for a given skill:
# Validate spec.yaml and SKILL.md (fast, no scan)
task validate-skill -- skills/{skill-name}
# Run skill-scanner and apply the security allowlist
task scan-skill -- skills/{skill-name}
# Build the OCI artifact locally (dry run, no push)
task build-skill -- skills/{skill-name}
# Build and push (requires registry auth — CI does this, not typically local)
PUSH=true task build-skill -- skills/{skill-name}
task scan-skill requires the scanner once per machine:
task scan-skill-setup # uv tool install cisco-ai-skill-scanner
Security Scanning
Every skill is scanned with
Cisco AI Defense skill-scanner
before packaging. This is blocking: any finding at or above HIGH
severity that isn't allowlisted fails the build.
Skill documentation is prose-heavy and full of code examples, so
keyword/pattern rules produce a lot of false positives — shell variable
expansion in documented setup commands (${TOKEN}, $HOME), install
one-liners (curl -L .../pup, sudo apt-get install, a vendor's official
Chocolatey/PowerShell bootstrap), example IP addresses, and placeholder
credential values in setup docs are the most common triggers, not real
threats.
When task scan-skill reports an unallowlisted finding:
-
Read the finding's
file_path/line_numberin the skill's actual source (clone it at the pinnedrefif you need full context). -
Decide if it's a genuine issue or a false positive / accepted risk.
-
If it's a false positive or an accepted risk, add it to
security.allowed_issuesin the skill'sspec.yaml, matching byrule_id(exact) orcategory(broader). Every entry needs areasonthat cites the specific matched text/location and explains why it's safe — see any existingskills/*/spec.yamlfor the house style, e.g.:security: allowed_issues: - rule_id: ATR_2026_00066 reason: "FP: matched shell variable expansion (`${TOKEN}`) in a documented setup command (SKILL.md:45) — standard shell syntax, not injected secrets." -
Re-run
task scan-skill -- skills/{skill-name}until it passes.
Never set security.insecure_ignore: true to work around a scan failure —
it disables the gate entirely rather than documenting why each finding is
safe. See scripts/skill-scan/README.md for the scanner wrapper scripts
and scripts/skill-scan/global_allowed_issues.yaml for issues allowlisted
across every skill (promote a per-skill entry there only once you've seen
the same false positive recur across unrelated skills).
What CI Does
On every PR touching skills/**/*.yaml, .github/workflows/build-skills.yml:
- Validates the spec and
SKILL.md(validate-skillsjob) - Scans the pinned source with skill-scanner and applies the
allowlist (
skill-security-scanjob) — this is the blocking security gate - Builds the OCI artifact as a dry run (no push on PRs)
On merge to main, it additionally pushes the artifact to
ghcr.io/stacklok/dockyard/skills/{name}:{version}, signs it with
Cosign, and attests SBOM, build provenance, and a SCAI-format security
scan predicate — the same supply-chain guarantees MCP server containers
get. See Security Overview and
Container Attestations.
A change to spec.ref without a corresponding spec.version bump fails
the skill-version-check CI job — see
Skill Versioning for why and how the bump is
computed.
Commit and PR
git add skills/{skill-name}/spec.yaml
git commit -s -m "Add {skill-name} skill
Package {skill-name} from {upstream-repo} at {commit-sha}.
Source: {upstream-repo-url}"
Include in your PR description what the skill does and a link to its upstream source, pinned commit, and redistribution license, same as an MCP server PR (see CONTRIBUTING.md).
See Also
- Skill Versioning — semver policy and auto-bump tooling
- Security Overview — scanning and attestation model
.claude/skills/package-skill/(also at.agents/skills/package-skill/) — a skill that automates this entire workflow (spec.yaml authoring, scanning, allowlist triage)- Adding MCP Servers — the equivalent guide for MCP server containers