@flydocs/cli 0.5.0-beta.16 → 0.5.0-beta.18
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 +752 -187
- package/package.json +1 -1
- package/template/.flydocs/config.json +1 -1
- package/template/.flydocs/version +1 -1
- package/template/CHANGELOG.md +24 -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.18";
|
|
19
19
|
CLI_NAME = "flydocs";
|
|
20
20
|
PACKAGE_NAME = "@flydocs/cli";
|
|
21
|
+
POSTHOG_API_KEY = "phc_v1MSJTQDFkMS90CBh3mxIz3v8bYCCnKU6v1ir6bz0Xn";
|
|
21
22
|
}
|
|
22
23
|
});
|
|
23
24
|
|
|
@@ -360,10 +361,10 @@ 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
369
|
for (const skill of CORE_SKILLS) {
|
|
369
370
|
if (skill === "flydocs-workflow") continue;
|
|
@@ -388,7 +389,7 @@ async function installOwnedSkills(templateDir, targetDir, tier) {
|
|
|
388
389
|
async function replaceOwnedSkills(templateDir, targetDir, tier) {
|
|
389
390
|
const skillsDir = join4(targetDir, ".claude", "skills");
|
|
390
391
|
const templateSkillsDir = join4(templateDir, ".claude", "skills");
|
|
391
|
-
const { rm:
|
|
392
|
+
const { rm: rm6 } = await import("fs/promises");
|
|
392
393
|
for (const skill of CORE_SKILLS) {
|
|
393
394
|
const src = join4(templateSkillsDir, skill);
|
|
394
395
|
if (await pathExists(src)) {
|
|
@@ -403,14 +404,14 @@ async function replaceOwnedSkills(templateDir, targetDir, tier) {
|
|
|
403
404
|
await replaceDirectory(src, dest);
|
|
404
405
|
}
|
|
405
406
|
} else if (await pathExists(dest)) {
|
|
406
|
-
await
|
|
407
|
+
await rm6(dest, { recursive: true, force: true });
|
|
407
408
|
}
|
|
408
409
|
}
|
|
409
410
|
const activeMech = MECHANISM_SKILLS[tier];
|
|
410
411
|
const inactiveMech = tier === "local" ? MECHANISM_SKILLS.cloud : MECHANISM_SKILLS.local;
|
|
411
412
|
const inactivePath = join4(skillsDir, inactiveMech);
|
|
412
413
|
if (await pathExists(inactivePath)) {
|
|
413
|
-
await
|
|
414
|
+
await rm6(inactivePath, { recursive: true, force: true });
|
|
414
415
|
}
|
|
415
416
|
await replaceDirectory(
|
|
416
417
|
join4(templateSkillsDir, activeMech),
|
|
@@ -422,9 +423,9 @@ async function replaceOwnedSkills(templateDir, targetDir, tier) {
|
|
|
422
423
|
}
|
|
423
424
|
}
|
|
424
425
|
async function copyCursorRules(targetDir) {
|
|
425
|
-
const { mkdir:
|
|
426
|
+
const { mkdir: mkdir8 } = await import("fs/promises");
|
|
426
427
|
const rulesDir = join4(targetDir, ".cursor", "rules");
|
|
427
|
-
await
|
|
428
|
+
await mkdir8(rulesDir, { recursive: true });
|
|
428
429
|
const workflowRule = join4(
|
|
429
430
|
targetDir,
|
|
430
431
|
".claude",
|
|
@@ -1643,6 +1644,139 @@ var init_update_check = __esm({
|
|
|
1643
1644
|
}
|
|
1644
1645
|
});
|
|
1645
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: false,
|
|
1678
|
+
anonymousId: randomUUID()
|
|
1679
|
+
};
|
|
1680
|
+
await writeConfig2(config);
|
|
1681
|
+
return config;
|
|
1682
|
+
}
|
|
1683
|
+
async function isEnabled() {
|
|
1684
|
+
try {
|
|
1685
|
+
if (process.env.FLYDOCS_TELEMETRY === "0") {
|
|
1686
|
+
return false;
|
|
1687
|
+
}
|
|
1688
|
+
const config = await readConfig2();
|
|
1689
|
+
if (config) {
|
|
1690
|
+
return config.enabled;
|
|
1691
|
+
}
|
|
1692
|
+
return false;
|
|
1693
|
+
} catch {
|
|
1694
|
+
return false;
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
function baseProperties() {
|
|
1698
|
+
return {
|
|
1699
|
+
cli_version: CLI_VERSION,
|
|
1700
|
+
os: process.platform,
|
|
1701
|
+
os_arch: process.arch,
|
|
1702
|
+
node_version: process.version,
|
|
1703
|
+
is_ci: Boolean(
|
|
1704
|
+
process.env.CI || process.env.CONTINUOUS_INTEGRATION || process.env.BUILD_NUMBER
|
|
1705
|
+
),
|
|
1706
|
+
$ip: null,
|
|
1707
|
+
$process_person_profile: false
|
|
1708
|
+
};
|
|
1709
|
+
}
|
|
1710
|
+
async function capture(event, properties = {}) {
|
|
1711
|
+
try {
|
|
1712
|
+
if (!await isEnabled()) {
|
|
1713
|
+
return;
|
|
1714
|
+
}
|
|
1715
|
+
const config = await ensureConfig();
|
|
1716
|
+
eventQueue.push({
|
|
1717
|
+
event,
|
|
1718
|
+
properties: {
|
|
1719
|
+
distinct_id: config.anonymousId,
|
|
1720
|
+
...baseProperties(),
|
|
1721
|
+
...properties
|
|
1722
|
+
},
|
|
1723
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1724
|
+
});
|
|
1725
|
+
} catch {
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
async function flush() {
|
|
1729
|
+
try {
|
|
1730
|
+
if (eventQueue.length === 0) {
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1733
|
+
if (!await isEnabled()) {
|
|
1734
|
+
eventQueue.length = 0;
|
|
1735
|
+
return;
|
|
1736
|
+
}
|
|
1737
|
+
const batch = eventQueue.splice(0, eventQueue.length);
|
|
1738
|
+
const controller = new AbortController();
|
|
1739
|
+
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS2);
|
|
1740
|
+
await fetch(POSTHOG_BATCH_URL, {
|
|
1741
|
+
method: "POST",
|
|
1742
|
+
headers: { "Content-Type": "application/json" },
|
|
1743
|
+
body: JSON.stringify({
|
|
1744
|
+
api_key: POSTHOG_API_KEY,
|
|
1745
|
+
batch
|
|
1746
|
+
}),
|
|
1747
|
+
signal: controller.signal
|
|
1748
|
+
});
|
|
1749
|
+
clearTimeout(timeout);
|
|
1750
|
+
} catch {
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
async function setEnabled(enabled) {
|
|
1754
|
+
const config = await ensureConfig();
|
|
1755
|
+
config.enabled = enabled;
|
|
1756
|
+
await writeConfig2(config);
|
|
1757
|
+
}
|
|
1758
|
+
async function getStatus() {
|
|
1759
|
+
const envOverride = process.env.FLYDOCS_TELEMETRY === "0";
|
|
1760
|
+
const config = await readConfig2();
|
|
1761
|
+
return {
|
|
1762
|
+
enabled: config?.enabled ?? false,
|
|
1763
|
+
envOverride,
|
|
1764
|
+
anonymousId: config?.anonymousId ?? null
|
|
1765
|
+
};
|
|
1766
|
+
}
|
|
1767
|
+
var CONFIG_DIR, CONFIG_FILE, POSTHOG_BATCH_URL, FETCH_TIMEOUT_MS2, eventQueue;
|
|
1768
|
+
var init_telemetry = __esm({
|
|
1769
|
+
"src/lib/telemetry.ts"() {
|
|
1770
|
+
"use strict";
|
|
1771
|
+
init_constants();
|
|
1772
|
+
CONFIG_DIR = join12(homedir2(), ".flydocs");
|
|
1773
|
+
CONFIG_FILE = join12(CONFIG_DIR, "telemetry.json");
|
|
1774
|
+
POSTHOG_BATCH_URL = "https://us.i.posthog.com/batch/";
|
|
1775
|
+
FETCH_TIMEOUT_MS2 = 5e3;
|
|
1776
|
+
eventQueue = [];
|
|
1777
|
+
}
|
|
1778
|
+
});
|
|
1779
|
+
|
|
1646
1780
|
// src/commands/install.ts
|
|
1647
1781
|
var install_exports = {};
|
|
1648
1782
|
__export(install_exports, {
|
|
@@ -1650,8 +1784,8 @@ __export(install_exports, {
|
|
|
1650
1784
|
});
|
|
1651
1785
|
import { defineCommand } from "citty";
|
|
1652
1786
|
import { resolve as resolve2 } from "path";
|
|
1653
|
-
import { join as
|
|
1654
|
-
import { mkdir as
|
|
1787
|
+
import { join as join13 } from "path";
|
|
1788
|
+
import { mkdir as mkdir6 } from "fs/promises";
|
|
1655
1789
|
import { confirm as confirm2, select, isCancel as isCancel3, cancel as cancel2 } from "@clack/prompts";
|
|
1656
1790
|
import pc6 from "picocolors";
|
|
1657
1791
|
var install_default;
|
|
@@ -1669,6 +1803,7 @@ var init_install = __esm({
|
|
|
1669
1803
|
init_gitignore();
|
|
1670
1804
|
init_post_install();
|
|
1671
1805
|
init_update_check();
|
|
1806
|
+
init_telemetry();
|
|
1672
1807
|
install_default = defineCommand({
|
|
1673
1808
|
meta: {
|
|
1674
1809
|
name: "install",
|
|
@@ -1704,6 +1839,7 @@ var init_install = __esm({
|
|
|
1704
1839
|
const templateDir = await resolveTemplatePath(args["local-source"]);
|
|
1705
1840
|
const version = await readTemplateVersion(templateDir);
|
|
1706
1841
|
printBanner(version);
|
|
1842
|
+
await capture("install_started", { template_version: version });
|
|
1707
1843
|
let targetDir;
|
|
1708
1844
|
if (args.path) {
|
|
1709
1845
|
targetDir = resolve2(args.path.replace(/^~/, process.env.HOME ?? "~"));
|
|
@@ -1730,7 +1866,7 @@ var init_install = __esm({
|
|
|
1730
1866
|
}
|
|
1731
1867
|
tier = args.tier;
|
|
1732
1868
|
printInfo(`Tier set via flag: ${tier}`);
|
|
1733
|
-
} else if (await pathExists(
|
|
1869
|
+
} else if (await pathExists(join13(targetDir, ".flydocs", "config.json"))) {
|
|
1734
1870
|
try {
|
|
1735
1871
|
const existing = await readConfig(targetDir);
|
|
1736
1872
|
if (existing.tier) {
|
|
@@ -1752,37 +1888,38 @@ var init_install = __esm({
|
|
|
1752
1888
|
tier = "local";
|
|
1753
1889
|
console.log();
|
|
1754
1890
|
}
|
|
1755
|
-
|
|
1891
|
+
await capture("install_tier_selected", { tier });
|
|
1892
|
+
if (!await pathExists(join13(targetDir, ".git"))) {
|
|
1756
1893
|
printWarning("No git repository detected. Run git init when ready.");
|
|
1757
1894
|
}
|
|
1758
1895
|
await ensureDirectories(targetDir, tier);
|
|
1759
1896
|
console.log("Installing framework files...");
|
|
1760
1897
|
await replaceDirectory(
|
|
1761
|
-
|
|
1762
|
-
|
|
1898
|
+
join13(templateDir, ".flydocs", "templates"),
|
|
1899
|
+
join13(targetDir, ".flydocs", "templates")
|
|
1763
1900
|
);
|
|
1764
1901
|
await replaceDirectory(
|
|
1765
|
-
|
|
1766
|
-
|
|
1902
|
+
join13(templateDir, ".flydocs", "hooks"),
|
|
1903
|
+
join13(targetDir, ".flydocs", "hooks")
|
|
1767
1904
|
);
|
|
1768
1905
|
await replaceDirectory(
|
|
1769
|
-
|
|
1770
|
-
|
|
1906
|
+
join13(templateDir, ".flydocs", "scripts"),
|
|
1907
|
+
join13(targetDir, ".flydocs", "scripts")
|
|
1771
1908
|
);
|
|
1772
1909
|
await copyFile(
|
|
1773
|
-
|
|
1774
|
-
|
|
1910
|
+
join13(templateDir, ".flydocs", "version"),
|
|
1911
|
+
join13(targetDir, ".flydocs", "version")
|
|
1775
1912
|
);
|
|
1776
|
-
const manifestSrc =
|
|
1913
|
+
const manifestSrc = join13(templateDir, "manifest.json");
|
|
1777
1914
|
if (await pathExists(manifestSrc)) {
|
|
1778
|
-
await copyFile(manifestSrc,
|
|
1915
|
+
await copyFile(manifestSrc, join13(targetDir, ".flydocs", "manifest.json"));
|
|
1779
1916
|
}
|
|
1780
|
-
const changelogSrc =
|
|
1917
|
+
const changelogSrc = join13(templateDir, "CHANGELOG.md");
|
|
1781
1918
|
if (await pathExists(changelogSrc)) {
|
|
1782
|
-
await copyFile(changelogSrc,
|
|
1919
|
+
await copyFile(changelogSrc, join13(targetDir, ".flydocs", "CHANGELOG.md"));
|
|
1783
1920
|
}
|
|
1784
1921
|
printStatus(".flydocs/templates, hooks, version, manifest, changelog");
|
|
1785
|
-
const configPath =
|
|
1922
|
+
const configPath = join13(targetDir, ".flydocs", "config.json");
|
|
1786
1923
|
if (!await pathExists(configPath)) {
|
|
1787
1924
|
const config = await createFreshConfig(templateDir, version, tier);
|
|
1788
1925
|
await writeConfig(targetDir, config);
|
|
@@ -1834,21 +1971,22 @@ var init_install = __esm({
|
|
|
1834
1971
|
installAgents = agentConfirm;
|
|
1835
1972
|
}
|
|
1836
1973
|
}
|
|
1974
|
+
await capture("install_agents_chosen", { install_agents: installAgents });
|
|
1837
1975
|
if (installAgents) {
|
|
1838
|
-
const claudeAgentsSrc =
|
|
1976
|
+
const claudeAgentsSrc = join13(templateDir, ".claude", "agents");
|
|
1839
1977
|
if (await pathExists(claudeAgentsSrc)) {
|
|
1840
|
-
await
|
|
1978
|
+
await mkdir6(join13(targetDir, ".claude", "agents"), { recursive: true });
|
|
1841
1979
|
await copyDirectoryContents(
|
|
1842
1980
|
claudeAgentsSrc,
|
|
1843
|
-
|
|
1981
|
+
join13(targetDir, ".claude", "agents")
|
|
1844
1982
|
);
|
|
1845
1983
|
}
|
|
1846
|
-
const cursorAgentsSrc =
|
|
1984
|
+
const cursorAgentsSrc = join13(templateDir, ".cursor", "agents");
|
|
1847
1985
|
if (await pathExists(cursorAgentsSrc)) {
|
|
1848
|
-
await
|
|
1986
|
+
await mkdir6(join13(targetDir, ".cursor", "agents"), { recursive: true });
|
|
1849
1987
|
await copyDirectoryContents(
|
|
1850
1988
|
cursorAgentsSrc,
|
|
1851
|
-
|
|
1989
|
+
join13(targetDir, ".cursor", "agents")
|
|
1852
1990
|
);
|
|
1853
1991
|
}
|
|
1854
1992
|
printStatus("Sub-agents installed (.claude/agents, .cursor/agents)");
|
|
@@ -1858,32 +1996,32 @@ var init_install = __esm({
|
|
|
1858
1996
|
console.log();
|
|
1859
1997
|
console.log("Installing commands and settings...");
|
|
1860
1998
|
await copyDirectoryContents(
|
|
1861
|
-
|
|
1862
|
-
|
|
1999
|
+
join13(templateDir, ".claude", "commands"),
|
|
2000
|
+
join13(targetDir, ".claude", "commands")
|
|
1863
2001
|
);
|
|
1864
2002
|
await copyFile(
|
|
1865
|
-
|
|
1866
|
-
|
|
2003
|
+
join13(templateDir, ".claude", "CLAUDE.md"),
|
|
2004
|
+
join13(targetDir, ".claude", "CLAUDE.md")
|
|
1867
2005
|
);
|
|
1868
2006
|
await copyFile(
|
|
1869
|
-
|
|
1870
|
-
|
|
2007
|
+
join13(templateDir, ".claude", "settings.json"),
|
|
2008
|
+
join13(targetDir, ".claude", "settings.json")
|
|
1871
2009
|
);
|
|
1872
2010
|
printStatus(".claude/ (commands, CLAUDE.md, settings)");
|
|
1873
2011
|
await copyDirectoryContents(
|
|
1874
|
-
|
|
1875
|
-
|
|
2012
|
+
join13(templateDir, ".claude", "commands"),
|
|
2013
|
+
join13(targetDir, ".cursor", "commands")
|
|
1876
2014
|
);
|
|
1877
2015
|
await copyFile(
|
|
1878
|
-
|
|
1879
|
-
|
|
2016
|
+
join13(templateDir, ".cursor", "hooks.json"),
|
|
2017
|
+
join13(targetDir, ".cursor", "hooks.json")
|
|
1880
2018
|
);
|
|
1881
2019
|
printStatus(".cursor/ (commands, hooks)");
|
|
1882
2020
|
await copyCursorRules(targetDir);
|
|
1883
2021
|
printStatus(".cursor/rules/");
|
|
1884
2022
|
await copyFile(
|
|
1885
|
-
|
|
1886
|
-
|
|
2023
|
+
join13(templateDir, "AGENTS.md"),
|
|
2024
|
+
join13(targetDir, "AGENTS.md")
|
|
1887
2025
|
);
|
|
1888
2026
|
printStatus("AGENTS.md");
|
|
1889
2027
|
await runManifestGeneration(targetDir);
|
|
@@ -1892,40 +2030,40 @@ var init_install = __esm({
|
|
|
1892
2030
|
console.log("Installing project templates...");
|
|
1893
2031
|
const userFiles = [
|
|
1894
2032
|
{
|
|
1895
|
-
src:
|
|
1896
|
-
dest:
|
|
2033
|
+
src: join13(templateDir, "flydocs", "context", "project.md"),
|
|
2034
|
+
dest: join13(targetDir, "flydocs", "context", "project.md"),
|
|
1897
2035
|
label: "flydocs/context/project.md"
|
|
1898
2036
|
},
|
|
1899
2037
|
{
|
|
1900
|
-
src:
|
|
1901
|
-
dest:
|
|
2038
|
+
src: join13(templateDir, "flydocs", "knowledge", "INDEX.md"),
|
|
2039
|
+
dest: join13(targetDir, "flydocs", "knowledge", "INDEX.md"),
|
|
1902
2040
|
label: "flydocs/knowledge/INDEX.md"
|
|
1903
2041
|
},
|
|
1904
2042
|
{
|
|
1905
|
-
src:
|
|
1906
|
-
dest:
|
|
2043
|
+
src: join13(templateDir, "flydocs", "knowledge", "README.md"),
|
|
2044
|
+
dest: join13(targetDir, "flydocs", "knowledge", "README.md"),
|
|
1907
2045
|
label: "flydocs/knowledge/README.md"
|
|
1908
2046
|
},
|
|
1909
2047
|
{
|
|
1910
|
-
src:
|
|
2048
|
+
src: join13(
|
|
1911
2049
|
templateDir,
|
|
1912
2050
|
"flydocs",
|
|
1913
2051
|
"knowledge",
|
|
1914
2052
|
"product",
|
|
1915
2053
|
"personas.md"
|
|
1916
2054
|
),
|
|
1917
|
-
dest:
|
|
2055
|
+
dest: join13(targetDir, "flydocs", "knowledge", "product", "personas.md"),
|
|
1918
2056
|
label: "flydocs/knowledge/product/personas.md"
|
|
1919
2057
|
},
|
|
1920
2058
|
{
|
|
1921
|
-
src:
|
|
2059
|
+
src: join13(
|
|
1922
2060
|
templateDir,
|
|
1923
2061
|
"flydocs",
|
|
1924
2062
|
"knowledge",
|
|
1925
2063
|
"product",
|
|
1926
2064
|
"user-flows.md"
|
|
1927
2065
|
),
|
|
1928
|
-
dest:
|
|
2066
|
+
dest: join13(
|
|
1929
2067
|
targetDir,
|
|
1930
2068
|
"flydocs",
|
|
1931
2069
|
"knowledge",
|
|
@@ -1935,18 +2073,18 @@ var init_install = __esm({
|
|
|
1935
2073
|
label: "flydocs/knowledge/product/user-flows.md"
|
|
1936
2074
|
},
|
|
1937
2075
|
{
|
|
1938
|
-
src:
|
|
1939
|
-
dest:
|
|
2076
|
+
src: join13(templateDir, "flydocs", "design-system", "README.md"),
|
|
2077
|
+
dest: join13(targetDir, "flydocs", "design-system", "README.md"),
|
|
1940
2078
|
label: "flydocs/design-system/README.md"
|
|
1941
2079
|
},
|
|
1942
2080
|
{
|
|
1943
|
-
src:
|
|
2081
|
+
src: join13(
|
|
1944
2082
|
templateDir,
|
|
1945
2083
|
"flydocs",
|
|
1946
2084
|
"design-system",
|
|
1947
2085
|
"component-patterns.md"
|
|
1948
2086
|
),
|
|
1949
|
-
dest:
|
|
2087
|
+
dest: join13(
|
|
1950
2088
|
targetDir,
|
|
1951
2089
|
"flydocs",
|
|
1952
2090
|
"design-system",
|
|
@@ -1955,13 +2093,13 @@ var init_install = __esm({
|
|
|
1955
2093
|
label: "flydocs/design-system/component-patterns.md"
|
|
1956
2094
|
},
|
|
1957
2095
|
{
|
|
1958
|
-
src:
|
|
1959
|
-
dest:
|
|
2096
|
+
src: join13(templateDir, "flydocs", "design-system", "token-mapping.md"),
|
|
2097
|
+
dest: join13(targetDir, "flydocs", "design-system", "token-mapping.md"),
|
|
1960
2098
|
label: "flydocs/design-system/token-mapping.md"
|
|
1961
2099
|
},
|
|
1962
2100
|
{
|
|
1963
|
-
src:
|
|
1964
|
-
dest:
|
|
2101
|
+
src: join13(templateDir, "flydocs", "README.md"),
|
|
2102
|
+
dest: join13(targetDir, "flydocs", "README.md"),
|
|
1965
2103
|
label: "flydocs/README.md"
|
|
1966
2104
|
}
|
|
1967
2105
|
];
|
|
@@ -1975,9 +2113,9 @@ var init_install = __esm({
|
|
|
1975
2113
|
}
|
|
1976
2114
|
}
|
|
1977
2115
|
}
|
|
1978
|
-
const envExampleSrc =
|
|
2116
|
+
const envExampleSrc = join13(templateDir, ".env.example");
|
|
1979
2117
|
if (await pathExists(envExampleSrc)) {
|
|
1980
|
-
await copyFile(envExampleSrc,
|
|
2118
|
+
await copyFile(envExampleSrc, join13(targetDir, ".env.example"));
|
|
1981
2119
|
printStatus(".env.example");
|
|
1982
2120
|
}
|
|
1983
2121
|
await ensureGitignore(targetDir);
|
|
@@ -1996,6 +2134,9 @@ var init_install = __esm({
|
|
|
1996
2134
|
} else {
|
|
1997
2135
|
printInfo("No framework detected in package.json");
|
|
1998
2136
|
}
|
|
2137
|
+
await capture("install_skills_chosen", {
|
|
2138
|
+
stack_detected: stack.raw
|
|
2139
|
+
});
|
|
1999
2140
|
console.log();
|
|
2000
2141
|
console.log("Checking for deprecated files...");
|
|
2001
2142
|
const deprecated = await scanDeprecated(targetDir);
|
|
@@ -2037,6 +2178,7 @@ var init_install = __esm({
|
|
|
2037
2178
|
}
|
|
2038
2179
|
printCompletionBox("Installation Complete!", nextSteps);
|
|
2039
2180
|
printBetaCta();
|
|
2181
|
+
const detectedIdes = [];
|
|
2040
2182
|
try {
|
|
2041
2183
|
const { execSync: execSync2, spawn } = await import("child_process");
|
|
2042
2184
|
const isInstalled = (cmd) => {
|
|
@@ -2072,6 +2214,7 @@ var init_install = __esm({
|
|
|
2072
2214
|
passCommand: false
|
|
2073
2215
|
});
|
|
2074
2216
|
}
|
|
2217
|
+
detectedIdes.push(...ideOptions.map((o) => o.cmd));
|
|
2075
2218
|
if (ideOptions.length === 1) {
|
|
2076
2219
|
const ide = ideOptions[0];
|
|
2077
2220
|
const launchConfirm = await confirm2({
|
|
@@ -2130,6 +2273,9 @@ var init_install = __esm({
|
|
|
2130
2273
|
}
|
|
2131
2274
|
} catch {
|
|
2132
2275
|
}
|
|
2276
|
+
await capture("install_ide_detected", { ides: detectedIdes });
|
|
2277
|
+
await capture("install_completed", { tier, version });
|
|
2278
|
+
await flush();
|
|
2133
2279
|
try {
|
|
2134
2280
|
const updateResult = await checkForUpdate();
|
|
2135
2281
|
if (updateResult) {
|
|
@@ -2148,8 +2294,8 @@ __export(update_exports, {
|
|
|
2148
2294
|
default: () => update_default
|
|
2149
2295
|
});
|
|
2150
2296
|
import { defineCommand as defineCommand2 } from "citty";
|
|
2151
|
-
import { resolve as resolve3, join as
|
|
2152
|
-
import { mkdir as
|
|
2297
|
+
import { resolve as resolve3, join as join14 } from "path";
|
|
2298
|
+
import { mkdir as mkdir7, cp as cp2, readFile as readFile9, readdir as readdir3, rm as rm4 } from "fs/promises";
|
|
2153
2299
|
import { select as select2, text, confirm as confirm3, isCancel as isCancel4, cancel as cancel3 } from "@clack/prompts";
|
|
2154
2300
|
import pc7 from "picocolors";
|
|
2155
2301
|
var update_default;
|
|
@@ -2168,6 +2314,7 @@ var init_update = __esm({
|
|
|
2168
2314
|
init_gitignore();
|
|
2169
2315
|
init_post_install();
|
|
2170
2316
|
init_update_check();
|
|
2317
|
+
init_telemetry();
|
|
2171
2318
|
update_default = defineCommand2({
|
|
2172
2319
|
meta: {
|
|
2173
2320
|
name: "update",
|
|
@@ -2210,6 +2357,7 @@ var init_update = __esm({
|
|
|
2210
2357
|
printBanner(version);
|
|
2211
2358
|
printInfo("Running in update mode \u2014 framework files will be refreshed");
|
|
2212
2359
|
console.log();
|
|
2360
|
+
await capture("update_started", { template_version: version });
|
|
2213
2361
|
let targetDir;
|
|
2214
2362
|
if (args.path) {
|
|
2215
2363
|
targetDir = resolve3(args.path.replace(/^~/, process.env.HOME ?? "~"));
|
|
@@ -2254,9 +2402,9 @@ var init_update = __esm({
|
|
|
2254
2402
|
}
|
|
2255
2403
|
targetDir = resolve3(targetDir);
|
|
2256
2404
|
process.chdir(targetDir);
|
|
2257
|
-
const hasVersion = await pathExists(
|
|
2405
|
+
const hasVersion = await pathExists(join14(targetDir, ".flydocs", "version"));
|
|
2258
2406
|
const hasConfig = await pathExists(
|
|
2259
|
-
|
|
2407
|
+
join14(targetDir, ".flydocs", "config.json")
|
|
2260
2408
|
);
|
|
2261
2409
|
if (!hasVersion && !hasConfig) {
|
|
2262
2410
|
printError(`Not a FlyDocs project: ${targetDir}`);
|
|
@@ -2267,8 +2415,8 @@ var init_update = __esm({
|
|
|
2267
2415
|
console.log();
|
|
2268
2416
|
let currentVersion = "0.1.0";
|
|
2269
2417
|
if (hasVersion) {
|
|
2270
|
-
const vContent = await
|
|
2271
|
-
|
|
2418
|
+
const vContent = await readFile9(
|
|
2419
|
+
join14(targetDir, ".flydocs", "version"),
|
|
2272
2420
|
"utf-8"
|
|
2273
2421
|
);
|
|
2274
2422
|
currentVersion = vContent.trim();
|
|
@@ -2294,9 +2442,15 @@ var init_update = __esm({
|
|
|
2294
2442
|
process.exit(0);
|
|
2295
2443
|
}
|
|
2296
2444
|
}
|
|
2445
|
+
await capture("update_version_compared", {
|
|
2446
|
+
current_version: currentVersion,
|
|
2447
|
+
target_version: version,
|
|
2448
|
+
version_status: versionStatus,
|
|
2449
|
+
force: args.force
|
|
2450
|
+
});
|
|
2297
2451
|
console.log(`Updating: v${currentVersion} \u2192 v${version}`);
|
|
2298
2452
|
console.log();
|
|
2299
|
-
const changelogPath =
|
|
2453
|
+
const changelogPath = join14(templateDir, "CHANGELOG.md");
|
|
2300
2454
|
const whatsNew = await getWhatsNew(changelogPath, currentVersion, version);
|
|
2301
2455
|
if (whatsNew.length > 0) {
|
|
2302
2456
|
console.log(pc7.cyan("What's new:"));
|
|
@@ -2308,23 +2462,23 @@ var init_update = __esm({
|
|
|
2308
2462
|
}
|
|
2309
2463
|
const now = /* @__PURE__ */ new Date();
|
|
2310
2464
|
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")}`;
|
|
2311
|
-
const backupDir =
|
|
2312
|
-
await
|
|
2465
|
+
const backupDir = join14(targetDir, ".flydocs", `backup-${ts}`);
|
|
2466
|
+
await mkdir7(backupDir, { recursive: true });
|
|
2313
2467
|
if (hasConfig) {
|
|
2314
2468
|
await cp2(
|
|
2315
|
-
|
|
2316
|
-
|
|
2469
|
+
join14(targetDir, ".flydocs", "config.json"),
|
|
2470
|
+
join14(backupDir, "config.json")
|
|
2317
2471
|
);
|
|
2318
2472
|
printStatus(`Config backed up to .flydocs/backup-${ts}/`);
|
|
2319
2473
|
}
|
|
2320
2474
|
try {
|
|
2321
|
-
const flydocsDir =
|
|
2475
|
+
const flydocsDir = join14(targetDir, ".flydocs");
|
|
2322
2476
|
const entries = await readdir3(flydocsDir);
|
|
2323
2477
|
const backups = entries.filter((e) => e.startsWith("backup-")).sort();
|
|
2324
2478
|
if (backups.length > 3) {
|
|
2325
2479
|
const toRemove = backups.slice(0, backups.length - 3);
|
|
2326
2480
|
for (const old of toRemove) {
|
|
2327
|
-
await rm4(
|
|
2481
|
+
await rm4(join14(flydocsDir, old), { recursive: true, force: true });
|
|
2328
2482
|
}
|
|
2329
2483
|
}
|
|
2330
2484
|
} catch {
|
|
@@ -2361,20 +2515,20 @@ var init_update = __esm({
|
|
|
2361
2515
|
}
|
|
2362
2516
|
console.log("Replacing framework directories...");
|
|
2363
2517
|
await replaceDirectory(
|
|
2364
|
-
|
|
2365
|
-
|
|
2518
|
+
join14(templateDir, ".flydocs", "templates"),
|
|
2519
|
+
join14(targetDir, ".flydocs", "templates")
|
|
2366
2520
|
);
|
|
2367
2521
|
await replaceDirectory(
|
|
2368
|
-
|
|
2369
|
-
|
|
2522
|
+
join14(templateDir, ".flydocs", "hooks"),
|
|
2523
|
+
join14(targetDir, ".flydocs", "hooks")
|
|
2370
2524
|
);
|
|
2371
2525
|
await replaceDirectory(
|
|
2372
|
-
|
|
2373
|
-
|
|
2526
|
+
join14(templateDir, ".flydocs", "scripts"),
|
|
2527
|
+
join14(targetDir, ".flydocs", "scripts")
|
|
2374
2528
|
);
|
|
2375
2529
|
printStatus(".flydocs/templates, hooks, scripts");
|
|
2376
2530
|
const hasExistingAgents = await pathExists(
|
|
2377
|
-
|
|
2531
|
+
join14(targetDir, ".claude", "agents")
|
|
2378
2532
|
);
|
|
2379
2533
|
let installAgents;
|
|
2380
2534
|
if (args.yes) {
|
|
@@ -2406,20 +2560,20 @@ var init_update = __esm({
|
|
|
2406
2560
|
}
|
|
2407
2561
|
}
|
|
2408
2562
|
if (installAgents) {
|
|
2409
|
-
const claudeAgentsSrc =
|
|
2563
|
+
const claudeAgentsSrc = join14(templateDir, ".claude", "agents");
|
|
2410
2564
|
if (await pathExists(claudeAgentsSrc)) {
|
|
2411
|
-
await
|
|
2565
|
+
await mkdir7(join14(targetDir, ".claude", "agents"), { recursive: true });
|
|
2412
2566
|
await copyDirectoryContents(
|
|
2413
2567
|
claudeAgentsSrc,
|
|
2414
|
-
|
|
2568
|
+
join14(targetDir, ".claude", "agents")
|
|
2415
2569
|
);
|
|
2416
2570
|
}
|
|
2417
|
-
const cursorAgentsSrc =
|
|
2571
|
+
const cursorAgentsSrc = join14(templateDir, ".cursor", "agents");
|
|
2418
2572
|
if (await pathExists(cursorAgentsSrc)) {
|
|
2419
|
-
await
|
|
2573
|
+
await mkdir7(join14(targetDir, ".cursor", "agents"), { recursive: true });
|
|
2420
2574
|
await copyDirectoryContents(
|
|
2421
2575
|
cursorAgentsSrc,
|
|
2422
|
-
|
|
2576
|
+
join14(targetDir, ".cursor", "agents")
|
|
2423
2577
|
);
|
|
2424
2578
|
}
|
|
2425
2579
|
printStatus(
|
|
@@ -2433,44 +2587,44 @@ var init_update = __esm({
|
|
|
2433
2587
|
console.log();
|
|
2434
2588
|
console.log("Replacing framework files...");
|
|
2435
2589
|
await copyFile(
|
|
2436
|
-
|
|
2437
|
-
|
|
2590
|
+
join14(templateDir, ".claude", "CLAUDE.md"),
|
|
2591
|
+
join14(targetDir, ".claude", "CLAUDE.md")
|
|
2438
2592
|
);
|
|
2439
2593
|
await copyFile(
|
|
2440
|
-
|
|
2441
|
-
|
|
2594
|
+
join14(templateDir, ".claude", "settings.json"),
|
|
2595
|
+
join14(targetDir, ".claude", "settings.json")
|
|
2442
2596
|
);
|
|
2443
2597
|
printStatus(".claude/CLAUDE.md, settings.json");
|
|
2444
2598
|
await copyDirectoryContents(
|
|
2445
|
-
|
|
2446
|
-
|
|
2599
|
+
join14(templateDir, ".claude", "commands"),
|
|
2600
|
+
join14(targetDir, ".claude", "commands")
|
|
2447
2601
|
);
|
|
2448
2602
|
await copyDirectoryContents(
|
|
2449
|
-
|
|
2450
|
-
|
|
2603
|
+
join14(templateDir, ".claude", "commands"),
|
|
2604
|
+
join14(targetDir, ".cursor", "commands")
|
|
2451
2605
|
);
|
|
2452
2606
|
printStatus(".claude/commands, .cursor/commands");
|
|
2453
|
-
const skillsReadmeSrc =
|
|
2607
|
+
const skillsReadmeSrc = join14(templateDir, ".claude", "skills", "README.md");
|
|
2454
2608
|
if (await pathExists(skillsReadmeSrc)) {
|
|
2455
2609
|
await copyFile(
|
|
2456
2610
|
skillsReadmeSrc,
|
|
2457
|
-
|
|
2611
|
+
join14(targetDir, ".claude", "skills", "README.md")
|
|
2458
2612
|
);
|
|
2459
2613
|
}
|
|
2460
2614
|
printStatus(".claude/skills/README.md");
|
|
2461
2615
|
await copyFile(
|
|
2462
|
-
|
|
2463
|
-
|
|
2616
|
+
join14(templateDir, ".cursor", "hooks.json"),
|
|
2617
|
+
join14(targetDir, ".cursor", "hooks.json")
|
|
2464
2618
|
);
|
|
2465
2619
|
printStatus(".cursor/hooks.json");
|
|
2466
2620
|
await copyFile(
|
|
2467
|
-
|
|
2468
|
-
|
|
2621
|
+
join14(templateDir, "AGENTS.md"),
|
|
2622
|
+
join14(targetDir, "AGENTS.md")
|
|
2469
2623
|
);
|
|
2470
2624
|
printStatus("AGENTS.md");
|
|
2471
|
-
const envExampleSrc =
|
|
2625
|
+
const envExampleSrc = join14(templateDir, ".env.example");
|
|
2472
2626
|
if (await pathExists(envExampleSrc)) {
|
|
2473
|
-
await copyFile(envExampleSrc,
|
|
2627
|
+
await copyFile(envExampleSrc, join14(targetDir, ".env.example"));
|
|
2474
2628
|
printStatus(".env.example");
|
|
2475
2629
|
}
|
|
2476
2630
|
await runManifestGeneration(targetDir);
|
|
@@ -2495,18 +2649,18 @@ var init_update = __esm({
|
|
|
2495
2649
|
printWarning("Config merge failed \u2014 config.json preserved as-is");
|
|
2496
2650
|
}
|
|
2497
2651
|
await copyFile(
|
|
2498
|
-
|
|
2499
|
-
|
|
2652
|
+
join14(templateDir, ".flydocs", "version"),
|
|
2653
|
+
join14(targetDir, ".flydocs", "version")
|
|
2500
2654
|
);
|
|
2501
2655
|
printStatus(`.flydocs/version \u2192 ${version}`);
|
|
2502
|
-
const clSrc =
|
|
2656
|
+
const clSrc = join14(templateDir, "CHANGELOG.md");
|
|
2503
2657
|
if (await pathExists(clSrc)) {
|
|
2504
|
-
await copyFile(clSrc,
|
|
2658
|
+
await copyFile(clSrc, join14(targetDir, ".flydocs", "CHANGELOG.md"));
|
|
2505
2659
|
printStatus(".flydocs/CHANGELOG.md");
|
|
2506
2660
|
}
|
|
2507
|
-
const mfSrc =
|
|
2661
|
+
const mfSrc = join14(templateDir, "manifest.json");
|
|
2508
2662
|
if (await pathExists(mfSrc)) {
|
|
2509
|
-
await copyFile(mfSrc,
|
|
2663
|
+
await copyFile(mfSrc, join14(targetDir, ".flydocs", "manifest.json"));
|
|
2510
2664
|
printStatus(".flydocs/manifest.json");
|
|
2511
2665
|
}
|
|
2512
2666
|
console.log();
|
|
@@ -2542,6 +2696,12 @@ var init_update = __esm({
|
|
|
2542
2696
|
`Backup: .flydocs/backup-${ts}/`
|
|
2543
2697
|
]);
|
|
2544
2698
|
printBetaCta();
|
|
2699
|
+
await capture("update_completed", {
|
|
2700
|
+
current_version: currentVersion,
|
|
2701
|
+
version,
|
|
2702
|
+
tier: effectiveTier
|
|
2703
|
+
});
|
|
2704
|
+
await flush();
|
|
2545
2705
|
try {
|
|
2546
2706
|
const updateResult = await checkForUpdate();
|
|
2547
2707
|
if (updateResult) {
|
|
@@ -2554,33 +2714,336 @@ var init_update = __esm({
|
|
|
2554
2714
|
}
|
|
2555
2715
|
});
|
|
2556
2716
|
|
|
2717
|
+
// src/commands/uninstall.ts
|
|
2718
|
+
var uninstall_exports = {};
|
|
2719
|
+
__export(uninstall_exports, {
|
|
2720
|
+
default: () => uninstall_default
|
|
2721
|
+
});
|
|
2722
|
+
import { defineCommand as defineCommand3 } from "citty";
|
|
2723
|
+
import { resolve as resolve4, join as join15 } from "path";
|
|
2724
|
+
import { readdir as readdir4, rm as rm5, rename as rename2 } from "fs/promises";
|
|
2725
|
+
import { confirm as confirm4, select as select3, isCancel as isCancel5, cancel as cancel4 } from "@clack/prompts";
|
|
2726
|
+
import pc8 from "picocolors";
|
|
2727
|
+
async function removeOwnedSkills(targetDir) {
|
|
2728
|
+
const skillsDir = join15(targetDir, ".claude", "skills");
|
|
2729
|
+
const removed = [];
|
|
2730
|
+
if (!await pathExists(skillsDir)) {
|
|
2731
|
+
return removed;
|
|
2732
|
+
}
|
|
2733
|
+
try {
|
|
2734
|
+
const entries = await readdir4(skillsDir);
|
|
2735
|
+
for (const entry of entries) {
|
|
2736
|
+
if (entry.startsWith(OWNED_SKILL_PREFIX)) {
|
|
2737
|
+
await rm5(join15(skillsDir, entry), { recursive: true, force: true });
|
|
2738
|
+
removed.push(`.claude/skills/${entry}`);
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
} catch {
|
|
2742
|
+
}
|
|
2743
|
+
return removed;
|
|
2744
|
+
}
|
|
2745
|
+
async function removeOwnedCursorRules(targetDir) {
|
|
2746
|
+
const rulesDir = join15(targetDir, ".cursor", "rules");
|
|
2747
|
+
const removed = [];
|
|
2748
|
+
if (!await pathExists(rulesDir)) {
|
|
2749
|
+
return removed;
|
|
2750
|
+
}
|
|
2751
|
+
try {
|
|
2752
|
+
const entries = await readdir4(rulesDir);
|
|
2753
|
+
for (const entry of entries) {
|
|
2754
|
+
if (entry.startsWith(OWNED_RULE_PREFIX) && entry.endsWith(".mdc")) {
|
|
2755
|
+
await rm5(join15(rulesDir, entry), { force: true });
|
|
2756
|
+
removed.push(`.cursor/rules/${entry}`);
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2759
|
+
} catch {
|
|
2760
|
+
}
|
|
2761
|
+
return removed;
|
|
2762
|
+
}
|
|
2763
|
+
async function isEmptyDir(dirPath) {
|
|
2764
|
+
try {
|
|
2765
|
+
const entries = await readdir4(dirPath);
|
|
2766
|
+
return entries.length === 0;
|
|
2767
|
+
} catch {
|
|
2768
|
+
return false;
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
async function cleanupEmptyParents(targetDir, dirs) {
|
|
2772
|
+
const cleaned = [];
|
|
2773
|
+
for (const dir of dirs) {
|
|
2774
|
+
const fullPath = join15(targetDir, dir);
|
|
2775
|
+
if (await pathExists(fullPath) && await isEmptyDir(fullPath)) {
|
|
2776
|
+
await rm5(fullPath, { recursive: true, force: true });
|
|
2777
|
+
cleaned.push(dir);
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
return cleaned;
|
|
2781
|
+
}
|
|
2782
|
+
var ALWAYS_REMOVED, OWNED_SKILL_PREFIX, OWNED_RULE_PREFIX, uninstall_default;
|
|
2783
|
+
var init_uninstall = __esm({
|
|
2784
|
+
"src/commands/uninstall.ts"() {
|
|
2785
|
+
"use strict";
|
|
2786
|
+
init_fs_ops();
|
|
2787
|
+
init_ui();
|
|
2788
|
+
init_constants();
|
|
2789
|
+
ALWAYS_REMOVED = [
|
|
2790
|
+
[".claude/CLAUDE.md", "file"],
|
|
2791
|
+
[".claude/settings.json", "file"],
|
|
2792
|
+
[".claude/agents", "dir"],
|
|
2793
|
+
[".claude/commands", "dir"],
|
|
2794
|
+
[".claude/skills/README.md", "file"],
|
|
2795
|
+
[".cursor/hooks.json", "file"],
|
|
2796
|
+
[".cursor/agents", "dir"],
|
|
2797
|
+
[".flydocs", "dir"],
|
|
2798
|
+
["AGENTS.md", "file"],
|
|
2799
|
+
[".env.example", "file"]
|
|
2800
|
+
];
|
|
2801
|
+
OWNED_SKILL_PREFIX = "flydocs-";
|
|
2802
|
+
OWNED_RULE_PREFIX = "flydocs-";
|
|
2803
|
+
uninstall_default = defineCommand3({
|
|
2804
|
+
meta: {
|
|
2805
|
+
name: "uninstall",
|
|
2806
|
+
description: "Remove FlyDocs from a project directory"
|
|
2807
|
+
},
|
|
2808
|
+
args: {
|
|
2809
|
+
path: {
|
|
2810
|
+
type: "string",
|
|
2811
|
+
description: "Uninstall from the specified directory"
|
|
2812
|
+
},
|
|
2813
|
+
here: {
|
|
2814
|
+
type: "boolean",
|
|
2815
|
+
description: "Uninstall from the current directory",
|
|
2816
|
+
default: false
|
|
2817
|
+
},
|
|
2818
|
+
all: {
|
|
2819
|
+
type: "boolean",
|
|
2820
|
+
description: "Remove everything including flydocs/ user content",
|
|
2821
|
+
default: false
|
|
2822
|
+
},
|
|
2823
|
+
yes: {
|
|
2824
|
+
type: "boolean",
|
|
2825
|
+
alias: ["y"],
|
|
2826
|
+
description: "Skip confirmation prompts",
|
|
2827
|
+
default: false
|
|
2828
|
+
},
|
|
2829
|
+
force: {
|
|
2830
|
+
type: "boolean",
|
|
2831
|
+
description: "Alias for --all --yes (complete removal, no prompts)",
|
|
2832
|
+
default: false
|
|
2833
|
+
}
|
|
2834
|
+
},
|
|
2835
|
+
async run({ args }) {
|
|
2836
|
+
printBanner(CLI_VERSION);
|
|
2837
|
+
let targetDir;
|
|
2838
|
+
if (args.path) {
|
|
2839
|
+
targetDir = resolve4(args.path.replace(/^~/, process.env.HOME ?? "~"));
|
|
2840
|
+
} else if (args.here) {
|
|
2841
|
+
targetDir = process.cwd();
|
|
2842
|
+
} else {
|
|
2843
|
+
targetDir = process.cwd();
|
|
2844
|
+
}
|
|
2845
|
+
if (!await pathExists(targetDir)) {
|
|
2846
|
+
printError(`Directory does not exist: ${targetDir}`);
|
|
2847
|
+
process.exit(1);
|
|
2848
|
+
}
|
|
2849
|
+
targetDir = resolve4(targetDir);
|
|
2850
|
+
const hasFlydocs = await pathExists(join15(targetDir, ".flydocs"));
|
|
2851
|
+
const hasAgentsMd = await pathExists(join15(targetDir, "AGENTS.md"));
|
|
2852
|
+
if (!hasFlydocs && !hasAgentsMd) {
|
|
2853
|
+
printError(`Not a FlyDocs project: ${targetDir}`);
|
|
2854
|
+
printInfo("No .flydocs/ directory or AGENTS.md found.");
|
|
2855
|
+
process.exit(1);
|
|
2856
|
+
}
|
|
2857
|
+
printInfo(`Project: ${targetDir}`);
|
|
2858
|
+
console.log();
|
|
2859
|
+
const forceAll = args.force;
|
|
2860
|
+
const removeAll = forceAll || args.all;
|
|
2861
|
+
const skipPrompts = forceAll || args.yes;
|
|
2862
|
+
let contentAction = "preserve";
|
|
2863
|
+
const hasUserContent = await pathExists(join15(targetDir, "flydocs"));
|
|
2864
|
+
if (hasUserContent) {
|
|
2865
|
+
if (removeAll) {
|
|
2866
|
+
contentAction = "remove";
|
|
2867
|
+
} else if (!skipPrompts) {
|
|
2868
|
+
const choice = await select3({
|
|
2869
|
+
message: "What should happen to your flydocs/ content (project docs, knowledge base)?",
|
|
2870
|
+
options: [
|
|
2871
|
+
{
|
|
2872
|
+
value: "archive",
|
|
2873
|
+
label: "Archive",
|
|
2874
|
+
hint: "Rename to flydocs-archive/ (safe, reversible)"
|
|
2875
|
+
},
|
|
2876
|
+
{
|
|
2877
|
+
value: "remove",
|
|
2878
|
+
label: "Remove completely",
|
|
2879
|
+
hint: "Permanently delete flydocs/ and all contents"
|
|
2880
|
+
},
|
|
2881
|
+
{
|
|
2882
|
+
value: "preserve",
|
|
2883
|
+
label: "Keep as-is",
|
|
2884
|
+
hint: "Leave flydocs/ untouched"
|
|
2885
|
+
}
|
|
2886
|
+
]
|
|
2887
|
+
});
|
|
2888
|
+
if (isCancel5(choice)) {
|
|
2889
|
+
cancel4("Uninstall cancelled.");
|
|
2890
|
+
process.exit(0);
|
|
2891
|
+
}
|
|
2892
|
+
contentAction = choice;
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
if (!skipPrompts) {
|
|
2896
|
+
console.log();
|
|
2897
|
+
console.log(pc8.bold("The following will be removed:"));
|
|
2898
|
+
console.log();
|
|
2899
|
+
console.log(" Framework files:");
|
|
2900
|
+
for (const [path] of ALWAYS_REMOVED) {
|
|
2901
|
+
console.log(` ${pc8.dim(path)}`);
|
|
2902
|
+
}
|
|
2903
|
+
console.log(` ${pc8.dim(".claude/skills/flydocs-*")}`);
|
|
2904
|
+
console.log(` ${pc8.dim(".cursor/rules/flydocs-*.mdc")}`);
|
|
2905
|
+
if (hasUserContent) {
|
|
2906
|
+
if (contentAction === "archive") {
|
|
2907
|
+
console.log();
|
|
2908
|
+
console.log(
|
|
2909
|
+
` User content: ${pc8.yellow("flydocs/ -> flydocs-archive/")}`
|
|
2910
|
+
);
|
|
2911
|
+
} else if (contentAction === "remove") {
|
|
2912
|
+
console.log();
|
|
2913
|
+
console.log(` User content: ${pc8.red("flydocs/ (deleted)")}`);
|
|
2914
|
+
} else {
|
|
2915
|
+
console.log();
|
|
2916
|
+
console.log(` User content: ${pc8.green("flydocs/ (preserved)")}`);
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
console.log();
|
|
2920
|
+
console.log(pc8.bold("Preserved:"));
|
|
2921
|
+
console.log(
|
|
2922
|
+
` ${pc8.dim(".claude/skills/ (non-flydocs community skills)")}`
|
|
2923
|
+
);
|
|
2924
|
+
console.log(` ${pc8.dim(".env, .env.local")}`);
|
|
2925
|
+
console.log();
|
|
2926
|
+
const shouldContinue = await confirm4({
|
|
2927
|
+
message: "Proceed with uninstall?"
|
|
2928
|
+
});
|
|
2929
|
+
if (isCancel5(shouldContinue) || !shouldContinue) {
|
|
2930
|
+
cancel4("Uninstall cancelled.");
|
|
2931
|
+
process.exit(0);
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
const result = {
|
|
2935
|
+
removed: [],
|
|
2936
|
+
skipped: [],
|
|
2937
|
+
archived: []
|
|
2938
|
+
};
|
|
2939
|
+
const removedSkills = await removeOwnedSkills(targetDir);
|
|
2940
|
+
result.removed.push(...removedSkills);
|
|
2941
|
+
const removedRules = await removeOwnedCursorRules(targetDir);
|
|
2942
|
+
result.removed.push(...removedRules);
|
|
2943
|
+
for (const [relativePath, type] of ALWAYS_REMOVED) {
|
|
2944
|
+
const fullPath = join15(targetDir, relativePath);
|
|
2945
|
+
if (!await pathExists(fullPath)) {
|
|
2946
|
+
result.skipped.push(relativePath);
|
|
2947
|
+
continue;
|
|
2948
|
+
}
|
|
2949
|
+
try {
|
|
2950
|
+
if (type === "dir") {
|
|
2951
|
+
await rm5(fullPath, { recursive: true, force: true });
|
|
2952
|
+
} else {
|
|
2953
|
+
await rm5(fullPath, { force: true });
|
|
2954
|
+
}
|
|
2955
|
+
result.removed.push(relativePath);
|
|
2956
|
+
} catch {
|
|
2957
|
+
printWarning(`Could not remove: ${relativePath}`);
|
|
2958
|
+
result.skipped.push(relativePath);
|
|
2959
|
+
}
|
|
2960
|
+
}
|
|
2961
|
+
if (hasUserContent) {
|
|
2962
|
+
const flydocsPath = join15(targetDir, "flydocs");
|
|
2963
|
+
if (contentAction === "archive") {
|
|
2964
|
+
const archivePath = join15(targetDir, "flydocs-archive");
|
|
2965
|
+
if (await pathExists(archivePath)) {
|
|
2966
|
+
await rm5(archivePath, { recursive: true, force: true });
|
|
2967
|
+
}
|
|
2968
|
+
await rename2(flydocsPath, archivePath);
|
|
2969
|
+
result.archived.push("flydocs/ -> flydocs-archive/");
|
|
2970
|
+
} else if (contentAction === "remove") {
|
|
2971
|
+
await rm5(flydocsPath, { recursive: true, force: true });
|
|
2972
|
+
result.removed.push("flydocs/");
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2975
|
+
const emptyCandidates = [
|
|
2976
|
+
".claude/skills",
|
|
2977
|
+
".claude",
|
|
2978
|
+
".cursor/rules",
|
|
2979
|
+
".cursor"
|
|
2980
|
+
];
|
|
2981
|
+
const cleaned = await cleanupEmptyParents(targetDir, emptyCandidates);
|
|
2982
|
+
for (const dir of cleaned) {
|
|
2983
|
+
result.removed.push(`${dir}/ (empty, cleaned up)`);
|
|
2984
|
+
}
|
|
2985
|
+
console.log();
|
|
2986
|
+
console.log(pc8.bold("Uninstall Summary"));
|
|
2987
|
+
console.log();
|
|
2988
|
+
if (result.removed.length > 0) {
|
|
2989
|
+
console.log(` ${pc8.green("Removed")} (${result.removed.length}):`);
|
|
2990
|
+
for (const item of result.removed) {
|
|
2991
|
+
printStatus(item);
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
if (result.archived.length > 0) {
|
|
2995
|
+
console.log();
|
|
2996
|
+
console.log(` ${pc8.yellow("Archived")} (${result.archived.length}):`);
|
|
2997
|
+
for (const item of result.archived) {
|
|
2998
|
+
printInfo(item);
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
if (result.skipped.length > 0) {
|
|
3002
|
+
console.log();
|
|
3003
|
+
console.log(
|
|
3004
|
+
` ${pc8.dim("Skipped")} (${result.skipped.length} \u2014 not found):`
|
|
3005
|
+
);
|
|
3006
|
+
for (const item of result.skipped) {
|
|
3007
|
+
console.log(` ${pc8.dim(item)}`);
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
console.log();
|
|
3011
|
+
printStatus("FlyDocs has been removed from this project.");
|
|
3012
|
+
console.log();
|
|
3013
|
+
printInfo(`To reinstall: ${pc8.cyan("npx @flydocs/cli install --here")}`);
|
|
3014
|
+
console.log();
|
|
3015
|
+
}
|
|
3016
|
+
});
|
|
3017
|
+
}
|
|
3018
|
+
});
|
|
3019
|
+
|
|
2557
3020
|
// src/commands/setup.ts
|
|
2558
3021
|
var setup_exports = {};
|
|
2559
3022
|
__export(setup_exports, {
|
|
2560
3023
|
default: () => setup_default
|
|
2561
3024
|
});
|
|
2562
|
-
import { defineCommand as
|
|
2563
|
-
import
|
|
3025
|
+
import { defineCommand as defineCommand4 } from "citty";
|
|
3026
|
+
import pc9 from "picocolors";
|
|
2564
3027
|
var setup_default;
|
|
2565
3028
|
var init_setup = __esm({
|
|
2566
3029
|
"src/commands/setup.ts"() {
|
|
2567
3030
|
"use strict";
|
|
2568
|
-
setup_default =
|
|
3031
|
+
setup_default = defineCommand4({
|
|
2569
3032
|
meta: {
|
|
2570
3033
|
name: "setup",
|
|
2571
3034
|
description: "Configure FlyDocs settings for this project"
|
|
2572
3035
|
},
|
|
2573
3036
|
run() {
|
|
2574
3037
|
console.log();
|
|
2575
|
-
console.log(` ${
|
|
3038
|
+
console.log(` ${pc9.bold("FlyDocs Setup")}`);
|
|
2576
3039
|
console.log();
|
|
2577
3040
|
console.log(` Setup runs inside your IDE as an interactive AI command.`);
|
|
2578
3041
|
console.log();
|
|
2579
3042
|
console.log(
|
|
2580
|
-
` ${
|
|
3043
|
+
` ${pc9.cyan("Claude Code:")} Type ${pc9.bold("/flydocs-setup")} in chat`
|
|
2581
3044
|
);
|
|
2582
3045
|
console.log(
|
|
2583
|
-
` ${
|
|
3046
|
+
` ${pc9.cyan("Cursor:")} Type ${pc9.bold("/flydocs-setup")} in chat`
|
|
2584
3047
|
);
|
|
2585
3048
|
console.log();
|
|
2586
3049
|
console.log(` This configures your project context, detects your stack,`);
|
|
@@ -2596,14 +3059,14 @@ var skills_exports = {};
|
|
|
2596
3059
|
__export(skills_exports, {
|
|
2597
3060
|
default: () => skills_default
|
|
2598
3061
|
});
|
|
2599
|
-
import { defineCommand as
|
|
2600
|
-
import
|
|
3062
|
+
import { defineCommand as defineCommand5 } from "citty";
|
|
3063
|
+
import pc10 from "picocolors";
|
|
2601
3064
|
var list, search, add, remove, skills_default;
|
|
2602
3065
|
var init_skills2 = __esm({
|
|
2603
3066
|
"src/commands/skills.ts"() {
|
|
2604
3067
|
"use strict";
|
|
2605
3068
|
init_skill_manager();
|
|
2606
|
-
list =
|
|
3069
|
+
list = defineCommand5({
|
|
2607
3070
|
meta: {
|
|
2608
3071
|
name: "list",
|
|
2609
3072
|
description: "List installed skills"
|
|
@@ -2619,26 +3082,26 @@ var init_skills2 = __esm({
|
|
|
2619
3082
|
console.log(`${total} skill(s) installed:`);
|
|
2620
3083
|
if (result.platform.length > 0) {
|
|
2621
3084
|
console.log();
|
|
2622
|
-
console.log(
|
|
3085
|
+
console.log(pc10.bold("Platform"));
|
|
2623
3086
|
for (const skill of result.platform) {
|
|
2624
3087
|
console.log(
|
|
2625
|
-
` ${skill.name} ${
|
|
3088
|
+
` ${skill.name} ${pc10.dim(`(${skill.triggers} triggers)`)}`
|
|
2626
3089
|
);
|
|
2627
3090
|
}
|
|
2628
3091
|
}
|
|
2629
3092
|
if (result.community.length > 0) {
|
|
2630
3093
|
console.log();
|
|
2631
|
-
console.log(
|
|
3094
|
+
console.log(pc10.bold("Community"));
|
|
2632
3095
|
for (const skill of result.community) {
|
|
2633
3096
|
console.log(
|
|
2634
|
-
` ${skill.name} ${
|
|
3097
|
+
` ${skill.name} ${pc10.dim(`(${skill.triggers} triggers)`)}`
|
|
2635
3098
|
);
|
|
2636
3099
|
}
|
|
2637
3100
|
}
|
|
2638
3101
|
console.log();
|
|
2639
3102
|
}
|
|
2640
3103
|
});
|
|
2641
|
-
search =
|
|
3104
|
+
search = defineCommand5({
|
|
2642
3105
|
meta: {
|
|
2643
3106
|
name: "search",
|
|
2644
3107
|
description: "Search community skills"
|
|
@@ -2654,24 +3117,24 @@ var init_skills2 = __esm({
|
|
|
2654
3117
|
const results = await searchCatalog(args.keyword);
|
|
2655
3118
|
if (results.length === 0) {
|
|
2656
3119
|
console.log(`No skills found for "${args.keyword}".`);
|
|
2657
|
-
console.log(` Browse the catalog at: ${
|
|
3120
|
+
console.log(` Browse the catalog at: ${pc10.cyan("https://skills.sh/")}`);
|
|
2658
3121
|
return;
|
|
2659
3122
|
}
|
|
2660
3123
|
console.log();
|
|
2661
3124
|
console.log(`${results.length} skill(s) matching "${args.keyword}":`);
|
|
2662
3125
|
console.log();
|
|
2663
3126
|
for (const skill of results) {
|
|
2664
|
-
console.log(` ${
|
|
3127
|
+
console.log(` ${pc10.bold(skill.name)}`);
|
|
2665
3128
|
console.log(` ${skill.description}`);
|
|
2666
|
-
console.log(` ${
|
|
3129
|
+
console.log(` ${pc10.dim(skill.repo)}`);
|
|
2667
3130
|
if (skill.tags.length > 0) {
|
|
2668
|
-
console.log(` ${
|
|
3131
|
+
console.log(` ${pc10.dim(skill.tags.join(", "))}`);
|
|
2669
3132
|
}
|
|
2670
3133
|
console.log();
|
|
2671
3134
|
}
|
|
2672
3135
|
}
|
|
2673
3136
|
});
|
|
2674
|
-
add =
|
|
3137
|
+
add = defineCommand5({
|
|
2675
3138
|
meta: {
|
|
2676
3139
|
name: "add",
|
|
2677
3140
|
description: "Install a community skill"
|
|
@@ -2687,7 +3150,7 @@ var init_skills2 = __esm({
|
|
|
2687
3150
|
await addSkill(process.cwd(), args.source);
|
|
2688
3151
|
}
|
|
2689
3152
|
});
|
|
2690
|
-
remove =
|
|
3153
|
+
remove = defineCommand5({
|
|
2691
3154
|
meta: {
|
|
2692
3155
|
name: "remove",
|
|
2693
3156
|
description: "Remove an installed community skill"
|
|
@@ -2703,7 +3166,7 @@ var init_skills2 = __esm({
|
|
|
2703
3166
|
await removeSkill(process.cwd(), args.name);
|
|
2704
3167
|
}
|
|
2705
3168
|
});
|
|
2706
|
-
skills_default =
|
|
3169
|
+
skills_default = defineCommand5({
|
|
2707
3170
|
meta: {
|
|
2708
3171
|
name: "skills",
|
|
2709
3172
|
description: "Manage FlyDocs skills (list, search, add, remove)"
|
|
@@ -2723,11 +3186,11 @@ var connect_exports = {};
|
|
|
2723
3186
|
__export(connect_exports, {
|
|
2724
3187
|
default: () => connect_default
|
|
2725
3188
|
});
|
|
2726
|
-
import { defineCommand as
|
|
2727
|
-
import { text as text2, confirm as
|
|
2728
|
-
import
|
|
2729
|
-
import { readFile as
|
|
2730
|
-
import { join as
|
|
3189
|
+
import { defineCommand as defineCommand6 } from "citty";
|
|
3190
|
+
import { text as text2, confirm as confirm5, isCancel as isCancel6, cancel as cancel5 } from "@clack/prompts";
|
|
3191
|
+
import pc11 from "picocolors";
|
|
3192
|
+
import { readFile as readFile10, writeFile as writeFile6, appendFile as appendFile2 } from "fs/promises";
|
|
3193
|
+
import { join as join16 } from "path";
|
|
2731
3194
|
var connect_default;
|
|
2732
3195
|
var init_connect = __esm({
|
|
2733
3196
|
"src/commands/connect.ts"() {
|
|
@@ -2736,7 +3199,7 @@ var init_connect = __esm({
|
|
|
2736
3199
|
init_fs_ops();
|
|
2737
3200
|
init_template();
|
|
2738
3201
|
init_ui();
|
|
2739
|
-
connect_default =
|
|
3202
|
+
connect_default = defineCommand6({
|
|
2740
3203
|
meta: {
|
|
2741
3204
|
name: "connect",
|
|
2742
3205
|
description: "Connect FlyDocs to a cloud provider (Linear)"
|
|
@@ -2761,11 +3224,11 @@ var init_connect = __esm({
|
|
|
2761
3224
|
},
|
|
2762
3225
|
async run({ args }) {
|
|
2763
3226
|
const targetDir = args.path ?? process.cwd();
|
|
2764
|
-
const configPath =
|
|
3227
|
+
const configPath = join16(targetDir, ".flydocs", "config.json");
|
|
2765
3228
|
if (!await pathExists(configPath)) {
|
|
2766
3229
|
printError("Not a FlyDocs project (.flydocs/config.json not found).");
|
|
2767
3230
|
console.log(
|
|
2768
|
-
` Run ${
|
|
3231
|
+
` Run ${pc11.cyan("flydocs")} first to install FlyDocs in this project.`
|
|
2769
3232
|
);
|
|
2770
3233
|
process.exit(1);
|
|
2771
3234
|
}
|
|
@@ -2773,19 +3236,19 @@ var init_connect = __esm({
|
|
|
2773
3236
|
if (config.tier === "cloud") {
|
|
2774
3237
|
printInfo("This project is already connected to the cloud tier.");
|
|
2775
3238
|
console.log();
|
|
2776
|
-
const reconnect = await
|
|
3239
|
+
const reconnect = await confirm5({
|
|
2777
3240
|
message: "Want to update your API key?"
|
|
2778
3241
|
});
|
|
2779
|
-
if (
|
|
3242
|
+
if (isCancel6(reconnect) || !reconnect) {
|
|
2780
3243
|
console.log(` No changes made.`);
|
|
2781
3244
|
return;
|
|
2782
3245
|
}
|
|
2783
3246
|
}
|
|
2784
3247
|
console.log();
|
|
2785
|
-
console.log(` ${
|
|
3248
|
+
console.log(` ${pc11.bold("Connect to Linear")}`);
|
|
2786
3249
|
console.log();
|
|
2787
3250
|
console.log(
|
|
2788
|
-
` ${
|
|
3251
|
+
` ${pc11.dim("Get your API key from: Linear \u2192 Settings \u2192 API \u2192 Personal API keys")}`
|
|
2789
3252
|
);
|
|
2790
3253
|
console.log();
|
|
2791
3254
|
let apiKey = args.key ?? "";
|
|
@@ -2800,8 +3263,8 @@ var init_connect = __esm({
|
|
|
2800
3263
|
return void 0;
|
|
2801
3264
|
}
|
|
2802
3265
|
});
|
|
2803
|
-
if (
|
|
2804
|
-
|
|
3266
|
+
if (isCancel6(keyInput)) {
|
|
3267
|
+
cancel5("Connection cancelled.");
|
|
2805
3268
|
process.exit(0);
|
|
2806
3269
|
}
|
|
2807
3270
|
apiKey = keyInput;
|
|
@@ -2825,34 +3288,34 @@ var init_connect = __esm({
|
|
|
2825
3288
|
throw new Error("Invalid response");
|
|
2826
3289
|
}
|
|
2827
3290
|
const viewer = data.data.viewer;
|
|
2828
|
-
printStatus(`Authenticated as ${
|
|
3291
|
+
printStatus(`Authenticated as ${pc11.bold(viewer.name)} (${viewer.email})`);
|
|
2829
3292
|
} catch {
|
|
2830
3293
|
printError("Invalid API key or network error.");
|
|
2831
3294
|
console.log(` Check your key and try again.`);
|
|
2832
3295
|
process.exit(1);
|
|
2833
3296
|
}
|
|
2834
|
-
const envPath =
|
|
2835
|
-
const envLocalPath =
|
|
3297
|
+
const envPath = join16(targetDir, ".env");
|
|
3298
|
+
const envLocalPath = join16(targetDir, ".env.local");
|
|
2836
3299
|
const targetEnvPath = await pathExists(envLocalPath) ? envLocalPath : envPath;
|
|
2837
3300
|
if (await pathExists(targetEnvPath)) {
|
|
2838
|
-
const envContent = await
|
|
3301
|
+
const envContent = await readFile10(targetEnvPath, "utf-8");
|
|
2839
3302
|
if (envContent.includes("LINEAR_API_KEY=")) {
|
|
2840
3303
|
const updated = envContent.replace(
|
|
2841
3304
|
/LINEAR_API_KEY=.*/,
|
|
2842
3305
|
`LINEAR_API_KEY=${apiKey}`
|
|
2843
3306
|
);
|
|
2844
|
-
await
|
|
3307
|
+
await writeFile6(targetEnvPath, updated, "utf-8");
|
|
2845
3308
|
} else {
|
|
2846
3309
|
await appendFile2(targetEnvPath, `
|
|
2847
3310
|
LINEAR_API_KEY=${apiKey}
|
|
2848
3311
|
`);
|
|
2849
3312
|
}
|
|
2850
3313
|
} else {
|
|
2851
|
-
await
|
|
3314
|
+
await writeFile6(targetEnvPath, `LINEAR_API_KEY=${apiKey}
|
|
2852
3315
|
`, "utf-8");
|
|
2853
3316
|
}
|
|
2854
3317
|
printStatus(
|
|
2855
|
-
`API key stored in ${
|
|
3318
|
+
`API key stored in ${pc11.dim(targetEnvPath === envLocalPath ? ".env.local" : ".env")}`
|
|
2856
3319
|
);
|
|
2857
3320
|
const wasLocal = config.tier === "local";
|
|
2858
3321
|
config.tier = "cloud";
|
|
@@ -2865,16 +3328,16 @@ LINEAR_API_KEY=${apiKey}
|
|
|
2865
3328
|
const templateDir = await resolveTemplatePath(
|
|
2866
3329
|
args["local-source"] || void 0
|
|
2867
3330
|
);
|
|
2868
|
-
const templateSkillsDir =
|
|
2869
|
-
const skillsDir =
|
|
3331
|
+
const templateSkillsDir = join16(templateDir, ".claude", "skills");
|
|
3332
|
+
const skillsDir = join16(targetDir, ".claude", "skills");
|
|
2870
3333
|
await replaceDirectory(
|
|
2871
|
-
|
|
2872
|
-
|
|
3334
|
+
join16(templateSkillsDir, "flydocs-cloud"),
|
|
3335
|
+
join16(skillsDir, "flydocs-cloud")
|
|
2873
3336
|
);
|
|
2874
|
-
const { rm:
|
|
2875
|
-
const localSkillDir =
|
|
3337
|
+
const { rm: rm6 } = await import("fs/promises");
|
|
3338
|
+
const localSkillDir = join16(skillsDir, "flydocs-local");
|
|
2876
3339
|
if (await pathExists(localSkillDir)) {
|
|
2877
|
-
await
|
|
3340
|
+
await rm6(localSkillDir, { recursive: true, force: true });
|
|
2878
3341
|
}
|
|
2879
3342
|
printStatus("Cloud mechanism skill installed");
|
|
2880
3343
|
} catch {
|
|
@@ -2885,14 +3348,14 @@ LINEAR_API_KEY=${apiKey}
|
|
|
2885
3348
|
}
|
|
2886
3349
|
console.log();
|
|
2887
3350
|
console.log(
|
|
2888
|
-
` ${
|
|
3351
|
+
` ${pc11.bold("Connected!")} Your project now syncs with Linear.`
|
|
2889
3352
|
);
|
|
2890
3353
|
console.log();
|
|
2891
3354
|
console.log(` Next steps:`);
|
|
2892
3355
|
console.log(
|
|
2893
|
-
` 1. Run ${
|
|
3356
|
+
` 1. Run ${pc11.cyan("/flydocs-setup")} in your IDE to configure your Linear project`
|
|
2894
3357
|
);
|
|
2895
|
-
console.log(` 2. Run ${
|
|
3358
|
+
console.log(` 2. Run ${pc11.cyan("/start-session")} to begin working`);
|
|
2896
3359
|
console.log();
|
|
2897
3360
|
}
|
|
2898
3361
|
});
|
|
@@ -2904,15 +3367,15 @@ var upgrade_exports = {};
|
|
|
2904
3367
|
__export(upgrade_exports, {
|
|
2905
3368
|
default: () => upgrade_default
|
|
2906
3369
|
});
|
|
2907
|
-
import { defineCommand as
|
|
2908
|
-
import
|
|
3370
|
+
import { defineCommand as defineCommand7 } from "citty";
|
|
3371
|
+
import pc12 from "picocolors";
|
|
2909
3372
|
var upgrade_default;
|
|
2910
3373
|
var init_upgrade = __esm({
|
|
2911
3374
|
"src/commands/upgrade.ts"() {
|
|
2912
3375
|
"use strict";
|
|
2913
3376
|
init_config();
|
|
2914
3377
|
init_fs_ops();
|
|
2915
|
-
upgrade_default =
|
|
3378
|
+
upgrade_default = defineCommand7({
|
|
2916
3379
|
meta: {
|
|
2917
3380
|
name: "upgrade",
|
|
2918
3381
|
description: "Learn about FlyDocs Cloud tier and upgrade from local"
|
|
@@ -2941,37 +3404,37 @@ var init_upgrade = __esm({
|
|
|
2941
3404
|
console.log();
|
|
2942
3405
|
if (currentTier === "cloud") {
|
|
2943
3406
|
console.log(
|
|
2944
|
-
` ${
|
|
3407
|
+
` ${pc12.green("\u2713")} You're already on the ${pc12.bold("cloud")} tier.`
|
|
2945
3408
|
);
|
|
2946
3409
|
console.log();
|
|
2947
3410
|
console.log(
|
|
2948
3411
|
` Your issues sync with Linear via the cloud mechanism skill.`
|
|
2949
3412
|
);
|
|
2950
3413
|
console.log(
|
|
2951
|
-
` Run ${
|
|
3414
|
+
` Run ${pc12.cyan("flydocs connect")} to update your connection settings.`
|
|
2952
3415
|
);
|
|
2953
3416
|
console.log();
|
|
2954
3417
|
return;
|
|
2955
3418
|
}
|
|
2956
|
-
console.log(` ${
|
|
3419
|
+
console.log(` ${pc12.bold("FlyDocs Cloud Tier")}`);
|
|
2957
3420
|
console.log();
|
|
2958
|
-
console.log(` You're currently on the ${
|
|
3421
|
+
console.log(` You're currently on the ${pc12.yellow("local")} tier.`);
|
|
2959
3422
|
console.log(` Upgrade to cloud for:`);
|
|
2960
3423
|
console.log();
|
|
2961
3424
|
console.log(
|
|
2962
|
-
` ${
|
|
3425
|
+
` ${pc12.cyan("\u2192")} Issue sync with Linear (Jira coming soon)`
|
|
2963
3426
|
);
|
|
2964
|
-
console.log(` ${
|
|
2965
|
-
console.log(` ${
|
|
2966
|
-
console.log(` ${
|
|
2967
|
-
console.log(` ${
|
|
3427
|
+
console.log(` ${pc12.cyan("\u2192")} Project milestones and cycle management`);
|
|
3428
|
+
console.log(` ${pc12.cyan("\u2192")} Team assignment and priority tracking`);
|
|
3429
|
+
console.log(` ${pc12.cyan("\u2192")} Project health updates and dashboards`);
|
|
3430
|
+
console.log(` ${pc12.cyan("\u2192")} Cross-project issue linking`);
|
|
2968
3431
|
console.log();
|
|
2969
|
-
console.log(` ${
|
|
3432
|
+
console.log(` ${pc12.bold("How to upgrade:")}`);
|
|
2970
3433
|
console.log();
|
|
2971
|
-
console.log(` 1. Sign up at ${
|
|
3434
|
+
console.log(` 1. Sign up at ${pc12.cyan("https://www.flydocs.ai")}`);
|
|
2972
3435
|
console.log(` 2. Get your Linear API key from Linear \u2192 Settings \u2192 API`);
|
|
2973
3436
|
console.log(
|
|
2974
|
-
` 3. Run ${
|
|
3437
|
+
` 3. Run ${pc12.cyan("flydocs connect")} to connect your project`
|
|
2975
3438
|
);
|
|
2976
3439
|
console.log();
|
|
2977
3440
|
}
|
|
@@ -2984,23 +3447,23 @@ var self_update_exports = {};
|
|
|
2984
3447
|
__export(self_update_exports, {
|
|
2985
3448
|
default: () => self_update_default
|
|
2986
3449
|
});
|
|
2987
|
-
import { defineCommand as
|
|
3450
|
+
import { defineCommand as defineCommand8 } from "citty";
|
|
2988
3451
|
import { execSync } from "child_process";
|
|
2989
|
-
import
|
|
3452
|
+
import pc13 from "picocolors";
|
|
2990
3453
|
var self_update_default;
|
|
2991
3454
|
var init_self_update = __esm({
|
|
2992
3455
|
"src/commands/self-update.ts"() {
|
|
2993
3456
|
"use strict";
|
|
2994
3457
|
init_constants();
|
|
2995
3458
|
init_ui();
|
|
2996
|
-
self_update_default =
|
|
3459
|
+
self_update_default = defineCommand8({
|
|
2997
3460
|
meta: {
|
|
2998
3461
|
name: "self-update",
|
|
2999
3462
|
description: "Update FlyDocs CLI to the latest version"
|
|
3000
3463
|
},
|
|
3001
3464
|
async run() {
|
|
3002
3465
|
console.log();
|
|
3003
|
-
console.log(` Updating ${
|
|
3466
|
+
console.log(` Updating ${pc13.cyan(PACKAGE_NAME)}...`);
|
|
3004
3467
|
console.log();
|
|
3005
3468
|
try {
|
|
3006
3469
|
execSync(`npm install -g ${PACKAGE_NAME}@beta`, {
|
|
@@ -3020,17 +3483,117 @@ var init_self_update = __esm({
|
|
|
3020
3483
|
}
|
|
3021
3484
|
});
|
|
3022
3485
|
|
|
3486
|
+
// src/commands/telemetry.ts
|
|
3487
|
+
var telemetry_exports = {};
|
|
3488
|
+
__export(telemetry_exports, {
|
|
3489
|
+
default: () => telemetry_default
|
|
3490
|
+
});
|
|
3491
|
+
import { defineCommand as defineCommand9 } from "citty";
|
|
3492
|
+
import pc14 from "picocolors";
|
|
3493
|
+
var enable, disable, status, telemetry_default;
|
|
3494
|
+
var init_telemetry2 = __esm({
|
|
3495
|
+
"src/commands/telemetry.ts"() {
|
|
3496
|
+
"use strict";
|
|
3497
|
+
init_telemetry();
|
|
3498
|
+
init_ui();
|
|
3499
|
+
enable = defineCommand9({
|
|
3500
|
+
meta: {
|
|
3501
|
+
name: "enable",
|
|
3502
|
+
description: "Enable anonymous usage analytics"
|
|
3503
|
+
},
|
|
3504
|
+
async run() {
|
|
3505
|
+
try {
|
|
3506
|
+
await setEnabled(true);
|
|
3507
|
+
printStatus("Telemetry enabled");
|
|
3508
|
+
} catch {
|
|
3509
|
+
printError("Failed to update telemetry settings");
|
|
3510
|
+
process.exit(1);
|
|
3511
|
+
}
|
|
3512
|
+
}
|
|
3513
|
+
});
|
|
3514
|
+
disable = defineCommand9({
|
|
3515
|
+
meta: {
|
|
3516
|
+
name: "disable",
|
|
3517
|
+
description: "Disable anonymous usage analytics"
|
|
3518
|
+
},
|
|
3519
|
+
async run() {
|
|
3520
|
+
try {
|
|
3521
|
+
await setEnabled(false);
|
|
3522
|
+
printStatus("Telemetry disabled");
|
|
3523
|
+
printInfo(
|
|
3524
|
+
"You can also set FLYDOCS_TELEMETRY=0 in your shell environment."
|
|
3525
|
+
);
|
|
3526
|
+
} catch {
|
|
3527
|
+
printError("Failed to update telemetry settings");
|
|
3528
|
+
process.exit(1);
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
});
|
|
3532
|
+
status = defineCommand9({
|
|
3533
|
+
meta: {
|
|
3534
|
+
name: "status",
|
|
3535
|
+
description: "Show current telemetry status"
|
|
3536
|
+
},
|
|
3537
|
+
async run() {
|
|
3538
|
+
const info = await getStatus();
|
|
3539
|
+
console.log();
|
|
3540
|
+
console.log(pc14.bold("Telemetry Status"));
|
|
3541
|
+
console.log();
|
|
3542
|
+
const effectivelyEnabled = info.enabled && !info.envOverride;
|
|
3543
|
+
console.log(
|
|
3544
|
+
` Enabled: ${effectivelyEnabled ? pc14.green("yes") : pc14.yellow("no")}`
|
|
3545
|
+
);
|
|
3546
|
+
if (info.envOverride) {
|
|
3547
|
+
console.log(
|
|
3548
|
+
` Env override: ${pc14.yellow("FLYDOCS_TELEMETRY=0 (disabled via env)")}`
|
|
3549
|
+
);
|
|
3550
|
+
}
|
|
3551
|
+
if (info.anonymousId) {
|
|
3552
|
+
console.log(` Anonymous ID: ${pc14.dim(info.anonymousId)}`);
|
|
3553
|
+
} else {
|
|
3554
|
+
console.log(
|
|
3555
|
+
` Anonymous ID: ${pc14.dim("(not yet created \u2014 generated on first run)")}`
|
|
3556
|
+
);
|
|
3557
|
+
}
|
|
3558
|
+
console.log();
|
|
3559
|
+
console.log(
|
|
3560
|
+
pc14.dim(
|
|
3561
|
+
" FlyDocs collects anonymous usage analytics to improve the CLI."
|
|
3562
|
+
)
|
|
3563
|
+
);
|
|
3564
|
+
console.log(
|
|
3565
|
+
pc14.dim(" No personal data, file contents, or code is ever collected.")
|
|
3566
|
+
);
|
|
3567
|
+
console.log();
|
|
3568
|
+
}
|
|
3569
|
+
});
|
|
3570
|
+
telemetry_default = defineCommand9({
|
|
3571
|
+
meta: {
|
|
3572
|
+
name: "telemetry",
|
|
3573
|
+
description: "Manage anonymous usage analytics (enable, disable, status)"
|
|
3574
|
+
},
|
|
3575
|
+
subCommands: {
|
|
3576
|
+
enable,
|
|
3577
|
+
disable,
|
|
3578
|
+
status
|
|
3579
|
+
}
|
|
3580
|
+
});
|
|
3581
|
+
}
|
|
3582
|
+
});
|
|
3583
|
+
|
|
3023
3584
|
// src/cli.ts
|
|
3024
3585
|
init_constants();
|
|
3025
|
-
import { defineCommand as
|
|
3586
|
+
import { defineCommand as defineCommand10, runMain } from "citty";
|
|
3026
3587
|
var SUB_COMMANDS = /* @__PURE__ */ new Set([
|
|
3027
3588
|
"install",
|
|
3028
3589
|
"update",
|
|
3590
|
+
"uninstall",
|
|
3029
3591
|
"setup",
|
|
3030
3592
|
"skills",
|
|
3031
3593
|
"connect",
|
|
3032
3594
|
"upgrade",
|
|
3033
|
-
"self-update"
|
|
3595
|
+
"self-update",
|
|
3596
|
+
"telemetry"
|
|
3034
3597
|
]);
|
|
3035
3598
|
var userArgs = process.argv.slice(2);
|
|
3036
3599
|
var hasMetaFlag = userArgs.some(
|
|
@@ -3040,7 +3603,7 @@ var firstPositional = userArgs.find((a) => !a.startsWith("-"));
|
|
|
3040
3603
|
if (!hasMetaFlag && (!firstPositional || !SUB_COMMANDS.has(firstPositional))) {
|
|
3041
3604
|
process.argv.splice(2, 0, "install");
|
|
3042
3605
|
}
|
|
3043
|
-
var main =
|
|
3606
|
+
var main = defineCommand10({
|
|
3044
3607
|
meta: {
|
|
3045
3608
|
name: CLI_NAME,
|
|
3046
3609
|
version: CLI_VERSION,
|
|
@@ -3049,11 +3612,13 @@ var main = defineCommand8({
|
|
|
3049
3612
|
subCommands: {
|
|
3050
3613
|
install: () => Promise.resolve().then(() => (init_install(), install_exports)).then((m) => m.default),
|
|
3051
3614
|
update: () => Promise.resolve().then(() => (init_update(), update_exports)).then((m) => m.default),
|
|
3615
|
+
uninstall: () => Promise.resolve().then(() => (init_uninstall(), uninstall_exports)).then((m) => m.default),
|
|
3052
3616
|
setup: () => Promise.resolve().then(() => (init_setup(), setup_exports)).then((m) => m.default),
|
|
3053
3617
|
skills: () => Promise.resolve().then(() => (init_skills2(), skills_exports)).then((m) => m.default),
|
|
3054
3618
|
connect: () => Promise.resolve().then(() => (init_connect(), connect_exports)).then((m) => m.default),
|
|
3055
3619
|
upgrade: () => Promise.resolve().then(() => (init_upgrade(), upgrade_exports)).then((m) => m.default),
|
|
3056
|
-
"self-update": () => Promise.resolve().then(() => (init_self_update(), self_update_exports)).then((m) => m.default)
|
|
3620
|
+
"self-update": () => Promise.resolve().then(() => (init_self_update(), self_update_exports)).then((m) => m.default),
|
|
3621
|
+
telemetry: () => Promise.resolve().then(() => (init_telemetry2(), telemetry_exports)).then((m) => m.default)
|
|
3057
3622
|
}
|
|
3058
3623
|
});
|
|
3059
3624
|
runMain(main);
|