@flydocs/cli 0.5.0-beta.16 → 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 +756 -187
- package/package.json +1 -1
- package/template/.flydocs/config.json +1 -1
- package/template/.flydocs/version +1 -1
- package/template/CHANGELOG.md +15 -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,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,143 @@ 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: 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
|
+
|
|
1646
1784
|
// src/commands/install.ts
|
|
1647
1785
|
var install_exports = {};
|
|
1648
1786
|
__export(install_exports, {
|
|
@@ -1650,8 +1788,8 @@ __export(install_exports, {
|
|
|
1650
1788
|
});
|
|
1651
1789
|
import { defineCommand } from "citty";
|
|
1652
1790
|
import { resolve as resolve2 } from "path";
|
|
1653
|
-
import { join as
|
|
1654
|
-
import { mkdir as
|
|
1791
|
+
import { join as join13 } from "path";
|
|
1792
|
+
import { mkdir as mkdir6 } from "fs/promises";
|
|
1655
1793
|
import { confirm as confirm2, select, isCancel as isCancel3, cancel as cancel2 } from "@clack/prompts";
|
|
1656
1794
|
import pc6 from "picocolors";
|
|
1657
1795
|
var install_default;
|
|
@@ -1669,6 +1807,7 @@ var init_install = __esm({
|
|
|
1669
1807
|
init_gitignore();
|
|
1670
1808
|
init_post_install();
|
|
1671
1809
|
init_update_check();
|
|
1810
|
+
init_telemetry();
|
|
1672
1811
|
install_default = defineCommand({
|
|
1673
1812
|
meta: {
|
|
1674
1813
|
name: "install",
|
|
@@ -1704,6 +1843,7 @@ var init_install = __esm({
|
|
|
1704
1843
|
const templateDir = await resolveTemplatePath(args["local-source"]);
|
|
1705
1844
|
const version = await readTemplateVersion(templateDir);
|
|
1706
1845
|
printBanner(version);
|
|
1846
|
+
await capture("install_started", { template_version: version });
|
|
1707
1847
|
let targetDir;
|
|
1708
1848
|
if (args.path) {
|
|
1709
1849
|
targetDir = resolve2(args.path.replace(/^~/, process.env.HOME ?? "~"));
|
|
@@ -1730,7 +1870,7 @@ var init_install = __esm({
|
|
|
1730
1870
|
}
|
|
1731
1871
|
tier = args.tier;
|
|
1732
1872
|
printInfo(`Tier set via flag: ${tier}`);
|
|
1733
|
-
} else if (await pathExists(
|
|
1873
|
+
} else if (await pathExists(join13(targetDir, ".flydocs", "config.json"))) {
|
|
1734
1874
|
try {
|
|
1735
1875
|
const existing = await readConfig(targetDir);
|
|
1736
1876
|
if (existing.tier) {
|
|
@@ -1752,37 +1892,38 @@ var init_install = __esm({
|
|
|
1752
1892
|
tier = "local";
|
|
1753
1893
|
console.log();
|
|
1754
1894
|
}
|
|
1755
|
-
|
|
1895
|
+
await capture("install_tier_selected", { tier });
|
|
1896
|
+
if (!await pathExists(join13(targetDir, ".git"))) {
|
|
1756
1897
|
printWarning("No git repository detected. Run git init when ready.");
|
|
1757
1898
|
}
|
|
1758
1899
|
await ensureDirectories(targetDir, tier);
|
|
1759
1900
|
console.log("Installing framework files...");
|
|
1760
1901
|
await replaceDirectory(
|
|
1761
|
-
|
|
1762
|
-
|
|
1902
|
+
join13(templateDir, ".flydocs", "templates"),
|
|
1903
|
+
join13(targetDir, ".flydocs", "templates")
|
|
1763
1904
|
);
|
|
1764
1905
|
await replaceDirectory(
|
|
1765
|
-
|
|
1766
|
-
|
|
1906
|
+
join13(templateDir, ".flydocs", "hooks"),
|
|
1907
|
+
join13(targetDir, ".flydocs", "hooks")
|
|
1767
1908
|
);
|
|
1768
1909
|
await replaceDirectory(
|
|
1769
|
-
|
|
1770
|
-
|
|
1910
|
+
join13(templateDir, ".flydocs", "scripts"),
|
|
1911
|
+
join13(targetDir, ".flydocs", "scripts")
|
|
1771
1912
|
);
|
|
1772
1913
|
await copyFile(
|
|
1773
|
-
|
|
1774
|
-
|
|
1914
|
+
join13(templateDir, ".flydocs", "version"),
|
|
1915
|
+
join13(targetDir, ".flydocs", "version")
|
|
1775
1916
|
);
|
|
1776
|
-
const manifestSrc =
|
|
1917
|
+
const manifestSrc = join13(templateDir, "manifest.json");
|
|
1777
1918
|
if (await pathExists(manifestSrc)) {
|
|
1778
|
-
await copyFile(manifestSrc,
|
|
1919
|
+
await copyFile(manifestSrc, join13(targetDir, ".flydocs", "manifest.json"));
|
|
1779
1920
|
}
|
|
1780
|
-
const changelogSrc =
|
|
1921
|
+
const changelogSrc = join13(templateDir, "CHANGELOG.md");
|
|
1781
1922
|
if (await pathExists(changelogSrc)) {
|
|
1782
|
-
await copyFile(changelogSrc,
|
|
1923
|
+
await copyFile(changelogSrc, join13(targetDir, ".flydocs", "CHANGELOG.md"));
|
|
1783
1924
|
}
|
|
1784
1925
|
printStatus(".flydocs/templates, hooks, version, manifest, changelog");
|
|
1785
|
-
const configPath =
|
|
1926
|
+
const configPath = join13(targetDir, ".flydocs", "config.json");
|
|
1786
1927
|
if (!await pathExists(configPath)) {
|
|
1787
1928
|
const config = await createFreshConfig(templateDir, version, tier);
|
|
1788
1929
|
await writeConfig(targetDir, config);
|
|
@@ -1834,21 +1975,22 @@ var init_install = __esm({
|
|
|
1834
1975
|
installAgents = agentConfirm;
|
|
1835
1976
|
}
|
|
1836
1977
|
}
|
|
1978
|
+
await capture("install_agents_chosen", { install_agents: installAgents });
|
|
1837
1979
|
if (installAgents) {
|
|
1838
|
-
const claudeAgentsSrc =
|
|
1980
|
+
const claudeAgentsSrc = join13(templateDir, ".claude", "agents");
|
|
1839
1981
|
if (await pathExists(claudeAgentsSrc)) {
|
|
1840
|
-
await
|
|
1982
|
+
await mkdir6(join13(targetDir, ".claude", "agents"), { recursive: true });
|
|
1841
1983
|
await copyDirectoryContents(
|
|
1842
1984
|
claudeAgentsSrc,
|
|
1843
|
-
|
|
1985
|
+
join13(targetDir, ".claude", "agents")
|
|
1844
1986
|
);
|
|
1845
1987
|
}
|
|
1846
|
-
const cursorAgentsSrc =
|
|
1988
|
+
const cursorAgentsSrc = join13(templateDir, ".cursor", "agents");
|
|
1847
1989
|
if (await pathExists(cursorAgentsSrc)) {
|
|
1848
|
-
await
|
|
1990
|
+
await mkdir6(join13(targetDir, ".cursor", "agents"), { recursive: true });
|
|
1849
1991
|
await copyDirectoryContents(
|
|
1850
1992
|
cursorAgentsSrc,
|
|
1851
|
-
|
|
1993
|
+
join13(targetDir, ".cursor", "agents")
|
|
1852
1994
|
);
|
|
1853
1995
|
}
|
|
1854
1996
|
printStatus("Sub-agents installed (.claude/agents, .cursor/agents)");
|
|
@@ -1858,32 +2000,32 @@ var init_install = __esm({
|
|
|
1858
2000
|
console.log();
|
|
1859
2001
|
console.log("Installing commands and settings...");
|
|
1860
2002
|
await copyDirectoryContents(
|
|
1861
|
-
|
|
1862
|
-
|
|
2003
|
+
join13(templateDir, ".claude", "commands"),
|
|
2004
|
+
join13(targetDir, ".claude", "commands")
|
|
1863
2005
|
);
|
|
1864
2006
|
await copyFile(
|
|
1865
|
-
|
|
1866
|
-
|
|
2007
|
+
join13(templateDir, ".claude", "CLAUDE.md"),
|
|
2008
|
+
join13(targetDir, ".claude", "CLAUDE.md")
|
|
1867
2009
|
);
|
|
1868
2010
|
await copyFile(
|
|
1869
|
-
|
|
1870
|
-
|
|
2011
|
+
join13(templateDir, ".claude", "settings.json"),
|
|
2012
|
+
join13(targetDir, ".claude", "settings.json")
|
|
1871
2013
|
);
|
|
1872
2014
|
printStatus(".claude/ (commands, CLAUDE.md, settings)");
|
|
1873
2015
|
await copyDirectoryContents(
|
|
1874
|
-
|
|
1875
|
-
|
|
2016
|
+
join13(templateDir, ".claude", "commands"),
|
|
2017
|
+
join13(targetDir, ".cursor", "commands")
|
|
1876
2018
|
);
|
|
1877
2019
|
await copyFile(
|
|
1878
|
-
|
|
1879
|
-
|
|
2020
|
+
join13(templateDir, ".cursor", "hooks.json"),
|
|
2021
|
+
join13(targetDir, ".cursor", "hooks.json")
|
|
1880
2022
|
);
|
|
1881
2023
|
printStatus(".cursor/ (commands, hooks)");
|
|
1882
2024
|
await copyCursorRules(targetDir);
|
|
1883
2025
|
printStatus(".cursor/rules/");
|
|
1884
2026
|
await copyFile(
|
|
1885
|
-
|
|
1886
|
-
|
|
2027
|
+
join13(templateDir, "AGENTS.md"),
|
|
2028
|
+
join13(targetDir, "AGENTS.md")
|
|
1887
2029
|
);
|
|
1888
2030
|
printStatus("AGENTS.md");
|
|
1889
2031
|
await runManifestGeneration(targetDir);
|
|
@@ -1892,40 +2034,40 @@ var init_install = __esm({
|
|
|
1892
2034
|
console.log("Installing project templates...");
|
|
1893
2035
|
const userFiles = [
|
|
1894
2036
|
{
|
|
1895
|
-
src:
|
|
1896
|
-
dest:
|
|
2037
|
+
src: join13(templateDir, "flydocs", "context", "project.md"),
|
|
2038
|
+
dest: join13(targetDir, "flydocs", "context", "project.md"),
|
|
1897
2039
|
label: "flydocs/context/project.md"
|
|
1898
2040
|
},
|
|
1899
2041
|
{
|
|
1900
|
-
src:
|
|
1901
|
-
dest:
|
|
2042
|
+
src: join13(templateDir, "flydocs", "knowledge", "INDEX.md"),
|
|
2043
|
+
dest: join13(targetDir, "flydocs", "knowledge", "INDEX.md"),
|
|
1902
2044
|
label: "flydocs/knowledge/INDEX.md"
|
|
1903
2045
|
},
|
|
1904
2046
|
{
|
|
1905
|
-
src:
|
|
1906
|
-
dest:
|
|
2047
|
+
src: join13(templateDir, "flydocs", "knowledge", "README.md"),
|
|
2048
|
+
dest: join13(targetDir, "flydocs", "knowledge", "README.md"),
|
|
1907
2049
|
label: "flydocs/knowledge/README.md"
|
|
1908
2050
|
},
|
|
1909
2051
|
{
|
|
1910
|
-
src:
|
|
2052
|
+
src: join13(
|
|
1911
2053
|
templateDir,
|
|
1912
2054
|
"flydocs",
|
|
1913
2055
|
"knowledge",
|
|
1914
2056
|
"product",
|
|
1915
2057
|
"personas.md"
|
|
1916
2058
|
),
|
|
1917
|
-
dest:
|
|
2059
|
+
dest: join13(targetDir, "flydocs", "knowledge", "product", "personas.md"),
|
|
1918
2060
|
label: "flydocs/knowledge/product/personas.md"
|
|
1919
2061
|
},
|
|
1920
2062
|
{
|
|
1921
|
-
src:
|
|
2063
|
+
src: join13(
|
|
1922
2064
|
templateDir,
|
|
1923
2065
|
"flydocs",
|
|
1924
2066
|
"knowledge",
|
|
1925
2067
|
"product",
|
|
1926
2068
|
"user-flows.md"
|
|
1927
2069
|
),
|
|
1928
|
-
dest:
|
|
2070
|
+
dest: join13(
|
|
1929
2071
|
targetDir,
|
|
1930
2072
|
"flydocs",
|
|
1931
2073
|
"knowledge",
|
|
@@ -1935,18 +2077,18 @@ var init_install = __esm({
|
|
|
1935
2077
|
label: "flydocs/knowledge/product/user-flows.md"
|
|
1936
2078
|
},
|
|
1937
2079
|
{
|
|
1938
|
-
src:
|
|
1939
|
-
dest:
|
|
2080
|
+
src: join13(templateDir, "flydocs", "design-system", "README.md"),
|
|
2081
|
+
dest: join13(targetDir, "flydocs", "design-system", "README.md"),
|
|
1940
2082
|
label: "flydocs/design-system/README.md"
|
|
1941
2083
|
},
|
|
1942
2084
|
{
|
|
1943
|
-
src:
|
|
2085
|
+
src: join13(
|
|
1944
2086
|
templateDir,
|
|
1945
2087
|
"flydocs",
|
|
1946
2088
|
"design-system",
|
|
1947
2089
|
"component-patterns.md"
|
|
1948
2090
|
),
|
|
1949
|
-
dest:
|
|
2091
|
+
dest: join13(
|
|
1950
2092
|
targetDir,
|
|
1951
2093
|
"flydocs",
|
|
1952
2094
|
"design-system",
|
|
@@ -1955,13 +2097,13 @@ var init_install = __esm({
|
|
|
1955
2097
|
label: "flydocs/design-system/component-patterns.md"
|
|
1956
2098
|
},
|
|
1957
2099
|
{
|
|
1958
|
-
src:
|
|
1959
|
-
dest:
|
|
2100
|
+
src: join13(templateDir, "flydocs", "design-system", "token-mapping.md"),
|
|
2101
|
+
dest: join13(targetDir, "flydocs", "design-system", "token-mapping.md"),
|
|
1960
2102
|
label: "flydocs/design-system/token-mapping.md"
|
|
1961
2103
|
},
|
|
1962
2104
|
{
|
|
1963
|
-
src:
|
|
1964
|
-
dest:
|
|
2105
|
+
src: join13(templateDir, "flydocs", "README.md"),
|
|
2106
|
+
dest: join13(targetDir, "flydocs", "README.md"),
|
|
1965
2107
|
label: "flydocs/README.md"
|
|
1966
2108
|
}
|
|
1967
2109
|
];
|
|
@@ -1975,9 +2117,9 @@ var init_install = __esm({
|
|
|
1975
2117
|
}
|
|
1976
2118
|
}
|
|
1977
2119
|
}
|
|
1978
|
-
const envExampleSrc =
|
|
2120
|
+
const envExampleSrc = join13(templateDir, ".env.example");
|
|
1979
2121
|
if (await pathExists(envExampleSrc)) {
|
|
1980
|
-
await copyFile(envExampleSrc,
|
|
2122
|
+
await copyFile(envExampleSrc, join13(targetDir, ".env.example"));
|
|
1981
2123
|
printStatus(".env.example");
|
|
1982
2124
|
}
|
|
1983
2125
|
await ensureGitignore(targetDir);
|
|
@@ -1996,6 +2138,9 @@ var init_install = __esm({
|
|
|
1996
2138
|
} else {
|
|
1997
2139
|
printInfo("No framework detected in package.json");
|
|
1998
2140
|
}
|
|
2141
|
+
await capture("install_skills_chosen", {
|
|
2142
|
+
stack_detected: stack.raw
|
|
2143
|
+
});
|
|
1999
2144
|
console.log();
|
|
2000
2145
|
console.log("Checking for deprecated files...");
|
|
2001
2146
|
const deprecated = await scanDeprecated(targetDir);
|
|
@@ -2037,6 +2182,7 @@ var init_install = __esm({
|
|
|
2037
2182
|
}
|
|
2038
2183
|
printCompletionBox("Installation Complete!", nextSteps);
|
|
2039
2184
|
printBetaCta();
|
|
2185
|
+
const detectedIdes = [];
|
|
2040
2186
|
try {
|
|
2041
2187
|
const { execSync: execSync2, spawn } = await import("child_process");
|
|
2042
2188
|
const isInstalled = (cmd) => {
|
|
@@ -2072,6 +2218,7 @@ var init_install = __esm({
|
|
|
2072
2218
|
passCommand: false
|
|
2073
2219
|
});
|
|
2074
2220
|
}
|
|
2221
|
+
detectedIdes.push(...ideOptions.map((o) => o.cmd));
|
|
2075
2222
|
if (ideOptions.length === 1) {
|
|
2076
2223
|
const ide = ideOptions[0];
|
|
2077
2224
|
const launchConfirm = await confirm2({
|
|
@@ -2130,6 +2277,9 @@ var init_install = __esm({
|
|
|
2130
2277
|
}
|
|
2131
2278
|
} catch {
|
|
2132
2279
|
}
|
|
2280
|
+
await capture("install_ide_detected", { ides: detectedIdes });
|
|
2281
|
+
await capture("install_completed", { tier, version });
|
|
2282
|
+
await flush();
|
|
2133
2283
|
try {
|
|
2134
2284
|
const updateResult = await checkForUpdate();
|
|
2135
2285
|
if (updateResult) {
|
|
@@ -2148,8 +2298,8 @@ __export(update_exports, {
|
|
|
2148
2298
|
default: () => update_default
|
|
2149
2299
|
});
|
|
2150
2300
|
import { defineCommand as defineCommand2 } from "citty";
|
|
2151
|
-
import { resolve as resolve3, join as
|
|
2152
|
-
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";
|
|
2153
2303
|
import { select as select2, text, confirm as confirm3, isCancel as isCancel4, cancel as cancel3 } from "@clack/prompts";
|
|
2154
2304
|
import pc7 from "picocolors";
|
|
2155
2305
|
var update_default;
|
|
@@ -2168,6 +2318,7 @@ var init_update = __esm({
|
|
|
2168
2318
|
init_gitignore();
|
|
2169
2319
|
init_post_install();
|
|
2170
2320
|
init_update_check();
|
|
2321
|
+
init_telemetry();
|
|
2171
2322
|
update_default = defineCommand2({
|
|
2172
2323
|
meta: {
|
|
2173
2324
|
name: "update",
|
|
@@ -2210,6 +2361,7 @@ var init_update = __esm({
|
|
|
2210
2361
|
printBanner(version);
|
|
2211
2362
|
printInfo("Running in update mode \u2014 framework files will be refreshed");
|
|
2212
2363
|
console.log();
|
|
2364
|
+
await capture("update_started", { template_version: version });
|
|
2213
2365
|
let targetDir;
|
|
2214
2366
|
if (args.path) {
|
|
2215
2367
|
targetDir = resolve3(args.path.replace(/^~/, process.env.HOME ?? "~"));
|
|
@@ -2254,9 +2406,9 @@ var init_update = __esm({
|
|
|
2254
2406
|
}
|
|
2255
2407
|
targetDir = resolve3(targetDir);
|
|
2256
2408
|
process.chdir(targetDir);
|
|
2257
|
-
const hasVersion = await pathExists(
|
|
2409
|
+
const hasVersion = await pathExists(join14(targetDir, ".flydocs", "version"));
|
|
2258
2410
|
const hasConfig = await pathExists(
|
|
2259
|
-
|
|
2411
|
+
join14(targetDir, ".flydocs", "config.json")
|
|
2260
2412
|
);
|
|
2261
2413
|
if (!hasVersion && !hasConfig) {
|
|
2262
2414
|
printError(`Not a FlyDocs project: ${targetDir}`);
|
|
@@ -2267,8 +2419,8 @@ var init_update = __esm({
|
|
|
2267
2419
|
console.log();
|
|
2268
2420
|
let currentVersion = "0.1.0";
|
|
2269
2421
|
if (hasVersion) {
|
|
2270
|
-
const vContent = await
|
|
2271
|
-
|
|
2422
|
+
const vContent = await readFile9(
|
|
2423
|
+
join14(targetDir, ".flydocs", "version"),
|
|
2272
2424
|
"utf-8"
|
|
2273
2425
|
);
|
|
2274
2426
|
currentVersion = vContent.trim();
|
|
@@ -2294,9 +2446,15 @@ var init_update = __esm({
|
|
|
2294
2446
|
process.exit(0);
|
|
2295
2447
|
}
|
|
2296
2448
|
}
|
|
2449
|
+
await capture("update_version_compared", {
|
|
2450
|
+
current_version: currentVersion,
|
|
2451
|
+
target_version: version,
|
|
2452
|
+
version_status: versionStatus,
|
|
2453
|
+
force: args.force
|
|
2454
|
+
});
|
|
2297
2455
|
console.log(`Updating: v${currentVersion} \u2192 v${version}`);
|
|
2298
2456
|
console.log();
|
|
2299
|
-
const changelogPath =
|
|
2457
|
+
const changelogPath = join14(templateDir, "CHANGELOG.md");
|
|
2300
2458
|
const whatsNew = await getWhatsNew(changelogPath, currentVersion, version);
|
|
2301
2459
|
if (whatsNew.length > 0) {
|
|
2302
2460
|
console.log(pc7.cyan("What's new:"));
|
|
@@ -2308,23 +2466,23 @@ var init_update = __esm({
|
|
|
2308
2466
|
}
|
|
2309
2467
|
const now = /* @__PURE__ */ new Date();
|
|
2310
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")}`;
|
|
2311
|
-
const backupDir =
|
|
2312
|
-
await
|
|
2469
|
+
const backupDir = join14(targetDir, ".flydocs", `backup-${ts}`);
|
|
2470
|
+
await mkdir7(backupDir, { recursive: true });
|
|
2313
2471
|
if (hasConfig) {
|
|
2314
2472
|
await cp2(
|
|
2315
|
-
|
|
2316
|
-
|
|
2473
|
+
join14(targetDir, ".flydocs", "config.json"),
|
|
2474
|
+
join14(backupDir, "config.json")
|
|
2317
2475
|
);
|
|
2318
2476
|
printStatus(`Config backed up to .flydocs/backup-${ts}/`);
|
|
2319
2477
|
}
|
|
2320
2478
|
try {
|
|
2321
|
-
const flydocsDir =
|
|
2479
|
+
const flydocsDir = join14(targetDir, ".flydocs");
|
|
2322
2480
|
const entries = await readdir3(flydocsDir);
|
|
2323
2481
|
const backups = entries.filter((e) => e.startsWith("backup-")).sort();
|
|
2324
2482
|
if (backups.length > 3) {
|
|
2325
2483
|
const toRemove = backups.slice(0, backups.length - 3);
|
|
2326
2484
|
for (const old of toRemove) {
|
|
2327
|
-
await rm4(
|
|
2485
|
+
await rm4(join14(flydocsDir, old), { recursive: true, force: true });
|
|
2328
2486
|
}
|
|
2329
2487
|
}
|
|
2330
2488
|
} catch {
|
|
@@ -2361,20 +2519,20 @@ var init_update = __esm({
|
|
|
2361
2519
|
}
|
|
2362
2520
|
console.log("Replacing framework directories...");
|
|
2363
2521
|
await replaceDirectory(
|
|
2364
|
-
|
|
2365
|
-
|
|
2522
|
+
join14(templateDir, ".flydocs", "templates"),
|
|
2523
|
+
join14(targetDir, ".flydocs", "templates")
|
|
2366
2524
|
);
|
|
2367
2525
|
await replaceDirectory(
|
|
2368
|
-
|
|
2369
|
-
|
|
2526
|
+
join14(templateDir, ".flydocs", "hooks"),
|
|
2527
|
+
join14(targetDir, ".flydocs", "hooks")
|
|
2370
2528
|
);
|
|
2371
2529
|
await replaceDirectory(
|
|
2372
|
-
|
|
2373
|
-
|
|
2530
|
+
join14(templateDir, ".flydocs", "scripts"),
|
|
2531
|
+
join14(targetDir, ".flydocs", "scripts")
|
|
2374
2532
|
);
|
|
2375
2533
|
printStatus(".flydocs/templates, hooks, scripts");
|
|
2376
2534
|
const hasExistingAgents = await pathExists(
|
|
2377
|
-
|
|
2535
|
+
join14(targetDir, ".claude", "agents")
|
|
2378
2536
|
);
|
|
2379
2537
|
let installAgents;
|
|
2380
2538
|
if (args.yes) {
|
|
@@ -2406,20 +2564,20 @@ var init_update = __esm({
|
|
|
2406
2564
|
}
|
|
2407
2565
|
}
|
|
2408
2566
|
if (installAgents) {
|
|
2409
|
-
const claudeAgentsSrc =
|
|
2567
|
+
const claudeAgentsSrc = join14(templateDir, ".claude", "agents");
|
|
2410
2568
|
if (await pathExists(claudeAgentsSrc)) {
|
|
2411
|
-
await
|
|
2569
|
+
await mkdir7(join14(targetDir, ".claude", "agents"), { recursive: true });
|
|
2412
2570
|
await copyDirectoryContents(
|
|
2413
2571
|
claudeAgentsSrc,
|
|
2414
|
-
|
|
2572
|
+
join14(targetDir, ".claude", "agents")
|
|
2415
2573
|
);
|
|
2416
2574
|
}
|
|
2417
|
-
const cursorAgentsSrc =
|
|
2575
|
+
const cursorAgentsSrc = join14(templateDir, ".cursor", "agents");
|
|
2418
2576
|
if (await pathExists(cursorAgentsSrc)) {
|
|
2419
|
-
await
|
|
2577
|
+
await mkdir7(join14(targetDir, ".cursor", "agents"), { recursive: true });
|
|
2420
2578
|
await copyDirectoryContents(
|
|
2421
2579
|
cursorAgentsSrc,
|
|
2422
|
-
|
|
2580
|
+
join14(targetDir, ".cursor", "agents")
|
|
2423
2581
|
);
|
|
2424
2582
|
}
|
|
2425
2583
|
printStatus(
|
|
@@ -2433,44 +2591,44 @@ var init_update = __esm({
|
|
|
2433
2591
|
console.log();
|
|
2434
2592
|
console.log("Replacing framework files...");
|
|
2435
2593
|
await copyFile(
|
|
2436
|
-
|
|
2437
|
-
|
|
2594
|
+
join14(templateDir, ".claude", "CLAUDE.md"),
|
|
2595
|
+
join14(targetDir, ".claude", "CLAUDE.md")
|
|
2438
2596
|
);
|
|
2439
2597
|
await copyFile(
|
|
2440
|
-
|
|
2441
|
-
|
|
2598
|
+
join14(templateDir, ".claude", "settings.json"),
|
|
2599
|
+
join14(targetDir, ".claude", "settings.json")
|
|
2442
2600
|
);
|
|
2443
2601
|
printStatus(".claude/CLAUDE.md, settings.json");
|
|
2444
2602
|
await copyDirectoryContents(
|
|
2445
|
-
|
|
2446
|
-
|
|
2603
|
+
join14(templateDir, ".claude", "commands"),
|
|
2604
|
+
join14(targetDir, ".claude", "commands")
|
|
2447
2605
|
);
|
|
2448
2606
|
await copyDirectoryContents(
|
|
2449
|
-
|
|
2450
|
-
|
|
2607
|
+
join14(templateDir, ".claude", "commands"),
|
|
2608
|
+
join14(targetDir, ".cursor", "commands")
|
|
2451
2609
|
);
|
|
2452
2610
|
printStatus(".claude/commands, .cursor/commands");
|
|
2453
|
-
const skillsReadmeSrc =
|
|
2611
|
+
const skillsReadmeSrc = join14(templateDir, ".claude", "skills", "README.md");
|
|
2454
2612
|
if (await pathExists(skillsReadmeSrc)) {
|
|
2455
2613
|
await copyFile(
|
|
2456
2614
|
skillsReadmeSrc,
|
|
2457
|
-
|
|
2615
|
+
join14(targetDir, ".claude", "skills", "README.md")
|
|
2458
2616
|
);
|
|
2459
2617
|
}
|
|
2460
2618
|
printStatus(".claude/skills/README.md");
|
|
2461
2619
|
await copyFile(
|
|
2462
|
-
|
|
2463
|
-
|
|
2620
|
+
join14(templateDir, ".cursor", "hooks.json"),
|
|
2621
|
+
join14(targetDir, ".cursor", "hooks.json")
|
|
2464
2622
|
);
|
|
2465
2623
|
printStatus(".cursor/hooks.json");
|
|
2466
2624
|
await copyFile(
|
|
2467
|
-
|
|
2468
|
-
|
|
2625
|
+
join14(templateDir, "AGENTS.md"),
|
|
2626
|
+
join14(targetDir, "AGENTS.md")
|
|
2469
2627
|
);
|
|
2470
2628
|
printStatus("AGENTS.md");
|
|
2471
|
-
const envExampleSrc =
|
|
2629
|
+
const envExampleSrc = join14(templateDir, ".env.example");
|
|
2472
2630
|
if (await pathExists(envExampleSrc)) {
|
|
2473
|
-
await copyFile(envExampleSrc,
|
|
2631
|
+
await copyFile(envExampleSrc, join14(targetDir, ".env.example"));
|
|
2474
2632
|
printStatus(".env.example");
|
|
2475
2633
|
}
|
|
2476
2634
|
await runManifestGeneration(targetDir);
|
|
@@ -2495,18 +2653,18 @@ var init_update = __esm({
|
|
|
2495
2653
|
printWarning("Config merge failed \u2014 config.json preserved as-is");
|
|
2496
2654
|
}
|
|
2497
2655
|
await copyFile(
|
|
2498
|
-
|
|
2499
|
-
|
|
2656
|
+
join14(templateDir, ".flydocs", "version"),
|
|
2657
|
+
join14(targetDir, ".flydocs", "version")
|
|
2500
2658
|
);
|
|
2501
2659
|
printStatus(`.flydocs/version \u2192 ${version}`);
|
|
2502
|
-
const clSrc =
|
|
2660
|
+
const clSrc = join14(templateDir, "CHANGELOG.md");
|
|
2503
2661
|
if (await pathExists(clSrc)) {
|
|
2504
|
-
await copyFile(clSrc,
|
|
2662
|
+
await copyFile(clSrc, join14(targetDir, ".flydocs", "CHANGELOG.md"));
|
|
2505
2663
|
printStatus(".flydocs/CHANGELOG.md");
|
|
2506
2664
|
}
|
|
2507
|
-
const mfSrc =
|
|
2665
|
+
const mfSrc = join14(templateDir, "manifest.json");
|
|
2508
2666
|
if (await pathExists(mfSrc)) {
|
|
2509
|
-
await copyFile(mfSrc,
|
|
2667
|
+
await copyFile(mfSrc, join14(targetDir, ".flydocs", "manifest.json"));
|
|
2510
2668
|
printStatus(".flydocs/manifest.json");
|
|
2511
2669
|
}
|
|
2512
2670
|
console.log();
|
|
@@ -2542,6 +2700,12 @@ var init_update = __esm({
|
|
|
2542
2700
|
`Backup: .flydocs/backup-${ts}/`
|
|
2543
2701
|
]);
|
|
2544
2702
|
printBetaCta();
|
|
2703
|
+
await capture("update_completed", {
|
|
2704
|
+
current_version: currentVersion,
|
|
2705
|
+
version,
|
|
2706
|
+
tier: effectiveTier
|
|
2707
|
+
});
|
|
2708
|
+
await flush();
|
|
2545
2709
|
try {
|
|
2546
2710
|
const updateResult = await checkForUpdate();
|
|
2547
2711
|
if (updateResult) {
|
|
@@ -2554,33 +2718,336 @@ var init_update = __esm({
|
|
|
2554
2718
|
}
|
|
2555
2719
|
});
|
|
2556
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
|
+
|
|
2557
3024
|
// src/commands/setup.ts
|
|
2558
3025
|
var setup_exports = {};
|
|
2559
3026
|
__export(setup_exports, {
|
|
2560
3027
|
default: () => setup_default
|
|
2561
3028
|
});
|
|
2562
|
-
import { defineCommand as
|
|
2563
|
-
import
|
|
3029
|
+
import { defineCommand as defineCommand4 } from "citty";
|
|
3030
|
+
import pc9 from "picocolors";
|
|
2564
3031
|
var setup_default;
|
|
2565
3032
|
var init_setup = __esm({
|
|
2566
3033
|
"src/commands/setup.ts"() {
|
|
2567
3034
|
"use strict";
|
|
2568
|
-
setup_default =
|
|
3035
|
+
setup_default = defineCommand4({
|
|
2569
3036
|
meta: {
|
|
2570
3037
|
name: "setup",
|
|
2571
3038
|
description: "Configure FlyDocs settings for this project"
|
|
2572
3039
|
},
|
|
2573
3040
|
run() {
|
|
2574
3041
|
console.log();
|
|
2575
|
-
console.log(` ${
|
|
3042
|
+
console.log(` ${pc9.bold("FlyDocs Setup")}`);
|
|
2576
3043
|
console.log();
|
|
2577
3044
|
console.log(` Setup runs inside your IDE as an interactive AI command.`);
|
|
2578
3045
|
console.log();
|
|
2579
3046
|
console.log(
|
|
2580
|
-
` ${
|
|
3047
|
+
` ${pc9.cyan("Claude Code:")} Type ${pc9.bold("/flydocs-setup")} in chat`
|
|
2581
3048
|
);
|
|
2582
3049
|
console.log(
|
|
2583
|
-
` ${
|
|
3050
|
+
` ${pc9.cyan("Cursor:")} Type ${pc9.bold("/flydocs-setup")} in chat`
|
|
2584
3051
|
);
|
|
2585
3052
|
console.log();
|
|
2586
3053
|
console.log(` This configures your project context, detects your stack,`);
|
|
@@ -2596,14 +3063,14 @@ var skills_exports = {};
|
|
|
2596
3063
|
__export(skills_exports, {
|
|
2597
3064
|
default: () => skills_default
|
|
2598
3065
|
});
|
|
2599
|
-
import { defineCommand as
|
|
2600
|
-
import
|
|
3066
|
+
import { defineCommand as defineCommand5 } from "citty";
|
|
3067
|
+
import pc10 from "picocolors";
|
|
2601
3068
|
var list, search, add, remove, skills_default;
|
|
2602
3069
|
var init_skills2 = __esm({
|
|
2603
3070
|
"src/commands/skills.ts"() {
|
|
2604
3071
|
"use strict";
|
|
2605
3072
|
init_skill_manager();
|
|
2606
|
-
list =
|
|
3073
|
+
list = defineCommand5({
|
|
2607
3074
|
meta: {
|
|
2608
3075
|
name: "list",
|
|
2609
3076
|
description: "List installed skills"
|
|
@@ -2619,26 +3086,26 @@ var init_skills2 = __esm({
|
|
|
2619
3086
|
console.log(`${total} skill(s) installed:`);
|
|
2620
3087
|
if (result.platform.length > 0) {
|
|
2621
3088
|
console.log();
|
|
2622
|
-
console.log(
|
|
3089
|
+
console.log(pc10.bold("Platform"));
|
|
2623
3090
|
for (const skill of result.platform) {
|
|
2624
3091
|
console.log(
|
|
2625
|
-
` ${skill.name} ${
|
|
3092
|
+
` ${skill.name} ${pc10.dim(`(${skill.triggers} triggers)`)}`
|
|
2626
3093
|
);
|
|
2627
3094
|
}
|
|
2628
3095
|
}
|
|
2629
3096
|
if (result.community.length > 0) {
|
|
2630
3097
|
console.log();
|
|
2631
|
-
console.log(
|
|
3098
|
+
console.log(pc10.bold("Community"));
|
|
2632
3099
|
for (const skill of result.community) {
|
|
2633
3100
|
console.log(
|
|
2634
|
-
` ${skill.name} ${
|
|
3101
|
+
` ${skill.name} ${pc10.dim(`(${skill.triggers} triggers)`)}`
|
|
2635
3102
|
);
|
|
2636
3103
|
}
|
|
2637
3104
|
}
|
|
2638
3105
|
console.log();
|
|
2639
3106
|
}
|
|
2640
3107
|
});
|
|
2641
|
-
search =
|
|
3108
|
+
search = defineCommand5({
|
|
2642
3109
|
meta: {
|
|
2643
3110
|
name: "search",
|
|
2644
3111
|
description: "Search community skills"
|
|
@@ -2654,24 +3121,24 @@ var init_skills2 = __esm({
|
|
|
2654
3121
|
const results = await searchCatalog(args.keyword);
|
|
2655
3122
|
if (results.length === 0) {
|
|
2656
3123
|
console.log(`No skills found for "${args.keyword}".`);
|
|
2657
|
-
console.log(` Browse the catalog at: ${
|
|
3124
|
+
console.log(` Browse the catalog at: ${pc10.cyan("https://skills.sh/")}`);
|
|
2658
3125
|
return;
|
|
2659
3126
|
}
|
|
2660
3127
|
console.log();
|
|
2661
3128
|
console.log(`${results.length} skill(s) matching "${args.keyword}":`);
|
|
2662
3129
|
console.log();
|
|
2663
3130
|
for (const skill of results) {
|
|
2664
|
-
console.log(` ${
|
|
3131
|
+
console.log(` ${pc10.bold(skill.name)}`);
|
|
2665
3132
|
console.log(` ${skill.description}`);
|
|
2666
|
-
console.log(` ${
|
|
3133
|
+
console.log(` ${pc10.dim(skill.repo)}`);
|
|
2667
3134
|
if (skill.tags.length > 0) {
|
|
2668
|
-
console.log(` ${
|
|
3135
|
+
console.log(` ${pc10.dim(skill.tags.join(", "))}`);
|
|
2669
3136
|
}
|
|
2670
3137
|
console.log();
|
|
2671
3138
|
}
|
|
2672
3139
|
}
|
|
2673
3140
|
});
|
|
2674
|
-
add =
|
|
3141
|
+
add = defineCommand5({
|
|
2675
3142
|
meta: {
|
|
2676
3143
|
name: "add",
|
|
2677
3144
|
description: "Install a community skill"
|
|
@@ -2687,7 +3154,7 @@ var init_skills2 = __esm({
|
|
|
2687
3154
|
await addSkill(process.cwd(), args.source);
|
|
2688
3155
|
}
|
|
2689
3156
|
});
|
|
2690
|
-
remove =
|
|
3157
|
+
remove = defineCommand5({
|
|
2691
3158
|
meta: {
|
|
2692
3159
|
name: "remove",
|
|
2693
3160
|
description: "Remove an installed community skill"
|
|
@@ -2703,7 +3170,7 @@ var init_skills2 = __esm({
|
|
|
2703
3170
|
await removeSkill(process.cwd(), args.name);
|
|
2704
3171
|
}
|
|
2705
3172
|
});
|
|
2706
|
-
skills_default =
|
|
3173
|
+
skills_default = defineCommand5({
|
|
2707
3174
|
meta: {
|
|
2708
3175
|
name: "skills",
|
|
2709
3176
|
description: "Manage FlyDocs skills (list, search, add, remove)"
|
|
@@ -2723,11 +3190,11 @@ var connect_exports = {};
|
|
|
2723
3190
|
__export(connect_exports, {
|
|
2724
3191
|
default: () => connect_default
|
|
2725
3192
|
});
|
|
2726
|
-
import { defineCommand as
|
|
2727
|
-
import { text as text2, confirm as
|
|
2728
|
-
import
|
|
2729
|
-
import { readFile as
|
|
2730
|
-
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";
|
|
2731
3198
|
var connect_default;
|
|
2732
3199
|
var init_connect = __esm({
|
|
2733
3200
|
"src/commands/connect.ts"() {
|
|
@@ -2736,7 +3203,7 @@ var init_connect = __esm({
|
|
|
2736
3203
|
init_fs_ops();
|
|
2737
3204
|
init_template();
|
|
2738
3205
|
init_ui();
|
|
2739
|
-
connect_default =
|
|
3206
|
+
connect_default = defineCommand6({
|
|
2740
3207
|
meta: {
|
|
2741
3208
|
name: "connect",
|
|
2742
3209
|
description: "Connect FlyDocs to a cloud provider (Linear)"
|
|
@@ -2761,11 +3228,11 @@ var init_connect = __esm({
|
|
|
2761
3228
|
},
|
|
2762
3229
|
async run({ args }) {
|
|
2763
3230
|
const targetDir = args.path ?? process.cwd();
|
|
2764
|
-
const configPath =
|
|
3231
|
+
const configPath = join16(targetDir, ".flydocs", "config.json");
|
|
2765
3232
|
if (!await pathExists(configPath)) {
|
|
2766
3233
|
printError("Not a FlyDocs project (.flydocs/config.json not found).");
|
|
2767
3234
|
console.log(
|
|
2768
|
-
` Run ${
|
|
3235
|
+
` Run ${pc11.cyan("flydocs")} first to install FlyDocs in this project.`
|
|
2769
3236
|
);
|
|
2770
3237
|
process.exit(1);
|
|
2771
3238
|
}
|
|
@@ -2773,19 +3240,19 @@ var init_connect = __esm({
|
|
|
2773
3240
|
if (config.tier === "cloud") {
|
|
2774
3241
|
printInfo("This project is already connected to the cloud tier.");
|
|
2775
3242
|
console.log();
|
|
2776
|
-
const reconnect = await
|
|
3243
|
+
const reconnect = await confirm5({
|
|
2777
3244
|
message: "Want to update your API key?"
|
|
2778
3245
|
});
|
|
2779
|
-
if (
|
|
3246
|
+
if (isCancel6(reconnect) || !reconnect) {
|
|
2780
3247
|
console.log(` No changes made.`);
|
|
2781
3248
|
return;
|
|
2782
3249
|
}
|
|
2783
3250
|
}
|
|
2784
3251
|
console.log();
|
|
2785
|
-
console.log(` ${
|
|
3252
|
+
console.log(` ${pc11.bold("Connect to Linear")}`);
|
|
2786
3253
|
console.log();
|
|
2787
3254
|
console.log(
|
|
2788
|
-
` ${
|
|
3255
|
+
` ${pc11.dim("Get your API key from: Linear \u2192 Settings \u2192 API \u2192 Personal API keys")}`
|
|
2789
3256
|
);
|
|
2790
3257
|
console.log();
|
|
2791
3258
|
let apiKey = args.key ?? "";
|
|
@@ -2800,8 +3267,8 @@ var init_connect = __esm({
|
|
|
2800
3267
|
return void 0;
|
|
2801
3268
|
}
|
|
2802
3269
|
});
|
|
2803
|
-
if (
|
|
2804
|
-
|
|
3270
|
+
if (isCancel6(keyInput)) {
|
|
3271
|
+
cancel5("Connection cancelled.");
|
|
2805
3272
|
process.exit(0);
|
|
2806
3273
|
}
|
|
2807
3274
|
apiKey = keyInput;
|
|
@@ -2825,34 +3292,34 @@ var init_connect = __esm({
|
|
|
2825
3292
|
throw new Error("Invalid response");
|
|
2826
3293
|
}
|
|
2827
3294
|
const viewer = data.data.viewer;
|
|
2828
|
-
printStatus(`Authenticated as ${
|
|
3295
|
+
printStatus(`Authenticated as ${pc11.bold(viewer.name)} (${viewer.email})`);
|
|
2829
3296
|
} catch {
|
|
2830
3297
|
printError("Invalid API key or network error.");
|
|
2831
3298
|
console.log(` Check your key and try again.`);
|
|
2832
3299
|
process.exit(1);
|
|
2833
3300
|
}
|
|
2834
|
-
const envPath =
|
|
2835
|
-
const envLocalPath =
|
|
3301
|
+
const envPath = join16(targetDir, ".env");
|
|
3302
|
+
const envLocalPath = join16(targetDir, ".env.local");
|
|
2836
3303
|
const targetEnvPath = await pathExists(envLocalPath) ? envLocalPath : envPath;
|
|
2837
3304
|
if (await pathExists(targetEnvPath)) {
|
|
2838
|
-
const envContent = await
|
|
3305
|
+
const envContent = await readFile10(targetEnvPath, "utf-8");
|
|
2839
3306
|
if (envContent.includes("LINEAR_API_KEY=")) {
|
|
2840
3307
|
const updated = envContent.replace(
|
|
2841
3308
|
/LINEAR_API_KEY=.*/,
|
|
2842
3309
|
`LINEAR_API_KEY=${apiKey}`
|
|
2843
3310
|
);
|
|
2844
|
-
await
|
|
3311
|
+
await writeFile6(targetEnvPath, updated, "utf-8");
|
|
2845
3312
|
} else {
|
|
2846
3313
|
await appendFile2(targetEnvPath, `
|
|
2847
3314
|
LINEAR_API_KEY=${apiKey}
|
|
2848
3315
|
`);
|
|
2849
3316
|
}
|
|
2850
3317
|
} else {
|
|
2851
|
-
await
|
|
3318
|
+
await writeFile6(targetEnvPath, `LINEAR_API_KEY=${apiKey}
|
|
2852
3319
|
`, "utf-8");
|
|
2853
3320
|
}
|
|
2854
3321
|
printStatus(
|
|
2855
|
-
`API key stored in ${
|
|
3322
|
+
`API key stored in ${pc11.dim(targetEnvPath === envLocalPath ? ".env.local" : ".env")}`
|
|
2856
3323
|
);
|
|
2857
3324
|
const wasLocal = config.tier === "local";
|
|
2858
3325
|
config.tier = "cloud";
|
|
@@ -2865,16 +3332,16 @@ LINEAR_API_KEY=${apiKey}
|
|
|
2865
3332
|
const templateDir = await resolveTemplatePath(
|
|
2866
3333
|
args["local-source"] || void 0
|
|
2867
3334
|
);
|
|
2868
|
-
const templateSkillsDir =
|
|
2869
|
-
const skillsDir =
|
|
3335
|
+
const templateSkillsDir = join16(templateDir, ".claude", "skills");
|
|
3336
|
+
const skillsDir = join16(targetDir, ".claude", "skills");
|
|
2870
3337
|
await replaceDirectory(
|
|
2871
|
-
|
|
2872
|
-
|
|
3338
|
+
join16(templateSkillsDir, "flydocs-cloud"),
|
|
3339
|
+
join16(skillsDir, "flydocs-cloud")
|
|
2873
3340
|
);
|
|
2874
|
-
const { rm:
|
|
2875
|
-
const localSkillDir =
|
|
3341
|
+
const { rm: rm6 } = await import("fs/promises");
|
|
3342
|
+
const localSkillDir = join16(skillsDir, "flydocs-local");
|
|
2876
3343
|
if (await pathExists(localSkillDir)) {
|
|
2877
|
-
await
|
|
3344
|
+
await rm6(localSkillDir, { recursive: true, force: true });
|
|
2878
3345
|
}
|
|
2879
3346
|
printStatus("Cloud mechanism skill installed");
|
|
2880
3347
|
} catch {
|
|
@@ -2885,14 +3352,14 @@ LINEAR_API_KEY=${apiKey}
|
|
|
2885
3352
|
}
|
|
2886
3353
|
console.log();
|
|
2887
3354
|
console.log(
|
|
2888
|
-
` ${
|
|
3355
|
+
` ${pc11.bold("Connected!")} Your project now syncs with Linear.`
|
|
2889
3356
|
);
|
|
2890
3357
|
console.log();
|
|
2891
3358
|
console.log(` Next steps:`);
|
|
2892
3359
|
console.log(
|
|
2893
|
-
` 1. Run ${
|
|
3360
|
+
` 1. Run ${pc11.cyan("/flydocs-setup")} in your IDE to configure your Linear project`
|
|
2894
3361
|
);
|
|
2895
|
-
console.log(` 2. Run ${
|
|
3362
|
+
console.log(` 2. Run ${pc11.cyan("/start-session")} to begin working`);
|
|
2896
3363
|
console.log();
|
|
2897
3364
|
}
|
|
2898
3365
|
});
|
|
@@ -2904,15 +3371,15 @@ var upgrade_exports = {};
|
|
|
2904
3371
|
__export(upgrade_exports, {
|
|
2905
3372
|
default: () => upgrade_default
|
|
2906
3373
|
});
|
|
2907
|
-
import { defineCommand as
|
|
2908
|
-
import
|
|
3374
|
+
import { defineCommand as defineCommand7 } from "citty";
|
|
3375
|
+
import pc12 from "picocolors";
|
|
2909
3376
|
var upgrade_default;
|
|
2910
3377
|
var init_upgrade = __esm({
|
|
2911
3378
|
"src/commands/upgrade.ts"() {
|
|
2912
3379
|
"use strict";
|
|
2913
3380
|
init_config();
|
|
2914
3381
|
init_fs_ops();
|
|
2915
|
-
upgrade_default =
|
|
3382
|
+
upgrade_default = defineCommand7({
|
|
2916
3383
|
meta: {
|
|
2917
3384
|
name: "upgrade",
|
|
2918
3385
|
description: "Learn about FlyDocs Cloud tier and upgrade from local"
|
|
@@ -2941,37 +3408,37 @@ var init_upgrade = __esm({
|
|
|
2941
3408
|
console.log();
|
|
2942
3409
|
if (currentTier === "cloud") {
|
|
2943
3410
|
console.log(
|
|
2944
|
-
` ${
|
|
3411
|
+
` ${pc12.green("\u2713")} You're already on the ${pc12.bold("cloud")} tier.`
|
|
2945
3412
|
);
|
|
2946
3413
|
console.log();
|
|
2947
3414
|
console.log(
|
|
2948
3415
|
` Your issues sync with Linear via the cloud mechanism skill.`
|
|
2949
3416
|
);
|
|
2950
3417
|
console.log(
|
|
2951
|
-
` Run ${
|
|
3418
|
+
` Run ${pc12.cyan("flydocs connect")} to update your connection settings.`
|
|
2952
3419
|
);
|
|
2953
3420
|
console.log();
|
|
2954
3421
|
return;
|
|
2955
3422
|
}
|
|
2956
|
-
console.log(` ${
|
|
3423
|
+
console.log(` ${pc12.bold("FlyDocs Cloud Tier")}`);
|
|
2957
3424
|
console.log();
|
|
2958
|
-
console.log(` You're currently on the ${
|
|
3425
|
+
console.log(` You're currently on the ${pc12.yellow("local")} tier.`);
|
|
2959
3426
|
console.log(` Upgrade to cloud for:`);
|
|
2960
3427
|
console.log();
|
|
2961
3428
|
console.log(
|
|
2962
|
-
` ${
|
|
3429
|
+
` ${pc12.cyan("\u2192")} Issue sync with Linear (Jira coming soon)`
|
|
2963
3430
|
);
|
|
2964
|
-
console.log(` ${
|
|
2965
|
-
console.log(` ${
|
|
2966
|
-
console.log(` ${
|
|
2967
|
-
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`);
|
|
2968
3435
|
console.log();
|
|
2969
|
-
console.log(` ${
|
|
3436
|
+
console.log(` ${pc12.bold("How to upgrade:")}`);
|
|
2970
3437
|
console.log();
|
|
2971
|
-
console.log(` 1. Sign up at ${
|
|
3438
|
+
console.log(` 1. Sign up at ${pc12.cyan("https://www.flydocs.ai")}`);
|
|
2972
3439
|
console.log(` 2. Get your Linear API key from Linear \u2192 Settings \u2192 API`);
|
|
2973
3440
|
console.log(
|
|
2974
|
-
` 3. Run ${
|
|
3441
|
+
` 3. Run ${pc12.cyan("flydocs connect")} to connect your project`
|
|
2975
3442
|
);
|
|
2976
3443
|
console.log();
|
|
2977
3444
|
}
|
|
@@ -2984,23 +3451,23 @@ var self_update_exports = {};
|
|
|
2984
3451
|
__export(self_update_exports, {
|
|
2985
3452
|
default: () => self_update_default
|
|
2986
3453
|
});
|
|
2987
|
-
import { defineCommand as
|
|
3454
|
+
import { defineCommand as defineCommand8 } from "citty";
|
|
2988
3455
|
import { execSync } from "child_process";
|
|
2989
|
-
import
|
|
3456
|
+
import pc13 from "picocolors";
|
|
2990
3457
|
var self_update_default;
|
|
2991
3458
|
var init_self_update = __esm({
|
|
2992
3459
|
"src/commands/self-update.ts"() {
|
|
2993
3460
|
"use strict";
|
|
2994
3461
|
init_constants();
|
|
2995
3462
|
init_ui();
|
|
2996
|
-
self_update_default =
|
|
3463
|
+
self_update_default = defineCommand8({
|
|
2997
3464
|
meta: {
|
|
2998
3465
|
name: "self-update",
|
|
2999
3466
|
description: "Update FlyDocs CLI to the latest version"
|
|
3000
3467
|
},
|
|
3001
3468
|
async run() {
|
|
3002
3469
|
console.log();
|
|
3003
|
-
console.log(` Updating ${
|
|
3470
|
+
console.log(` Updating ${pc13.cyan(PACKAGE_NAME)}...`);
|
|
3004
3471
|
console.log();
|
|
3005
3472
|
try {
|
|
3006
3473
|
execSync(`npm install -g ${PACKAGE_NAME}@beta`, {
|
|
@@ -3020,17 +3487,117 @@ var init_self_update = __esm({
|
|
|
3020
3487
|
}
|
|
3021
3488
|
});
|
|
3022
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
|
+
|
|
3023
3588
|
// src/cli.ts
|
|
3024
3589
|
init_constants();
|
|
3025
|
-
import { defineCommand as
|
|
3590
|
+
import { defineCommand as defineCommand10, runMain } from "citty";
|
|
3026
3591
|
var SUB_COMMANDS = /* @__PURE__ */ new Set([
|
|
3027
3592
|
"install",
|
|
3028
3593
|
"update",
|
|
3594
|
+
"uninstall",
|
|
3029
3595
|
"setup",
|
|
3030
3596
|
"skills",
|
|
3031
3597
|
"connect",
|
|
3032
3598
|
"upgrade",
|
|
3033
|
-
"self-update"
|
|
3599
|
+
"self-update",
|
|
3600
|
+
"telemetry"
|
|
3034
3601
|
]);
|
|
3035
3602
|
var userArgs = process.argv.slice(2);
|
|
3036
3603
|
var hasMetaFlag = userArgs.some(
|
|
@@ -3040,7 +3607,7 @@ var firstPositional = userArgs.find((a) => !a.startsWith("-"));
|
|
|
3040
3607
|
if (!hasMetaFlag && (!firstPositional || !SUB_COMMANDS.has(firstPositional))) {
|
|
3041
3608
|
process.argv.splice(2, 0, "install");
|
|
3042
3609
|
}
|
|
3043
|
-
var main =
|
|
3610
|
+
var main = defineCommand10({
|
|
3044
3611
|
meta: {
|
|
3045
3612
|
name: CLI_NAME,
|
|
3046
3613
|
version: CLI_VERSION,
|
|
@@ -3049,11 +3616,13 @@ var main = defineCommand8({
|
|
|
3049
3616
|
subCommands: {
|
|
3050
3617
|
install: () => Promise.resolve().then(() => (init_install(), install_exports)).then((m) => m.default),
|
|
3051
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),
|
|
3052
3620
|
setup: () => Promise.resolve().then(() => (init_setup(), setup_exports)).then((m) => m.default),
|
|
3053
3621
|
skills: () => Promise.resolve().then(() => (init_skills2(), skills_exports)).then((m) => m.default),
|
|
3054
3622
|
connect: () => Promise.resolve().then(() => (init_connect(), connect_exports)).then((m) => m.default),
|
|
3055
3623
|
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)
|
|
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)
|
|
3057
3626
|
}
|
|
3058
3627
|
});
|
|
3059
3628
|
runMain(main);
|