Skip to content

Skills and resources

Skill

Skill is a Rust-backed domain object representing an agent skill conforming to the Agent Skills specification.

from skilly import Skill

skill = Skill(
    name="code-review",
    description="Review code for correctness and maintainability.",
    body="# Instructions\n\nReview the proposed change.",
)

Constructor parameters

Parameter Type Description
name str Skill name (used as directory name).
description str What the skill does and when to use it.
body str Markdown body for a programmatically constructed SKILL.md.
path StrPath \| None Filesystem path if loaded from disk.
license str \| None License name or reference.
compatibility str \| None Environment requirements.
metadata dict[str, str] \| None Additional frontmatter metadata.
allowed_tools str \| None Space-separated pre-approved tools.
resources list[SkillResourceLike] \| None Bundled resource files.

Key properties

Property Type Description
name str Skill name.
description str Description text.
text str Canonical reconstructed SKILL.md text.
raw bytes Exact source bytes for a discovered SKILL.md; canonical bytes for a constructed skill.
is_text() bool Whether raw is valid UTF-8.
path Path \| None Filesystem path if loaded from disk.
license str \| None License identifier.
compatibility str \| None Environment requirements.
metadata dict[str, str] Frontmatter metadata.
allowed_tools str \| None Allowed tools string.
resources list[SkillResource] Bundled resources.
directory_name str Normalized directory name for the skill.
source str Origin source identifier.
repository_provider str \| None Repository provider for repository-backed installs.
repository_url str \| None Canonical repository skill URL used for updates.
repository_commit_sha str \| None Immutable repository revision used for installation.

File content

Use raw when exact source bytes matter (for example, for a hash or archive) and text when you need a readable SKILL.md reconstruction. Every bundled file is exposed through resources, scripts, references, or assets and uses the same raw, text, and is_text() interface.

skill.raw
skill.text

for resource in skill.resources:
    if resource.is_text():
        print(resource.text)
    else:
        save_bytes(resource.raw)

Repository discovery

from collections.abc import Mapping

from skilly import RepositoryDiscoveryClient, parse_repository_location


class ApplicationTransport:
    def get(
        self,
        url: str,
        *,
        headers: Mapping[str, str],
        params: Mapping[str, str],
    ) -> bytes:
        # Delegate to the application's vetted HTTP client. It must enforce
        # its DNS, redirect, timeout, response-size, concurrency, and status
        # policies before returning the complete body.
        return application_http_client.get_bytes(
            url, headers=headers, params=params
        )

location = parse_repository_location("https://bitbucket.org/example/skills")
discovery = RepositoryDiscoveryClient(ApplicationTransport())
skills = discovery.discover("https://bitbucket.org/example/skills")

data_center = parse_repository_location(
    "https://git.example.com/bitbucket/projects/ENG/repos/skills",
    provider="bitbucket-data-center",
)

Supported providers are "github", "bitbucket-cloud", and "bitbucket-data-center". GitHub and Bitbucket Cloud are detected from their public URLs. Pass provider="bitbucket-data-center" for Bitbucket Data Center.

RepositoryDiscoveryClient has no built-in network fallback. Its transport receives every request made during ref resolution, provider traversal, pagination, and archive/file retrieval. The transport must reject unwanted redirects and non-public resolved addresses, apply connect/read/total timeouts, cap the complete response body before returning it, limit its own concurrency, and raise for unsuccessful responses. It also owns authentication and proxy/TLS policy. Skilly continues to validate provider payloads, repository paths, and archive/resource limits.

Class methods

# Load from a SKILL.md file
skill = Skill.from_file("path/to/SKILL.md")

# Load from a directory containing SKILL.md
skill = Skill.from_dir("path/to/skill/dir")

# Parse from raw markdown text
skill = Skill.from_text(text)

# Load a complete bundle from exact in-memory bytes
skill = Skill.from_bundle(skill_markdown, resources)

In-memory bundles

Skill.from_bundle(skill_markdown, resources=()) loads and validates a complete bundle without reading or writing a filesystem, executing a bundled script, importing modules, invoking a shell, or making network requests. It preserves the supplied SKILL.md bytes in skill.raw and each resource's bytes in resource.raw.

from pathlib import PurePosixPath

from skilly import Skill, SkillBundleError, SkillResource

try:
    skill = Skill.from_bundle(
        b"---\nname: on-call\ndescription: Runbook instructions.\n---\nRead first.\n",
        (
            SkillResource(
                relative_path=PurePosixPath("references/runbook.md"),
                kind="reference",
                raw=b"# Runbook\n",
            ),
        ),
    )
except SkillBundleError as error:
    print(error.code, error.path, error.field)

SkillBundleError is a ValueError with stable code, path, and optional field attributes. Current codes are invalid_utf8, invalid_frontmatter, invalid_field, invalid_resource_path, and duplicate_resource_path. Resource kind remains caller-provided metadata; it is not inferred from or checked against the path.

Instance methods

# Check if the skill is installed
skill.is_installed()

# Check whether a skill can be refreshed
skill.is_dependency()
skill.can_update()

# Compare with another skill
skill.matches(other)

# Get a specific resource by path
resource = skill.get_resource("scripts/deploy.sh")

# Install to a directory
skill.install_to(directory=".agents/skills", skill_name="my-skill")

SkillResource

from skilly import SkillResource

resource = SkillResource(
    relative_path="scripts/deploy.sh",
    kind="script",
    raw=b"#!/bin/sh\necho Deploying...",
)
Field Type Description
relative_path PurePosixPath Path relative to the skill directory.
kind ResourceKind One of "script", "reference", "asset", "other".
raw bytes Exact file bytes.
text str UTF-8 decoded content; raises UnicodeDecodeError for binary files.
is_text() bool Whether text can be read without a decoding error.

ResourceKind

Type alias for Literal["script", "reference", "asset", "other"].

Repository provenance

Repository discovery records repository_provider, repository_url, and repository_commit_sha automatically. Use RepositoryDiscoveryClient for all remote skills, then install the selected result with SkillRepository. Pass the same client to SkillRepository(discovery_client=...) when repository-backed updates must use that network boundary too.