# Getting started with skill hardening

URL: https://deploy-preview-4124--ornate-narwhal-088216.netlify.app/chainguard/agent-skills/skill-hardening.md
Last Modified: September 28, 2026
Tags: Agent Skills, Getting Started, chainctl

Upload an agent skill for hardening, track the job, browse results in user folders, and review the report before installing the skill.

Use chainctl skills harden to upload an agent skill, submit it for server-side hardening, and download the result with a report of the changes and scanner findings. You can submit a local directory or harden an artifact you have already pushed to your organization&rsquo;s uploads registry.
This guide builds on Getting started with the Chainguard Skills Registry, covering hardening and job tracking before you install the skill.
Note: Chainguard Agent Skills is in beta.
Prerequisites You need:
An installed and authenticated chainctl that includes skills harden and skills status. An organization with a Skills entitlement and accepted Skills terms. Permission to upload skills, submit and read hardening jobs, and pull the results. Set up your organization In the commands below, replace your-organization with your organization&rsquo;s name or UIDP (its unique identifier).
If onboarding is not already complete, an organization administrator with skills.entitlements.create and terms.accept permissions runs:
chainctl skills entitlements create --parent your-organization chainctl skills accept-terms --group your-organizationReview and accept the terms in the interactive prompt. To check whether the organization already has an entitlement, run:
chainctl skills entitlements list --parent your-organizationAn entitlement enables access to the service. Its presence does not indicate that a skill has been uploaded or hardened.
Check your chainctl version Check that your chainctl version includes the commands:
chainctl skills harden --help chainctl skills status --helpThe harden help should show --folder, --digest, --wait, and --timeout. If it shows only the generic skills help, update chainctl.
Create and validate an example skill Create a small skill that produces a release checklist:
mkdir harden-demo cat &gt; harden-demo/SKILL.md &lt;&lt;&#39;EOF&#39; --- name: harden-demo description: Write a short release checklist when the user asks to prepare a software release. license: Apache-2.0 --- Ask the user for the project name and intended release version if either is missing. Return a checklist covering tests, release notes, and the release owner. Use only information provided by the user. Mark missing details as &#34;to confirm&#34;. EOF chainctl skills validate ./harden-demoThe directory name must match the frontmatter name. Keep the directory within the 10 MB limit. Validation checks the skill&rsquo;s structure locally; the hardening pipeline performs the subsequent review and evaluation.
Harden a local directory From the directory containing harden-demo, run:
chainctl skills harden ./harden-demo --group your-organization --wait --timeout 30mThe command packages and uploads the directory, submits a hardening job, prints its ID, and waits for completion. --folder ./harden-demo is equivalent to the positional directory argument. A separate skills push is unnecessary for this workflow.
The examples use the production registries. chainctl uploads to uploads.cgr.dev by default in production; no registry environment variable is required.
On success, the command prints the hardened artifact&rsquo;s reference and digest and downloads it into ./hardened/harden-demo/. The download includes SKILL.md, any supporting files, and HARDENING.md with the hardening report and findings.
The hardened artifact is published under the submitting user&rsquo;s namespace:
skills.cgr.dev/&lt;org-uidp&gt;/users/&lt;user-namespace&gt;/harden-demo@sha256:&lt;digest&gt;The service generates the user namespace. Save the exact reference returned by the command, including users/&lt;user-namespace&gt;/ and the digest, for subsequent pulls or installs.
Submit now and check later Omit --wait to return after submission. Use -o id to capture the job ID:
JOB_ID=$(chainctl skills harden ./harden-demo --group your-organization -o id) chainctl skills status --group your-organization --id &#34;$JOB_ID&#34;To resume waiting and download the result:
chainctl skills status --group your-organization --id &#34;$JOB_ID&#34; --wait --timeout 30m--id takes the 64-character job ID, without a sha256: prefix or an operation path. Repeating a submission with the same organization, user, skill name, and content digest returns the same job. Use status when you only need to check progress.
--timeout requires --wait and bounds the waiting command, including its other work. A timeout or Ctrl-C stops the local command; it does not cancel the server-side job. Resume with the saved ID. A pipeline failure exits nonzero and prints its failure reason.
Harden an existing upload You can also push a tagged artifact first and then explicitly request hardening:
chainctl skills push ./harden-demo --group your-organization --tag v1.0.0 chainctl skills list --group your-organization --source uploads chainctl skills harden uploads.cgr.dev/your-organization/harden-demo:v1.0.0 \ --group your-organization --wait --timeout 30mpush stores the original artifact in uploads.cgr.dev. Use harden to submit it for hardening and status to track the job. A successful push does not mean that a hardened result is available in skills.cgr.dev.
The upload must be in the same organization passed to --group. This command accepts a reference at &lt;uploads-host&gt;/&lt;org&gt;/&lt;skill-name&gt;; use the organization root when pushing an artifact you intend to harden this way.
To select the exact artifact from the push output, use its digest instead:
chainctl skills harden --group your-organization --name harden-demo \ --digest &#39;sha256:&lt;64-hex-digest-from-push&gt;&#39; --wait --timeout 30m--digest requires --name and takes only the digest, not a tag or full registry reference. Choose one input form per invocation: a path, --folder, an uploads reference, or --digest with --name.
Browse results in user folders Why do I only see a users folder? By default, chainctl skills list reads the hardened registry (--source skills) and shows only the immediate folders and skills at the selected level. For example:
chainctl skills list --group your-organization SOURCE | TYPE | NAME | TAGS | UPDATED ----------------|--------|-------|------|--------- skills.cgr.dev | folder | users | -- | --users is a registry folder containing namespaces for users who submit skills for hardening. A row with TYPE set to folder has no skill tag or update time, so those columns show --. The folder row alone does not tell you whether a hardening job has completed or whether your skill is inside it.
Hardened results are organized like this:
skills.cgr.dev/&lt;org-uidp&gt;/ └── users/ └── &lt;user-namespace&gt;/ └── harden-demoEach submitting user has a separate namespace, so different users can harden a skill with the same name without sharing a repository path.
Expand all user folders Add --recursive (or -r) to include skills from every nested folder in the listing:
chainctl skills list --group your-organization --source skills --recursiveThe NAME column shows the full path relative to the organization, such as users/&lt;user-namespace&gt;/harden-demo. Repeating the default non-recursive command continues to show only the top-level folder.
The TAGS column lists all tags for each skill, including version tags and generated hardening tags. Skills without tags are also listed, with -- in that column. The CLI does not require a latest tag. MCP skill discovery uses latest, so its results can differ from the CLI listing.
To browse one level at a time, append the registry folder path to --group:
chainctl skills list --group your-organization/users chainctl skills list --group &#34;your-organization/users/&lt;user-namespace&gt;&#34;Replace &lt;user-namespace&gt; with a folder name returned by the first command. These paths select registry folders; they do not refer to directories on your machine.
Find a skill after pushing it If push returned an uploads.cgr.dev reference, select the uploads source to browse that registry:
chainctl skills list --group your-organization --source uploads --recursiveTo browse uploads and hardened results in one listing:
chainctl skills list --group your-organization --source all --recursiveUse the SOURCE column to distinguish the registries:
Source option Registry Contents --source skills (default) skills.cgr.dev Hardened skills, including skills in user namespaces. --source uploads uploads.cgr.dev Original uploads. --source all Both registries Skills from either source, labeled by registry. If you have only run push, follow Harden an existing upload. If you already submitted a hardening job, use chainctl skills status --group your-organization --id &quot;$JOB_ID&quot; to check it. An entitlement listing or a users folder row is not a job status check.
Find a skill that is missing from the listing First, check the source and folder: use --source uploads for an uploaded original, --source skills for a hardened result, and --recursive to include nested skills.
Older chainctl builds display a LATEST TAG column and omit skills without a latest tag. This can hide version-tagged uploads and completed hardening results. Update chainctl to use the listing with all tags. You can also inspect and pull these artifacts by their exact references.
For an upload, inspect the full reference from the push output:
chainctl skills describe uploads.cgr.dev/your-organization/harden-demo:v1.0.0For a hardening job, use status and save the returned hardened reference as described in Review and install the result. Use that reference for describe, pull, or install; an empty listing does not mean the job failed.
Review and install the result Read hardened/harden-demo/HARDENING.md for the change summary and findings, including findings that remain open. Review the resulting instructions before using the skill. A successful hardening job can still have remaining findings.
Copy the full hardened reference printed by harden or status:
export HARDENED_REF=&#39;&lt;full-hardened-reference-including-@sha256:digest&gt;&#39; chainctl skills describe &#34;$HARDENED_REF&#34; chainctl skills install &#34;$HARDENED_REF&#34;install detects your local agents and reports where it placed the skill. Use the installed name and location shown by the command to load it in your agent, then ask it to prepare a release checklist for a test project.
If ./hardened/harden-demo/ already contains a previous download, --wait will not overwrite it. Check status without --wait, then pull the returned reference into a new directory:
chainctl skills pull &#34;$HARDENED_REF&#34; ./harden-demo-reviewed
