Use when the user wants to manage Agent Skills — install/add/acquire from a repo or path ("install skills from this repo", "이 repo로 스킬 설치해줘", "add this skill"), recommend skills that fit a project ("이 프로젝트에 맞는 스킬 추천", "what skills fit here"), or organize/dedup what they own ("스킬 관리", "스킬 정리"). Acquire: fetch candidates, curate a subset, dedup by purpose-digest, audit/rename, record provenance, flat-symlink to global/project. Recommend: catalog owned skills → match project need → activate. Token-frugal: lexical prefilter + LLM, no vectors; bodies read once at install.
Instal·la
npx skillscat add wonbywondev/claude-plugins/skill-manager Instal·la des del registre de SkillsCat.
skill-manager
Acquire third-party Agent Skills into the central repo (~/dev/agent/skills) the right way: curated, deduped, provenance-tracked, flat-symlinked. Engine is lexical prefilter + purpose-digest + LLM judgment (no LEANN/vector DB). Mechanics live in the plugin compass; this is the runbook.
Load helpers once:
source "${CLAUDE_PLUGIN_ROOT}/lib/common.sh"then source the otherlib/*.sh.
Or just run/skill-manager:add <repo|path>.
Pipeline
- fetch —
sm_fetch_clone <repo|path> <staged>thensm_fetch_candidates <staged>→ TSVrel⇥name⇥desc(broken symlinks & nested refs excluded). No placement yet. - select — if multiple candidates, run
sm_select_filter "<tsv>" "$(sm_installed_tool_keywords)"→ per-candidatekeep|exclude(superseded|already-installed)|flag(tool-overlap). The tool-overlap keywords come fromlib/tools.mapfiltered to installed CLIs (live discovery), so e.g. animagegen-*candidate flags against an installedpencil. Show the user the recommended subset and exclusions; let them confirm. Single candidate → auto. - digest — for each confirmed skill, generate a 1-2 line purpose-digest by reading the body ONCE: build the prompt with
sm_digest_prompt <skill.md> <name>, then YOU write the digest text. This is the only time the body enters context. - dedup (token-frugal) —
- Build the corpus with
sm_dedup_corpus— every owned skill (catalog description) with registry purpose-digests overlaid where present. This compares the new skill against the whole central repo (~400), not just the handful in the registry. One python pass. sm_prefilter "<new-digest>" "$(sm_dedup_corpus)" 8 0.08→ top-K candidates. Empty → no duplicate, skip the LLM judge entirely.- If candidates: compare the new digest against each candidate digest yourself (short text) → duplicate / similar / distinct. Only if digests are genuinely ambiguous, spawn a subagent to read the candidate + new bodies and return just a verdict (keeps main context clean).
- Trigger collision:
sm_shared_keywords "<new-triggers>" "<existing-triggers>"; overlap → warn. - Relations ledger: on similar/collision, run
sm_routing_lookup "$(sm_skills_repo)/ROUTING.md" <new> <counterpart>(기존 관계 확인) → ROUTING.md에 관계 항목 append를 제안(행 자격:백틱스킬명 2개+, 관계 1~2줄; 사용자 컨펌 후 쓰기). 관계는 registry digest에 넣지 않는다(digest=정체성만). 활성 스킬 description의 "Not for X — use Y" 1절은 런타임 분기 캐시로 별개 유지(서드파티 본문은 불변 — ROUTING.md에만). - On duplicate/similar, ask: continue / cancel / replace.
- Build the corpus with
- audit —
sm_audit_check <skill.md>(fix missing frontmatter);sm_audit_invocation <skill.md> <upstream_dir>→ the invocation name (= place folder name; frontmatternamenormalized). - place —
sm_place <src> <invocation_name> [group] [license_file]. Folder name = invocation name (rename). Group only in the source repo (e.g.taste-skill/<name>); third-party → carry LICENSE. - register —
sm_register_upsert <name> source=… source_type=git|npm|local fork_commit=… license=… upstream_dir=… digest="…" trigger_keywords="…" scope=… link_mode=copy. - link —
sm_link <placed_dir> <invocation_name> <scope>(scopeglobalorproject:<path>). Flat, per-skill — never link a group folder whole. If scope unspecified, recommend: always-useful → global; situational/variant → project or leave unlinked (token cost: each active skill's description is resident every session).
Recommend (project → owned skills)
When the user wants skills for a project ("이 프로젝트에 맞는 스킬 추천", "what skills fit here"), or via /skill-manager:recommend [brief]:
sm_catalog→ owned-skill catalog (name⇥desc; cohesive bundle = 1, grab-bag = per-leaf).- Match the project need (brief + detected stack + its CLAUDE.md/plan) against the catalog directly — no vectors (catalog is small; read it whole, handle Korean↔English). Pick top-N, prioritizing dormant skills (in
SKILLS_REPObut unlinked — e.g.korean/,gstack/). - Offer to activate:
sm_link "$(sm_skill_dir <name>)" <name> "project:<path>"(flat symlink into the project;globalonly if asked). Cohesive bundles activate as one umbrella entry.
Defaults & guards
- Third-party skills are vendored + symlinked, not turned into plugins/marketplace entries (that is for your own work).
- Skip broken/dangling symlinks everywhere (they crash indexers).
- Don't eager-backfill digests for the ~400 existing skills; generate lazily when one becomes a prefilter candidate.
Helpers
source ${CLAUDE_PLUGIN_ROOT}/lib/common.sh then lib/{fetch,select,digest,dedup,audit,place,register,link,recommend,usage,skill_aware,routing}.sh. Paths via SKILLS_REPO / GLOBAL_SKILLS_DIR / SKILL_MANAGER_HOME (env override).
Usage stats — 토큰 위생 (관측층 소비)
sm_usage_auto → telemetry DB 우선(~/dev/agent/data/claude-code-toolcalls.db, 멱등 증분·즉답), 없으면 sm_usage(transcript jsonl 풀스캔) 폴백. skill⇥count⇥last_used 호출순. /skill-manager:status가 표시. 활성인데 호출 0 = 매 세션 description 토큰 상주 후보. 단 ① dormant는 항상 0(무의미) ② 상황대기형(gpt-taste·variant)은 0이어도 유지. ⚠ 강등은 자동 X — 사용자 "스킬 정리" 요청 시에만 논의.
관측층 경계·활용 (⚠ read-only)
~/dev/agent/data/*(calls·skill_versions·events)의 쓰기 주체는 임포터뿐(계약: 그 폴더 README). skill-manager는 SELECT만(mode=ro) — INSERT/UPDATE/스키마 변경 절대 금지.- 로컬 변조·버전 drift 검사 =
skill_versions(SKILL.md sha256 시간축): 설치일 이후 새 sha 등장 = 로컬 수정 or 업데이트. upstream 추적은 registryfork_commit과 조합(3점 대조: upstream@HEAD ↔ fork_commit ↔ 우리 사본). 별도 content-hash 저장은 하지 않는다(skill_versions가 상위호환 — 현재 해시가 아닌 이력).