Skip to content
Navigation

Multi-source skill registry for loading skills from local paths and GitHub repositories.

Module: orbiter.skills

python
from orbiter.skills import (
    Skill,
    SkillRegistry,
    SkillError,
    ConflictStrategy,
    parse_github_url,
    extract_front_matter,
    DEFAULT_CACHE_DIR,
    SKILL_FILENAMES,
)

SkillError

python
class SkillError(OrbiterError)

Raised for skill loading or registry errors (missing directories, duplicate skills with raise strategy, etc.). Inherits from OrbiterError.


ConflictStrategy

python
class ConflictStrategy(StrEnum)

How to handle duplicate skill names across sources.

Values

MemberValueDescription
KEEP_FIRST"keep_first"Keep the first skill loaded with a given name (default).
KEEP_LAST"keep_last"Replace with the latest skill loaded with a given name.
RAISE"raise"Raise a SkillError on duplicate names.

Constants

DEFAULT_CACHE_DIR

python
DEFAULT_CACHE_DIR = Path.home() / ".orbiter" / "skills"

Default directory for caching GitHub repository clones.

SKILL_FILENAMES

python
SKILL_FILENAMES = {"skill.md", "SKILL.md"}

Recognized filenames for skill definitions.


Skill

python
class Skill

A loaded skill with metadata and usage content. Uses __slots__ for memory efficiency.

Constructor

python
def __init__(
    self,
    *,
    name: str,
    description: str = "",
    usage: str = "",
    tool_list: dict[str, list[str]] | None = None,
    skill_type: str = "",
    active: bool = True,
    path: str = "",
) -> None
NameTypeDefaultDescription
namestr(required)Unique skill name.
descriptionstr""Human-readable description.
usagestr""Markdown body content (usage instructions).
tool_listdict[str, list[str]] | NoneNoneMapping of tool names to action lists.
skill_typestr""Skill type — empty string for tool skills, "agent" for agent skills.
activeboolTrueWhether the skill starts active.
pathstr""Filesystem path to the source skill.md file.

Attributes

NameTypeDescription
namestrSkill name.
descriptionstrSkill description.
usagestrMarkdown usage content.
tool_listdict[str, list[str]]Tool name to action list mapping.
skill_typestrSkill type identifier.
activeboolWhether the skill is active.
pathstrSource file path.

Example

python
from orbiter.skills import Skill

skill = Skill(
    name="web_search",
    description="Search the web for information.",
    usage="Use this skill to find up-to-date information.",
    tool_list={"search_api": ["search", "fetch_page"]},
    active=True,
)
print(skill)  # Skill(name='web_search', type='', active=True)

SkillRegistry

python
class SkillRegistry

Multi-source skill registry. Loads skills from local filesystem paths and GitHub repository URLs. Remote repositories are shallow-cloned and cached.

Constructor

python
def __init__(
    self,
    *,
    conflict: ConflictStrategy | str = ConflictStrategy.KEEP_FIRST,
    cache_dir: Path | None = None,
) -> None
NameTypeDefaultDescription
conflictConflictStrategy | strConflictStrategy.KEEP_FIRSTStrategy for handling duplicate skill names.
cache_dirPath | NoneNoneDirectory for caching GitHub clones. Defaults to ~/.orbiter/skills/.

Properties

skills

python
@property
def skills(self) -> dict[str, Skill]

All loaded skills keyed by name. Returns a copy of the internal dict.

Methods

register_source()

python
def register_source(self, source: str) -> None

Add a skill source (local path or GitHub URL).

NameTypeDefaultDescription
sourcestr(required)Local directory path or GitHub repository URL.

load_all()

python
def load_all(self) -> dict[str, Skill]

Load skills from all registered sources.

Returns: Dict mapping skill name to Skill.

Raises: SkillError on conflict when strategy is RAISE.

get()

python
def get(self, name: str) -> Skill

Retrieve a skill by name.

NameTypeDefaultDescription
namestr(required)The skill name.

Returns: The Skill instance.

Raises: SkillError if the skill is not found.

python
def search(
    self,
    *,
    query: str = "",
    skill_type: str | None = None,
    active_only: bool = False,
) -> list[Skill]

Search skills by text query, type, and active status.

NameTypeDefaultDescription
querystr""Case-insensitive substring to match against name or description.
skill_typestr | NoneNoneFilter by skill type (e.g. "agent").
active_onlyboolFalseIf True, only return active skills.

Returns: List of matching skills.

list_names()

python
def list_names(self) -> list[str]

Return all loaded skill names.

Returns: List of name strings.

Example

python
from orbiter.skills import SkillRegistry, ConflictStrategy

reg = SkillRegistry(conflict=ConflictStrategy.KEEP_LAST)

# Register local skills
reg.register_source("/path/to/my/skills")

# Register GitHub skills
reg.register_source("https://github.com/user/repo/tree/main/skills")

# Load all skills
skills = reg.load_all()
for name, skill in skills.items():
    print(f"{name}: {skill.description}")

# Search
results = reg.search(query="search", active_only=True)

# Get specific skill
web_skill = reg.get("web_search")
print(web_skill.usage)

parse_github_url()

python
def parse_github_url(url: str) -> dict[str, str] | None

Parse a GitHub URL into owner, repo, branch, and subdirectory.

Parameters

NameTypeDefaultDescription
urlstr(required)A GitHub URL.

Returns

Dict with keys owner, repo, branch, subdir, or None if the URL is not a valid GitHub URL.

Example

python
from orbiter.skills import parse_github_url

result = parse_github_url("https://github.com/user/repo/tree/main/skills")
# {"owner": "user", "repo": "repo", "branch": "main", "subdir": "skills"}

result = parse_github_url("https://github.com/user/repo")
# {"owner": "user", "repo": "repo", "branch": "main", "subdir": ""}

result = parse_github_url("not a github url")
# None

extract_front_matter()

python
def extract_front_matter(text: str) -> tuple[dict[str, Any], str]

Extract YAML front-matter and body from a markdown skill file.

Parameters

NameTypeDefaultDescription
textstr(required)Full text content of a skill.md file.

Returns

Tuple of (front_matter_dict, body_string). Front-matter keys are lowercased. The tool_list value is JSON-parsed if present. The active value is converted to a boolean.

Example

python
from orbiter.skills import extract_front_matter

text = """---
name: my_skill
description: A useful skill
active: true
tool_list: {"search": ["web_search"]}
---
# Usage
Use this skill to search the web.
"""

meta, body = extract_front_matter(text)
# meta = {"name": "my_skill", "description": "A useful skill", "active": True, "tool_list": {"search": ["web_search"]}}
# body = "# Usage\nUse this skill to search the web."

Skill File Format

Skills are defined in skill.md or SKILL.md files with YAML front-matter:

markdown
---
name: web_search
description: Search the web for current information
type: agent
active: true
tool_list: {"search_api": ["search", "fetch"]}
---
# Web Search Skill

Use this skill when you need to find up-to-date information.

## Usage
1. Call the search_api tool with your query
2. Process the results

Front-Matter Fields

FieldTypeDescription
namestringSkill name (falls back to parent directory name if absent).
descriptionstringHuman-readable description (also accepts desc).
typestringSkill type: empty for tool skills, "agent" for agent skills.
activebooleanWhether the skill starts active (true/false).
tool_listJSON objectMapping of tool names to action lists.