@drunkcoding/agents-and-skills 0.0.44 → 0.0.46

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.
Files changed (107) hide show
  1. package/.claude-plugin/marketplace.json +2 -47
  2. package/README.md +3 -6
  3. package/package.json +4 -1
  4. package/plugins/multica-tool/.claude-plugin/plugin.json +1 -1
  5. package/plugins/multica-tool/scripts/lib.mjs +53 -4
  6. package/plugins/multica-tool/scripts/multica-export.mjs +170 -50
  7. package/plugins/multica-tool/scripts/multica-import.mjs +209 -27
  8. package/plugins/multica-tool/skills/export/SKILL.md +91 -22
  9. package/plugins/multica-tool/skills/import/SKILL.md +24 -9
  10. package/plugins/multica-tool/skills/sync/SKILL.md +1 -1
  11. package/plugins/plugin-validator/.claude-plugin/plugin.json +1 -1
  12. package/plugins/html-effectiveness/.claude-plugin/plugin.json +0 -17
  13. package/plugins/html-effectiveness/README.md +0 -28
  14. package/plugins/html-effectiveness/agents/report-builder.md +0 -66
  15. package/plugins/html-effectiveness/assets/base.css +0 -51
  16. package/plugins/html-effectiveness/assets/base.js +0 -11
  17. package/plugins/html-effectiveness/assets/charts.js +0 -1
  18. package/plugins/html-effectiveness/assets/components.css +0 -10
  19. package/plugins/html-effectiveness/commands/html-report.md +0 -13
  20. package/plugins/html-effectiveness/docs/template-gallery.md +0 -28
  21. package/plugins/html-effectiveness/package.json +0 -6
  22. package/plugins/html-effectiveness/scripts/_tmp.js +0 -37
  23. package/plugins/html-effectiveness/scripts/catalog.js +0 -47
  24. package/plugins/html-effectiveness/scripts/extract.js +0 -104
  25. package/plugins/html-effectiveness/scripts/mustache.js +0 -90
  26. package/plugins/html-effectiveness/scripts/render.js +0 -176
  27. package/plugins/html-effectiveness/skills/html-effectiveness/SKILL.md +0 -94
  28. package/plugins/html-effectiveness/templates/01-exploration-code-approaches.html.tmpl +0 -400
  29. package/plugins/html-effectiveness/templates/02-exploration-visual-designs.html.tmpl +0 -456
  30. package/plugins/html-effectiveness/templates/03-code-review-pr.html.tmpl +0 -581
  31. package/plugins/html-effectiveness/templates/04-code-understanding.html.tmpl +0 -443
  32. package/plugins/html-effectiveness/templates/05-design-system.html.tmpl +0 -578
  33. package/plugins/html-effectiveness/templates/06-component-variants.html.tmpl +0 -557
  34. package/plugins/html-effectiveness/templates/07-prototype-animation.html.tmpl +0 -417
  35. package/plugins/html-effectiveness/templates/08-prototype-interaction.html.tmpl +0 -363
  36. package/plugins/html-effectiveness/templates/09-slide-deck.html.tmpl +0 -535
  37. package/plugins/html-effectiveness/templates/10-svg-illustrations.html.tmpl +0 -444
  38. package/plugins/html-effectiveness/templates/11-status-report.html.tmpl +0 -152
  39. package/plugins/html-effectiveness/templates/12-incident-report.html.tmpl +0 -547
  40. package/plugins/html-effectiveness/templates/13-flowchart-diagram.html.tmpl +0 -361
  41. package/plugins/html-effectiveness/templates/14-research-feature-explainer.html.tmpl +0 -348
  42. package/plugins/html-effectiveness/templates/15-research-concept-explainer.html.tmpl +0 -334
  43. package/plugins/html-effectiveness/templates/16-implementation-plan.html.tmpl +0 -657
  44. package/plugins/html-effectiveness/templates/17-pr-writeup.html.tmpl +0 -553
  45. package/plugins/html-effectiveness/templates/18-editor-triage-board.html.tmpl +0 -541
  46. package/plugins/html-effectiveness/templates/19-editor-feature-flags.html.tmpl +0 -627
  47. package/plugins/html-effectiveness/templates/20-editor-prompt-tuner.html.tmpl +0 -687
  48. package/plugins/html-effectiveness/templates/manifest.json +0 -441
  49. package/plugins/team-share/.claude-plugin/plugin.json +0 -18
  50. package/plugins/team-share/README.md +0 -46
  51. package/plugins/team-share/agents/team-share.md +0 -53
  52. package/plugins/team-share/commands/team-share.md +0 -4
  53. package/plugins/team-share/skills/claude-config/SKILL.md +0 -143
  54. package/plugins/team-share/skills/codegraph-setup/SKILL.md +0 -81
  55. package/plugins/team-share/skills/understand-setup/SKILL.md +0 -115
  56. package/plugins/tech-graph/.claude-plugin/plugin.json +0 -17
  57. package/plugins/tech-graph/README.md +0 -66
  58. package/plugins/tech-graph/agents/tech-graph.md +0 -97
  59. package/plugins/tech-graph/commands/tech-graph.md +0 -13
  60. package/plugins/tech-graph/scripts/check-deps.sh +0 -55
  61. package/plugins/tech-graph/skills/tech-graph/LICENSE +0 -21
  62. package/plugins/tech-graph/skills/tech-graph/README.md +0 -555
  63. package/plugins/tech-graph/skills/tech-graph/README.zh.md +0 -514
  64. package/plugins/tech-graph/skills/tech-graph/SKILL.md +0 -263
  65. package/plugins/tech-graph/skills/tech-graph/agents/openai.yaml +0 -4
  66. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style1-flat.png +0 -0
  67. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style2-dark.png +0 -0
  68. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style3-blueprint.png +0 -0
  69. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style4-notion.png +0 -0
  70. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style5-glass.png +0 -0
  71. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style6-claude.png +0 -0
  72. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style7-openai.png +0 -0
  73. package/plugins/tech-graph/skills/tech-graph/fixtures/agent-memory-types-style4.json +0 -181
  74. package/plugins/tech-graph/skills/tech-graph/fixtures/api-flow-style7.json +0 -40
  75. package/plugins/tech-graph/skills/tech-graph/fixtures/mem0-style1.json +0 -297
  76. package/plugins/tech-graph/skills/tech-graph/fixtures/microservices-style3.json +0 -64
  77. package/plugins/tech-graph/skills/tech-graph/fixtures/multi-agent-style5.json +0 -45
  78. package/plugins/tech-graph/skills/tech-graph/fixtures/system-architecture-style6.json +0 -48
  79. package/plugins/tech-graph/skills/tech-graph/fixtures/tool-call-style2.json +0 -182
  80. package/plugins/tech-graph/skills/tech-graph/package.json +0 -42
  81. package/plugins/tech-graph/skills/tech-graph/references/diagram-types.md +0 -171
  82. package/plugins/tech-graph/skills/tech-graph/references/icons.md +0 -406
  83. package/plugins/tech-graph/skills/tech-graph/references/style-1-flat-icon.md +0 -108
  84. package/plugins/tech-graph/skills/tech-graph/references/style-2-dark-terminal.md +0 -107
  85. package/plugins/tech-graph/skills/tech-graph/references/style-3-blueprint.md +0 -113
  86. package/plugins/tech-graph/skills/tech-graph/references/style-4-notion-clean.md +0 -95
  87. package/plugins/tech-graph/skills/tech-graph/references/style-5-glassmorphism.md +0 -125
  88. package/plugins/tech-graph/skills/tech-graph/references/style-6-claude-official.md +0 -209
  89. package/plugins/tech-graph/skills/tech-graph/references/style-7-openai.md +0 -215
  90. package/plugins/tech-graph/skills/tech-graph/references/style-diagram-matrix.md +0 -135
  91. package/plugins/tech-graph/skills/tech-graph/references/svg-layout-best-practices.md +0 -100
  92. package/plugins/tech-graph/skills/tech-graph/references/svg-to-png.md +0 -115
  93. package/plugins/tech-graph/skills/tech-graph/scripts/README.md +0 -269
  94. package/plugins/tech-graph/skills/tech-graph/scripts/generate-diagram.sh +0 -181
  95. package/plugins/tech-graph/skills/tech-graph/scripts/generate-from-template.py +0 -1587
  96. package/plugins/tech-graph/skills/tech-graph/scripts/test-all-styles.sh +0 -143
  97. package/plugins/tech-graph/skills/tech-graph/scripts/validate-svg.sh +0 -306
  98. package/plugins/tech-graph/skills/tech-graph/templates/agent-architecture.svg +0 -28
  99. package/plugins/tech-graph/skills/tech-graph/templates/architecture.svg +0 -23
  100. package/plugins/tech-graph/skills/tech-graph/templates/comparison-matrix.svg +0 -14
  101. package/plugins/tech-graph/skills/tech-graph/templates/data-flow.svg +0 -28
  102. package/plugins/tech-graph/skills/tech-graph/templates/er-diagram.svg +0 -21
  103. package/plugins/tech-graph/skills/tech-graph/templates/flowchart.svg +0 -21
  104. package/plugins/tech-graph/skills/tech-graph/templates/sequence.svg +0 -20
  105. package/plugins/tech-graph/skills/tech-graph/templates/state-machine.svg +0 -20
  106. package/plugins/tech-graph/skills/tech-graph/templates/timeline.svg +0 -19
  107. package/plugins/tech-graph/skills/tech-graph/templates/use-case.svg +0 -21
@@ -1,22 +1,35 @@
1
1
  import * as nodeFs from "node:fs";
2
- import { listSkills, listAgents, listAgentsIncludingArchived, listSquads, listRuntimes, listWorkspaceMembers, getSquadMembers, findByName, makeCli, realExec, requireAuth, resolveWorkspaceId, listProjects, getProjectResources, findByTitle, listAutopilots, getAutopilot } from "./lib.mjs";
2
+ import { listSkills, listAgents, listAgentsIncludingArchived, listSquads, listRuntimes, listWorkspaceMembers, getSquadMembers, findByName, makeCli, realExec, requireAuth, resolveWorkspaceId, listProjects, getProjectResources, findByTitle, listAutopilots, getAutopilot, listLabels, listProperties, listWorkspaceMcpServers } from "./lib.mjs";
3
3
 
4
- // User-facing selectable types are agents/squads/projects/autopilots; skills follow agents.
4
+ // User-facing selectable types are agents/squads/projects/autopilots/labels/properties;
5
+ // skills follow agents. Default stays agents,squads — everything else opts in.
5
6
  export function parseInclude(raw) {
6
7
  const set = new Set((raw ? raw.split(",") : ["agents", "squads"]).map((s) => s.trim()).filter(Boolean));
7
8
  if (set.has("agents")) set.add("skills");
8
9
  return set;
9
10
  }
10
11
 
