@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 +295 -237
- package/package.json +1 -1
- package/template/.claude/agents/implementation-agent.md +1 -1
- package/template/.claude/agents/research-agent.md +1 -1
- package/template/.claude/commands/flydocs-setup.md +3 -3
- package/template/.claude/commands/flydocs-update.md +3 -4
- package/template/.claude/settings.json +0 -10
- package/template/.claude/skills/README.md +35 -41
- package/template/.cursor/hooks.json +0 -5
- package/template/.env.example +2 -1
- package/template/.flydocs/config.json +3 -8
- package/template/.flydocs/hooks/auto-approve.py +2 -2
- package/template/.flydocs/hooks/post-edit.py +13 -0
- package/template/.flydocs/templates/instructions.md +17 -69
- package/template/.flydocs/version +1 -1
- package/template/flydocs/README.md +36 -55
- package/template/flydocs/design-system/README.md +21 -13
- package/template/manifest.json +4 -17
- package/template/.cursor/mcp.json +0 -16
- package/template/.flydocs/hooks/prefer-scripts.py +0 -89
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.
|
|
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
|
|
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,
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
1006
|
+
selected = filtered;
|
|
981
1007
|
console.log(" Auto-accepting all (--yes)");
|
|
982
1008
|
} else {
|
|
983
|
-
const options =
|
|
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:
|
|
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
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
1168
|
-
const legacyDir =
|
|
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(
|
|
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 =
|
|
1207
|
+
const src = join9(contextDir, f);
|
|
1181
1208
|
if (await pathExists(src)) {
|
|
1182
|
-
await rename(src,
|
|
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 =
|
|
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(
|
|
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 = [
|
|
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
|
|
1301
|
+
import { join as join10 } from "path";
|
|
1274
1302
|
async function ensureGitignore(targetDir) {
|
|
1275
|
-
const gitignorePath =
|
|
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 =
|
|
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
|
|
1374
|
-
const
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
1623
|
-
|
|
1673
|
+
join12(templateDir, ".flydocs", "templates"),
|
|
1674
|
+
join12(targetDir, ".flydocs", "templates")
|
|
1624
1675
|
);
|
|
1625
1676
|
await replaceDirectory(
|
|
1626
|
-
|
|
1627
|
-
|
|
1677
|
+
join12(templateDir, ".flydocs", "hooks"),
|
|
1678
|
+
join12(targetDir, ".flydocs", "hooks")
|
|
1628
1679
|
);
|
|
1629
1680
|
await replaceDirectory(
|
|
1630
|
-
|
|
1631
|
-
|
|
1681
|
+
join12(templateDir, ".flydocs", "scripts"),
|
|
1682
|
+
join12(targetDir, ".flydocs", "scripts")
|
|
1632
1683
|
);
|
|
1633
1684
|
await copyFile(
|
|
1634
|
-
|
|
1635
|
-
|
|
1685
|
+
join12(templateDir, ".flydocs", "version"),
|
|
1686
|
+
join12(targetDir, ".flydocs", "version")
|
|
1636
1687
|
);
|
|
1637
|
-
const manifestSrc =
|
|
1688
|
+
const manifestSrc = join12(templateDir, "manifest.json");
|
|
1638
1689
|
if (await pathExists(manifestSrc)) {
|
|
1639
|
-
await copyFile(manifestSrc,
|
|
1690
|
+
await copyFile(manifestSrc, join12(targetDir, ".flydocs", "manifest.json"));
|
|
1640
1691
|
}
|
|
1641
|
-
const changelogSrc =
|
|
1692
|
+
const changelogSrc = join12(templateDir, "CHANGELOG.md");
|
|
1642
1693
|
if (await pathExists(changelogSrc)) {
|
|
1643
|
-
await copyFile(changelogSrc,
|
|
1694
|
+
await copyFile(changelogSrc, join12(targetDir, ".flydocs", "CHANGELOG.md"));
|
|
1644
1695
|
}
|
|
1645
1696
|
printStatus(".flydocs/templates, hooks, version, manifest, changelog");
|
|
1646
|
-
const configPath =
|
|
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 =
|
|
1723
|
+
const claudeAgentsSrc = join12(templateDir, ".claude", "agents");
|
|
1673
1724
|
if (await pathExists(claudeAgentsSrc)) {
|
|
1674
1725
|
await copyDirectoryContents(
|
|
1675
1726
|
claudeAgentsSrc,
|
|
1676
|
-
|
|
1727
|
+
join12(targetDir, ".claude", "agents")
|
|
1677
1728
|
);
|
|
1678
1729
|
}
|
|
1679
1730
|
await copyDirectoryContents(
|
|
1680
|
-
|
|
1681
|
-
|
|
1731
|
+
join12(templateDir, ".claude", "commands"),
|
|
1732
|
+
join12(targetDir, ".claude", "commands")
|
|
1682
1733
|
);
|
|
1683
1734
|
await copyFile(
|
|
1684
|
-
|
|
1685
|
-
|
|
1735
|
+
join12(templateDir, ".claude", "CLAUDE.md"),
|
|
1736
|
+
join12(targetDir, ".claude", "CLAUDE.md")
|
|
1686
1737
|
);
|
|
1687
1738
|
await copyFile(
|
|
1688
|
-
|
|
1689
|
-
|
|
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 =
|
|
1743
|
+
const cursorAgentsSrc = join12(templateDir, ".cursor", "agents");
|
|
1693
1744
|
if (await pathExists(cursorAgentsSrc)) {
|
|
1694
1745
|
await copyDirectoryContents(
|
|
1695
1746
|
cursorAgentsSrc,
|
|
1696
|
-
|
|
1747
|
+
join12(targetDir, ".cursor", "agents")
|
|
1697
1748
|
);
|
|
1698
1749
|
}
|
|
1699
1750
|
await copyDirectoryContents(
|
|
1700
|
-
|
|
1701
|
-
|
|
1751
|
+
join12(templateDir, ".claude", "commands"),
|
|
1752
|
+
join12(targetDir, ".cursor", "commands")
|
|
1702
1753
|
);
|
|
1703
1754
|
await copyFile(
|
|
1704
|
-
|
|
1705
|
-
|
|
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
|
-
|
|
1721
|
-
|
|
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:
|
|
1731
|
-
dest:
|
|
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:
|
|
1736
|
-
dest:
|
|
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:
|
|
1741
|
-
dest:
|
|
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:
|
|
1787
|
+
src: join12(
|
|
1746
1788
|
templateDir,
|
|
1747
1789
|
"flydocs",
|
|
1748
1790
|
"knowledge",
|
|
1749
1791
|
"product",
|
|
1750
1792
|
"personas.md"
|
|
1751
1793
|
),
|
|
1752
|
-
dest:
|
|
1794
|
+
dest: join12(targetDir, "flydocs", "knowledge", "product", "personas.md"),
|
|
1753
1795
|
label: "flydocs/knowledge/product/personas.md"
|
|
1754
1796
|
},
|
|
1755
1797
|
{
|
|
1756
|
-
src:
|
|
1798
|
+
src: join12(
|
|
1757
1799
|
templateDir,
|
|
1758
1800
|
"flydocs",
|
|
1759
1801
|
"knowledge",
|
|
1760
1802
|
"product",
|
|
1761
1803
|
"user-flows.md"
|
|
1762
1804
|
),
|
|
1763
|
-
dest:
|
|
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:
|
|
1774
|
-
dest:
|
|
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:
|
|
1820
|
+
src: join12(
|
|
1779
1821
|
templateDir,
|
|
1780
1822
|
"flydocs",
|
|
1781
1823
|
"design-system",
|
|
1782
1824
|
"component-patterns.md"
|
|
1783
1825
|
),
|
|
1784
|
-
dest:
|
|
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:
|
|
1794
|
-
dest:
|
|
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:
|
|
1799
|
-
dest:
|
|
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 =
|
|
1855
|
+
const envExampleSrc = join12(templateDir, ".env.example");
|
|
1814
1856
|
if (await pathExists(envExampleSrc)) {
|
|
1815
|
-
const hasEnv = await pathExists(
|
|
1816
|
-
const hasEnvExample = await pathExists(
|
|
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,
|
|
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:
|
|
1922
|
+
const { execSync: execSync2, spawn } = await import("child_process");
|
|
1881
1923
|
const isInstalled = (cmd) => {
|
|
1882
1924
|
try {
|
|
1883
|
-
|
|
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
|
|
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(
|
|
2138
|
+
const hasVersion = await pathExists(join13(targetDir, ".flydocs", "version"));
|
|
2097
2139
|
const hasConfig = await pathExists(
|
|
2098
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
2192
|
+
const backupDir = join13(targetDir, ".flydocs", `backup-${ts}`);
|
|
2151
2193
|
await mkdir5(backupDir, { recursive: true });
|
|
2152
2194
|
if (hasConfig) {
|
|
2153
2195
|
await cp2(
|
|
2154
|
-
|
|
2155
|
-
|
|
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 =
|
|
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(
|
|
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
|
-
|
|
2205
|
-
|
|
2245
|
+
join13(templateDir, ".flydocs", "templates"),
|
|
2246
|
+
join13(targetDir, ".flydocs", "templates")
|
|
2206
2247
|
);
|
|
2207
2248
|
await replaceDirectory(
|
|
2208
|
-
|
|
2209
|
-
|
|
2249
|
+
join13(templateDir, ".flydocs", "hooks"),
|
|
2250
|
+
join13(targetDir, ".flydocs", "hooks")
|
|
2210
2251
|
);
|
|
2211
2252
|
await replaceDirectory(
|
|
2212
|
-
|
|
2213
|
-
|
|
2253
|
+
join13(templateDir, ".flydocs", "scripts"),
|
|
2254
|
+
join13(targetDir, ".flydocs", "scripts")
|
|
2214
2255
|
);
|
|
2215
2256
|
printStatus(".flydocs/templates, hooks, scripts");
|
|
2216
|
-
const claudeAgentsSrc =
|
|
2257
|
+
const claudeAgentsSrc = join13(templateDir, ".claude", "agents");
|
|
2217
2258
|
if (await pathExists(claudeAgentsSrc)) {
|
|
2218
2259
|
await copyDirectoryContents(
|
|
2219
2260
|
claudeAgentsSrc,
|
|
2220
|
-
|
|
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 =
|
|
2267
|
+
const cursorAgentsSrc = join13(templateDir, ".cursor", "agents");
|
|
2227
2268
|
if (await pathExists(cursorAgentsSrc)) {
|
|
2228
2269
|
await copyDirectoryContents(
|
|
2229
2270
|
cursorAgentsSrc,
|
|
2230
|
-
|
|
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
|
-
|
|
2238
|
-
|
|
2278
|
+
join13(templateDir, ".claude", "CLAUDE.md"),
|
|
2279
|
+
join13(targetDir, ".claude", "CLAUDE.md")
|
|
2239
2280
|
);
|
|
2240
2281
|
await copyFile(
|
|
2241
|
-
|
|
2242
|
-
|
|
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
|
-
|
|
2247
|
-
|
|
2287
|
+
join13(templateDir, ".claude", "commands"),
|
|
2288
|
+
join13(targetDir, ".claude", "commands")
|
|
2248
2289
|
);
|
|
2249
2290
|
await copyDirectoryContents(
|
|
2250
|
-
|
|
2251
|
-
|
|
2291
|
+
join13(templateDir, ".claude", "commands"),
|
|
2292
|
+
join13(targetDir, ".cursor", "commands")
|
|
2252
2293
|
);
|
|
2253
2294
|
printStatus(".claude/commands, .cursor/commands");
|
|
2254
|
-
const skillsReadmeSrc =
|
|
2295
|
+
const skillsReadmeSrc = join13(templateDir, ".claude", "skills", "README.md");
|
|
2255
2296
|
if (await pathExists(skillsReadmeSrc)) {
|
|
2256
2297
|
await copyFile(
|
|
2257
2298
|
skillsReadmeSrc,
|
|
2258
|
-
|
|
2299
|
+
join13(targetDir, ".claude", "skills", "README.md")
|
|
2259
2300
|
);
|
|
2260
2301
|
}
|
|
2261
2302
|
printStatus(".claude/skills/README.md");
|
|
2262
2303
|
await copyFile(
|
|
2263
|
-
|
|
2264
|
-
|
|
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
|
-
|
|
2269
|
-
|
|
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
|
-
|
|
2295
|
-
|
|
2335
|
+
join13(templateDir, ".flydocs", "version"),
|
|
2336
|
+
join13(targetDir, ".flydocs", "version")
|
|
2296
2337
|
);
|
|
2297
2338
|
printStatus(`.flydocs/version \u2192 ${version}`);
|
|
2298
|
-
const clSrc =
|
|
2339
|
+
const clSrc = join13(templateDir, "CHANGELOG.md");
|
|
2299
2340
|
if (await pathExists(clSrc)) {
|
|
2300
|
-
await copyFile(clSrc,
|
|
2341
|
+
await copyFile(clSrc, join13(targetDir, ".flydocs", "CHANGELOG.md"));
|
|
2301
2342
|
printStatus(".flydocs/CHANGELOG.md");
|
|
2302
2343
|
}
|
|
2303
|
-
const mfSrc =
|
|
2344
|
+
const mfSrc = join13(templateDir, "manifest.json");
|
|
2304
2345
|
if (await pathExists(mfSrc)) {
|
|
2305
|
-
await copyFile(mfSrc,
|
|
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
|
-
|
|
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
|
|
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(
|
|
2459
|
+
console.log(pc8.bold("Platform"));
|
|
2405
2460
|
for (const skill of result.platform) {
|
|
2406
2461
|
console.log(
|
|
2407
|
-
` ${skill.name} ${
|
|
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(
|
|
2468
|
+
console.log(pc8.bold("Community"));
|
|
2414
2469
|
for (const skill of result.community) {
|
|
2415
2470
|
console.log(
|
|
2416
|
-
` ${skill.name} ${
|
|
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: ${
|
|
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(` ${
|
|
2501
|
+
console.log(` ${pc8.bold(skill.name)}`);
|
|
2447
2502
|
console.log(` ${skill.description}`);
|
|
2448
|
-
console.log(` ${
|
|
2503
|
+
console.log(` ${pc8.dim(skill.repo)}`);
|
|
2449
2504
|
if (skill.tags.length > 0) {
|
|
2450
|
-
console.log(` ${
|
|
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
|
|
2565
|
+
import pc9 from "picocolors";
|
|
2511
2566
|
import { readFile as readFile9, writeFile as writeFile5, appendFile as appendFile2 } from "fs/promises";
|
|
2512
|
-
import { join as
|
|
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 =
|
|
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 ${
|
|
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(` ${
|
|
2622
|
+
console.log(` ${pc9.bold("Connect to Linear")}`);
|
|
2569
2623
|
console.log();
|
|
2570
2624
|
console.log(
|
|
2571
|
-
` ${
|
|
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
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
const
|
|
2607
|
-
|
|
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 =
|
|
2614
|
-
const envLocalPath =
|
|
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 ${
|
|
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 =
|
|
2648
|
-
const skillsDir =
|
|
2705
|
+
const templateSkillsDir = join14(templateDir, ".claude", "skills");
|
|
2706
|
+
const skillsDir = join14(targetDir, ".claude", "skills");
|
|
2649
2707
|
await replaceDirectory(
|
|
2650
|
-
|
|
2651
|
-
|
|
2708
|
+
join14(templateSkillsDir, "flydocs-cloud"),
|
|
2709
|
+
join14(skillsDir, "flydocs-cloud")
|
|
2652
2710
|
);
|
|
2653
2711
|
const { rm: rm5 } = await import("fs/promises");
|
|
2654
|
-
const localSkillDir =
|
|
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
|
-
` ${
|
|
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 ${
|
|
2730
|
+
` 1. Run ${pc9.cyan("/flydocs-setup")} in your IDE to configure your Linear project`
|
|
2673
2731
|
);
|
|
2674
|
-
console.log(` 2. Run ${
|
|
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
|
|
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
|
-
` ${
|
|
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 ${
|
|
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(` ${
|
|
2793
|
+
console.log(` ${pc10.bold("FlyDocs Cloud Tier")}`);
|
|
2736
2794
|
console.log();
|
|
2737
|
-
console.log(` You're currently on the ${
|
|
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
|
-
` ${
|
|
2799
|
+
` ${pc10.cyan("\u2192")} Issue sync with Linear (Jira coming soon)`
|
|
2742
2800
|
);
|
|
2743
|
-
console.log(` ${
|
|
2744
|
-
console.log(` ${
|
|
2745
|
-
console.log(` ${
|
|
2746
|
-
console.log(` ${
|
|
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(` ${
|
|
2806
|
+
console.log(` ${pc10.bold("How to upgrade:")}`);
|
|
2749
2807
|
console.log();
|
|
2750
|
-
console.log(` 1. Sign up at ${
|
|
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 ${
|
|
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
|
|
2768
|
-
import
|
|
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 ${
|
|
2840
|
+
console.log(` Updating ${pc11.cyan(PACKAGE_NAME)}...`);
|
|
2783
2841
|
console.log();
|
|
2784
2842
|
try {
|
|
2785
|
-
|
|
2843
|
+
execSync(`npm install -g ${PACKAGE_NAME}@beta`, {
|
|
2786
2844
|
stdio: "inherit",
|
|
2787
2845
|
timeout: 6e4
|
|
2788
2846
|
});
|