Skip to content

feat: Cabinet-style skill installer in /skills UI#21

Merged
AvivK5498 merged 2 commits into
mainfrom
feat/skill-installer
May 15, 2026
Merged

feat: Cabinet-style skill installer in /skills UI#21
AvivK5498 merged 2 commits into
mainfrom
feat/skill-installer

Conversation

@AvivK5498

Copy link
Copy Markdown
Owner

Summary

  • Adds an Install skill button to /skills that pulls SKILL bundles from skills.sh, github.com URLs, or github:owner/repo[/skill] shortcodes — no shell needed
  • Three new daemon endpoints (/api/skills/preview, /api/skills/install, DELETE /api/skills/:key); install can optionally attach the skill to one or more agents in a single call
  • Per-skill provenance in data/skills-lock.json drives the source pill + uninstall button on each installed-skill card; post-install screen surfaces scanSkillDirectory findings inline (warnings never block install)

Implementation notes

  • src/skills/import-source.ts — parser for skills.sh (incl. www.), github.com URLs (/tree/<ref> aware), and github:owner/repo[@/]skill shorthand. local: paths intentionally unsupported.
  • src/skills/import.ts — shallow git clone --branch <ref> with a strict ref whitelist; resolves the skill subtree via direct path → /skills/<name>.claude-plugin/plugin.json → recursive walk; copies with verbatimSymlinks so a hostile bundle can't symlink out of the clone.
  • src/skills/lock.ts — JSON lockfile, atomic-ish read/update/remove.
  • Server changes contained to src/server.ts; GET /api/available-skills now carries each skill's lock entry so the UI can render provenance without an extra round-trip. clearSkillCache() fires on install/uninstall.
  • UI: new SkillInstallDialog (paste → preview → install) with agent-attach toggles; /skills page gets uninstall confirm + source pill.

Test plan

  • 14/14 parser unit tests pass (bun test src/skills/import-source.test.ts)
  • npx tsc --noEmit clean (root + ui); next build clean
  • End-to-end smoke against a sandboxed daemon: install github:anthropics/skills/pdf → file on disk, lockfile written, list endpoint returns provenance, uninstall cleans both
  • Manual install of https://www.skills.sh/juliusbrussee/caveman/caveman against live worktree daemon (the fix in 4c60b10)
  • Negative paths rejected: local:/etc/passwd (unknown source), ref=--upload-pack=evil (ref injection), DELETE /api/skills/..%2Fetc (traversal)

🤖 Generated with Claude Code

AvivK5498 and others added 2 commits May 15, 2026 13:49
Adds three daemon endpoints and an Install dialog so skills can be pulled
from skills.sh / github.com / github:owner/repo[/skill] without leaving
the UI.

Backend (src/skills/):
- import-source.ts: parser for skills.sh URL, github.com URL, and
  github:owner/repo[@/]skill shorthand. local: explicitly unsupported.
- import.ts: previewSkill() hits the GitHub API + raw SKILL.md for the
  preview card; importSkill() shallow-clones, resolves the skill subtree
  (direct, /skills/, .claude-plugin manifest, recursive walk), copies
  with verbatimSymlinks. Tight ref whitelist guards `git clone --branch`.
- lock.ts: data/skills-lock.json keyed by skill name; provenance survives
  restarts, drives the UI's source pill + uninstall button.

Endpoints in src/server.ts:
- POST /api/skills/preview, POST /api/skills/install, DELETE /api/skills/:key
- GET /api/available-skills now returns each skill's lock entry
- install can attach to one or more agents in a single call

UI (ui/):
- New SkillInstallDialog with paste-and-preview flow + agent attach toggles
- /skills page gets an Install button; installed skills show source +
  uninstall confirm; post-install screen surfaces scanSkillDirectory
  findings inline (warnings never block install).

12/12 parser unit tests; smoke-tested install/list/uninstall against a
local daemon (pdf skill from anthropics/skills).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
skills.sh redirects to www.skills.sh in the browser, so URLs the user
pastes from the address bar were rejected with "unrecognized source
format". Allow the optional www. prefix; add a regression test for the
exact URL that surfaced this.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@AvivK5498 AvivK5498 merged commit e5d506f into main May 15, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant