Install
$ agentstack add skill-efanwang-skills-manager-skills-manager ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Skills Manager
Manage the sibling skills of this directory for one installed agent at a time. A single skills-manager instance scans only its own parent directory, whether it is installed under a Claude Code, Cursor, or Codex CLI skills root. It does not aggregate skills across Claude Code, Cursor, and Codex CLI. Install a separate copy in each agent's skills root when the user wants separate per-agent inventories.
Supported installation roots include:
- Claude Code:
~/.claude/skills/or project.claude/skills/ - Cursor:
~/.cursor/skills/, project.cursor/skills/, or a shared project
skills directory the Cursor agent discovers
- Codex CLI:
~/.codex/skills/,$HOME/.agents/skills/, or project
.agents/skills/
Mental model
- Each skill is a sibling directory under
/containing a
SKILL.md.
sources.json(in this directory) records where each remote skill came from.
Without a record, a skill is unclaimed — we don't know its origin.
- A skill is one of three types:
- remote — has a
urlinsources.json; can be checked / updated. - local — has an empty
{}record; user marked it as private; skip checks. - unclaimed — no record at all; user hasn't told us where it came from.
When to trigger (and what to run)
Scenario A: list skills (and show update status)
Triggers: "list my skills", "what skills do I have", "show skills", "which skills are outdated", "check for updates".
Interpret "all my skills" / "我的所有 skill" as all sibling skill directories under this skills-manager installation's parent directory. Do not expand that to every programming tool's skills (Claude Code, Cursor, Codex CLI, etc.) unless the user explicitly asks for a cross-tool inventory.
Run full inventory by default. This keeps the list command ergonomic: if the first cheap scan finds unclaimed skills, inventory runs the source audit once, writes high-confidence claims, and returns the final post-audit table data.
python /scripts/inventory.py --check-remote --audit-unclaimed
If the user explicitly says "preview only", "just list, don't write", or "no audit", use the read-only command instead:
python /scripts/inventory.py --check-remote
Output shapes:
- Without
--audit-unclaimed: JSON array of inventory entries. - With
--audit-unclaimed: JSON object{ "entries": [...], "audit": {...} }.
Parse entries (or the bare array for read-only output) and render as a markdown table with exactly four semantic columns: skill name, type, description, and status. Localize the column labels to the user's response language instead of forcing Chinese.
Example for a Chinese response:
| Skill名称 | 类型 | 功能描述 | 状态 | |---|---|---|---| | brainstorming | Git | ... | 🟢 最新 / 🔴 过期 | | my-private | 本地 | ... | 🟢 最新 | | unknown-thing | 未知 | ... | 🟡 未知 |
Example for an English response:
| Skill name | Type | Description | Status | |---|---|---|---| | brainstorming | Git | ... | 🟢 Latest / 🔴 Outdated | | my-private | Local | ... | 🟢 Latest | | unknown-thing | Unknown | ... | 🟡 Unknown |
Output contract: always render all four semantic columns. Do not omit the description column to make the answer shorter, even on repeat list requests, after source-audit follow-ups, or when every skill has a known source. Use the inventory JSON description field as the source of the description, but choose whether to keep it as written, translate it, or summarize it according to the user's response language.
Status indicator contract:
- The status column must include one of these exact visual indicators:
🟢 for current, 🔴 for outdated, or 🟡 for unknown.
- These symbols are semantic status markers required by this skill's output
contract, not decorative emoji. They intentionally override generic style rules such as "avoid emoji" for this table's status column only.
- If the runtime, terminal, or user explicitly forbids emoji display, fall back
to text labels: [latest], [outdated], [unknown] (localized to the user's response language).
Display mappings:
- Type:
remote→Git;local→ localized "local";unclaimed→
localized "unknown".
- Status:
up_to_date→ localized "🟢 latest"update_available→ localized "🔴 outdated"local→ localized "🟢 latest"unclaimed/unknown/error/null→ localized "🟡 unknown"
After the table, summarize in the user's response language, for example in Chinese: "共 X 个,最新 Y 个,过期 Z 个,本地 W 个,未知 V 个"; or in English: "Total X, latest Y, outdated Z, local W, unknown V." If audit.ran is true, also summarize how many were auto-claimed, need review, or had no match.
If audit.ran is true and any report has decision: "no_match", decision: "needs_review", or decision: "git_remote_unsupported", do not stop after explaining that the script does not run web search. Continue immediately into Scenario E's agent web-search handoff in the same turn, unless the user explicitly said "just list", "no audit", "preview only", "do not search", or "no network". The intended default for list/check requests is:
inventory --check-remote --audit-unclaimed
→ auto-claim .git/config / embedded GitHub URL evidence
→ agent web search for remaining unknown/needs_review skills
→ sources.py claim-remote / claim-local for clear decisions
→ final table + concise summary
Do not offer "要处理未识别来源吗?" as the stopping point when unresolved reports already include search_query_hint; use those hints now.
If the user later asks something like "just show me the ones with updates", re-filter the same JSON output — do not re-run inventory.
Scenario B: update skill(s)
Triggers: "update X", "update all outdated", "refresh brainstorming", "pull latest".
- If user said "all outdated", first run inventory
--check-remoteto find
them.
- List the target skills back to the user for confirmation (destructive
action).
- For each, run:
``powershell python /scripts/update_skill.py ``
- Each successful update writes a backup under
.backup/--/.
Report the backup path in your summary so the user can roll back manually.
Scenario D: install a new skill from GitHub
Triggers: "install X from ", "add this skill: ", "下载这个 skill: ", or any time the user hands over a GitHub URL and asks you to set it up locally.
Always go through install_skill.py. Do not git clone manually — the script bundles cloning, atomic placement, and sources.json registration so the skill is correctly tracked from day one.
python /scripts/install_skill.py [--name ]
Accepted URL forms (the script normalizes all of these):
https://github.com//(only valid if SKILL.md is at the repo root)https://github.com///tree//https://github.com///blob///SKILL.mdhttps://raw.githubusercontent.com/////SKILL.mdgit@github.com:/.git
Defaults and behavior worth knowing:
- Skill name defaults to
namein the upstream SKILL.md frontmatter. Pass
--name to override (useful when names collide).
- Branch defaults to the repo's default branch (auto-detected via
ls-remote --symref). Pass --branch if the URL omits it AND the default is wrong, or if the branch name contains /.
- If a skill with the resolved name already exists, the existing copy is moved
to .backup/--/ before installing. Report this path back to the user.
- On any failure after the swap, the script tries to roll back. If rollback
also fails, it surfaces both error strings — pass them to the user verbatim.
Confirm with the user before installing (destructive if it overwrites an existing skill). After success, summarize: name, source repo, installed revision, backup path (if any).
Scenario C: delete a skill
Triggers: "delete X", "remove X", "uninstall X".
This is destructive; do not automate it.
- Confirm with the user: show the absolute path that will be moved.
- Backup using PowerShell (same drive, atomic on Windows):
``powershell $ts = Get-Date -Format yyyyMMdd-HHmmss Move-Item / /.backup/-$ts ``
- Remove the sources.json record (only if it had one):
``powershell python /scripts/sources.py remove ``
- Report success and the backup path.
Never edit sources.json directly. Always go through sources.py.
Scenario E: audit unclaimed skills (batch)
Triggers: "figure out where all my skills came from", "batch claim unknown skills", "auto-detect sources for installed skills", or proactively offer when Scenario A surfaces several unclaimed rows.
This is an agent-assisted source tracing workflow. The scripts collect mechanical evidence; the agent decides source identity; sources.py registers confirmed sources. Open-world source search belongs to the agent because it can use page, repository, owner, README, and search-result context to distinguish official sources from mirrors, dotfiles, registries, and marketplace copies.
Default invocation — DO NOT add --dry-run unless the user explicitly asks for a preview. Audit is not destructive: it only writes sources.json for low-risk evidence (.git/config or embedded source URL). No skill files are touched. Mistakes are reversible (sources.py remove and re-run). Treat audit like update_skill.py, not like install_skill.py or delete — no confirmation needed beforehand, just report results afterwards.
python /scripts/audit_unclaimed.py # collect evidence and auto-claim only trusted/explicit sources
python /scripts/audit_unclaimed.py --dry-run # ONLY when user says "先看看不要动" / "preview only"
If you (agent) reflexively add --dry-run "to be safe", you'll surprise the user the same way they were surprised before this note was added: the script will dutifully report high-similarity trusted hits but write nothing.
Per skill the workflow has three gates:
.git/configinspection (offline). If the skill directory is itself a
git checkout pointing at github.com, claim it with the live branch + rev-parse HEAD.
- SKILL.md local GitHub URL hint. A GitHub URL written inside the local
skill is treated as explicit evidence, then verified via raw + similarity.
- Agent web search. For unresolved skills, the script emits a
search_query_hint; the agent uses its own web search to find and judge the source, then registers confirmed results through sources.py.
Confidence rules:
- Trusted/explicit gates (
.git/config, local GitHub URL hint): high(both ratios ≥ 0.90) → auto-claim.installed_revisionis the upstream HEAD SHA **only when similarity is
exactly 1.0**. Otherwise it is recorded as null, so inventory reports update_available and update_skill.py can re-align it.
- Agent web search:
- The script does not run web search itself.
- The agent must use its available web search capability for unresolved
audit reports during Scenario A / Scenario E, unless the user explicitly opted out of search.
- Agent search results are evidence for source identity, not automatic claims.
- Once source identity is clear, run
sources.py claim-remoteor
sources.py claim-local.
When installed_revision is null, both inventory --check-remote and check_remote.py surface the skill as update_available so the user/agent is prompted to run update_skill.py, which overwrites the local copy with upstream HEAD and writes the now-correct installed_revision. This is the self-healing path: claim makes a conservative record, update aligns it.
Agent web-search handoff. Every unresolved report carries a search_query_hint when the local description is long enough. This is a mandatory continuation step for the agent, not a note to pass back to the user. Search with combinations such as:
SKILL.md GitHub
"" "SKILL.md"
"" GitHub
When reviewing web search results:
- Prefer official or purpose-built source repos, standard
skills//
paths, and repos whose owner/name clearly match the skill family.
- Treat dotfiles,
.agents/skills,.claude/skills, registry, marketplace,
mirror, awesome-list, and ordinary product repos as likely copies.
- Compare the candidate
SKILL.mdname, description, and opening body against
the local skill before registering it.
- Once source identity is clear, run
sources.py claim-remotewith the
candidate's url/branch/subpath. If multiple candidates still look plausible, ask the user instead of guessing.
When many skills remain unresolved, process them in a compact batch: search the strongest query for each skill, record clear matches immediately, and ask the user only about ambiguous or user-authored-looking skills. Do not final-answer with only "these need web search" when web search is available to the agent.
Output is a JSON {summary, reports, inventory_after} payload. Render to the user as:
- "已自动登记 K 个" — show each (name → repo+subpath, source: git_dir /
embedded_url). These were trusted/explicit matches.
- "未识别 M 个" — before finalizing, use
search_query_hintwith the
agent's web search capability. Once you have a source, agent runs sources.py claim-remote (if from GitHub) or sources.py claim-local (if user-authored). Do not re-run audit expecting web search to write records.
- Then re-render the Scenario A table from
inventory_afterso the user sees
the new state in one shot — no need to invoke inventory.py separately. (inventory_after is null when --dry-run is used, because sources.json wasn't modified and a fresh inventory would just repeat the pre-audit state.)
See the "Claim wizard" section below for the exact sources.py claim-remote / claim-local parameter syntax — it's the single source of truth for those commands.
Important: the script never auto claim-local. If a skill matched no upstream, surface it to the user and ask if it's their own work.
Claim wizard (handling unclaimed skills)
Triggers: "claim unknown skills", "I want to know where my skills came from", "set up update tracking for all skills", or proactively offer it when the user sees many unclaimed rows in scenario A.
For each unclaimed skill, in order:
- Read its SKILL.md (first ~60 lines). Note name + description + style.
- Search the web using the current agent's available web search
capability. Start with "" SKILL.md github, the local title, and any distinctive phrase from the description. Prefer GitHub source pages and official docs over registries, dotfiles, mirrors, and marketplace copies.
- Compare. For top 1–3 candidates, fetch the raw SKILL.md using the
current agent's web fetch tool or curl, save it to /.tmp/-candidate.md, then: ``powershell python /scripts/similarity.py //SKILL.md /.tmp/-candidate.md ``
- Decide based on
confidence:
high→ tell the user: "I'm confident this is from/. OK
to register?"
mid→ present candidates with ratios, ask user to pick.low→ ask: "Is this skill written by you (not from GitHub)? Or do you
remember the source URL?"
- Register. Once user confirms:
```powershell # From GitHub python /scripts/sources.py claim-remote \ --url --branch --subpath
# User-authored / private python /scripts/sources.py claim-local ```
claim-remote fetches upstream SKILL.md and compares it to local before recording installed_revision:
- byte-equal → records the real HEAD SHA returned by
git ls-remote - any difference → records
installed_revision = nulland emits a
verify_note explaining the similarity ratio Pass --no-resolve --assume-revision to skip the verification (offline / scripted scenarios); the caller is then responsible for the honesty of the recorded SHA.
A null revision is not an error: it's the honest "I know the source repo but not which commit your local c
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: EfanWang
- Source: EfanWang/skills-manager
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.