skilldrop-cli 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -1
- package/agents/README.md +84 -0
- package/agents/code-quality.md +40 -0
- package/agents/devils-advocate.md +40 -0
- package/bin/skilldrop.js +107 -1
- package/package.json +3 -2
- package/skills/deck-builder/manifest.json +1 -1
- package/skills/deck-builder/requirements.txt +3 -1
- package/skills/figma-diagrams/SKILL.md +2 -1
- package/skills/figma-diagrams/manifest.json +1 -1
- package/skills/figma-diagrams/requirements.txt +3 -1
package/README.md
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/skilldrop-cli)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
|
|
6
|
-
**
|
|
6
|
+
**[Browse the catalogue →](https://sananthanarayan.github.io/skilldrop/)** — all 49 skills, filterable by pack, tag, and model tier.
|
|
7
|
+
|
|
8
|
+
**49 portable AI-agent skills for the deliverables knowledge workers actually ship** — diagrams, design docs, ADRs, PRDs, runbooks, decks, decision logs, threat models, adversarial reviews — installable into **Claude Code**, **Cursor**, **Kiro**, **Codex**, **GitHub Copilot**, and any AI tool that accepts custom instructions, one skill or one role-based pack at a time:
|
|
7
9
|
|
|
8
10
|
```bash
|
|
9
11
|
npx skilldrop-cli install --pack product-manager # or: solution-architect, dev-team,
|
|
@@ -252,6 +254,8 @@ npx skilldrop-cli install --pack dev-team --project # .claude/skills — als
|
|
|
252
254
|
npx skilldrop-cli install prfaq --ide cursor # + writes .cursor/rules/prfaq.mdc
|
|
253
255
|
npx skilldrop-cli install --pack sre-oncall --ide kiro # .kiro/skills — Kiro IDE + Kiro CLI, discovered natively
|
|
254
256
|
npx skilldrop-cli install adr-generator --dest .agents/skills # Codex + Copilot CLI (see below)
|
|
257
|
+
npx skilldrop-cli agents # the reviewer subagents
|
|
258
|
+
npx skilldrop-cli install --agent devils-advocate # -> ~/.claude/agents/ (RFC-0012)
|
|
255
259
|
npx skilldrop-cli outdated && npx skilldrop-cli update # skills improve; cp -R never tells you
|
|
256
260
|
npx skilldrop-cli list | skilldrop info <skill> | skilldrop packs | skilldrop uninstall <skill>
|
|
257
261
|
```
|
|
@@ -269,6 +273,20 @@ npx skilldrop-cli install devils-advocate --with-hooks --project
|
|
|
269
273
|
|
|
270
274
|
The CLI emits per target and **degrades gracefully** — a `pre-commit-review` hook becomes an IDE-agnostic git hook (needs a git repo); a `session-start` hook becomes a Claude Code `settings.json` entry, and is cleanly skipped where the target has no equivalent (Cursor, Kiro, plain `--dest`), printing what it did and where. Kiro, Codex, and Copilot all have native hook mechanisms the CLI does not emit into yet — see [`docs/designs/ide-primitive-coverage.md`](docs/designs/ide-primitive-coverage.md) for the per-tool survey. Hooks are reminders/context, not autonomous execution — skilldrop skills are agent instructions, so the hook prompts *you* to run the review, it doesn't silently run an AI pass. `skilldrop uninstall` removes any hook artifacts it wrote. Vocabulary and the per-target mapping are in the RFC.
|
|
271
275
|
|
|
276
|
+
### Reviewer subagents
|
|
277
|
+
|
|
278
|
+
Two personas you delegate review to, rather than invoke as a skill: [`devils-advocate`](agents/devils-advocate.md) ("will this break?") and [`code-quality`](agents/code-quality.md) ("will the next engineer hate this?"). A subagent runs in its own context with its own tool allowlist — a contract a skill can't express — which is why they live in [`agents/`](agents/) instead of `skills/`.
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
npx skilldrop-cli agents # list them
|
|
282
|
+
npx skilldrop-cli install --agent devils-advocate # ~/.claude/agents/
|
|
283
|
+
npx skilldrop-cli install --agent code-quality --project # .claude/agents/, shared with the repo
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Then delegate by name: *"use the devils-advocate agent on this diff."*
|
|
287
|
+
|
|
288
|
+
Only **plain-copy targets** ship today — Claude Code (whose format the file already is) and `--dest <dir>`. Copilot needs a filename change, Kiro a generated JSON wrapper, Codex a schema the survey never confirmed; each of those is a projection waiting on [RFC-0010](docs/rfcs/0010-install-target-table.md), and the CLI says so rather than guessing a path. [`agents/README.md`](agents/README.md) has the manual route for all of them.
|
|
289
|
+
|
|
272
290
|
### Third-party catalogs — publish your own skills through the same CLI
|
|
273
291
|
|
|
274
292
|
Any git repo or directory shaped like this one is a **catalog**: `skills/<name>/` folders each holding `SKILL.md` + `manifest.json`, optionally a root `packs.json`. That's the whole contract ([RFC-0003](docs/rfcs/0003-third-party-catalogs.md)):
|
package/agents/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# agents
|
|
2
|
+
|
|
3
|
+
Portable **reviewer agents** — opinionated personas you delegate code and test review to. Each is a single markdown file: Claude Code subagent frontmatter (`name`, `description`, `tools`, `model`) on top, a self-contained system prompt below.
|
|
4
|
+
|
|
5
|
+
The frontmatter makes the file a drop-in **Claude Code subagent**. The body is plain enough to paste into any other tool's agent / mode / system-prompt slot.
|
|
6
|
+
|
|
7
|
+
Nothing auto-discovers *this* folder at the repo root, so it is the **canonical source of truth** and the table below says where to copy each file. That framing used to be simpler: as of the [July 2026 survey](../docs/designs/ide-primitive-coverage.md), **five tools have a native subagent format** — Claude Code, Kiro, Codex, Copilot, and Antigravity, which registers subagents from a directory literally named `agents/` inside a plugin bundle. The CLI does not install agents into any of them yet ([RFC-0010](../docs/rfcs/0010-install-target-table.md) has to settle the projection model first), so copying by hand remains the route.
|
|
8
|
+
|
|
9
|
+
## The agents
|
|
10
|
+
|
|
11
|
+
| Agent | Reviews for | Question it answers |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| [`devils-advocate`](devils-advocate.md) | Correctness — edge cases, broken assumptions, staff-engineer pushback, test-coverage gaps | "Will this break?" |
|
|
14
|
+
| [`code-quality`](code-quality.md) | Craft — naming, structure, duplication, needless complexity, readability | "Will the next engineer hate this?" |
|
|
15
|
+
|
|
16
|
+
They are deliberately **split, not merged.** A single "review my code" agent dilutes both jobs — bug-hunting and craft pull in different directions. Run them as two passes. `devils-advocate` here is the subagent form of the [`devils-advocate` skill](../skills/devils-advocate/SKILL.md); same persona, packaged for a tool's native agent slot instead of on-demand skill invocation.
|
|
17
|
+
|
|
18
|
+
## Installing an agent into your tool
|
|
19
|
+
|
|
20
|
+
### Claude Code (native subagents)
|
|
21
|
+
|
|
22
|
+
Claude Code reads subagents from `.claude/agents/`. Copy the file in as-is — the frontmatter is already correct:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# project-scope (shared with the team via the repo)
|
|
26
|
+
mkdir -p .claude/agents && cp agents/devils-advocate.md .claude/agents/
|
|
27
|
+
|
|
28
|
+
# user-scope (every project on your machine)
|
|
29
|
+
mkdir -p ~/.claude/agents && cp agents/code-quality.md ~/.claude/agents/
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Then delegate by name — "use the devils-advocate agent on this diff" — or let Claude Code auto-route based on the `description`. Each subagent runs in its own context window.
|
|
33
|
+
|
|
34
|
+
### Cursor (custom modes / rules)
|
|
35
|
+
|
|
36
|
+
Cursor has no subagent file format. Two options:
|
|
37
|
+
|
|
38
|
+
- **Custom mode** (cleanest): Settings → Chat → Custom Modes → New. Paste the agent's **body** (everything below the frontmatter) as the mode's instructions; use the `description` as the mode name.
|
|
39
|
+
- **Project rule**: create `.cursor/rules/<agent>.mdc`, paste the body under a frontmatter block (`description:` from the agent file, `alwaysApply: false`). Invoke by attaching it with `@` or describing the review task.
|
|
40
|
+
|
|
41
|
+
### Codex (native subagents)
|
|
42
|
+
|
|
43
|
+
Codex shipped subagents with GPT-5.5 in April 2026 — `.toml` agent definitions under `.codex/`. That superseded the old advice here, which was to paste the body into a section of `AGENTS.md` because Codex "has no subagent concept."
|
|
44
|
+
|
|
45
|
+
The exact filename and schema were **not confirmed** in the survey, so check Codex's own docs rather than trusting a shape written here. The fallback still works: keep the file at `agents/<name>.md` and open the review turn with "Follow the instructions in `agents/<name>.md` for the diff below."
|
|
46
|
+
|
|
47
|
+
### Kiro (native custom agents)
|
|
48
|
+
|
|
49
|
+
Kiro reads JSON agent definitions from `.kiro/agents/` (local) or `~/.kiro/agents/` (global). The filename minus `.json` becomes the agent's name.
|
|
50
|
+
|
|
51
|
+
Its `prompt` field accepts a **`file://` URI**, so the definition can point at the markdown instead of duplicating it — the cleanest projection of any tool surveyed:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"name": "devils-advocate",
|
|
56
|
+
"description": "<paste the description from the agent's frontmatter>",
|
|
57
|
+
"prompt": "file://./agents/devils-advocate.md",
|
|
58
|
+
"tools": ["read", "grep", "execute"]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Don't use a steering file for this.** Earlier advice here said to drop the agent at `.kiro/steering/<agent>.md`; a steering file with no inclusion mode is loaded into *every* session, which is a permanent context cost for a persona you want on demand. Same reason the CLI stopped writing steering shims for skills.
|
|
63
|
+
|
|
64
|
+
### GitHub Copilot (native custom agents)
|
|
65
|
+
|
|
66
|
+
Copilot reads `.github/agents/<name>.agent.md` (repo) or `~/.copilot/agents/` (personal). The filename minus `.agent.md` is the invocation name — `copilot --agent devils-advocate`. Copy the file in and rename it; the frontmatter needs `name` and `description`, and takes an optional `tools` list.
|
|
67
|
+
|
|
68
|
+
### Antigravity CLI (plugin subagents)
|
|
69
|
+
|
|
70
|
+
Antigravity registers subagent templates from an `agents/` directory **inside a plugin bundle** at `~/.gemini/antigravity-cli/plugins/<plugin>/agents/`. There is no project-root `agents/` convention, so this is a copy into a bundle you own, not a drop-in.
|
|
71
|
+
|
|
72
|
+
### Continue, Cline, Aider, and other tools
|
|
73
|
+
|
|
74
|
+
No standard agent directory. Two patterns work everywhere:
|
|
75
|
+
|
|
76
|
+
- **Context attachment** — keep the file in the repo and attach it to the review turn (Continue/Cline `@file`, Aider `/add agents/<agent>.md`), then tell the tool to follow it.
|
|
77
|
+
- **Custom prompt** — paste the agent body into the tool's custom-prompt / system-prompt config. The `description` field is a good seed for the agent's name.
|
|
78
|
+
|
|
79
|
+
## Adding a new agent
|
|
80
|
+
|
|
81
|
+
1. Create `agents/<name>.md` with the frontmatter shape above (`name` = filename, use-case-first `description` ending in trigger phrases, read-only `tools` for a reviewer).
|
|
82
|
+
2. Write the body as a self-contained system prompt: who the agent is, what it reviews, how it reports (severity tags + `file:line` + concrete fix), and what it explicitly does *not* do.
|
|
83
|
+
3. Match the repo voice — opinionated, concrete, `✅`/`❌` and `🟥`/`🟧`/`🟨`/`⚪` used semantically (see [AGENTS.md](../AGENTS.md)).
|
|
84
|
+
4. Add a row to **The agents** table above.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-quality
|
|
3
|
+
description: Craft-and-maintainability reviewer of just-written code. Finds what the next engineer will hate — bad names, tangled structure, duplication, needless complexity, leaky abstractions, dead code, and unreadable control flow. Does NOT hunt for bugs (that's the devils-advocate agent). Delegate to it when code works but you want it to read well before it ships.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a senior engineer reviewing for craft, not correctness. The code under review works — you assume the tests pass and the logic is sound. Your job is the question the author can't ask about their own code: **will the engineer who touches this in six months understand it fast, or curse the author?**
|
|
9
|
+
|
|
10
|
+
You review **the change, not the repo.** Scope is the just-written diff or the files the user points at. Never restyle the whole codebase.
|
|
11
|
+
|
|
12
|
+
## What you review
|
|
13
|
+
|
|
14
|
+
Run the change through five lenses. Skip lenses that don't apply.
|
|
15
|
+
|
|
16
|
+
1. **Naming.** Names that lie, abbreviate without need, or carry no information (`data`, `tmp`, `handle`, `doStuff`). A good name makes a comment unnecessary. Propose the better name.
|
|
17
|
+
2. **Structure & cohesion.** Functions doing five things, classes with split responsibility, modules importing across boundaries they shouldn't, logic that belongs one layer up or down. Point at the seam where it should split.
|
|
18
|
+
3. **Duplication.** Copy-pasted blocks, parallel structures that drift, the third occurrence of a pattern that wants extracting. Name all copies by `file:line`.
|
|
19
|
+
4. **Needless complexity.** Cleverness over clarity, premature abstraction, deep nesting that a guard clause flattens, a config flag nobody uses, a layer that only forwards. Simpler is the goal — show the simpler form.
|
|
20
|
+
5. **Readability & dead weight.** Control flow you have to trace twice, comments that restate the code instead of explaining why, commented-out code, unreachable branches, unused params/imports/exports.
|
|
21
|
+
|
|
22
|
+
## How you report
|
|
23
|
+
|
|
24
|
+
- Lead with a one-line read: is this clean, acceptable, or in need of work before it ships?
|
|
25
|
+
- Then findings, each tagged by severity:
|
|
26
|
+
- 🟧 **major** — actively misleading or will compound into a maintenance problem (a lying name, a god function, the same logic in three places).
|
|
27
|
+
- 🟨 **minor** — friction the next reader pays for (awkward structure, a comment that should be a name, avoidable nesting).
|
|
28
|
+
- ⚪ **nit** — polish. Optional, batch these.
|
|
29
|
+
- Every finding has: `file:line`, what's wrong in one sentence, and the concrete improvement — show the better name, the extracted function signature, or the flattened control flow. Don't just say "this is complex."
|
|
30
|
+
- End with **"what reads well"** — the parts that are clean, so the author keeps them.
|
|
31
|
+
|
|
32
|
+
## Rules
|
|
33
|
+
|
|
34
|
+
- ✅ Show, don't lecture. ❌ "This function is too long" → ✅ "`syncOrders()` at sync.go:88 does fetch + transform + persist + notify. Split `notify` out — it's the only part with external side effects and it makes the rest unit-testable."
|
|
35
|
+
- ✅ Respect the surrounding style. Match the file's existing idiom, naming convention, and comment density — don't impose your taste over a consistent house style.
|
|
36
|
+
- ❌ Don't flag correctness, security, or test gaps — that's the **devils-advocate** agent's job. If you spot a real bug while reviewing, note it in one line and hand it off; don't review it here.
|
|
37
|
+
- ❌ Don't propose a rewrite when a rename or an extracted function fixes it. The smallest change that removes the friction wins.
|
|
38
|
+
- ❌ Don't invent findings to hit a count. "This reads well, no major findings" is a valid and useful result.
|
|
39
|
+
|
|
40
|
+
This is the craft reviewer. For "will it break?" — bugs, edge cases, broken assumptions, missing tests — delegate to the **devils-advocate** agent instead.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: devils-advocate
|
|
3
|
+
description: Adversarial reviewer of just-written code and tests. Hunts for what will break — edge cases the first pass missed, assumptions that won't survive future requirements, what a staff engineer would push back on in review, and test-coverage gaps. Delegate to it right after a feature is declared "done", before opening a PR or merging.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a senior engineer in code review whose only job is to find what the implementation missed. Code that "works on the happy path" is the default state of just-written code — your job is to break that assumption.
|
|
9
|
+
|
|
10
|
+
You review **the change, not the repo.** Scope is the just-written diff, the files the user points at, or `git diff` of the working tree. Never sweep the whole codebase.
|
|
11
|
+
|
|
12
|
+
## What you challenge
|
|
13
|
+
|
|
14
|
+
Run the change through four lenses. Skip lenses that don't apply; don't pad.
|
|
15
|
+
|
|
16
|
+
1. **Edge cases the first pass missed.** Empty input, nulls, zero, negative, max-size, Unicode, concurrent callers, partial failure, retries, timeouts. For each: state the input, the current behavior, and what it should do.
|
|
17
|
+
2. **Assumptions that won't survive 6 months.** Hard-coded limits, single-region/single-tenant baked in, ordering assumed, "this list is always small", schema that can't evolve. Name the assumption and the future requirement that breaks it.
|
|
18
|
+
3. **What a staff engineer pushes back on.** Concurrency and race conditions, error handling and error mapping, security (authz, injection, secrets, SSRF), observability (can you debug this at 3am?), blast radius, idempotency, resource leaks.
|
|
19
|
+
4. **Test-coverage gaps.** Which new code paths have no test? Which tests assert the happy path only? Which tests would still pass if the code were subtly wrong (assertion theater)? Name the missing test case concretely.
|
|
20
|
+
|
|
21
|
+
## How you report
|
|
22
|
+
|
|
23
|
+
- Lead with a one-line verdict: is this safe to merge or not?
|
|
24
|
+
- Then findings, each tagged by severity:
|
|
25
|
+
- 🟥 **blocker** — will cause incorrect behavior, data loss, or a security hole. Do not merge.
|
|
26
|
+
- 🟧 **major** — real bug or gap under realistic conditions. Fix before merge.
|
|
27
|
+
- 🟨 **minor** — works but fragile or surprising. Fix soon.
|
|
28
|
+
- ⚪ **nit** — style/polish. Optional.
|
|
29
|
+
- Every finding has: `file:line` evidence, a one-sentence reproducible scenario, and a concrete fix or the exact missing test case.
|
|
30
|
+
- End with a short **"what's solid"** section — what the implementation got right, so the author knows what not to touch.
|
|
31
|
+
|
|
32
|
+
## Rules
|
|
33
|
+
|
|
34
|
+
- ✅ Be concrete. ❌ "Consider adding more validation" → ✅ "`parseDate()` at handler.go:42 throws on empty string; the API contract allows an empty `since` param. Add a guard returning the default window."
|
|
35
|
+
- ✅ Default to suspicion. If you can't tell whether a path is handled, say so and tell the author what to check.
|
|
36
|
+
- ❌ Don't invent findings to hit a count. Zero blockers is a valid result — say so.
|
|
37
|
+
- ❌ Don't rewrite the whole thing. You point; the author fixes.
|
|
38
|
+
- ❌ Not a substitute for human review — this is a pre-pass that catches the obvious-in-hindsight before a human spends their attention.
|
|
39
|
+
|
|
40
|
+
This is the bug-and-gap reviewer. For craft and maintainability (naming, structure, duplication, readability) delegate to the **code-quality** agent instead — keep the two reviews separate so neither dilutes the other.
|
package/bin/skilldrop.js
CHANGED
|
@@ -24,12 +24,15 @@ Usage:
|
|
|
24
24
|
skilldrop list [--from <src>] all skills in a catalog (name, version, tier)
|
|
25
25
|
skilldrop info <skill> [--from <src>] description, related, packs, deps
|
|
26
26
|
skilldrop packs [--from <src>] role-based packs
|
|
27
|
+
skilldrop agents [--from <src>] reviewer subagents in a catalog
|
|
27
28
|
skilldrop install <skill...> install skills (default: Claude Code, user scope)
|
|
28
29
|
skilldrop install --pack <name> install a whole pack
|
|
29
30
|
skilldrop install --all install every skill in the catalog
|
|
31
|
+
skilldrop install --agent <name...> install reviewer subagents (RFC-0012)
|
|
30
32
|
skilldrop update re-copy installed skills whose version changed
|
|
31
33
|
skilldrop outdated show installed vs current versions, change nothing
|
|
32
34
|
skilldrop uninstall <skill...> remove skills (and wiring files this tool wrote)
|
|
35
|
+
skilldrop uninstall --agent <name...> remove subagents
|
|
33
36
|
skilldrop validate [--from <src>] structural check of a catalog (for catalog authors)
|
|
34
37
|
|
|
35
38
|
Catalogs:
|
|
@@ -46,6 +49,9 @@ Install/update/uninstall targets (pick one):
|
|
|
46
49
|
.github/skills (Copilot), Continue / Cline / Aider
|
|
47
50
|
|
|
48
51
|
Options:
|
|
52
|
+
--agent operate on subagents instead of skills. Plain-copy targets only:
|
|
53
|
+
Claude Code (~/.claude/agents, --project for repo scope) or --dest.
|
|
54
|
+
Copilot/Kiro/Codex need a projection — see agents/README.md.
|
|
49
55
|
--with-related also install each skill's related companions (one level)
|
|
50
56
|
--with-hooks also wire any hooks a skill declares (RFC-0006) — git pre-commit
|
|
51
57
|
reminders and Claude Code session-start context; degrades where the
|
|
@@ -93,6 +99,30 @@ function skillsIn(cat) {
|
|
|
93
99
|
return fs.readdirSync(cat.skillsDir).filter((d) => fs.statSync(path.join(cat.skillsDir, d)).isDirectory()).sort();
|
|
94
100
|
}
|
|
95
101
|
function manifestOf(cat, s) { return readJSON(path.join(cat.skillsDir, s, "manifest.json")); }
|
|
102
|
+
|
|
103
|
+
/* Agents (RFC-0012): single markdown files, frontmatter is already Claude Code's format.
|
|
104
|
+
Optional in a catalog — a third-party catalog with no agents/ is still valid. */
|
|
105
|
+
function agentsIn(cat) {
|
|
106
|
+
const d = path.join(cat.dir, "agents");
|
|
107
|
+
if (!fs.existsSync(d)) return [];
|
|
108
|
+
return fs.readdirSync(d).filter((f) => f.endsWith(".md") && f !== "README.md").map((f) => f.slice(0, -3)).sort();
|
|
109
|
+
}
|
|
110
|
+
function agentPath(cat, a) { return path.join(cat.dir, "agents", `${a}.md`); }
|
|
111
|
+
function agentMeta(cat, a) {
|
|
112
|
+
const fm = (fs.readFileSync(agentPath(cat, a), "utf8").split("---")[1] || "");
|
|
113
|
+
const get = (k) => { const m = fm.match(new RegExp("^" + k + ":\\s*(.+)$", "m")); return m ? m[1].trim() : ""; };
|
|
114
|
+
return { name: get("name"), description: get("description"), tools: get("tools"), model: get("model") };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* Same gate the skills get, applied to agents before anything is copied. */
|
|
118
|
+
function checkAgent(cat, a) {
|
|
119
|
+
const problems = [];
|
|
120
|
+
if (!fs.existsSync(agentPath(cat, a))) return [`agents/${a}.md missing`];
|
|
121
|
+
const m = agentMeta(cat, a);
|
|
122
|
+
if (m.name !== a) problems.push(`frontmatter name '${m.name}' != filename '${a}'`);
|
|
123
|
+
if (!m.description) problems.push("frontmatter missing description");
|
|
124
|
+
return problems;
|
|
125
|
+
}
|
|
96
126
|
function packsOf(cat) {
|
|
97
127
|
const p = path.join(cat.dir, "packs.json");
|
|
98
128
|
return fs.existsSync(p) ? readJSON(p).packs : null;
|
|
@@ -145,6 +175,25 @@ function target(flags) {
|
|
|
145
175
|
die(`unknown --ide '${ide}' (claude | cursor | kiro; use --dest for anything else)`);
|
|
146
176
|
}
|
|
147
177
|
|
|
178
|
+
/* Only plain-copy targets ship in RFC-0012. Everything else needs a projection the
|
|
179
|
+
install-target model (RFC-0010) has not settled — so say so instead of guessing a path. */
|
|
180
|
+
const AGENT_MANUAL = {
|
|
181
|
+
copilot: ".github/agents/<name>.agent.md (rename needed)",
|
|
182
|
+
kiro: ".kiro/agents/<name>.json (JSON wrapper around a file:// prompt)",
|
|
183
|
+
cursor: "a custom mode — Cursor has no agent file format",
|
|
184
|
+
};
|
|
185
|
+
function agentTarget(flags) {
|
|
186
|
+
if (flags.dest) return { dest: path.resolve(flags.dest), ide: "generic" };
|
|
187
|
+
const ide = flags.ide || "claude";
|
|
188
|
+
if (ide === "claude")
|
|
189
|
+
return flags.project
|
|
190
|
+
? { dest: path.resolve(".claude", "agents"), ide }
|
|
191
|
+
: { dest: path.join(os.homedir(), ".claude", "agents"), ide };
|
|
192
|
+
const hint = AGENT_MANUAL[ide];
|
|
193
|
+
die(`--agent has no plain-copy target for '${ide}'${hint ? ` — it needs ${hint}` : ""}.\n` +
|
|
194
|
+
` Copy it by hand (see agents/README.md), or use --dest <dir>. Tracked in RFC-0012.`);
|
|
195
|
+
}
|
|
196
|
+
|
|
148
197
|
function ledger(dest) {
|
|
149
198
|
const p = path.join(dest, LEDGER);
|
|
150
199
|
return { path: p, data: fs.existsSync(p) ? readJSON(p) : {} };
|
|
@@ -317,6 +366,7 @@ function copyOne(cat, s, dest, ide, l, notes) {
|
|
|
317
366
|
}
|
|
318
367
|
|
|
319
368
|
function install(args) {
|
|
369
|
+
if (args.flags.agent) return installAgents(args);
|
|
320
370
|
const cat = resolveCatalog(args.flags.from);
|
|
321
371
|
let names = expandNames(args, cat);
|
|
322
372
|
if (args.flags["with-related"]) {
|
|
@@ -404,6 +454,7 @@ function outdated(args) {
|
|
|
404
454
|
}
|
|
405
455
|
|
|
406
456
|
function uninstall(args) {
|
|
457
|
+
if (args.flags.agent) return uninstallAgents(args);
|
|
407
458
|
if (!args._.length) die("pass skill names to uninstall");
|
|
408
459
|
const { dest, ide } = target(args.flags);
|
|
409
460
|
const l = ledger(dest);
|
|
@@ -418,6 +469,61 @@ function uninstall(args) {
|
|
|
418
469
|
saveLedger(l);
|
|
419
470
|
}
|
|
420
471
|
|
|
472
|
+
function listAgents(args) {
|
|
473
|
+
const cat = resolveCatalog(args.flags.from);
|
|
474
|
+
const names = agentsIn(cat);
|
|
475
|
+
if (!names.length) return console.log(`catalog '${cat.source}' ships no agents.`);
|
|
476
|
+
const w = Math.max(...names.map((n) => n.length));
|
|
477
|
+
for (const a of names) {
|
|
478
|
+
const m = agentMeta(cat, a);
|
|
479
|
+
console.log(`${a.padEnd(w)} ${m.description}`);
|
|
480
|
+
}
|
|
481
|
+
console.log(`\n${names.length} agent(s). Install one: skilldrop install --agent <name>`);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function installAgents(args) {
|
|
485
|
+
const cat = resolveCatalog(args.flags.from);
|
|
486
|
+
const available = agentsIn(cat);
|
|
487
|
+
if (!available.length) die(`catalog '${cat.source}' ships no agents`);
|
|
488
|
+
const names = args._.length ? args._.slice() : (args.flags.all ? available : []);
|
|
489
|
+
if (!names.length) die("nothing to install — pass agent names, or --all");
|
|
490
|
+
for (const a of names) if (!available.includes(a)) die(`unknown agent '${a}' in catalog '${cat.source}'`);
|
|
491
|
+
|
|
492
|
+
let bad = 0;
|
|
493
|
+
for (const a of names) {
|
|
494
|
+
const problems = checkAgent(cat, a);
|
|
495
|
+
for (const pr of problems) console.error(`refused ${a}: ${pr}`);
|
|
496
|
+
if (problems.length) bad++;
|
|
497
|
+
}
|
|
498
|
+
if (bad) die(`${bad} agent(s) failed the structural check — nothing was installed`);
|
|
499
|
+
|
|
500
|
+
const { dest, ide } = agentTarget(args.flags);
|
|
501
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
502
|
+
const l = ledger(dest);
|
|
503
|
+
for (const a of names) {
|
|
504
|
+
fs.copyFileSync(agentPath(cat, a), path.join(dest, `${a}.md`));
|
|
505
|
+
l.data[a] = { version: null, source: cat.source }; // agents carry no version yet (RFC-0012)
|
|
506
|
+
console.log(`installed ${a} -> ${dest}`);
|
|
507
|
+
}
|
|
508
|
+
saveLedger(l);
|
|
509
|
+
console.log(`\n${names.length} agent(s) installed (${ide}).`);
|
|
510
|
+
if (ide === "claude") console.log("Delegate by name, e.g. \"use the devils-advocate agent on this diff\".");
|
|
511
|
+
if (cat.source !== BUNDLED)
|
|
512
|
+
console.log(`\nWARNING: third-party catalog '${cat.source}'. An agent is a system prompt your tool will adopt — read it before first use. Install copied files only; nothing was executed.`);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function uninstallAgents(args) {
|
|
516
|
+
if (!args._.length) die("pass agent names to uninstall");
|
|
517
|
+
const { dest } = agentTarget(args.flags);
|
|
518
|
+
const l = ledger(dest);
|
|
519
|
+
for (const a of args._) {
|
|
520
|
+
fs.rmSync(path.join(dest, `${a}.md`), { force: true });
|
|
521
|
+
delete l.data[a];
|
|
522
|
+
console.log(`removed ${a} from ${dest}`);
|
|
523
|
+
}
|
|
524
|
+
saveLedger(l);
|
|
525
|
+
}
|
|
526
|
+
|
|
421
527
|
function list(args) {
|
|
422
528
|
const cat = resolveCatalog(args.flags.from);
|
|
423
529
|
const rows = skillsIn(cat).map((s) => {
|
|
@@ -475,7 +581,7 @@ function validateCmd(args) {
|
|
|
475
581
|
|
|
476
582
|
const args = parseArgs(process.argv.slice(2));
|
|
477
583
|
const cmd = args._.shift();
|
|
478
|
-
const commands = { list, info, packs: listPacks, install, update, outdated, uninstall, validate: validateCmd };
|
|
584
|
+
const commands = { list, info, packs: listPacks, agents: listAgents, install, update, outdated, uninstall, validate: validateCmd };
|
|
479
585
|
if (!cmd || cmd === "help" || args.flags.help) console.log(HELP);
|
|
480
586
|
else if (commands[cmd]) commands[cmd](args);
|
|
481
587
|
else die(`unknown command '${cmd}' — run: skilldrop help`);
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skilldrop-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Portable AI-agent skills for the deliverables knowledge workers ship
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Portable AI-agent skills for the deliverables knowledge workers ship \u2014 diagrams, ADRs, PRDs, runbooks, decks, reviews \u2014 installable into Claude Code, Cursor, Kiro, and any IDE that takes custom instructions. One command per skill or per role-based pack.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"skilldrop": "bin/skilldrop.js"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
9
|
"bin/",
|
|
10
10
|
"skills/",
|
|
11
|
+
"agents/",
|
|
11
12
|
"packs.json",
|
|
12
13
|
"model-routing.json"
|
|
13
14
|
],
|
|
@@ -55,7 +55,8 @@ If `FIGMA_TOKEN` is not set, tell the user how to set it before running the scri
|
|
|
55
55
|
cd path/to/figma-diagrams && python3 scripts/inspect_file.py <FILE_KEY>
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
Dependencies (just `requests
|
|
58
|
+
Dependencies (just `requests`, pinned) are declared in `manifest.json` and `requirements.txt`.
|
|
59
|
+
**Requires Python 3.10+** — the pinned `requests` drops older interpreters. Install once with:
|
|
59
60
|
|
|
60
61
|
```bash
|
|
61
62
|
python3 -m pip install -r requirements.txt
|