skilldrop-cli 0.6.0 → 0.8.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 +5 -1
- package/agents/README.md +35 -15
- package/bin/skilldrop.js +65 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -292,11 +292,15 @@ Four targets, each projecting only as much as the tool's format demands:
|
|
|
292
292
|
| *(default)* | `~/.claude/agents/<name>.md` | none — the file already is Claude Code's format |
|
|
293
293
|
| `--ide copilot` | `.github/agents/<name>.agent.md` | a rename |
|
|
294
294
|
| `--ide kiro` | `.kiro/agents/<name>.json` | generated JSON; tool names mapped to Kiro's built-ins |
|
|
295
|
+
| `--ide codex` | `~/.codex/agents/<name>.toml` (`--project` for repo) | generated TOML |
|
|
296
|
+
| `--ide antigravity` | `~/.gemini/config/agents/<name>.md` (`--project` → `.agents/agents/`) | frontmatter rewritten, `subagent: true` added |
|
|
295
297
|
| `--dest <dir>` | `<dir>/<name>.md` | none |
|
|
296
298
|
|
|
297
299
|
The Kiro emitter maps `Read`/`Grep`/`Glob`/`Bash` to `read`/`grep`/`glob`/`shell` against [Kiro's built-in tool reference](https://kiro.dev/docs/cli/reference/built-in-tools/), and **names any tool it can't map instead of dropping it silently** — a mistranslated permission is worse than a missing one. It omits `allowedTools` so you're prompted per tool call.
|
|
298
300
|
|
|
299
|
-
|
|
301
|
+
Each generated target omits the permission field it cannot map safely rather than guessing one: Kiro's `allowedTools` and Codex's `sandbox_mode` are both left unset, so an agent inherits the session's permissions and is prompted per call. A widened permission nobody asked for is worse than an extra prompt.
|
|
302
|
+
|
|
303
|
+
**Every surveyed tool now installs.** Only Cursor is absent, because it has no agent file format at all — use a custom mode ([`agents/README.md`](agents/README.md) has the steps).
|
|
300
304
|
|
|
301
305
|
### Third-party catalogs — publish your own skills through the same CLI
|
|
302
306
|
|
package/agents/README.md
CHANGED
|
@@ -4,7 +4,17 @@ Portable **reviewer agents** — opinionated personas you delegate code and test
|
|
|
4
4
|
|
|
5
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
6
|
|
|
7
|
-
Nothing auto-discovers *this* folder at the repo root, so it is the **canonical source of truth
|
|
7
|
+
Nothing auto-discovers *this* folder at the repo root, so it is the **canonical source of truth**. 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.
|
|
8
|
+
|
|
9
|
+
**The CLI installs into four of them** ([RFC-0012](../docs/rfcs/0012-subagent-installation.md)):
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx skilldrop-cli agents # list
|
|
13
|
+
npx skilldrop-cli install --agent devils-advocate # ~/.claude/agents/
|
|
14
|
+
npx skilldrop-cli install --agent devils-advocate --ide kiro # .kiro/agents/*.json
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Five of the five tools with a native format now install by command** — Claude Code, Kiro, Codex, Copilot, and Antigravity. Only Cursor needs hand-work, because it has no agent file format at all. Each section below gives the command where one exists, and the manual route either way.
|
|
8
18
|
|
|
9
19
|
## The agents
|
|
10
20
|
|
|
@@ -40,34 +50,44 @@ Cursor has no subagent file format. Two options:
|
|
|
40
50
|
|
|
41
51
|
### Codex (native subagents)
|
|
42
52
|
|
|
43
|
-
|
|
53
|
+
```bash
|
|
54
|
+
npx skilldrop-cli install --agent devils-advocate --ide codex # ~/.codex/agents/<name>.toml
|
|
55
|
+
```
|
|
44
56
|
|
|
45
|
-
|
|
57
|
+
Standalone TOML in `~/.codex/agents/` or `.codex/agents/` (`--project`). Codex requires `name`, `description`, and `developer_instructions`, and **rejects unknown fields** — so the emitter writes exactly those three. It leaves `sandbox_mode` unset, which means the agent inherits the parent session's permissions; Codex has no `tools` field, and guessing a sandbox value would either break the agent or silently widen what it can do.
|
|
46
58
|
|
|
47
59
|
### Kiro (native custom agents)
|
|
48
60
|
|
|
49
|
-
|
|
61
|
+
```bash
|
|
62
|
+
npx skilldrop-cli install --agent devils-advocate --ide kiro # .kiro/agents/<name>.json
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Kiro reads JSON agent definitions from `.kiro/agents/` (local) or `~/.kiro/agents/` (global). The emitter maps Claude Code tool names to [Kiro's built-ins](https://kiro.dev/docs/cli/reference/built-in-tools/) — `Read`/`Grep`/`Glob`/`Bash` → `read`/`grep`/`glob`/`shell` — and **names any tool it cannot map** rather than dropping it silently.
|
|
50
66
|
|
|
51
|
-
|
|
67
|
+
Two choices worth knowing if you hand-write one instead:
|
|
52
68
|
|
|
53
|
-
|
|
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
|
-
```
|
|
69
|
+
- **The prompt is inlined, not a `file://` reference.** Kiro's docs show a relative `file://` path but do not say whether it resolves against the workspace root or the JSON file, and a wrong path fails *silently* — the agent loads with no instructions.
|
|
70
|
+
- **`allowedTools` is omitted**, so you are prompted per tool call. That is the right default for a reviewer, and it avoids [kirodotdev/Kiro#6714](https://github.com/kirodotdev/Kiro/issues/6714), where the field does not load as configured.
|
|
61
71
|
|
|
62
72
|
**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
73
|
|
|
64
74
|
### GitHub Copilot (native custom agents)
|
|
65
75
|
|
|
66
|
-
|
|
76
|
+
```bash
|
|
77
|
+
npx skilldrop-cli install --agent devils-advocate --ide copilot # .github/agents/<name>.agent.md
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
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`. The install is a pure rename; nothing in the file changes.
|
|
67
81
|
|
|
68
82
|
### Antigravity CLI (plugin subagents)
|
|
69
83
|
|
|
70
|
-
|
|
84
|
+
```bash
|
|
85
|
+
npx skilldrop-cli install --agent devils-advocate --ide antigravity # ~/.gemini/config/agents/
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Antigravity discovers subagents at `~/.gemini/config/agents/<name>.md` (global) or `.agents/agents/<name>.md` (workspace, `--project`) — markdown with YAML frontmatter, same shape as these files. A plugin bundle is a *third* option, not a requirement; [RFC-0013](../docs/rfcs/0013-antigravity-plugin-bundle.md) records why an earlier draft wrongly thought it was the only one.
|
|
89
|
+
|
|
90
|
+
The emitter adds **`subagent: true`** — without it the agent exists but `invoke_subagent` cannot reach it — and maps `Read`/`Grep`/`Bash` to `view_file`/`grep_search`/`run_command`. Antigravity has no glob-style tool, so `Glob` is named and dropped rather than bent into `list_dir`.
|
|
71
91
|
|
|
72
92
|
### Continue, Cline, Aider, and other tools
|
|
73
93
|
|
package/bin/skilldrop.js
CHANGED
|
@@ -53,8 +53,10 @@ Options:
|
|
|
53
53
|
(default) ~/.claude/agents Claude Code (--project for repo scope)
|
|
54
54
|
--ide kiro ./.kiro/agents generated JSON, tools mapped
|
|
55
55
|
--ide copilot ./.github/agents <name>.agent.md
|
|
56
|
+
--ide codex ~/.codex/agents generated TOML (--project for repo)
|
|
57
|
+
--ide antigravity ~/.gemini/config/agents markdown, subagent: true
|
|
56
58
|
--dest <dir> any directory copied as-is
|
|
57
|
-
|
|
59
|
+
Cursor has no agent format — use a custom mode (agents/README.md).
|
|
58
60
|
--with-related also install each skill's related companions (one level)
|
|
59
61
|
--with-hooks also wire any hooks a skill declares (RFC-0006) — git pre-commit
|
|
60
62
|
reminders and Claude Code session-start context; degrades where the
|
|
@@ -201,11 +203,43 @@ function kiroAgentJSON(meta, body) {
|
|
|
201
203
|
return { json: JSON.stringify(agent, null, 2) + "\n", unmapped: [...new Set(unmapped)] };
|
|
202
204
|
}
|
|
203
205
|
|
|
206
|
+
/* Antigravity agent markdown (RFC-0013). Only mappings confirmed in Antigravity's own
|
|
207
|
+
subagents doc are listed. There is no glob-style tool in its file tooling
|
|
208
|
+
(view_file / list_dir / grep_search / write_to_file), so Glob is dropped and named
|
|
209
|
+
rather than bent into list_dir — a different operation. */
|
|
210
|
+
const ANTIGRAVITY_TOOLS = { Read: "view_file", Grep: "grep_search", Bash: "run_command" };
|
|
211
|
+
const ANTIGRAVITY_MODELS = new Set(["inherit", "flash", "pro"]);
|
|
212
|
+
|
|
213
|
+
function antigravityAgentMD(meta, body) {
|
|
214
|
+
const declared = meta.tools ? meta.tools.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
215
|
+
const tools = [], unmapped = [];
|
|
216
|
+
for (const d of declared) (ANTIGRAVITY_TOOLS[d] ? tools : unmapped).push(ANTIGRAVITY_TOOLS[d] || d);
|
|
217
|
+
// YAML double-quoted scalars are a superset of JSON strings, so JSON.stringify is a
|
|
218
|
+
// correct quoter here — descriptions contain em-dashes and embedded quotes.
|
|
219
|
+
const lines = [`name: ${JSON.stringify(meta.name)}`, `description: ${JSON.stringify(meta.description)}`];
|
|
220
|
+
if (tools.length) lines.push(`tools: [${tools.join(", ")}]`);
|
|
221
|
+
lines.push("subagent: true"); // required, or invoke_subagent cannot reach it
|
|
222
|
+
if (ANTIGRAVITY_MODELS.has(meta.model)) lines.push(`model: ${meta.model}`);
|
|
223
|
+
return { md: `---\n${lines.join("\n")}\n---\n\n${body}\n`, unmapped: [...new Set(unmapped)] };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/* Codex agent TOML. Schema confirmed at learn.chatgpt.com/docs/agent-configuration/subagents:
|
|
227
|
+
name, description and developer_instructions are required; unknown fields are rejected.
|
|
228
|
+
sandbox_mode is deliberately NOT emitted — Codex has no `tools` field, permissions come
|
|
229
|
+
from sandbox_mode, and its permitted values are unconfirmed. Omitting it inherits the
|
|
230
|
+
parent session, which is the only behaviour that can neither break the agent nor
|
|
231
|
+
silently widen what it may do. */
|
|
232
|
+
function codexAgentTOML(meta, body) {
|
|
233
|
+
const esc = (s) => s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
234
|
+
const safe = body.includes('"""') ? body.replace(/"""/g, '\\"\\"\\"') : body;
|
|
235
|
+
return `name = "${esc(meta.name)}"\n` +
|
|
236
|
+
`description = "${esc(meta.description)}"\n` +
|
|
237
|
+
`developer_instructions = """\n${safe}\n"""\n`;
|
|
238
|
+
}
|
|
239
|
+
|
|
204
240
|
/* Only plain-copy targets ship in RFC-0012. Everything else needs a projection the
|
|
205
241
|
install-target model (RFC-0010) has not settled — so say so instead of guessing a path. */
|
|
206
242
|
const AGENT_MANUAL = {
|
|
207
|
-
codex: ".codex/*.toml — the schema was never confirmed, so emitting one would be a guess",
|
|
208
|
-
antigravity: "an agents/ directory inside a plugin bundle you own",
|
|
209
243
|
cursor: "a custom mode — Cursor has no agent file format",
|
|
210
244
|
};
|
|
211
245
|
function agentTarget(flags) {
|
|
@@ -215,11 +249,17 @@ function agentTarget(flags) {
|
|
|
215
249
|
return flags.project
|
|
216
250
|
? { dest: path.resolve(".claude", "agents"), ide }
|
|
217
251
|
: { dest: path.join(os.homedir(), ".claude", "agents"), ide };
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
? { dest: path.join(os.homedir(), ".kiro", "agents"), ide }
|
|
221
|
-
: { dest: path.resolve(".kiro", "agents"), ide };
|
|
252
|
+
// Kiro and Copilot agent dirs are repo-relative by convention, so --project is implied.
|
|
253
|
+
if (ide === "kiro") return { dest: path.resolve(".kiro", "agents"), ide };
|
|
222
254
|
if (ide === "copilot") return { dest: path.resolve(".github", "agents"), ide };
|
|
255
|
+
if (ide === "codex")
|
|
256
|
+
return flags.project
|
|
257
|
+
? { dest: path.resolve(".codex", "agents"), ide }
|
|
258
|
+
: { dest: path.join(os.homedir(), ".codex", "agents"), ide };
|
|
259
|
+
if (ide === "antigravity")
|
|
260
|
+
return flags.project
|
|
261
|
+
? { dest: path.resolve(".agents", "agents"), ide }
|
|
262
|
+
: { dest: path.join(os.homedir(), ".gemini", "config", "agents"), ide };
|
|
223
263
|
const hint = AGENT_MANUAL[ide];
|
|
224
264
|
die(`--agent has no target for '${ide}'${hint ? ` — it needs ${hint}` : ""}.\n` +
|
|
225
265
|
` Copy it by hand (see agents/README.md), or use --dest <dir>. Tracked in RFC-0012.`);
|
|
@@ -238,6 +278,21 @@ function writeAgent(cat, a, dest, ide) {
|
|
|
238
278
|
? ` ${a}: no Kiro equivalent for ${unmapped.join(", ")} — dropped from tools, add by hand if needed`
|
|
239
279
|
: null };
|
|
240
280
|
}
|
|
281
|
+
if (ide === "antigravity") {
|
|
282
|
+
const raw = fs.readFileSync(src, "utf8");
|
|
283
|
+
const body = raw.split("---").slice(2).join("---").trim();
|
|
284
|
+
const { md, unmapped } = antigravityAgentMD(agentMeta(cat, a), body);
|
|
285
|
+
fs.writeFileSync(path.join(dest, `${a}.md`), md);
|
|
286
|
+
return { file: `${a}.md`, warn: unmapped.length
|
|
287
|
+
? ` ${a}: no Antigravity equivalent for ${unmapped.join(", ")} — dropped from tools, add by hand if needed`
|
|
288
|
+
: null };
|
|
289
|
+
}
|
|
290
|
+
if (ide === "codex") {
|
|
291
|
+
const raw = fs.readFileSync(src, "utf8");
|
|
292
|
+
const body = raw.split("---").slice(2).join("---").trim();
|
|
293
|
+
fs.writeFileSync(path.join(dest, `${a}.toml`), codexAgentTOML(agentMeta(cat, a), body));
|
|
294
|
+
return { file: `${a}.toml`, warn: null };
|
|
295
|
+
}
|
|
241
296
|
const name = ide === "copilot" ? `${a}.agent.md` : `${a}.md`;
|
|
242
297
|
fs.copyFileSync(src, path.join(dest, name));
|
|
243
298
|
return { file: name, warn: null };
|
|
@@ -562,6 +617,8 @@ function installAgents(args) {
|
|
|
562
617
|
if (ide === "claude") console.log("Delegate by name, e.g. \"use the devils-advocate agent on this diff\".");
|
|
563
618
|
if (ide === "kiro") console.log("Kiro grants `tools` but not auto-approval — you are prompted per call by design.");
|
|
564
619
|
if (ide === "copilot") console.log("Invoke with: copilot --agent <name>");
|
|
620
|
+
if (ide === "codex") console.log("sandbox_mode is left unset, so each agent inherits the parent session's permissions.");
|
|
621
|
+
if (ide === "antigravity") console.log("Emitted with `subagent: true` so invoke_subagent can reach them.");
|
|
565
622
|
if (cat.source !== BUNDLED)
|
|
566
623
|
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.`);
|
|
567
624
|
}
|
|
@@ -572,7 +629,7 @@ function uninstallAgents(args) {
|
|
|
572
629
|
const l = ledger(dest);
|
|
573
630
|
for (const a of args._) {
|
|
574
631
|
const rec = l.data[a];
|
|
575
|
-
for (const f of new Set([rec && rec.file, `${a}.md`, `${a}.json`, `${a}.agent.md`].filter(Boolean)))
|
|
632
|
+
for (const f of new Set([rec && rec.file, `${a}.md`, `${a}.json`, `${a}.agent.md`, `${a}.toml`].filter(Boolean)))
|
|
576
633
|
fs.rmSync(path.join(dest, f), { force: true });
|
|
577
634
|
delete l.data[a];
|
|
578
635
|
console.log(`removed ${a} from ${dest}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skilldrop-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
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"
|