@flydocs/cli 0.5.0-beta.6 → 0.5.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -15,7 +15,7 @@ var CLI_VERSION, CLI_NAME, PACKAGE_NAME;
15
15
  var init_constants = __esm({
16
16
  "src/lib/constants.ts"() {
17
17
  "use strict";
18
- CLI_VERSION = "0.5.0-beta.6";
18
+ CLI_VERSION = "0.5.0-beta.7";
19
19
  CLI_NAME = "flydocs";
20
20
  PACKAGE_NAME = "@flydocs/cli";
21
21
  }
@@ -148,9 +148,6 @@ function printError(message) {
148
148
  function printInfo(message) {
149
149
  console.log(`${pc2.cyan("\u2139")} ${message}`);
150
150
  }
151
- function printStub(command) {
152
- printWarning(`${pc2.bold(command)} is not yet implemented.`);
153
- }
154
151
  function printBanner(version) {
155
152
  const pink = (t) => pc2.bold(pc2.magenta(t));
156
153
  const purple = (t) => pc2.bold(pc2.cyan(t));
@@ -242,7 +239,6 @@ function extractPreservedValues(config) {
242
239
  issueLabels: config.issueLabels ?? {},
243
240
  statusMapping: config.statusMapping ?? {},
244
241
  detectedStack: config.detectedStack ?? {},
245
- mcp: config.mcp ?? {},
246
242
  skills: config.skills ?? {},
247
243
  designSystem: config.designSystem ?? null,
248
244
  aiLabor: config.aiLabor ?? {}
@@ -275,9 +271,6 @@ async function mergeConfig(templateDir, version, tierFlag, preserved) {
275
271
  if (Object.keys(preserved.detectedStack).length > 0) {
276
272
  config.detectedStack = preserved.detectedStack;
277
273
  }
278
- if (Object.keys(preserved.mcp).length > 0) {
279
- config.mcp = preserved.mcp;
280
- }
281
274
  if (Object.keys(preserved.skills).length > 0) {
282
275
  config.skills = preserved.skills;
283
276
  }
@@ -322,12 +315,6 @@ async function installOwnedSkills(templateDir, targetDir, tier) {
322
315
  await replaceDirectory(src, join4(skillsDir, skill));
323
316
  }
324
317
  }
325
- for (const skill of SUPPORTING_SKILLS) {
326
- const src = join4(templateSkillsDir, skill);
327
- if (await pathExists(src)) {
328
- await replaceDirectory(src, join4(skillsDir, skill));
329
- }
330
- }
331
318
  const readmeSrc = join4(templateSkillsDir, "README.md");
332
319
  if (await pathExists(readmeSrc)) {
333
320
  await copyFile(readmeSrc, join4(skillsDir, "README.md"));
@@ -336,7 +323,7 @@ async function installOwnedSkills(templateDir, targetDir, tier) {
336
323
  async function replaceOwnedSkills(templateDir, targetDir, tier) {
337
324
  const skillsDir = join4(targetDir, ".claude", "skills");
338
325
  const templateSkillsDir = join4(templateDir, ".claude", "skills");
339
- for (const skill of [...OWNED_SKILLS, ...SUPPORTING_SKILLS]) {
326
+ for (const skill of OWNED_SKILLS) {
340
327
  const src = join4(templateSkillsDir, skill);
341
328
  if (await pathExists(src)) {
342
329
  await replaceDirectory(src, join4(skillsDir, skill));
@@ -384,20 +371,8 @@ async function copyCursorRules(targetDir) {
384
371
  await copyFile(mechRule, join4(rulesDir, "flydocs-mechanism.mdc"));
385
372
  }
386
373
  }
387
- for (const skill of PREMIUM_CURSOR_RULES) {
388
- const skillRule = join4(
389
- targetDir,
390
- ".claude",
391
- "skills",
392
- skill,
393
- "cursor-rule.mdc"
394
- );
395
- if (await pathExists(skillRule)) {
396
- await copyFile(skillRule, join4(rulesDir, `${skill}.mdc`));
397
- }
398
- }
399
374
  }
400
- var OWNED_SKILLS, SUPPORTING_SKILLS, MECHANISM_SKILLS, PREMIUM_CURSOR_RULES;
375
+ var OWNED_SKILLS, MECHANISM_SKILLS;
401
376
  var init_skills = __esm({
402
377
  "src/lib/skills.ts"() {
403
378
  "use strict";
@@ -408,22 +383,61 @@ var init_skills = __esm({
408
383
  "flydocs-estimates",
409
384
  "flydocs-context-graph"
410
385
  ];
411
- SUPPORTING_SKILLS = [
412
- "implementation-flow",
413
- "review-workflow",
414
- "spec-templates"
415
- ];
416
386
  MECHANISM_SKILLS = {
417
387
  local: "flydocs-local",
418
388
  cloud: "flydocs-cloud"
419
389
  };
420
- PREMIUM_CURSOR_RULES = ["flydocs-figma", "flydocs-estimates"];
421
390
  }
422
391
  });
423
392
 
424
393
  // src/lib/stack.ts
425
394
  import { readFile as readFile3 } from "fs/promises";
426
395
  import { join as join5 } from "path";
396
+ async function parseProjectMdStack(targetDir) {
397
+ const detected = /* @__PURE__ */ new Set();
398
+ const projectMdPath = join5(targetDir, "flydocs", "context", "project.md");
399
+ try {
400
+ const content = await readFile3(projectMdPath, "utf-8");
401
+ const stackMatch = content.match(/## Stack\n([\s\S]*?)(?=\n## |\n---|\z)/);
402
+ if (!stackMatch) return detected;
403
+ const stackSection = stackMatch[1].toLowerCase();
404
+ const keywordMap = {
405
+ "next.js": ["nextjs", "react"],
406
+ nextjs: ["nextjs", "react"],
407
+ react: ["react"],
408
+ vue: ["vue"],
409
+ nuxt: ["nuxt", "vue"],
410
+ angular: ["angular"],
411
+ svelte: ["svelte"],
412
+ sveltekit: ["svelte"],
413
+ expo: ["expo", "react"],
414
+ typescript: ["typescript"],
415
+ tailwind: ["tailwind"],
416
+ convex: ["convex"],
417
+ prisma: ["prisma"],
418
+ postgresql: ["prisma"],
419
+ clerk: ["clerk"],
420
+ python: ["python"],
421
+ django: ["python"],
422
+ flask: ["python"],
423
+ fastapi: ["python"],
424
+ golang: ["go"],
425
+ " go ": ["go"],
426
+ rust: ["rust"],
427
+ vitest: ["vitest"],
428
+ jest: ["jest"]
429
+ };
430
+ for (const [keyword, triggers] of Object.entries(keywordMap)) {
431
+ if (stackSection.includes(keyword)) {
432
+ for (const trigger of triggers) {
433
+ detected.add(trigger);
434
+ }
435
+ }
436
+ }
437
+ } catch {
438
+ }
439
+ return detected;
440
+ }
427
441
  async function detectStack(targetDir) {
428
442
  const detected = /* @__PURE__ */ new Set();
429
443
  const pkgPath = join5(targetDir, "package.json");
@@ -492,6 +506,10 @@ async function detectStack(targetDir) {
492
506
  if (await pathExists(join5(targetDir, "Cargo.toml"))) {
493
507
  detected.add("rust");
494
508
  }
509
+ const projectMdStack = await parseProjectMdStack(targetDir);
510
+ for (const item of projectMdStack) {
511
+ detected.add(item);
512
+ }
495
513
  const raw = Array.from(detected);
496
514
  return {
497
515
  raw,
@@ -530,7 +548,7 @@ var init_stack = __esm({
530
548
  });
531
549
 
532
550
  // src/lib/post-install.ts
533
- import { execSync } from "child_process";
551
+ import { execFileSync } from "child_process";
534
552
  import { join as join6 } from "path";
535
553
  async function runManifestGeneration(targetDir) {
536
554
  const scriptPath = join6(
@@ -541,7 +559,7 @@ async function runManifestGeneration(targetDir) {
541
559
  );
542
560
  if (!await pathExists(scriptPath)) return;
543
561
  try {
544
- execSync(`python3 "${scriptPath}"`, {
562
+ execFileSync("python3", [scriptPath], {
545
563
  cwd: targetDir,
546
564
  stdio: "pipe"
547
565
  });
@@ -561,7 +579,7 @@ async function runContextGraphBuild(targetDir) {
561
579
  );
562
580
  if (!await pathExists(scriptPath)) return;
563
581
  try {
564
- execSync(`python3 "${scriptPath}"`, {
582
+ execFileSync("python3", [scriptPath], {
565
583
  cwd: targetDir,
566
584
  stdio: "pipe"
567
585
  });
@@ -944,6 +962,7 @@ var init_skill_manager = __esm({
944
962
  });
945
963
 
946
964
  // src/lib/community-skills.ts
965
+ import { join as join8 } from "path";
947
966
  import { multiselect, isCancel, cancel } from "@clack/prompts";
948
967
  import pc4 from "picocolors";
949
968
  function suggestSkills(stack) {
@@ -962,7 +981,14 @@ function suggestSkills(stack) {
962
981
  }
963
982
  async function promptCommunitySkills(targetDir, stack, autoYes) {
964
983
  const suggestions = suggestSkills(stack);
965
- if (suggestions.length === 0) {
984
+ const skillsDir = join8(targetDir, ".claude", "skills");
985
+ const filtered = [];
986
+ for (const skill of suggestions) {
987
+ if (!await pathExists(join8(skillsDir, skill.name))) {
988
+ filtered.push(skill);
989
+ }
990
+ }
991
+ if (filtered.length === 0) {
966
992
  printInfo("No community skills suggested for detected stack.");
967
993
  console.log(` Browse more at: ${pc4.cyan("https://skills.sh/")}`);
968
994
  return;
@@ -977,10 +1003,10 @@ async function promptCommunitySkills(targetDir, stack, autoYes) {
977
1003
  console.log();
978
1004
  let selected;
979
1005
  if (autoYes) {
980
- selected = suggestions;
1006
+ selected = filtered;
981
1007
  console.log(" Auto-accepting all (--yes)");
982
1008
  } else {
983
- const options = suggestions.map((s) => ({
1009
+ const options = filtered.map((s) => ({
984
1010
  value: s,
985
1011
  label: s.name,
986
1012
  hint: s.description,
@@ -990,7 +1016,7 @@ async function promptCommunitySkills(targetDir, stack, autoYes) {
990
1016
  message: "Select community skills to install (space to toggle, enter to confirm)",
991
1017
  options,
992
1018
  required: false,
993
- initialValues: suggestions
1019
+ initialValues: filtered
994
1020
  });
995
1021
  if (isCancel(result)) {
996
1022
  cancel("Skipped community skills");
@@ -1026,6 +1052,7 @@ var COMMUNITY_SKILLS_MAP;
1026
1052
  var init_community_skills = __esm({
1027
1053
  "src/lib/community-skills.ts"() {
1028
1054
  "use strict";
1055
+ init_fs_ops();
1029
1056
  init_ui();
1030
1057
  init_skill_manager();
1031
1058
  COMMUNITY_SKILLS_MAP = [
@@ -1115,47 +1142,47 @@ var init_community_skills = __esm({
1115
1142
 
1116
1143
  // src/lib/deprecated.ts
1117
1144
  import { readdir as readdir2, mkdir as mkdir3, rename, rm as rm3 } from "fs/promises";
1118
- import { join as join8 } from "path";
1145
+ import { join as join9 } from "path";
1119
1146
  import { confirm, isCancel as isCancel2 } from "@clack/prompts";
1120
1147
  async function scanDeprecated(targetDir) {
1121
1148
  const found = [];
1122
1149
  for (const item of [...DEPRECATED_DIRS, ...DEPRECATED_FILES]) {
1123
- if (await pathExists(join8(targetDir, item))) {
1150
+ if (await pathExists(join9(targetDir, item))) {
1124
1151
  found.push(item);
1125
1152
  }
1126
1153
  }
1127
1154
  for (const skill of DEPRECATED_SKILLS) {
1128
- const p = join8(targetDir, ".claude", "skills", skill);
1155
+ const p = join9(targetDir, ".claude", "skills", skill);
1129
1156
  if (await pathExists(p)) {
1130
1157
  found.push(`.claude/skills/${skill}`);
1131
1158
  }
1132
1159
  }
1133
1160
  for (const dir of DEPRECATED_RULES_DIR) {
1134
- if (await pathExists(join8(targetDir, dir))) {
1161
+ if (await pathExists(join9(targetDir, dir))) {
1135
1162
  found.push(dir);
1136
1163
  }
1137
1164
  }
1138
1165
  for (const hook of DEPRECATED_HOOKS) {
1139
- const p = join8(targetDir, ".flydocs", "hooks", hook);
1166
+ const p = join9(targetDir, ".flydocs", "hooks", hook);
1140
1167
  if (await pathExists(p)) {
1141
1168
  found.push(`.flydocs/hooks/${hook}`);
1142
1169
  }
1143
1170
  }
1144
1171
  for (const rule of DEPRECATED_CURSOR_RULES) {
1145
- const p = join8(targetDir, ".cursor", "rules", rule);
1172
+ const p = join9(targetDir, ".cursor", "rules", rule);
1146
1173
  if (await pathExists(p)) {
1147
1174
  found.push(`.cursor/rules/${rule}`);
1148
1175
  }
1149
1176
  }
1150
1177
  for (const dir of DEPRECATED_CURSOR_RULE_DIRS) {
1151
- const p = join8(targetDir, ".cursor", "rules", dir);
1178
+ const p = join9(targetDir, ".cursor", "rules", dir);
1152
1179
  if (await pathExists(p)) {
1153
1180
  found.push(`.cursor/rules/${dir}`);
1154
1181
  }
1155
1182
  }
1156
1183
  for (const cmd of DEPRECATED_COMMANDS) {
1157
1184
  for (const prefix of [".cursor/commands", ".claude/commands"]) {
1158
- const p = join8(targetDir, prefix, cmd);
1185
+ const p = join9(targetDir, prefix, cmd);
1159
1186
  if (await pathExists(p)) {
1160
1187
  found.push(`${prefix}/${cmd}`);
1161
1188
  }
@@ -1164,12 +1191,12 @@ async function scanDeprecated(targetDir) {
1164
1191
  return found;
1165
1192
  }
1166
1193
  async function handleLegacyContext(targetDir) {
1167
- const contextDir = join8(targetDir, "flydocs", "context");
1168
- const legacyDir = join8(contextDir, "legacy");
1194
+ const contextDir = join9(targetDir, "flydocs", "context");
1195
+ const legacyDir = join9(contextDir, "legacy");
1169
1196
  const oldFiles = ["overview.md", "stack.md", "standards.md"];
1170
1197
  let hasOld = false;
1171
1198
  for (const f of oldFiles) {
1172
- if (await pathExists(join8(contextDir, f))) {
1199
+ if (await pathExists(join9(contextDir, f))) {
1173
1200
  hasOld = true;
1174
1201
  break;
1175
1202
  }
@@ -1177,9 +1204,9 @@ async function handleLegacyContext(targetDir) {
1177
1204
  if (hasOld) {
1178
1205
  await mkdir3(legacyDir, { recursive: true });
1179
1206
  for (const f of oldFiles) {
1180
- const src = join8(contextDir, f);
1207
+ const src = join9(contextDir, f);
1181
1208
  if (await pathExists(src)) {
1182
- await rename(src, join8(legacyDir, f));
1209
+ await rename(src, join9(legacyDir, f));
1183
1210
  printStatus(`Moved flydocs/context/${f} \u2192 legacy/`);
1184
1211
  }
1185
1212
  }
@@ -1189,7 +1216,7 @@ async function handleLegacyContext(targetDir) {
1189
1216
  }
1190
1217
  }
1191
1218
  async function checkLegacyFolder(targetDir) {
1192
- const legacyDir = join8(targetDir, "flydocs", "context", "legacy");
1219
+ const legacyDir = join9(targetDir, "flydocs", "context", "legacy");
1193
1220
  if (!await pathExists(legacyDir)) return null;
1194
1221
  try {
1195
1222
  const entries = await readdir2(legacyDir);
@@ -1219,7 +1246,7 @@ async function promptCleanup(targetDir, paths) {
1219
1246
  return;
1220
1247
  }
1221
1248
  for (const p of paths) {
1222
- await rm3(join8(targetDir, p), { recursive: true, force: true });
1249
+ await rm3(join9(targetDir, p), { recursive: true, force: true });
1223
1250
  printStatus(`Deleted: ${p}`);
1224
1251
  }
1225
1252
  }
@@ -1230,19 +1257,20 @@ var init_deprecated = __esm({
1230
1257
  init_fs_ops();
1231
1258
  init_ui();
1232
1259
  DEPRECATED_DIRS = [".docflow", "docflow"];
1233
- DEPRECATED_FILES = ["AGENTS.md.bak"];
1260
+ DEPRECATED_FILES = ["AGENTS.md.bak", ".cursor/mcp.json"];
1234
1261
  DEPRECATED_SKILLS = [
1235
1262
  "linear-workflow",
1236
1263
  "session-workflow",
1237
1264
  "ai-labor-estimate",
1238
1265
  "component-workflow",
1239
- "figma-mcp",
1240
- "implementation-flow",
1241
- "review-workflow",
1242
- "spec-templates"
1266
+ "figma-mcp"
1243
1267
  ];
1244
1268
  DEPRECATED_RULES_DIR = [".flydocs/rules"];
1245
- DEPRECATED_HOOKS = ["linear-auto-approve.py", "session-end.py"];
1269
+ DEPRECATED_HOOKS = [
1270
+ "linear-auto-approve.py",
1271
+ "session-end.py",
1272
+ "prefer-scripts.py"
1273
+ ];
1246
1274
  DEPRECATED_CURSOR_RULES = [
1247
1275
  "designer-agent.mdc",
1248
1276
  "docflow-core.mdc",
@@ -1270,9 +1298,9 @@ var init_deprecated = __esm({
1270
1298
 
1271
1299
  // src/lib/gitignore.ts
1272
1300
  import { readFile as readFile5, writeFile as writeFile3, appendFile } from "fs/promises";
1273
- import { join as join9 } from "path";
1301
+ import { join as join10 } from "path";
1274
1302
  async function ensureGitignore(targetDir) {
1275
- const gitignorePath = join9(targetDir, ".gitignore");
1303
+ const gitignorePath = join10(targetDir, ".gitignore");
1276
1304
  if (await pathExists(gitignorePath)) {
1277
1305
  const content = await readFile5(gitignorePath, "utf-8");
1278
1306
  if (!content.includes("# FlyDocs")) {
@@ -1286,7 +1314,7 @@ async function ensureGitignore(targetDir) {
1286
1314
  }
1287
1315
  }
1288
1316
  async function migrateGitignore(targetDir) {
1289
- const gitignorePath = join9(targetDir, ".gitignore");
1317
+ const gitignorePath = join10(targetDir, ".gitignore");
1290
1318
  if (!await pathExists(gitignorePath)) return;
1291
1319
  const content = await readFile5(gitignorePath, "utf-8");
1292
1320
  if (!content.includes("flydocs/context/graph.json")) {
@@ -1370,8 +1398,10 @@ __pycache__/
1370
1398
  // src/lib/version.ts
1371
1399
  import { readFile as readFile6 } from "fs/promises";
1372
1400
  function compareVersions(v1, v2) {
1373
- const parts1 = v1.split(".").map(Number);
1374
- const parts2 = v2.split(".").map(Number);
1401
+ const [core1, pre1] = v1.split("-", 2);
1402
+ const [core2, pre2] = v2.split("-", 2);
1403
+ const parts1 = core1.split(".").map(Number);
1404
+ const parts2 = core2.split(".").map(Number);
1375
1405
  const len = Math.max(parts1.length, parts2.length);
1376
1406
  for (let i = 0; i < len; i++) {
1377
1407
  const a = parts1[i] ?? 0;
@@ -1379,6 +1409,27 @@ function compareVersions(v1, v2) {
1379
1409
  if (a < b) return "older";
1380
1410
  if (a > b) return "newer";
1381
1411
  }
1412
+ if (!pre1 && pre2) return "newer";
1413
+ if (pre1 && !pre2) return "older";
1414
+ if (!pre1 && !pre2) return "equal";
1415
+ const preParts1 = pre1.split(".");
1416
+ const preParts2 = pre2.split(".");
1417
+ const preLen = Math.max(preParts1.length, preParts2.length);
1418
+ for (let i = 0; i < preLen; i++) {
1419
+ const a = preParts1[i];
1420
+ const b = preParts2[i];
1421
+ if (a === void 0) return "older";
1422
+ if (b === void 0) return "newer";
1423
+ const numA = Number(a);
1424
+ const numB = Number(b);
1425
+ if (!Number.isNaN(numA) && !Number.isNaN(numB)) {
1426
+ if (numA < numB) return "older";
1427
+ if (numA > numB) return "newer";
1428
+ continue;
1429
+ }
1430
+ if (a < b) return "older";
1431
+ if (a > b) return "newer";
1432
+ }
1382
1433
  return "equal";
1383
1434
  }
1384
1435
  async function getWhatsNew(changelogPath, fromVersion, toVersion) {
@@ -1391,7 +1442,7 @@ async function getWhatsNew(changelogPath, fromVersion, toVersion) {
1391
1442
  const sections = content.split(/^## \[/m);
1392
1443
  const relevant = [];
1393
1444
  for (const section of sections.slice(1)) {
1394
- const match = section.match(/^([\d.]+)\]/);
1445
+ const match = section.match(/^([\d.]+(?:-[\w.]+)?)\]/);
1395
1446
  if (!match) continue;
1396
1447
  const ver = match[1];
1397
1448
  if (compareVersions(ver, fromVersion) !== "older" && compareVersions(ver, fromVersion) !== "equal" && (compareVersions(ver, toVersion) === "older" || compareVersions(ver, toVersion) === "equal")) {
@@ -1414,7 +1465,7 @@ var init_version = __esm({
1414
1465
 
1415
1466
  // src/lib/update-check.ts
1416
1467
  import { readFile as readFile7, writeFile as writeFile4, mkdir as mkdir4 } from "fs/promises";
1417
- import { join as join10 } from "path";
1468
+ import { join as join11 } from "path";
1418
1469
  import { homedir } from "os";
1419
1470
  import pc5 from "picocolors";
1420
1471
  async function readCache() {
@@ -1431,7 +1482,7 @@ async function readCache() {
1431
1482
  }
1432
1483
  async function writeCache(cache) {
1433
1484
  try {
1434
- await mkdir4(join10(homedir(), ".flydocs"), { recursive: true });
1485
+ await mkdir4(join11(homedir(), ".flydocs"), { recursive: true });
1435
1486
  await writeFile4(CACHE_FILE, JSON.stringify(cache), "utf-8");
1436
1487
  } catch {
1437
1488
  }
@@ -1500,7 +1551,7 @@ var init_update_check = __esm({
1500
1551
  "use strict";
1501
1552
  init_constants();
1502
1553
  init_version();
1503
- CACHE_FILE = join10(homedir(), ".flydocs", "update-check.json");
1554
+ CACHE_FILE = join11(homedir(), ".flydocs", "update-check.json");
1504
1555
  CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
1505
1556
  FETCH_TIMEOUT_MS = 5e3;
1506
1557
  }
@@ -1513,7 +1564,7 @@ __export(install_exports, {
1513
1564
  });
1514
1565
  import { defineCommand } from "citty";
1515
1566
  import { resolve as resolve2 } from "path";
1516
- import { join as join11 } from "path";
1567
+ import { join as join12 } from "path";
1517
1568
  import { confirm as confirm2, select, isCancel as isCancel3, cancel as cancel2 } from "@clack/prompts";
1518
1569
  var install_default;
1519
1570
  var init_install = __esm({
@@ -1591,7 +1642,7 @@ var init_install = __esm({
1591
1642
  }
1592
1643
  tier = args.tier;
1593
1644
  printInfo(`Tier set via flag: ${tier}`);
1594
- } else if (await pathExists(join11(targetDir, ".flydocs", "config.json"))) {
1645
+ } else if (await pathExists(join12(targetDir, ".flydocs", "config.json"))) {
1595
1646
  try {
1596
1647
  const existing = await readConfig(targetDir);
1597
1648
  if (existing.tier) {
@@ -1613,37 +1664,37 @@ var init_install = __esm({
1613
1664
  tier = "local";
1614
1665
  console.log();
1615
1666
  }
1616
- if (!await pathExists(join11(targetDir, ".git"))) {
1667
+ if (!await pathExists(join12(targetDir, ".git"))) {
1617
1668
  printWarning("No git repository detected. Run git init when ready.");
1618
1669
  }
1619
1670
  await ensureDirectories(targetDir, tier);
1620
1671
  console.log("Installing framework files...");
1621
1672
  await replaceDirectory(
1622
- join11(templateDir, ".flydocs", "templates"),
1623
- join11(targetDir, ".flydocs", "templates")
1673
+ join12(templateDir, ".flydocs", "templates"),
1674
+ join12(targetDir, ".flydocs", "templates")
1624
1675
  );
1625
1676
  await replaceDirectory(
1626
- join11(templateDir, ".flydocs", "hooks"),
1627
- join11(targetDir, ".flydocs", "hooks")
1677
+ join12(templateDir, ".flydocs", "hooks"),
1678
+ join12(targetDir, ".flydocs", "hooks")
1628
1679
  );
1629
1680
  await replaceDirectory(
1630
- join11(templateDir, ".flydocs", "scripts"),
1631
- join11(targetDir, ".flydocs", "scripts")
1681
+ join12(templateDir, ".flydocs", "scripts"),
1682
+ join12(targetDir, ".flydocs", "scripts")
1632
1683
  );
1633
1684
  await copyFile(
1634
- join11(templateDir, ".flydocs", "version"),
1635
- join11(targetDir, ".flydocs", "version")
1685
+ join12(templateDir, ".flydocs", "version"),
1686
+ join12(targetDir, ".flydocs", "version")
1636
1687
  );
1637
- const manifestSrc = join11(templateDir, "manifest.json");
1688
+ const manifestSrc = join12(templateDir, "manifest.json");
1638
1689
  if (await pathExists(manifestSrc)) {
1639
- await copyFile(manifestSrc, join11(targetDir, ".flydocs", "manifest.json"));
1690
+ await copyFile(manifestSrc, join12(targetDir, ".flydocs", "manifest.json"));
1640
1691
  }
1641
- const changelogSrc = join11(templateDir, "CHANGELOG.md");
1692
+ const changelogSrc = join12(templateDir, "CHANGELOG.md");
1642
1693
  if (await pathExists(changelogSrc)) {
1643
- await copyFile(changelogSrc, join11(targetDir, ".flydocs", "CHANGELOG.md"));
1694
+ await copyFile(changelogSrc, join12(targetDir, ".flydocs", "CHANGELOG.md"));
1644
1695
  }
1645
1696
  printStatus(".flydocs/templates, hooks, version, manifest, changelog");
1646
- const configPath = join11(targetDir, ".flydocs", "config.json");
1697
+ const configPath = join12(targetDir, ".flydocs", "config.json");
1647
1698
  if (!await pathExists(configPath)) {
1648
1699
  const config = await createFreshConfig(templateDir, version, tier);
1649
1700
  await writeConfig(targetDir, config);
@@ -1669,56 +1720,47 @@ var init_install = __esm({
1669
1720
  printStatus(`Skills installed (tier: ${tier})`);
1670
1721
  console.log();
1671
1722
  console.log("Installing agents and commands...");
1672
- const claudeAgentsSrc = join11(templateDir, ".claude", "agents");
1723
+ const claudeAgentsSrc = join12(templateDir, ".claude", "agents");
1673
1724
  if (await pathExists(claudeAgentsSrc)) {
1674
1725
  await copyDirectoryContents(
1675
1726
  claudeAgentsSrc,
1676
- join11(targetDir, ".claude", "agents")
1727
+ join12(targetDir, ".claude", "agents")
1677
1728
  );
1678
1729
  }
1679
1730
  await copyDirectoryContents(
1680
- join11(templateDir, ".claude", "commands"),
1681
- join11(targetDir, ".claude", "commands")
1731
+ join12(templateDir, ".claude", "commands"),
1732
+ join12(targetDir, ".claude", "commands")
1682
1733
  );
1683
1734
  await copyFile(
1684
- join11(templateDir, ".claude", "CLAUDE.md"),
1685
- join11(targetDir, ".claude", "CLAUDE.md")
1735
+ join12(templateDir, ".claude", "CLAUDE.md"),
1736
+ join12(targetDir, ".claude", "CLAUDE.md")
1686
1737
  );
1687
1738
  await copyFile(
1688
- join11(templateDir, ".claude", "settings.json"),
1689
- join11(targetDir, ".claude", "settings.json")
1739
+ join12(templateDir, ".claude", "settings.json"),
1740
+ join12(targetDir, ".claude", "settings.json")
1690
1741
  );
1691
1742
  printStatus(".claude/ (agents, commands, CLAUDE.md, settings)");
1692
- const cursorAgentsSrc = join11(templateDir, ".cursor", "agents");
1743
+ const cursorAgentsSrc = join12(templateDir, ".cursor", "agents");
1693
1744
  if (await pathExists(cursorAgentsSrc)) {
1694
1745
  await copyDirectoryContents(
1695
1746
  cursorAgentsSrc,
1696
- join11(targetDir, ".cursor", "agents")
1747
+ join12(targetDir, ".cursor", "agents")
1697
1748
  );
1698
1749
  }
1699
1750
  await copyDirectoryContents(
1700
- join11(templateDir, ".claude", "commands"),
1701
- join11(targetDir, ".cursor", "commands")
1751
+ join12(templateDir, ".claude", "commands"),
1752
+ join12(targetDir, ".cursor", "commands")
1702
1753
  );
1703
1754
  await copyFile(
1704
- join11(templateDir, ".cursor", "hooks.json"),
1705
- join11(targetDir, ".cursor", "hooks.json")
1755
+ join12(templateDir, ".cursor", "hooks.json"),
1756
+ join12(targetDir, ".cursor", "hooks.json")
1706
1757
  );
1707
1758
  printStatus(".cursor/ (agents, commands, hooks)");
1708
1759
  await copyCursorRules(targetDir);
1709
1760
  printStatus(".cursor/rules/");
1710
- const mcpResult = await copyFileIfNotExists(
1711
- join11(templateDir, ".cursor", "mcp.json"),
1712
- join11(targetDir, ".cursor", "mcp.json")
1713
- );
1714
- if (mcpResult === "created") {
1715
- printStatus(".cursor/mcp.json (new)");
1716
- } else {
1717
- printWarning(".cursor/mcp.json exists, preserving");
1718
- }
1719
1761
  await copyFile(
1720
- join11(templateDir, "AGENTS.md"),
1721
- join11(targetDir, "AGENTS.md")
1762
+ join12(templateDir, "AGENTS.md"),
1763
+ join12(targetDir, "AGENTS.md")
1722
1764
  );
1723
1765
  printStatus("AGENTS.md");
1724
1766
  await runManifestGeneration(targetDir);
@@ -1727,40 +1769,40 @@ var init_install = __esm({
1727
1769
  console.log("Installing project templates...");
1728
1770
  const userFiles = [
1729
1771
  {
1730
- src: join11(templateDir, "flydocs", "context", "project.md"),
1731
- dest: join11(targetDir, "flydocs", "context", "project.md"),
1772
+ src: join12(templateDir, "flydocs", "context", "project.md"),
1773
+ dest: join12(targetDir, "flydocs", "context", "project.md"),
1732
1774
  label: "flydocs/context/project.md"
1733
1775
  },
1734
1776
  {
1735
- src: join11(templateDir, "flydocs", "knowledge", "INDEX.md"),
1736
- dest: join11(targetDir, "flydocs", "knowledge", "INDEX.md"),
1777
+ src: join12(templateDir, "flydocs", "knowledge", "INDEX.md"),
1778
+ dest: join12(targetDir, "flydocs", "knowledge", "INDEX.md"),
1737
1779
  label: "flydocs/knowledge/INDEX.md"
1738
1780
  },
1739
1781
  {
1740
- src: join11(templateDir, "flydocs", "knowledge", "README.md"),
1741
- dest: join11(targetDir, "flydocs", "knowledge", "README.md"),
1782
+ src: join12(templateDir, "flydocs", "knowledge", "README.md"),
1783
+ dest: join12(targetDir, "flydocs", "knowledge", "README.md"),
1742
1784
  label: "flydocs/knowledge/README.md"
1743
1785
  },
1744
1786
  {
1745
- src: join11(
1787
+ src: join12(
1746
1788
  templateDir,
1747
1789
  "flydocs",
1748
1790
  "knowledge",
1749
1791
  "product",
1750
1792
  "personas.md"
1751
1793
  ),
1752
- dest: join11(targetDir, "flydocs", "knowledge", "product", "personas.md"),
1794
+ dest: join12(targetDir, "flydocs", "knowledge", "product", "personas.md"),
1753
1795
  label: "flydocs/knowledge/product/personas.md"
1754
1796
  },
1755
1797
  {
1756
- src: join11(
1798
+ src: join12(
1757
1799
  templateDir,
1758
1800
  "flydocs",
1759
1801
  "knowledge",
1760
1802
  "product",
1761
1803
  "user-flows.md"
1762
1804
  ),
1763
- dest: join11(
1805
+ dest: join12(
1764
1806
  targetDir,
1765
1807
  "flydocs",
1766
1808
  "knowledge",
@@ -1770,18 +1812,18 @@ var init_install = __esm({
1770
1812
  label: "flydocs/knowledge/product/user-flows.md"
1771
1813
  },
1772
1814
  {
1773
- src: join11(templateDir, "flydocs", "design-system", "README.md"),
1774
- dest: join11(targetDir, "flydocs", "design-system", "README.md"),
1815
+ src: join12(templateDir, "flydocs", "design-system", "README.md"),
1816
+ dest: join12(targetDir, "flydocs", "design-system", "README.md"),
1775
1817
  label: "flydocs/design-system/README.md"
1776
1818
  },
1777
1819
  {
1778
- src: join11(
1820
+ src: join12(
1779
1821
  templateDir,
1780
1822
  "flydocs",
1781
1823
  "design-system",
1782
1824
  "component-patterns.md"
1783
1825
  ),
1784
- dest: join11(
1826
+ dest: join12(
1785
1827
  targetDir,
1786
1828
  "flydocs",
1787
1829
  "design-system",
@@ -1790,13 +1832,13 @@ var init_install = __esm({
1790
1832
  label: "flydocs/design-system/component-patterns.md"
1791
1833
  },
1792
1834
  {
1793
- src: join11(templateDir, "flydocs", "design-system", "token-mapping.md"),
1794
- dest: join11(targetDir, "flydocs", "design-system", "token-mapping.md"),
1835
+ src: join12(templateDir, "flydocs", "design-system", "token-mapping.md"),
1836
+ dest: join12(targetDir, "flydocs", "design-system", "token-mapping.md"),
1795
1837
  label: "flydocs/design-system/token-mapping.md"
1796
1838
  },
1797
1839
  {
1798
- src: join11(templateDir, "flydocs", "README.md"),
1799
- dest: join11(targetDir, "flydocs", "README.md"),
1840
+ src: join12(templateDir, "flydocs", "README.md"),
1841
+ dest: join12(targetDir, "flydocs", "README.md"),
1800
1842
  label: "flydocs/README.md"
1801
1843
  }
1802
1844
  ];
@@ -1810,12 +1852,12 @@ var init_install = __esm({
1810
1852
  }
1811
1853
  }
1812
1854
  }
1813
- const envExampleSrc = join11(templateDir, ".env.example");
1855
+ const envExampleSrc = join12(templateDir, ".env.example");
1814
1856
  if (await pathExists(envExampleSrc)) {
1815
- const hasEnv = await pathExists(join11(targetDir, ".env"));
1816
- const hasEnvExample = await pathExists(join11(targetDir, ".env.example"));
1857
+ const hasEnv = await pathExists(join12(targetDir, ".env"));
1858
+ const hasEnvExample = await pathExists(join12(targetDir, ".env.example"));
1817
1859
  if (!hasEnv && !hasEnvExample) {
1818
- await copyFile(envExampleSrc, join11(targetDir, ".env.example"));
1860
+ await copyFile(envExampleSrc, join12(targetDir, ".env.example"));
1819
1861
  printStatus(".env.example (new)");
1820
1862
  }
1821
1863
  }
@@ -1877,10 +1919,10 @@ var init_install = __esm({
1877
1919
  printCompletionBox("Installation Complete!", nextSteps);
1878
1920
  printBetaCta();
1879
1921
  try {
1880
- const { execSync: execSync4, spawn } = await import("child_process");
1922
+ const { execSync: execSync2, spawn } = await import("child_process");
1881
1923
  const isInstalled = (cmd) => {
1882
1924
  try {
1883
- execSync4(`which ${cmd}`, { stdio: "pipe" });
1925
+ execSync2(`which ${cmd}`, { stdio: "pipe" });
1884
1926
  return true;
1885
1927
  } catch {
1886
1928
  return false;
@@ -1987,7 +2029,7 @@ __export(update_exports, {
1987
2029
  default: () => update_default
1988
2030
  });
1989
2031
  import { defineCommand as defineCommand2 } from "citty";
1990
- import { resolve as resolve3, join as join12 } from "path";
2032
+ import { resolve as resolve3, join as join13 } from "path";
1991
2033
  import { mkdir as mkdir5, cp as cp2, readFile as readFile8, readdir as readdir3, rm as rm4 } from "fs/promises";
1992
2034
  import { select as select2, text, confirm as confirm3, isCancel as isCancel4, cancel as cancel3 } from "@clack/prompts";
1993
2035
  import pc6 from "picocolors";
@@ -2093,9 +2135,9 @@ var init_update = __esm({
2093
2135
  }
2094
2136
  targetDir = resolve3(targetDir);
2095
2137
  process.chdir(targetDir);
2096
- const hasVersion = await pathExists(join12(targetDir, ".flydocs", "version"));
2138
+ const hasVersion = await pathExists(join13(targetDir, ".flydocs", "version"));
2097
2139
  const hasConfig = await pathExists(
2098
- join12(targetDir, ".flydocs", "config.json")
2140
+ join13(targetDir, ".flydocs", "config.json")
2099
2141
  );
2100
2142
  if (!hasVersion && !hasConfig) {
2101
2143
  printError(`Not a FlyDocs project: ${targetDir}`);
@@ -2107,7 +2149,7 @@ var init_update = __esm({
2107
2149
  let currentVersion = "0.1.0";
2108
2150
  if (hasVersion) {
2109
2151
  const vContent = await readFile8(
2110
- join12(targetDir, ".flydocs", "version"),
2152
+ join13(targetDir, ".flydocs", "version"),
2111
2153
  "utf-8"
2112
2154
  );
2113
2155
  currentVersion = vContent.trim();
@@ -2135,7 +2177,7 @@ var init_update = __esm({
2135
2177
  }
2136
2178
  console.log(`Updating: v${currentVersion} \u2192 v${version}`);
2137
2179
  console.log();
2138
- const changelogPath = join12(templateDir, "CHANGELOG.md");
2180
+ const changelogPath = join13(templateDir, "CHANGELOG.md");
2139
2181
  const whatsNew = await getWhatsNew(changelogPath, currentVersion, version);
2140
2182
  if (whatsNew.length > 0) {
2141
2183
  console.log(pc6.cyan("What's new:"));
@@ -2147,23 +2189,23 @@ var init_update = __esm({
2147
2189
  }
2148
2190
  const now = /* @__PURE__ */ new Date();
2149
2191
  const ts = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, "0")}${String(now.getDate()).padStart(2, "0")}-${String(now.getHours()).padStart(2, "0")}${String(now.getMinutes()).padStart(2, "0")}${String(now.getSeconds()).padStart(2, "0")}`;
2150
- const backupDir = join12(targetDir, ".flydocs", `backup-${ts}`);
2192
+ const backupDir = join13(targetDir, ".flydocs", `backup-${ts}`);
2151
2193
  await mkdir5(backupDir, { recursive: true });
2152
2194
  if (hasConfig) {
2153
2195
  await cp2(
2154
- join12(targetDir, ".flydocs", "config.json"),
2155
- join12(backupDir, "config.json")
2196
+ join13(targetDir, ".flydocs", "config.json"),
2197
+ join13(backupDir, "config.json")
2156
2198
  );
2157
2199
  printStatus(`Config backed up to .flydocs/backup-${ts}/`);
2158
2200
  }
2159
2201
  try {
2160
- const flydocsDir = join12(targetDir, ".flydocs");
2202
+ const flydocsDir = join13(targetDir, ".flydocs");
2161
2203
  const entries = await readdir3(flydocsDir);
2162
2204
  const backups = entries.filter((e) => e.startsWith("backup-")).sort();
2163
2205
  if (backups.length > 3) {
2164
2206
  const toRemove = backups.slice(0, backups.length - 3);
2165
2207
  for (const old of toRemove) {
2166
- await rm4(join12(flydocsDir, old), { recursive: true, force: true });
2208
+ await rm4(join13(flydocsDir, old), { recursive: true, force: true });
2167
2209
  }
2168
2210
  }
2169
2211
  } catch {
@@ -2176,7 +2218,6 @@ var init_update = __esm({
2176
2218
  issueLabels: {},
2177
2219
  statusMapping: {},
2178
2220
  detectedStack: {},
2179
- mcp: {},
2180
2221
  skills: {},
2181
2222
  designSystem: null,
2182
2223
  aiLabor: {}
@@ -2201,72 +2242,72 @@ var init_update = __esm({
2201
2242
  }
2202
2243
  console.log("Replacing framework directories...");
2203
2244
  await replaceDirectory(
2204
- join12(templateDir, ".flydocs", "templates"),
2205
- join12(targetDir, ".flydocs", "templates")
2245
+ join13(templateDir, ".flydocs", "templates"),
2246
+ join13(targetDir, ".flydocs", "templates")
2206
2247
  );
2207
2248
  await replaceDirectory(
2208
- join12(templateDir, ".flydocs", "hooks"),
2209
- join12(targetDir, ".flydocs", "hooks")
2249
+ join13(templateDir, ".flydocs", "hooks"),
2250
+ join13(targetDir, ".flydocs", "hooks")
2210
2251
  );
2211
2252
  await replaceDirectory(
2212
- join12(templateDir, ".flydocs", "scripts"),
2213
- join12(targetDir, ".flydocs", "scripts")
2253
+ join13(templateDir, ".flydocs", "scripts"),
2254
+ join13(targetDir, ".flydocs", "scripts")
2214
2255
  );
2215
2256
  printStatus(".flydocs/templates, hooks, scripts");
2216
- const claudeAgentsSrc = join12(templateDir, ".claude", "agents");
2257
+ const claudeAgentsSrc = join13(templateDir, ".claude", "agents");
2217
2258
  if (await pathExists(claudeAgentsSrc)) {
2218
2259
  await copyDirectoryContents(
2219
2260
  claudeAgentsSrc,
2220
- join12(targetDir, ".claude", "agents")
2261
+ join13(targetDir, ".claude", "agents")
2221
2262
  );
2222
2263
  }
2223
2264
  printStatus(".claude/agents");
2224
2265
  await replaceOwnedSkills(templateDir, targetDir, effectiveTier);
2225
2266
  printStatus(`.claude/skills (tier: ${effectiveTier})`);
2226
- const cursorAgentsSrc = join12(templateDir, ".cursor", "agents");
2267
+ const cursorAgentsSrc = join13(templateDir, ".cursor", "agents");
2227
2268
  if (await pathExists(cursorAgentsSrc)) {
2228
2269
  await copyDirectoryContents(
2229
2270
  cursorAgentsSrc,
2230
- join12(targetDir, ".cursor", "agents")
2271
+ join13(targetDir, ".cursor", "agents")
2231
2272
  );
2232
2273
  }
2233
2274
  printStatus(".cursor/agents");
2234
2275
  console.log();
2235
2276
  console.log("Replacing framework files...");
2236
2277
  await copyFile(
2237
- join12(templateDir, ".claude", "CLAUDE.md"),
2238
- join12(targetDir, ".claude", "CLAUDE.md")
2278
+ join13(templateDir, ".claude", "CLAUDE.md"),
2279
+ join13(targetDir, ".claude", "CLAUDE.md")
2239
2280
  );
2240
2281
  await copyFile(
2241
- join12(templateDir, ".claude", "settings.json"),
2242
- join12(targetDir, ".claude", "settings.json")
2282
+ join13(templateDir, ".claude", "settings.json"),
2283
+ join13(targetDir, ".claude", "settings.json")
2243
2284
  );
2244
2285
  printStatus(".claude/CLAUDE.md, settings.json");
2245
2286
  await copyDirectoryContents(
2246
- join12(templateDir, ".claude", "commands"),
2247
- join12(targetDir, ".claude", "commands")
2287
+ join13(templateDir, ".claude", "commands"),
2288
+ join13(targetDir, ".claude", "commands")
2248
2289
  );
2249
2290
  await copyDirectoryContents(
2250
- join12(templateDir, ".claude", "commands"),
2251
- join12(targetDir, ".cursor", "commands")
2291
+ join13(templateDir, ".claude", "commands"),
2292
+ join13(targetDir, ".cursor", "commands")
2252
2293
  );
2253
2294
  printStatus(".claude/commands, .cursor/commands");
2254
- const skillsReadmeSrc = join12(templateDir, ".claude", "skills", "README.md");
2295
+ const skillsReadmeSrc = join13(templateDir, ".claude", "skills", "README.md");
2255
2296
  if (await pathExists(skillsReadmeSrc)) {
2256
2297
  await copyFile(
2257
2298
  skillsReadmeSrc,
2258
- join12(targetDir, ".claude", "skills", "README.md")
2299
+ join13(targetDir, ".claude", "skills", "README.md")
2259
2300
  );
2260
2301
  }
2261
2302
  printStatus(".claude/skills/README.md");
2262
2303
  await copyFile(
2263
- join12(templateDir, ".cursor", "hooks.json"),
2264
- join12(targetDir, ".cursor", "hooks.json")
2304
+ join13(templateDir, ".cursor", "hooks.json"),
2305
+ join13(targetDir, ".cursor", "hooks.json")
2265
2306
  );
2266
2307
  printStatus(".cursor/hooks.json");
2267
2308
  await copyFile(
2268
- join12(templateDir, "AGENTS.md"),
2269
- join12(targetDir, "AGENTS.md")
2309
+ join13(templateDir, "AGENTS.md"),
2310
+ join13(targetDir, "AGENTS.md")
2270
2311
  );
2271
2312
  printStatus("AGENTS.md");
2272
2313
  await runManifestGeneration(targetDir);
@@ -2291,18 +2332,18 @@ var init_update = __esm({
2291
2332
  printWarning("Config merge failed \u2014 config.json preserved as-is");
2292
2333
  }
2293
2334
  await copyFile(
2294
- join12(templateDir, ".flydocs", "version"),
2295
- join12(targetDir, ".flydocs", "version")
2335
+ join13(templateDir, ".flydocs", "version"),
2336
+ join13(targetDir, ".flydocs", "version")
2296
2337
  );
2297
2338
  printStatus(`.flydocs/version \u2192 ${version}`);
2298
- const clSrc = join12(templateDir, "CHANGELOG.md");
2339
+ const clSrc = join13(templateDir, "CHANGELOG.md");
2299
2340
  if (await pathExists(clSrc)) {
2300
- await copyFile(clSrc, join12(targetDir, ".flydocs", "CHANGELOG.md"));
2341
+ await copyFile(clSrc, join13(targetDir, ".flydocs", "CHANGELOG.md"));
2301
2342
  printStatus(".flydocs/CHANGELOG.md");
2302
2343
  }
2303
- const mfSrc = join12(templateDir, "manifest.json");
2344
+ const mfSrc = join13(templateDir, "manifest.json");
2304
2345
  if (await pathExists(mfSrc)) {
2305
- await copyFile(mfSrc, join12(targetDir, ".flydocs", "manifest.json"));
2346
+ await copyFile(mfSrc, join13(targetDir, ".flydocs", "manifest.json"));
2306
2347
  printStatus(".flydocs/manifest.json");
2307
2348
  }
2308
2349
  console.log();
@@ -2356,18 +2397,32 @@ __export(setup_exports, {
2356
2397
  default: () => setup_default
2357
2398
  });
2358
2399
  import { defineCommand as defineCommand3 } from "citty";
2400
+ import pc7 from "picocolors";
2359
2401
  var setup_default;
2360
2402
  var init_setup = __esm({
2361
2403
  "src/commands/setup.ts"() {
2362
2404
  "use strict";
2363
- init_ui();
2364
2405
  setup_default = defineCommand3({
2365
2406
  meta: {
2366
2407
  name: "setup",
2367
2408
  description: "Configure FlyDocs settings for this project"
2368
2409
  },
2369
2410
  run() {
2370
- printStub("flydocs setup");
2411
+ console.log();
2412
+ console.log(` ${pc7.bold("FlyDocs Setup")}`);
2413
+ console.log();
2414
+ console.log(` Setup runs inside your IDE as an interactive AI command.`);
2415
+ console.log();
2416
+ console.log(
2417
+ ` ${pc7.cyan("Claude Code:")} Type ${pc7.bold("/flydocs-setup")} in chat`
2418
+ );
2419
+ console.log(
2420
+ ` ${pc7.cyan("Cursor:")} Type ${pc7.bold("/flydocs-setup")} in chat`
2421
+ );
2422
+ console.log();
2423
+ console.log(` This configures your project context, detects your stack,`);
2424
+ console.log(` and installs community skills tailored to your codebase.`);
2425
+ console.log();
2371
2426
  }
2372
2427
  });
2373
2428
  }
@@ -2379,7 +2434,7 @@ __export(skills_exports, {
2379
2434
  default: () => skills_default
2380
2435
  });
2381
2436
  import { defineCommand as defineCommand4 } from "citty";
2382
- import pc7 from "picocolors";
2437
+ import pc8 from "picocolors";
2383
2438
  var list, search, add, remove, skills_default;
2384
2439
  var init_skills2 = __esm({
2385
2440
  "src/commands/skills.ts"() {
@@ -2401,19 +2456,19 @@ var init_skills2 = __esm({
2401
2456
  console.log(`${total} skill(s) installed:`);
2402
2457
  if (result.platform.length > 0) {
2403
2458
  console.log();
2404
- console.log(pc7.bold("Platform"));
2459
+ console.log(pc8.bold("Platform"));
2405
2460
  for (const skill of result.platform) {
2406
2461
  console.log(
2407
- ` ${skill.name} ${pc7.dim(`(${skill.triggers} triggers)`)}`
2462
+ ` ${skill.name} ${pc8.dim(`(${skill.triggers} triggers)`)}`
2408
2463
  );
2409
2464
  }
2410
2465
  }
2411
2466
  if (result.community.length > 0) {
2412
2467
  console.log();
2413
- console.log(pc7.bold("Community"));
2468
+ console.log(pc8.bold("Community"));
2414
2469
  for (const skill of result.community) {
2415
2470
  console.log(
2416
- ` ${skill.name} ${pc7.dim(`(${skill.triggers} triggers)`)}`
2471
+ ` ${skill.name} ${pc8.dim(`(${skill.triggers} triggers)`)}`
2417
2472
  );
2418
2473
  }
2419
2474
  }
@@ -2436,18 +2491,18 @@ var init_skills2 = __esm({
2436
2491
  const results = await searchCatalog(args.keyword);
2437
2492
  if (results.length === 0) {
2438
2493
  console.log(`No skills found for "${args.keyword}".`);
2439
- console.log(` Browse the catalog at: ${pc7.cyan("https://skills.sh/")}`);
2494
+ console.log(` Browse the catalog at: ${pc8.cyan("https://skills.sh/")}`);
2440
2495
  return;
2441
2496
  }
2442
2497
  console.log();
2443
2498
  console.log(`${results.length} skill(s) matching "${args.keyword}":`);
2444
2499
  console.log();
2445
2500
  for (const skill of results) {
2446
- console.log(` ${pc7.bold(skill.name)}`);
2501
+ console.log(` ${pc8.bold(skill.name)}`);
2447
2502
  console.log(` ${skill.description}`);
2448
- console.log(` ${pc7.dim(skill.repo)}`);
2503
+ console.log(` ${pc8.dim(skill.repo)}`);
2449
2504
  if (skill.tags.length > 0) {
2450
- console.log(` ${pc7.dim(skill.tags.join(", "))}`);
2505
+ console.log(` ${pc8.dim(skill.tags.join(", "))}`);
2451
2506
  }
2452
2507
  console.log();
2453
2508
  }
@@ -2507,10 +2562,9 @@ __export(connect_exports, {
2507
2562
  });
2508
2563
  import { defineCommand as defineCommand5 } from "citty";
2509
2564
  import { text as text2, confirm as confirm4, isCancel as isCancel5, cancel as cancel4 } from "@clack/prompts";
2510
- import pc8 from "picocolors";
2565
+ import pc9 from "picocolors";
2511
2566
  import { readFile as readFile9, writeFile as writeFile5, appendFile as appendFile2 } from "fs/promises";
2512
- import { join as join13 } from "path";
2513
- import { execSync as execSync2 } from "child_process";
2567
+ import { join as join14 } from "path";
2514
2568
  var connect_default;
2515
2569
  var init_connect = __esm({
2516
2570
  "src/commands/connect.ts"() {
@@ -2544,11 +2598,11 @@ var init_connect = __esm({
2544
2598
  },
2545
2599
  async run({ args }) {
2546
2600
  const targetDir = args.path ?? process.cwd();
2547
- const configPath = join13(targetDir, ".flydocs", "config.json");
2601
+ const configPath = join14(targetDir, ".flydocs", "config.json");
2548
2602
  if (!await pathExists(configPath)) {
2549
2603
  printError("Not a FlyDocs project (.flydocs/config.json not found).");
2550
2604
  console.log(
2551
- ` Run ${pc8.cyan("flydocs")} first to install FlyDocs in this project.`
2605
+ ` Run ${pc9.cyan("flydocs")} first to install FlyDocs in this project.`
2552
2606
  );
2553
2607
  process.exit(1);
2554
2608
  }
@@ -2565,10 +2619,10 @@ var init_connect = __esm({
2565
2619
  }
2566
2620
  }
2567
2621
  console.log();
2568
- console.log(` ${pc8.bold("Connect to Linear")}`);
2622
+ console.log(` ${pc9.bold("Connect to Linear")}`);
2569
2623
  console.log();
2570
2624
  console.log(
2571
- ` ${pc8.dim("Get your API key from: Linear \u2192 Settings \u2192 API \u2192 Personal API keys")}`
2625
+ ` ${pc9.dim("Get your API key from: Linear \u2192 Settings \u2192 API \u2192 Personal API keys")}`
2572
2626
  );
2573
2627
  console.log();
2574
2628
  let apiKey = args.key ?? "";
@@ -2591,27 +2645,31 @@ var init_connect = __esm({
2591
2645
  }
2592
2646
  printInfo("Validating API key...");
2593
2647
  try {
2594
- const result = execSync2(
2595
- `python3 -c "
2596
- import urllib.request, json
2597
- req = urllib.request.Request('https://api.linear.app/graphql',
2598
- data=json.dumps({'query': '{ viewer { id name email } }'}).encode(),
2599
- headers={'Authorization': '${apiKey}', 'Content-Type': 'application/json'})
2600
- res = urllib.request.urlopen(req)
2601
- data = json.loads(res.read())
2602
- print(json.dumps(data['data']['viewer']))
2603
- "`,
2604
- { encoding: "utf-8", timeout: 15e3 }
2605
- );
2606
- const viewer = JSON.parse(result.trim());
2607
- printStatus(`Authenticated as ${pc8.bold(viewer.name)} (${viewer.email})`);
2648
+ const response = await fetch("https://api.linear.app/graphql", {
2649
+ method: "POST",
2650
+ headers: {
2651
+ Authorization: apiKey,
2652
+ "Content-Type": "application/json"
2653
+ },
2654
+ body: JSON.stringify({ query: "{ viewer { id name email } }" }),
2655
+ signal: AbortSignal.timeout(15e3)
2656
+ });
2657
+ if (!response.ok) {
2658
+ throw new Error(`HTTP ${response.status}`);
2659
+ }
2660
+ const data = await response.json();
2661
+ if (!data.data?.viewer) {
2662
+ throw new Error("Invalid response");
2663
+ }
2664
+ const viewer = data.data.viewer;
2665
+ printStatus(`Authenticated as ${pc9.bold(viewer.name)} (${viewer.email})`);
2608
2666
  } catch {
2609
2667
  printError("Invalid API key or network error.");
2610
2668
  console.log(` Check your key and try again.`);
2611
2669
  process.exit(1);
2612
2670
  }
2613
- const envPath = join13(targetDir, ".env");
2614
- const envLocalPath = join13(targetDir, ".env.local");
2671
+ const envPath = join14(targetDir, ".env");
2672
+ const envLocalPath = join14(targetDir, ".env.local");
2615
2673
  const targetEnvPath = await pathExists(envLocalPath) ? envLocalPath : envPath;
2616
2674
  if (await pathExists(targetEnvPath)) {
2617
2675
  const envContent = await readFile9(targetEnvPath, "utf-8");
@@ -2631,7 +2689,7 @@ LINEAR_API_KEY=${apiKey}
2631
2689
  `, "utf-8");
2632
2690
  }
2633
2691
  printStatus(
2634
- `API key stored in ${pc8.dim(targetEnvPath === envLocalPath ? ".env.local" : ".env")}`
2692
+ `API key stored in ${pc9.dim(targetEnvPath === envLocalPath ? ".env.local" : ".env")}`
2635
2693
  );
2636
2694
  const wasLocal = config.tier === "local";
2637
2695
  config.tier = "cloud";
@@ -2644,14 +2702,14 @@ LINEAR_API_KEY=${apiKey}
2644
2702
  const templateDir = await resolveTemplatePath(
2645
2703
  args["local-source"] || void 0
2646
2704
  );
2647
- const templateSkillsDir = join13(templateDir, ".claude", "skills");
2648
- const skillsDir = join13(targetDir, ".claude", "skills");
2705
+ const templateSkillsDir = join14(templateDir, ".claude", "skills");
2706
+ const skillsDir = join14(targetDir, ".claude", "skills");
2649
2707
  await replaceDirectory(
2650
- join13(templateSkillsDir, "flydocs-cloud"),
2651
- join13(skillsDir, "flydocs-cloud")
2708
+ join14(templateSkillsDir, "flydocs-cloud"),
2709
+ join14(skillsDir, "flydocs-cloud")
2652
2710
  );
2653
2711
  const { rm: rm5 } = await import("fs/promises");
2654
- const localSkillDir = join13(skillsDir, "flydocs-local");
2712
+ const localSkillDir = join14(skillsDir, "flydocs-local");
2655
2713
  if (await pathExists(localSkillDir)) {
2656
2714
  await rm5(localSkillDir, { recursive: true, force: true });
2657
2715
  }
@@ -2664,14 +2722,14 @@ LINEAR_API_KEY=${apiKey}
2664
2722
  }
2665
2723
  console.log();
2666
2724
  console.log(
2667
- ` ${pc8.bold("Connected!")} Your project now syncs with Linear.`
2725
+ ` ${pc9.bold("Connected!")} Your project now syncs with Linear.`
2668
2726
  );
2669
2727
  console.log();
2670
2728
  console.log(` Next steps:`);
2671
2729
  console.log(
2672
- ` 1. Run ${pc8.cyan("/flydocs-setup")} in your IDE to configure your Linear project`
2730
+ ` 1. Run ${pc9.cyan("/flydocs-setup")} in your IDE to configure your Linear project`
2673
2731
  );
2674
- console.log(` 2. Run ${pc8.cyan("/start-session")} to begin working`);
2732
+ console.log(` 2. Run ${pc9.cyan("/start-session")} to begin working`);
2675
2733
  console.log();
2676
2734
  }
2677
2735
  });
@@ -2684,7 +2742,7 @@ __export(upgrade_exports, {
2684
2742
  default: () => upgrade_default
2685
2743
  });
2686
2744
  import { defineCommand as defineCommand6 } from "citty";
2687
- import pc9 from "picocolors";
2745
+ import pc10 from "picocolors";
2688
2746
  var upgrade_default;
2689
2747
  var init_upgrade = __esm({
2690
2748
  "src/commands/upgrade.ts"() {
@@ -2720,37 +2778,37 @@ var init_upgrade = __esm({
2720
2778
  console.log();
2721
2779
  if (currentTier === "cloud") {
2722
2780
  console.log(
2723
- ` ${pc9.green("\u2713")} You're already on the ${pc9.bold("cloud")} tier.`
2781
+ ` ${pc10.green("\u2713")} You're already on the ${pc10.bold("cloud")} tier.`
2724
2782
  );
2725
2783
  console.log();
2726
2784
  console.log(
2727
2785
  ` Your issues sync with Linear via the cloud mechanism skill.`
2728
2786
  );
2729
2787
  console.log(
2730
- ` Run ${pc9.cyan("flydocs connect")} to update your connection settings.`
2788
+ ` Run ${pc10.cyan("flydocs connect")} to update your connection settings.`
2731
2789
  );
2732
2790
  console.log();
2733
2791
  return;
2734
2792
  }
2735
- console.log(` ${pc9.bold("FlyDocs Cloud Tier")}`);
2793
+ console.log(` ${pc10.bold("FlyDocs Cloud Tier")}`);
2736
2794
  console.log();
2737
- console.log(` You're currently on the ${pc9.yellow("local")} tier.`);
2795
+ console.log(` You're currently on the ${pc10.yellow("local")} tier.`);
2738
2796
  console.log(` Upgrade to cloud for:`);
2739
2797
  console.log();
2740
2798
  console.log(
2741
- ` ${pc9.cyan("\u2192")} Issue sync with Linear (Jira coming soon)`
2799
+ ` ${pc10.cyan("\u2192")} Issue sync with Linear (Jira coming soon)`
2742
2800
  );
2743
- console.log(` ${pc9.cyan("\u2192")} Project milestones and cycle management`);
2744
- console.log(` ${pc9.cyan("\u2192")} Team assignment and priority tracking`);
2745
- console.log(` ${pc9.cyan("\u2192")} Project health updates and dashboards`);
2746
- console.log(` ${pc9.cyan("\u2192")} Cross-project issue linking`);
2801
+ console.log(` ${pc10.cyan("\u2192")} Project milestones and cycle management`);
2802
+ console.log(` ${pc10.cyan("\u2192")} Team assignment and priority tracking`);
2803
+ console.log(` ${pc10.cyan("\u2192")} Project health updates and dashboards`);
2804
+ console.log(` ${pc10.cyan("\u2192")} Cross-project issue linking`);
2747
2805
  console.log();
2748
- console.log(` ${pc9.bold("How to upgrade:")}`);
2806
+ console.log(` ${pc10.bold("How to upgrade:")}`);
2749
2807
  console.log();
2750
- console.log(` 1. Sign up at ${pc9.cyan("https://www.flydocs.ai")}`);
2808
+ console.log(` 1. Sign up at ${pc10.cyan("https://www.flydocs.ai")}`);
2751
2809
  console.log(` 2. Get your Linear API key from Linear \u2192 Settings \u2192 API`);
2752
2810
  console.log(
2753
- ` 3. Run ${pc9.cyan("flydocs connect")} to connect your project`
2811
+ ` 3. Run ${pc10.cyan("flydocs connect")} to connect your project`
2754
2812
  );
2755
2813
  console.log();
2756
2814
  }
@@ -2764,8 +2822,8 @@ __export(self_update_exports, {
2764
2822
  default: () => self_update_default
2765
2823
  });
2766
2824
  import { defineCommand as defineCommand7 } from "citty";
2767
- import { execSync as execSync3 } from "child_process";
2768
- import pc10 from "picocolors";
2825
+ import { execSync } from "child_process";
2826
+ import pc11 from "picocolors";
2769
2827
  var self_update_default;
2770
2828
  var init_self_update = __esm({
2771
2829
  "src/commands/self-update.ts"() {
@@ -2779,10 +2837,10 @@ var init_self_update = __esm({
2779
2837
  },
2780
2838
  async run() {
2781
2839
  console.log();
2782
- console.log(` Updating ${pc10.cyan(PACKAGE_NAME)}...`);
2840
+ console.log(` Updating ${pc11.cyan(PACKAGE_NAME)}...`);
2783
2841
  console.log();
2784
2842
  try {
2785
- execSync3(`npm install -g ${PACKAGE_NAME}@beta`, {
2843
+ execSync(`npm install -g ${PACKAGE_NAME}@beta`, {
2786
2844
  stdio: "inherit",
2787
2845
  timeout: 6e4
2788
2846
  });