youmd 0.8.0 → 0.8.5

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 (121) hide show
  1. package/dist/commands/chat.d.ts.map +1 -1
  2. package/dist/commands/chat.js +20 -2
  3. package/dist/commands/chat.js.map +1 -1
  4. package/dist/commands/env.d.ts +21 -4
  5. package/dist/commands/env.d.ts.map +1 -1
  6. package/dist/commands/env.js +250 -24
  7. package/dist/commands/env.js.map +1 -1
  8. package/dist/commands/login.d.ts +1 -0
  9. package/dist/commands/login.d.ts.map +1 -1
  10. package/dist/commands/login.js +20 -4
  11. package/dist/commands/login.js.map +1 -1
  12. package/dist/commands/machine.d.ts +28 -1
  13. package/dist/commands/machine.d.ts.map +1 -1
  14. package/dist/commands/machine.js +529 -4
  15. package/dist/commands/machine.js.map +1 -1
  16. package/dist/commands/project.d.ts.map +1 -1
  17. package/dist/commands/project.js +862 -17
  18. package/dist/commands/project.js.map +1 -1
  19. package/dist/commands/prompts.d.ts +19 -0
  20. package/dist/commands/prompts.d.ts.map +1 -1
  21. package/dist/commands/prompts.js +304 -1
  22. package/dist/commands/prompts.js.map +1 -1
  23. package/dist/commands/pull.d.ts.map +1 -1
  24. package/dist/commands/pull.js +28 -8
  25. package/dist/commands/pull.js.map +1 -1
  26. package/dist/commands/push.d.ts +3 -1
  27. package/dist/commands/push.d.ts.map +1 -1
  28. package/dist/commands/push.js +26 -12
  29. package/dist/commands/push.js.map +1 -1
  30. package/dist/commands/skill.d.ts.map +1 -1
  31. package/dist/commands/skill.js +19 -15
  32. package/dist/commands/skill.js.map +1 -1
  33. package/dist/commands/stack.d.ts.map +1 -1
  34. package/dist/commands/stack.js +20 -17
  35. package/dist/commands/stack.js.map +1 -1
  36. package/dist/commands/status.d.ts.map +1 -1
  37. package/dist/commands/status.js +38 -0
  38. package/dist/commands/status.js.map +1 -1
  39. package/dist/commands/sync.d.ts +2 -0
  40. package/dist/commands/sync.d.ts.map +1 -1
  41. package/dist/commands/sync.js +235 -2
  42. package/dist/commands/sync.js.map +1 -1
  43. package/dist/index.js +157 -31
  44. package/dist/index.js.map +1 -1
  45. package/dist/lib/api.d.ts +398 -0
  46. package/dist/lib/api.d.ts.map +1 -1
  47. package/dist/lib/api.js +104 -0
  48. package/dist/lib/api.js.map +1 -1
  49. package/dist/lib/daemon.d.ts +26 -0
  50. package/dist/lib/daemon.d.ts.map +1 -0
  51. package/dist/lib/daemon.js +187 -0
  52. package/dist/lib/daemon.js.map +1 -0
  53. package/dist/lib/first-run.d.ts +1 -1
  54. package/dist/lib/first-run.d.ts.map +1 -1
  55. package/dist/lib/first-run.js +8 -0
  56. package/dist/lib/first-run.js.map +1 -1
  57. package/dist/lib/machine-bootstrap-prompt.d.ts +17 -0
  58. package/dist/lib/machine-bootstrap-prompt.d.ts.map +1 -0
  59. package/dist/lib/machine-bootstrap-prompt.js +426 -0
  60. package/dist/lib/machine-bootstrap-prompt.js.map +1 -0
  61. package/dist/lib/machine-projects.d.ts +71 -0
  62. package/dist/lib/machine-projects.d.ts.map +1 -0
  63. package/dist/lib/machine-projects.js +510 -0
  64. package/dist/lib/machine-projects.js.map +1 -0
  65. package/dist/lib/machine-verify.d.ts +175 -0
  66. package/dist/lib/machine-verify.d.ts.map +1 -0
  67. package/dist/lib/machine-verify.js +684 -0
  68. package/dist/lib/machine-verify.js.map +1 -0
  69. package/dist/lib/portfolio-audit.d.ts +34 -0
  70. package/dist/lib/portfolio-audit.d.ts.map +1 -0
  71. package/dist/lib/portfolio-audit.js +254 -0
  72. package/dist/lib/portfolio-audit.js.map +1 -0
  73. package/dist/lib/portfolio-graph.d.ts +104 -0
  74. package/dist/lib/portfolio-graph.d.ts.map +1 -0
  75. package/dist/lib/portfolio-graph.js +281 -0
  76. package/dist/lib/portfolio-graph.js.map +1 -0
  77. package/dist/lib/project-strategy.d.ts +45 -0
  78. package/dist/lib/project-strategy.d.ts.map +1 -0
  79. package/dist/lib/project-strategy.js +234 -0
  80. package/dist/lib/project-strategy.js.map +1 -0
  81. package/dist/lib/realtime-sync.d.ts +128 -0
  82. package/dist/lib/realtime-sync.d.ts.map +1 -0
  83. package/dist/lib/realtime-sync.js +215 -0
  84. package/dist/lib/realtime-sync.js.map +1 -0
  85. package/dist/lib/reusable-patterns.d.ts +30 -0
  86. package/dist/lib/reusable-patterns.d.ts.map +1 -0
  87. package/dist/lib/reusable-patterns.js +375 -0
  88. package/dist/lib/reusable-patterns.js.map +1 -0
  89. package/dist/lib/skill-catalog.d.ts.map +1 -1
  90. package/dist/lib/skill-catalog.js +20 -0
  91. package/dist/lib/skill-catalog.js.map +1 -1
  92. package/dist/lib/skills.d.ts +1 -0
  93. package/dist/lib/skills.d.ts.map +1 -1
  94. package/dist/lib/skills.js +43 -13
  95. package/dist/lib/skills.js.map +1 -1
  96. package/dist/lib/version.d.ts +2 -0
  97. package/dist/lib/version.d.ts.map +1 -0
  98. package/dist/lib/version.js +63 -0
  99. package/dist/lib/version.js.map +1 -0
  100. package/dist/mcp/registry.d.ts +5 -1
  101. package/dist/mcp/registry.d.ts.map +1 -1
  102. package/dist/mcp/registry.js +426 -2
  103. package/dist/mcp/registry.js.map +1 -1
  104. package/dist/mcp/server.d.ts +2 -0
  105. package/dist/mcp/server.d.ts.map +1 -1
  106. package/dist/mcp/server.js +50 -5
  107. package/dist/mcp/server.js.map +1 -1
  108. package/package.json +2 -1
  109. package/scripts/env-vault/README.md +21 -2
  110. package/scripts/env-vault/backup.sh +24 -1
  111. package/scripts/env-vault/restore.sh +123 -8
  112. package/scripts/skillstack-sync/README.md +35 -10
  113. package/scripts/skillstack-sync/bootstrap-new-mac.sh +31 -0
  114. package/scripts/skillstack-sync/capture-agent-config.sh +1 -0
  115. package/scripts/skillstack-sync/com.youmd.context-sync.plist +38 -0
  116. package/scripts/skillstack-sync/com.youmd.identity-sync.plist +3 -1
  117. package/scripts/skillstack-sync/com.youmd.realtime-sync.plist +35 -0
  118. package/scripts/skillstack-sync/com.youmd.skillstack-sync.plist +1 -1
  119. package/scripts/skillstack-sync/context-sync.sh +69 -1
  120. package/scripts/skillstack-sync/install-daemons.sh +10 -3
  121. package/skills/machine-bootstrap.md +312 -0
@@ -40,9 +40,16 @@ exports.machineCommand = machineCommand;
40
40
  exports.machineSetupCommand = machineSetupCommand;
41
41
  const fs = __importStar(require("fs"));
42
42
  const path = __importStar(require("path"));
43
+ const os = __importStar(require("os"));
44
+ const readline = __importStar(require("readline"));
43
45
  const child_process = __importStar(require("child_process"));
44
46
  const chalk_1 = __importDefault(require("chalk"));
45
47
  const render_1 = require("../lib/render");
48
+ const config_1 = require("../lib/config");
49
+ const api_1 = require("../lib/api");
50
+ const machine_projects_1 = require("../lib/machine-projects");
51
+ const machine_verify_1 = require("../lib/machine-verify");
52
+ const machine_bootstrap_prompt_1 = require("../lib/machine-bootstrap-prompt");
46
53
  // The compiled file lives at dist/commands/machine.js.
47
54
  // Walking up two levels lands at the package root, then into scripts/.
48
55
  function resolveSkillstackScript(name) {
@@ -56,25 +63,543 @@ function assertScriptExists(scriptPath) {
56
63
  process.exit(1);
57
64
  }
58
65
  }
66
+ function machineProofSyncPayload(proof, reportPath) {
67
+ return {
68
+ schemaVersion: proof.schemaVersion,
69
+ generatedAt: proof.generatedAt,
70
+ hostName: proof.hostName,
71
+ platform: proof.platform,
72
+ rootDir: proof.rootDir,
73
+ secretValuesExposed: proof.secretValuesExposed,
74
+ reportPath,
75
+ source: "cli",
76
+ agentName: "youmd machine verify",
77
+ summary: proof.summary,
78
+ };
79
+ }
80
+ async function persistMachineProofReport(proof, opts) {
81
+ let latestPath;
82
+ if (opts.writeReport) {
83
+ const paths = (0, machine_verify_1.writeMachineVerificationProof)(proof, opts.reportPath ? expandHome(opts.reportPath) : undefined);
84
+ latestPath = paths.latestPath;
85
+ console.log("");
86
+ console.log(chalk_1.default.dim(" proof report: ") + chalk_1.default.cyan(paths.latestPath));
87
+ console.log(chalk_1.default.dim(" proof archive: ") + chalk_1.default.cyan(paths.archivedPath));
88
+ }
89
+ if (opts.syncReport) {
90
+ const res = await (0, api_1.syncMachineProof)(machineProofSyncPayload(proof, latestPath));
91
+ if (res.ok && res.data.success) {
92
+ const action = res.data.created ? "created" : "updated";
93
+ console.log(chalk_1.default.dim(" proof sync: ") + chalk_1.default.green(`${action} You.md machine record`));
94
+ }
95
+ else {
96
+ console.log(chalk_1.default.hex("#C46A3A")(" proof sync failed") + chalk_1.default.dim(` — ${(0, api_1.apiErrorMessage)(res.data) || `HTTP ${res.status}`}`));
97
+ process.exitCode = 1;
98
+ }
99
+ }
100
+ }
59
101
  function printHelp() {
60
102
  console.log("");
61
103
  console.log(" " + chalk_1.default.bold("youmd machine") + chalk_1.default.dim(" -- cross-machine setup and agent config sync"));
62
104
  console.log("");
63
105
  console.log(" " + chalk_1.default.hex("#C46A3A")("Commands"));
64
106
  console.log(" " + chalk_1.default.cyan("setup") + chalk_1.default.dim(" bootstrap a fresh Mac: clone synced repos, restore skills, guide secrets + daemons"));
107
+ console.log(" " + chalk_1.default.cyan("projects") + chalk_1.default.dim(" create/clone active You.md project repos into a Desktop code root"));
108
+ console.log(" " + chalk_1.default.cyan("verify") + chalk_1.default.dim(" audit cloned project readiness without reading secret values"));
109
+ console.log(" " + chalk_1.default.cyan("prompt") + chalk_1.default.dim(" print a one-command Claude Code/Codex fresh-computer setup prompt"));
65
110
  console.log(" " + chalk_1.default.cyan("capture") + chalk_1.default.dim(" snapshot agent config (settings, commands, plugins) into ~/.agent-shared"));
66
111
  console.log(" " + chalk_1.default.cyan("restore") + chalk_1.default.dim(" apply ~/.agent-shared/agent-config/ back onto this machine"));
67
112
  console.log("");
68
113
  console.log(" " + chalk_1.default.dim("Options:"));
69
- console.log(" " + chalk_1.default.cyan("--force") + chalk_1.default.dim(" (restore) overwrite existing files without backing them up"));
70
- console.log(" " + chalk_1.default.cyan("--dry-run") + chalk_1.default.dim(" (restore) preview what would be written, write nothing"));
114
+ console.log(" " + chalk_1.default.cyan("--root <dir>") + chalk_1.default.dim(" (projects) workspace root, default ~/Desktop/CODE_YOU"));
115
+ console.log(" " + chalk_1.default.cyan("--days <n>") + chalk_1.default.dim(" (projects) recent activity window, default 30"));
116
+ console.log(" " + chalk_1.default.cyan("--limit <n>") + chalk_1.default.dim(" (prompt) portfolio graph project cap, default 80"));
117
+ console.log(" " + chalk_1.default.cyan("--key <key>") + chalk_1.default.dim(" (prompt) embed a You.md API key for non-interactive login"));
118
+ console.log(" " + chalk_1.default.cyan("--env-vault <path>") + chalk_1.default.dim(" (prompt) encrypted .env.local vault path to restore"));
119
+ console.log(" " + chalk_1.default.cyan("--require-env-vault") + chalk_1.default.dim(" (prompt) fail setup proof unless YOUMD_ENV_VAULT is restored"));
120
+ console.log(" " + chalk_1.default.cyan("--max-clone-projects <n>") + chalk_1.default.dim(" (projects/prompt) cap clones for clean-host proof runs"));
121
+ console.log(" " + chalk_1.default.cyan("--recent-only") + chalk_1.default.dim(" (projects) skip projects outside the activity window without prompting"));
122
+ console.log(" " + chalk_1.default.cyan("--include-inactive") + chalk_1.default.dim(" (projects) audit override; include inactive/non-focused portfolio projects"));
123
+ console.log(" " + chalk_1.default.cyan("--max-projects <n>") + chalk_1.default.dim(" (verify) project scan cap, default 80"));
124
+ console.log(" " + chalk_1.default.cyan("--install-deps") + chalk_1.default.dim(" (verify) run bounded dependency installs before checks/probes"));
125
+ console.log(" " + chalk_1.default.cyan("--install-timeout-ms <n>") + chalk_1.default.dim(" (verify) timeout per dependency install, default 180000"));
126
+ console.log(" " + chalk_1.default.cyan("--max-install-projects <n>") + chalk_1.default.dim(" (verify) package project install cap, default 4"));
127
+ console.log(" " + chalk_1.default.cyan("--run-checks") + chalk_1.default.dim(" (verify) run bounded package checks after audit"));
128
+ console.log(" " + chalk_1.default.cyan("--check-scripts <names>") + chalk_1.default.dim(" (verify) comma list, default typecheck,lint,test,build"));
129
+ console.log(" " + chalk_1.default.cyan("--check-timeout-ms <n>") + chalk_1.default.dim(" (verify) timeout per script, default 120000"));
130
+ console.log(" " + chalk_1.default.cyan("--max-check-projects <n>") + chalk_1.default.dim(" (verify) package project run cap, default 8"));
131
+ console.log(" " + chalk_1.default.cyan("--probe-servers") + chalk_1.default.dim(" (verify) start bounded dev servers and probe localhost"));
132
+ console.log(" " + chalk_1.default.cyan("--server-timeout-ms <n>") + chalk_1.default.dim(" (verify) timeout per server probe, default 45000"));
133
+ console.log(" " + chalk_1.default.cyan("--max-server-projects <n>") + chalk_1.default.dim(" (verify) dev server probe cap, default 3"));
134
+ console.log(" " + chalk_1.default.cyan("--server-start-port <n>") + chalk_1.default.dim(" (verify) first localhost probe port, default 4310"));
135
+ console.log(" " + chalk_1.default.cyan("--write-report") + chalk_1.default.dim(" (verify) write secret-safe JSON proof to ~/.youmd/machine-reports/latest.json"));
136
+ console.log(" " + chalk_1.default.cyan("--sync-report") + chalk_1.default.dim(" (verify) sync proof summary to the You.md machine dashboard"));
137
+ console.log(" " + chalk_1.default.cyan("--report-path <path>") + chalk_1.default.dim(" (verify) custom machine proof report path"));
138
+ console.log(" " + chalk_1.default.cyan("--no-github") + chalk_1.default.dim(" (projects) skip authenticated GitHub recent-repo scan"));
139
+ console.log(" " + chalk_1.default.cyan("--yes") + chalk_1.default.dim(" (projects) include older projects without prompting"));
140
+ console.log(" " + chalk_1.default.cyan("--no-clone") + chalk_1.default.dim(" (projects) create directories only"));
141
+ console.log(" " + chalk_1.default.cyan("--force") + chalk_1.default.dim(" (restore) overwrite existing files without backing them up"));
142
+ console.log(" " + chalk_1.default.cyan("--dry-run") + chalk_1.default.dim(" preview writes without changing files"));
143
+ console.log("");
144
+ }
145
+ function createRL() {
146
+ return readline.createInterface({ input: process.stdin, output: process.stdout });
147
+ }
148
+ function ask(rl, question) {
149
+ return new Promise((resolve) => {
150
+ rl.question(question, (answer) => resolve(answer.trim()));
151
+ });
152
+ }
153
+ function expandHome(input) {
154
+ return input === "~" || input.startsWith("~/")
155
+ ? path.join(os.homedir(), input.slice(2))
156
+ : input;
157
+ }
158
+ function readActiveYouJson() {
159
+ const bundleDir = (0, config_1.resolveActiveBundleDir)();
160
+ if (!bundleDir)
161
+ return null;
162
+ const youJsonPath = path.join(bundleDir, "you.json");
163
+ if (!fs.existsSync(youJsonPath))
164
+ return null;
165
+ try {
166
+ return JSON.parse(fs.readFileSync(youJsonPath, "utf-8"));
167
+ }
168
+ catch {
169
+ return null;
170
+ }
171
+ }
172
+ function commandExists(name) {
173
+ const result = child_process.spawnSync("sh", ["-lc", `command -v ${name}`], {
174
+ stdio: "ignore",
175
+ });
176
+ return result.status === 0;
177
+ }
178
+ function cloneProject(candidate, targetDir) {
179
+ if (fs.existsSync(targetDir)) {
180
+ const entries = fs.readdirSync(targetDir);
181
+ if (entries.length > 0)
182
+ return "skipped";
183
+ }
184
+ if (!candidate.cloneSpec || !candidate.githubUrl) {
185
+ fs.mkdirSync(targetDir, { recursive: true });
186
+ return "created";
187
+ }
188
+ fs.mkdirSync(path.dirname(targetDir), { recursive: true });
189
+ const result = commandExists("gh")
190
+ ? child_process.spawnSync("gh", ["repo", "clone", candidate.cloneSpec, targetDir], { stdio: "inherit" })
191
+ : child_process.spawnSync("git", ["clone", candidate.githubUrl, targetDir], { stdio: "inherit" });
192
+ return result.status === 0 ? "cloned" : "failed";
193
+ }
194
+ function readRecentGithubProjectsFromGh(days) {
195
+ if (!commandExists("gh"))
196
+ return [];
197
+ const result = child_process.spawnSync("gh", [
198
+ "api",
199
+ "-X",
200
+ "GET",
201
+ "/user/repos",
202
+ "-F",
203
+ "sort=pushed",
204
+ "-F",
205
+ "direction=desc",
206
+ "-F",
207
+ "per_page=100",
208
+ "-F",
209
+ "affiliation=owner,collaborator,organization_member",
210
+ "--paginate",
211
+ "--jq",
212
+ ".[] | {name, fullName: .full_name, url: .html_url, pushedAt: .pushed_at, updatedAt: .updated_at, description, homepage, isPrivate: .private}",
213
+ ], { encoding: "utf-8" });
214
+ if (result.status !== 0 || !result.stdout.trim())
215
+ return [];
216
+ const cutoff = Date.now() - days * 86400000;
217
+ return result.stdout
218
+ .split("\n")
219
+ .map((line) => line.trim())
220
+ .filter(Boolean)
221
+ .flatMap((line) => {
222
+ try {
223
+ const parsed = JSON.parse(line);
224
+ if (!parsed.pushedAt || Date.parse(parsed.pushedAt) < cutoff)
225
+ return [];
226
+ return [parsed];
227
+ }
228
+ catch {
229
+ return [];
230
+ }
231
+ });
232
+ }
233
+ async function machineProjectsCommand(opts = {}) {
234
+ const youJson = readActiveYouJson();
235
+ if (!youJson) {
236
+ console.log(chalk_1.default.hex("#C46A3A")(" no local You.md bundle found."));
237
+ console.log(chalk_1.default.dim(" run ") + chalk_1.default.cyan("youmd login && youmd pull") + chalk_1.default.dim(" first, then retry: ") + chalk_1.default.cyan("youmd machine projects"));
238
+ return;
239
+ }
240
+ const defaultRoot = path.join(os.homedir(), "Desktop", "CODE_YOU");
241
+ let rootDir = expandHome(opts.root || defaultRoot);
242
+ let rl = null;
243
+ const interactive = process.stdin.isTTY && process.stdout.isTTY;
244
+ if (!opts.root && interactive) {
245
+ rl = createRL();
246
+ const answer = await ask(rl, chalk_1.default.dim(` code project directory [${rootDir}]: `));
247
+ if (answer)
248
+ rootDir = expandHome(answer);
249
+ }
250
+ const activeDays = Number(opts.days || 30);
251
+ let portfolioGraph = null;
252
+ if ((0, config_1.isAuthenticated)()) {
253
+ const graphRes = await (0, api_1.getPortfolioGraph)({ includeTasks: true });
254
+ if (graphRes.ok && graphRes.data) {
255
+ portfolioGraph = graphRes.data;
256
+ console.log(chalk_1.default.dim(` portfolio graph: ${graphRes.data.projects.length} project${graphRes.data.projects.length === 1 ? "" : "s"} / ${graphRes.data.recentTrackedProjects.length} tracked repo${graphRes.data.recentTrackedProjects.length === 1 ? "" : "s"}`));
257
+ }
258
+ else {
259
+ console.log(chalk_1.default.dim(` portfolio graph: unavailable (${(0, api_1.apiErrorMessage)(graphRes.data) || `HTTP ${graphRes.status}`}); falling back to local bundle + GitHub`));
260
+ }
261
+ }
262
+ else {
263
+ console.log(chalk_1.default.dim(" portfolio graph: skipped until youmd login completes"));
264
+ }
265
+ const githubProjects = opts.github === false ? [] : readRecentGithubProjectsFromGh(activeDays);
266
+ if (githubProjects.length > 0) {
267
+ console.log(chalk_1.default.dim(` github: found ${githubProjects.length} repo${githubProjects.length === 1 ? "" : "s"} pushed within ${activeDays || 30}d`));
268
+ }
269
+ else if (opts.github !== false) {
270
+ console.log(chalk_1.default.dim(" github: no authenticated recent repos found; using local You.md project records"));
271
+ }
272
+ const plan = (0, machine_projects_1.buildMachineProjectPlan)(youJson, {
273
+ rootDir,
274
+ activeDays: Number.isFinite(activeDays) && activeDays > 0 ? activeDays : 30,
275
+ githubProjects,
276
+ portfolioGraph,
277
+ includeInactive: opts.includeInactive,
278
+ });
279
+ let selected = [...plan.recent];
280
+ if (plan.older.length > 0 && opts.recentOnly) {
281
+ console.log("");
282
+ console.log(chalk_1.default.dim(` skipped ${plan.older.length} project${plan.older.length === 1 ? "" : "s"} outside the ${activeDays || 30}d activity window (--recent-only)`));
283
+ }
284
+ else if (plan.older.length > 0) {
285
+ console.log("");
286
+ console.log(chalk_1.default.dim(` older projects outside the ${activeDays || 30}d window:`));
287
+ for (const candidate of plan.older) {
288
+ console.log(chalk_1.default.dim(` - ${candidate.name} (${candidate.reason})`));
289
+ }
290
+ if (opts.yes) {
291
+ selected = selected.concat(plan.older);
292
+ }
293
+ else if (interactive) {
294
+ if (!rl)
295
+ rl = createRL();
296
+ for (const candidate of plan.older) {
297
+ const answer = await ask(rl, chalk_1.default.dim(` include ${candidate.name}? [y/N]: `));
298
+ if (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") {
299
+ selected.push(candidate);
300
+ }
301
+ }
302
+ }
303
+ }
304
+ rl?.close();
305
+ const maxCloneProjects = Number(opts.maxCloneProjects || 0);
306
+ const hasCloneCap = Number.isFinite(maxCloneProjects) && maxCloneProjects > 0;
307
+ if (hasCloneCap && selected.length > maxCloneProjects) {
308
+ selected = selected.slice(0, maxCloneProjects);
309
+ }
310
+ console.log("");
311
+ console.log(" " + chalk_1.default.bold("machine project bootstrap"));
312
+ console.log(chalk_1.default.dim(` root: ${plan.rootDir}`));
313
+ console.log(chalk_1.default.dim(` selected: ${selected.length} project${selected.length === 1 ? "" : "s"}`));
314
+ if (hasCloneCap) {
315
+ console.log(chalk_1.default.dim(` clone cap: ${maxCloneProjects} project${maxCloneProjects === 1 ? "" : "s"} (proof mode)`));
316
+ }
317
+ console.log(chalk_1.default.dim(` graph inputs: ${plan.sourceCounts.portfolioGraphProjects} portfolio project${plan.sourceCounts.portfolioGraphProjects === 1 ? "" : "s"} / ${plan.sourceCounts.portfolioGraphTrackedProjects} graph-tracked repo${plan.sourceCounts.portfolioGraphTrackedProjects === 1 ? "" : "s"} / ${plan.sourceCounts.githubProjects} gh repo${plan.sourceCounts.githubProjects === 1 ? "" : "s"} / ${plan.sourceCounts.bundleProjects} bundle project${plan.sourceCounts.bundleProjects === 1 ? "" : "s"}`));
318
+ if (plan.sourceCounts.portfolioGraphProjects > 0 && !opts.includeInactive) {
319
+ console.log(chalk_1.default.dim(" setup gate: Portfolio Graph status=active and focus=Top Priority/Focusing only"));
320
+ }
321
+ if (plan.skipped.length > 0) {
322
+ console.log(chalk_1.default.dim(` skipped duplicates/unusable/not setup-eligible: ${plan.skipped.length}`));
323
+ }
324
+ console.log("");
325
+ if (selected.length === 0) {
326
+ console.log(chalk_1.default.dim(" nothing selected. no dirt made on the desktop today."));
327
+ return;
328
+ }
329
+ if (opts.dryRun) {
330
+ for (const candidate of selected) {
331
+ const target = path.join(plan.rootDir, candidate.targetDirName);
332
+ const action = opts.clone === false || !candidate.githubUrl ? "mkdir" : "clone";
333
+ const meta = [
334
+ candidate.githubUrl ? `<- ${candidate.githubUrl}` : "",
335
+ candidate.stackName ? `[${candidate.stackName}]` : "",
336
+ `source:${candidate.source}`,
337
+ candidate.focus ? `focus:${candidate.focus.slice(0, 72)}` : "",
338
+ ].filter(Boolean).join(" ");
339
+ console.log(` ${chalk_1.default.cyan(action.padEnd(5))} ${target}${meta ? chalk_1.default.dim(` ${meta}`) : ""}`);
340
+ }
341
+ return;
342
+ }
343
+ fs.mkdirSync(plan.rootDir, { recursive: true });
344
+ let cloned = 0;
345
+ let created = 0;
346
+ let skipped = 0;
347
+ let failed = 0;
348
+ for (const candidate of selected) {
349
+ const target = path.join(plan.rootDir, candidate.targetDirName);
350
+ if (opts.clone === false) {
351
+ if (!fs.existsSync(target)) {
352
+ fs.mkdirSync(target, { recursive: true });
353
+ created++;
354
+ console.log(chalk_1.default.green(" ✓") + chalk_1.default.dim(` ${candidate.targetDirName}`));
355
+ }
356
+ else {
357
+ skipped++;
358
+ console.log(chalk_1.default.dim(` - ${candidate.targetDirName} already exists`));
359
+ }
360
+ continue;
361
+ }
362
+ const result = cloneProject(candidate, target);
363
+ if (result === "cloned")
364
+ cloned++;
365
+ else if (result === "created")
366
+ created++;
367
+ else if (result === "skipped")
368
+ skipped++;
369
+ else
370
+ failed++;
371
+ }
372
+ console.log("");
373
+ console.log(chalk_1.default.green(` done: ${cloned} cloned, ${created} directories created, ${skipped} skipped${failed ? `, ${failed} failed` : ""}`));
374
+ console.log(chalk_1.default.dim(" next: open Claude Code or Codex from that CODE folder and run ") + chalk_1.default.cyan("you"));
375
+ }
376
+ async function machineVerifyCommand(opts = {}) {
377
+ const defaultRoot = path.join(os.homedir(), "Desktop", "CODE_YOU");
378
+ const rootDir = expandHome(opts.root || defaultRoot);
379
+ const maxProjects = Number(opts.maxProjects || 80);
380
+ const report = (0, machine_verify_1.buildMachineReadinessReport)(rootDir, Number.isFinite(maxProjects) && maxProjects > 0 ? maxProjects : 80);
381
+ console.log("");
382
+ console.log(" " + chalk_1.default.bold("machine readiness audit"));
383
+ console.log(chalk_1.default.dim(` root: ${report.rootDir}`));
384
+ console.log(chalk_1.default.dim(` scanned: ${report.scanned} project director${report.scanned === 1 ? "y" : "ies"}`));
385
+ console.log(chalk_1.default.dim(` git: ${report.totals.gitRepos} / packages: ${report.totals.packageProjects} / env.local: ${report.totals.envLocal} / env examples: ${report.totals.envExample}`));
386
+ console.log(chalk_1.default.dim(` agent docs: ${report.totals.agentDocs} / project-context: ${report.totals.projectContext} / ready: ${report.totals.ready} / needs env: ${report.totals.needsEnv} / partial: ${report.totals.partial}`));
387
+ console.log("");
388
+ if (report.projects.length === 0) {
389
+ console.log(chalk_1.default.dim(" no cloned projects found yet. run ") + chalk_1.default.cyan("youmd machine projects") + chalk_1.default.dim(" first."));
390
+ if (opts.writeReport || opts.syncReport) {
391
+ const proof = (0, machine_verify_1.buildMachineVerificationProof)({ readiness: report });
392
+ await persistMachineProofReport(proof, {
393
+ writeReport: opts.writeReport,
394
+ syncReport: opts.syncReport,
395
+ reportPath: opts.reportPath,
396
+ });
397
+ }
398
+ console.log("");
399
+ return;
400
+ }
401
+ for (const project of report.projects) {
402
+ const statusColor = project.status === "ready"
403
+ ? chalk_1.default.green
404
+ : project.status === "needs-env"
405
+ ? chalk_1.default.yellow
406
+ : project.status === "empty"
407
+ ? chalk_1.default.dim
408
+ : chalk_1.default.hex("#C46A3A");
409
+ const tags = [
410
+ project.isGitRepo ? "git" : "no-git",
411
+ project.packageManager || "no-pkg",
412
+ project.hasEnvLocal ? ".env.local" : project.hasEnvExample ? "env-needed" : "no-env-template",
413
+ project.hasAgentDocs ? "agent-docs" : "agent-docs-missing",
414
+ ];
415
+ console.log(` ${statusColor(project.status.padEnd(9))} ${chalk_1.default.cyan(project.dirName)} ${chalk_1.default.dim(tags.join(" · "))}`);
416
+ if (project.remoteUrl)
417
+ console.log(chalk_1.default.dim(` remote: ${project.remoteUrl}`));
418
+ if (project.suggestedChecks.length > 0) {
419
+ console.log(chalk_1.default.dim(` checks: ${project.suggestedChecks.slice(0, 4).join(" | ")}`));
420
+ }
421
+ for (const note of project.notes.slice(0, 2)) {
422
+ console.log(chalk_1.default.dim(` note: ${note}`));
423
+ }
424
+ }
425
+ console.log("");
426
+ console.log(chalk_1.default.dim(" secret rule: readiness checks only inspect file names and package scripts; .env.local values are never read."));
427
+ let installReport;
428
+ let runReport;
429
+ let probeReport;
430
+ if (opts.installDeps) {
431
+ installReport = (0, machine_verify_1.buildMachineInstallReport)(rootDir, {
432
+ timeoutMs: Number(opts.installTimeoutMs || 180000),
433
+ maxProjects: Number(opts.maxInstallProjects || 4),
434
+ scanLimit: Number.isFinite(maxProjects) && maxProjects > 0 ? maxProjects : 80,
435
+ });
436
+ console.log("");
437
+ console.log(" " + chalk_1.default.bold("bounded dependency install"));
438
+ console.log(chalk_1.default.dim(` max projects: ${installReport.maxProjects} / timeout: ${installReport.timeoutMs}ms per project`));
439
+ console.log(chalk_1.default.dim(` passed: ${installReport.totals.passed} / failed: ${installReport.totals.failed} / timeout: ${installReport.totals.timeout} / skipped: ${installReport.totals.skipped}`));
440
+ console.log("");
441
+ if (installReport.results.length === 0) {
442
+ console.log(chalk_1.default.dim(" no package projects were available for dependency install."));
443
+ console.log("");
444
+ }
445
+ for (const result of installReport.results) {
446
+ const statusColor = result.status === "passed"
447
+ ? chalk_1.default.green
448
+ : result.status === "skipped"
449
+ ? chalk_1.default.dim
450
+ : result.status === "timeout"
451
+ ? chalk_1.default.yellow
452
+ : chalk_1.default.hex("#C46A3A");
453
+ console.log(` ${statusColor(result.status.padEnd(7))} ${chalk_1.default.cyan(result.dirName)} ${chalk_1.default.dim(result.command)} ${chalk_1.default.dim(`${result.durationMs}ms`)}`);
454
+ if (result.reason)
455
+ console.log(chalk_1.default.dim(` reason: ${result.reason}`));
456
+ if (result.status !== "passed" && result.status !== "skipped" && result.outputTail) {
457
+ console.log(chalk_1.default.dim(" output tail:"));
458
+ for (const line of result.outputTail.split("\n").slice(-12)) {
459
+ console.log(chalk_1.default.dim(` ${line}`));
460
+ }
461
+ }
462
+ }
463
+ if (installReport.totals.failed > 0 || installReport.totals.timeout > 0) {
464
+ process.exitCode = 1;
465
+ }
466
+ }
467
+ if (!opts.runChecks && !opts.probeServers) {
468
+ if (opts.writeReport || opts.syncReport) {
469
+ const proof = (0, machine_verify_1.buildMachineVerificationProof)({ readiness: report, installs: installReport });
470
+ await persistMachineProofReport(proof, {
471
+ writeReport: opts.writeReport,
472
+ syncReport: opts.syncReport,
473
+ reportPath: opts.reportPath,
474
+ });
475
+ }
476
+ console.log(chalk_1.default.dim(" run ") + chalk_1.default.cyan("youmd machine verify --install-deps --run-checks --probe-servers") + chalk_1.default.dim(" to install deps, execute bounded checks, and smoke-probe dev servers."));
477
+ console.log("");
478
+ return;
479
+ }
480
+ if (opts.runChecks) {
481
+ const checkScripts = opts.checkScripts
482
+ ? opts.checkScripts.split(",").map((script) => script.trim()).filter(Boolean)
483
+ : undefined;
484
+ runReport = (0, machine_verify_1.buildMachineRunChecksReport)(rootDir, {
485
+ scripts: checkScripts,
486
+ timeoutMs: Number(opts.checkTimeoutMs || 120000),
487
+ maxProjects: Number(opts.maxCheckProjects || 8),
488
+ scanLimit: Number.isFinite(maxProjects) && maxProjects > 0 ? maxProjects : 80,
489
+ });
490
+ console.log("");
491
+ console.log(" " + chalk_1.default.bold("bounded package checks"));
492
+ console.log(chalk_1.default.dim(` scripts: ${runReport.requestedScripts.join(", ")}`));
493
+ console.log(chalk_1.default.dim(` max projects: ${runReport.maxProjects} / timeout: ${runReport.timeoutMs}ms per script`));
494
+ console.log(chalk_1.default.dim(` passed: ${runReport.totals.passed} / failed: ${runReport.totals.failed} / timeout: ${runReport.totals.timeout} / skipped: ${runReport.totals.skipped}`));
495
+ console.log("");
496
+ if (runReport.results.length === 0) {
497
+ console.log(chalk_1.default.dim(" no package projects had requested check scripts."));
498
+ console.log("");
499
+ }
500
+ for (const result of runReport.results) {
501
+ const statusColor = result.status === "passed"
502
+ ? chalk_1.default.green
503
+ : result.status === "skipped"
504
+ ? chalk_1.default.dim
505
+ : result.status === "timeout"
506
+ ? chalk_1.default.yellow
507
+ : chalk_1.default.hex("#C46A3A");
508
+ console.log(` ${statusColor(result.status.padEnd(7))} ${chalk_1.default.cyan(result.dirName)} ${chalk_1.default.dim(result.command)} ${chalk_1.default.dim(`${result.durationMs}ms`)}`);
509
+ if (result.reason)
510
+ console.log(chalk_1.default.dim(` reason: ${result.reason}`));
511
+ if (result.status !== "passed" && result.status !== "skipped" && result.outputTail) {
512
+ console.log(chalk_1.default.dim(" output tail:"));
513
+ for (const line of result.outputTail.split("\n").slice(-12)) {
514
+ console.log(chalk_1.default.dim(` ${line}`));
515
+ }
516
+ }
517
+ }
518
+ if (runReport.totals.failed > 0 || runReport.totals.timeout > 0) {
519
+ process.exitCode = 1;
520
+ }
521
+ }
522
+ if (opts.probeServers) {
523
+ probeReport = await (0, machine_verify_1.buildMachineServerProbeReport)(rootDir, {
524
+ timeoutMs: Number(opts.serverTimeoutMs || 45000),
525
+ maxProjects: Number(opts.maxServerProjects || 3),
526
+ startPort: Number(opts.serverStartPort || 4310),
527
+ scanLimit: Number.isFinite(maxProjects) && maxProjects > 0 ? maxProjects : 80,
528
+ });
529
+ console.log("");
530
+ console.log(" " + chalk_1.default.bold("bounded dev server probes"));
531
+ console.log(chalk_1.default.dim(` max projects: ${probeReport.maxProjects} / timeout: ${probeReport.timeoutMs}ms per server / first port: ${probeReport.startPort}`));
532
+ console.log(chalk_1.default.dim(` passed: ${probeReport.totals.passed} / failed: ${probeReport.totals.failed} / timeout: ${probeReport.totals.timeout} / skipped: ${probeReport.totals.skipped}`));
533
+ console.log("");
534
+ if (probeReport.results.length === 0) {
535
+ console.log(chalk_1.default.dim(" no package projects had a dev script to probe."));
536
+ console.log("");
537
+ }
538
+ for (const result of probeReport.results) {
539
+ const statusColor = result.status === "passed"
540
+ ? chalk_1.default.green
541
+ : result.status === "skipped"
542
+ ? chalk_1.default.dim
543
+ : result.status === "timeout"
544
+ ? chalk_1.default.yellow
545
+ : chalk_1.default.hex("#C46A3A");
546
+ const statusSuffix = result.statusCode ? ` HTTP ${result.statusCode}` : "";
547
+ console.log(` ${statusColor(result.status.padEnd(7))} ${chalk_1.default.cyan(result.dirName)} ${chalk_1.default.dim(result.command)} ${chalk_1.default.dim(`${result.url}${statusSuffix} · ${result.durationMs}ms`)}`);
548
+ if (result.reason)
549
+ console.log(chalk_1.default.dim(` reason: ${result.reason}`));
550
+ if (result.status !== "passed" && result.status !== "skipped" && result.outputTail) {
551
+ console.log(chalk_1.default.dim(" output tail:"));
552
+ for (const line of result.outputTail.split("\n").slice(-12)) {
553
+ console.log(chalk_1.default.dim(` ${line}`));
554
+ }
555
+ }
556
+ }
557
+ if (probeReport.totals.failed > 0 || probeReport.totals.timeout > 0) {
558
+ process.exitCode = 1;
559
+ }
560
+ }
561
+ if (opts.writeReport || opts.syncReport) {
562
+ const proof = (0, machine_verify_1.buildMachineVerificationProof)({
563
+ readiness: report,
564
+ installs: installReport,
565
+ checks: runReport,
566
+ servers: probeReport,
567
+ });
568
+ await persistMachineProofReport(proof, {
569
+ writeReport: opts.writeReport,
570
+ syncReport: opts.syncReport,
571
+ reportPath: opts.reportPath,
572
+ });
573
+ }
71
574
  console.log("");
72
575
  }
73
- function machineCommand(subcommand, opts = {}) {
576
+ async function machineCommand(subcommand, opts = {}) {
74
577
  if (!subcommand || subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
75
578
  printHelp();
76
579
  return;
77
580
  }
581
+ if (subcommand === "projects") {
582
+ await machineProjectsCommand(opts);
583
+ return;
584
+ }
585
+ if (subcommand === "verify" || subcommand === "readiness" || subcommand === "doctor") {
586
+ await machineVerifyCommand(opts);
587
+ return;
588
+ }
589
+ if (subcommand === "prompt" || subcommand === "new-computer" || subcommand === "new-machine") {
590
+ console.log("");
591
+ console.log((0, machine_bootstrap_prompt_1.buildFreshMachineBootstrapPrompt)({
592
+ apiKey: opts.key,
593
+ root: opts.root,
594
+ days: opts.days,
595
+ limit: opts.limit,
596
+ maxCloneProjects: opts.maxCloneProjects,
597
+ envVaultPath: opts.envVault,
598
+ requireEnvVault: opts.requireEnvVault,
599
+ }));
600
+ console.log("");
601
+ return;
602
+ }
78
603
  if (subcommand === "setup") {
79
604
  const scriptPath = resolveSkillstackScript("bootstrap-new-mac.sh");
80
605
  assertScriptExists(scriptPath);
@@ -137,6 +662,6 @@ function machineCommand(subcommand, opts = {}) {
137
662
  }
138
663
  // Preserve the original export name for any callers that imported it directly.
139
664
  function machineSetupCommand() {
140
- machineCommand("setup");
665
+ void machineCommand("setup");
141
666
  }
142
667
  //# sourceMappingURL=machine.js.map