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 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
- Codex and Antigravity still refuse, printing why: Codex's `.toml` agent schema was never confirmed, and emitting a guess is the one thing worse than not shipping the target. [`agents/README.md`](agents/README.md) has the manual route.
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** 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.
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
- 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."
53
+ ```bash
54
+ npx skilldrop-cli install --agent devils-advocate --ide codex # ~/.codex/agents/<name>.toml
55
+ ```
44
56
 
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."
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
- Kiro reads JSON agent definitions from `.kiro/agents/` (local) or `~/.kiro/agents/` (global). The filename minus `.json` becomes the agent's name.
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
- 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:
67
+ Two choices worth knowing if you hand-write one instead:
52
68
 
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
- ```
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
- 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.
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
- 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.
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
- Codex and Antigravity still refuse with the reason — see agents/README.md.
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
- if (ide === "kiro")
219
- return flags.project === false
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.6.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"