buildanything 2.0.0 → 2.1.2

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 (115) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +9 -1
  3. package/README.md +57 -61
  4. package/agents/a11y-architect.md +2 -0
  5. package/agents/briefing-officer.md +172 -0
  6. package/agents/business-model.md +14 -12
  7. package/agents/code-architect.md +6 -1
  8. package/agents/code-reviewer.md +3 -2
  9. package/agents/code-simplifier.md +12 -4
  10. package/agents/design-brand-guardian.md +19 -0
  11. package/agents/design-critic.md +16 -11
  12. package/agents/design-inclusive-visuals-specialist.md +2 -0
  13. package/agents/design-ui-designer.md +17 -0
  14. package/agents/design-ux-architect.md +15 -0
  15. package/agents/design-ux-researcher.md +102 -7
  16. package/agents/engineering-ai-engineer.md +2 -0
  17. package/agents/engineering-backend-architect.md +2 -0
  18. package/agents/engineering-data-engineer.md +2 -0
  19. package/agents/engineering-devops-automator.md +2 -0
  20. package/agents/engineering-frontend-developer.md +13 -0
  21. package/agents/engineering-mobile-app-builder.md +2 -0
  22. package/agents/engineering-rapid-prototyper.md +15 -2
  23. package/agents/engineering-security-engineer.md +2 -0
  24. package/agents/engineering-senior-developer.md +13 -0
  25. package/agents/engineering-sre.md +2 -0
  26. package/agents/engineering-technical-writer.md +2 -0
  27. package/agents/feature-intel.md +8 -7
  28. package/agents/ios-app-review-guardian.md +2 -0
  29. package/agents/ios-foundation-models-specialist.md +2 -0
  30. package/agents/ios-product-reality-auditor.md +292 -0
  31. package/agents/ios-storekit-specialist.md +2 -0
  32. package/agents/ios-swift-architect.md +1 -0
  33. package/agents/ios-swift-search.md +1 -0
  34. package/agents/ios-swift-ui-design.md +7 -4
  35. package/agents/marketing-app-store-optimizer.md +2 -0
  36. package/agents/planner.md +6 -1
  37. package/agents/pr-test-analyzer.md +3 -2
  38. package/agents/product-feedback-synthesizer.md +62 -0
  39. package/agents/product-owner.md +163 -0
  40. package/agents/product-reality-auditor.md +216 -0
  41. package/agents/product-spec-writer.md +176 -0
  42. package/agents/refactor-cleaner.md +9 -1
  43. package/agents/security-reviewer.md +2 -1
  44. package/agents/silent-failure-hunter.md +2 -1
  45. package/agents/swift-build-resolver.md +2 -0
  46. package/agents/swift-reviewer.md +2 -1
  47. package/agents/tech-feasibility.md +5 -3
  48. package/agents/testing-api-tester.md +2 -0
  49. package/agents/testing-evidence-collector.md +24 -0
  50. package/agents/testing-performance-benchmarker.md +2 -0
  51. package/agents/testing-reality-checker.md +2 -1
  52. package/agents/visual-research.md +7 -5
  53. package/bin/adapters/scribe-tool.ts +4 -2
  54. package/bin/adapters/write-lease-tool.ts +1 -1
  55. package/bin/buildanything-runtime.ts +20 -107
  56. package/bin/graph-index.js +24 -0
  57. package/bin/graph-index.ts +340 -0
  58. package/bin/mcp-servers/graph-mcp.js +26 -0
  59. package/bin/mcp-servers/graph-mcp.ts +481 -0
  60. package/bin/mcp-servers/orchestrator-mcp.js +26 -0
  61. package/bin/mcp-servers/orchestrator-mcp.ts +361 -0
  62. package/bin/setup.js +272 -111
  63. package/commands/build.md +424 -177
  64. package/commands/idea-sweep.md +2 -2
  65. package/commands/setup.md +15 -4
  66. package/commands/ux-review.md +3 -3
  67. package/commands/verify.md +3 -0
  68. package/docs/migration/phase-graph.yaml +573 -157
  69. package/hooks/design-md-lint +4 -0
  70. package/hooks/design-md-lint.ts +295 -0
  71. package/hooks/pre-tool-use.ts +37 -6
  72. package/hooks/record-mode-transitions.ts +63 -6
  73. package/hooks/subagent-start.ts +3 -2
  74. package/package.json +3 -1
  75. package/protocols/agent-prompt-authoring.md +165 -0
  76. package/protocols/architecture-schema.md +10 -3
  77. package/protocols/cleanup.md +4 -0
  78. package/protocols/decision-log.md +8 -4
  79. package/protocols/design-md-authoring.md +520 -0
  80. package/protocols/design-md-spec.md +362 -0
  81. package/protocols/fake-data-detector.md +1 -1
  82. package/protocols/ios-fake-data-detector.md +65 -0
  83. package/protocols/ios-phase-branches.md +128 -43
  84. package/protocols/launch-readiness.md +9 -5
  85. package/protocols/metric-loop.md +1 -1
  86. package/protocols/page-spec-schema.md +234 -0
  87. package/protocols/product-spec-schema.md +354 -0
  88. package/protocols/sprint-tasks-schema.md +53 -0
  89. package/protocols/state-schema.json +38 -3
  90. package/protocols/state-schema.md +32 -2
  91. package/protocols/verify.md +29 -1
  92. package/protocols/web-phase-branches.md +246 -76
  93. package/skills/ios/ios-bootstrap/SKILL.md +1 -1
  94. package/src/graph/ids.ts +86 -0
  95. package/src/graph/index.ts +32 -0
  96. package/src/graph/parser/architecture.ts +603 -0
  97. package/src/graph/parser/component-manifest.ts +268 -0
  98. package/src/graph/parser/decisions-jsonl.ts +407 -0
  99. package/src/graph/parser/design-md-pass2.ts +253 -0
  100. package/src/graph/parser/design-md.ts +477 -0
  101. package/src/graph/parser/page-spec.ts +496 -0
  102. package/src/graph/parser/product-spec.ts +930 -0
  103. package/src/graph/parser/screenshot.ts +342 -0
  104. package/src/graph/parser/sprint-tasks.ts +317 -0
  105. package/src/graph/storage/index.ts +1154 -0
  106. package/src/graph/types.ts +432 -0
  107. package/src/graph/util/dhash.ts +84 -0
  108. package/src/lrr/aggregator.ts +105 -10
  109. package/src/orchestrator/hooks/context-header.ts +34 -10
  110. package/src/orchestrator/hooks/token-accounting.ts +25 -14
  111. package/src/orchestrator/mcp/cycle-counter.ts +2 -1
  112. package/src/orchestrator/mcp/scribe.ts +27 -16
  113. package/src/orchestrator/mcp/write-lease.ts +30 -13
  114. package/src/orchestrator/phase4-shared-context.ts +20 -4
  115. package/protocols/visual-dna.md +0 -185
