@flydocs/cli 0.5.0-beta.15 → 0.5.0-beta.17
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 +779 -192
- package/package.json +1 -1
- package/template/.flydocs/config.json +1 -1
- package/template/.flydocs/version +1 -1
- package/template/CHANGELOG.md +25 -0
- package/template/manifest.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11,13 +11,14 @@ var __export = (target, all) => {
|
|
|
11
11
|
|
|
12
12
|
// src/lib/constants.ts
|
|
13
13
|
import pc from "picocolors";
|
|
14
|
-
var CLI_VERSION, CLI_NAME, PACKAGE_NAME;
|
|
14
|
+
var CLI_VERSION, CLI_NAME, PACKAGE_NAME, POSTHOG_API_KEY;
|
|
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.17";
|
|
19
19
|
CLI_NAME = "flydocs";
|
|
20
20
|
PACKAGE_NAME = "@flydocs/cli";
|
|
21
|
+
POSTHOG_API_KEY = "phc_v1MSJTQDFkMS90CBh3mxIz3v8bYCCnKU6v1ir6bz0Xn";
|
|
21
22
|
}
|
|
22
23
|
});
|
|
23
24
|
|
|
@@ -360,18 +361,26 @@ async function installOwnedSkills(templateDir, targetDir, tier) {
|
|
|
360
361
|
join4(templateSkillsDir, activeMech),
|
|
361
362
|
join4(skillsDir, activeMech)
|
|
362
363
|
);
|
|
363
|
-
const { rm:
|
|
364
|
+
const { rm: rm6 } = await import("fs/promises");
|
|
364
365
|
const inactivePath = join4(skillsDir, inactiveMech);
|
|
365
366
|
if (await pathExists(inactivePath)) {
|
|
366
|
-
await
|
|
367
|
+
await rm6(inactivePath, { recursive: true, force: true });
|
|
367
368
|
}
|
|
368
|
-
for (const skill of
|
|
369
|
+
for (const skill of CORE_SKILLS) {
|
|
369
370
|
if (skill === "flydocs-workflow") continue;
|
|
370
371
|
const src = join4(templateSkillsDir, skill);
|
|
371
372
|
if (await pathExists(src)) {
|
|
372
373
|
await replaceDirectory(src, join4(skillsDir, skill));
|
|
373
374
|
}
|
|
374
375
|
}
|
|
376
|
+
if (tier === "cloud") {
|
|
377
|
+
for (const skill of CLOUD_ONLY_SKILLS) {
|
|
378
|
+
const src = join4(templateSkillsDir, skill);
|
|
379
|
+
if (await pathExists(src)) {
|
|
380
|
+
await replaceDirectory(src, join4(skillsDir, skill));
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
375
384
|
const readmeSrc = join4(templateSkillsDir, "README.md");
|
|
376
385
|
if (await pathExists(readmeSrc)) {
|
|
377
386
|
await copyFile(readmeSrc, join4(skillsDir, "README.md"));
|
|
@@ -380,18 +389,29 @@ async function installOwnedSkills(templateDir, targetDir, tier) {
|
|
|
380
389
|
async function replaceOwnedSkills(templateDir, targetDir, tier) {
|
|
381
390
|
const skillsDir = join4(targetDir, ".claude", "skills");
|
|
382
391
|
const templateSkillsDir = join4(templateDir, ".claude", "skills");
|
|
383
|
-
|
|
392
|
+
const { rm: rm6 } = await import("fs/promises");
|
|
393
|
+
for (const skill of CORE_SKILLS) {
|
|
384
394
|
const src = join4(templateSkillsDir, skill);
|
|
385
395
|
if (await pathExists(src)) {
|
|
386
396
|
await replaceDirectory(src, join4(skillsDir, skill));
|
|
387
397
|
}
|
|
388
398
|
}
|
|
389
|
-
const
|
|
399
|
+
for (const skill of CLOUD_ONLY_SKILLS) {
|
|
400
|
+
const dest = join4(skillsDir, skill);
|
|
401
|
+
if (tier === "cloud") {
|
|
402
|
+
const src = join4(templateSkillsDir, skill);
|
|
403
|
+
if (await pathExists(src)) {
|
|
404
|
+
await replaceDirectory(src, dest);
|
|
405
|
+
}
|
|
406
|
+
} else if (await pathExists(dest)) {
|
|
407
|
+
await rm6(dest, { recursive: true, force: true });
|
|
408
|
+
}
|
|
409
|
+
}
|
|
390
410
|
const activeMech = MECHANISM_SKILLS[tier];
|
|
391
411
|
const inactiveMech = tier === "local" ? MECHANISM_SKILLS.cloud : MECHANISM_SKILLS.local;
|
|
392
412
|
const inactivePath = join4(skillsDir, inactiveMech);
|
|
393
413
|
if (await pathExists(inactivePath)) {
|
|
394
|
-
await
|
|
414
|
+
await rm6(inactivePath, { recursive: true, force: true });
|
|
395
415
|
}
|
|
396
416
|
await replaceDirectory(
|
|
397
417
|
join4(templateSkillsDir, activeMech),
|
|
@@ -403,9 +423,9 @@ async function replaceOwnedSkills(templateDir, targetDir, tier) {
|
|
|
403
423
|
}
|
|
404
424
|
}
|
|
405
425
|
async function copyCursorRules(targetDir) {
|
|
406
|
-
const { mkdir:
|
|
426
|
+
const { mkdir: mkdir8 } = await import("fs/promises");
|
|
407
427
|
const rulesDir = join4(targetDir, ".cursor", "rules");
|
|
408
|
-
await
|
|
428
|
+
await mkdir8(rulesDir, { recursive: true });
|
|
409
429
|
const workflowRule = join4(
|
|
410
430
|
targetDir,
|
|
411
431
|
".claude",
|
|
@@ -439,18 +459,17 @@ async function copyCursorRules(targetDir) {
|
|
|
439
459
|
await copyFile(context7Rule, join4(rulesDir, "flydocs-context7.mdc"));
|
|
440
460
|
}
|
|
441
461
|
}
|
|
442
|
-
var
|
|
462
|
+
var CORE_SKILLS, CLOUD_ONLY_SKILLS, MECHANISM_SKILLS;
|
|
443
463
|
var init_skills = __esm({
|
|
444
464
|
"src/lib/skills.ts"() {
|
|
445
465
|
"use strict";
|
|
446
466
|
init_fs_ops();
|
|
447
|
-
|
|
467
|
+
CORE_SKILLS = [
|
|
448
468
|
"flydocs-workflow",
|
|
449
|
-
"flydocs-figma",
|
|
450
|
-
"flydocs-estimates",
|
|
451
469
|
"flydocs-context-graph",
|
|
452
470
|
"flydocs-context7"
|
|
453
471
|
];
|
|
472
|
+
CLOUD_ONLY_SKILLS = ["flydocs-figma", "flydocs-estimates"];
|
|
454
473
|
MECHANISM_SKILLS = {
|
|
455
474
|
local: "flydocs-local",
|
|
456
475
|
cloud: "flydocs-cloud"
|
|
@@ -1625,6 +1644,143 @@ var init_update_check = __esm({
|
|
|
1625
1644
|
}
|
|
1626
1645
|
});
|
|
1627
1646
|
|
|
1647
|
+
// src/lib/telemetry.ts
|
|
1648
|
+
import { readFile as readFile8, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
1649
|
+
import { randomUUID } from "crypto";
|
|
1650
|
+
import { join as join12 } from "path";
|
|
1651
|
+
import { homedir as homedir2 } from "os";
|
|
1652
|
+
async function readConfig2() {
|
|
1653
|
+
try {
|
|
1654
|
+
const raw = await readFile8(CONFIG_FILE, "utf-8");
|
|
1655
|
+
const parsed = JSON.parse(raw);
|
|
1656
|
+
if (typeof parsed === "object" && parsed !== null && "enabled" in parsed && "anonymousId" in parsed && typeof parsed.enabled === "boolean" && typeof parsed.anonymousId === "string") {
|
|
1657
|
+
return parsed;
|
|
1658
|
+
}
|
|
1659
|
+
return null;
|
|
1660
|
+
} catch {
|
|
1661
|
+
return null;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
async function writeConfig2(config) {
|
|
1665
|
+
try {
|
|
1666
|
+
await mkdir5(CONFIG_DIR, { recursive: true });
|
|
1667
|
+
await writeFile5(CONFIG_FILE, JSON.stringify(config, null, 2), "utf-8");
|
|
1668
|
+
} catch {
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
async function ensureConfig() {
|
|
1672
|
+
const existing = await readConfig2();
|
|
1673
|
+
if (existing) {
|
|
1674
|
+
return existing;
|
|
1675
|
+
}
|
|
1676
|
+
const config = {
|
|
1677
|
+
enabled: true,
|
|
1678
|
+
anonymousId: randomUUID()
|
|
1679
|
+
};
|
|
1680
|
+
await writeConfig2(config);
|
|
1681
|
+
printInfo(
|
|
1682
|
+
"Anonymous usage analytics enabled. Run `flydocs telemetry disable` to opt out."
|
|
1683
|
+
);
|
|
1684
|
+
return config;
|
|
1685
|
+
}
|
|
1686
|
+
async function isEnabled() {
|
|
1687
|
+
try {
|
|
1688
|
+
if (process.env.FLYDOCS_TELEMETRY === "0") {
|
|
1689
|
+
return false;
|
|
1690
|
+
}
|
|
1691
|
+
const config = await readConfig2();
|
|
1692
|
+
if (config) {
|
|
1693
|
+
return config.enabled;
|
|
1694
|
+
}
|
|
1695
|
+
return true;
|
|
1696
|
+
} catch {
|
|
1697
|
+
return false;
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
function baseProperties() {
|
|
1701
|
+
return {
|
|
1702
|
+
cli_version: CLI_VERSION,
|
|
1703
|
+
os: process.platform,
|
|
1704
|
+
os_arch: process.arch,
|
|
1705
|
+
node_version: process.version,
|
|
1706
|
+
is_ci: Boolean(
|
|
1707
|
+
process.env.CI || process.env.CONTINUOUS_INTEGRATION || process.env.BUILD_NUMBER
|
|
1708
|
+
),
|
|
1709
|
+
$ip: null,
|
|
1710
|
+
$process_person_profile: false
|
|
1711
|
+
};
|
|
1712
|
+
}
|
|
1713
|
+
async function capture(event, properties = {}) {
|
|
1714
|
+
try {
|
|
1715
|
+
if (!await isEnabled()) {
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
const config = await ensureConfig();
|
|
1719
|
+
eventQueue.push({
|
|
1720
|
+
event,
|
|
1721
|
+
properties: {
|
|
1722
|
+
distinct_id: config.anonymousId,
|
|
1723
|
+
...baseProperties(),
|
|
1724
|
+
...properties
|
|
1725
|
+
},
|
|
1726
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1727
|
+
});
|
|
1728
|
+
} catch {
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
async function flush() {
|
|
1732
|
+
try {
|
|
1733
|
+
if (eventQueue.length === 0) {
|
|
1734
|
+
return;
|
|
1735
|
+
}
|
|
1736
|
+
if (!await isEnabled()) {
|
|
1737
|
+
eventQueue.length = 0;
|
|
1738
|
+
return;
|
|
1739
|
+
}
|
|
1740
|
+
const batch = eventQueue.splice(0, eventQueue.length);
|
|
1741
|
+
const controller = new AbortController();
|
|
1742
|
+
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS2);
|
|
1743
|
+
await fetch(POSTHOG_BATCH_URL, {
|
|
1744
|
+
method: "POST",
|
|
1745
|
+
headers: { "Content-Type": "application/json" },
|
|
1746
|
+
body: JSON.stringify({
|
|
1747
|
+
api_key: POSTHOG_API_KEY,
|
|
1748
|
+
batch
|
|
1749
|
+
}),
|
|
1750
|
+
signal: controller.signal
|
|
1751
|
+
});
|
|
1752
|
+
clearTimeout(timeout);
|
|
1753
|
+
} catch {
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
async function setEnabled(enabled) {
|
|
1757
|
+
const config = await ensureConfig();
|
|
1758
|
+
config.enabled = enabled;
|
|
1759
|
+
await writeConfig2(config);
|
|
1760
|
+
}
|
|
1761
|
+
async function getStatus() {
|
|
1762
|
+
const envOverride = process.env.FLYDOCS_TELEMETRY === "0";
|
|
1763
|
+
const config = await readConfig2();
|
|
1764
|
+
return {
|
|
1765
|
+
enabled: config?.enabled ?? true,
|
|
1766
|
+
envOverride,
|
|
1767
|
+
anonymousId: config?.anonymousId ?? null
|
|
1768
|
+
};
|
|
1769
|
+
}
|
|
1770
|
+
var CONFIG_DIR, CONFIG_FILE, POSTHOG_BATCH_URL, FETCH_TIMEOUT_MS2, eventQueue;
|
|
1771
|
+
var init_telemetry = __esm({
|
|
1772
|
+
"src/lib/telemetry.ts"() {
|
|
1773
|
+
"use strict";
|
|
1774
|
+
init_constants();
|
|
1775
|
+
init_ui();
|
|
1776
|
+
CONFIG_DIR = join12(homedir2(), ".flydocs");
|
|
1777
|
+
CONFIG_FILE = join12(CONFIG_DIR, "telemetry.json");
|
|
1778
|
+
POSTHOG_BATCH_URL = "https://us.i.posthog.com/batch/";
|
|
1779
|
+
FETCH_TIMEOUT_MS2 = 5e3;
|
|
1780
|
+
eventQueue = [];
|
|
1781
|
+
}
|
|
1782
|
+
});
|
|
1783
|
+
|
|
1628
1784
|
// src/commands/install.ts
|
|
1629
1785
|
var install_exports = {};
|
|
1630
1786
|
__export(install_exports, {
|
|
@@ -1632,8 +1788,8 @@ __export(install_exports, {
|
|
|
1632
1788
|
});
|
|
1633
1789
|
import { defineCommand } from "citty";
|
|
1634
1790
|
import { resolve as resolve2 } from "path";
|
|
1635
|
-
import { join as
|
|
1636
|
-
import { mkdir as
|
|
1791
|
+
import { join as join13 } from "path";
|
|
1792
|
+
import { mkdir as mkdir6 } from "fs/promises";
|
|
1637
1793
|
import { confirm as confirm2, select, isCancel as isCancel3, cancel as cancel2 } from "@clack/prompts";
|
|
1638
1794
|
import pc6 from "picocolors";
|
|
1639
1795
|
var install_default;
|
|
@@ -1651,6 +1807,7 @@ var init_install = __esm({
|
|
|
1651
1807
|
init_gitignore();
|
|
1652
1808
|
init_post_install();
|
|
1653
1809
|
init_update_check();
|
|
1810
|
+
init_telemetry();
|
|
1654
1811
|
install_default = defineCommand({
|
|
1655
1812
|
meta: {
|
|
1656
1813
|
name: "install",
|
|
@@ -1686,6 +1843,7 @@ var init_install = __esm({
|
|
|
1686
1843
|
const templateDir = await resolveTemplatePath(args["local-source"]);
|
|
1687
1844
|
const version = await readTemplateVersion(templateDir);
|
|
1688
1845
|
printBanner(version);
|
|
1846
|
+
await capture("install_started", { template_version: version });
|
|
1689
1847
|
let targetDir;
|
|
1690
1848
|
if (args.path) {
|
|
1691
1849
|
targetDir = resolve2(args.path.replace(/^~/, process.env.HOME ?? "~"));
|
|
@@ -1712,7 +1870,7 @@ var init_install = __esm({
|
|
|
1712
1870
|
}
|
|
1713
1871
|
tier = args.tier;
|
|
1714
1872
|
printInfo(`Tier set via flag: ${tier}`);
|
|
1715
|
-
} else if (await pathExists(
|
|
1873
|
+
} else if (await pathExists(join13(targetDir, ".flydocs", "config.json"))) {
|
|
1716
1874
|
try {
|
|
1717
1875
|
const existing = await readConfig(targetDir);
|
|
1718
1876
|
if (existing.tier) {
|
|
@@ -1734,37 +1892,38 @@ var init_install = __esm({
|
|
|
1734
1892
|
tier = "local";
|
|
1735
1893
|
console.log();
|
|
1736
1894
|
}
|
|
1737
|
-
|
|
1895
|
+
await capture("install_tier_selected", { tier });
|
|
1896
|
+
if (!await pathExists(join13(targetDir, ".git"))) {
|
|
1738
1897
|
printWarning("No git repository detected. Run git init when ready.");
|
|
1739
1898
|
}
|
|
1740
1899
|
await ensureDirectories(targetDir, tier);
|
|
1741
1900
|
console.log("Installing framework files...");
|
|
1742
1901
|
await replaceDirectory(
|
|
1743
|
-
|
|
1744
|
-
|
|
1902
|
+
join13(templateDir, ".flydocs", "templates"),
|
|
1903
|
+
join13(targetDir, ".flydocs", "templates")
|
|
1745
1904
|
);
|
|
1746
1905
|
await replaceDirectory(
|
|
1747
|
-
|
|
1748
|
-
|
|
1906
|
+
join13(templateDir, ".flydocs", "hooks"),
|
|
1907
|
+
join13(targetDir, ".flydocs", "hooks")
|
|
1749
1908
|
);
|
|
1750
1909
|
await replaceDirectory(
|
|
1751
|
-
|
|
1752
|
-
|
|
1910
|
+
join13(templateDir, ".flydocs", "scripts"),
|
|
1911
|
+
join13(targetDir, ".flydocs", "scripts")
|
|
1753
1912
|
);
|
|
1754
1913
|
await copyFile(
|
|
1755
|
-
|
|
1756
|
-
|
|
1914
|
+
join13(templateDir, ".flydocs", "version"),
|
|
1915
|
+
join13(targetDir, ".flydocs", "version")
|
|
1757
1916
|
);
|
|
1758
|
-
const manifestSrc =
|
|
1917
|
+
const manifestSrc = join13(templateDir, "manifest.json");
|
|
1759
1918
|
if (await pathExists(manifestSrc)) {
|
|
1760
|
-
await copyFile(manifestSrc,
|
|
1919
|
+
await copyFile(manifestSrc, join13(targetDir, ".flydocs", "manifest.json"));
|
|
1761
1920
|
}
|
|
1762
|
-
const changelogSrc =
|
|
1921
|
+
const changelogSrc = join13(templateDir, "CHANGELOG.md");
|
|
1763
1922
|
if (await pathExists(changelogSrc)) {
|
|
1764
|
-
await copyFile(changelogSrc,
|
|
1923
|
+
await copyFile(changelogSrc, join13(targetDir, ".flydocs", "CHANGELOG.md"));
|
|
1765
1924
|
}
|
|
1766
1925
|
printStatus(".flydocs/templates, hooks, version, manifest, changelog");
|
|
1767
|
-
const configPath =
|
|
1926
|
+
const configPath = join13(targetDir, ".flydocs", "config.json");
|
|
1768
1927
|
if (!await pathExists(configPath)) {
|
|
1769
1928
|
const config = await createFreshConfig(templateDir, version, tier);
|
|
1770
1929
|
await writeConfig(targetDir, config);
|
|
@@ -1816,21 +1975,22 @@ var init_install = __esm({
|
|
|
1816
1975
|
installAgents = agentConfirm;
|
|
1817
1976
|
}
|
|
1818
1977
|
}
|
|
1978
|
+
await capture("install_agents_chosen", { install_agents: installAgents });
|
|
1819
1979
|
if (installAgents) {
|
|
1820
|
-
const claudeAgentsSrc =
|
|
1980
|
+
const claudeAgentsSrc = join13(templateDir, ".claude", "agents");
|
|
1821
1981
|
if (await pathExists(claudeAgentsSrc)) {
|
|
1822
|
-
await
|
|
1982
|
+
await mkdir6(join13(targetDir, ".claude", "agents"), { recursive: true });
|
|
1823
1983
|
await copyDirectoryContents(
|
|
1824
1984
|
claudeAgentsSrc,
|
|
1825
|
-
|
|
1985
|
+
join13(targetDir, ".claude", "agents")
|
|
1826
1986
|
);
|
|
1827
1987
|
}
|
|
1828
|
-
const cursorAgentsSrc =
|
|
1988
|
+
const cursorAgentsSrc = join13(templateDir, ".cursor", "agents");
|
|
1829
1989
|
if (await pathExists(cursorAgentsSrc)) {
|
|
1830
|
-
await
|
|
1990
|
+
await mkdir6(join13(targetDir, ".cursor", "agents"), { recursive: true });
|
|
1831
1991
|
await copyDirectoryContents(
|
|
1832
1992
|
cursorAgentsSrc,
|
|
1833
|
-
|
|
1993
|
+
join13(targetDir, ".cursor", "agents")
|
|
1834
1994
|
);
|
|
1835
1995
|
}
|
|
1836
1996
|
printStatus("Sub-agents installed (.claude/agents, .cursor/agents)");
|
|
@@ -1840,32 +2000,32 @@ var init_install = __esm({
|
|
|
1840
2000
|
console.log();
|
|
1841
2001
|
console.log("Installing commands and settings...");
|
|
1842
2002
|
await copyDirectoryContents(
|
|
1843
|
-
|
|
1844
|
-
|
|
2003
|
+
join13(templateDir, ".claude", "commands"),
|
|
2004
|
+
join13(targetDir, ".claude", "commands")
|
|
1845
2005
|
);
|
|
1846
2006
|
await copyFile(
|
|
1847
|
-
|
|
1848
|
-
|
|
2007
|
+
join13(templateDir, ".claude", "CLAUDE.md"),
|
|
2008
|
+
join13(targetDir, ".claude", "CLAUDE.md")
|
|
1849
2009
|
);
|
|
1850
2010
|
await copyFile(
|
|
1851
|
-
|
|
1852
|
-
|
|
2011
|
+
join13(templateDir, ".claude", "settings.json"),
|
|
2012
|
+
join13(targetDir, ".claude", "settings.json")
|
|
1853
2013
|
);
|
|
1854
2014
|
printStatus(".claude/ (commands, CLAUDE.md, settings)");
|
|
1855
2015
|
await copyDirectoryContents(
|
|
1856
|
-
|
|
1857
|
-
|
|
2016
|
+
join13(templateDir, ".claude", "commands"),
|
|
2017
|
+
join13(targetDir, ".cursor", "commands")
|
|
1858
2018
|
);
|
|
1859
2019
|
await copyFile(
|
|
1860
|
-
|
|
1861
|
-
|
|
2020
|
+
join13(templateDir, ".cursor", "hooks.json"),
|
|
2021
|
+
join13(targetDir, ".cursor", "hooks.json")
|
|
1862
2022
|
);
|
|
1863
2023
|
printStatus(".cursor/ (commands, hooks)");
|
|
1864
2024
|
await copyCursorRules(targetDir);
|
|
1865
2025
|
printStatus(".cursor/rules/");
|
|
1866
2026
|
await copyFile(
|
|
1867
|
-
|
|
1868
|
-
|
|
2027
|
+
join13(templateDir, "AGENTS.md"),
|
|
2028
|
+
join13(targetDir, "AGENTS.md")
|
|
1869
2029
|
);
|
|
1870
2030
|
printStatus("AGENTS.md");
|
|
1871
2031
|
await runManifestGeneration(targetDir);
|
|
@@ -1874,40 +2034,40 @@ var init_install = __esm({
|
|
|
1874
2034
|
console.log("Installing project templates...");
|
|
1875
2035
|
const userFiles = [
|
|
1876
2036
|
{
|
|
1877
|
-
src:
|
|
1878
|
-
dest:
|
|
2037
|
+
src: join13(templateDir, "flydocs", "context", "project.md"),
|
|
2038
|
+
dest: join13(targetDir, "flydocs", "context", "project.md"),
|
|
1879
2039
|
label: "flydocs/context/project.md"
|
|
1880
2040
|
},
|
|
1881
2041
|
{
|
|
1882
|
-
src:
|
|
1883
|
-
dest:
|
|
2042
|
+
src: join13(templateDir, "flydocs", "knowledge", "INDEX.md"),
|
|
2043
|
+
dest: join13(targetDir, "flydocs", "knowledge", "INDEX.md"),
|
|
1884
2044
|
label: "flydocs/knowledge/INDEX.md"
|
|
1885
2045
|
},
|
|
1886
2046
|
{
|
|
1887
|
-
src:
|
|
1888
|
-
dest:
|
|
2047
|
+
src: join13(templateDir, "flydocs", "knowledge", "README.md"),
|
|
2048
|
+
dest: join13(targetDir, "flydocs", "knowledge", "README.md"),
|
|
1889
2049
|
label: "flydocs/knowledge/README.md"
|
|
1890
2050
|
},
|
|
1891
2051
|
{
|
|
1892
|
-
src:
|
|
2052
|
+
src: join13(
|
|
1893
2053
|
templateDir,
|
|
1894
2054
|
"flydocs",
|
|
1895
2055
|
"knowledge",
|
|
1896
2056
|
"product",
|
|
1897
2057
|
"personas.md"
|
|
1898
2058
|
),
|
|
1899
|
-
dest:
|
|
2059
|
+
dest: join13(targetDir, "flydocs", "knowledge", "product", "personas.md"),
|
|
1900
2060
|
label: "flydocs/knowledge/product/personas.md"
|
|
1901
2061
|
},
|
|
1902
2062
|
{
|
|
1903
|
-
src:
|
|
2063
|
+
src: join13(
|
|
1904
2064
|
templateDir,
|
|
1905
2065
|
"flydocs",
|
|
1906
2066
|
"knowledge",
|
|
1907
2067
|
"product",
|
|
1908
2068
|
"user-flows.md"
|
|
1909
2069
|
),
|
|
1910
|
-
dest:
|
|
2070
|
+
dest: join13(
|
|
1911
2071
|
targetDir,
|
|
1912
2072
|
"flydocs",
|
|
1913
2073
|
"knowledge",
|
|
@@ -1917,18 +2077,18 @@ var init_install = __esm({
|
|
|
1917
2077
|
label: "flydocs/knowledge/product/user-flows.md"
|
|
1918
2078
|
},
|
|
1919
2079
|
{
|
|
1920
|
-
src:
|
|
1921
|
-
dest:
|
|
2080
|
+
src: join13(templateDir, "flydocs", "design-system", "README.md"),
|
|
2081
|
+
dest: join13(targetDir, "flydocs", "design-system", "README.md"),
|
|
1922
2082
|
label: "flydocs/design-system/README.md"
|
|
1923
2083
|
},
|
|
1924
2084
|
{
|
|
1925
|
-
src:
|
|
2085
|
+
src: join13(
|
|
1926
2086
|
templateDir,
|
|
1927
2087
|
"flydocs",
|
|
1928
2088
|
"design-system",
|
|
1929
2089
|
"component-patterns.md"
|
|
1930
2090
|
),
|
|
1931
|
-
dest:
|
|
2091
|
+
dest: join13(
|
|
1932
2092
|
targetDir,
|
|
1933
2093
|
"flydocs",
|
|
1934
2094
|
"design-system",
|
|
@@ -1937,13 +2097,13 @@ var init_install = __esm({
|
|
|
1937
2097
|
label: "flydocs/design-system/component-patterns.md"
|
|
1938
2098
|
},
|
|
1939
2099
|
{
|
|
1940
|
-
src:
|
|
1941
|
-
dest:
|
|
2100
|
+
src: join13(templateDir, "flydocs", "design-system", "token-mapping.md"),
|
|
2101
|
+
dest: join13(targetDir, "flydocs", "design-system", "token-mapping.md"),
|
|
1942
2102
|
label: "flydocs/design-system/token-mapping.md"
|
|
1943
2103
|
},
|
|
1944
2104
|
{
|
|
1945
|
-
src:
|
|
1946
|
-
dest:
|
|
2105
|
+
src: join13(templateDir, "flydocs", "README.md"),
|
|
2106
|
+
dest: join13(targetDir, "flydocs", "README.md"),
|
|
1947
2107
|
label: "flydocs/README.md"
|
|
1948
2108
|
}
|
|
1949
2109
|
];
|
|
@@ -1957,9 +2117,9 @@ var init_install = __esm({
|
|
|
1957
2117
|
}
|
|
1958
2118
|
}
|
|
1959
2119
|
}
|
|
1960
|
-
const envExampleSrc =
|
|
2120
|
+
const envExampleSrc = join13(templateDir, ".env.example");
|
|
1961
2121
|
if (await pathExists(envExampleSrc)) {
|
|
1962
|
-
await copyFile(envExampleSrc,
|
|
2122
|
+
await copyFile(envExampleSrc, join13(targetDir, ".env.example"));
|
|
1963
2123
|
printStatus(".env.example");
|
|
1964
2124
|
}
|
|
1965
2125
|
await ensureGitignore(targetDir);
|
|
@@ -1978,6 +2138,9 @@ var init_install = __esm({
|
|
|
1978
2138
|
} else {
|
|
1979
2139
|
printInfo("No framework detected in package.json");
|
|
1980
2140
|
}
|
|
2141
|
+
await capture("install_skills_chosen", {
|
|
2142
|
+
stack_detected: stack.raw
|
|
2143
|
+
});
|
|
1981
2144
|
console.log();
|
|
1982
2145
|
console.log("Checking for deprecated files...");
|
|
1983
2146
|
const deprecated = await scanDeprecated(targetDir);
|
|
@@ -2019,6 +2182,7 @@ var init_install = __esm({
|
|
|
2019
2182
|
}
|
|
2020
2183
|
printCompletionBox("Installation Complete!", nextSteps);
|
|
2021
2184
|
printBetaCta();
|
|
2185
|
+
const detectedIdes = [];
|
|
2022
2186
|
try {
|
|
2023
2187
|
const { execSync: execSync2, spawn } = await import("child_process");
|
|
2024
2188
|
const isInstalled = (cmd) => {
|
|
@@ -2054,6 +2218,7 @@ var init_install = __esm({
|
|
|
2054
2218
|
passCommand: false
|
|
2055
2219
|
});
|
|
2056
2220
|
}
|
|
2221
|
+
detectedIdes.push(...ideOptions.map((o) => o.cmd));
|
|
2057
2222
|
if (ideOptions.length === 1) {
|
|
2058
2223
|
const ide = ideOptions[0];
|
|
2059
2224
|
const launchConfirm = await confirm2({
|
|
@@ -2112,6 +2277,9 @@ var init_install = __esm({
|
|
|
2112
2277
|
}
|
|
2113
2278
|
} catch {
|
|
2114
2279
|
}
|
|
2280
|
+
await capture("install_ide_detected", { ides: detectedIdes });
|
|
2281
|
+
await capture("install_completed", { tier, version });
|
|
2282
|
+
await flush();
|
|
2115
2283
|
try {
|
|
2116
2284
|
const updateResult = await checkForUpdate();
|
|
2117
2285
|
if (updateResult) {
|
|
@@ -2130,8 +2298,8 @@ __export(update_exports, {
|
|
|
2130
2298
|
default: () => update_default
|
|
2131
2299
|
});
|
|
2132
2300
|
import { defineCommand as defineCommand2 } from "citty";
|
|
2133
|
-
import { resolve as resolve3, join as
|
|
2134
|
-
import { mkdir as
|
|
2301
|
+
import { resolve as resolve3, join as join14 } from "path";
|
|
2302
|
+
import { mkdir as mkdir7, cp as cp2, readFile as readFile9, readdir as readdir3, rm as rm4 } from "fs/promises";
|
|
2135
2303
|
import { select as select2, text, confirm as confirm3, isCancel as isCancel4, cancel as cancel3 } from "@clack/prompts";
|
|
2136
2304
|
import pc7 from "picocolors";
|
|
2137
2305
|
var update_default;
|
|
@@ -2150,6 +2318,7 @@ var init_update = __esm({
|
|
|
2150
2318
|
init_gitignore();
|
|
2151
2319
|
init_post_install();
|
|
2152
2320
|
init_update_check();
|
|
2321
|
+
init_telemetry();
|
|
2153
2322
|
update_default = defineCommand2({
|
|
2154
2323
|
meta: {
|
|
2155
2324
|
name: "update",
|
|
@@ -2192,6 +2361,7 @@ var init_update = __esm({
|
|
|
2192
2361
|
printBanner(version);
|
|
2193
2362
|
printInfo("Running in update mode \u2014 framework files will be refreshed");
|
|
2194
2363
|
console.log();
|
|
2364
|
+
await capture("update_started", { template_version: version });
|
|
2195
2365
|
let targetDir;
|
|
2196
2366
|
if (args.path) {
|
|
2197
2367
|
targetDir = resolve3(args.path.replace(/^~/, process.env.HOME ?? "~"));
|
|
@@ -2236,9 +2406,9 @@ var init_update = __esm({
|
|
|
2236
2406
|
}
|
|
2237
2407
|
targetDir = resolve3(targetDir);
|
|
2238
2408
|
process.chdir(targetDir);
|
|
2239
|
-
const hasVersion = await pathExists(
|
|
2409
|
+
const hasVersion = await pathExists(join14(targetDir, ".flydocs", "version"));
|
|
2240
2410
|
const hasConfig = await pathExists(
|
|
2241
|
-
|
|
2411
|
+
join14(targetDir, ".flydocs", "config.json")
|
|
2242
2412
|
);
|
|
2243
2413
|
if (!hasVersion && !hasConfig) {
|
|
2244
2414
|
printError(`Not a FlyDocs project: ${targetDir}`);
|
|
@@ -2249,8 +2419,8 @@ var init_update = __esm({
|
|
|
2249
2419
|
console.log();
|
|
2250
2420
|
let currentVersion = "0.1.0";
|
|
2251
2421
|
if (hasVersion) {
|
|
2252
|
-
const vContent = await
|
|
2253
|
-
|
|
2422
|
+
const vContent = await readFile9(
|
|
2423
|
+
join14(targetDir, ".flydocs", "version"),
|
|
2254
2424
|
"utf-8"
|
|
2255
2425
|
);
|
|
2256
2426
|
currentVersion = vContent.trim();
|
|
@@ -2276,9 +2446,15 @@ var init_update = __esm({
|
|
|
2276
2446
|
process.exit(0);
|
|
2277
2447
|
}
|
|
2278
2448
|
}
|
|
2449
|
+
await capture("update_version_compared", {
|
|
2450
|
+
current_version: currentVersion,
|
|
2451
|
+
target_version: version,
|
|
2452
|
+
version_status: versionStatus,
|
|
2453
|
+
force: args.force
|
|
2454
|
+
});
|
|
2279
2455
|
console.log(`Updating: v${currentVersion} \u2192 v${version}`);
|
|
2280
2456
|
console.log();
|
|
2281
|
-
const changelogPath =
|
|
2457
|
+
const changelogPath = join14(templateDir, "CHANGELOG.md");
|
|
2282
2458
|
const whatsNew = await getWhatsNew(changelogPath, currentVersion, version);
|
|
2283
2459
|
if (whatsNew.length > 0) {
|
|
2284
2460
|
console.log(pc7.cyan("What's new:"));
|
|
@@ -2290,23 +2466,23 @@ var init_update = __esm({
|
|
|
2290
2466
|
}
|
|
2291
2467
|
const now = /* @__PURE__ */ new Date();
|
|
2292
2468
|
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")}`;
|
|
2293
|
-
const backupDir =
|
|
2294
|
-
await
|
|
2469
|
+
const backupDir = join14(targetDir, ".flydocs", `backup-${ts}`);
|
|
2470
|
+
await mkdir7(backupDir, { recursive: true });
|
|
2295
2471
|
if (hasConfig) {
|
|
2296
2472
|
await cp2(
|
|
2297
|
-
|
|
2298
|
-
|
|
2473
|
+
join14(targetDir, ".flydocs", "config.json"),
|
|
2474
|
+
join14(backupDir, "config.json")
|
|
2299
2475
|
);
|
|
2300
2476
|
printStatus(`Config backed up to .flydocs/backup-${ts}/`);
|
|
2301
2477
|
}
|
|
2302
2478
|
try {
|
|
2303
|
-
const flydocsDir =
|
|
2479
|
+
const flydocsDir = join14(targetDir, ".flydocs");
|
|
2304
2480
|
const entries = await readdir3(flydocsDir);
|
|
2305
2481
|
const backups = entries.filter((e) => e.startsWith("backup-")).sort();
|
|
2306
2482
|
if (backups.length > 3) {
|
|
2307
2483
|
const toRemove = backups.slice(0, backups.length - 3);
|
|
2308
2484
|
for (const old of toRemove) {
|
|
2309
|
-
await rm4(
|
|
2485
|
+
await rm4(join14(flydocsDir, old), { recursive: true, force: true });
|
|
2310
2486
|
}
|
|
2311
2487
|
}
|
|
2312
2488
|
} catch {
|
|
@@ -2343,20 +2519,20 @@ var init_update = __esm({
|
|
|
2343
2519
|
}
|
|
2344
2520
|
console.log("Replacing framework directories...");
|
|
2345
2521
|
await replaceDirectory(
|
|
2346
|
-
|
|
2347
|
-
|
|
2522
|
+
join14(templateDir, ".flydocs", "templates"),
|
|
2523
|
+
join14(targetDir, ".flydocs", "templates")
|
|
2348
2524
|
);
|
|
2349
2525
|
await replaceDirectory(
|
|
2350
|
-
|
|
2351
|
-
|
|
2526
|
+
join14(templateDir, ".flydocs", "hooks"),
|
|
2527
|
+
join14(targetDir, ".flydocs", "hooks")
|
|
2352
2528
|
);
|
|
2353
2529
|
await replaceDirectory(
|
|
2354
|
-
|
|
2355
|
-
|
|
2530
|
+
join14(templateDir, ".flydocs", "scripts"),
|
|
2531
|
+
join14(targetDir, ".flydocs", "scripts")
|
|
2356
2532
|
);
|
|
2357
2533
|
printStatus(".flydocs/templates, hooks, scripts");
|
|
2358
2534
|
const hasExistingAgents = await pathExists(
|
|
2359
|
-
|
|
2535
|
+
join14(targetDir, ".claude", "agents")
|
|
2360
2536
|
);
|
|
2361
2537
|
let installAgents;
|
|
2362
2538
|
if (args.yes) {
|
|
@@ -2388,20 +2564,20 @@ var init_update = __esm({
|
|
|
2388
2564
|
}
|
|
2389
2565
|
}
|
|
2390
2566
|
if (installAgents) {
|
|
2391
|
-
const claudeAgentsSrc =
|
|
2567
|
+
const claudeAgentsSrc = join14(templateDir, ".claude", "agents");
|
|
2392
2568
|
if (await pathExists(claudeAgentsSrc)) {
|
|
2393
|
-
await
|
|
2569
|
+
await mkdir7(join14(targetDir, ".claude", "agents"), { recursive: true });
|
|
2394
2570
|
await copyDirectoryContents(
|
|
2395
2571
|
claudeAgentsSrc,
|
|
2396
|
-
|
|
2572
|
+
join14(targetDir, ".claude", "agents")
|
|
2397
2573
|
);
|
|
2398
2574
|
}
|
|
2399
|
-
const cursorAgentsSrc =
|
|
2575
|
+
const cursorAgentsSrc = join14(templateDir, ".cursor", "agents");
|
|
2400
2576
|
if (await pathExists(cursorAgentsSrc)) {
|
|
2401
|
-
await
|
|
2577
|
+
await mkdir7(join14(targetDir, ".cursor", "agents"), { recursive: true });
|
|
2402
2578
|
await copyDirectoryContents(
|
|
2403
2579
|
cursorAgentsSrc,
|
|
2404
|
-
|
|
2580
|
+
join14(targetDir, ".cursor", "agents")
|
|
2405
2581
|
);
|
|
2406
2582
|
}
|
|
2407
2583
|
printStatus(
|
|
@@ -2415,44 +2591,44 @@ var init_update = __esm({
|
|
|
2415
2591
|
console.log();
|
|
2416
2592
|
console.log("Replacing framework files...");
|
|
2417
2593
|
await copyFile(
|
|
2418
|
-
|
|
2419
|
-
|
|
2594
|
+
join14(templateDir, ".claude", "CLAUDE.md"),
|
|
2595
|
+
join14(targetDir, ".claude", "CLAUDE.md")
|
|
2420
2596
|
);
|
|
2421
2597
|
await copyFile(
|
|
2422
|
-
|
|
2423
|
-
|
|
2598
|
+
join14(templateDir, ".claude", "settings.json"),
|
|
2599
|
+
join14(targetDir, ".claude", "settings.json")
|
|
2424
2600
|
);
|
|
2425
2601
|
printStatus(".claude/CLAUDE.md, settings.json");
|
|
2426
2602
|
await copyDirectoryContents(
|
|
2427
|
-
|
|
2428
|
-
|
|
2603
|
+
join14(templateDir, ".claude", "commands"),
|
|
2604
|
+
join14(targetDir, ".claude", "commands")
|
|
2429
2605
|
);
|
|
2430
2606
|
await copyDirectoryContents(
|
|
2431
|
-
|
|
2432
|
-
|
|
2607
|
+
join14(templateDir, ".claude", "commands"),
|
|
2608
|
+
join14(targetDir, ".cursor", "commands")
|
|
2433
2609
|
);
|
|
2434
2610
|
printStatus(".claude/commands, .cursor/commands");
|
|
2435
|
-
const skillsReadmeSrc =
|
|
2611
|
+
const skillsReadmeSrc = join14(templateDir, ".claude", "skills", "README.md");
|
|
2436
2612
|
if (await pathExists(skillsReadmeSrc)) {
|
|
2437
2613
|
await copyFile(
|
|
2438
2614
|
skillsReadmeSrc,
|
|
2439
|
-
|
|
2615
|
+
join14(targetDir, ".claude", "skills", "README.md")
|
|
2440
2616
|
);
|
|
2441
2617
|
}
|
|
2442
2618
|
printStatus(".claude/skills/README.md");
|
|
2443
2619
|
await copyFile(
|
|
2444
|
-
|
|
2445
|
-
|
|
2620
|
+
join14(templateDir, ".cursor", "hooks.json"),
|
|
2621
|
+
join14(targetDir, ".cursor", "hooks.json")
|
|
2446
2622
|
);
|
|
2447
2623
|
printStatus(".cursor/hooks.json");
|
|
2448
2624
|
await copyFile(
|
|
2449
|
-
|
|
2450
|
-
|
|
2625
|
+
join14(templateDir, "AGENTS.md"),
|
|
2626
|
+
join14(targetDir, "AGENTS.md")
|
|
2451
2627
|
);
|
|
2452
2628
|
printStatus("AGENTS.md");
|
|
2453
|
-
const envExampleSrc =
|
|
2629
|
+
const envExampleSrc = join14(templateDir, ".env.example");
|
|
2454
2630
|
if (await pathExists(envExampleSrc)) {
|
|
2455
|
-
await copyFile(envExampleSrc,
|
|
2631
|
+
await copyFile(envExampleSrc, join14(targetDir, ".env.example"));
|
|
2456
2632
|
printStatus(".env.example");
|
|
2457
2633
|
}
|
|
2458
2634
|
await runManifestGeneration(targetDir);
|
|
@@ -2477,18 +2653,18 @@ var init_update = __esm({
|
|
|
2477
2653
|
printWarning("Config merge failed \u2014 config.json preserved as-is");
|
|
2478
2654
|
}
|
|
2479
2655
|
await copyFile(
|
|
2480
|
-
|
|
2481
|
-
|
|
2656
|
+
join14(templateDir, ".flydocs", "version"),
|
|
2657
|
+
join14(targetDir, ".flydocs", "version")
|
|
2482
2658
|
);
|
|
2483
2659
|
printStatus(`.flydocs/version \u2192 ${version}`);
|
|
2484
|
-
const clSrc =
|
|
2660
|
+
const clSrc = join14(templateDir, "CHANGELOG.md");
|
|
2485
2661
|
if (await pathExists(clSrc)) {
|
|
2486
|
-
await copyFile(clSrc,
|
|
2662
|
+
await copyFile(clSrc, join14(targetDir, ".flydocs", "CHANGELOG.md"));
|
|
2487
2663
|
printStatus(".flydocs/CHANGELOG.md");
|
|
2488
2664
|
}
|
|
2489
|
-
const mfSrc =
|
|
2665
|
+
const mfSrc = join14(templateDir, "manifest.json");
|
|
2490
2666
|
if (await pathExists(mfSrc)) {
|
|
2491
|
-
await copyFile(mfSrc,
|
|
2667
|
+
await copyFile(mfSrc, join14(targetDir, ".flydocs", "manifest.json"));
|
|
2492
2668
|
printStatus(".flydocs/manifest.json");
|
|
2493
2669
|
}
|
|
2494
2670
|
console.log();
|
|
@@ -2524,6 +2700,12 @@ var init_update = __esm({
|
|
|
2524
2700
|
`Backup: .flydocs/backup-${ts}/`
|
|
2525
2701
|
]);
|
|
2526
2702
|
printBetaCta();
|
|
2703
|
+
await capture("update_completed", {
|
|
2704
|
+
current_version: currentVersion,
|
|
2705
|
+
version,
|
|
2706
|
+
tier: effectiveTier
|
|
2707
|
+
});
|
|
2708
|
+
await flush();
|
|
2527
2709
|
try {
|
|
2528
2710
|
const updateResult = await checkForUpdate();
|
|
2529
2711
|
if (updateResult) {
|
|
@@ -2536,33 +2718,336 @@ var init_update = __esm({
|
|
|
2536
2718
|
}
|
|
2537
2719
|
});
|
|
2538
2720
|
|
|
2721
|
+
// src/commands/uninstall.ts
|
|
2722
|
+
var uninstall_exports = {};
|
|
2723
|
+
__export(uninstall_exports, {
|
|
2724
|
+
default: () => uninstall_default
|
|
2725
|
+
});
|
|
2726
|
+
import { defineCommand as defineCommand3 } from "citty";
|
|
2727
|
+
import { resolve as resolve4, join as join15 } from "path";
|
|
2728
|
+
import { readdir as readdir4, rm as rm5, rename as rename2 } from "fs/promises";
|
|
2729
|
+
import { confirm as confirm4, select as select3, isCancel as isCancel5, cancel as cancel4 } from "@clack/prompts";
|
|
2730
|
+
import pc8 from "picocolors";
|
|
2731
|
+
async function removeOwnedSkills(targetDir) {
|
|
2732
|
+
const skillsDir = join15(targetDir, ".claude", "skills");
|
|
2733
|
+
const removed = [];
|
|
2734
|
+
if (!await pathExists(skillsDir)) {
|
|
2735
|
+
return removed;
|
|
2736
|
+
}
|
|
2737
|
+
try {
|
|
2738
|
+
const entries = await readdir4(skillsDir);
|
|
2739
|
+
for (const entry of entries) {
|
|
2740
|
+
if (entry.startsWith(OWNED_SKILL_PREFIX)) {
|
|
2741
|
+
await rm5(join15(skillsDir, entry), { recursive: true, force: true });
|
|
2742
|
+
removed.push(`.claude/skills/${entry}`);
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
} catch {
|
|
2746
|
+
}
|
|
2747
|
+
return removed;
|
|
2748
|
+
}
|
|
2749
|
+
async function removeOwnedCursorRules(targetDir) {
|
|
2750
|
+
const rulesDir = join15(targetDir, ".cursor", "rules");
|
|
2751
|
+
const removed = [];
|
|
2752
|
+
if (!await pathExists(rulesDir)) {
|
|
2753
|
+
return removed;
|
|
2754
|
+
}
|
|
2755
|
+
try {
|
|
2756
|
+
const entries = await readdir4(rulesDir);
|
|
2757
|
+
for (const entry of entries) {
|
|
2758
|
+
if (entry.startsWith(OWNED_RULE_PREFIX) && entry.endsWith(".mdc")) {
|
|
2759
|
+
await rm5(join15(rulesDir, entry), { force: true });
|
|
2760
|
+
removed.push(`.cursor/rules/${entry}`);
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
} catch {
|
|
2764
|
+
}
|
|
2765
|
+
return removed;
|
|
2766
|
+
}
|
|
2767
|
+
async function isEmptyDir(dirPath) {
|
|
2768
|
+
try {
|
|
2769
|
+
const entries = await readdir4(dirPath);
|
|
2770
|
+
return entries.length === 0;
|
|
2771
|
+
} catch {
|
|
2772
|
+
return false;
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
async function cleanupEmptyParents(targetDir, dirs) {
|
|
2776
|
+
const cleaned = [];
|
|
2777
|
+
for (const dir of dirs) {
|
|
2778
|
+
const fullPath = join15(targetDir, dir);
|
|
2779
|
+
if (await pathExists(fullPath) && await isEmptyDir(fullPath)) {
|
|
2780
|
+
await rm5(fullPath, { recursive: true, force: true });
|
|
2781
|
+
cleaned.push(dir);
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
return cleaned;
|
|
2785
|
+
}
|
|
2786
|
+
var ALWAYS_REMOVED, OWNED_SKILL_PREFIX, OWNED_RULE_PREFIX, uninstall_default;
|
|
2787
|
+
var init_uninstall = __esm({
|
|
2788
|
+
"src/commands/uninstall.ts"() {
|
|
2789
|
+
"use strict";
|
|
2790
|
+
init_fs_ops();
|
|
2791
|
+
init_ui();
|
|
2792
|
+
init_constants();
|
|
2793
|
+
ALWAYS_REMOVED = [
|
|
2794
|
+
[".claude/CLAUDE.md", "file"],
|
|
2795
|
+
[".claude/settings.json", "file"],
|
|
2796
|
+
[".claude/agents", "dir"],
|
|
2797
|
+
[".claude/commands", "dir"],
|
|
2798
|
+
[".claude/skills/README.md", "file"],
|
|
2799
|
+
[".cursor/hooks.json", "file"],
|
|
2800
|
+
[".cursor/agents", "dir"],
|
|
2801
|
+
[".flydocs", "dir"],
|
|
2802
|
+
["AGENTS.md", "file"],
|
|
2803
|
+
[".env.example", "file"]
|
|
2804
|
+
];
|
|
2805
|
+
OWNED_SKILL_PREFIX = "flydocs-";
|
|
2806
|
+
OWNED_RULE_PREFIX = "flydocs-";
|
|
2807
|
+
uninstall_default = defineCommand3({
|
|
2808
|
+
meta: {
|
|
2809
|
+
name: "uninstall",
|
|
2810
|
+
description: "Remove FlyDocs from a project directory"
|
|
2811
|
+
},
|
|
2812
|
+
args: {
|
|
2813
|
+
path: {
|
|
2814
|
+
type: "string",
|
|
2815
|
+
description: "Uninstall from the specified directory"
|
|
2816
|
+
},
|
|
2817
|
+
here: {
|
|
2818
|
+
type: "boolean",
|
|
2819
|
+
description: "Uninstall from the current directory",
|
|
2820
|
+
default: false
|
|
2821
|
+
},
|
|
2822
|
+
all: {
|
|
2823
|
+
type: "boolean",
|
|
2824
|
+
description: "Remove everything including flydocs/ user content",
|
|
2825
|
+
default: false
|
|
2826
|
+
},
|
|
2827
|
+
yes: {
|
|
2828
|
+
type: "boolean",
|
|
2829
|
+
alias: ["y"],
|
|
2830
|
+
description: "Skip confirmation prompts",
|
|
2831
|
+
default: false
|
|
2832
|
+
},
|
|
2833
|
+
force: {
|
|
2834
|
+
type: "boolean",
|
|
2835
|
+
description: "Alias for --all --yes (complete removal, no prompts)",
|
|
2836
|
+
default: false
|
|
2837
|
+
}
|
|
2838
|
+
},
|
|
2839
|
+
async run({ args }) {
|
|
2840
|
+
printBanner(CLI_VERSION);
|
|
2841
|
+
let targetDir;
|
|
2842
|
+
if (args.path) {
|
|
2843
|
+
targetDir = resolve4(args.path.replace(/^~/, process.env.HOME ?? "~"));
|
|
2844
|
+
} else if (args.here) {
|
|
2845
|
+
targetDir = process.cwd();
|
|
2846
|
+
} else {
|
|
2847
|
+
targetDir = process.cwd();
|
|
2848
|
+
}
|
|
2849
|
+
if (!await pathExists(targetDir)) {
|
|
2850
|
+
printError(`Directory does not exist: ${targetDir}`);
|
|
2851
|
+
process.exit(1);
|
|
2852
|
+
}
|
|
2853
|
+
targetDir = resolve4(targetDir);
|
|
2854
|
+
const hasFlydocs = await pathExists(join15(targetDir, ".flydocs"));
|
|
2855
|
+
const hasAgentsMd = await pathExists(join15(targetDir, "AGENTS.md"));
|
|
2856
|
+
if (!hasFlydocs && !hasAgentsMd) {
|
|
2857
|
+
printError(`Not a FlyDocs project: ${targetDir}`);
|
|
2858
|
+
printInfo("No .flydocs/ directory or AGENTS.md found.");
|
|
2859
|
+
process.exit(1);
|
|
2860
|
+
}
|
|
2861
|
+
printInfo(`Project: ${targetDir}`);
|
|
2862
|
+
console.log();
|
|
2863
|
+
const forceAll = args.force;
|
|
2864
|
+
const removeAll = forceAll || args.all;
|
|
2865
|
+
const skipPrompts = forceAll || args.yes;
|
|
2866
|
+
let contentAction = "preserve";
|
|
2867
|
+
const hasUserContent = await pathExists(join15(targetDir, "flydocs"));
|
|
2868
|
+
if (hasUserContent) {
|
|
2869
|
+
if (removeAll) {
|
|
2870
|
+
contentAction = "remove";
|
|
2871
|
+
} else if (!skipPrompts) {
|
|
2872
|
+
const choice = await select3({
|
|
2873
|
+
message: "What should happen to your flydocs/ content (project docs, knowledge base)?",
|
|
2874
|
+
options: [
|
|
2875
|
+
{
|
|
2876
|
+
value: "archive",
|
|
2877
|
+
label: "Archive",
|
|
2878
|
+
hint: "Rename to flydocs-archive/ (safe, reversible)"
|
|
2879
|
+
},
|
|
2880
|
+
{
|
|
2881
|
+
value: "remove",
|
|
2882
|
+
label: "Remove completely",
|
|
2883
|
+
hint: "Permanently delete flydocs/ and all contents"
|
|
2884
|
+
},
|
|
2885
|
+
{
|
|
2886
|
+
value: "preserve",
|
|
2887
|
+
label: "Keep as-is",
|
|
2888
|
+
hint: "Leave flydocs/ untouched"
|
|
2889
|
+
}
|
|
2890
|
+
]
|
|
2891
|
+
});
|
|
2892
|
+
if (isCancel5(choice)) {
|
|
2893
|
+
cancel4("Uninstall cancelled.");
|
|
2894
|
+
process.exit(0);
|
|
2895
|
+
}
|
|
2896
|
+
contentAction = choice;
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
if (!skipPrompts) {
|
|
2900
|
+
console.log();
|
|
2901
|
+
console.log(pc8.bold("The following will be removed:"));
|
|
2902
|
+
console.log();
|
|
2903
|
+
console.log(" Framework files:");
|
|
2904
|
+
for (const [path] of ALWAYS_REMOVED) {
|
|
2905
|
+
console.log(` ${pc8.dim(path)}`);
|
|
2906
|
+
}
|
|
2907
|
+
console.log(` ${pc8.dim(".claude/skills/flydocs-*")}`);
|
|
2908
|
+
console.log(` ${pc8.dim(".cursor/rules/flydocs-*.mdc")}`);
|
|
2909
|
+
if (hasUserContent) {
|
|
2910
|
+
if (contentAction === "archive") {
|
|
2911
|
+
console.log();
|
|
2912
|
+
console.log(
|
|
2913
|
+
` User content: ${pc8.yellow("flydocs/ -> flydocs-archive/")}`
|
|
2914
|
+
);
|
|
2915
|
+
} else if (contentAction === "remove") {
|
|
2916
|
+
console.log();
|
|
2917
|
+
console.log(` User content: ${pc8.red("flydocs/ (deleted)")}`);
|
|
2918
|
+
} else {
|
|
2919
|
+
console.log();
|
|
2920
|
+
console.log(` User content: ${pc8.green("flydocs/ (preserved)")}`);
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
console.log();
|
|
2924
|
+
console.log(pc8.bold("Preserved:"));
|
|
2925
|
+
console.log(
|
|
2926
|
+
` ${pc8.dim(".claude/skills/ (non-flydocs community skills)")}`
|
|
2927
|
+
);
|
|
2928
|
+
console.log(` ${pc8.dim(".env, .env.local")}`);
|
|
2929
|
+
console.log();
|
|
2930
|
+
const shouldContinue = await confirm4({
|
|
2931
|
+
message: "Proceed with uninstall?"
|
|
2932
|
+
});
|
|
2933
|
+
if (isCancel5(shouldContinue) || !shouldContinue) {
|
|
2934
|
+
cancel4("Uninstall cancelled.");
|
|
2935
|
+
process.exit(0);
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
const result = {
|
|
2939
|
+
removed: [],
|
|
2940
|
+
skipped: [],
|
|
2941
|
+
archived: []
|
|
2942
|
+
};
|
|
2943
|
+
const removedSkills = await removeOwnedSkills(targetDir);
|
|
2944
|
+
result.removed.push(...removedSkills);
|
|
2945
|
+
const removedRules = await removeOwnedCursorRules(targetDir);
|
|
2946
|
+
result.removed.push(...removedRules);
|
|
2947
|
+
for (const [relativePath, type] of ALWAYS_REMOVED) {
|
|
2948
|
+
const fullPath = join15(targetDir, relativePath);
|
|
2949
|
+
if (!await pathExists(fullPath)) {
|
|
2950
|
+
result.skipped.push(relativePath);
|
|
2951
|
+
continue;
|
|
2952
|
+
}
|
|
2953
|
+
try {
|
|
2954
|
+
if (type === "dir") {
|
|
2955
|
+
await rm5(fullPath, { recursive: true, force: true });
|
|
2956
|
+
} else {
|
|
2957
|
+
await rm5(fullPath, { force: true });
|
|
2958
|
+
}
|
|
2959
|
+
result.removed.push(relativePath);
|
|
2960
|
+
} catch {
|
|
2961
|
+
printWarning(`Could not remove: ${relativePath}`);
|
|
2962
|
+
result.skipped.push(relativePath);
|
|
2963
|
+
}
|
|
2964
|
+
}
|
|
2965
|
+
if (hasUserContent) {
|
|
2966
|
+
const flydocsPath = join15(targetDir, "flydocs");
|
|
2967
|
+
if (contentAction === "archive") {
|
|
2968
|
+
const archivePath = join15(targetDir, "flydocs-archive");
|
|
2969
|
+
if (await pathExists(archivePath)) {
|
|
2970
|
+
await rm5(archivePath, { recursive: true, force: true });
|
|
2971
|
+
}
|
|
2972
|
+
await rename2(flydocsPath, archivePath);
|
|
2973
|
+
result.archived.push("flydocs/ -> flydocs-archive/");
|
|
2974
|
+
} else if (contentAction === "remove") {
|
|
2975
|
+
await rm5(flydocsPath, { recursive: true, force: true });
|
|
2976
|
+
result.removed.push("flydocs/");
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
const emptyCandidates = [
|
|
2980
|
+
".claude/skills",
|
|
2981
|
+
".claude",
|
|
2982
|
+
".cursor/rules",
|
|
2983
|
+
".cursor"
|
|
2984
|
+
];
|
|
2985
|
+
const cleaned = await cleanupEmptyParents(targetDir, emptyCandidates);
|
|
2986
|
+
for (const dir of cleaned) {
|
|
2987
|
+
result.removed.push(`${dir}/ (empty, cleaned up)`);
|
|
2988
|
+
}
|
|
2989
|
+
console.log();
|
|
2990
|
+
console.log(pc8.bold("Uninstall Summary"));
|
|
2991
|
+
console.log();
|
|
2992
|
+
if (result.removed.length > 0) {
|
|
2993
|
+
console.log(` ${pc8.green("Removed")} (${result.removed.length}):`);
|
|
2994
|
+
for (const item of result.removed) {
|
|
2995
|
+
printStatus(item);
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
if (result.archived.length > 0) {
|
|
2999
|
+
console.log();
|
|
3000
|
+
console.log(` ${pc8.yellow("Archived")} (${result.archived.length}):`);
|
|
3001
|
+
for (const item of result.archived) {
|
|
3002
|
+
printInfo(item);
|
|
3003
|
+
}
|
|
3004
|
+
}
|
|
3005
|
+
if (result.skipped.length > 0) {
|
|
3006
|
+
console.log();
|
|
3007
|
+
console.log(
|
|
3008
|
+
` ${pc8.dim("Skipped")} (${result.skipped.length} \u2014 not found):`
|
|
3009
|
+
);
|
|
3010
|
+
for (const item of result.skipped) {
|
|
3011
|
+
console.log(` ${pc8.dim(item)}`);
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
console.log();
|
|
3015
|
+
printStatus("FlyDocs has been removed from this project.");
|
|
3016
|
+
console.log();
|
|
3017
|
+
printInfo(`To reinstall: ${pc8.cyan("npx @flydocs/cli install --here")}`);
|
|
3018
|
+
console.log();
|
|
3019
|
+
}
|
|
3020
|
+
});
|
|
3021
|
+
}
|
|
3022
|
+
});
|
|
3023
|
+
|
|
2539
3024
|
// src/commands/setup.ts
|
|
2540
3025
|
var setup_exports = {};
|
|
2541
3026
|
__export(setup_exports, {
|
|
2542
3027
|
default: () => setup_default
|
|
2543
3028
|
});
|
|
2544
|
-
import { defineCommand as
|
|
2545
|
-
import
|
|
3029
|
+
import { defineCommand as defineCommand4 } from "citty";
|
|
3030
|
+
import pc9 from "picocolors";
|
|
2546
3031
|
var setup_default;
|
|
2547
3032
|
var init_setup = __esm({
|
|
2548
3033
|
"src/commands/setup.ts"() {
|
|
2549
3034
|
"use strict";
|
|
2550
|
-
setup_default =
|
|
3035
|
+
setup_default = defineCommand4({
|
|
2551
3036
|
meta: {
|
|
2552
3037
|
name: "setup",
|
|
2553
3038
|
description: "Configure FlyDocs settings for this project"
|
|
2554
3039
|
},
|
|
2555
3040
|
run() {
|
|
2556
3041
|
console.log();
|
|
2557
|
-
console.log(` ${
|
|
3042
|
+
console.log(` ${pc9.bold("FlyDocs Setup")}`);
|
|
2558
3043
|
console.log();
|
|
2559
3044
|
console.log(` Setup runs inside your IDE as an interactive AI command.`);
|
|
2560
3045
|
console.log();
|
|
2561
3046
|
console.log(
|
|
2562
|
-
` ${
|
|
3047
|
+
` ${pc9.cyan("Claude Code:")} Type ${pc9.bold("/flydocs-setup")} in chat`
|
|
2563
3048
|
);
|
|
2564
3049
|
console.log(
|
|
2565
|
-
` ${
|
|
3050
|
+
` ${pc9.cyan("Cursor:")} Type ${pc9.bold("/flydocs-setup")} in chat`
|
|
2566
3051
|
);
|
|
2567
3052
|
console.log();
|
|
2568
3053
|
console.log(` This configures your project context, detects your stack,`);
|
|
@@ -2578,14 +3063,14 @@ var skills_exports = {};
|
|
|
2578
3063
|
__export(skills_exports, {
|
|
2579
3064
|
default: () => skills_default
|
|
2580
3065
|
});
|
|
2581
|
-
import { defineCommand as
|
|
2582
|
-
import
|
|
3066
|
+
import { defineCommand as defineCommand5 } from "citty";
|
|
3067
|
+
import pc10 from "picocolors";
|
|
2583
3068
|
var list, search, add, remove, skills_default;
|
|
2584
3069
|
var init_skills2 = __esm({
|
|
2585
3070
|
"src/commands/skills.ts"() {
|
|
2586
3071
|
"use strict";
|
|
2587
3072
|
init_skill_manager();
|
|
2588
|
-
list =
|
|
3073
|
+
list = defineCommand5({
|
|
2589
3074
|
meta: {
|
|
2590
3075
|
name: "list",
|
|
2591
3076
|
description: "List installed skills"
|
|
@@ -2601,26 +3086,26 @@ var init_skills2 = __esm({
|
|
|
2601
3086
|
console.log(`${total} skill(s) installed:`);
|
|
2602
3087
|
if (result.platform.length > 0) {
|
|
2603
3088
|
console.log();
|
|
2604
|
-
console.log(
|
|
3089
|
+
console.log(pc10.bold("Platform"));
|
|
2605
3090
|
for (const skill of result.platform) {
|
|
2606
3091
|
console.log(
|
|
2607
|
-
` ${skill.name} ${
|
|
3092
|
+
` ${skill.name} ${pc10.dim(`(${skill.triggers} triggers)`)}`
|
|
2608
3093
|
);
|
|
2609
3094
|
}
|
|
2610
3095
|
}
|
|
2611
3096
|
if (result.community.length > 0) {
|
|
2612
3097
|
console.log();
|
|
2613
|
-
console.log(
|
|
3098
|
+
console.log(pc10.bold("Community"));
|
|
2614
3099
|
for (const skill of result.community) {
|
|
2615
3100
|
console.log(
|
|
2616
|
-
` ${skill.name} ${
|
|
3101
|
+
` ${skill.name} ${pc10.dim(`(${skill.triggers} triggers)`)}`
|
|
2617
3102
|
);
|
|
2618
3103
|
}
|
|
2619
3104
|
}
|
|
2620
3105
|
console.log();
|
|
2621
3106
|
}
|
|
2622
3107
|
});
|
|
2623
|
-
search =
|
|
3108
|
+
search = defineCommand5({
|
|
2624
3109
|
meta: {
|
|
2625
3110
|
name: "search",
|
|
2626
3111
|
description: "Search community skills"
|
|
@@ -2636,24 +3121,24 @@ var init_skills2 = __esm({
|
|
|
2636
3121
|
const results = await searchCatalog(args.keyword);
|
|
2637
3122
|
if (results.length === 0) {
|
|
2638
3123
|
console.log(`No skills found for "${args.keyword}".`);
|
|
2639
|
-
console.log(` Browse the catalog at: ${
|
|
3124
|
+
console.log(` Browse the catalog at: ${pc10.cyan("https://skills.sh/")}`);
|
|
2640
3125
|
return;
|
|
2641
3126
|
}
|
|
2642
3127
|
console.log();
|
|
2643
3128
|
console.log(`${results.length} skill(s) matching "${args.keyword}":`);
|
|
2644
3129
|
console.log();
|
|
2645
3130
|
for (const skill of results) {
|
|
2646
|
-
console.log(` ${
|
|
3131
|
+
console.log(` ${pc10.bold(skill.name)}`);
|
|
2647
3132
|
console.log(` ${skill.description}`);
|
|
2648
|
-
console.log(` ${
|
|
3133
|
+
console.log(` ${pc10.dim(skill.repo)}`);
|
|
2649
3134
|
if (skill.tags.length > 0) {
|
|
2650
|
-
console.log(` ${
|
|
3135
|
+
console.log(` ${pc10.dim(skill.tags.join(", "))}`);
|
|
2651
3136
|
}
|
|
2652
3137
|
console.log();
|
|
2653
3138
|
}
|
|
2654
3139
|
}
|
|
2655
3140
|
});
|
|
2656
|
-
add =
|
|
3141
|
+
add = defineCommand5({
|
|
2657
3142
|
meta: {
|
|
2658
3143
|
name: "add",
|
|
2659
3144
|
description: "Install a community skill"
|
|
@@ -2669,7 +3154,7 @@ var init_skills2 = __esm({
|
|
|
2669
3154
|
await addSkill(process.cwd(), args.source);
|
|
2670
3155
|
}
|
|
2671
3156
|
});
|
|
2672
|
-
remove =
|
|
3157
|
+
remove = defineCommand5({
|
|
2673
3158
|
meta: {
|
|
2674
3159
|
name: "remove",
|
|
2675
3160
|
description: "Remove an installed community skill"
|
|
@@ -2685,7 +3170,7 @@ var init_skills2 = __esm({
|
|
|
2685
3170
|
await removeSkill(process.cwd(), args.name);
|
|
2686
3171
|
}
|
|
2687
3172
|
});
|
|
2688
|
-
skills_default =
|
|
3173
|
+
skills_default = defineCommand5({
|
|
2689
3174
|
meta: {
|
|
2690
3175
|
name: "skills",
|
|
2691
3176
|
description: "Manage FlyDocs skills (list, search, add, remove)"
|
|
@@ -2705,11 +3190,11 @@ var connect_exports = {};
|
|
|
2705
3190
|
__export(connect_exports, {
|
|
2706
3191
|
default: () => connect_default
|
|
2707
3192
|
});
|
|
2708
|
-
import { defineCommand as
|
|
2709
|
-
import { text as text2, confirm as
|
|
2710
|
-
import
|
|
2711
|
-
import { readFile as
|
|
2712
|
-
import { join as
|
|
3193
|
+
import { defineCommand as defineCommand6 } from "citty";
|
|
3194
|
+
import { text as text2, confirm as confirm5, isCancel as isCancel6, cancel as cancel5 } from "@clack/prompts";
|
|
3195
|
+
import pc11 from "picocolors";
|
|
3196
|
+
import { readFile as readFile10, writeFile as writeFile6, appendFile as appendFile2 } from "fs/promises";
|
|
3197
|
+
import { join as join16 } from "path";
|
|
2713
3198
|
var connect_default;
|
|
2714
3199
|
var init_connect = __esm({
|
|
2715
3200
|
"src/commands/connect.ts"() {
|
|
@@ -2718,7 +3203,7 @@ var init_connect = __esm({
|
|
|
2718
3203
|
init_fs_ops();
|
|
2719
3204
|
init_template();
|
|
2720
3205
|
init_ui();
|
|
2721
|
-
connect_default =
|
|
3206
|
+
connect_default = defineCommand6({
|
|
2722
3207
|
meta: {
|
|
2723
3208
|
name: "connect",
|
|
2724
3209
|
description: "Connect FlyDocs to a cloud provider (Linear)"
|
|
@@ -2743,11 +3228,11 @@ var init_connect = __esm({
|
|
|
2743
3228
|
},
|
|
2744
3229
|
async run({ args }) {
|
|
2745
3230
|
const targetDir = args.path ?? process.cwd();
|
|
2746
|
-
const configPath =
|
|
3231
|
+
const configPath = join16(targetDir, ".flydocs", "config.json");
|
|
2747
3232
|
if (!await pathExists(configPath)) {
|
|
2748
3233
|
printError("Not a FlyDocs project (.flydocs/config.json not found).");
|
|
2749
3234
|
console.log(
|
|
2750
|
-
` Run ${
|
|
3235
|
+
` Run ${pc11.cyan("flydocs")} first to install FlyDocs in this project.`
|
|
2751
3236
|
);
|
|
2752
3237
|
process.exit(1);
|
|
2753
3238
|
}
|
|
@@ -2755,19 +3240,19 @@ var init_connect = __esm({
|
|
|
2755
3240
|
if (config.tier === "cloud") {
|
|
2756
3241
|
printInfo("This project is already connected to the cloud tier.");
|
|
2757
3242
|
console.log();
|
|
2758
|
-
const reconnect = await
|
|
3243
|
+
const reconnect = await confirm5({
|
|
2759
3244
|
message: "Want to update your API key?"
|
|
2760
3245
|
});
|
|
2761
|
-
if (
|
|
3246
|
+
if (isCancel6(reconnect) || !reconnect) {
|
|
2762
3247
|
console.log(` No changes made.`);
|
|
2763
3248
|
return;
|
|
2764
3249
|
}
|
|
2765
3250
|
}
|
|
2766
3251
|
console.log();
|
|
2767
|
-
console.log(` ${
|
|
3252
|
+
console.log(` ${pc11.bold("Connect to Linear")}`);
|
|
2768
3253
|
console.log();
|
|
2769
3254
|
console.log(
|
|
2770
|
-
` ${
|
|
3255
|
+
` ${pc11.dim("Get your API key from: Linear \u2192 Settings \u2192 API \u2192 Personal API keys")}`
|
|
2771
3256
|
);
|
|
2772
3257
|
console.log();
|
|
2773
3258
|
let apiKey = args.key ?? "";
|
|
@@ -2782,8 +3267,8 @@ var init_connect = __esm({
|
|
|
2782
3267
|
return void 0;
|
|
2783
3268
|
}
|
|
2784
3269
|
});
|
|
2785
|
-
if (
|
|
2786
|
-
|
|
3270
|
+
if (isCancel6(keyInput)) {
|
|
3271
|
+
cancel5("Connection cancelled.");
|
|
2787
3272
|
process.exit(0);
|
|
2788
3273
|
}
|
|
2789
3274
|
apiKey = keyInput;
|
|
@@ -2807,34 +3292,34 @@ var init_connect = __esm({
|
|
|
2807
3292
|
throw new Error("Invalid response");
|
|
2808
3293
|
}
|
|
2809
3294
|
const viewer = data.data.viewer;
|
|
2810
|
-
printStatus(`Authenticated as ${
|
|
3295
|
+
printStatus(`Authenticated as ${pc11.bold(viewer.name)} (${viewer.email})`);
|
|
2811
3296
|
} catch {
|
|
2812
3297
|
printError("Invalid API key or network error.");
|
|
2813
3298
|
console.log(` Check your key and try again.`);
|
|
2814
3299
|
process.exit(1);
|
|
2815
3300
|
}
|
|
2816
|
-
const envPath =
|
|
2817
|
-
const envLocalPath =
|
|
3301
|
+
const envPath = join16(targetDir, ".env");
|
|
3302
|
+
const envLocalPath = join16(targetDir, ".env.local");
|
|
2818
3303
|
const targetEnvPath = await pathExists(envLocalPath) ? envLocalPath : envPath;
|
|
2819
3304
|
if (await pathExists(targetEnvPath)) {
|
|
2820
|
-
const envContent = await
|
|
3305
|
+
const envContent = await readFile10(targetEnvPath, "utf-8");
|
|
2821
3306
|
if (envContent.includes("LINEAR_API_KEY=")) {
|
|
2822
3307
|
const updated = envContent.replace(
|
|
2823
3308
|
/LINEAR_API_KEY=.*/,
|
|
2824
3309
|
`LINEAR_API_KEY=${apiKey}`
|
|
2825
3310
|
);
|
|
2826
|
-
await
|
|
3311
|
+
await writeFile6(targetEnvPath, updated, "utf-8");
|
|
2827
3312
|
} else {
|
|
2828
3313
|
await appendFile2(targetEnvPath, `
|
|
2829
3314
|
LINEAR_API_KEY=${apiKey}
|
|
2830
3315
|
`);
|
|
2831
3316
|
}
|
|
2832
3317
|
} else {
|
|
2833
|
-
await
|
|
3318
|
+
await writeFile6(targetEnvPath, `LINEAR_API_KEY=${apiKey}
|
|
2834
3319
|
`, "utf-8");
|
|
2835
3320
|
}
|
|
2836
3321
|
printStatus(
|
|
2837
|
-
`API key stored in ${
|
|
3322
|
+
`API key stored in ${pc11.dim(targetEnvPath === envLocalPath ? ".env.local" : ".env")}`
|
|
2838
3323
|
);
|
|
2839
3324
|
const wasLocal = config.tier === "local";
|
|
2840
3325
|
config.tier = "cloud";
|
|
@@ -2847,16 +3332,16 @@ LINEAR_API_KEY=${apiKey}
|
|
|
2847
3332
|
const templateDir = await resolveTemplatePath(
|
|
2848
3333
|
args["local-source"] || void 0
|
|
2849
3334
|
);
|
|
2850
|
-
const templateSkillsDir =
|
|
2851
|
-
const skillsDir =
|
|
3335
|
+
const templateSkillsDir = join16(templateDir, ".claude", "skills");
|
|
3336
|
+
const skillsDir = join16(targetDir, ".claude", "skills");
|
|
2852
3337
|
await replaceDirectory(
|
|
2853
|
-
|
|
2854
|
-
|
|
3338
|
+
join16(templateSkillsDir, "flydocs-cloud"),
|
|
3339
|
+
join16(skillsDir, "flydocs-cloud")
|
|
2855
3340
|
);
|
|
2856
|
-
const { rm:
|
|
2857
|
-
const localSkillDir =
|
|
3341
|
+
const { rm: rm6 } = await import("fs/promises");
|
|
3342
|
+
const localSkillDir = join16(skillsDir, "flydocs-local");
|
|
2858
3343
|
if (await pathExists(localSkillDir)) {
|
|
2859
|
-
await
|
|
3344
|
+
await rm6(localSkillDir, { recursive: true, force: true });
|
|
2860
3345
|
}
|
|
2861
3346
|
printStatus("Cloud mechanism skill installed");
|
|
2862
3347
|
} catch {
|
|
@@ -2867,14 +3352,14 @@ LINEAR_API_KEY=${apiKey}
|
|
|
2867
3352
|
}
|
|
2868
3353
|
console.log();
|
|
2869
3354
|
console.log(
|
|
2870
|
-
` ${
|
|
3355
|
+
` ${pc11.bold("Connected!")} Your project now syncs with Linear.`
|
|
2871
3356
|
);
|
|
2872
3357
|
console.log();
|
|
2873
3358
|
console.log(` Next steps:`);
|
|
2874
3359
|
console.log(
|
|
2875
|
-
` 1. Run ${
|
|
3360
|
+
` 1. Run ${pc11.cyan("/flydocs-setup")} in your IDE to configure your Linear project`
|
|
2876
3361
|
);
|
|
2877
|
-
console.log(` 2. Run ${
|
|
3362
|
+
console.log(` 2. Run ${pc11.cyan("/start-session")} to begin working`);
|
|
2878
3363
|
console.log();
|
|
2879
3364
|
}
|
|
2880
3365
|
});
|
|
@@ -2886,15 +3371,15 @@ var upgrade_exports = {};
|
|
|
2886
3371
|
__export(upgrade_exports, {
|
|
2887
3372
|
default: () => upgrade_default
|
|
2888
3373
|
});
|
|
2889
|
-
import { defineCommand as
|
|
2890
|
-
import
|
|
3374
|
+
import { defineCommand as defineCommand7 } from "citty";
|
|
3375
|
+
import pc12 from "picocolors";
|
|
2891
3376
|
var upgrade_default;
|
|
2892
3377
|
var init_upgrade = __esm({
|
|
2893
3378
|
"src/commands/upgrade.ts"() {
|
|
2894
3379
|
"use strict";
|
|
2895
3380
|
init_config();
|
|
2896
3381
|
init_fs_ops();
|
|
2897
|
-
upgrade_default =
|
|
3382
|
+
upgrade_default = defineCommand7({
|
|
2898
3383
|
meta: {
|
|
2899
3384
|
name: "upgrade",
|
|
2900
3385
|
description: "Learn about FlyDocs Cloud tier and upgrade from local"
|
|
@@ -2923,37 +3408,37 @@ var init_upgrade = __esm({
|
|
|
2923
3408
|
console.log();
|
|
2924
3409
|
if (currentTier === "cloud") {
|
|
2925
3410
|
console.log(
|
|
2926
|
-
` ${
|
|
3411
|
+
` ${pc12.green("\u2713")} You're already on the ${pc12.bold("cloud")} tier.`
|
|
2927
3412
|
);
|
|
2928
3413
|
console.log();
|
|
2929
3414
|
console.log(
|
|
2930
3415
|
` Your issues sync with Linear via the cloud mechanism skill.`
|
|
2931
3416
|
);
|
|
2932
3417
|
console.log(
|
|
2933
|
-
` Run ${
|
|
3418
|
+
` Run ${pc12.cyan("flydocs connect")} to update your connection settings.`
|
|
2934
3419
|
);
|
|
2935
3420
|
console.log();
|
|
2936
3421
|
return;
|
|
2937
3422
|
}
|
|
2938
|
-
console.log(` ${
|
|
3423
|
+
console.log(` ${pc12.bold("FlyDocs Cloud Tier")}`);
|
|
2939
3424
|
console.log();
|
|
2940
|
-
console.log(` You're currently on the ${
|
|
3425
|
+
console.log(` You're currently on the ${pc12.yellow("local")} tier.`);
|
|
2941
3426
|
console.log(` Upgrade to cloud for:`);
|
|
2942
3427
|
console.log();
|
|
2943
3428
|
console.log(
|
|
2944
|
-
` ${
|
|
3429
|
+
` ${pc12.cyan("\u2192")} Issue sync with Linear (Jira coming soon)`
|
|
2945
3430
|
);
|
|
2946
|
-
console.log(` ${
|
|
2947
|
-
console.log(` ${
|
|
2948
|
-
console.log(` ${
|
|
2949
|
-
console.log(` ${
|
|
3431
|
+
console.log(` ${pc12.cyan("\u2192")} Project milestones and cycle management`);
|
|
3432
|
+
console.log(` ${pc12.cyan("\u2192")} Team assignment and priority tracking`);
|
|
3433
|
+
console.log(` ${pc12.cyan("\u2192")} Project health updates and dashboards`);
|
|
3434
|
+
console.log(` ${pc12.cyan("\u2192")} Cross-project issue linking`);
|
|
2950
3435
|
console.log();
|
|
2951
|
-
console.log(` ${
|
|
3436
|
+
console.log(` ${pc12.bold("How to upgrade:")}`);
|
|
2952
3437
|
console.log();
|
|
2953
|
-
console.log(` 1. Sign up at ${
|
|
3438
|
+
console.log(` 1. Sign up at ${pc12.cyan("https://www.flydocs.ai")}`);
|
|
2954
3439
|
console.log(` 2. Get your Linear API key from Linear \u2192 Settings \u2192 API`);
|
|
2955
3440
|
console.log(
|
|
2956
|
-
` 3. Run ${
|
|
3441
|
+
` 3. Run ${pc12.cyan("flydocs connect")} to connect your project`
|
|
2957
3442
|
);
|
|
2958
3443
|
console.log();
|
|
2959
3444
|
}
|
|
@@ -2966,23 +3451,23 @@ var self_update_exports = {};
|
|
|
2966
3451
|
__export(self_update_exports, {
|
|
2967
3452
|
default: () => self_update_default
|
|
2968
3453
|
});
|
|
2969
|
-
import { defineCommand as
|
|
3454
|
+
import { defineCommand as defineCommand8 } from "citty";
|
|
2970
3455
|
import { execSync } from "child_process";
|
|
2971
|
-
import
|
|
3456
|
+
import pc13 from "picocolors";
|
|
2972
3457
|
var self_update_default;
|
|
2973
3458
|
var init_self_update = __esm({
|
|
2974
3459
|
"src/commands/self-update.ts"() {
|
|
2975
3460
|
"use strict";
|
|
2976
3461
|
init_constants();
|
|
2977
3462
|
init_ui();
|
|
2978
|
-
self_update_default =
|
|
3463
|
+
self_update_default = defineCommand8({
|
|
2979
3464
|
meta: {
|
|
2980
3465
|
name: "self-update",
|
|
2981
3466
|
description: "Update FlyDocs CLI to the latest version"
|
|
2982
3467
|
},
|
|
2983
3468
|
async run() {
|
|
2984
3469
|
console.log();
|
|
2985
|
-
console.log(` Updating ${
|
|
3470
|
+
console.log(` Updating ${pc13.cyan(PACKAGE_NAME)}...`);
|
|
2986
3471
|
console.log();
|
|
2987
3472
|
try {
|
|
2988
3473
|
execSync(`npm install -g ${PACKAGE_NAME}@beta`, {
|
|
@@ -3002,17 +3487,117 @@ var init_self_update = __esm({
|
|
|
3002
3487
|
}
|
|
3003
3488
|
});
|
|
3004
3489
|
|
|
3490
|
+
// src/commands/telemetry.ts
|
|
3491
|
+
var telemetry_exports = {};
|
|
3492
|
+
__export(telemetry_exports, {
|
|
3493
|
+
default: () => telemetry_default
|
|
3494
|
+
});
|
|
3495
|
+
import { defineCommand as defineCommand9 } from "citty";
|
|
3496
|
+
import pc14 from "picocolors";
|
|
3497
|
+
var enable, disable, status, telemetry_default;
|
|
3498
|
+
var init_telemetry2 = __esm({
|
|
3499
|
+
"src/commands/telemetry.ts"() {
|
|
3500
|
+
"use strict";
|
|
3501
|
+
init_telemetry();
|
|
3502
|
+
init_ui();
|
|
3503
|
+
enable = defineCommand9({
|
|
3504
|
+
meta: {
|
|
3505
|
+
name: "enable",
|
|
3506
|
+
description: "Enable anonymous usage analytics"
|
|
3507
|
+
},
|
|
3508
|
+
async run() {
|
|
3509
|
+
try {
|
|
3510
|
+
await setEnabled(true);
|
|
3511
|
+
printStatus("Telemetry enabled");
|
|
3512
|
+
} catch {
|
|
3513
|
+
printError("Failed to update telemetry settings");
|
|
3514
|
+
process.exit(1);
|
|
3515
|
+
}
|
|
3516
|
+
}
|
|
3517
|
+
});
|
|
3518
|
+
disable = defineCommand9({
|
|
3519
|
+
meta: {
|
|
3520
|
+
name: "disable",
|
|
3521
|
+
description: "Disable anonymous usage analytics"
|
|
3522
|
+
},
|
|
3523
|
+
async run() {
|
|
3524
|
+
try {
|
|
3525
|
+
await setEnabled(false);
|
|
3526
|
+
printStatus("Telemetry disabled");
|
|
3527
|
+
printInfo(
|
|
3528
|
+
"You can also set FLYDOCS_TELEMETRY=0 in your shell environment."
|
|
3529
|
+
);
|
|
3530
|
+
} catch {
|
|
3531
|
+
printError("Failed to update telemetry settings");
|
|
3532
|
+
process.exit(1);
|
|
3533
|
+
}
|
|
3534
|
+
}
|
|
3535
|
+
});
|
|
3536
|
+
status = defineCommand9({
|
|
3537
|
+
meta: {
|
|
3538
|
+
name: "status",
|
|
3539
|
+
description: "Show current telemetry status"
|
|
3540
|
+
},
|
|
3541
|
+
async run() {
|
|
3542
|
+
const info = await getStatus();
|
|
3543
|
+
console.log();
|
|
3544
|
+
console.log(pc14.bold("Telemetry Status"));
|
|
3545
|
+
console.log();
|
|
3546
|
+
const effectivelyEnabled = info.enabled && !info.envOverride;
|
|
3547
|
+
console.log(
|
|
3548
|
+
` Enabled: ${effectivelyEnabled ? pc14.green("yes") : pc14.yellow("no")}`
|
|
3549
|
+
);
|
|
3550
|
+
if (info.envOverride) {
|
|
3551
|
+
console.log(
|
|
3552
|
+
` Env override: ${pc14.yellow("FLYDOCS_TELEMETRY=0 (disabled via env)")}`
|
|
3553
|
+
);
|
|
3554
|
+
}
|
|
3555
|
+
if (info.anonymousId) {
|
|
3556
|
+
console.log(` Anonymous ID: ${pc14.dim(info.anonymousId)}`);
|
|
3557
|
+
} else {
|
|
3558
|
+
console.log(
|
|
3559
|
+
` Anonymous ID: ${pc14.dim("(not yet created \u2014 generated on first run)")}`
|
|
3560
|
+
);
|
|
3561
|
+
}
|
|
3562
|
+
console.log();
|
|
3563
|
+
console.log(
|
|
3564
|
+
pc14.dim(
|
|
3565
|
+
" FlyDocs collects anonymous usage analytics to improve the CLI."
|
|
3566
|
+
)
|
|
3567
|
+
);
|
|
3568
|
+
console.log(
|
|
3569
|
+
pc14.dim(" No personal data, file contents, or code is ever collected.")
|
|
3570
|
+
);
|
|
3571
|
+
console.log();
|
|
3572
|
+
}
|
|
3573
|
+
});
|
|
3574
|
+
telemetry_default = defineCommand9({
|
|
3575
|
+
meta: {
|
|
3576
|
+
name: "telemetry",
|
|
3577
|
+
description: "Manage anonymous usage analytics (enable, disable, status)"
|
|
3578
|
+
},
|
|
3579
|
+
subCommands: {
|
|
3580
|
+
enable,
|
|
3581
|
+
disable,
|
|
3582
|
+
status
|
|
3583
|
+
}
|
|
3584
|
+
});
|
|
3585
|
+
}
|
|
3586
|
+
});
|
|
3587
|
+
|
|
3005
3588
|
// src/cli.ts
|
|
3006
3589
|
init_constants();
|
|
3007
|
-
import { defineCommand as
|
|
3590
|
+
import { defineCommand as defineCommand10, runMain } from "citty";
|
|
3008
3591
|
var SUB_COMMANDS = /* @__PURE__ */ new Set([
|
|
3009
3592
|
"install",
|
|
3010
3593
|
"update",
|
|
3594
|
+
"uninstall",
|
|
3011
3595
|
"setup",
|
|
3012
3596
|
"skills",
|
|
3013
3597
|
"connect",
|
|
3014
3598
|
"upgrade",
|
|
3015
|
-
"self-update"
|
|
3599
|
+
"self-update",
|
|
3600
|
+
"telemetry"
|
|
3016
3601
|
]);
|
|
3017
3602
|
var userArgs = process.argv.slice(2);
|
|
3018
3603
|
var hasMetaFlag = userArgs.some(
|
|
@@ -3022,7 +3607,7 @@ var firstPositional = userArgs.find((a) => !a.startsWith("-"));
|
|
|
3022
3607
|
if (!hasMetaFlag && (!firstPositional || !SUB_COMMANDS.has(firstPositional))) {
|
|
3023
3608
|
process.argv.splice(2, 0, "install");
|
|
3024
3609
|
}
|
|
3025
|
-
var main =
|
|
3610
|
+
var main = defineCommand10({
|
|
3026
3611
|
meta: {
|
|
3027
3612
|
name: CLI_NAME,
|
|
3028
3613
|
version: CLI_VERSION,
|
|
@@ -3031,11 +3616,13 @@ var main = defineCommand8({
|
|
|
3031
3616
|
subCommands: {
|
|
3032
3617
|
install: () => Promise.resolve().then(() => (init_install(), install_exports)).then((m) => m.default),
|
|
3033
3618
|
update: () => Promise.resolve().then(() => (init_update(), update_exports)).then((m) => m.default),
|
|
3619
|
+
uninstall: () => Promise.resolve().then(() => (init_uninstall(), uninstall_exports)).then((m) => m.default),
|
|
3034
3620
|
setup: () => Promise.resolve().then(() => (init_setup(), setup_exports)).then((m) => m.default),
|
|
3035
3621
|
skills: () => Promise.resolve().then(() => (init_skills2(), skills_exports)).then((m) => m.default),
|
|
3036
3622
|
connect: () => Promise.resolve().then(() => (init_connect(), connect_exports)).then((m) => m.default),
|
|
3037
3623
|
upgrade: () => Promise.resolve().then(() => (init_upgrade(), upgrade_exports)).then((m) => m.default),
|
|
3038
|
-
"self-update": () => Promise.resolve().then(() => (init_self_update(), self_update_exports)).then((m) => m.default)
|
|
3624
|
+
"self-update": () => Promise.resolve().then(() => (init_self_update(), self_update_exports)).then((m) => m.default),
|
|
3625
|
+
telemetry: () => Promise.resolve().then(() => (init_telemetry2(), telemetry_exports)).then((m) => m.default)
|
|
3039
3626
|
}
|
|
3040
3627
|
});
|
|
3041
3628
|
runMain(main);
|