Skip to main content

Manage agent skills

Agent skills are reusable bundles of instructions, scripts, and resources that teach AI agents how to perform specific tasks. While MCP servers provide tools (the raw capabilities an agent can call), skills provide the knowledge of when, why, and how to use those tools effectively.

ToolHive lets you install skills from a ToolHive Registry Server (by name), OCI registries (by reference), or Git repositories (by URL), and manages their lifecycle across multiple AI clients.

New to skills?

If you're not sure what skills are or how they relate to MCP servers, see Understanding skills for a conceptual overview.

Prerequisites

  • The ToolHive API server must be running. Start it in a separate terminal window (the command blocks while running):

    thv serve

    The server must remain running while you use thv skill commands.

    Using the ToolHive desktop app?

    If the ToolHive desktop app is already running, the API server is available automatically. You can skip the thv serve step and use thv skill commands directly.

  • A supported AI client installed. See the client compatibility reference for which clients support skills.

Install a skill

You can install skills from a ToolHive Registry Server (by name), an OCI registry (by reference), or a Git repository (by URL).

Install from the registry

The simplest way to install a skill is by name. ToolHive looks up the skill in the configured Registry Server and installs it automatically:

thv skill install <SKILL_NAME>

For example:

thv skill install toolhive-cli-user

Install from an OCI registry

To install a specific version of a skill from an OCI registry, provide the full OCI reference:

thv skill install ghcr.io/<OWNER>/skills/<SKILL_NAME>:<TAG>

Install from a Git repository

To install a skill directly from a Git repository:

thv skill install git://github.com/anthropics/skills@main#skills/webapp-testing

The URL format is git://host/owner/repo[@ref][#path/to/skill], where @ref is a branch, tag, or commit hash, and #path points to the skill subdirectory.

What's happening?

When you install a skill, ToolHive:

  1. Resolves the skill source (registry, OCI, or Git)
  2. Downloads and extracts the skill files
  3. Writes the SKILL.md and supporting files to your AI client's skills directory
  4. Records the installation in its database

Your AI client discovers the skill automatically by reading from its skills directory.

Overwrite an existing skill

If a skill is already installed and you want to replace it, use the --force flag:

thv skill install my-skill --force

Target a specific client

If you have multiple supported clients, ToolHive installs the skill for the first one it detects. To control which client receives the skill, use the --clients flag:

thv skill install my-skill --clients claude-code

Install to multiple clients at once

You can install a skill to multiple clients in a single command by comma-separating client names:

thv skill install my-skill --clients claude-code,cursor

To install to every skill-supporting client at once, use the special all value:

thv skill install my-skill --clients all

If any client installation fails, ToolHive rolls back all changes for that install operation.

See the client compatibility reference for the full list of clients that support skills.

Add a skill to a group

You can organize skills into groups, just like MCP servers. Skills in a group are automatically installed to clients registered with that group:

thv skill install my-skill --group development

Choose a scope

Skills support two scopes that control where the skill files are installed:

  • User scope (default): Installs the skill globally for your user account. The skill is available across all projects.
  • Project scope: Installs the skill in a specific project directory. The skill is only available when working in that project.

Install a user-scoped skill

thv skill install my-skill

This installs the skill to your home directory (for example, ~/.claude/skills/my-skill/ for Claude Code).

Install a project-scoped skill

thv skill install my-skill --scope project --project-root /path/to/project

This installs the skill to the project directory (for example, /path/to/project/.claude/skills/my-skill/ for Claude Code).

note

The project root must be a Git repository. ToolHive validates this to prevent installing skills in arbitrary directories.

List installed skills

To see all installed skills:

thv skill list

The output shows the name, version, scope, status, clients, and source reference for each skill.

Filter the list

You can filter skills by scope, client, or group:

thv skill list --scope user
thv skill list --client claude-code
thv skill list --group development

Get JSON output

thv skill list --format json

View skill details

To see detailed information about a specific skill:

thv skill info <SKILL_NAME>

This shows the skill's name, version, description, scope, status, source reference, installation date, and associated clients.

Uninstall a skill

To remove an installed skill:

thv skill uninstall <SKILL_NAME>

For project-scoped skills, specify the scope and project root:

thv skill uninstall my-skill --scope project --project-root /path/to/project

This removes the skill files from all associated client directories and deletes the database record.

Pin and reconcile project skills

Project-scoped skills can be pinned to a lock file (toolhive.lock.yaml at the project root) that records each installed skill's resolved reference and digest. The lock file lets you commit the exact set of skills a project depends on, reinstall them deterministically on another machine, and gate upgrades in CI.

Experimental

The lock file, thv skill sync, and thv skill upgrade are experimental. Set TOOLHIVE_SKILLS_LOCK_ENABLED=true on the environment that runs thv serve (or the ToolHive desktop app) to enable them. With the flag unset, thv skill install behaves as before and the sync and upgrade commands return an error.

Project scope is required. User-scoped skills are not tracked by the lock file.

Reconcile installs against the lock file

Use thv skill sync to restore a project's installed skills to match the lock file. This is the typical entry point after cloning a project or checking out a branch that changed which skills are pinned:

cd /path/to/project
thv skill sync

Missing or drifted skills are reinstalled at their pinned digest. Sync prompts for confirmation before installing because skill content is a set of instructions that AI agents follow; pass --yes to skip the prompt in non-interactive contexts such as CI.

To report drift without changing anything (a CI freshness check):

thv skill sync --check

Exit code 2 means drift or missing entries were found (nothing was installed). Exit code 3 means one or more skills failed while others succeeded, so results are mixed. A generic error (exit code 1) means the command could not run.

To record lock entries for existing unmanaged installs, or to remove installs no longer present in the lock file:

thv skill sync --adopt
thv skill sync --prune

Upgrade project skills

Use thv skill upgrade to re-resolve pinned entries and install newer content where available:

thv skill upgrade

Pass one or more skill names to limit the upgrade to a subset. Skills pinned to an immutable reference (an OCI digest or a full Git commit hash) are reported as not upgradable - there is nothing newer to resolve to.

To see what would change without persisting anything:

thv skill upgrade --preview

For a CI freshness gate that fails when newer content is available but never installs:

thv skill upgrade --fail-on-changes

Verify skill signatures

When the lock file is enabled, ToolHive verifies signatures on project-scoped skill installs and re-verifies them on every thv skill sync. This gates the skill supply chain: a skill whose content or signer has changed since it was pinned will not silently replace the pinned version.

Verification is transparent - thv skill install my-skill for a signed OCI artifact succeeds without extra flags and records the signer identity in the lock file. The following sections cover the cases where you have to make an explicit choice.

Install an unsigned skill

By default, ToolHive rejects unsigned project-scoped installs with an error like:

unsigned skill "my-skill" rejected; set allow_unsigned
(--allow-unsigned) to record an exception

To allow the install and record the exception in the lock file:

thv skill install my-skill --scope project \
--project-root /path/to/project --allow-unsigned

Subsequent syncs of the same entry treat the recorded exception as the expected state; they do not re-prompt for the flag.

Upgrade to a differently signed skill

thv skill upgrade refuses to move a pinned skill to an artifact signed by a different identity, or to an unsigned artifact. The status column in the output reports the reason as signer-change-blocked.

To allow the upgrade and replace the recorded signer identity with the new one:

thv skill upgrade my-skill --allow-signer-change

Rotate trust deliberately - a signer change is the expected way a skill distribution transfers between publishers, but it also matches the pattern of a compromised release.

Verification coverage

  • OCI-installed skills carry a Sigstore bundle. ToolHive verifies the bundle against the public-good Sigstore instance, requiring a signed certificate timestamp, a transparency log entry, and an observer timestamp. The lock file records the signer's identity, certificate issuer, and optionally the repository URI and Sigstore instance URL.
  • Git-installed skills are verified against a gitsign commit signature. The signing time is checked against the leaf certificate's validity window. ToolHive does not yet validate the embedded Rekor transparency-log proof for Git installs, so the recorded provenance for these entries carries less assurance than the OCI equivalent.

Verification uses embedded Fulcio and Rekor roots, so it works offline once the skill and its bundle are on disk. thv skill sync re-verifies each entry offline against the recorded identity, and reports a signature mismatch as drift.

Create a skill

Every skill requires a SKILL.md file at the root of its directory. At a minimum, the file needs name and description fields in YAML frontmatter, followed by Markdown instructions for the agent:

my-skill/SKILL.md
---
name: my-skill
description: >-
What this skill does and when to use it. Include keywords that help agents
identify relevant tasks.
---
# Instructions

Step-by-step instructions for the agent...

The name must be lowercase alphanumeric with hyphens, must match the directory name, and must not start or end with a hyphen.

You can also add optional files in scripts/, references/, and assets/ subdirectories for executable code, documentation, and static resources.

For the full list of frontmatter fields (version, license, allowed-tools, and more) and directory structure details, see Understanding skills.

Build and publish skills

Once you've created a skill, you can package it as an OCI artifact and publish it to a registry for others to install.

Validate a skill

Before building, validate your skill directory to check for errors:

thv skill validate ./my-skill

This verifies that:

  • A SKILL.md file exists with valid frontmatter
  • The name and description fields are present
  • The name matches the directory name
  • No symlinks or path traversal issues exist

Build an OCI artifact

Package your skill into an OCI artifact:

thv skill build ./my-skill

To specify a custom tag:

thv skill build ./my-skill --tag ghcr.io/my-org/skills/my-skill:v1.0.0

The build command stores the artifact in your local OCI store and prints the reference.

Push to a registry

After building, push the artifact to a remote OCI registry:

thv skill push ghcr.io/my-org/skills/my-skill:v1.0.0
note

Pushing to a remote registry uses your existing container registry credentials (for example, from docker login or podman login). Make sure you're authenticated before pushing.

List and remove locally-built skill artifacts

After building skills locally, you can view and manage the artifacts stored in your local OCI store.

List locally-built artifacts

thv skill builds

This lists all OCI skill artifacts built locally with thv skill build. The output shows the tag, digest, name, and version of each artifact:

TAG DIGEST NAME VERSION
ghcr.io/my-org/skills/my-skill:v1.0.0 sha256:a1b2c3d4... my-skill 1.0.0
my-skill:latest sha256:e5f6a7b8... my-skill

For JSON output:

thv skill builds --format json

Remove a locally-built artifact

To remove an artifact from the local OCI store:

thv skill builds remove <TAG>

For example:

thv skill builds remove my-skill:latest

This removes the artifact and cleans up its blobs from the local store. If multiple tags share the same digest, the blobs are retained until all tags pointing to that digest are removed.

Next steps

Troubleshooting

Skill command fails with a connection error

All skill commands require the ToolHive API server to be running. Start it with:

thv serve

Then retry your skill command.

Skill not discovered by your AI client

If your AI client doesn't see an installed skill:

  1. Verify the skill is installed:

    thv skill list
  2. Check that the skill was installed for the correct client:

    thv skill info <SKILL_NAME>
  3. Verify the skill files exist in the expected directory. For example:

    • Claude Code: ~/.claude/skills/<SKILL_NAME>/ (user) or <PROJECT_ROOT>/.claude/skills/<SKILL_NAME>/ (project)
    • Cursor: ~/.cursor/skills/<SKILL_NAME>/ (user) or <PROJECT_ROOT>/.cursor/skills/<SKILL_NAME>/ (project)
  4. Restart your AI client to trigger skill discovery.

Skill validation fails

Run thv skill validate to see specific errors:

thv skill validate ./my-skill

Common issues include:

  • Missing SKILL.md file in the directory
  • Missing name or description in the frontmatter
  • Skill name doesn't match the directory name
  • Symlinks present in the skill directory (not allowed for security)
Signature verification errors on install or sync

Signature verification runs on project-scoped installs when TOOLHIVE_SKILLS_LOCK_ENABLED=true is set on the ToolHive server.

  • unsigned skill ... rejected: The artifact has no Sigstore bundle or Git signature. Pass --allow-unsigned to record the exception in the lock file, or use a signed release.
  • signer-change-blocked on upgrade: The candidate artifact is signed by a different identity than the recorded one, or is unsigned. Confirm the change is expected, then re-run with --allow-signer-change to rotate trust.
  • Sync reports a signature mismatch as drift: The stored bundle no longer verifies against the recorded identity. Run thv skill sync (without --check) to reinstall from the pinned reference, which re-runs install-time verification.
Push to registry fails with authentication error

Make sure you're authenticated with your container registry:

# For GitHub Container Registry
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin

# For Docker Hub
docker login

Then retry the push command.