2026-02-28 12:16:19 +08:00
# 🧰 OpenWebUI Skills Manager Tool
2026-03-16 01:21:11 +08:00
| By [Fu-Jie ](https://github.com/Fu-Jie ) · v0.3.0 | [⭐ Star this repo ](https://github.com/Fu-Jie/openwebui-extensions ) |
| :--- | ---: |
|  |  |  |  |  |  |  |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
2026-02-28 12:16:19 +08:00
A standalone OpenWebUI Tool plugin to manage native **Workspace > Skills ** for any model.
2026-02-28 23:06:08 +08:00
## What's New
2026-03-08 18:21:21 +08:00
- **🤖 Automatic Repo Root Discovery**: Install any GitHub repo by providing just the root URL (e.g., `https://github.com/owner/repo` ). System auto-converts to discovery mode and installs all skills.
- **🔄 Batch Deduplication**: Automatically removes duplicate URLs from batch installations and detects duplicate skill names.
2026-02-28 23:06:08 +08:00
- Added GitHub skills-directory auto-discovery for `install_skill` (e.g., `.../tree/main/skills` ) to install all child skills in one request.
- Fixed language detection with robust frontend-first fallback (`__event_call__` + timeout), request header fallback, and profile fallback.
2026-02-28 12:16:19 +08:00
## Key Features
- **🌐 Model-agnostic**: Can be enabled for any model that supports OpenWebUI Tools.
- **🛠️ Simple Skill Management**: Directly manage OpenWebUI skill records.
- **🔐 User-scoped Safety**: Operates on current user's accessible skills.
- **📡 Friendly Status Feedback**: Emits status bubbles for each operation.
2026-03-08 18:21:21 +08:00
- **🔍 Auto-Discovery**: Automatically discovers and installs all skills from GitHub repository trees.
- **⚙️ Smart Deduplication**: Removes duplicate URLs and detects conflicting skill names during batch installation.
2026-02-28 12:16:19 +08:00
## How to Use
1. Open OpenWebUI and go to **Workspace > Tools ** .
2026-02-28 23:20:30 +08:00
2. Install **OpenWebUI Skills Manager Tool ** from the official marketplace.
2026-02-28 12:16:19 +08:00
3. Enable this tool for your model/chat.
4. Ask the model to call tool operations, for example:
- "List my skills"
- "Show skill named docs-writer"
- "Create a skill named meeting-notes with content ..."
- "Update skill ..."
- "Delete skill ..."
2026-02-28 23:20:30 +08:00
### Manual Installation (Alternative)
- Create a new Tool and paste `openwebui_skills_manager.py` .
2026-02-28 15:53:04 +08:00
## Example: Install Skills
2026-03-08 18:21:21 +08:00
This tool can fetch and install skills directly from URLs (supporting GitHub repo roots, tree/blob, raw markdown, and .zip/.tar archives).
### Auto-discover all skills from a GitHub repo
- "Install skills from <https://github.com/nicobailon/visual-explainer>" ← Auto-discovers all subdirectories
- "Install all skills from <https://github.com/anthropics/skills>" ← Installs entire skills directory
2026-02-28 15:53:04 +08:00
### Install a single skill from GitHub
2026-02-28 23:13:16 +08:00
- "Install skill from <https://github.com/anthropics/skills/tree/main/skills/xlsx>"
2026-02-28 15:53:04 +08:00
- "Install skill from <https://github.com/Fu-Jie/openwebui-extensions/blob/main/.agent/skills/test-copilot-pipe/SKILL.md>"
### Batch install multiple skills
2026-02-28 23:13:16 +08:00
- "Install these skills: ['https://github.com/anthropics/skills/tree/main/skills/xlsx', 'https://github.com/anthropics/skills/tree/main/skills/docx']"
2026-02-28 15:53:04 +08:00
2026-03-08 18:21:21 +08:00
> **Tip**: For GitHub, the tool automatically resolves directory (tree) URLs by looking for `SKILL.md`.
## Installation Logic
### URL Type Recognition & Processing
The `install_skill` method automatically detects and handles different URL formats with the following logic:
#### **1. GitHub Repository Root** (Auto-Discovery)
**Format:** `https://github.com/owner/repo` or `https://github.com/owner/repo/`
**Processing:**
1. Detected via regex: `^https://github\.com/([^/]+)/([^/]+)/?$`
2. Automatically converted to: `https://github.com/owner/repo/tree/main`
3. API queries all subdirectories at `/repos/{owner}/{repo}/contents?ref=main`
4. For each subdirectory, creates skill URLs
5. Attempts to fetch `SKILL.md` from each directory
6. All discovered skills installed in **batch mode **
**Example Flow:**
```
Input: https://github.com/nicobailon/visual-explainer
↓ [Detect: repo root]
↓ [Convert: add /tree/main]
↓ [Query: GitHub API for subdirs]
Discover: skill1, skill2, skill3, ...
↓ [Batch mode]
Install: All skills found
```
#### **2. GitHub Tree (Directory) URL** (Auto-Discovery)
**Format:** `https://github.com/owner/repo/tree/branch/path/to/directory`
**Processing:**
1. Detected via regex: `/tree/` in URL
2. API queries directory contents: `/repos/{owner}/{repo}/contents/path?ref=branch`
3. Filters for subdirectories (skips `.hidden` dirs)
4. For each subdirectory, attempts to fetch `SKILL.md`
5. All discovered skills installed in **batch mode **
**Example:**
```
Input: https://github.com/anthropics/skills/tree/main/skills
↓ [Query: /repos/anthropics/skills/contents/skills?ref=main]
Discover: xlsx, docx, pptx, markdown, ...
Install: All 12 skills in batch mode
```
#### **3. GitHub Blob (File) URL** (Single Install)
**Format:** `https://github.com/owner/repo/blob/branch/path/to/SKILL.md`
**Processing:**
1. Detected via pattern: `/blob/` in URL
2. Converted to raw URL: `https://raw.githubusercontent.com/owner/repo/branch/path/to/SKILL.md`
3. Content fetched and parsed as single skill
4. Installed in **single mode **
**Example:**
```
Input: https://github.com/user/repo/blob/main/SKILL.md
↓ [Convert: /blob/ → raw.githubusercontent.com]
↓ [Fetch: raw markdown content]
Parse: Skill name, description, content
Install: Single skill
```
#### **4. Raw GitHub URL** (Single Install)
**Format:** `https://raw.githubusercontent.com/owner/repo/branch/path/to/SKILL.md`
**Processing:**
1. Direct download from raw content endpoint
2. Content parsed as markdown with frontmatter
3. Skill metadata extracted (name, description from frontmatter)
4. Installed in **single mode **
**Example:**
```
Input: https://raw.githubusercontent.com/Fu-Jie/openwebui-extensions/main/SKILL.md
↓ [Fetch: raw content directly]
Parse: Extract metadata
Install: Single skill
```
#### **5. Archive Files** (Single Install)
**Format:** `https://example.com/skill.zip` or `.tar` , `.tar.gz` , `.tgz`
**Processing:**
1. Detected via file extension: `.zip` , `.tar` , `.tar.gz` , `.tgz`
2. Downloaded and extracted safely:
- Validates member paths (prevents path traversal attacks)
- Extracts to temporary directory
3. Searches for `SKILL.md` in archive root
4. Content parsed and installed in **single mode **
**Example:**
```
Input: https://github.com/user/repo/releases/download/v1.0/my-skill.zip
↓ [Download: zip archive]
↓ [Extract safely: validate paths]
↓ [Search: SKILL.md]
Parse: Extract metadata
Install: Single skill
```
### Batch Mode vs Single Mode
| Mode | Triggered By | Behavior | Result |
|------|--------------|----------|--------|
| **Batch ** | Repo root or tree URL | All subdirectories auto-discovered | List of { succeeded, failed, results } |
| **Single ** | Blob, raw, or archive URL | Direct content fetch and parse | { success, id, name, ... } |
| **Batch ** | List of URLs | Each URL processed individually | List of results |
### Deduplication During Batch Install
When multiple URLs are provided in batch mode:
1. **URL Deduplication ** : Removes duplicate URLs (preserves order)
2. **Name Collision Detection ** : Tracks installed skill names
- If same name appears multiple times → warning notification
- Action depends on `ALLOW_OVERWRITE_ON_CREATE` valve
**Example:**
```
Input URLs: [url1, url1, url2, url2, url3]
↓ [Deduplicate]
Unique: [url1, url2, url3]
Process: 3 URLs
Output: "Removed 2 duplicate URL(s)"
```
### Skill Name Resolution
During parsing, skill names are resolved in this order:
1. **User-provided name ** (if specified in `name` parameter)
2. **Frontmatter metadata ** (from `---` block at file start)
3. **Markdown h1 heading ** (first `# Title` found)
4. **Extracted directory/file name ** (from URL path)
5. **Fallback name: ** `"installed-skill"` (last resort)
**Example:**
```
Markdown document structure:
───────────────────────────
---
title: "My Custom Skill"
description: "Does something useful"
---
# Alternative Title
Content here...
───────────────────────────
Resolution order:
1. Check frontmatter: title = "My Custom Skill" ✓ Use this
2. (Skip other options)
Result: Skill created as "My Custom Skill"
```
### Safety & Security
All installations enforce:
- ✅ **Domain Whitelist ** (TRUSTED_DOMAINS): Only github.com, huggingface.co, githubusercontent.com allowed
- ✅ **Scheme Validation ** : Only http/https URLs accepted
- ✅ **Path Traversal Prevention ** : Archives validated before extraction
- ✅ **User Scope ** : Operations isolated per user_id
- ✅ **Timeout Protection ** : Configurable timeout (default 12s)
### Error Handling
| Error Case | Handling |
|-----------|----------|
| Unsupported scheme (ftp://, file://) | Blocked at validation |
| Untrusted domain | Rejected (domain not in whitelist) |
| URL fetch timeout | Timeout error with retry suggestion |
| Invalid archive | Error on extraction attempt |
| No SKILL.md found | Error per subdirectory (batch continues) |
| Duplicate skill name | Warning notification (depends on valve) |
| Missing skill name | Error (name is required) |
2026-02-28 15:53:04 +08:00
2026-02-28 12:16:19 +08:00
## Configuration (Valves)
| Parameter | Default | Description |
2026-03-08 18:21:21 +08:00
| --- | --- | --- |
2026-02-28 12:16:19 +08:00
| `SHOW_STATUS` | `True` | Show operation status updates in OpenWebUI status bar. |
| `ALLOW_OVERWRITE_ON_CREATE` | `False` | Allow `create_skill` /`install_skill` to overwrite same-name skill by default. |
| `INSTALL_FETCH_TIMEOUT` | `12.0` | URL fetch timeout in seconds for skill installation. |
2026-03-16 01:29:18 +08:00
| `TRUSTED_DOMAINS` | `github.com,huggingface.co,githubusercontent.com` | Comma-separated list of primary trusted domains for downloads (always enforced). Subdomains automatically allowed (e.g., `github.com` allows `api.github.com` ). See [Domain Whitelist Guide ](https://github.com/Fu-Jie/openwebui-extensions/blob/main/plugins/tools/openwebui-skills-manager/docs/DOMAIN_WHITELIST.md ). |
2026-02-28 12:16:19 +08:00
## Supported Tool Methods
| Method | Purpose |
2026-02-28 15:53:04 +08:00
| --- | --- |
2026-02-28 12:16:19 +08:00
| `list_skills` | List current user's skills. |
| `show_skill` | Show one skill by `skill_id` or `name` . |
| `install_skill` | Install skill from URL into OpenWebUI native skills. |
| `create_skill` | Create a new skill (or overwrite when allowed). |
2026-03-08 18:21:21 +08:00
| `update_skill` | Modify an existing skill by id or name. Update any combination of: `new_name` (rename), `description` , `content` , or `is_active` (enable/disable). Validates name uniqueness. |
2026-02-28 12:16:19 +08:00
| `delete_skill` | Delete a skill by `skill_id` or `name` . |
## Support
If this plugin has been useful, a star on [OpenWebUI Extensions ](https://github.com/Fu-Jie/openwebui-extensions ) is a big motivation for me. Thank you for the support.
## Others
- This tool manages OpenWebUI native skill records and supports direct URL installation.
- For advanced orchestration, combine with other Pipe/Tool workflows.
## Changelog
See full history in the GitHub repository releases and commits.