11
- // Instructions live in a sibling .md referenced by `instructions_file` (mirrors
12
- // avatar_file). Legacy bundles carry no instructions_file and keep instructions
13
- // inline in the JSON — fall back to that so older exports still import.
14
- function readInstructions(fs, dir, rec) {
15
- if (rec.instructions_file && fs.existsSync(`${dir}/${rec.instructions_file}`)) {
16
- return fs.readFileSync(`${dir}/${rec.instructions_file}`, "utf8");
12
+ // A prose field (instructions/description) lives in a sibling .md referenced by
13
+ // `<field>_file` (mirrors avatar_file). Legacy bundles carry no `<field>_file`
14
+ // and keep the prose inline in the JSON — fall back to that so older exports
15
+ // still import.
16
+ function readSidecar(fs, dir, rec, fileKey, inlineKey) {
17
+ if (rec[fileKey] && fs.existsSync(`${dir}/${rec[fileKey]}`)) {
18
+ return fs.readFileSync(`${dir}/${rec[fileKey]}`, "utf8");
17
19
  }
18
- return rec.instructions ?? "";
20
+ return rec[inlineKey] ?? "";
19
21
  }
22
+ const readInstructions = (fs, dir, rec) => readSidecar(fs, dir, rec, "instructions_file", "instructions");
23
+
24
+ // Workspace-wide sets (labels, properties, MCP roster) live in their own flat
25
+ // folder, pointed at by `<key>_file` in the manifest. Legacy bundles carried the
26
+ // array inline under `<key>` — fall back to that so older exports still import.
27
+ export function readTaxonomy(fs, dir, manifest, key) {
28
+ const rel = manifest[`${key}_file`];
29
+ if (rel && fs.existsSync(`${dir}/${rel}`)) return JSON.parse(fs.readFileSync(`${dir}/${rel}`, "utf8"));
30
+ return manifest[key] ?? [];
31
+ }
32
+ const readDescription = (fs, dir, rec) => readSidecar(fs, dir, rec, "description_file", "description");
20
33
 
21
34
  // Relative paths of every file under root (recursing into subdirs like scripts/).
22
35
  function walkSkillFiles(fs, root, rel = "") {
@@ -83,9 +96,14 @@ export function importAgents({ cli, manifest, dir, skillIdMap, runtimeMap, fs =
83
96
  const avatarUnsupported = []; // emoji avatar — no CLI setter for agents
84
97
  const permissionApplyFailures = []; // CLI rejected --public-to-member
85
98
  const permissionUnsupported = []; // no member target resolved in the destination
99
+ const mcpServersUnresolved = []; // bundled server name absent from the destination library
100
+ const mcpServersApplyFailures = []; // CLI rejected the enable/disable
86
101
  // Lazy + memoized: destination member user_ids, only listed when an agent needs them.
87
102
  let destMemberIds = null;
88
103
  const getDestMemberIds = () => destMemberIds ??= new Set(listWorkspaceMembers(cli).map((m) => m.user_id));
104
+ // Lazy + memoized: destination MCP library, name -> id.
105
+ let destMcp = null;
106
+ const destMcpServerIds = () => destMcp ??= new Map(listWorkspaceMcpServers(cli).map((m) => [m.name, m.id]));
89
107
  let created = 0, updated = 0, reused = 0;
90
108
  // Includes archived agents so a bundle name matching a retired agent restores
91
109
  // and reuses it instead of failing to create under the held name.
@@ -100,7 +118,8 @@ export function importAgents({ cli, manifest, dir, skillIdMap, runtimeMap, fs =
100
118
  "--visibility", rec.visibility ?? "private",
101
119
  "--max-concurrent-tasks", String(rec.max_concurrent_tasks ?? 6),
102
120
  ];
103
- if (rec.description) common.push("--description", rec.description);
121
+ const description = readDescription(fs, dir, rec);
122
+ if (description) common.push("--description", description);
104
123
  const instructions = readInstructions(fs, dir, rec);
105
124
  if (instructions) common.push("--instructions", instructions);
106
125
  if (rec.model) common.push("--model", rec.model);
@@ -129,6 +148,21 @@ export function importAgents({ cli, manifest, dir, skillIdMap, runtimeMap, fs =
129
148
  const skillIds = (rec.skill_names ?? []).map((n) => skillIdMap.get(n)).filter(Boolean);
130
149
  cli.run(["agent", "skills", "set", id, "--skill-ids", skillIds.join(",")]);
131
150
 
151
+ // Workspace MCP server assignments, resolved by NAME against the destination
152
+ // library (ids are per-workspace). A server the destination doesn't have is
153
+ // reported, not created: `workspace mcp list` never returns the server entry
154
+ // JSON, so the bundle has no config to recreate it from.
155
+ for (const m of rec.mcp_servers ?? []) {
156
+ const serverId = destMcpServerIds().get(m.name);
157
+ if (!serverId) { mcpServersUnresolved.push(`${rec.name}:${m.name}`); continue; }
158
+ try { cli.run(["agent", "mcp", "add", id, serverId]); } catch { /* already assigned */ }
159
+ try {
160
+ cli.run(["agent", "mcp", m.enabled ? "enable" : "disable", id, serverId]);
161
+ } catch {
162
+ mcpServersApplyFailures.push(`${rec.name}:${m.name}`);
163
+ }
164
+ }
165
+
132
166
  // Avatar: only ever set it when the target agent has none — never clobber an
133
167
  // avatar an existing agent already has. Agents accept only image uploads
134
168
  // (`agent avatar --file`); an emoji-only avatar can't be restored via the CLI.
@@ -187,7 +221,7 @@ export function importAgents({ cli, manifest, dir, skillIdMap, runtimeMap, fs =
187
221
  }
188
222
  }
189
223
  }
190
- return { idMap, sourceIdMap, created, updated, reused, secretsApplyFailures, avatarApplyFailures, avatarUnsupported, permissionApplyFailures, permissionUnsupported };
224
+ return { idMap, sourceIdMap, created, updated, reused, secretsApplyFailures, avatarApplyFailures, avatarUnsupported, permissionApplyFailures, permissionUnsupported, mcpServersUnresolved, mcpServersApplyFailures };
191
225
  }
192
226
 
193
227
  // Rewrites `mention://agent/<id>` links (e.g. `[@dev-backend](mention://agent/<id>)`)
@@ -269,7 +303,8 @@ export function importProjects({ cli, manifest, dir, agentIdMap, fs = nodeFs })
269
303
  for (const entry of manifest.projects ?? []) {
270
304
  const rec = JSON.parse(fs.readFileSync(`${dir}/${entry.file}`, "utf8"));
271
305
  const flags = ["--title", rec.title];
272
- if (rec.description) flags.push("--description", rec.description);
306
+ const description = readDescription(fs, dir, rec);
307
+ if (description) flags.push("--description", description);
273
308
  if (rec.icon) flags.push("--icon", rec.icon);
274
309
  if (rec.status) flags.push("--status", rec.status);
275
310
  if (rec.due_date) flags.push("--due-date", rec.due_date);
@@ -339,6 +374,9 @@ export function importAutopilots({ cli, manifest, dir, agentIdMap, fs = nodeFs }
339
374
  const idMap = new Map();
340
375
  let created = 0, updated = 0;
341
376
  const projectUnresolved = [], subscribersUnresolved = [], priorityNotCaptured = [], webhookReissued = [];
377
+ // Every import lands paused; these were live at the source and need a
378
+ // deliberate `autopilot update <id> --status active` at the destination.
379
+ const activeAtSource = recs.filter((r) => r.status === "active").map((r) => r.title);
342
380
  const existing = listAutopilots(cli);
343
381
  let destProjects = null;
344
382
  const resolveProjectId = (title) => (destProjects ??= listProjects(cli)).find((p) => p.title === title)?.id ?? null;
@@ -347,12 +385,14 @@ export function importAutopilots({ cli, manifest, dir, agentIdMap, fs = nodeFs }
347
385
 
348
386
  for (const rec of recs) {
349
387
  const common = [];
350
- if (rec.description) common.push("--description", rec.description);
388
+ const description = readDescription(fs, dir, rec);
389
+ if (description) common.push("--description", description);
351
390
  if (rec.issue_title_template) common.push("--issue-title-template", rec.issue_title_template);
352
- // priority is never present today — the multica CLI/API accepts it on write but
353
- // never returns it on read, so export can't capture the source's real value.
354
- if (rec.priority && rec.priority !== "none") common.push("--priority", rec.priority);
355
- else priorityNotCaptured.push(rec.title);
391
+ // Priority never round-trips: the API omits it on read, and as of multica
392
+ // 0.4.36 `autopilot create`/`update` reject `--priority` outright ("unknown
393
+ // flag"). Passing a legacy bundle's value through would abort the import, so
394
+ // it is always reported instead of applied.
395
+ priorityNotCaptured.push(rec.title);
356
396
 
357
397
  if (rec.project_title) {
358
398
  const projectId = resolveProjectId(rec.project_title);
@@ -397,7 +437,82 @@ export function importAutopilots({ cli, manifest, dir, agentIdMap, fs = nodeFs }
397
437
  if (t.kind === "webhook") webhookReissued.push(rec.title);
398
438
  }
399
439
  }
400
- return { idMap, created, updated, projectUnresolved, subscribersUnresolved, priorityNotCaptured, webhookReissued };
440
+ return { idMap, created, updated, projectUnresolved, subscribersUnresolved, priorityNotCaptured, webhookReissued, activeAtSource };
441
+ }
442
+
443
+ // Workspace issue labels, matched by name. Colour is the only field the CLI can
444
+ // set besides the name — a label's description has no `--description` flag on
445
+ // `label create`/`update` (multica 0.4.36), so it is reported, never applied.
446
+ export function importLabels({ cli, manifest, dir, fs = nodeFs }) {
447
+ const entries = readTaxonomy(fs, dir, manifest, "labels");
448
+ if (!entries.length) return { created: 0, updated: 0, descriptionUnsupported: [] };
449
+ const existing = listLabels(cli);
450
+ let created = 0, updated = 0;
451
+ const descriptionUnsupported = [];
452
+ for (const l of entries) {
453
+ const match = findByName(existing, l.name);
454
+ if (match) {
455
+ cli.run(["label", "update", match.id, "--color", l.color]);
456
+ updated++;
457
+ } else {
458
+ cli.run(["label", "create", "--name", l.name, "--color", l.color]);
459
+ created++;
460
+ }
461
+ // Only worth reporting when the destination doesn't already carry the same text.
462
+ if (l.description && match?.description !== l.description) descriptionUnsupported.push(l.name);
463
+ }
464
+ return { created, updated, descriptionUnsupported };
465
+ }
466
+
467
+ // Workspace custom issue property definitions, matched by name — the same key
468
+ // issue values reference, and the key `property update` uses to re-match existing
469
+ // options so their ids (and any values already set on issues) survive.
470
+ //
471
+ // A property's type is immutable: a name collision with a different type is
472
+ // skipped and reported rather than forced, since re-creating it would orphan
473
+ // every value already stored under that name at the destination.
474
+ export function importProperties({ cli, manifest, dir, fs = nodeFs }) {
475
+ const entries = readTaxonomy(fs, dir, manifest, "properties");
476
+ if (!entries.length) return { created: 0, updated: 0, typeConflicts: [], archivedApplied: [] };
477
+ const existing = listProperties(cli);
478
+ let created = 0, updated = 0;
479
+ const typeConflicts = [], archivedApplied = [];
480
+ for (const p of entries) {
481
+ const match = findByName(existing, p.name);
482
+ if (match && match.type !== p.type) {
483
+ typeConflicts.push(`${p.name} (destination is "${match.type}", bundle is "${p.type}" — type is immutable)`);
484
+ continue;
485
+ }
486
+ // Unarchive first so the update below always lands on an active definition;
487
+ // the desired archived state is re-applied at the end of the loop body.
488
+ if (match?.archived) cli.run(["property", "unarchive", p.name]);
489
+
490
+ const flags = [];
491
+ if (p.description) flags.push("--description", p.description);
492
+ if (p.icon) flags.push("--icon", p.icon);
493
+ // `--option` is select/multi_select only; every other type exports none.
494
+ for (const o of p.options ?? []) flags.push("--option", o.color ? `${o.name}:${o.color}` : o.name);
495
+
496
+ if (match) {
497
+ cli.run(["property", "update", p.name, ...flags]);
498
+ updated++;
499
+ } else {
500
+ cli.run(["property", "create", "--name", p.name, "--type", p.type, ...flags]);
501
+ created++;
502
+ }
503
+ if (p.archived) { cli.run(["property", "archive", p.name]); archivedApplied.push(p.name); }
504
+ }
505
+ return { created, updated, typeConflicts, archivedApplied };
506
+ }
507
+
508
+ // Workspace MCP servers named in the bundle that the destination library lacks.
509
+ // Only name + transport ever travel (see listWorkspaceMcpServers), so these are
510
+ // reported for manual re-entry — never created.
511
+ export function mcpServerGap({ cli, manifest, dir, fs = nodeFs }) {
512
+ const wanted = readTaxonomy(fs, dir, manifest, "mcp_servers");
513
+ if (!wanted.length) return [];
514
+ const have = new Set(listWorkspaceMcpServers(cli).map((m) => m.name));
515
+ return wanted.filter((m) => !have.has(m.name)).map((m) => m.name);
401
516
  }
402
517
 
403
518
  export function collectSourceRuntimes(manifest) {
@@ -457,7 +572,7 @@ export function importBundle({ cli, dir, runtimeMap, include, fs = nodeFs }) {
457
572
  : { idMap: new Map(), created: 0, updated: 0 };
458
573
  const agentRes = inc.has("agents")
459
574
  ? importAgents({ cli, manifest, dir, skillIdMap: skillRes.idMap, runtimeMap: effective, fs })
460
- : { idMap: new Map(), sourceIdMap: new Map(), created: 0, updated: 0, reused: 0, secretsApplyFailures: [], avatarApplyFailures: [], avatarUnsupported: [], permissionApplyFailures: [], permissionUnsupported: [] };
575
+ : { idMap: new Map(), sourceIdMap: new Map(), created: 0, updated: 0, reused: 0, secretsApplyFailures: [], avatarApplyFailures: [], avatarUnsupported: [], permissionApplyFailures: [], permissionUnsupported: [], mcpServersUnresolved: [], mcpServersApplyFailures: [] };
461
576
  // Runs after every agent exists so forward-referencing mentions resolve.
462
577
  const mentionRes = inc.has("agents")
463
578
  ? rewriteAgentMentions({ cli, manifest, dir, agentIdMap: agentRes.idMap, sourceIdMap: agentRes.sourceIdMap, fs })
@@ -469,6 +584,7 @@ export function importBundle({ cli, dir, runtimeMap, include, fs = nodeFs }) {
469
584
  if (inc.has("squads")) {
470
585
  for (const squad of manifest.squads ?? []) {
471
586
  squad.instructions = readInstructions(fs, dir, squad);
587
+ squad.description = readDescription(fs, dir, squad);
472
588
  const r = importSquad({ cli, squad, agentIdMap: agentRes.idMap, sourceIdMap: agentRes.sourceIdMap });
473
589
  if (r.skipped) { squadsSkipped.push(squad.name); continue; }
474
590
  squadIdMap.set(squad.name, r.newId);
@@ -482,15 +598,22 @@ export function importBundle({ cli, dir, runtimeMap, include, fs = nodeFs }) {
482
598
  projectRes = importProjects({ cli, manifest, dir, agentIdMap: agentRes.idMap, fs });
483
599
  }
484
600
 
485
- let autopilotRes = { idMap: new Map(), created: 0, updated: 0, projectUnresolved: [], subscribersUnresolved: [], priorityNotCaptured: [], webhookReissued: [] };
601
+ let autopilotRes = { idMap: new Map(), created: 0, updated: 0, projectUnresolved: [], subscribersUnresolved: [], priorityNotCaptured: [], webhookReissued: [], activeAtSource: [] };
486
602
  if (inc.has("autopilots")) {
487
603
  autopilotRes = importAutopilots({ cli, manifest, dir, agentIdMap: agentRes.idMap, fs });
488
604
  }
489
605
 
606
+ const labelRes = inc.has("labels")
607
+ ? importLabels({ cli, manifest, dir, fs })
608
+ : { created: 0, updated: 0, descriptionUnsupported: [] };
609
+ const propertyRes = inc.has("properties")
610
+ ? importProperties({ cli, manifest, dir, fs })
611
+ : { created: 0, updated: 0, typeConflicts: [], archivedApplied: [] };
612
+
490
613
  return {
491
614
  include: [...inc],
492
- created: { skills: skillRes.created, agents: agentRes.created, squads: squadsCreated, projects: projectRes.created, autopilots: autopilotRes.created },
493
- updated: { skills: skillRes.updated, agents: agentRes.updated, squads: squadsUpdated, projects: projectRes.updated, autopilots: autopilotRes.updated },
615
+ created: { skills: skillRes.created, agents: agentRes.created, squads: squadsCreated, projects: projectRes.created, autopilots: autopilotRes.created, labels: labelRes.created, properties: propertyRes.created },
616
+ updated: { skills: skillRes.updated, agents: agentRes.updated, squads: squadsUpdated, projects: projectRes.updated, autopilots: autopilotRes.updated, labels: labelRes.updated, properties: propertyRes.updated },
494
617
  // Agents restored from archived + updated to the bundle's definition — distinct
495
618
  // from a plain update (an active-name match). Only agents can be reused today.
496
619
  reused: { agents: agentRes.reused },
@@ -506,6 +629,13 @@ export function importBundle({ cli, dir, runtimeMap, include, fs = nodeFs }) {
506
629
  avatarUnsupported: agentRes.avatarUnsupported,
507
630
  permissionApplyFailures: agentRes.permissionApplyFailures,
508
631
  permissionUnsupported: agentRes.permissionUnsupported,
632
+ mcpServersUnresolved: agentRes.mcpServersUnresolved,
633
+ mcpServersApplyFailures: agentRes.mcpServersApplyFailures,
634
+ // Bundled workspace MCP servers missing at the destination. The CLI never
635
+ // exposes a server's entry JSON on read, so each must be re-added by hand
636
+ // (`multica workspace mcp add <name> --server-config ...`) before its agent
637
+ // assignments can land.
638
+ mcpServersNotCreatable: mcpServerGap({ cli, manifest, dir, fs }),
509
639
  squadsSkipped,
510
640
  priorityUnsupported: projectRes.priorityUnsupported,
511
641
  resourcesUnsupported: projectRes.resourcesUnsupported,
@@ -514,6 +644,10 @@ export function importBundle({ cli, dir, runtimeMap, include, fs = nodeFs }) {
514
644
  autopilotSubscribersUnresolved: autopilotRes.subscribersUnresolved,
515
645
  autopilotPriorityNotCaptured: autopilotRes.priorityNotCaptured,
516
646
  autopilotWebhookReissued: autopilotRes.webhookReissued,
647
+ autopilotsActiveAtSource: autopilotRes.activeAtSource,
648
+ labelDescriptionUnsupported: labelRes.descriptionUnsupported,
649
+ propertyTypeConflicts: propertyRes.typeConflicts,
650
+ propertiesArchived: propertyRes.archivedApplied,
517
651
  };
518
652
  }
519
653
 
@@ -521,13 +655,20 @@ export function preflight({ cli, dir, runtimeMap, include, fs = nodeFs }) {
521
655
  const inc = include ?? new Set(["skills", "agents", "squads"]);
522
656
  const manifest = JSON.parse(fs.readFileSync(`${dir}/manifest.json`, "utf8"));
523
657
  const count = (k) => (manifest[k] ?? []).length;
524
- const bundle = { skills: count("skills"), agents: count("agents"), squads: count("squads"), projects: count("projects"), autopilots: count("autopilots") };
658
+ // labels/properties/mcp live in their own folder; read through the manifest
659
+ // pointer (with the legacy inline fallback) rather than counting a key that
660
+ // current bundles no longer carry.
661
+ const bundleLabels = readTaxonomy(fs, dir, manifest, "labels");
662
+ const bundleProperties = readTaxonomy(fs, dir, manifest, "properties");
663
+ const bundle = { skills: count("skills"), agents: count("agents"), squads: count("squads"), projects: count("projects"), autopilots: count("autopilots"), labels: bundleLabels.length, properties: bundleProperties.length };
525
664
  const willImport = {
526
665
  skills: inc.has("skills") ? bundle.skills : 0,
527
666
  agents: inc.has("agents") ? bundle.agents : 0,
528
667
  squads: inc.has("squads") ? bundle.squads : 0,
529
668
  projects: inc.has("projects") ? bundle.projects : 0,
530
669
  autopilots: inc.has("autopilots") ? bundle.autopilots : 0,
670
+ labels: inc.has("labels") ? bundle.labels : 0,
671
+ properties: inc.has("properties") ? bundle.properties : 0,
531
672
  };
532
673
 
533
674
  const incompatibilities = [];
@@ -589,15 +730,56 @@ export function preflight({ cli, dir, runtimeMap, include, fs = nodeFs }) {
589
730
  } else if (!agentAvailable(rec.assignee_name)) {
590
731
  incompatibilities.push({ type: "autopilot-assignee-missing", detail: `${rec.title} → agent "${rec.assignee_name}" (ensure this agent exists in the destination or is included in this import)` });
591
732
  }
592
- if (!rec.priority) {
593
- incompatibilities.push({ type: "autopilot-priority-not-captured", detail: `${rec.title} (the multica CLI/API never returns an autopilot's priority, so export could not capture it)` });
594
- }
733
+ incompatibilities.push({ type: "autopilot-priority-not-captured", detail: `${rec.title} (the multica CLI/API never returns an autopilot's priority on read, and multica 0.4.36 dropped --priority from autopilot create/update — it can be neither captured nor restored)` });
595
734
  if (rec.project_title && !projectAvailable(rec.project_title)) {
596
735
  incompatibilities.push({ type: "autopilot-project-missing", detail: `${rec.title} → project "${rec.project_title}" (not found in the destination)` });
597
736
  }
598
737
  if (rec.had_webhook_trigger) {
599
738
  incompatibilities.push({ type: "autopilot-webhook-reissued", detail: `${rec.title} (webhook trigger will get a newly issued URL — the old one never travels)` });
600
739
  }
740
+ if (rec.status === "active") {
741
+ incompatibilities.push({ type: "autopilot-arrives-paused", detail: `${rec.title} (active at the source; every imported autopilot lands paused — activate it deliberately at the destination)` });
742
+ }
743
+ }
744
+ }
745
+
746
+ // MCP: the workspace library can never be recreated from a bundle (no CLI read
747
+ // of a server's entry JSON), so a missing server blocks its agent assignments.
748
+ if (inc.has("agents")) {
749
+ for (const name of mcpServerGap({ cli, manifest, dir, fs })) {
750
+ incompatibilities.push({ type: "mcp-server-not-creatable", detail: `${name} (in the bundle's workspace MCP roster but absent at the destination; \`workspace mcp list\` never returns a server's config, so re-add it with \`multica workspace mcp add ${name} --server-config ...\`)` });
751
+ }
752
+ let destMcpNames = null;
753
+ const mcpAvailable = (n) => (destMcpNames ??= new Set(listWorkspaceMcpServers(cli).map((m) => m.name))).has(n);
754
+ for (const a of manifest.agents ?? []) {
755
+ const rec = JSON.parse(fs.readFileSync(`${dir}/${a.file}`, "utf8"));
756
+ for (const m of rec.mcp_servers ?? []) {
757
+ if (!mcpAvailable(m.name)) {
758
+ incompatibilities.push({ type: "agent-mcp-server-missing", detail: `${rec.name} → MCP server "${m.name}" (not in the destination workspace library — the assignment will be skipped)` });
759
+ }
760
+ }
761
+ }
762
+ }
763
+
764
+ if (inc.has("labels")) {
765
+ for (const l of bundleLabels) {
766
+ if (l.description) {
767
+ incompatibilities.push({ type: "label-description-not-settable", detail: `${l.name} (the multica CLI exposes no --description flag on label create/update)` });
768
+ }
769
+ }
770
+ }
771
+
772
+ if (inc.has("properties")) {
773
+ // Read-only mirror of importProperties' immutable-type skip.
774
+ const existingProps = bundleProperties.length ? listProperties(cli) : [];
775
+ for (const prop of bundleProperties) {
776
+ const match = findByName(existingProps, prop.name);
777
+ if (match && match.type !== prop.type) {
778
+ incompatibilities.push({ type: "property-type-conflict", detail: `${prop.name} (destination is "${match.type}", bundle is "${prop.type}" — type is immutable, this property will be skipped)` });
779
+ }
780
+ if (prop.archived) {
781
+ incompatibilities.push({ type: "property-archived", detail: `${prop.name} (archived at the source — imported, then archived at the destination too)` });
782
+ }
601
783
  }
602
784
  }
603
785
 
@@ -628,7 +810,7 @@ function main() {
628
810
  const dryRun = args.includes("--dry-run");
629
811
 
630
812
  if (!dir || !workspace) {
631
- console.error("Usage: multica-import.mjs --dir <folder> --workspace <name> [--runtime-map <src=dst,...>] [--include <csv>] [--dry-run]");
813
+ console.error("Usage: multica-import.mjs --dir <folder> --workspace <name> [--runtime-map <src=dst,...>] [--include agents,squads,projects,autopilots,labels,properties] [--dry-run]");
632
814
  process.exit(1);
633
815
  }
634
816
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: export
3
- description: Use when the user wants to export Multica skills, agents, or squads to a local folder for backup, version control, or cross-workspace migration.
3
+ description: Use when the user wants to export Multica skills, agents, squads, projects, or autopilots to a local folder for backup, version control, or cross-workspace migration. Supports whole-workspace exports by level (skill, agent, squad, project) or a single named resource.
4
4
  allowed-tools: Bash, Read
5
5
  ---
6
6
 
@@ -18,11 +18,31 @@ multica auth status 2>&1 || true
18
18
 
19
19
  If `multica login` is required, surface that message verbatim and stop.
20
20
 
21
- ## Step 2 — Determine scope and resource ID
21
+ ## Step 2 — Pick a level, or a single resource
22
22
 
23
- If the user named a specific resource and type (`skill`, `agent`, `squad`, `project`, or `autopilot`), use those directly.
23
+ There are two ways to export, and they are mutually exclusive:
24
24
 
25
- Otherwise, list available resources for the chosen type and present a pick list:
25
+ - **Whole workspace, by level** (`--level`) the default shape. A level bundles its own tier plus every tier below it. Use this whenever the user asks for a workspace, a backup, or a migration.
26
+ - **One named resource** (`--scope <type> --id <id>`) — for a single skill, agent, squad, project, or autopilot.
27
+
28
+ ### Levels
29
+
30
+ Lowest tier first; **the default level is `squad`**.
31
+
32
+ | `--level` | Object folders written |
33
+ |---|---|
34
+ | `skill` | `skills/` |
35
+ | `agent` | `skills/`, `agents/` |
36
+ | `squad` *(default)* | `skills/`, `agents/`, `squads/` |
37
+ | `project` | `skills/`, `agents/`, `squads/`, `projects/`, `autopilots/`, `labels/`, `properties/`, `mcp/` |
38
+
39
+ Notes on the tiers:
40
+
41
+ - **Project** carries portable project metadata (title, description, icon, priority, status, dates, lead mapping) plus its attached resource records — **never issues, never members**. Workspace issue **labels**, custom **properties**, and the workspace **MCP server roster** ride along at this level.
42
+ - **Autopilots** are bundled **only** at `--level project`. Every other level omits them.
43
+ - `--level skill` keeps every workspace skill, including ones no agent references. Every higher level prunes those orphans, since the agents are what reference them.
44
+
45
+ If the user asked for a single resource but did not name it, list the type and present a pick list:
26
46
 
27
47
  ```bash
28
48
  multica <type> list --output json
@@ -37,51 +57,100 @@ If the user specified an output directory, use it verbatim. Otherwise default to
37
57
  First resolve `<workspace-name>`:
38
58
 
39
59
  - If the user named a source workspace (the value you would pass as `--workspace <name>`), use that name.
40
- - Otherwise, read the current default workspace's name:
41
-
42
- ```bash
43
- multica workspace get --output json
44
- ```
45
-
46
- and take its `.name`.
60
+ - Otherwise, run `multica workspace get --output json` and take its `.name` (the current default workspace).
47
61
 
48
62
  Slugify the resolved name for filesystem safety — lowercase it, replace each run of non-`[a-z0-9]` characters with a single `-`, and trim leading/trailing `-` (the same rule the scripts use internally).
49
63
 
50
- Then construct the default directory by scope:
64
+ Then construct the default directory:
51
65
 
52
- - `all` or `projects` (whole workspace) → `export/<workspace-name>`
53
- - a single resource (`skill`, `agent`, `squad`, `project`, or `autopilot`) → `export/<workspace-name>/<slug>-<type>`, where `<slug>` is the slugified resource name and `<type>` is the resource type.
66
+ - a whole-workspace export (`--level`) → `export/<workspace-name>`
67
+ - a single resource (`--scope <type> --id`) → `export/<workspace-name>/<slug>-<type>`, where `<slug>` is the slugified resource name and `<type>` is the resource type.
54
68
 
55
- Examples: `export all from mx-workspace` → `export/mx-workspace`; `export skill "Foo Bar" from mx-workspace` → `export/mx-workspace/foo-bar-skill`.
69
+ Examples: `export everything from mx-workspace` → `export/mx-workspace`; `export skill "Foo Bar" from mx-workspace` → `export/mx-workspace/foo-bar-skill`.
56
70
 
57
71
  ## Step 4 — Run the export
58
72
 
73
+ Whole workspace, by level (the default path — `--level` defaults to `squad`):
74
+
75
+ ```bash
76
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/multica-export.mjs" \
77
+ --out <dir> \
78
+ [--level skill|agent|squad|project] \
79
+ [--workspace <workspace-name>]
80
+ ```
81
+
82
+ One named resource:
83
+
59
84
  ```bash
60
85
  node "${CLAUDE_PLUGIN_ROOT}/scripts/multica-export.mjs" \
61
- --scope <skill|agent|squad|project|projects|autopilot|all> \
86
+ --scope <skill|agent|squad|project|autopilot> \
62
87
  --id <id> \
63
88
  --out <dir> \
64
89
  [--workspace <workspace-name>]
65
90
  ```
66
91
 
67
- `--id` is required for `skill`, `agent`, `squad`, `project`, and `autopilot` (a single named resource); it is **not needed** for `projects` (every project in the workspace) or `all` (the entire workspace). `all` does **not** include autopilots — an autopilot is always exported explicitly, by name, never auto-bundled.
92
+ `--scope` and `--level` are mutually exclusive; the script exits 1 if both are passed. `--id` is required with `--scope`.
93
+
94
+ A workspace export is one flat, deduped bundle: a skill, agent, or squad reached from several places is written exactly once and referenced by name.
95
+
96
+ Every export that reaches a resource with a dependency **bundles that dependency** so the bundle is self-contained — a squad's leader and members, a project's lead agent, an autopilot's assignee agent or squad, and every skill those agents use. On import, only `github_repo` project resources are portable and recreated; other resource types are reported and skipped.
97
+
98
+ ### Folder layout
99
+
100
+ One flat folder per object type:
101
+
102
+ ```
103
+ <dir>/
104
+ manifest.json
105
+ skills/<slug>/SKILL.md, config.json, <skill files…>
106
+ agents/<slug>.json, <slug>.md, <slug>.description.md, <slug>.avatar.<ext>
107
+ squads/<slug>.json, <slug>.md, <slug>.description.md
108
+ projects/<slug>.json, <slug>.description.md
109
+ autopilots/<slug>.json, <slug>.description.md
110
+ labels/labels.json
111
+ properties/properties.json
112
+ mcp/servers.json
113
+ ```
114
+
115
+ `manifest.json` points at `labels/`, `properties/` and `mcp/` via `labels_file`, `properties_file` and `mcp_servers_file` (with a matching `*_count`); the arrays themselves are no longer inline. Import still reads a pre-folder bundle that carried them inline.
116
+
117
+ ### Issue labels, custom properties, and the MCP roster
118
+
119
+ `--scope project` and `--level project` also bundle the workspace's **issue labels**, **custom issue property definitions**, and the **workspace MCP server roster**, so a migrated project lands somewhere its issues can actually be labelled and filled in. All three are **workspace-scoped in Multica — there is no project-scoped label, property, or MCP server** — so what travels is the whole workspace's taxonomy, not a per-project subset. State that plainly to the user when they ask for "the project's labels".
120
+
121
+ Narrower selections (`skill`, `agent`, `squad`, `autopilot` scopes; `skill`/`agent`/`squad` levels) bundle none of the three — a single resource is not a workspace migration.
122
+
123
+ What travels, and what cannot:
124
+
125
+ - **Labels** — `name` and `color`. A label's `description` is captured in the bundle for review but **cannot be restored**: `label create`/`label update` expose no `--description` flag. Every affected label is listed in `labelDescriptionsNotPortable`.
126
+ - **Properties** — `name`, `type`, `description`, `icon`, `archived`, and each select option's `name` + `color`. Server-assigned `position` and `usage_count` are not bundled (no CLI setter). Option **ids** are deliberately dropped: `property update` re-matches options by name at the destination, which is also how issue values reference them.
127
+ - Archived property definitions **are** included (`property list --include-archived`), so a retired definition arrives retired instead of reappearing in every picker.
128
+ - **MCP servers** — `name` and `transport` only. A server's entry JSON (command/args/env, and any token inside it) is **write-only in the CLI**: `workspace mcp add`/`update` accept it, and nothing reads it back. So `mcp/servers.json` is a roster, not a copy — every entry is listed in `mcpServerConfigsNotPortable`, and each must be re-added by hand at the destination before agent assignments can attach to it.
129
+
130
+ Every agent record also carries `mcp_servers` — which workspace MCP servers that agent uses, as `{name, enabled}`. This is separate from the agent's own inline `mcp_config`. Import re-links them by name against the destination library.
68
131
 
69
- Pass `--scope all` (with no `--id`) to export the **entire workspace** every skill, agent, squad, and project into one flat, deduped bundle. A skill or agent shared across many agents/squads is written exactly once and referenced by name.
132
+ The script writes `manifest.json`, skill `SKILL.md` files, agent JSON files, and squad JSON files into `<dir>`. Every resource's prose fields are externalized to sibling Markdown files, never embedded in the JSON so they are easy to read, diff, and edit:
70
133
 
71
- Exporting a project (or `projects`/`all`) also **bundles the project's lead agent** so the bundle is self-contained; projects carry metadata only (title, description, icon, priority, status, dates, lead mapping) plus their attached resource records — never issues. On import, only `github_repo` resources are portable and recreated; other resource types are reported and skipped.
134
+ - **instructions** (system prompt / charter, agents and squads) `<slug>.md`, referenced by an `instructions_file` key.
135
+ - **description** (agents, squads, projects, autopilots) → `<slug>.description.md`, referenced by a `description_file` key.
72
136
 
73
- 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`.
137
+ An empty field gets no file and no `*_file` key. Skills keep their own layout the description lives in `SKILL.md` frontmatter and the body is the content.
74
138
 
75
139
  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.
76
140
 
77
- Exporting `--scope autopilot` bundles the autopilot's **assignee** so the bundle is self-contained an agent assignee (and its skills), or a squad assignee (its members, their skills, and the squad itself). It also captures the schedule and webhook triggers, the target project's **title** (not its ID — resolved by name on import) when one is set, and human subscribers' **names** (not their IDs). A webhook trigger's secret (URL/token) is **never** written to the bundle — only that it exists (its label); a fresh secret is issued on import.
141
+ Exporting `--scope autopilot` bundles the autopilot configuration **and its assignee** (an agent, or a squad with its members and their skills), so the bundle imports on its own. The assignee is linked by name (`assignee_type` + `assignee_name`); import resolves that name against the bundle first, then the destination workspace. An autopilot's `status` is captured, but **every imported autopilot lands paused** regardless — the ones that were live at the source are listed in `autopilotsActiveAtSource` so they can be re-activated deliberately. The bundle also captures the schedule and webhook triggers, the target project's **title** (not its ID — resolved by name on import) when one is set, and human subscribers' **names** (not their IDs). A webhook trigger's secret (URL/token) is **never** written to the bundle — only that it exists (its label); a fresh secret is issued on import.
78
142
 
79
143
  ## Step 5 — Report results
80
144
 
81
145
  Parse the JSON output from the script and report:
82
146
 
83
147
  - Directory written to.
84
- - Count of skills, agents, squads, and projects exported.
148
+ - The level (or the single resource) exported.
149
+ - Count of skills, agents, squads, projects, and autopilots exported.
85
150
  - If `pruned_skills` is non-empty, note it: "Pruned N orphan skill(s) not linked to any agent: `<name>`, …" (these are standalone workspace skills that no exported agent references — only `--scope all` produces them).
86
151
  - If `warnings` is non-empty, surface every agent name verbatim with this message: "WARNING: the following agents' exported files contain custom environment variables or MCP config in PLAINTEXT — treat the export directory as sensitive (avoid committing it to a public repo, restrict file permissions, delete it once the import is done): `<agent-name>`."
87
152
  - If `autopilotWebhookTriggers` is non-empty, surface every autopilot title verbatim with: "NOTE: the following autopilots have a webhook trigger — its secret was NOT exported; a newly issued URL will be created on import: `<autopilot-title>`."
153
+ - Count of labels and custom properties bundled (`manifest.labels.length`, `manifest.properties.length`), noting that both are workspace-wide, not project-specific.
154
+ - If `autopilotsActiveAtSource` is non-empty, surface every title verbatim with: "NOTE: the following autopilots were ACTIVE at the source; every imported autopilot lands paused — re-activate each one deliberately with `multica autopilot update <id> --status active`: `<autopilot-title>`."
155
+ - If `mcpServerConfigsNotPortable` is non-empty, surface every server name verbatim with: "NOTE: the following workspace MCP servers travelled by name and transport only — the CLI never returns a server's config on read, so re-add each one at the destination (`multica workspace mcp add <name> --server-config ...`) before importing the agents that use it: `<server-name>`."
156
+ - If `labelDescriptionsNotPortable` is non-empty, surface every label name verbatim with: "NOTE: the following labels have a description that the multica CLI cannot set on import (`label create`/`update` have no `--description` flag) — re-enter it in the Multica UI at the destination: `<label-name>`."