package/bin/setup.js CHANGED
@@ -28,7 +28,12 @@ const IOS_MCPS = [
28
28
  },
29
29
  ];
30
30
 
31
- const isIos = process.argv.includes("--ios");
31
+ const isIosFlag = process.argv.includes("--ios");
32
+
33
+ function detectExistingIos() {
34
+ const mcps = run("claude", ["mcp", "list"]) ?? "";
35
+ return mcps.includes("xcodebuildmcp") || mcps.includes("apple-docs");
36
+ }
32
37
 
33
38
  function run(command, args) {
34
39
  try {
@@ -41,11 +46,107 @@ function run(command, args) {
41
46
  }
42
47
  }
43
48
 
49
+ function runJson(command, args) {
50
+ const out = run(command, args);
51
+ if (!out) return null;
52
+ try {
53
+ return JSON.parse(out);
54
+ } catch {
55
+ return null;
56
+ }
57
+ }
58
+
59
+ function snapshotState() {
60
+ const plugins = runJson("claude", ["plugin", "list", "--json"]);
61
+ const marketplaces = runJson("claude", ["plugin", "marketplace", "list", "--json"]);
62
+ const skillsOutput = run("npx", ["--no-install", "skills", "list", "-g"]) ?? "";
63
+
64
+ return {
65
+ installedPluginIds: new Set((plugins ?? []).map((p) => p.id)),
66
+ pluginVersions: new Map((plugins ?? []).map((p) => [p.id, p.version])),
67
+ installedMarketplaces: new Set((marketplaces ?? []).map((m) => m.name)),
68
+ installedSkills: skillsOutput,
69
+ hasBin: (name) => run("which", [name]) !== null,
70
+ pluginJsonAvailable: plugins !== null,
71
+ };
72
+ }
73
+
74
+ function ensureMarketplace(state, name, source, report) {
75
+ if (state.installedMarketplaces.has(name)) {
76
+ report.marketplacesPresent.push(name);
77
+ return true;
78
+ }
79
+ const result = run("claude", ["plugin", "marketplace", "add", source]);
80
+ if (result === null) {
81
+ report.failures.push(`marketplace: ${name}`);
82
+ return false;
83
+ }
84
+ report.marketplacesAdded.push(name);
85
+ return true;
86
+ }
87
+
88
+ function ensurePlugin(state, pluginName, marketplace, report) {
89
+ const id = `${pluginName}@${marketplace}`;
90
+ if (state.installedPluginIds.has(id)) {
91
+ report.pluginsPresent.push(pluginName);
92
+ return { alreadyInstalled: true, id };
93
+ }
94
+ const result = run("claude", ["plugin", "install", id]);
95
+ if (result === null) {
96
+ report.failures.push(`plugin: ${pluginName}`);
97
+ return { alreadyInstalled: false, id, failed: true };
98
+ }
99
+ report.pluginsInstalled.push(pluginName);
100
+ return { alreadyInstalled: false, id };
101
+ }
102
+
103
+ function updateBuildanything(state, report) {
104
+ const id = `${PLUGIN}@${MARKETPLACE}`;
105
+ const oldVersion = state.pluginVersions.get(id);
106
+ const result = run("claude", ["plugin", "update", id]);
107
+ if (result === null) {
108
+ report.failures.push(`update: ${PLUGIN}`);
109
+ return;
110
+ }
111
+ const fresh = runJson("claude", ["plugin", "list", "--json"]);
112
+ const newVersion = fresh?.find((p) => p.id === id)?.version;
113
+ if (oldVersion && newVersion && oldVersion !== newVersion) {
114
+ report.updated.push(`${PLUGIN}: ${oldVersion} → ${newVersion}`);
115
+ } else {
116
+ report.pluginsPresent.push(`${PLUGIN} (up to date)`);
117
+ }
118
+ }
119
+
120
+ function ensureBin(name, installCmd, report) {
121
+ if (run("which", [name]) !== null) {
122
+ report.binsPresent.push(name);
123
+ return true;
124
+ }
125
+ const result = run(installCmd.cmd, installCmd.args);
126
+ if (result === null) {
127
+ report.failures.push(`${name} (install manually: ${installCmd.manual})`);
128
+ return false;
129
+ }
130
+ report.binsInstalled.push(name);
131
+ return true;
132
+ }
133
+
134
+ function ensureSkill(state, skillArgs, skillLabel, report) {
135
+ if (state.installedSkills.includes(skillLabel)) {
136
+ report.skillsPresent.push(skillLabel);
137
+ return;
138
+ }
139
+ const result = run("npx", ["skills", "add", ...skillArgs]);
140
+ if (result === null) {
141
+ report.failures.push(`skill: ${skillLabel}`);
142
+ return;
143
+ }
144
+ report.skillsInstalled.push(skillLabel);
145
+ }
146
+
44
147
  function main() {
45
148
  console.log("\n buildanything — one command to build an entire product\n");
46
- if (isIos) console.log(" iOS mode: will also install XcodeBuildMCP, apple-docs-mcp, and Maestro.\n");
47
149
 
48
- // Check claude is installed
49
150
  const version = run("claude", ["--version"]);
50
151
  if (!version) {
51
152
  console.error(
@@ -56,167 +157,227 @@ function main() {
56
157
  }
57
158
  console.log(` Found Claude Code ${version}`);
58
159
 
59
- // Add marketplace and install buildanything
60
- console.log(` Adding marketplace from ${REPO}...`);
61
- const addResult = run("claude", ["plugin", "marketplace", "add", REPO]);
62
- if (addResult === null) {
63
- console.error(
64
- " Error: Failed to add marketplace. Check your internet connection and try again.\n"
65
- );
66
- process.exit(1);
67
- }
68
- console.log(" Marketplace added.");
160
+ const existingIos = detectExistingIos();
161
+ const isIos = isIosFlag || existingIos;
162
+ if (isIosFlag) console.log(" iOS mode: will install XcodeBuildMCP, apple-docs-mcp, and Maestro.\n");
163
+ else if (existingIos) console.log(" Detected existing iOS setup — will verify iOS tools are current.\n");
69
164
 
70
- console.log(` Installing ${PLUGIN} plugin...`);
71
- const installResult = run("claude", [
72
- "plugin",
73
- "install",
74
- `${PLUGIN}@${MARKETPLACE}`,
75
- ]);
76
- if (installResult === null) {
77
- console.error(
78
- " Error: Failed to install plugin. Try manually:\n" +
79
- ` /plugin marketplace add ${REPO}\n` +
80
- ` /plugin install ${PLUGIN}@${MARKETPLACE}\n`
81
- );
82
- process.exit(1);
165
+ const state = snapshotState();
166
+ if (!state.pluginJsonAvailable) {
167
+ console.log(" (Claude plugin list unavailable — running in blind re-install mode)");
83
168
  }
84
- console.log(" buildanything installed.\n");
85
169
 
86
- // Install official companion plugins
87
- console.log(" Installing companion plugins from official marketplace...");
88
- const installed = [];
89
- const skipped = [];
170
+ const report = {
171
+ marketplacesAdded: [],
172
+ marketplacesPresent: [],
173
+ pluginsInstalled: [],
174
+ pluginsPresent: [],
175
+ updated: [],
176
+ binsInstalled: [],
177
+ binsPresent: [],
178
+ skillsInstalled: [],
179
+ skillsPresent: [],
180
+ mcpsAdded: [],
181
+ mcpsPresent: [],
182
+ failures: [],
183
+ };
90
184
 
91
- for (const plugin of OFFICIAL_PLUGINS) {
92
- const fullName = `${plugin.name}@${OFFICIAL_MARKETPLACE}`;
93
- process.stdout.write(` ${plugin.name} (${plugin.desc})... `);
94
- const result = run("claude", ["plugin", "install", fullName]);
95
- if (result === null) {
96
- console.log("skipped (may already be installed)");
97
- skipped.push(plugin.name);
98
- } else {
99
- console.log("installed");
100
- installed.push(plugin.name);
101
- }
185
+ // Marketplace
186
+ console.log(`\n Ensuring marketplace ${MARKETPLACE}...`);
187
+ const marketplaceOk = ensureMarketplace(state, MARKETPLACE, REPO, report);
188
+ if (!marketplaceOk) {
189
+ console.error(" Error: Failed to add marketplace. Check your internet connection.\n");
190
+ process.exit(1);
102
191
  }
103
192
 
104
- // Install tsxrequired by all plugin hooks (pre-tool-use, subagent-start/stop,
105
- // compile-writer-owner-cache, record-mode-transitions). Hooks use
106
- // `npx --no-install tsx` which silently degrades if tsx is missing.
107
- console.log("\n Installing tsx (TypeScript runner for plugin hooks)...");
108
- const tsxCheck = run("which", ["tsx"]);
109
- if (tsxCheck) {
110
- console.log(" already installed");
193
+ // buildanything plugininstall if missing, else update
194
+ console.log(` Ensuring ${PLUGIN} plugin...`);
195
+ const buildId = `${PLUGIN}@${MARKETPLACE}`;
196
+ if (state.installedPluginIds.has(buildId)) {
197
+ updateBuildanything(state, report);
111
198
  } else {
112
- process.stdout.write(" tsx... ");
113
- const tsxResult = run("npm", ["install", "-g", "tsx"]);
114
- if (tsxResult === null) {
115
- console.log("failed (install manually: npm i -g tsx)");
116
- } else {
117
- console.log("installed");
118
- }
199
+ ensurePlugin(state, PLUGIN, MARKETPLACE, report);
119
200
  }
120
201
 
121
- // Install agent-browser for behavioral verification
122
- console.log("\n Installing agent-browser (behavioral testing)...");
123
-
124
- process.stdout.write(" CLI... ");
125
- const abCheck = run("which", ["agent-browser"]);
126
- if (abCheck) {
127
- console.log("already installed");
128
- } else {
129
- const abResult = run("npm", ["install", "-g", "agent-browser"]);
130
- if (abResult === null) {
131
- console.log("failed (install manually: npm i -g agent-browser)");
202
+ // Official companion plugins
203
+ console.log("\n Ensuring companion plugins...");
204
+ for (const plugin of OFFICIAL_PLUGINS) {
205
+ const id = `${plugin.name}@${OFFICIAL_MARKETPLACE}`;
206
+ if (state.installedPluginIds.has(id)) {
207
+ console.log(` ${plugin.name} — already installed`);
208
+ report.pluginsPresent.push(plugin.name);
132
209
  } else {
133
- console.log("installed");
210
+ process.stdout.write(` ${plugin.name} (${plugin.desc})... `);
211
+ const result = run("claude", ["plugin", "install", id]);
212
+ if (result === null) {
213
+ console.log("failed");
214
+ report.failures.push(`plugin: ${plugin.name}`);
215
+ } else {
216
+ console.log("installed");
217
+ report.pluginsInstalled.push(plugin.name);
218
+ }
134
219
  }
135
220
  }
136
221
 
137
- process.stdout.write(" Chrome browser... ");
138
- const chromeResult = run("agent-browser", ["install"]);
139
- if (chromeResult === null) {
140
- console.log("skipped (run manually: agent-browser install)");
141
- } else {
142
- console.log("ready");
143
- }
222
+ // tsx — required by hooks
223
+ console.log("\n Ensuring tsx (TypeScript runner for plugin hooks)...");
224
+ ensureBin(
225
+ "tsx",
226
+ { cmd: "npm", args: ["install", "-g", "tsx"], manual: "npm i -g tsx" },
227
+ report
228
+ );
229
+ console.log(
230
+ ` tsx — ${report.binsPresent.includes("tsx") ? "already installed" : report.binsInstalled.includes("tsx") ? "installed" : "failed"}`
231
+ );
144
232
 
145
- process.stdout.write(" agent-browser skill... ");
146
- const skillResult = run("npx", ["skills", "add", "vercel-labs/agent-browser"]);
147
- if (skillResult === null) {
148
- console.log("skipped (install manually: npx skills add vercel-labs/agent-browser)");
149
- } else {
150
- console.log("installed");
151
- }
233
+ // agent-browser CLI + Chrome + skills
234
+ console.log("\n Ensuring agent-browser (behavioral testing)...");
235
+ ensureBin(
236
+ "agent-browser",
237
+ {
238
+ cmd: "npm",
239
+ args: ["install", "-g", "agent-browser"],
240
+ manual: "npm i -g agent-browser",
241
+ },
242
+ report
243
+ );
244
+ console.log(
245
+ ` agent-browser CLI — ${report.binsPresent.includes("agent-browser") ? "already installed" : report.binsInstalled.includes("agent-browser") ? "installed" : "failed"}`
246
+ );
152
247
 
153
- process.stdout.write(" dogfood skill... ");
154
- const dfResult = run("npx", ["skills", "add", "vercel-labs/agent-browser", "--skill", "dogfood"]);
155
- if (dfResult === null) {
156
- console.log("skipped (install manually: npx skills add vercel-labs/agent-browser --skill dogfood)");
248
+ // Chrome for agent-browser — agent-browser install is internally idempotent,
249
+ // but we skip the call when the CLI was already present (assume prior setup).
250
+ if (report.binsPresent.includes("agent-browser")) {
251
+ console.log(" Chrome browser skipped (agent-browser already configured)");
157
252
  } else {
158
- console.log("installed");
253
+ process.stdout.write(" Chrome browser... ");
254
+ const chromeResult = run("agent-browser", ["install"]);
255
+ console.log(chromeResult === null ? "skipped (run: agent-browser install)" : "ready");
159
256
  }
160
257
 
161
- // iOS-specific deps only when --ios flag is passed
258
+ // Skillscheck before re-adding
259
+ ensureSkill(
260
+ state,
261
+ ["vercel-labs/agent-browser"],
262
+ "agent-browser",
263
+ report
264
+ );
265
+ console.log(
266
+ ` agent-browser skill — ${report.skillsPresent.includes("agent-browser") ? "already installed" : report.skillsInstalled.includes("agent-browser") ? "installed" : "failed"}`
267
+ );
268
+
269
+ ensureSkill(
270
+ state,
271
+ ["vercel-labs/agent-browser", "--skill", "dogfood"],
272
+ "dogfood",
273
+ report
274
+ );
275
+ console.log(
276
+ ` dogfood skill — ${report.skillsPresent.includes("dogfood") ? "already installed" : report.skillsInstalled.includes("dogfood") ? "installed" : "failed"}`
277
+ );
278
+
279
+ // iOS-specific
162
280
  if (isIos) {
163
- console.log("\n Installing iOS MCP servers...");
281
+ console.log("\n Ensuring iOS MCP servers...");
164
282
  const existingMcps = run("claude", ["mcp", "list"]) ?? "";
165
283
 
166
284
  for (const mcp of IOS_MCPS) {
167
285
  process.stdout.write(` ${mcp.name} (${mcp.desc})... `);
168
286
  if (existingMcps.includes(mcp.name)) {
169
287
  console.log("already configured");
288
+ report.mcpsPresent.push(mcp.name);
170
289
  } else {
171
290
  const result = run("claude", ["mcp", "add", mcp.name, "--", ...mcp.args]);
172
291
  if (result === null) {
173
- console.log(`failed (add manually: claude mcp add ${mcp.name} -- ${mcp.args.join(" ")})`);
292
+ console.log("failed");
293
+ report.failures.push(`mcp: ${mcp.name}`);
174
294
  } else {
175
295
  console.log("configured");
296
+ report.mcpsAdded.push(mcp.name);
176
297
  }
177
298
  }
178
299
  }
179
300
 
180
- console.log("\n Installing Maestro (iOS E2E test runner)...");
181
- process.stdout.write(" maestro... ");
182
- const maestroCheck = run("which", ["maestro"]);
183
- if (maestroCheck) {
184
- console.log("already installed");
301
+ console.log("\n Ensuring Maestro (iOS E2E test runner)...");
302
+ if (run("which", ["maestro"]) !== null) {
303
+ console.log(" maestro already installed");
304
+ report.binsPresent.push("maestro");
185
305
  } else {
186
306
  const brewCheck = run("which", ["brew"]);
307
+ process.stdout.write(" maestro... ");
187
308
  if (!brewCheck) {
188
- console.log("skipped — Homebrew not found (install Homebrew first, then: brew install maestro)");
309
+ console.log("skipped — Homebrew not found");
310
+ report.failures.push("maestro (install Homebrew first, then: brew install maestro)");
189
311
  } else {
190
312
  const maestroResult = run("brew", ["install", "maestro"]);
191
313
  if (maestroResult === null) {
192
- console.log("failed (install manually: brew install maestro)");
314
+ console.log("failed");
315
+ report.failures.push("maestro (brew install maestro)");
193
316
  } else {
194
317
  console.log("installed");
318
+ report.binsInstalled.push("maestro");
195
319
  }
196
320
  }
197
321
  }
198
322
  }
199
323
 
200
- const completionMsg = isIos
201
- ? "\n Setup complete! Restart Claude Code so MCP servers load, then use:\n" +
202
- " /buildanything:build <your iOS app idea> — full iOS pipeline\n"
203
- : "\n Setup complete! Start Claude Code and use:\n" +
204
- " /buildanything:build <your idea> — full product pipeline\n" +
205
- " /buildanything:idea-sweep <your idea> — parallel research sweep\n";
324
+ // Summary
325
+ printSummary(report, isIos);
326
+ }
206
327
 
207
- console.log(completionMsg);
328
+ function printSummary(report, isIos) {
329
+ console.log("\n ─── Summary ───");
208
330
 
209
- if (!isIos) {
210
- console.log(" Building an iOS app? Re-run with: npx buildanything --ios\n");
331
+ const newThings = [
332
+ ...report.marketplacesAdded.map((n) => ` marketplace: ${n}`),
333
+ ...report.pluginsInstalled.map((n) => ` plugin: ${n}`),
334
+ ...report.binsInstalled.map((n) => ` bin: ${n}`),
335
+ ...report.skillsInstalled.map((n) => ` skill: ${n}`),
336
+ ...report.mcpsAdded.map((n) => ` mcp: ${n}`),
337
+ ];
338
+
339
+ const alreadyThere =
340
+ report.marketplacesPresent.length +
341
+ report.pluginsPresent.length +
342
+ report.binsPresent.length +
343
+ report.skillsPresent.length +
344
+ report.mcpsPresent.length;
345
+
346
+ if (report.updated.length > 0) {
347
+ console.log(" Updated:");
348
+ report.updated.forEach((u) => console.log(` ${u}`));
349
+ }
350
+
351
+ if (newThings.length > 0) {
352
+ console.log(` Newly installed (${newThings.length}):`);
353
+ newThings.forEach((t) => console.log(t));
211
354
  }
212
355
 
213
- if (installed.length > 0) {
214
- console.log(` Companion plugins installed: ${installed.join(", ")}`);
356
+ if (alreadyThere > 0) {
357
+ console.log(` Already present: ${alreadyThere} item${alreadyThere === 1 ? "" : "s"}`);
215
358
  }
216
- if (skipped.length > 0) {
217
- console.log(` Already installed: ${skipped.join(", ")}`);
359
+
360
+ if (report.failures.length > 0) {
361
+ console.log(` Failures (${report.failures.length}):`);
362
+ report.failures.forEach((f) => console.log(` ${f}`));
363
+ }
364
+
365
+ const nothingChanged =
366
+ newThings.length === 0 && report.updated.length === 0 && report.failures.length === 0;
367
+
368
+ if (nothingChanged) {
369
+ console.log(" Everything is already up to date.");
370
+ }
371
+
372
+ console.log(
373
+ isIos
374
+ ? "\n Restart Claude Code so MCP servers load, then use:\n /buildanything:build <your iOS app idea>\n"
375
+ : "\n Start Claude Code and use:\n /buildanything:build <your idea> — full product pipeline\n /buildanything:idea-sweep <your idea> — parallel research sweep\n"
376
+ );
377
+
378
+ if (!isIos) {
379
+ console.log(" Building an iOS app? Re-run with: npx buildanything --ios\n");
218
380
  }
219
- console.log();
220
381
  }
221
382
 
222
383
  main();