Skill Installer
Installer and deploy surface for the skill system.
Public contract:
- Use
sk init(skill-system-cli) as the primary bootstrap entrypoint for this repository. - Use
sk install deploy --target <path>for advanced sidecar attachment into external projects. scripts/skills.shremains the implementation backend for installer/deploy operations.
Project-Scoped DB/MCP Guidance
- PostgreSQL-backed skills should follow project-scoped DB targeting (
<project>-memory) by auto-detection. - Do not rely on shell-global
SKILL_PGDATABASE; prefer project-local overrides only when required. - Do not allow ambient
PGDATABASEto silently steer skill runtime DB targets. - MCP server entries should use absolute skill paths in globally-installed setups.
Use the helper scripts based on the task:
- List curated skills when the user asks what is available, or if the user uses this skill without specifying what to do.
- Install from the curated list when the user provides a skill name.
- Install from another repo when the user provides a GitHub repo/path (including private repos).
Install skills with the helper scripts.
Bootstrap (First-Run)
Run scripts/skills.sh bootstrap to detect and scaffold the skill system:
- Detect missing structure:
config/,note/,.tkt/,skills-lock.json - Scaffold any missing directories with stub files
- Compute hashes for any
"pending"entries inskills-lock.json - Validate all installed skills have
SKILL.md - Check dependencies (
python3,git,bash)
scripts/skills.sh bootstrap
# or via sk CLI:
sk install bootstrapOutput is JSON with checks (what was found) and actions_taken (what was created).
This is idempotent — safe to run multiple times. Agents should run it when they detect the skill system is partially initialized or when a user asks to set up skills.
Communication
When listing curated skills, show available names and which ones are already installed in the current scope.
Scripts
All of these scripts use network, so when running in the sandbox, request escalation when running them.
scripts/list-curated-skills.py(prints curated list with installed annotations)scripts/list-curated-skills.py --format jsonscripts/skills.sh(unified wrapper for install, list, update, sync, deploy)scripts/skills.sh doctor --target <path>(detect-only preflight checks)scripts/skills.sh deploy --target <path> [--mode minimal|local|full] [--no-dashboard](sidecar deploy into a target project; dashboard generated by default)scripts/skills.sh dashboard --target <path>(generate target dashboard/index.html)scripts/skills.sh host-shell <bootstrap|discover|compat|doctor> [--target <path>](thin host plugin shell MVP)scripts/install-skill-from-github.py --repo <owner>/<repo> --path <path/to/skill> [<path/to/skill>...]scripts/install-skill-from-github.py --url https://github.com/<owner>/<repo>/tree/<ref>/<path>scripts/update-skills.py --allscripts/update-skills.py --skill <skill-name> [--update] [--dry-run]
Doctor (Preflight)
Run scripts/skills.sh doctor --target /path/to/project to inspect a target project without modifying it.
Doctor reports:
- target existence, directory type, and writability
- git binary/repo signal
- required structure presence (
config/,note/,.tkt/,skills-lock.json) - sidecar skill-system footprint for deployed projects
- dashboard presence (
dashboard/index.html) and dashboard generator skill entrypoint - optional database readiness signal (env/config + psql availability)
Output shape:
statustargetchecksrecommended_actionshealthy
Dashboard (Target Render)
Run scripts/skills.sh dashboard --target /path/to/project to generate a dashboard for a target project.
Dashboard generation behavior:
- reuses
skills/skill-system-dashboard/scripts/generate.pyas the single rendering source - reads target project context (
skills/,.tkt/,.memory/, and optional.env/.env.localdatabase URL) - writes output to
<target>/dashboard/index.htmlby default - tolerates missing target structures by rendering empty sections instead of failing
- returns structured JSON (including
status,output, andtarget) - includes one-click launch guidance mapping
/SK-dashboardtosk dashboard
Deploy (Sidecar)
Run scripts/skills.sh deploy --target /path/to/project [--mode minimal|local|full] [--no-dashboard] to deploy the current skill-system repo as a sidecar into a target project.
Deploy behavior:
- creates or reuses target
.skill-system/as the managed sidecar root - copies skill-system assets into the sidecar without overwriting existing sidecar files
- scaffolds missing target
config/,note/,.tkt/, andskills-lock.json - links mutable target state back into the sidecar so sidecar tools operate on target project state
- ensures target
skillsresolves to sidecarskillsfor existing CLI/dashboard path expectations - generates dashboard/index.html by default; use
--no-dashboardto skip - runs
doctor --targetafter deployment and returns a health summary - emits
dashboard_onboardingpayload fields so users can run/SK-dashboardor the equivalent CLI command immediately
Thin Host Plugin Shell MVP
The installer ships a minimal host-shell adapter to validate composition boundaries without taking ownership from existing modules.
Entry:
scripts/skills.sh host-shell bootstrap --target /path/to/project
scripts/skills.sh host-shell discover --target /path/to/project
scripts/skills.sh host-shell compat
scripts/skills.sh host-shell doctor --target /path/to/projectBoundary guarantees:
- Memory remains module-first (
mem.py+ MCP). Plugin behavior is optional adapter logic. - Control-plane ownership remains with
skill-system-tktandskill-system-review. - Planning ownership remains with
skill-system-workflow. - Graph/dashboard/debug ownership remains with their existing modules.
This is intentionally an MVP shell and not a platform redesign.
Update
Use scripts/update-skills.py to compare installed skill directories with hashes from skills-lock.json.
--allchecks every locked skill;--skill <name>checks one skill.- Add
--updateto reinstall missing/drifted skills and refreshcomputedHash. - Add
--dry-runto report planned updates without making changes. --preserve-insight/--no-preserve-insightcontrols local insight-preservation merge behavior (--preserve-insightdefault true).- Optional:
--lockfile <path>and--skills-dir <path>.
When update runs with preserve mode enabled, the installer performs a 3-way merge:
original baseline -> local modified -> upstream new
Conflicts are never auto-merged. Conflict markers are written for user review.
Behavior and Options
- Defaults to direct download for public GitHub repos.
- If download fails with auth/permission errors, falls back to git sparse checkout.
- Aborts if the destination skill directory already exists unless
--forceis set. - Global installs use
$SKILLS_GLOBAL_HOME/skills/<skill-name>(default~/.skills-system/skills). - Multiple
--pathvalues install multiple skills in one run, each named from the path basename unless--nameis supplied. - Options:
--ref <ref>(defaultmain),--dest <path>,--method auto|download|git,--force.
Notes
- Curated listing is fetched from
https://github.com/openai/skills/tree/main/skills/.curatedvia the GitHub API. If it is unavailable, explain the error and exit. - Private GitHub repos can be accessed via existing git credentials or optional
GITHUB_TOKEN/GH_TOKENfor download. - Git fallback tries HTTPS first, then SSH.
- Installed annotations come from scoped skill directories (
$SKILLS_GLOBAL_HOME/skillsand project-localskills/).
{
"schema_version": "2.0",
"id": "skill-system-installer",
"version": "1.0.0",
"capabilities": ["skill-install", "skill-list", "skill-update", "skill-status", "skill-sync", "skill-bootstrap", "skill-doctor", "skill-dashboard", "skill-deploy"],
"effects": ["net.fetch", "fs.write", "fs.read", "proc.exec"],
"operations": {
"bootstrap": {
"description": "First-run setup: detect missing structure, scaffold directories, compute pending lockfile hashes, validate skills.",
"input": {},
"output": {
"description": "Bootstrap report with checks and actions taken",
"fields": { "checks": "object", "actions_taken": "array" }
},
"entrypoints": {
"unix": ["bash", "scripts/skills.sh", "bootstrap"]
}
},
"doctor": {
"description": "Detect-only preflight checks for a target project. Reports readiness and recommended actions without changing files.",
"input": {
"target": { "type": "string", "required": false, "default": ".", "description": "Target project directory to inspect" }
},
"output": {
"description": "Preflight report",
"fields": {
"status": "ok | error",
"target": "string",
"checks": "object",
"recommended_actions": "array",
"healthy": "boolean"
}
},
"entrypoints": {
"unix": ["bash", "scripts/skills.sh", "doctor", "--target", "{target}"]
}
},
"dashboard": {
"description": "Generate target dashboard/index.html using target project context and tolerant empty-section rendering.",
"input": {
"target": { "type": "string", "required": false, "default": ".", "description": "Target project directory" }
},
"output": {
"description": "Dashboard generation report",
"fields": {
"status": "ok | error",
"output": "string",
"target": "string"
}
},
"entrypoints": {
"unix": ["bash", "scripts/skills.sh", "dashboard", "--target", "{target}"]
}
},
"deploy": {
"description": "Deploy the current skill-system repo as a sidecar into a target project and report post-deploy health.",
"input": {
"target": { "type": "string", "required": true, "description": "Target project directory" },
"mode": { "type": "string", "required": false, "default": "full", "description": "Bootstrap profile: minimal, local, or full" },
"dashboard": { "type": "boolean", "required": false, "default": false, "description": "Generate dashboard/index.html after deploy" }
},
"output": {
"description": "Deploy report with paths, actions taken, and doctor health summary",
"fields": {
"status": "ok | error",
"target": "string",
"sidecar": "string",
"deployed_paths": "object",
"actions_taken": "array",
"health_summary": "object"
}
},
"entrypoints": {
"unix": ["bash", "scripts/skills.sh", "deploy", "--target", "{target}", "--mode", "{mode}"]
}
},
"list": {
"description": "List available curated skills with installed annotations and show local/global installed skills.",
"input": {
"format": { "type": "string", "required": false, "default": "text", "description": "Output format: text or json" }
},
"output": {
"description": "List of curated skills with install status",
"fields": { "skills": "array of {name, installed}" }
},
"entrypoints": {
"unix": ["python3", "scripts/list-curated-skills.py", "--format", "{format}"],
"windows": ["python", "scripts/list-curated-skills.py", "--format", "{format}"]
}
},
"install": {
"description": "Install a skill from GitHub repo path. The scripts/skills.sh wrapper provides a scoped alternative entrypoint.",
"input": {
"repo": { "type": "string", "required": true, "description": "GitHub owner/repo" },
"path": { "type": "string", "required": true, "description": "Path to skill within repo" }
},
"output": {
"description": "Installed skill path",
"fields": { "installed_path": "string" }
},
"entrypoints": {
"unix": ["python3", "scripts/install-skill-from-github.py", "--repo", "{repo}", "--path", "{path}"],
"windows": ["python", "scripts/install-skill-from-github.py", "--repo", "{repo}", "--path", "{path}"],
"unix_wrapper": ["bash", "scripts/skills.sh", "install", "--repo", "{repo}", "--path", "{path}"]
}
},
"update": {
"description": "Check skill drift against lockfile and optionally update drifted skills.",
"input": {
"scope": { "type": "string", "required": true, "description": "Either all or one" },
"skill": { "type": "string", "required": false, "description": "Skill name when scope is one" },
"apply": { "type": "boolean", "required": false, "default": false, "description": "Apply updates when true" },
"dry_run": { "type": "boolean", "required": false, "default": false, "description": "Report only" },
"preserve_insight": { "type": "boolean", "required": false, "default": true, "description": "Preserve local insight edits via 3-way merge with conflict markers" }
},
"output": {
"description": "Drift report and optional update actions",
"fields": { "status": "ok | error", "table": "skill_name/local_hash/lock_hash/status" }
},
"entrypoints": {
"unix": ["python3", "scripts/update-skills.py", "--all"],
"windows": ["python", "scripts/update-skills.py", "--all"]
}
},
"status": {
"description": "Report drift/version status and spec-compatibility warnings.",
"input": {
"scope": { "type": "string", "required": false, "description": "global or local", "default": "local" },
"skill": { "type": "string", "required": false, "description": "Optional skill name" }
},
"output": {
"description": "Status rows with warning details",
"fields": { "status": "ok | error", "skills": "array" }
},
"entrypoints": {
"unix": ["bash", "scripts/skills.sh", "status"],
"windows": ["bash", "scripts/skills.sh", "status"]
}
},
"sync": {
"description": "Synchronize global skills into the local workspace.",
"input": {
"strategy": { "type": "string", "required": false, "default": "copy", "description": "Sync strategy: copy or symlink" },
"force": { "type": "boolean", "required": false, "default": false, "description": "Overwrite existing local skills when true" },
"skills": { "type": "string", "required": false, "description": "Comma-separated skill names" }
},
"output": {
"description": "Sync report and updated local lockfile",
"fields": { "status": "ok | error", "skills": "array of synced or skipped skill names" }
},
"entrypoints": {
"unix": ["bash", "scripts/skills.sh", "sync"]
}
}
},
"stdout_contract": {
"last_line_json": false
}
}