Automatically share skills, migrate local skills to code repositories, open source skills, skill version management, configure git remote
Migrate user's locally created temporary skills to a project repository via symlinks, and initialize Git for version tracking.
| Command | Description |
|---|---|
/share-skill <skill-name> |
Migrate specified skill to code repository and initialize git |
/share-skill config |
Configure code_root and other settings |
/share-skill <skill-name> --remote <url> |
Migrate and configure remote URL |
/share-skill list |
List all local skills available for migration |
/share-skill remote <alias> <endpoint> |
Configure Git remote alias |
/share-skill remote list |
List configured remote aliases |
/share-skill docs |
Generate documentation website for the repository |
/share-skill docs --style <name> |
Generate docs with specified design style |
/share-skill docs --skill <ui-skill> |
Use specified UI skill to design docs |
/share-skill docs config |
Configure default design style or UI skill |
/share-skill allow |
One-time authorization for this skill's permissions |
| Natural language | e.g., "Help me open source port-allocator and push to github" |
All settings are stored in ~/.claude/share-skill-config.json:
{
"code_root": "~/Codes",
"skills_repo": "skills",
"github_username": "guo-yu",
"remotes": {
"github": "git@github.com:guo-yu/skills",
"gitlab": "git@gitlab.com:guo-yu/skills"
},
"default_remote": "github",
"auto_detected": true,
"docs": {
"style": "botanical",
"custom_skill": null,
"custom_domain": null
}
}
Configuration Fields:
| Field | Description | Default |
|---|---|---|
code_root |
Base directory for code repositories | ~/Codes |
skills_repo |
Name of skills repository folder | skills |
github_username |
GitHub username for URLs | Auto-detected |
remotes |
Git remote aliases | Auto-configured |
docs.custom_domain |
Custom domain for docs site | null (use GitHub Pages) |
Path Variables:
Throughout this document, the following variables are used:
{code_root} → Value of code_root config (e.g., ~/Codes){skills_repo} → Value of skills_repo config (e.g., skills){skills_path} → {code_root}/{skills_repo} (e.g., ~/Codes/skills){username} → Value of github_username configshare-skill automatically creates a Claude Code Plugin Marketplace structure, enabling users to install skills via the /plugin command.
Once your skills repository is set up, users can install skills with:
# Add the marketplace (one-time setup)
/plugin marketplace add {username}/{skills_repo}
# Install individual skills
/plugin install port-allocator@{username}-{skills_repo}
/plugin install share-skill@{username}-{skills_repo}
The repository requires two types of manifest files:
1. Root marketplace.json ({skills_path}/.claude-plugin/marketplace.json):
{
"name": "{username}-{skills_repo}",
"owner": {
"name": "{display-name}",
"email": "{username}@users.noreply.github.com"
},
"metadata": {
"description": "A collection of productivity skills for Claude Code",
"version": "1.0.0"
},
"plugins": [
{
"name": "skill-name",
"source": "./skill-name",
"description": "Skill description from SKILL.md frontmatter"
}
]
}
2. Plugin manifest ({skills_path}/<skill-name>/.claude-plugin/plugin.json):
{
"name": "skill-name",
"description": "Skill description",
"version": "1.0.0"
}
{skills_path}/
├── .claude-plugin/
│ └── marketplace.json # Root marketplace config
├── port-allocator/
│ ├── .claude-plugin/
│ │ └── plugin.json # Plugin manifest
│ ├── SKILL.md
│ └── ...
├── share-skill/
│ ├── .claude-plugin/
│ │ └── plugin.json
│ ├── SKILL.md
│ └── ...
└── docs/
└── ...
| Command | Description |
|---|---|
/plugin marketplace add <repo> |
Add a marketplace (GitHub: owner/repo) |
/plugin marketplace update |
Update all marketplace indexes |
/plugin install <name>@<marketplace> |
Install a plugin from marketplace |
/plugin validate . |
Validate marketplace structure |
On first invocation of share-skill, it automatically detects settings:
Auto-detection Logic:
Check if config file exists
if [ ! -f ~/.claude/share-skill-config.json ]; then
# First run, perform auto-detection
fi
Detect code_root directory
# Check common code directory locations in order
for dir in ~/Codes ~/Code ~/Projects ~/Dev ~/Development ~/repos; do
if [ -d "$dir" ]; then
CODE_ROOT="$dir"
break
fi
done
# If none found, default to ~/Codes
CODE_ROOT="${CODE_ROOT:-~/Codes}"
Read Git global config for username
# Try to get username
USERNAME=$(git config --global user.name)
# If username contains spaces, try extracting from GitHub email
if [[ "$USERNAME" == *" "* ]]; then
EMAIL=$(git config --global user.email)
# Extract from xxx@users.noreply.github.com
USERNAME=$(echo "$EMAIL" | grep -oP '^\d+-?\K[^@]+(?=@users\.noreply\.github\.com)')
fi
# If still unable to determine, try extracting from remote URL
if [ -z "$USERNAME" ]; then
USERNAME=$(git config --global --get-regexp "url.*github.com" | grep -oP 'github\.com[:/]\K[^/]+' | head -1)
fi
Generate default config
{
"code_root": "<detected-code-root>",
"skills_repo": "skills",
"github_username": "<detected-username>",
"remotes": {
"github": "git@github.com:<detected-username>/skills"
},
"default_remote": "github",
"auto_detected": true,
"docs": {
"style": "botanical",
"custom_skill": null,
"custom_domain": null
}
}
Output detection result
First run, auto-detecting settings...
Detected settings:
Code root: ~/Codes
GitHub username: guo-yu
Auto-configured:
Skills path: ~/Codes/skills
Remote: git@github.com:guo-yu/skills
Config file: ~/.claude/share-skill-config.json
To modify, use:
/share-skill config
/share-skill configInteractive configuration for share-skill settings:
TUI Interface (AskUserQuestion):
Configure share-skill settings:
Code root directory:
Current: ~/Codes
[ ] ~/Codes
[ ] ~/Code
[ ] ~/Projects
[ ] Other... (enter custom path)
Custom domain for documentation:
Current: (none - using GitHub Pages)
[ ] No custom domain (use {username}.github.io/{repo})
[ ] Enter custom domain...
Implementation:
# Read current config
CONFIG=$(cat ~/.claude/share-skill-config.json 2>/dev/null || echo '{}')
# After user selection, update config
# Example: Update code_root
jq --arg root "$NEW_CODE_ROOT" '.code_root = $root' <<< "$CONFIG" > ~/.claude/share-skill-config.json
If settings cannot be auto-detected, prompt user to configure:
Unable to auto-detect settings
Please configure manually:
/share-skill config
Or specify when migrating:
/share-skill <skill-name> --remote git@github.com:your-username/skills.git
When user invokes via natural language, intelligent analysis is needed:
User might say:
xxxDefault behavior: Use auto-detected username + default repository name skills
User might say:
git@github.com:<username>/skills/<skill-name>.gitImportant rule: Modifying remote path requires explicit specification
If user wants to use non-default remote path, must explicitly specify via:
Explicit command-line specification
/share-skill <skill-name> --remote git@github.com:other-user/other-repo.git
Explicit path in natural language
OK: "Help me push port-allocator to git@github.com:my-org/tools.git"
OK: "Open source to gitlab, address is git@gitlab.com:team/shared-skills.git"
NOT OK: "Help me push to somewhere else" (unclear, will ask for specific address)
NOT OK: "Use another repository" (unclear, will ask for specific address)
Address Resolution Rules:
"Help me open source xxx"
-> Use default config: git@github.com:<auto-detected-user>/skills
-> Final address: git@github.com:<user>/skills/<skill-name>.git
"Push to git@github.com:other-user/repo.git"
-> Detected full address, use directly
"Open source to gitlab" (gitlab not configured)
-> Prompt: Please specify full GitLab address
Skills may exist at the following locations, searched by priority:
# 1. Standard skills directory
~/.claude/skills/<skill-name>/SKILL.md
# 2. User custom skills directory
~/.claude/skills/*/<skill-name>/SKILL.md
# 3. Standalone skill file
~/.claude/skills/<skill-name>.md
# 4. Project-level skills (current working directory)
.claude/skills/<skill-name>/SKILL.md
Search command:
# Search for directories containing SKILL.md under ~/.claude
find ~/.claude -name "SKILL.md" -type f 2>/dev/null | while read f; do
dir=$(dirname "$f")
name=$(basename "$dir")
echo "$name: $dir"
done
# Or search for specific name
find ~/.claude -type d -name "<skill-name>" 2>/dev/null
After finding skill:
/share-skill remote <alias> <endpoint>Configure Git remote alias:
Read existing config
cat ~/.claude/share-skill-config.json 2>/dev/null || echo '{"remotes":{}}'
Update config
{
"remotes": {
"<alias>": "<endpoint>"
}
}
Write config file (preserve existing config)
Output confirmation
Remote alias configured
Alias: github
Address: git@github.com:guo-yu/skills
Usage:
/share-skill <skill-name> --remote github
or: "Help me open source xxx to github"
/share-skill remote listList configured remote aliases:
cat ~/.claude/share-skill-config.json | jq '.remotes'
Output format:
Configured remote aliases:
github -> git@github.com:guo-yu/skills
gitlab -> git@gitlab.com:guo-yu/skills
gitee -> git@gitee.com:guo-yu/skills
Default: github
/share-skill <skill-name> [--remote <url|alias>]Migrate specified skill from ~/.claude/ directory to {skills_path}/:
Search skill location
# First check standard location
if [ -d ~/.claude/skills/<skill-name> ]; then
SKILL_PATH=~/.claude/skills/<skill-name>
else
# Recursive search
SKILL_PATH=$(find ~/.claude -type d -name "<skill-name>" 2>/dev/null | head -1)
fi
Check target directory
ls {skills_path}/<skill-name> 2>/dev/null
Execute migration
# Create target directory (if doesn't exist)
mkdir -p {skills_path}
# Move skill to code directory
mv ~/.claude/skills/<skill-name> {skills_path}/
# Create symlink
ln -s {skills_path}/<skill-name> ~/.claude/skills/<skill-name>
Create .gitignore
cat > {skills_path}/<skill-name>/.gitignore << 'EOF'
# OS
.DS_Store
Thumbs.db
# Editor
.vscode/
.idea/
*.swp
*.swo
# Logs
*.log
# Temp
tmp/
temp/
EOF
Initialize Git
cd {skills_path}/<skill-name>
git init
git add .
git commit -m "Initial commit: <skill-name> skill"
Configure remote (if specified)
If user specified --remote:
# If it's an alias, resolve to full address
if [ "<remote>" is alias ]; then
ENDPOINT=$(read alias's endpoint from config)
REMOTE_URL="${ENDPOINT}/<skill-name>.git"
else
REMOTE_URL="<remote>"
fi
cd {skills_path}/<skill-name>
git remote add origin "$REMOTE_URL"
git push -u origin master
Ask when remote not specified
If user didn't specify remote, ask after migration using AskUserQuestion:
Do you want to configure Git remote address?
Options:
- Use github (git@github.com:guo-yu/skills/<skill-name>.git)
- Use gitlab (git@gitlab.com:guo-yu/skills/<skill-name>.git)
- Enter custom address
- Skip for now
Post-migration automation (automatic, no interaction)
After migration completes, automatically update all related files:
8.1 Update docs/js/main.js SKILLS config
// Add new skill to SKILLS object
const SKILLS = {
// ... existing skills
'<skill-name>': {
name: '<skill-name>',
description: '<extracted from SKILL.md frontmatter>',
path: '<skill-name>'
}
};
8.2 Update docs/js/main.js SKILL_MARKETING config
// Generate marketing content for the new skill
const SKILL_MARKETING = {
// ... existing skills
'<skill-name>': {
en: {
headline: '<generated from skill description>',
why: '<generated explanation>',
painPoints: [
{ icon: '🔥', title: '...', desc: '...' },
{ icon: '🧠', title: '...', desc: '...' },
{ icon: '💥', title: '...', desc: '...' }
],
triggers: [
'<natural language example 1>',
'<natural language example 2>'
]
},
'zh-CN': { /* Chinese translation including triggers */ },
ja: { /* Japanese translation including triggers */ }
}
};
8.3 Update all README files
Add new skill to the skills table in all language versions:
# Files to update:
# - {skills_path}/README.md
# - {skills_path}/README.zh-CN.md
# - {skills_path}/README.ja.md
# Extract description from SKILL.md frontmatter
DESCRIPTION=$(grep -A1 "^description:" {skills_path}/<skill-name>/SKILL.md | tail -1 | sed 's/^description: //')
# Add row to skills table in each README
# English: | [skill-name](./skill-name/) | Description |
# Chinese: | [skill-name](./skill-name/) | 中文描述 |
# Japanese: | [skill-name](./skill-name/) | 日本語説明 |
8.4 (Automatic) Skill lists are dynamically generated
The skill lists in navigation dropdown, mobile menu, and sidebar are
dynamically generated from the SKILLS object in main.js. No manual
HTML editing required - step 8.1 handles this automatically.
Icon SVG path guidelines (for step 8.1):
| Skill Type | SVG Icon Path |
|---|---|
| Port/Network | <circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/> |
| Sharing/Export | <circle cx="18" cy="5" r="3"/>...(share icon) |
| Security/Permissions | <rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/> |
| Translation/i18n | <circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3..."/> |
8.5 Generate translations using skill-i18n
Automatically invoke skill-i18n to translate SKILL.md:
# Check if skill-i18n is available
if [ -d ~/.claude/skills/skill-i18n ] || [ -L ~/.claude/skills/skill-i18n ]; then
# Use Skill tool to invoke skill-i18n with integration flags
# Skill: skill-i18n
# Args: --lang zh-CN,ja --files SKILL.md --skill <skill-name> --no-prompt --overwrite
#
# This generates:
# - {skills_path}/<skill-name>/SKILL.zh-CN.md
# - {skills_path}/<skill-name>/SKILL.ja.md
fi
Implementation: Use the Skill tool to invoke skill-i18n:
Skill(skill: "skill-i18n", args: "--lang zh-CN,ja --files SKILL.md --skill <skill-name> --no-prompt --overwrite")
If skill-i18n is not available, skip this step and output:
⚠ skill-i18n not found, skipping translations
Install with: ln -s {skills_path}/skill-i18n ~/.claude/skills/skill-i18n
8.6 Update cache version
# Update version numbers in docs/index.html
VERSION=$(date +%s)
sed -i '' "s/main.js?v=[0-9]*/main.js?v=$VERSION/" {skills_path}/docs/index.html
sed -i '' "s/custom.css?v=[0-9]*/custom.css?v=$VERSION/" {skills_path}/docs/index.html
8.7 Create/Update Plugin Marketplace structure
To enable installation via /plugin marketplace, create the plugin manifest files:
# Create plugin.json for the new skill
mkdir -p {skills_path}/<skill-name>/.claude-plugin
cat > {skills_path}/<skill-name>/.claude-plugin/plugin.json << EOF
{
"name": "<skill-name>",
"description": "<extracted from SKILL.md frontmatter>",
"version": "1.0.0"
}
EOF
Update the root marketplace.json to include the new skill:
# Read existing marketplace.json and add new plugin entry
# File: {skills_path}/.claude-plugin/marketplace.json
# Add to plugins array:
{
"name": "<skill-name>",
"source": "./<skill-name>",
"description": "<extracted from SKILL.md frontmatter>"
}
Marketplace structure after migration:
{skills_path}/
├── .claude-plugin/
│ └── marketplace.json # Root marketplace config
├── <skill-name>/
│ ├── .claude-plugin/
│ │ └── plugin.json # Plugin manifest
│ ├── SKILL.md
│ └── ...
└── ...
8.8 Commit all changes
cd {skills_path}
git add .
git commit -m "Add <skill-name>: update docs, README, translations, and plugin manifest"
git push # If remote is configured
Post-migration output:
Post-migration updates completed:
✓ Updated docs/js/main.js (SKILLS + SKILL_MARKETING)
✓ Updated README.md, README.zh-CN.md, README.ja.md
✓ Generated SKILL.zh-CN.md, SKILL.ja.md
✓ Updated cache version in docs/index.html
✓ Created .claude-plugin/plugin.json
✓ Updated .claude-plugin/marketplace.json
✓ Committed and pushed changes
Note: Skill lists (navbar, mobile menu, sidebar, install commands) are
dynamically generated from SKILLS config - no HTML editing needed.
/share-skill listList all local skills available for migration (excluding symlinks):
# Search for all directories containing SKILL.md under ~/.claude
echo "Discovered skills:"
find ~/.claude -name "SKILL.md" -type f 2>/dev/null | while read f; do
dir=$(dirname "$f")
name=$(basename "$dir")
if [ -L "$dir" ]; then
target=$(readlink "$dir")
echo " $name -> $target (migrated)"
else
echo " $name: $dir (available)"
fi
done
Skill migration successful
skill: <skill-name>
New location: {skills_path}/<skill-name>
Symlink: ~/.claude/skills/<skill-name> -> {skills_path}/<skill-name>
Git: Initialized and committed
Remote: git@github.com:guo-yu/skills/<skill-name>.git
Post-migration updates:
✓ Updated docs/js/main.js (SKILLS + SKILL_MARKETING)
✓ Updated README.md, README.zh-CN.md, README.ja.md
✓ Generated SKILL.zh-CN.md, SKILL.ja.md
✓ Updated cache version in docs/index.html
✓ Committed and pushed changes
Repository URL: https://github.com/guo-yu/skills
Skill migration successful
skill: <skill-name>
New location: {skills_path}/<skill-name>
Symlink: ~/.claude/skills/<skill-name> -> {skills_path}/<skill-name>
Git: Initialized and committed
Post-migration updates:
✓ Updated docs/js/main.js (SKILLS + SKILL_MARKETING)
✓ Updated README.md, README.zh-CN.md, README.ja.md
✓ Generated SKILL.zh-CN.md, SKILL.ja.md
✓ Updated cache version in docs/index.html
✓ Committed changes (not pushed - no remote configured)
Do you want to configure remote address?
Skill already migrated
<skill-name> is already a symlink:
~/.claude/skills/<skill-name> -> {skills_path}/<skill-name>
Local skills available for migration (N):
- art-master
- design-master
- prompt-generator
Migrated skills (M):
- port-allocator -> {skills_path}/port-allocator
- share-skill -> {skills_path}/share-skill
share-skill supports two Git management modes:
| Mode | Trigger | Git Structure | Remote |
|---|---|---|---|
| Monorepo | Default endpoint | Parent repo managed | guo-yu/skills |
| Standalone | Custom endpoint | Independent .git | User specified |
When using default endpoint, all skills are managed by parent repo {skills_path}/.git:
{skills_path}/
├── .git/ # Parent repo -> guo-yu/skills
├── .gitignore
├── README.md
├── port-allocator/ # No independent .git, managed by parent
│ ├── .gitignore
│ └── SKILL.md
├── share-skill/
│ ├── .gitignore
│ └── SKILL.md
└── skill-permissions/
├── .gitignore
└── SKILL.md
Operations:
# After adding new skill
cd {skills_path}
git add <new-skill>/
git commit -m "Add <new-skill>"
git push
When user specifies custom endpoint, that skill has independent .git:
{skills_path}/
├── .git/ # Parent repo
├── .gitignore # Contains: /custom-skill/
├── custom-skill/ # Independent repo -> user specified address
│ ├── .git/
│ └── SKILL.md
└── port-allocator/ # Managed by parent repo
Parent repo .gitignore auto-updates:
# Skills with custom endpoints
/custom-skill/
Regardless of mode, ~/.claude/skills/ uses symlinks:
~/.claude/skills/
├── port-allocator -> {skills_path}/port-allocator
├── share-skill -> {skills_path}/share-skill
└── skill-permissions -> {skills_path}/skill-permissions
If you encounter permission prompts, first run:
/share-skill allow
/share-skill allowExecute one-time authorization, adding permissions required by this skill to Claude Code config:
~/.claude/settings.jsonpermissions.allow:{
"permissions": {
"allow": [
"Bash(cat ~/.claude/*)",
"Bash(find ~/.claude *)",
"Bash(ls {skills_path}/*)",
"Bash(mkdir -p {skills_path}*)",
"Bash(mv ~/.claude/skills/* *)",
"Bash(ln -s {skills_path}/* *)",
"Bash(git *)",
"Bash(dirname *)",
"Bash(basename *)",
"Bash(readlink *)"
]
}
}
Output format:
Claude Code permissions configured
Added allowed command patterns:
- Bash(cat ~/.claude/*)
- Bash(find ~/.claude *)
- Bash(ls {skills_path}/*)
- Bash(mkdir -p {skills_path}*)
- Bash(mv ~/.claude/skills/* *)
- Bash(ln -s {skills_path}/* *)
- Bash(git *)
- Bash(dirname *)
- Bash(basename *)
- Bash(readlink *)
Config file: ~/.claude/settings.json
/share-skill allow to configure permissions firstshare-skill supports automatically generating elegant documentation websites to showcase skill usage instructions.
/share-skill docsGenerate GitHub Pages documentation website for skills repository.
Parameters:
--style <name>: Use preset design style (default: botanical)--skill <ui-skill>: Use specified UI skill for design--domain <domain>: Configure custom domain--i18n: Enable i18n language selection for SKILL.md and README filesSince generating multi-language documentation is time-consuming and token-intensive, users can select which languages to generate via an interactive TUI checkbox.
Trigger: When running /share-skill docs with --i18n flag, or when the command detects SKILL.md files need translation.
TUI Interface:
Select languages for documentation (Space to toggle, Enter to confirm):
[x] English (en) - Always generated
[ ] 简体中文 (zh-CN) - Simplified Chinese
[ ] 日本語 (ja) - Japanese
[ ] Other... - Enter custom language code
Selected: English
Default Selection:
Custom Language Input: When user selects "Other...", prompt for language code:
Enter language code (e.g., 'ko' for Korean, 'de' for German):
> ko
Language added: 한국어 (ko)
AskUserQuestion Implementation:
{
"questions": [
{
"question": "Which languages should be generated for documentation?",
"header": "Languages",
"multiSelect": true,
"options": [
{ "label": "English (en)", "description": "Required, always generated" },
{ "label": "简体中文 (zh-CN)", "description": "Simplified Chinese translation" },
{ "label": "日本語 (ja)", "description": "Japanese translation" },
{ "label": "Other...", "description": "Enter a custom language code" }
]
}
]
}
Generated Files Based on Selection:
| Selection | SKILL Files | README Files |
|---|---|---|
| English only | SKILL.md |
README.md |
| +Chinese | SKILL.md, SKILL.zh-CN.md |
README.md, README.zh-CN.md |
| +Japanese | SKILL.md, SKILL.ja.md |
README.md, README.ja.md |
| +Korean | SKILL.md, SKILL.ko.md |
README.md, README.ko.md |
Execution steps:
Check repository structure
# Confirm in skills repository directory
if [ ! -d {skills_path}/.git ]; then
echo "Please run this command in skills repository first"
exit 1
fi
Read config
# Read design preferences from config
cat ~/.claude/share-skill-config.json | jq '.docs'
Select design method
--skill specified: call corresponding UI skill (e.g., ui-ux-pro-max)--style (default botanical)Generate documentation website
mkdir -p {skills_path}/docs
mkdir -p {skills_path}/docs/css
mkdir -p {skills_path}/docs/js
Configure local development server
Handle based on endpoint config and existing package.json:
Scenario A: Monorepo mode (default endpoint)
Check if {skills_path}/package.json exists:
if [ -f {skills_path}/package.json ]; then
# Exists, only add docs-related scripts (don't overwrite existing content)
# Use jq or manual merge for scripts
else
# Doesn't exist, create new package.json
fi
package.json exists: Append dev:docs script
# Read existing package.json, add new script
jq '.scripts["dev:docs"] = "npx serve . -l <port>"' package.json > tmp.json
mv tmp.json package.json
package.json doesn't exist: Create new file
{
"name": "claude-code-skills",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "npx serve . -l <port>"
}
}
Scenario B: Standalone mode (custom endpoint)
Each skill has independent Git repository, check each package.json:
SKILL_DIR={skills_path}/<skill-name>
if [ -f "$SKILL_DIR/package.json" ]; then
# Important: don't overwrite user's existing package.json
# Only append docs script (if doesn't exist)
echo "Detected existing package.json, appending dev:docs script"
else
# Create minimal package.json
echo "Creating package.json..."
fi
Port allocation flow:
~/.claude/port-registry.json to get next available portSafety rules:
scripts fielddev script exists, use dev:docs as alternative command nameConfigure custom domain
Handle custom domain based on config:
# Read custom_domain from config
CUSTOM_DOMAIN=$(cat ~/.claude/share-skill-config.json | jq -r '.docs.custom_domain // empty')
USERNAME=$(cat ~/.claude/share-skill-config.json | jq -r '.github_username')
REPO=$(cat ~/.claude/share-skill-config.json | jq -r '.skills_repo')
# Check if CNAME already exists
if [ -f {skills_path}/docs/CNAME ]; then
EXISTING_DOMAIN=$(cat {skills_path}/docs/CNAME)
echo "CNAME already exists: $EXISTING_DOMAIN"
fi
First-time setup - Ask user via AskUserQuestion:
{
"questions": [{
"question": "Do you want to configure a custom domain for the documentation site?",
"header": "Domain",
"multiSelect": false,
"options": [
{ "label": "No custom domain", "description": "Use {username}.github.io/{repo}" },
{ "label": "Enter custom domain", "description": "e.g., docs.example.com" }
]
}]
}
Based on user selection:
if [ -n "$CUSTOM_DOMAIN" ]; then
# User has custom domain configured
echo "$CUSTOM_DOMAIN" > {skills_path}/docs/CNAME
# Update config
jq --arg domain "$CUSTOM_DOMAIN" '.docs.custom_domain = $domain' \
~/.claude/share-skill-config.json > tmp.json && mv tmp.json ~/.claude/share-skill-config.json
else
# No custom domain - remove CNAME if exists
rm -f {skills_path}/docs/CNAME
fi
Update footer link based on domain:
// main.js - Dynamic footer URL
function getDocsUrl() {
const config = { /* loaded from config or constants */ };
if (config.custom_domain) {
return `https://${config.custom_domain}/`;
}
return `https://${REPO_OWNER}.github.io/${REPO_NAME}/`;
}
Update cache version number
Auto-update resource file version numbers each time docs content is modified to avoid browser cache issues:
# Generate version number (using timestamp)
VERSION=$(date +%s)
# Update version number in index.html
sed -i '' "s/main.js?v=[0-9]*/main.js?v=$VERSION/" docs/index.html
sed -i '' "s/custom.css?v=[0-9]*/custom.css?v=$VERSION/" docs/index.html
Or use file hash:
JS_HASH=$(md5 -q docs/js/main.js | head -c 8)
CSS_HASH=$(md5 -q docs/css/custom.css | head -c 8)
sed -i '' "s/main.js?v=[a-z0-9]*/main.js?v=$JS_HASH/" docs/index.html
sed -i '' "s/custom.css?v=[a-z0-9]*/custom.css?v=$CSS_HASH/" docs/index.html
index.html template should contain version placeholders:
<link rel="stylesheet" href="css/custom.css?v=1">
<script src="js/main.js?v=1"></script>
Commit and push
git add docs/
git commit -m "Update documentation site"
git push
The generated documentation site includes the following features:
The navbar brand (avatar + title) links to the repository URL and is dynamically populated from GitHub API:
<!-- index.html -->
<a class="navbar-brand" id="repoLink" href="https://github.com/{username}/{repo}" target="_blank">
<img class="brand-avatar" id="userAvatar" src="" alt="Avatar">
<span class="brand-text" id="brandTitle">Skills</span>
</a>
// main.js - Update repo link dynamically
const repoLink = document.getElementById('repoLink');
if (repoLink) {
repoLink.href = `https://github.com/${REPO_OWNER}/${REPO_NAME}`;
}
The favicon uses the GitHub user's avatar image:
<!-- index.html head section -->
<link rel="icon" id="favicon" type="image/png" href="">
// main.js - Set favicon to user's avatar
const favicon = document.getElementById('favicon');
if (favicon) {
favicon.href = user.avatar_url;
}
Footer links to the documentation site, dynamically choosing between custom domain and GitHub Pages:
<footer class="footer">
<div class="footer-content">
<p>Made with <span class="heart">♥</span> by <a id="footerLink" href="">Yu's skills</a></p>
</div>
</footer>
// main.js - Set footer link based on custom_domain config
const CUSTOM_DOMAIN = null; // Set to domain string or null for GitHub Pages
function getDocsUrl() {
if (CUSTOM_DOMAIN) {
return `https://${CUSTOM_DOMAIN}/`;
}
return `https://${REPO_OWNER}.github.io/${REPO_NAME}/`;
}
// Update footer link
const footerLink = document.getElementById('footerLink');
if (footerLink) {
footerLink.href = getDocsUrl();
}
URL Selection Logic:
custom_domain config |
Footer URL |
|---|---|
null |
https://{username}.github.io/{repo}/ |
"docs.example.com" |
https://docs.example.com/ |
When loading language-specific SKILL.md files, add cache busting to ensure fresh content:
// main.js
const CACHE_VERSION = Date.now();
function getBasePath(skillName, lang = 'en') {
const fileName = lang === 'en' ? 'SKILL.md' : `SKILL.${lang}.md`;
if (isGitHubPages) {
// Add cache busting for GitHub raw content
return `https://raw.githubusercontent.com/${REPO_OWNER}/${REPO_NAME}/${BRANCH}/${skillName}/${fileName}?v=${CACHE_VERSION}`;
} else {
// Add cache busting for local development
return `../${skillName}/${fileName}?v=${CACHE_VERSION}`;
}
}
The main.js file should include repository configuration at the top:
// Repository configuration - UPDATE THESE VALUES
const REPO_OWNER = '{github-username}'; // e.g., 'guo-yu'
const REPO_NAME = '{repo-name}'; // e.g., 'skills'
const BRANCH = 'master'; // or 'main'
// Cache busting version
const CACHE_VERSION = Date.now();
Each skill displays a compelling marketing section above the documentation content, highlighting:
SKILL_MARKETING Data Structure in main.js:
const SKILL_MARKETING = {
'skill-name': {
en: {
headline: 'Compelling one-liner value proposition',
why: 'Detailed explanation of why this skill exists and how it helps users...',
painPoints: [
{
icon: '🔥',
title: 'Problem Title',
desc: 'Description of the problem this skill solves.'
},
{
icon: '🧠',
title: 'Another Problem',
desc: 'Description of another pain point.'
},
{
icon: '💥',
title: 'Third Problem',
desc: 'Description of the third issue addressed.'
}
],
triggers: [
'Example natural language prompt 1',
'Example natural language prompt 2'
]
},
'zh-CN': {
headline: '中文标题',
why: '中文说明...',
painPoints: [/* ... */],
triggers: [
'自然语言触发示例 1',
'自然语言触发示例 2'
]
},
ja: {
headline: '日本語タイトル',
why: '日本語説明...',
painPoints: [/* ... */],
triggers: [
'自然言語トリガー例 1',
'自然言語トリガー例 2'
]
}
}
};
Render Function:
function renderMarketingSection(skillName) {
const marketing = SKILL_MARKETING[skillName];
if (!marketing) return '';
const content = marketing[currentLang] || marketing['en'];
// Returns HTML with .marketing-section structure
}
CSS Classes:
.marketing-section - Container with gradient background.marketing-title - Gradient text headline.marketing-why - Value proposition paragraph.pain-points-grid - 3-column responsive grid.pain-point-card - Glass card with icon, title, descriptionTriggers Section (Natural Language Examples):
Display 2-3 example phrases users can say to trigger this skill. Shown below pain points.
// triggers field in SKILL_MARKETING
triggers: [
'Help me allocate a port for my project',
'Start the dev server for me'
]
Render Function for Triggers:
function renderTriggersSection(skillName) {
const marketing = SKILL_MARKETING[skillName];
if (!marketing) return '';
const content = marketing[currentLang] || marketing['en'];
if (!content || !content.triggers || content.triggers.length === 0) return '';
const t = I18N[currentLang];
const triggersHtml = content.triggers.map(trigger => `
<div class="trigger-item">
<span class="trigger-quote">"${trigger}"</span>
</div>
`).join('');
return `
<div class="triggers-section">
<h3 class="triggers-title">💬 ${t.triggersTitle}</h3>
<p class="triggers-desc">${t.triggersDesc}</p>
<div class="triggers-list">
${triggersHtml}
</div>
</div>
`;
}
CSS Classes for Triggers:
.triggers-section - Container with subtle background.triggers-title - Section heading with emoji.triggers-desc - Instruction text.triggers-list - Vertical list of examples.trigger-item - Individual example with left border accent.trigger-quote - Italic quoted textGuidelines for Writing Marketing Content:
The documentation site uses a three-column responsive layout:
<div class="main-container three-column">
<!-- Left Sidebar: Skills navigation + Table of Contents -->
<aside class="sidebar glass">
<div class="sidebar-content">
<div class="sidebar-section">
<h4 class="sidebar-heading" data-i18n="skills">Skills</h4>
<nav class="sidebar-nav">
<a class="sidebar-link" href="?skill=port-allocator">port-allocator</a>
<a class="sidebar-link" href="?skill=share-skill">share-skill</a>
<!-- ... more skills -->
</nav>
</div>
<div class="sidebar-section">
<h4 class="sidebar-heading" data-i18n="onThisPage">On This Page</h4>
<div class="js-toc"></div> <!-- Tocbot generates TOC here -->
</div>
</div>
</aside>
<!-- Main Content: Markdown documentation -->
<main class="main-content">
<article class="js-toc-content content-card glass" id="content">
<!-- Rendered markdown content -->
</article>
</main>
<!-- Right Sidebar: Installation instructions -->
<aside class="sidebar-right glass">
<!-- Installation section -->
</aside>
</div>
Responsive Behavior:
The right sidebar provides quick installation instructions:
<aside class="sidebar-right glass">
<div class="sidebar-content">
<div class="sidebar-section">
<!-- Natural language installation recommendation -->
<div class="install-natural">
<p class="install-natural-desc" data-i18n="installNaturalDesc">We recommend installing via natural language:</p>
<div class="install-natural-example">
"<span data-i18n="installNaturalExample">Please help me install this skill:</span> https://github.com/{username}/{repo}"
</div>
</div>
<!-- Command line installation -->
<div class="install-code">
<pre><code><span class="comment"># <span data-i18n="addMarketplace">Add marketplace</span></span>
<span class="cmd">/plugin marketplace add {username}/{repo}</span>
<span class="comment"># <span data-i18n="installSkills">Install skills</span></span>
<span class="cmd">/plugin install {skill-name}@{username}-{repo}</span></code></pre>
</div>
<a class="install-link" href="https://github.com/{username}/{repo}#installation" target="_blank" data-i18n="moreOptions">More installation options</a>
</div>
</div>
</aside>
CSS Classes for Natural Language Installation:
.install-natural - Container with bottom border separator.install-natural-desc - Recommendation text.install-natural-example - Quoted example with left border accenti18n Support for Installation and Triggers:
const I18N = {
en: {
installation: 'Installation',
installNaturalDesc: 'We recommend installing via natural language:',
installNaturalExample: 'Please help me install this skill:',
installDesc: 'The easiest way to install:',
addMarketplace: 'Add marketplace',
installSkills: 'Install skills',
moreOptions: 'More installation options',
triggersTitle: 'How to Use',
triggersDesc: 'Trigger this skill with natural language:'
},
'zh-CN': {
installation: '安装方法',
installNaturalDesc: '我们推荐使用自然语言安装:',
installNaturalExample: '请帮我安装这个 skill:',
installDesc: '最简单的安装方式:',
addMarketplace: '添加技能市场',
installSkills: '安装技能',
moreOptions: '更多安装选项',
triggersTitle: '如何调用',
triggersDesc: '使用自然语言即可触发此 skill:'
},
ja: {
installation: 'インストール',
installNaturalDesc: '自然言語でのインストールをお勧めします:',
installNaturalExample: 'このスキルをインストールしてください:',
installDesc: '最も簡単なインストール方法:',
addMarketplace: 'マーケットプレイスを追加',
installSkills: 'スキルをインストール',
moreOptions: 'その他のインストールオプション',
triggersTitle: '使い方',
triggersDesc: '自然言語でこのスキルを呼び出せます:'
}
};
Use Tocbot library to auto-generate table of contents from headings:
<!-- In <head> -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.32.2/tocbot.min.css">
<!-- Before closing </body> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.32.2/tocbot.min.js"></script>
// Initialize after content loads
tocbot.init({
tocSelector: '.js-toc',
contentSelector: '.js-toc-content',
headingSelector: 'h1, h2, h3',
scrollSmooth: true,
scrollSmoothDuration: 300,
headingsOffset: 100,
scrollSmoothOffset: -100
});
Use highlight.js for code block syntax highlighting:
<!-- In <head> -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
<!-- Before closing </body> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
// After rendering markdown
document.querySelectorAll('pre code').forEach((block) => {
hljs.highlightElement(block);
});
/share-skill docs configConfigure documentation generation default settings.
Interactive options:
Configure documentation website design
Design method:
1. Use preset style
2. Use UI skill
Preset styles:
- botanical (default): Natural botanical style, elegant and soft
- minimal: Minimalist black and white
- tech: Modern tech-forward style
UI skills:
- ui-ux-pro-max: Professional UI/UX design skill
- (other UI skills user has installed)
Custom domain: (optional)
botanical - Natural Botanical Style (default)Design Philosophy: A digital tribute to nature—breathing, flowing, rooted in organic beauty. Soft, refined, and thoughtful, rejecting the rigid technocratic coldness and hyper-digital sharpness of modern tech aesthetic in favor of warmth, tactility, and the imperfections of the natural world.
Core Elements:
Color System:
| Usage | Color | Value |
|---|---|---|
| Background | Warm white/Rice paper | #F9F8F4 |
| Foreground | Deep forest green | #2D3A31 |
| Primary | Sage green | #8C9A84 |
| Secondary | Soft clay/Mushroom | #DCCFC2 |
| Border | Stone | #E6E2DA |
| Interactive | Terracotta | #C27B66 |
Font Pairing:
Border Radius Rules:
rounded-3xl (24px)rounded-full (pill shape)rounded-t-full (arch) or rounded-[40px]Paper Texture Overlay (Critical):
<div
className="pointer-events-none fixed inset-0 z-50 opacity-[0.015]"
style={{
backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 400 400' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`,
backgroundRepeat: "repeat",
}}
/>
Shadow System:
/* Default */
box-shadow: 0 4px 6px -1px rgba(45, 58, 49, 0.05);
/* Medium */
box-shadow: 0 10px 15px -3px rgba(45, 58, 49, 0.05);
/* Large */
box-shadow: 0 20px 40px -10px rgba(45, 58, 49, 0.05);
Motion Guidelines:
duration-300 (button hover, link color)duration-500 (card lift, transforms)duration-700 to duration-1000 (image zoom)-translate-y-1 with enhanced shadowResponsive Strategy:
grid-cols-1 -> md:grid-cols-3If user has installed ui-ux-pro-max or other UI skills, can call it to design docs:
/share-skill docs --skill ui-ux-pro-max
Execution flow:
Detect if skill exists
if [ -d ~/.claude/skills/ui-ux-pro-max ] || [ -L ~/.claude/skills/ui-ux-pro-max ]; then
echo "Detected ui-ux-pro-max skill"
fi
Call skill to generate design
{skills_path}/docs/ directoryAsk design preference (if UI skill supports)
Using ui-ux-pro-max to design documentation website
Please select design style:
1. glassmorphism
2. claymorphism
3. minimalism
4. brutalism
5. neumorphism
6. bento-grid
Generation success:
Documentation website generated
Location: {skills_path}/docs/
Design style: botanical (Natural Botanical Style)
Custom domain: skill.guoyu.me
File structure:
docs/
├── index.html
├── CNAME
├── css/
│ └── custom.css
└── js/
└── main.js
Pushed to GitHub
Visit: https://skill.guoyu.me
GitHub Pages setup:
1. Repository Settings -> Pages
2. Source: Deploy from a branch
3. Branch: master, /docs
Using UI skill:
Documentation website generated
Location: {skills_path}/docs/
Design: ui-ux-pro-max (glassmorphism style)
Custom domain: skill.guoyu.me
Visit: https://skill.guoyu.me
share-skill automatically generates/updates multi-language README files when creating or updating repositories.
| Language | Filename | Language Code |
|---|---|---|
| English (default) | README.md |
en |
| Simplified Chinese | README.zh-CN.md |
zh-CN |
| Japanese | README.ja.md |
ja |
skills/
├── README.md # English (default)
├── README.zh-CN.md # Simplified Chinese
├── README.ja.md # Japanese
└── ...
Each README file contains language switch links at the top:
<p align="center">
<a href="README.md">English</a> |
<a href="README.zh-CN.md">简体中文</a> |
<a href="README.ja.md">日本語</a>
</p>
| Repository Type | English | Simplified Chinese | Japanese |
|---|---|---|---|
| Skill Set | {username}'s Skills |
{username} 的技能集 |
{username} のスキル |
| Single Skill | {username}'s Skill: {name} |
{username} 的技能: {name} |
{username} のスキル: {name} |
<p align="center">
<a href="README.md">English</a> |
<a href="README.zh-CN.md">简体中文</a> |
<a href="README.ja.md">日本語</a>
</p>
# {username}'s Skills
My collection of custom Claude Code skills for productivity and automation.
## Skills
| Skill | Description |
|-------|-------------|
| [port-allocator](./port-allocator/) | Automatically allocate development server ports |
| [share-skill](./share-skill/) | Migrate skills to repositories with Git support |
## Documentation
This skill set has an online documentation site generated by [share-skill](https://github.com/guo-yu/skills/tree/master/share-skill).
**With Custom Domain:**
https://{custom_domain}/
**GitHub Pages:**
https://{username}.github.io/{repo-name}/
### Setup GitHub Pages
1. Go to repository **Settings** -> **Pages**
2. Under "Source", select **Deploy from a branch**
3. Choose branch: `master` (or `main`), folder: `/docs`
4. (Optional) Add custom domain
## License
MIT
---
Made with ♥ by [Yu's skills](https://skill.guoyu.me/)
<p align="center">
<a href="README.md">English</a> |
<a href="README.zh-CN.md">简体中文</a> |
<a href="README.ja.md">日本語</a>
</p>
# {username} 的技能集
我的 Claude Code 自定义技能集合,用于提高生产力和自动化。
## 技能列表
| 技能 | 说明 |
|------|------|
| [port-allocator](./port-allocator/) | 自动分配开发服务器端口 |
| [share-skill](./share-skill/) | 将技能迁移到仓库并支持 Git 版本管理 |
## 在线文档
本技能集有一个由 [share-skill](https://github.com/guo-yu/skills/tree/master/share-skill) 生成的在线文档网站。
**自定义域名访问:**
https://{custom_domain}/
**GitHub Pages 访问:**
https://{username}.github.io/{repo-name}/
### 配置 GitHub Pages
1. 进入仓库 **Settings** -> **Pages**
2. 在 "Source" 下选择 **Deploy from a branch**
3. 选择分支: `master` (或 `main`),文件夹: `/docs`
4. (可选) 在 "Custom domain" 中添加自定义域名
## 许可证
MIT
---
Made with ♥ by [Yu's skills](https://skill.guoyu.me/)
<p align="center">
<a href="README.md">English</a> |
<a href="README.zh-CN.md">简体中文</a> |
<a href="README.ja.md">日本語</a>
</p>
# {username} のスキル
生産性と自動化のための Claude Code カスタムスキルコレクション。
## スキル一覧
| スキル | 説明 |
|--------|------|
| [port-allocator](./port-allocator/) | 開発サーバーポートの自動割り当て |
| [share-skill](./share-skill/) | Git サポート付きでスキルをリポジトリに移行 |
## ドキュメント
このスキルセットには [share-skill](https://github.com/guo-yu/skills/tree/master/share-skill) で生成されたオンラインドキュメントサイトがあります。
**カスタムドメイン:**
https://{custom_domain}/
**GitHub Pages:**
https://{username}.github.io/{repo-name}/
### GitHub Pages の設定
1. リポジトリの **Settings** -> **Pages** に移動
2. "Source" で **Deploy from a branch** を選択
3. ブランチ: `master` (または `main`)、フォルダ: `/docs` を選択
4. (オプション) "Custom domain" にカスタムドメインを追加
## ライセンス
MIT
---
Made with ♥ by [Yu's skills](https://skill.guoyu.me/)
When executing /share-skill docs or /share-skill <skill-name>:
Read config
CONFIG=$(cat ~/.claude/share-skill-config.json)
GITHUB_URL=$(echo "$CONFIG" | jq -r '.remotes.github')
GITHUB_USERNAME=$(echo "$GITHUB_URL" | grep -oP 'github\.com[:/]\K[^/]+')
CUSTOM_DOMAIN=$(echo "$CONFIG" | jq -r '.docs.custom_domain // empty')
REPO_NAME=$(basename "$(git rev-parse --show-toplevel)")
Generate language switch navigation
LANG_NAV='<p align="center">
<a href="README.md">English</a> |
<a href="README.zh-CN.md">简体中文</a> |
<a href="README.ja.md">日本語</a>
</p>'
Generate README for all languages
# Define language config
declare -A LANG_CONFIG
LANG_CONFIG[en]="README.md"
LANG_CONFIG[zh-CN]="README.zh-CN.md"
LANG_CONFIG[ja]="README.ja.md"
# Generate README for each language
for lang in en zh-CN ja; do
FILE="${LANG_CONFIG[$lang]}"
generate_readme "$lang" "$FILE"
done
Write README files
generate_readme() {
local lang=$1
local file=$2
# Select template based on language
case $lang in
en)
TITLE="${GITHUB_USERNAME}'s Skills"
# ... English content
;;
zh-CN)
TITLE="${GITHUB_USERNAME} 的技能集"
# ... Chinese content
;;
ja)
TITLE="${GITHUB_USERNAME} のスキル"
# ... Japanese content
;;
esac
cat > "$file" << EOF
$LANG_NAV
# $TITLE
...
EOF
}
README multi-language files updated
Generated files:
- README.md (English)
- README.zh-CN.md (Simplified Chinese)
- README.ja.md (Japanese)
Documentation link: https://skill.guoyu.me/
Included sections:
- Language switch navigation
- Skills list
- Documentation (online docs instructions)
- License
- Attribution (Made with ♥)
share-skill provides a verification script to ensure generated documentation matches the SKILL.md specifications.
Location: share-skill/test/verify-docs.sh
Usage:
# Test current directory
./share-skill/test/verify-docs.sh .
# Test specific repository
./share-skill/test/verify-docs.sh ~/Codes/skills
Checks performed:
| Category | Checks |
|---|---|
| Directory Structure | docs/index.html, docs/js/main.js, docs/css/custom.css, docs/CNAME |
| index.html | Favicon, navbar brand, three-column layout, language switcher, installation section, tocbot, highlight.js, footer, version numbers |
| main.js | REPO_OWNER, REPO_NAME, BRANCH, CACHE_VERSION, I18N object, getBasePath, dynamic favicon/repoLink, tocbot.init, hljs |
| README Files | README.md, README.zh-CN.md, README.ja.md, language navigation links, footer attribution |
| Skill Files | SKILL.md, SKILL.zh-CN.md, SKILL.ja.md for each skill |
| Skills Config | Each skill configured in main.js SKILLS object |
Sample Output:
╔════════════════════════════════════════════════════════════╗
║ share-skill Documentation Verification Script ║
╚════════════════════════════════════════════════════════════╝
Repository: /Users/username/Codes/skills
── 1. Directory Structure ──
✓ docs/index.html exists
✓ docs/js/main.js exists
✓ docs/css/custom.css exists
✓ docs/CNAME exists (custom domain configured)
── 2. index.html Structure ──
✓ Favicon element with id='favicon'
✓ Navbar brand with id='repoLink'
...
════════════════════════════════════════════════════════════
Summary
════════════════════════════════════════════════════════════
Passed: 71
Failed: 0
Warnings: 0
✓ All required checks passed!
Exit Codes:
0: All checks passed1: One or more checks failedRun the verification script:
/share-skill docs