@drunkcoding/agents-and-skills 0.0.39 → 0.0.40

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.
@@ -12,7 +12,7 @@
12
12
  "name": "tech-graph",
13
13
  "source": "./plugins/tech-graph",
14
14
  "description": "6-step wizard for technical diagrams (SVG/PNG) via fireworks-tech-graph",
15
- "version": "0.0.39",
15
+ "version": "0.0.40",
16
16
  "category": "diagram",
17
17
  "keywords": [
18
18
  "diagram",
@@ -26,7 +26,7 @@
26
26
  "name": "html-effectiveness",
27
27
  "source": "./plugins/html-effectiveness",
28
28
  "description": "Generate self-contained interactive HTML reports from 20 upstream templates via a conversational agent.",
29
- "version": "0.0.39",
29
+ "version": "0.0.40",
30
30
  "category": "reports",
31
31
  "keywords": [
32
32
  "html",
@@ -41,7 +41,7 @@
41
41
  "name": "plugin-validator",
42
42
  "source": "./plugins/plugin-validator",
43
43
  "description": "Orchestrated validator for Claude Code plugins — validates skills, agents, commands, and hooks across every plugin under plugins/**.",
44
- "version": "0.0.39",
44
+ "version": "0.0.40",
45
45
  "category": "tooling",
46
46
  "keywords": [
47
47
  "validation",
@@ -57,7 +57,7 @@
57
57
  "name": "team-share",
58
58
  "source": "./plugins/team-share",
59
59
  "description": "Onboard your team with an interactive setup menu: install CodeGraph, build the Understand-Anything knowledge graph, and share Claude Code settings — run any combination, all idempotent.",
60
- "version": "0.0.39",
60
+ "version": "0.0.40",
61
61
  "category": "tooling",
62
62
  "keywords": [
63
63
  "onboarding",
@@ -73,7 +73,7 @@
73
73
  "name": "multica-tool",
74
74
  "source": "./plugins/multica-tool",
75
75
  "description": "Export, import, and sync Multica skills, agents, and squads between workspaces.",
76
- "version": "0.0.39",
76
+ "version": "0.0.40",
77
77
  "category": "workflow",
78
78
  "keywords": [
79
79
  "multica",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drunkcoding/agents-and-skills",
3
- "version": "0.0.39",
3
+ "version": "0.0.40",
4
4
  "description": "Personal collection of Claude Code skills and agents, installable via `npx skills`.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "html-effectiveness",
3
3
  "displayName": "HTML Effectiveness Reports",
4
- "version": "0.0.39",
4
+ "version": "0.0.40",
5
5
  "description": "Generate self-contained interactive HTML reports from 20 upstream templates via a conversational agent.",
6
6
  "author": {
7
7
  "name": "Steven Hoang"
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "multica-tool",
3
- "version": "0.0.39",
3
+ "version": "0.0.40",
4
4
  "description": "Export, import, and sync Multica skills, agents, and squads between workspaces via the multica CLI."
5
5
  }
@@ -31,7 +31,7 @@ export function redactAgent(a) {
31
31
  // a is a normalized agent from getAgent, with `custom_env`/
32
32
  // `custom_env_fetch_failed` attached by the caller (collectAgent) — getAgent
33
33
  // itself never fetches custom_env, since it requires a separate audited call.
34
- const { id, has_custom_env, mcp_config_redacted, custom_env_fetch_failed, mcp_config, custom_env, skills, runtime_id, ...rest } = a;
34
+ const { id, has_custom_env, mcp_config_redacted, custom_env_fetch_failed, mcp_config, custom_env, skills, runtime_id, instructions, ...rest } = a;
35
35
  const mcpUsable = !mcp_config_redacted && nonEmpty(mcp_config);
36
36
  const envUsable = !custom_env_fetch_failed && nonEmpty(custom_env);
37
37
  // mcp_config_redacted / custom_env_fetch_failed alone still flag hadSecrets even
@@ -39,10 +39,10 @@ export function redactAgent(a) {
39
39
  // but couldn't be captured, not just silently see an empty bundle.
40
40
  const hadSecrets = mcpUsable || envUsable || !!mcp_config_redacted || !!custom_env_fetch_failed;
41
41
  return {
42
- // source_id lets import-time mention rewriting map stale `mention://agent/<id>`
43
- // links (in this or another agent's/squad's instructions) to the new id.
44
42
  record: {
45
43
  ...rest,
44
+ // source_id lets import-time mention rewriting map stale `mention://agent/<id>`
45
+ // links (in this or another agent's/squad's instructions) to the new id.
46
46
  source_id: id,
47
47
  source_runtime_id: runtime_id,
48
48
  skill_names: [],
@@ -51,6 +51,9 @@ export function redactAgent(a) {
51
51
  had_secrets: hadSecrets,
52
52
  },
53
53
  hadSecrets,
54
+ // instructions are written to a sibling .md by the caller (see avatar_file),
55
+ // never embedded in the JSON record.
56
+ instructions: instructions ?? "",
54
57
  };
55
58
  }
56
59
 
@@ -65,7 +68,13 @@ export function buildManifest({ scope, sourceWorkspaceId, skills, agents, squads
65
68
  source_workspace_id: sourceWorkspaceId,
66
69
  skills: [...seenSkills.values()].map((s) => ({ name: s.name, dir: `skills/${slugify(s.name)}`, source_id: s.source_id })),
67
70
  agents: [...seenAgents.values()].map((a) => ({ name: a.name, file: `agents/${slugify(a.name)}.json`, source_id: a.source_id, source_runtime_id: a.source_runtime_id, source_runtime_provider: a.source_runtime_provider ?? null, skill_names: a.skill_names, had_secrets: !!a.had_secrets })),
68
- squads: (squads ?? []).map((squad) => ({ name: squad.name, file: `squads/${slugify(squad.name)}.json`, description: squad.description ?? "", instructions: squad.instructions ?? "", avatar_url: squad.avatar_url ?? null, leader_name: squad.leader_name, members: squad.members })),
71
+ squads: (squads ?? []).map((squad) => {
72
+ const file = `squads/${slugify(squad.name)}.json`;
73
+ const entry = { name: squad.name, file, description: squad.description ?? "", avatar_url: squad.avatar_url ?? null, leader_name: squad.leader_name, members: squad.members };
74
+ // Instructions go to a sibling .md (see squad write loop); only referenced when non-empty.
75
+ if (squad.instructions) entry.instructions_file = file.replace(/\.json$/, ".md");
76
+ return entry;
77
+ }),
69
78
  };
70
79
  }
71
80
 
@@ -170,10 +179,21 @@ export function exportResource({ cli, scope, ids, outDir, sourceWorkspaceId, fs
170
179
  record.avatar_file = rel;
171
180
  }
172
181
  }
182
+ // Instructions live in a sibling .md for reviewability (same sibling-file
183
+ // pattern as avatar_file); only written when non-empty.
184
+ if (red.instructions) {
185
+ const rel = entry.file.replace(/\.json$/, ".md");
186
+ fs.writeFileSync(`${outDir}/${rel}`, red.instructions);
187
+ record.instructions_file = rel;
188
+ }
173
189
  fs.writeFileSync(`${outDir}/${entry.file}`, JSON.stringify(record, null, 2));
174
190
  }
191
+ const squadInstrByName = new Map(squads.map((s) => [s.name, s.instructions ?? ""]));
175
192
  for (const entry of manifest.squads) {
176
193
  fs.mkdirSync(`${outDir}/squads`, { recursive: true });
194
+ if (entry.instructions_file) {
195
+ fs.writeFileSync(`${outDir}/${entry.instructions_file}`, squadInstrByName.get(entry.name) ?? "");
196
+ }
177
197
  fs.writeFileSync(`${outDir}/${entry.file}`, JSON.stringify(entry, null, 2));
178
198
  }
179
199
  fs.writeFileSync(`${outDir}/manifest.json`, JSON.stringify(manifest, null, 2));
@@ -1,6 +1,16 @@
1
1
  import * as nodeFs from "node:fs";
2
2
  import { listSkills, listAgents, listSquads, listRuntimes, listWorkspaceMembers, getSquadMembers, findByName, makeCli, realExec, requireAuth, resolveWorkspaceId } from "./lib.mjs";
3
3
 
4
+ // Instructions live in a sibling .md referenced by `instructions_file` (mirrors
5
+ // avatar_file). Legacy bundles carry no instructions_file and keep instructions
6
+ // inline in the JSON — fall back to that so older exports still import.
7
+ function readInstructions(fs, dir, rec) {
8
+ if (rec.instructions_file && fs.existsSync(`${dir}/${rec.instructions_file}`)) {
9
+ return fs.readFileSync(`${dir}/${rec.instructions_file}`, "utf8");
10
+ }
11
+ return rec.instructions ?? "";
12
+ }
13
+
4
14
  // Relative paths of every file under root (recursing into subdirs like scripts/).
5
15
  function walkSkillFiles(fs, root, rel = "") {
6
16
  const out = [];
@@ -82,7 +92,8 @@ export function importAgents({ cli, manifest, dir, skillIdMap, runtimeMap, fs =
82
92
  "--max-concurrent-tasks", String(rec.max_concurrent_tasks ?? 6),
83
93
  ];
84
94
  if (rec.description) common.push("--description", rec.description);
85
- if (rec.instructions) common.push("--instructions", rec.instructions);
95
+ const instructions = readInstructions(fs, dir, rec);
96
+ if (instructions) common.push("--instructions", instructions);
86
97
  if (rec.model) common.push("--model", rec.model);
87
98
  if (rec.thinking_level) common.push("--thinking-level", rec.thinking_level);
88
99
  if (rec.runtime_config && Object.keys(rec.runtime_config).length) common.push("--runtime-config", JSON.stringify(rec.runtime_config));
@@ -184,9 +195,10 @@ export function rewriteAgentMentions({ cli, manifest, dir, agentIdMap, sourceIdM
184
195
  let updated = 0;
185
196
  for (const a of manifest.agents) {
186
197
  const rec = JSON.parse(fs.readFileSync(`${dir}/${a.file}`, "utf8"));
187
- if (!rec.instructions) continue;
188
- const rewritten = rewriteMentions(rec.instructions, sourceIdMap);
189
- if (rewritten === rec.instructions) continue;
198
+ const instructions = readInstructions(fs, dir, rec);
199
+ if (!instructions) continue;
200
+ const rewritten = rewriteMentions(instructions, sourceIdMap);
201
+ if (rewritten === instructions) continue;
190
202
  cli.run(["agent", "update", agentIdMap.get(rec.name), "--instructions", rewritten]);
191
203
  updated++;
192
204
  }
@@ -280,6 +292,7 @@ export function importBundle({ cli, dir, runtimeMap, fs = nodeFs }) {
280
292
  const squadIdMap = new Map();
281
293
  let squadsCreated = 0, squadsUpdated = 0;
282
294
  for (const squad of manifest.squads ?? []) {
295
+ squad.instructions = readInstructions(fs, dir, squad);
283
296
  const r = importSquad({ cli, squad, agentIdMap: agentRes.idMap, sourceIdMap: agentRes.sourceIdMap });
284
297
  squadIdMap.set(squad.name, r.newId);
285
298
  squadsCreated += r.created;
@@ -52,7 +52,7 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/multica-export.mjs" \
52
52
 
53
53
  Pass `--scope all` (with no `--id`) to export the **entire workspace** — every skill, agent, and squad — into one flat, deduped bundle. A skill or agent shared across many agents/squads is written exactly once and referenced by name.
54
54
 
55
- The script writes `manifest.json`, skill SKILL.md files, agent JSON files, and squad JSON files into `<dir>`.
55
+ The script writes `manifest.json`, skill `SKILL.md` files, agent JSON files, and squad JSON files into `<dir>`. Each agent's and squad's **instructions** (system prompt / charter) are written to a sibling Markdown file — `agents/<slug>.md`, `squads/<slug>.md` — referenced by an `instructions_file` key in the JSON, so the prose is easy to read, diff, and edit. Agents/squads with no instructions get no `.md`.
56
56
 
57
57
  Avatars are captured automatically: an agent's uploaded-image avatar is downloaded into the bundle (`agents/<slug>.avatar.<ext>`) and referenced by `avatar_file`; emoji avatars (agents and squads) and a squad's avatar are recorded as the `avatar_url` string.
58
58
 
@@ -40,6 +40,8 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/multica-import.mjs" \
40
40
 
41
41
  The import also rewrites any `mention://agent/<id>` link inside squad and agent instructions (e.g. `[@dev-backend](mention://agent/<id>)`) from the source agent's id to its new id in the target workspace — the CLI does this automatically for every agent captured in the bundle; no extra flag needed. Mentions pointing to an agent outside the bundle are left untouched.
42
42
 
43
+ Instructions are read back from each resource's sibling `.md` (`agents/<slug>.md`, `squads/<slug>.md`) when present — editing that Markdown is the supported way to review and enhance an agent's or squad's instructions before import. Older bundles that predate the split (instructions inline in the JSON, no `instructions_file`) still import unchanged.
44
+
43
45
  Avatars are restored automatically, but **only when the target resource has none** — an existing agent or squad that already carries an avatar is never overwritten. New agents get their bundled image re-uploaded; new squads get their `avatar_url` (emoji or URL) set. An agent whose source avatar was an emoji can't be restored (the CLI has no emoji setter for agents) and is reported as unsupported.
44
46
 
45
47
  ## Step 3 — Report results
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "plugin-validator",
3
3
  "displayName": "Plugin Validator",
4
- "version": "0.0.39",
4
+ "version": "0.0.40",
5
5
  "description": "Orchestrated validator for Claude Code plugins — validates skills, agents, commands, and hooks across every plugin under plugins/**.",
6
6
  "author": {
7
7
  "name": "Steven Hoang"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "team-share",
3
3
  "displayName": "Team Share",
4
- "version": "0.0.39",
4
+ "version": "0.0.40",
5
5
  "description": "Onboard your team with an interactive setup menu: install CodeGraph, build the Understand-Anything knowledge graph, and share Claude Code settings — run any combination, all idempotent.",
6
6
  "author": {
7
7
  "name": "Steven Hoang"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tech-graph",
3
- "version": "0.0.39",
3
+ "version": "0.0.40",
4
4
  "description": "Step-by-step wizard for generating technical diagrams as SVG+PNG.",
5
5
  "author": {
6
6
  "name": "steven"