Initial commit
This commit is contained in:
11
.claude-plugin/plugin.json
Normal file
11
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "local-install-skill",
|
||||
"description": "Install Claude Code skills from GitHub repositories to project scope",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "lagz0ne"
|
||||
},
|
||||
"commands": [
|
||||
"./commands"
|
||||
]
|
||||
}
|
||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# local-install-skill
|
||||
|
||||
Install Claude Code skills from GitHub repositories to project scope
|
||||
329
commands/install-skill.md
Normal file
329
commands/install-skill.md
Normal file
@@ -0,0 +1,329 @@
|
||||
---
|
||||
name: install-skill
|
||||
description: Install a skill from GitHub to project scope (.claude/skills/)
|
||||
arguments:
|
||||
- name: source
|
||||
description: "GitHub repo with optional branch and skill path: user/repo, user/repo:skill-name, user/repo#branch:skill-name, or user/repo --all"
|
||||
required: true
|
||||
- name: mode
|
||||
description: "Installation mode: --copy (files only) or --submodule (git submodule, default)"
|
||||
required: false
|
||||
---
|
||||
|
||||
# Install Skill from GitHub
|
||||
|
||||
You are installing a Claude Code skill from a GitHub repository to project scope.
|
||||
|
||||
## Parse the Input
|
||||
|
||||
Parse the source argument: `$ARGUMENTS.source`
|
||||
|
||||
Supported formats:
|
||||
- `user/repo` - Clone repo, look for skill at root or in `skills/` directory
|
||||
- `user/repo:skill-name` - Install specific skill from `skills/<skill-name>/`
|
||||
- `user/repo#branch` - Use specific branch
|
||||
- `user/repo#branch:skill-name` - Branch + specific skill
|
||||
- `user/repo --all` - Install all skills found in repo
|
||||
|
||||
Extract:
|
||||
- `owner`: GitHub username/org
|
||||
- `repo`: Repository name
|
||||
- `branch`: Branch name (default: repo's default branch)
|
||||
- `skillPath`: Path to skill within repo (optional)
|
||||
- `installAll`: Boolean flag for --all
|
||||
|
||||
## Determine Installation Mode
|
||||
|
||||
Check for mode flags in `$ARGUMENTS.mode` or within `$ARGUMENTS.source`:
|
||||
|
||||
**Flag detection:**
|
||||
|
||||
1. First check `$ARGUMENTS.mode`:
|
||||
- If `--copy` or `copy`: `mode = "copy"`
|
||||
- If `--submodule` or `submodule`: `mode = "submodule"`
|
||||
|
||||
2. If not found, check if flag is appended to source string:
|
||||
- Split `$ARGUMENTS.source` by spaces
|
||||
- If last token is `--copy`: `mode = "copy"`, remove flag from source
|
||||
- If last token is `--submodule`: `mode = "submodule"`, remove flag from source
|
||||
|
||||
3. If no flag found, prompt user:
|
||||
|
||||
**Interactive prompt (when no flag):**
|
||||
|
||||
```
|
||||
Use AskUserQuestion:
|
||||
question: "How would you like to install this skill?"
|
||||
header: "Install Mode"
|
||||
multiSelect: false
|
||||
options:
|
||||
- label: "Submodule (recommended)"
|
||||
description: "Full repo as git submodule, easy updates via git submodule update"
|
||||
- label: "Copy"
|
||||
description: "Only skill files copied, minimal footprint, re-run install to update"
|
||||
```
|
||||
|
||||
Map user response to mode variable:
|
||||
- "Submodule (recommended)" → `mode = "submodule"`
|
||||
- "Copy" → `mode = "copy"`
|
||||
|
||||
**Default:** If user doesn't respond or cancels, default to `mode = "submodule"`.
|
||||
|
||||
The `mode` variable (value: `"copy"` or `"submodule"`) is used in subsequent installation steps.
|
||||
|
||||
## Installation Process
|
||||
|
||||
### Step 1: Setup directories
|
||||
|
||||
```bash
|
||||
mkdir -p .claude/skills
|
||||
```
|
||||
|
||||
### Step 2: Find skills to install
|
||||
|
||||
If `--all` flag:
|
||||
- Look for `skills/` directory in cloned repo
|
||||
- Find all subdirectories containing `SKILL.md`
|
||||
- Collect list of skill names
|
||||
|
||||
If specific skill path:
|
||||
- Check if `skills/<skill-name>/SKILL.md` exists
|
||||
- If not, check if `<skill-name>/SKILL.md` exists at root
|
||||
- If not found, report error with helpful message
|
||||
|
||||
If no skill specified:
|
||||
- Check if repo root has `SKILL.md` (repo IS the skill)
|
||||
- If not, check if `skills/` directory exists and has exactly one skill
|
||||
- If multiple skills found, list them and ask user to specify
|
||||
|
||||
### Step 3: Validate each skill
|
||||
|
||||
For each skill to install:
|
||||
1. Verify `SKILL.md` exists
|
||||
2. Read frontmatter and validate:
|
||||
- `name` field exists (max 64 chars)
|
||||
- `description` field exists (max 1024 chars)
|
||||
3. Warn if validation fails but continue
|
||||
|
||||
### Step 4: Execute Installation Based on Mode
|
||||
|
||||
#### If mode is "copy":
|
||||
|
||||
**2a. Clone to temporary directory:**
|
||||
```bash
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
git clone --depth=1 https://github.com/<owner>/<repo>.git "$TEMP_DIR"
|
||||
```
|
||||
|
||||
If specific branch:
|
||||
```bash
|
||||
git clone --depth=1 --branch <branch> https://github.com/<owner>/<repo>.git "$TEMP_DIR"
|
||||
```
|
||||
|
||||
**2b. Get commit SHA before cleanup:**
|
||||
```bash
|
||||
COMMIT_SHA=$(git -C "$TEMP_DIR" rev-parse HEAD)
|
||||
```
|
||||
|
||||
**2c. Copy skill directory:**
|
||||
```bash
|
||||
mkdir -p .claude/skills
|
||||
cp -r "$TEMP_DIR/<skillPath>" ".claude/skills/<skill-name>"
|
||||
```
|
||||
|
||||
**2d. Clean up temp directory:**
|
||||
```bash
|
||||
rm -rf "$TEMP_DIR"
|
||||
```
|
||||
|
||||
#### If mode is "submodule":
|
||||
|
||||
**2a. Check if this is a git repository:**
|
||||
```bash
|
||||
git rev-parse --git-dir > /dev/null 2>&1
|
||||
```
|
||||
|
||||
If not a git repo, error:
|
||||
```
|
||||
Error: Submodule mode requires a git repository.
|
||||
|
||||
Either initialize git first (git init) or use --copy mode.
|
||||
```
|
||||
|
||||
**2b. Check if submodule already exists:**
|
||||
```bash
|
||||
if [ -d ".claude/submodules/<repo>" ]; then
|
||||
# Verify it's the same source
|
||||
EXISTING_URL=$(git config --file .gitmodules submodule..claude/submodules/<repo>.url)
|
||||
EXPECTED_URL="https://github.com/<owner>/<repo>.git"
|
||||
|
||||
if [ "$EXISTING_URL" = "$EXPECTED_URL" ]; then
|
||||
# Same URL - use existing submodule, skip git submodule add
|
||||
echo "Submodule already exists with matching URL, using existing"
|
||||
else
|
||||
# Different URL - error
|
||||
echo "Error: Submodule exists but URL differs"
|
||||
echo " Existing: $EXISTING_URL"
|
||||
echo " Expected: $EXPECTED_URL"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
**2c. Add submodule if not exists:**
|
||||
|
||||
Skip if submodule already exists with matching URL (from step 2b).
|
||||
|
||||
Otherwise:
|
||||
```bash
|
||||
mkdir -p .claude/submodules
|
||||
git submodule add https://github.com/<owner>/<repo>.git .claude/submodules/<repo>
|
||||
```
|
||||
|
||||
If specific branch:
|
||||
```bash
|
||||
git submodule add -b <branch> https://github.com/<owner>/<repo>.git .claude/submodules/<repo>
|
||||
```
|
||||
|
||||
**2d. Get commit SHA:**
|
||||
```bash
|
||||
COMMIT_SHA=$(git -C ".claude/submodules/<repo>" rev-parse HEAD)
|
||||
```
|
||||
|
||||
### Step 5: Create symlinks (submodule mode only)
|
||||
|
||||
**Skip this step if mode is "copy"** - files are already in `.claude/skills/<name>/`.
|
||||
|
||||
For submodule mode, create symlink:
|
||||
|
||||
Check if `.claude/skills/<skill-name>` already exists:
|
||||
- If symlink pointing to same target: skip, already installed
|
||||
- If symlink pointing elsewhere or regular directory: ask user to overwrite or skip
|
||||
|
||||
Create relative symlink:
|
||||
```bash
|
||||
mkdir -p .claude/skills
|
||||
ln -s ../submodules/<repo>/<skillPath> .claude/skills/<skill-name>
|
||||
```
|
||||
|
||||
For example, if skill is at `skills/brainstorming/`:
|
||||
```bash
|
||||
ln -s ../submodules/superpowers/skills/brainstorming .claude/skills/brainstorming
|
||||
```
|
||||
|
||||
### Step 6: Update registry
|
||||
|
||||
Read or create `.claude/local-plugins.yaml`:
|
||||
|
||||
```yaml
|
||||
version: 2
|
||||
skills: {}
|
||||
submodules: {}
|
||||
```
|
||||
|
||||
**Migration:** If `.claude/local-plugins.json` exists (v1), migrate it first:
|
||||
1. Read JSON content
|
||||
2. Convert each repo's skills to v2 format with `mode: legacy`
|
||||
3. Write to `.claude/local-plugins.yaml`
|
||||
4. Delete `.claude/local-plugins.json`
|
||||
|
||||
**Add skill entry:**
|
||||
|
||||
```yaml
|
||||
skills:
|
||||
<skill-name>:
|
||||
mode: <copy|submodule>
|
||||
source: github.com/<owner>/<repo>
|
||||
repo: <repo>
|
||||
branch: <branch>
|
||||
skillPath: <path/to/skill>
|
||||
installedAt: <ISO timestamp>
|
||||
commitSha: <sha>
|
||||
```
|
||||
|
||||
**If submodule mode, also update submodules section:**
|
||||
|
||||
```yaml
|
||||
submodules:
|
||||
<repo>:
|
||||
source: github.com/<owner>/<repo>
|
||||
path: .claude/submodules/<repo>
|
||||
skills:
|
||||
- <skill-name>
|
||||
```
|
||||
|
||||
If repo already in submodules, just append skill name to the `skills` list.
|
||||
|
||||
**Write YAML:** Use proper YAML formatting with 2-space indentation.
|
||||
|
||||
### Step 7: Update .gitignore (copy mode only)
|
||||
|
||||
**Skip this step for submodule mode** - submodules are tracked by git naturally.
|
||||
|
||||
For copy mode, the skill files in `.claude/skills/<name>/` will be committed directly. No .gitignore changes needed.
|
||||
|
||||
**Note:** The old `.claude/plugins/local/` pattern can be removed from .gitignore if present, as we no longer use that directory.
|
||||
|
||||
### Step 8: Report success
|
||||
|
||||
**Copy mode output:**
|
||||
```
|
||||
Installing skill from github.com/<owner>/<repo>...
|
||||
├── Mode: Copy
|
||||
├── Downloading: <skillPath>
|
||||
├── Copying to: .claude/skills/<skill-name>
|
||||
└── Status: Installed successfully
|
||||
|
||||
Skill "<skill-name>" is now available in this project.
|
||||
```
|
||||
|
||||
**Submodule mode output:**
|
||||
```
|
||||
Installing skill from github.com/<owner>/<repo>...
|
||||
├── Mode: Submodule
|
||||
├── Adding submodule: .claude/submodules/<repo>
|
||||
├── Creating symlink: .claude/skills/<skill-name>
|
||||
└── Status: Installed successfully
|
||||
|
||||
Skill "<skill-name>" is now available in this project.
|
||||
|
||||
Note: Team members should run `git submodule update --init` after cloning.
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Repository not found:**
|
||||
```
|
||||
Error: Repository not found: github.com/<owner>/<repo>
|
||||
|
||||
Check the repository URL and ensure it's public or you have access.
|
||||
```
|
||||
|
||||
**No SKILL.md found:**
|
||||
```
|
||||
Error: No SKILL.md found at <owner>/<repo>:<path>
|
||||
|
||||
Expected structure:
|
||||
skill-name/
|
||||
└── SKILL.md (required)
|
||||
|
||||
Available skills in this repo:
|
||||
- skill-a (skills/skill-a/)
|
||||
- skill-b (skills/skill-b/)
|
||||
|
||||
Try: /install-skill <owner>/<repo>:skill-a
|
||||
```
|
||||
|
||||
**Network error:**
|
||||
```
|
||||
Error: Failed to clone repository
|
||||
|
||||
Check your network connection and try again.
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Always use relative symlinks so they work when repo is moved
|
||||
- The `.claude/plugins/local/` directory should NOT be committed (add to .gitignore)
|
||||
- The `.claude/skills/<name>` symlinks SHOULD be committed (team sharing)
|
||||
- Team members need to run `/install-skill` after cloning to populate local repos
|
||||
176
commands/remove-skill.md
Normal file
176
commands/remove-skill.md
Normal file
@@ -0,0 +1,176 @@
|
||||
---
|
||||
name: remove-skill
|
||||
description: Remove a locally installed skill
|
||||
arguments:
|
||||
- name: skill_name
|
||||
description: "Name of the skill to remove"
|
||||
required: true
|
||||
---
|
||||
|
||||
# Remove Locally Installed Skill
|
||||
|
||||
You are removing a Claude Code skill that was installed via `/install-skill`.
|
||||
|
||||
## Parse the Input
|
||||
|
||||
- `skill_name`: `$ARGUMENTS.skill_name` - The skill to remove
|
||||
|
||||
## Removal Process
|
||||
|
||||
### Step 1: Read registry and find skill
|
||||
|
||||
Read `.claude/local-plugins.yaml`.
|
||||
|
||||
Look up `skills.<skill_name>`. If not found:
|
||||
```
|
||||
Error: Skill "<skill_name>" not found in registry.
|
||||
|
||||
Installed skills:
|
||||
- skill-a (copy)
|
||||
- skill-b (submodule)
|
||||
|
||||
Use the exact skill name from the list above.
|
||||
```
|
||||
|
||||
Extract the skill's `mode` for appropriate removal.
|
||||
|
||||
### Step 2: Remove skill files/symlink
|
||||
|
||||
#### If mode is "copy":
|
||||
|
||||
```bash
|
||||
rm -rf ".claude/skills/<skill_name>"
|
||||
```
|
||||
|
||||
#### If mode is "submodule":
|
||||
|
||||
```bash
|
||||
rm ".claude/skills/<skill_name>" # Remove symlink only
|
||||
```
|
||||
|
||||
### Step 3: Update registry - skills section
|
||||
|
||||
Remove the skill entry from `skills` section.
|
||||
|
||||
### Step 4: Handle submodule cleanup (submodule mode only)
|
||||
|
||||
**Skip if mode is "copy".**
|
||||
|
||||
Check if other skills still use this submodule:
|
||||
1. Read `submodules.<repo>.skills` list
|
||||
2. Remove `<skill_name>` from the list
|
||||
3. If list is now empty, remove the submodule:
|
||||
|
||||
```bash
|
||||
git submodule deinit .claude/submodules/<repo>
|
||||
git rm .claude/submodules/<repo>
|
||||
rm -rf .git/modules/.claude/submodules/<repo>
|
||||
```
|
||||
|
||||
Remove the repo entry from `submodules` section.
|
||||
|
||||
If other skills still use the submodule:
|
||||
```
|
||||
Note: Submodule .claude/submodules/<repo> retained.
|
||||
Other skills still using it: skill-x, skill-y
|
||||
```
|
||||
|
||||
### Step 5: Clean up empty directories
|
||||
|
||||
```bash
|
||||
# Remove empty skills directory if no skills left
|
||||
rmdir .claude/skills 2>/dev/null || true
|
||||
|
||||
# Remove empty submodules directory if no submodules left
|
||||
rmdir .claude/submodules 2>/dev/null || true
|
||||
```
|
||||
|
||||
### Step 6: Write updated registry
|
||||
|
||||
Write `.claude/local-plugins.yaml`.
|
||||
|
||||
If no skills remain, consider removing the file:
|
||||
```bash
|
||||
if [ -z "$(grep -v '^version:' .claude/local-plugins.yaml | grep -v '^skills: {}' | grep -v '^submodules: {}')" ]; then
|
||||
rm .claude/local-plugins.yaml
|
||||
fi
|
||||
```
|
||||
|
||||
### Step 7: Report success
|
||||
|
||||
**Copy mode removal:**
|
||||
```
|
||||
Removing skill "<skill_name>"...
|
||||
├── Mode: Copy
|
||||
├── Removed: .claude/skills/<skill_name>/
|
||||
└── Registry updated
|
||||
|
||||
Skill "<skill_name>" has been removed.
|
||||
```
|
||||
|
||||
**Submodule mode removal (submodule kept):**
|
||||
```
|
||||
Removing skill "<skill_name>"...
|
||||
├── Mode: Submodule
|
||||
├── Removed symlink: .claude/skills/<skill_name>
|
||||
├── Submodule retained: .claude/submodules/<repo>
|
||||
│ └── Other skills: skill-x, skill-y
|
||||
└── Registry updated
|
||||
|
||||
Skill "<skill_name>" has been removed.
|
||||
```
|
||||
|
||||
**Submodule mode removal (submodule removed):**
|
||||
```
|
||||
Removing skill "<skill_name>"...
|
||||
├── Mode: Submodule
|
||||
├── Removed symlink: .claude/skills/<skill_name>
|
||||
├── Removed submodule: .claude/submodules/<repo>
|
||||
└── Registry updated
|
||||
|
||||
Skill "<skill_name>" and its submodule have been removed.
|
||||
```
|
||||
|
||||
## List Installed Skills
|
||||
|
||||
If user runs `/remove-skill` without arguments or with `--list`:
|
||||
|
||||
```
|
||||
Locally installed skills:
|
||||
|
||||
Copy mode:
|
||||
- my-custom-skill (from github.com/user/repo)
|
||||
|
||||
Submodule mode:
|
||||
- brainstorming (from github.com/obra/superpowers)
|
||||
- tdd (from github.com/obra/superpowers)
|
||||
|
||||
Use: /remove-skill <skill-name>
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Skill files missing but in registry:**
|
||||
```
|
||||
Warning: Skill "<skill_name>" in registry but files not found.
|
||||
Cleaning up registry entry...
|
||||
|
||||
Done. Registry cleaned.
|
||||
```
|
||||
|
||||
**Permission error:**
|
||||
```
|
||||
Error: Permission denied removing .claude/skills/<skill_name>
|
||||
|
||||
Check file permissions and try again.
|
||||
```
|
||||
|
||||
**Submodule removal fails:**
|
||||
```
|
||||
Error: Failed to remove submodule .claude/submodules/<repo>
|
||||
|
||||
Manual cleanup may be required:
|
||||
git submodule deinit .claude/submodules/<repo>
|
||||
git rm .claude/submodules/<repo>
|
||||
rm -rf .git/modules/.claude/submodules/<repo>
|
||||
```
|
||||
161
commands/update-skill.md
Normal file
161
commands/update-skill.md
Normal file
@@ -0,0 +1,161 @@
|
||||
---
|
||||
name: update-skill
|
||||
description: Update locally installed skills from their GitHub repositories
|
||||
arguments:
|
||||
- name: target
|
||||
description: "Repository name to update, or --all to update all repos"
|
||||
required: false
|
||||
---
|
||||
|
||||
# Update Locally Installed Skills
|
||||
|
||||
You are updating Claude Code skills that were installed via `/install-skill`.
|
||||
|
||||
## Parse the Input
|
||||
|
||||
Parse the target argument: `$ARGUMENTS.target`
|
||||
|
||||
- If empty or not provided: List installed skills and ask which to update
|
||||
- If `--all`: Update all updateable skills
|
||||
- Otherwise: Update the specified skill or repo
|
||||
|
||||
## Update Process
|
||||
|
||||
### Step 1: Read registry
|
||||
|
||||
Read `.claude/local-plugins.yaml`.
|
||||
|
||||
**Migration check:** If `.claude/local-plugins.json` exists but `.yaml` doesn't, run migration first.
|
||||
|
||||
If no registry found:
|
||||
```
|
||||
No locally installed skills found.
|
||||
|
||||
Use /install-skill to install skills from GitHub.
|
||||
```
|
||||
|
||||
### Step 2: Identify what to update
|
||||
|
||||
**If `--all`:**
|
||||
- Get all skills from registry
|
||||
- Group by mode for appropriate update method
|
||||
|
||||
**If specific target:**
|
||||
- Check if it's a skill name in `skills` section
|
||||
- Check if it's a repo name in `submodules` section
|
||||
- If not found, list available options
|
||||
|
||||
**If no target:**
|
||||
- List all skills with their mode and source
|
||||
- Ask user which to update
|
||||
|
||||
### Step 3: Update based on mode
|
||||
|
||||
#### For submodule-based skills:
|
||||
|
||||
Update the entire submodule (updates all skills from that repo):
|
||||
|
||||
Capture old and new SHA:
|
||||
```bash
|
||||
# BEFORE fetch/pull
|
||||
OLD_SHA=$(git -C .claude/submodules/<repo> rev-parse HEAD)
|
||||
|
||||
# Fetch and pull
|
||||
git -C .claude/submodules/<repo> fetch origin
|
||||
git -C .claude/submodules/<repo> pull origin <branch>
|
||||
|
||||
# AFTER pull
|
||||
NEW_SHA=$(git -C .claude/submodules/<repo> rev-parse HEAD)
|
||||
```
|
||||
|
||||
Update all skills from this repo in registry with new `commitSha`.
|
||||
|
||||
#### For copy-based skills:
|
||||
|
||||
Re-download and overwrite:
|
||||
|
||||
```bash
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
git clone --depth=1 --branch <branch> https://github.com/<owner>/<repo>.git "$TEMP_DIR"
|
||||
NEW_SHA=$(git -C "$TEMP_DIR" rev-parse HEAD)
|
||||
```
|
||||
|
||||
Compare with stored `commitSha`. If same:
|
||||
```
|
||||
Skill "<name>" is already up to date (sha: <sha>)
|
||||
```
|
||||
|
||||
If different:
|
||||
```bash
|
||||
rm -rf ".claude/skills/<skill-name>"
|
||||
cp -r "$TEMP_DIR/<skillPath>" ".claude/skills/<skill-name>"
|
||||
rm -rf "$TEMP_DIR"
|
||||
```
|
||||
|
||||
Update `commitSha` in registry.
|
||||
|
||||
### Step 4: Verify integrity
|
||||
|
||||
**For submodule skills:**
|
||||
- Check symlinks still point to valid targets
|
||||
- If skill was removed from upstream repo, warn user
|
||||
|
||||
**For copy skills:**
|
||||
- Verify files were copied successfully
|
||||
|
||||
### Step 5: Update registry
|
||||
|
||||
Write updated `.claude/local-plugins.yaml` with new `commitSha` values.
|
||||
|
||||
### Step 6: Report results
|
||||
|
||||
**No changes:**
|
||||
```
|
||||
Updating <skill-name>...
|
||||
└── Already up to date (sha: abc123)
|
||||
```
|
||||
|
||||
**Updated (submodule):**
|
||||
```
|
||||
Updating submodule <repo>...
|
||||
├── Previous: abc123
|
||||
├── Updated to: def456
|
||||
├── Skills updated: brainstorming, tdd
|
||||
└── Symlinks verified: OK
|
||||
|
||||
Skills updated successfully.
|
||||
```
|
||||
|
||||
**Updated (copy):**
|
||||
```
|
||||
Updating skill <name>...
|
||||
├── Previous: abc123
|
||||
├── Updated to: def456
|
||||
├── Files replaced in: .claude/skills/<name>
|
||||
└── Status: Updated successfully
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Submodule directory missing:**
|
||||
```
|
||||
Error: Submodule not found: .claude/submodules/<repo>
|
||||
|
||||
Run `git submodule update --init` or reinstall with /install-skill.
|
||||
```
|
||||
|
||||
**Network error:**
|
||||
```
|
||||
Error: Failed to fetch updates
|
||||
|
||||
Check your network connection and try again.
|
||||
```
|
||||
|
||||
**Skill not in registry:**
|
||||
```
|
||||
Error: Skill "<name>" not found in registry.
|
||||
|
||||
Installed skills:
|
||||
- skill-a (copy mode)
|
||||
- skill-b (submodule mode)
|
||||
```
|
||||
53
plugin.lock.json
Normal file
53
plugin.lock.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||
"pluginId": "gh:lagz0ne/local-install-skill:",
|
||||
"normalized": {
|
||||
"repo": null,
|
||||
"ref": "refs/tags/v20251128.0",
|
||||
"commit": "f24b9afa1862d79aa7f539cf94bf26ce642d397c",
|
||||
"treeHash": "2f76f6f0a7f7e4583e66b5059c1ce7b3274f286385b151715220afb6dfb3f86b",
|
||||
"generatedAt": "2025-11-28T10:20:03.201634Z",
|
||||
"toolVersion": "publish_plugins.py@0.2.0"
|
||||
},
|
||||
"origin": {
|
||||
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||
"branch": "master",
|
||||
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||
},
|
||||
"manifest": {
|
||||
"name": "local-install-skill",
|
||||
"description": "Install Claude Code skills from GitHub repositories to project scope",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"content": {
|
||||
"files": [
|
||||
{
|
||||
"path": "README.md",
|
||||
"sha256": "7954e2e78b9072bbb0a0e9d6b90988607da269c815cfce0f2d2303e4b7b19b19"
|
||||
},
|
||||
{
|
||||
"path": ".claude-plugin/plugin.json",
|
||||
"sha256": "3df0e6c6d065a86a011735a8f64b6fe280353024eb08c9869b29fe86655a19d7"
|
||||
},
|
||||
{
|
||||
"path": "commands/install-skill.md",
|
||||
"sha256": "bafb1faef194050303835d4dfe6656d0b48f66e0d0801c79a52446ba812ef827"
|
||||
},
|
||||
{
|
||||
"path": "commands/remove-skill.md",
|
||||
"sha256": "12381afa8b155bc35da1b22b7b7b8739fce6b64918f87936c3d7e0895f8ff111"
|
||||
},
|
||||
{
|
||||
"path": "commands/update-skill.md",
|
||||
"sha256": "f0717a6dafc0853cfdf4e39631352a3b211e54aed3164e5311b9331c7a86331f"
|
||||
}
|
||||
],
|
||||
"dirSha256": "2f76f6f0a7f7e4583e66b5059c1ce7b3274f286385b151715220afb6dfb3f86b"
|
||||
},
|
||||
"security": {
|
||||
"scannedAt": null,
|
||||
"scannerVersion": null,
|
||||
"flags": []
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user