skillfiles
Parsing of local skill markdown files into the fields needed by the client.
A skill file is a Markdown document whose leading YAML frontmatter (between
--- fences) describes the skill. This module is intentionally pure: it has no
client import and performs no network access, so it can be unit-tested trivially.
Frontmatter keys consumed:
- name (str, required): display name of the skill.
- description (str, required): short description of the skill.
The full file text (frontmatter fences included) becomes the skill content,
which is what gets injected into chat context on the server.
Classes
InvalidSkillFileError
Bases: ValueError
Raised when a skill file cannot be parsed into a valid skill.
Causes include: no frontmatter block present, YAML that fails to parse, a
frontmatter block that does not decode to a mapping, or a missing/empty
name or description field.
ParsedSkillFile
A parsed skill file ready to be synced to Open WebUI.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Display name of the skill (from frontmatter). |
description |
str
|
Short description of the skill (from frontmatter). |
id |
str
|
Normalized Open WebUI id derived from |
content |
str
|
The complete file text, frontmatter block included. This is the text that Open WebUI stores as the skill content and injects into chat context when the skill is referenced. |
- Code Reference skillfiles Functions parse_skill_file
- Code Reference skillfiles Classes DiscoveredSkillFile
DiscoveredSkillFile
DiscoveredSkillFile(
path: Path,
parsed: Optional[ParsedSkillFile],
skip_reason: Optional[str],
)
One entry in a directory skill scan, produced by discover_skill_files.
Invariant: a file is syncable iff parsed is not None, in which case
skip_reason is None. Otherwise parsed is None and skip_reason explains
why the file was not syncable (e.g. not a skill, unparseable frontmatter, or
a duplicate normalized id).
Attributes:
| Name | Type | Description |
|---|---|---|
path |
Path
|
Path to the |
parsed |
Optional[ParsedSkillFile]
|
The |
skip_reason |
Optional[str]
|
Why this file is not syncable, or None when it is. |
- Code Reference skillfiles Functions discover_skill_files
Functions
normalize_skill_id
Normalize a skill name into its Open WebUI id.
Mirrors the backend normalization applied on create: lowercase the name and
replace spaces with hyphens. For example "My Cool Skill" becomes
"my-cool-skill".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The human-readable skill name. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The normalized id string. |
Source code in src/owui_client/skillfiles.py
parse_skill_file
parse_skill_file(path: str | Path) -> ParsedSkillFile
Parse a local Markdown skill file into name, description, id, and content.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Path to a |
required |
Returns:
| Type | Description |
|---|---|
ParsedSkillFile
|
|
Raises:
| Type | Description |
|---|---|
`InvalidSkillFileError`
|
If the file has no frontmatter, the frontmatter
is unparseable, or |
Source code in src/owui_client/skillfiles.py
discover_skill_files
discover_skill_files(
dir_path: str | Path,
) -> list[DiscoveredSkillFile]
Recursively discover and parse every Markdown skill file under a directory.
Walks dir_path at arbitrary depth (skills commonly live in their own
subdirs), deterministically sorted by path, and parses each .md file via
parse_skill_file. Files that are not valid skills (no frontmatter,
unparseable YAML, missing/empty name or description) are reported
with a skip_reason rather than raising, so one bad file does not abort the
whole scan.
After parsing, duplicate normalized ids among the successfully-parsed files
are detected: any id claimed by more than one file marks ALL of those files
as skipped (parsed set to None) with a reason naming the other files.
This function is pure and performs no network access.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dir_path
|
str | Path
|
Directory to scan recursively. |
required |
Returns:
| Type | Description |
|---|---|
list[DiscoveredSkillFile]
|
A list of |
Raises:
| Type | Description |
|---|---|
`InvalidSkillFileError`
|
If |