Initial commit: skillshare meta-skill
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
8
skillshare/.skillshare-meta.json
Normal file
8
skillshare/.skillshare-meta.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"source": "github.com/runkids/skillshare/skills/skillshare",
|
||||
"type": "github-subdir",
|
||||
"installed_at": "2026-01-29T15:54:54.355308942Z",
|
||||
"repo_url": "https://github.com/runkids/skillshare.git",
|
||||
"subdir": "skills/skillshare",
|
||||
"version": "0134ec0"
|
||||
}
|
||||
108
skillshare/SKILL.md
Normal file
108
skillshare/SKILL.md
Normal file
@@ -0,0 +1,108 @@
|
||||
---
|
||||
name: skillshare
|
||||
version: 0.6.4
|
||||
description: Syncs skills across AI CLI tools from a single source of truth. Use when asked to "sync skills", "pull skills", "show status", "list skills", "install skill", "initialize skillshare", or manage skill targets.
|
||||
argument-hint: "[command] [target] [--dry-run]"
|
||||
---
|
||||
|
||||
# Skillshare CLI
|
||||
|
||||
```
|
||||
Source: ~/.config/skillshare/skills ← Edit here (single source of truth)
|
||||
↓ sync
|
||||
Targets: ~/.claude/skills, ~/.cursor/skills, ... ← Symlinked from source
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```bash
|
||||
skillshare status # Always run first
|
||||
skillshare sync # Push to all targets
|
||||
skillshare sync --dry-run # Preview changes
|
||||
skillshare pull claude # Import from target → source
|
||||
skillshare list # Show skills and tracked repos
|
||||
```
|
||||
|
||||
## Command Patterns
|
||||
|
||||
| Intent | Command |
|
||||
|--------|---------|
|
||||
| Sync skills | `skillshare sync` |
|
||||
| Preview first | `skillshare sync --dry-run` then `sync` |
|
||||
| Create new skill | `skillshare new <name>` then `sync` |
|
||||
| Pull from target | `skillshare pull <name>` then `sync` |
|
||||
| Install skill | `skillshare install <source>` then `sync` |
|
||||
| Install from repo (browse) | `skillshare install owner/repo` (discovery mode) |
|
||||
| Install team repo | `skillshare install <git-url> --track` then `sync` |
|
||||
| Update skill/repo | `skillshare update <name>` then `sync` |
|
||||
| Update all tracked | `skillshare update --all` then `sync` |
|
||||
| Remove skill | `skillshare uninstall <name>` then `sync` |
|
||||
| List skills | `skillshare list` or `list --verbose` |
|
||||
| Cross-machine push | `skillshare push -m "message"` |
|
||||
| Cross-machine pull | `skillshare pull --remote` |
|
||||
| Backup/restore | `skillshare backup --list`, `restore <target>` |
|
||||
| Add custom target | `skillshare target add <name> <path>` |
|
||||
| Change sync mode | `skillshare target <name> --mode merge\|symlink` |
|
||||
| Upgrade CLI/skill | `skillshare upgrade` |
|
||||
| Diagnose issues | `skillshare doctor` |
|
||||
|
||||
## Init (Non-Interactive)
|
||||
|
||||
**CRITICAL:** Use flags — AI cannot respond to CLI prompts.
|
||||
|
||||
**Source path:** Always use default `~/.config/skillshare/skills`. Only use `--source` if user explicitly requests a different location.
|
||||
|
||||
**Step 1:** Check existing skills
|
||||
```bash
|
||||
ls ~/.claude/skills ~/.cursor/skills 2>/dev/null | head -10
|
||||
```
|
||||
|
||||
**Step 2:** Run init based on findings
|
||||
|
||||
| Found | Command |
|
||||
|-------|---------|
|
||||
| Skills in one target | `skillshare init --copy-from <name> --all-targets --git` |
|
||||
| Skills in multiple | Ask user which to import |
|
||||
| No existing skills | `skillshare init --no-copy --all-targets --git` |
|
||||
|
||||
**Step 3:** `skillshare status`
|
||||
|
||||
**Adding new agents later (AI must use --select):**
|
||||
```bash
|
||||
skillshare init --discover --select "windsurf,kilocode" # Non-interactive (AI use this)
|
||||
# skillshare init --discover # Interactive only (NOT for AI)
|
||||
```
|
||||
|
||||
See [init.md](references/init.md) for all flags.
|
||||
|
||||
## Team Edition
|
||||
|
||||
```bash
|
||||
skillshare install github.com/team/skills --track # Install as tracked repo
|
||||
skillshare update _team-skills # Update later
|
||||
```
|
||||
|
||||
Tracked repos: `_` prefix, nested paths use `__` (e.g., `_team__frontend__ui`).
|
||||
|
||||
**Naming convention:** Use `{team}:{name}` in SKILL.md to avoid collisions.
|
||||
|
||||
## Safety
|
||||
|
||||
- **NEVER** `rm -rf` on symlinked skills — deletes source
|
||||
- Use `skillshare uninstall <name>` to safely remove
|
||||
|
||||
## Zero-Install
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/runkids/skillshare/main/skills/skillshare/scripts/run.sh | sh -s -- status
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [init.md](references/init.md) - Init flags
|
||||
- [sync.md](references/sync.md) - Sync, pull, push
|
||||
- [install.md](references/install.md) - Install, update, uninstall
|
||||
- [status.md](references/status.md) - Status, diff, list, doctor
|
||||
- [targets.md](references/targets.md) - Target management
|
||||
- [backup.md](references/backup.md) - Backup, restore
|
||||
- [TROUBLESHOOTING.md](references/TROUBLESHOOTING.md) - Recovery
|
||||
143
skillshare/references/TROUBLESHOOTING.md
Normal file
143
skillshare/references/TROUBLESHOOTING.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# Skillshare Troubleshooting
|
||||
|
||||
Common issues, solutions, and tips for AI assistants.
|
||||
|
||||
## Common Issues
|
||||
|
||||
| Problem | Diagnosis | Solution |
|
||||
|---------|-----------|----------|
|
||||
| "config not found" | Config missing | Run `skillshare init` |
|
||||
| Target shows differences | Files out of sync | Run `skillshare sync` |
|
||||
| Lost source files | Deleted via symlink | `cd ~/.config/skillshare/skills && git checkout -- <skill>/` |
|
||||
| Target has local skills | Need to preserve | Ensure `merge` mode, then `skillshare pull` before sync |
|
||||
| Skill not appearing | Not synced yet | Run `skillshare sync` after install |
|
||||
| Can't find installed skills | Wrong directory | Check `skillshare status` for source path |
|
||||
| "permission denied" | Symlink issues | Check file ownership and permissions |
|
||||
| Git remote not set | Push fails | Run `git remote add origin <url>` in source |
|
||||
|
||||
## Recovery Workflow
|
||||
|
||||
When something goes wrong:
|
||||
|
||||
```bash
|
||||
skillshare doctor # 1. Diagnose issues
|
||||
skillshare backup # 2. Create safety backup
|
||||
skillshare sync --dry-run # 3. Preview fix
|
||||
skillshare sync # 4. Apply fix
|
||||
```
|
||||
|
||||
## Git Recovery
|
||||
|
||||
If source files were accidentally deleted:
|
||||
|
||||
```bash
|
||||
cd ~/.config/skillshare/skills
|
||||
git status # See what's missing
|
||||
git checkout -- <skill-name>/ # Restore specific skill
|
||||
git checkout -- . # Restore all deleted files
|
||||
```
|
||||
|
||||
If you need to restore from backup:
|
||||
|
||||
```bash
|
||||
skillshare backup --list # List available backups
|
||||
skillshare restore claude --from <timestamp>
|
||||
```
|
||||
|
||||
## Tips for AI Assistants
|
||||
|
||||
### Symlink Behavior
|
||||
|
||||
Understanding symlinks is critical:
|
||||
|
||||
1. **merge mode** (default): Each skill in target is a symlink to source
|
||||
- Editing `~/.claude/skills/my-skill/SKILL.md` edits the source
|
||||
- Changes are immediate and affect all targets
|
||||
- Safe: `skillshare uninstall my-skill`
|
||||
- **DANGEROUS**: `rm -rf ~/.claude/skills/my-skill` - deletes source!
|
||||
|
||||
2. **symlink mode**: Entire target directory is a symlink
|
||||
- `~/.claude/skills` → `~/.config/skillshare/skills`
|
||||
- All targets are identical
|
||||
- No local skills possible
|
||||
|
||||
### When to Use --dry-run
|
||||
|
||||
Always use `--dry-run` in these situations:
|
||||
|
||||
- User is cautious or new to skillshare
|
||||
- Before `sync` on first use
|
||||
- Before `pull --all` to see what will be imported
|
||||
- Before `install` from unknown sources
|
||||
- Before `restore` to preview what will change
|
||||
- Before `target remove` to understand impact
|
||||
|
||||
### Safe vs Dangerous Operations
|
||||
|
||||
**Safe operations:**
|
||||
```bash
|
||||
skillshare target remove <name> # Removes symlinks, keeps source
|
||||
skillshare uninstall <name> # Removes skill properly
|
||||
skillshare sync # Creates/updates symlinks
|
||||
```
|
||||
|
||||
**NEVER do this:**
|
||||
```bash
|
||||
rm -rf ~/.claude/skills/my-skill # Deletes source via symlink!
|
||||
rm -rf ~/.claude/skills # May delete entire source!
|
||||
```
|
||||
|
||||
### Creating New Skills
|
||||
|
||||
Guide users to create skills in source:
|
||||
|
||||
1. Create directory: `~/.config/skillshare/skills/<skill-name>/`
|
||||
2. Create `SKILL.md` with required frontmatter:
|
||||
```yaml
|
||||
---
|
||||
name: skill-name
|
||||
description: What this skill does
|
||||
---
|
||||
```
|
||||
3. Run `skillshare sync` to distribute
|
||||
|
||||
### Git Workflow Reminders
|
||||
|
||||
After any skill changes, remind user to push:
|
||||
|
||||
```bash
|
||||
skillshare push # Simple: commit + push
|
||||
skillshare push -m "Add new skill" # With custom message
|
||||
```
|
||||
|
||||
### Handling Init Prompts
|
||||
|
||||
AI cannot respond to CLI prompts. When user asks to initialize:
|
||||
|
||||
1. Ask clarifying questions in chat
|
||||
2. Build the command with appropriate flags
|
||||
3. Run non-interactively
|
||||
|
||||
Example conversation:
|
||||
- AI: "Do you have existing skills to copy from Claude or another tool?"
|
||||
- User: "Yes, from Claude"
|
||||
- AI: "Which CLI tools should I set up as targets?"
|
||||
- User: "Claude and Cursor"
|
||||
- AI: "Should I initialize git for version control?"
|
||||
- User: "Yes"
|
||||
- AI runs: `skillshare init --copy-from claude --targets "claude,cursor" --git`
|
||||
|
||||
### Debugging Sync Issues
|
||||
|
||||
If sync seems stuck or wrong:
|
||||
|
||||
```bash
|
||||
skillshare status # Check current state
|
||||
skillshare diff # See actual differences
|
||||
ls -la ~/.claude/skills # Check symlink targets
|
||||
```
|
||||
|
||||
Look for:
|
||||
- Broken symlinks (pointing to non-existent files)
|
||||
- Regular files instead of symlinks
|
||||
- Wrong symlink targets
|
||||
23
skillshare/references/backup.md
Normal file
23
skillshare/references/backup.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Backup & Restore Commands
|
||||
|
||||
## backup
|
||||
|
||||
Creates backup of target skills.
|
||||
|
||||
```bash
|
||||
skillshare backup # Backup all targets
|
||||
skillshare backup claude # Backup specific target
|
||||
skillshare backup --list # List available backups
|
||||
skillshare backup --cleanup # Remove old backups
|
||||
```
|
||||
|
||||
Backups stored in: `~/.config/skillshare/backups/<timestamp>/`
|
||||
|
||||
## restore
|
||||
|
||||
Restores skills from backup.
|
||||
|
||||
```bash
|
||||
skillshare restore claude # From latest backup
|
||||
skillshare restore claude --from 2026-01-14_21-22-18 # From specific backup
|
||||
```
|
||||
71
skillshare/references/init.md
Normal file
71
skillshare/references/init.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Init Command
|
||||
|
||||
Initializes skillshare configuration.
|
||||
|
||||
## Key Concept
|
||||
|
||||
**Source is always `~/.config/skillshare/skills`** — never a CLI directory like `.claude/skills`.
|
||||
|
||||
- `--copy-from claude` = import skills FROM claude INTO source
|
||||
- `--copy-from` does NOT change where source is located
|
||||
|
||||
## Copy Source Flags (mutually exclusive)
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--copy-from <name\|path>` | Copy skills from target name or directory path |
|
||||
| `--no-copy` | Start with empty source |
|
||||
|
||||
## Target Flags (mutually exclusive)
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--targets <list>` | Comma-separated targets: `"claude,cursor,codex"` |
|
||||
| `--all-targets` | Add all detected CLI targets |
|
||||
| `--no-targets` | Skip target setup |
|
||||
|
||||
## Git Flags (mutually exclusive)
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--git` | Initialize git in source (recommended) |
|
||||
| `--no-git` | Skip git initialization |
|
||||
|
||||
## Discover Flags (for adding new agents to existing config)
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--discover` | Detect and add new agents to existing config (interactive) |
|
||||
| `--select <list>` | Comma-separated agents to add (non-interactive, requires `--discover`) |
|
||||
|
||||
## Other Flags
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--source <path>` | Custom source directory (**only if user explicitly requests**) |
|
||||
| `--remote <url>` | Set git remote (implies `--git`) |
|
||||
| `--dry-run` | Preview without making changes |
|
||||
|
||||
**AI Note:** Never use `--source` unless the user explicitly asks to change the source location.
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
# Fresh start with all targets and git
|
||||
skillshare init --no-copy --all-targets --git
|
||||
|
||||
# Copy from Claude, specific targets
|
||||
skillshare init --copy-from claude --targets "claude,cursor" --git
|
||||
|
||||
# Minimal setup
|
||||
skillshare init --no-copy --no-targets --no-git
|
||||
|
||||
# Custom source with remote
|
||||
skillshare init --source ~/my-skills --remote git@github.com:user/skills.git
|
||||
|
||||
# Add new agents to existing config (non-interactive)
|
||||
skillshare init --discover --select "windsurf,kilocode"
|
||||
|
||||
# Add new agents (interactive)
|
||||
skillshare init --discover
|
||||
```
|
||||
62
skillshare/references/install.md
Normal file
62
skillshare/references/install.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Install, Update & Uninstall
|
||||
|
||||
## install
|
||||
|
||||
Adds a skill from various sources.
|
||||
|
||||
```bash
|
||||
# GitHub shorthand (auto-expands to github.com/...)
|
||||
skillshare install owner/repo # Discovery mode
|
||||
skillshare install owner/repo/path/to/skill # Direct path
|
||||
|
||||
# Full URLs
|
||||
skillshare install github.com/user/repo # Discovery mode
|
||||
skillshare install github.com/user/repo/skill # Direct path
|
||||
skillshare install git@github.com:user/repo.git # SSH
|
||||
|
||||
# Local
|
||||
skillshare install ~/Downloads/my-skill
|
||||
|
||||
# Team repo (preserves .git for updates)
|
||||
skillshare install github.com/team/skills --track
|
||||
```
|
||||
|
||||
**Flags:**
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--name <name>` | Custom skill name |
|
||||
| `--force, -f` | Overwrite existing |
|
||||
| `--update, -u` | Update existing (git pull or reinstall) |
|
||||
| `--track, -t` | Install as tracked repo (Team Edition) |
|
||||
| `--dry-run, -n` | Preview without installing |
|
||||
|
||||
After install: `skillshare sync`
|
||||
|
||||
## update
|
||||
|
||||
Updates skills or tracked repos.
|
||||
|
||||
```bash
|
||||
skillshare update my-skill # Update from stored source
|
||||
skillshare update _team-repo # Git pull tracked repo
|
||||
skillshare update --all # Update all tracked repos
|
||||
skillshare update _repo --force # Discard local changes and update
|
||||
```
|
||||
|
||||
Safety: Repos with uncommitted changes are blocked by default.
|
||||
Use `--force` to discard local changes and pull latest.
|
||||
|
||||
After update: `skillshare sync`
|
||||
|
||||
## uninstall
|
||||
|
||||
Removes a skill from source.
|
||||
|
||||
```bash
|
||||
skillshare uninstall my-skill # With confirmation
|
||||
skillshare uninstall my-skill --force # Skip confirmation
|
||||
skillshare uninstall my-skill --dry-run
|
||||
```
|
||||
|
||||
After uninstall: `skillshare sync`
|
||||
62
skillshare/references/status.md
Normal file
62
skillshare/references/status.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Status & Inspection Commands
|
||||
|
||||
## status
|
||||
|
||||
Shows source location, targets, and sync state.
|
||||
|
||||
```bash
|
||||
skillshare status
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
Source: ~/.config/skillshare/skills (4 skills)
|
||||
Targets:
|
||||
claude ✓ synced ~/.claude/skills
|
||||
codex ✓ synced ~/.codex/skills
|
||||
cursor ⚠ 1 diff ~/.cursor/skills
|
||||
|
||||
Version:
|
||||
✓ CLI: 0.6.4
|
||||
✓ Skill: 0.6.4 (up to date)
|
||||
```
|
||||
|
||||
## diff
|
||||
|
||||
Shows differences between source and targets.
|
||||
|
||||
```bash
|
||||
skillshare diff # All targets
|
||||
skillshare diff claude # Specific target
|
||||
```
|
||||
|
||||
## list
|
||||
|
||||
Lists installed skills.
|
||||
|
||||
```bash
|
||||
skillshare list # Basic list
|
||||
skillshare list --verbose # With source and install info
|
||||
```
|
||||
|
||||
## doctor
|
||||
|
||||
Checks configuration health and diagnoses issues.
|
||||
|
||||
```bash
|
||||
skillshare doctor
|
||||
```
|
||||
|
||||
## upgrade
|
||||
|
||||
Upgrades CLI binary and/or built-in skillshare skill.
|
||||
|
||||
```bash
|
||||
skillshare upgrade # Both CLI + skill
|
||||
skillshare upgrade --cli # CLI only
|
||||
skillshare upgrade --skill # Skill only
|
||||
skillshare upgrade --force # Skip confirmation
|
||||
skillshare upgrade --dry-run # Preview
|
||||
```
|
||||
|
||||
After upgrading skill: `skillshare sync`
|
||||
41
skillshare/references/sync.md
Normal file
41
skillshare/references/sync.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Sync, Pull & Push Commands
|
||||
|
||||
## sync
|
||||
|
||||
Pushes skills from source to all targets.
|
||||
|
||||
```bash
|
||||
skillshare sync # Execute sync
|
||||
skillshare sync --dry-run # Preview only
|
||||
```
|
||||
|
||||
## pull
|
||||
|
||||
Brings skills from target(s) to source.
|
||||
|
||||
```bash
|
||||
skillshare pull claude # Pull from specific target
|
||||
skillshare pull --all # Pull from all targets
|
||||
skillshare pull --remote # Pull from git remote + sync all
|
||||
```
|
||||
|
||||
## push
|
||||
|
||||
Commits and pushes source to git remote.
|
||||
|
||||
```bash
|
||||
skillshare push # Default commit message
|
||||
skillshare push -m "message" # Custom commit message
|
||||
skillshare push --dry-run # Preview only
|
||||
```
|
||||
|
||||
## Workflows
|
||||
|
||||
**Local workflow:**
|
||||
1. Create skill in any target (e.g., `~/.claude/skills/my-skill/`)
|
||||
2. `skillshare pull claude` - bring to source
|
||||
3. `skillshare sync` - distribute to all targets
|
||||
|
||||
**Cross-machine workflow:**
|
||||
1. Machine A: `skillshare push` - commit and push to remote
|
||||
2. Machine B: `skillshare pull --remote` - pull from remote + sync
|
||||
33
skillshare/references/targets.md
Normal file
33
skillshare/references/targets.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Target Management
|
||||
|
||||
## target
|
||||
|
||||
Manages sync targets.
|
||||
|
||||
```bash
|
||||
skillshare target list # List all targets
|
||||
skillshare target claude # Show target info
|
||||
skillshare target add myapp ~/.myapp/skills # Add custom target
|
||||
skillshare target remove myapp # Remove target
|
||||
```
|
||||
|
||||
## Sync Modes
|
||||
|
||||
```bash
|
||||
skillshare target claude --mode merge # Individual skill symlinks (default)
|
||||
skillshare target claude --mode symlink # Entire directory symlinked
|
||||
```
|
||||
|
||||
**Mode comparison:**
|
||||
|
||||
| Mode | Behavior | Local Skills |
|
||||
|------|----------|--------------|
|
||||
| `merge` | Creates individual symlinks for each skill | Preserved |
|
||||
| `symlink` | Entire target directory is a symlink | Not possible |
|
||||
|
||||
## Safe Target Removal
|
||||
|
||||
```bash
|
||||
skillshare target remove <name> # Safe: only removes link
|
||||
# NOT: rm -rf ~/.target/skills # Dangerous: may delete source
|
||||
```
|
||||
135
skillshare/scripts/run.sh
Executable file
135
skillshare/scripts/run.sh
Executable file
@@ -0,0 +1,135 @@
|
||||
#!/bin/sh
|
||||
# skillshare runner - npx-style execution without installation
|
||||
# Usage: curl -fsSL https://raw.githubusercontent.com/runkids/skillshare/main/skills/skillshare/scripts/run.sh | sh -s -- [command] [args]
|
||||
# Or: sh run.sh [command] [args]
|
||||
set -e
|
||||
|
||||
REPO="runkids/skillshare"
|
||||
CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/skillshare"
|
||||
BIN_DIR="$CACHE_DIR/bin"
|
||||
BINARY="$BIN_DIR/skillshare"
|
||||
VERSION_FILE="$CACHE_DIR/.version"
|
||||
MAX_AGE=86400 # Check for updates every 24 hours
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
info() { printf "${CYAN}[skillshare]${NC} %s\n" "$1" >&2; }
|
||||
success() { printf "${GREEN}[skillshare]${NC} %s\n" "$1" >&2; }
|
||||
warn() { printf "${YELLOW}[skillshare]${NC} %s\n" "$1" >&2; }
|
||||
error() { printf "${RED}[skillshare]${NC} %s\n" "$1" >&2; exit 1; }
|
||||
|
||||
# Detect OS
|
||||
detect_os() {
|
||||
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
case "$OS" in
|
||||
darwin) OS="darwin" ;;
|
||||
linux) OS="linux" ;;
|
||||
mingw*|msys*|cygwin*) error "Windows is not supported via this script. Please download from GitHub releases." ;;
|
||||
*) error "Unsupported OS: $OS" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Detect architecture
|
||||
detect_arch() {
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
x86_64|amd64) ARCH="amd64" ;;
|
||||
arm64|aarch64) ARCH="arm64" ;;
|
||||
*) error "Unsupported architecture: $ARCH" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get file modification time in seconds since epoch (cross-platform)
|
||||
get_file_age() {
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
stat -f %m "$1" 2>/dev/null || echo 0
|
||||
else
|
||||
stat -c %Y "$1" 2>/dev/null || echo 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if we need to update (version file older than MAX_AGE)
|
||||
needs_update() {
|
||||
[ ! -f "$VERSION_FILE" ] && return 0
|
||||
[ ! -x "$BINARY" ] && return 0
|
||||
|
||||
file_time=$(get_file_age "$VERSION_FILE")
|
||||
current_time=$(date +%s)
|
||||
age=$((current_time - file_time))
|
||||
|
||||
[ "$age" -ge "$MAX_AGE" ]
|
||||
}
|
||||
|
||||
# Get latest version from GitHub API
|
||||
get_latest_version() {
|
||||
LATEST=$(curl -sL "https://api.github.com/repos/${REPO}/releases/latest" | grep '"tag_name"' | cut -d'"' -f4)
|
||||
if [ -z "$LATEST" ]; then
|
||||
error "Failed to get latest version. Check your internet connection."
|
||||
fi
|
||||
VERSION=${LATEST#v}
|
||||
}
|
||||
|
||||
# Download and install to cache
|
||||
download_binary() {
|
||||
detect_os
|
||||
detect_arch
|
||||
get_latest_version
|
||||
|
||||
URL="https://github.com/${REPO}/releases/download/${LATEST}/skillshare_${VERSION}_${OS}_${ARCH}.tar.gz"
|
||||
|
||||
info "Downloading skillshare ${VERSION} for ${OS}/${ARCH}..."
|
||||
|
||||
mkdir -p "$BIN_DIR"
|
||||
|
||||
TMP_DIR=$(mktemp -d)
|
||||
trap "rm -rf $TMP_DIR" EXIT
|
||||
|
||||
if ! curl -sL "$URL" | tar xz -C "$TMP_DIR" 2>/dev/null; then
|
||||
error "Failed to download. URL: $URL"
|
||||
fi
|
||||
|
||||
if [ ! -f "$TMP_DIR/skillshare" ]; then
|
||||
error "Binary not found in archive"
|
||||
fi
|
||||
|
||||
mv "$TMP_DIR/skillshare" "$BINARY"
|
||||
chmod +x "$BINARY"
|
||||
echo "$VERSION" > "$VERSION_FILE"
|
||||
|
||||
success "Cached skillshare ${VERSION} at ${BIN_DIR}"
|
||||
}
|
||||
|
||||
# Main logic
|
||||
main() {
|
||||
# 1. Check if skillshare is already in PATH
|
||||
if command -v skillshare >/dev/null 2>&1; then
|
||||
exec skillshare "$@"
|
||||
fi
|
||||
|
||||
# 2. Check cached binary
|
||||
if [ -x "$BINARY" ]; then
|
||||
if ! needs_update; then
|
||||
exec "$BINARY" "$@"
|
||||
fi
|
||||
|
||||
# Try to update, but fall back to cached version on failure
|
||||
if download_binary 2>/dev/null; then
|
||||
exec "$BINARY" "$@"
|
||||
else
|
||||
warn "Update check failed, using cached version"
|
||||
touch "$VERSION_FILE" # Reset timer
|
||||
exec "$BINARY" "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 3. First run - download binary
|
||||
download_binary
|
||||
exec "$BINARY" "$@"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user