@flydocs/cli 0.6.0-alpha.33 → 0.6.0-alpha.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -15,7 +15,7 @@ var CLI_VERSION, CLI_NAME, PACKAGE_NAME, POSTHOG_API_KEY;
15
15
  var init_constants = __esm({
16
16
  "src/lib/constants.ts"() {
17
17
  "use strict";
18
- CLI_VERSION = "0.6.0-alpha.33";
18
+ CLI_VERSION = "0.6.0-alpha.35";
19
19
  CLI_NAME = "flydocs";
20
20
  PACKAGE_NAME = "@flydocs/cli";
21
21
  POSTHOG_API_KEY = "phc_v1MSJTQDFkMS90CBh3mxIz3v8bYCCnKU6v1ir6bz0Xn";
@@ -1328,6 +1328,11 @@ async function scanDeprecated(targetDir) {
1328
1328
  found.push(item);
1329
1329
  }
1330
1330
  }
1331
+ for (const file of DEPRECATED_CONTEXT_FILES) {
1332
+ if (await pathExists(join10(targetDir, file))) {
1333
+ found.push(file);
1334
+ }
1335
+ }
1331
1336
  for (const skill of DEPRECATED_SKILLS) {
1332
1337
  const p = join10(targetDir, ".claude", "skills", skill);
1333
1338
  if (await pathExists(p)) {
@@ -1413,6 +1418,17 @@ async function checkLegacyFolder(targetDir) {
1413
1418
  }
1414
1419
  return null;
1415
1420
  }
1421
+ async function autoCleanup(targetDir, paths) {
1422
+ let cleaned = 0;
1423
+ for (const p of paths) {
1424
+ await rm3(join10(targetDir, p), { recursive: true, force: true });
1425
+ cleaned++;
1426
+ }
1427
+ if (cleaned > 0) {
1428
+ printStatus(`Cleaned ${cleaned} deprecated file(s)`);
1429
+ }
1430
+ return cleaned;
1431
+ }
1416
1432
  async function promptCleanup(targetDir, paths) {
1417
1433
  if (paths.length === 0) {
1418
1434
  printStatus("No deprecated files found");
@@ -1436,7 +1452,7 @@ async function promptCleanup(targetDir, paths) {
1436
1452
  printStatus(`Deleted: ${p}`);
1437
1453
  }
1438
1454
  }
1439
- var DEPRECATED_DIRS, DEPRECATED_FILES, DEPRECATED_SKILLS, DEPRECATED_RULES_DIR, DEPRECATED_FLYDOCS_DIRS, DEPRECATED_HOOKS, DEPRECATED_CURSOR_RULES, DEPRECATED_CURSOR_RULE_DIRS, DEPRECATED_COMMANDS;
1455
+ var DEPRECATED_DIRS, DEPRECATED_FILES, DEPRECATED_CONTEXT_FILES, DEPRECATED_SKILLS, DEPRECATED_RULES_DIR, DEPRECATED_FLYDOCS_DIRS, DEPRECATED_HOOKS, DEPRECATED_CURSOR_RULES, DEPRECATED_CURSOR_RULE_DIRS, DEPRECATED_COMMANDS;
1440
1456
  var init_deprecated = __esm({
1441
1457
  "src/lib/deprecated.ts"() {
1442
1458
  "use strict";
@@ -1444,6 +1460,11 @@ var init_deprecated = __esm({
1444
1460
  init_ui();
1445
1461
  DEPRECATED_DIRS = [".docflow", "docflow"];
1446
1462
  DEPRECATED_FILES = ["AGENTS.md.bak", ".cursor/mcp.json"];
1463
+ DEPRECATED_CONTEXT_FILES = [
1464
+ "flydocs/context/overview.md",
1465
+ "flydocs/context/stack.md",
1466
+ "flydocs/context/standards.md"
1467
+ ];
1447
1468
  DEPRECATED_SKILLS = [
1448
1469
  "linear-workflow",
1449
1470
  "session-workflow",
@@ -3027,11 +3048,11 @@ async function fetchTemplates(apiKey, sinceVersion, workspaceId) {
3027
3048
  }
3028
3049
  return await response.json();
3029
3050
  }
3030
- async function fetchArtifacts(apiKey, sinceVersion) {
3051
+ async function fetchArtifacts(apiKey, sinceVersion, workspaceId) {
3031
3052
  const baseUrl = resolveRelayUrl();
3032
3053
  const response = await fetch(`${baseUrl}/artifacts?since=${sinceVersion}`, {
3033
3054
  method: "GET",
3034
- headers: headers(apiKey),
3055
+ headers: headers(apiKey, workspaceId),
3035
3056
  signal: AbortSignal.timeout(3e4)
3036
3057
  });
3037
3058
  if (!response.ok) {
@@ -3044,23 +3065,6 @@ async function fetchArtifacts(apiKey, sinceVersion) {
3044
3065
  }
3045
3066
  return await response.json();
3046
3067
  }
3047
- async function fetchAgentConfigs(apiKey, workspaceId) {
3048
- const baseUrl = resolveRelayUrl();
3049
- const response = await fetch(`${baseUrl}/artifacts/agent-configs`, {
3050
- method: "GET",
3051
- headers: headers(apiKey, workspaceId),
3052
- signal: AbortSignal.timeout(15e3)
3053
- });
3054
- if (!response.ok) {
3055
- const body = await response.text().catch(() => "");
3056
- throw new RelayError(
3057
- `agent-configs fetch failed (${response.status})`,
3058
- response.status,
3059
- body
3060
- );
3061
- }
3062
- return await response.json();
3063
- }
3064
3068
  async function triggerScan(apiKey, repoName, options) {
3065
3069
  const baseUrl = resolveRelayUrl();
3066
3070
  const body = {
@@ -3191,7 +3195,7 @@ function isPathSkipped(artifactPath, skipPaths) {
3191
3195
  );
3192
3196
  }
3193
3197
  async function syncArtifacts(targetDir, apiKey, workspaceId, currentVersion, skipPaths = []) {
3194
- const response = await fetchArtifacts(apiKey, currentVersion);
3198
+ const response = await fetchArtifacts(apiKey, currentVersion, workspaceId);
3195
3199
  if (response.artifacts.length === 0) {
3196
3200
  return { written: 0, skipped: 0, version: currentVersion };
3197
3201
  }
@@ -3213,23 +3217,6 @@ async function syncArtifacts(targetDir, apiKey, workspaceId, currentVersion, ski
3213
3217
  }
3214
3218
  return { written, skipped, version: response.version };
3215
3219
  }
3216
- async function syncAgentConfigs(targetDir, apiKey, workspaceId, skipPaths = []) {
3217
- const response = await fetchAgentConfigs(apiKey, workspaceId);
3218
- let written = 0;
3219
- for (const file of response.files) {
3220
- if (skipPaths.length > 0 && isPathSkipped(file.path, skipPaths)) {
3221
- continue;
3222
- }
3223
- const filePath = join19(targetDir, file.path);
3224
- await mkdir9(dirname3(filePath), { recursive: true });
3225
- await writeFile11(filePath, file.content, "utf-8");
3226
- written++;
3227
- }
3228
- if (written > 0) {
3229
- printStatus(`Wrote ${written} agent config(s) (CLAUDE.md, AGENTS.md)`);
3230
- }
3231
- return written;
3232
- }
3233
3220
  async function writeArtifact(targetDir, artifact) {
3234
3221
  const filePath = join19(targetDir, artifact.path);
3235
3222
  await mkdir9(dirname3(filePath), { recursive: true });
@@ -3271,25 +3258,6 @@ async function syncAllArtifacts(targetDir, apiKey, workspaceId, currentArtifactV
3271
3258
  printWarning("Artifact sync failed. Will retry on next sync.");
3272
3259
  }
3273
3260
  }
3274
- try {
3275
- const configCount = await syncAgentConfigs(
3276
- targetDir,
3277
- apiKey,
3278
- workspaceId,
3279
- skipPaths
3280
- );
3281
- if (configCount > 0) {
3282
- changes.push(`Wrote ${configCount} agent config(s)`);
3283
- }
3284
- } catch (err) {
3285
- if (err instanceof RelayError) {
3286
- printWarning(
3287
- `Could not fetch agent configs (${err.status}). Will retry on next sync.`
3288
- );
3289
- } else {
3290
- printWarning("Agent config sync failed. Will retry on next sync.");
3291
- }
3292
- }
3293
3261
  return { artifactVersion, changes };
3294
3262
  }
3295
3263
  var init_artifacts = __esm({
@@ -3938,7 +3906,14 @@ __export(init_exports, {
3938
3906
  default: () => init_default
3939
3907
  });
3940
3908
  import { defineCommand as defineCommand4 } from "citty";
3941
- import { text as text2, confirm as confirm3, select as select2, isCancel as isCancel4, cancel as cancel3 } from "@clack/prompts";
3909
+ import {
3910
+ text as text2,
3911
+ confirm as confirm3,
3912
+ select as select2,
3913
+ multiselect as multiselect2,
3914
+ isCancel as isCancel4,
3915
+ cancel as cancel3
3916
+ } from "@clack/prompts";
3942
3917
  import pc9 from "picocolors";
3943
3918
  import { join as join24 } from "path";
3944
3919
  import { mkdir as mkdir12, writeFile as writeFile16 } from "fs/promises";
@@ -4309,19 +4284,61 @@ async function isParentDirectory(dir) {
4309
4284
  }
4310
4285
  async function runMultiRepoInit(parentDir, keyArg) {
4311
4286
  const repos = await detectSiblingRepos(parentDir);
4312
- const repoNames = Object.keys(repos).sort();
4313
- printInfo(`Detected ${repoNames.length} repos:`);
4314
- for (const name of repoNames) {
4315
- console.log(` ${pc9.cyan(name)}`);
4316
- }
4287
+ const allRepoNames = Object.keys(repos).sort();
4288
+ printInfo(`Detected ${allRepoNames.length} repos:`);
4317
4289
  console.log();
4318
- const shouldContinue = await confirm3({
4319
- message: `Initialize all ${repoNames.length} repos?`
4290
+ const existingInstalls = [];
4291
+ for (const name of allRepoNames) {
4292
+ const repoDir = join24(parentDir, name);
4293
+ const hasSkills = await pathExists(join24(repoDir, ".claude", "skills"));
4294
+ const hasConfig = await pathExists(
4295
+ join24(repoDir, ".flydocs", "config.json")
4296
+ );
4297
+ if (hasSkills && hasConfig) {
4298
+ existingInstalls.push(name);
4299
+ }
4300
+ }
4301
+ if (existingInstalls.length > 0) {
4302
+ printWarning(
4303
+ `${existingInstalls.length} repo(s) have existing single-repo FlyDocs installs:`
4304
+ );
4305
+ for (const name of existingInstalls) {
4306
+ console.log(` ${pc9.yellow(name)}`);
4307
+ }
4308
+ console.log();
4309
+ console.log(` Multi-repo init will migrate these to workspace mode:`);
4310
+ console.log(
4311
+ ` ${pc9.dim("- IDE configs (skills, hooks, commands) move to workspace root")}`
4312
+ );
4313
+ console.log(
4314
+ ` ${pc9.dim("- Per-repo context (project.md, service.json) preserved")}`
4315
+ );
4316
+ console.log(
4317
+ ` ${pc9.dim("- Existing IDE configs archived to flydocs/knowledge/archived/")}`
4318
+ );
4319
+ console.log();
4320
+ }
4321
+ const selectedRepos = await multiselect2({
4322
+ message: "Which repos would you like to initialize?",
4323
+ options: allRepoNames.map((name) => ({
4324
+ value: name,
4325
+ label: name,
4326
+ hint: existingInstalls.includes(name) ? "has existing install" : void 0
4327
+ })),
4328
+ initialValues: allRepoNames,
4329
+ required: true
4320
4330
  });
4321
- if (isCancel4(shouldContinue) || !shouldContinue) {
4331
+ if (isCancel4(selectedRepos)) {
4322
4332
  cancel3("Init cancelled.");
4323
4333
  process.exit(0);
4324
4334
  }
4335
+ const repoNames = selectedRepos;
4336
+ if (repoNames.length === 0) {
4337
+ cancel3("No repos selected.");
4338
+ process.exit(0);
4339
+ }
4340
+ printInfo(`Initializing ${repoNames.length} of ${allRepoNames.length} repos`);
4341
+ console.log();
4325
4342
  const firstRepoDir = join24(parentDir, repoNames[0]);
4326
4343
  const { apiKey, workspaceId } = await resolveAndValidateKey(
4327
4344
  keyArg,
@@ -4380,9 +4397,13 @@ async function runMultiRepoInit(parentDir, keyArg) {
4380
4397
  if (existing) {
4381
4398
  allSkipped.push(".flydocs-workspace.json (already exists)");
4382
4399
  } else {
4400
+ const selectedRepoEntries = {};
4401
+ for (const name of repoNames) {
4402
+ if (repos[name]) selectedRepoEntries[name] = repos[name];
4403
+ }
4383
4404
  const workspaceFile = buildWorkspaceFile(
4384
4405
  firstResponse.workspaceId,
4385
- repos
4406
+ selectedRepoEntries
4386
4407
  );
4387
4408
  await writeWorkspaceFile(parentDir, workspaceFile);
4388
4409
  allActions.push(`.flydocs-workspace.json (${repoNames.length} repos)`);
@@ -4799,7 +4820,10 @@ async function runSync(targetDir) {
4799
4820
  }
4800
4821
  let serverResponse;
4801
4822
  try {
4802
- serverResponse = await fetchConfigV2(apiKey, { workspaceId });
4823
+ serverResponse = await fetchConfigV2(apiKey, {
4824
+ workspaceId,
4825
+ includeContext: true
4826
+ });
4803
4827
  } catch (err) {
4804
4828
  if (err instanceof RelayError) {
4805
4829
  printWarning(`Server unavailable (${err.status}), using cached config.`);
@@ -4910,6 +4934,33 @@ async function runSync(targetDir) {
4910
4934
  changes.push(`Deleted ${conflicts.deleted} non-core skill(s)`);
4911
4935
  }
4912
4936
  }
4937
+ const deprecated = await scanDeprecated(targetDir);
4938
+ if (deprecated.length > 0) {
4939
+ const cleaned = await autoCleanup(targetDir, deprecated);
4940
+ changes.push(`Removed ${cleaned} deprecated file(s)`);
4941
+ }
4942
+ if (serverResponse.context?.projectMd) {
4943
+ const { writeFile: fsWriteFile } = await import("fs/promises");
4944
+ const contextDir = join26(targetDir, "flydocs", "context");
4945
+ await mkdir14(contextDir, { recursive: true });
4946
+ await fsWriteFile(
4947
+ join26(contextDir, "project.md"),
4948
+ serverResponse.context.projectMd,
4949
+ "utf-8"
4950
+ );
4951
+ changes.push("Updated flydocs/context/project.md from server");
4952
+ }
4953
+ if (serverResponse.context?.serviceJson) {
4954
+ const { writeFile: fsWriteFile } = await import("fs/promises");
4955
+ const contextDir = join26(targetDir, "flydocs", "context");
4956
+ await mkdir14(contextDir, { recursive: true });
4957
+ await fsWriteFile(
4958
+ join26(contextDir, "service.json"),
4959
+ JSON.stringify(serverResponse.context.serviceJson, null, 2) + "\n",
4960
+ "utf-8"
4961
+ );
4962
+ changes.push("Updated flydocs/context/service.json from server");
4963
+ }
4913
4964
  await migrateGitignore(targetDir);
4914
4965
  return changes;
4915
4966
  }
@@ -4938,10 +4989,11 @@ var init_sync = __esm({
4938
4989
  init_workspace();
4939
4990
  init_relay_client();
4940
4991
  init_skill_conflicts();
4992
+ init_deprecated();
4941
4993
  sync_default = defineCommand5({
4942
4994
  meta: {
4943
4995
  name: "sync",
4944
- description: "Pull latest config and templates from server"
4996
+ description: "Sync files from server (alias for update)"
4945
4997
  },
4946
4998
  args: {
4947
4999
  path: {
@@ -4952,6 +5004,7 @@ var init_sync = __esm({
4952
5004
  async run({ args }) {
4953
5005
  const targetDir = args.path ?? process.cwd();
4954
5006
  console.log();
5007
+ printInfo("Note: flydocs sync is now an alias for flydocs update");
4955
5008
  const changes = await runSync(targetDir);
4956
5009
  if (changes.length === 0) {
4957
5010
  printStatus("Already up to date.");
@@ -5001,7 +5054,7 @@ var init_update = __esm({
5001
5054
  update_default = defineCommand6({
5002
5055
  meta: {
5003
5056
  name: "update",
5004
- description: "Update an existing FlyDocs installation"
5057
+ description: "Update CLI and sync all managed files from server"
5005
5058
  },
5006
5059
  args: {
5007
5060
  path: {
@@ -5157,10 +5210,6 @@ var init_update = __esm({
5157
5210
  printStatus(change);
5158
5211
  }
5159
5212
  }
5160
- console.log();
5161
- console.log(
5162
- ` ${pc11.dim("Tip: use")} ${pc11.cyan("flydocs sync")} ${pc11.dim("for file-only refresh (no CLI update).")}`
5163
- );
5164
5213
  await capture("update_completed", {
5165
5214
  current_version: currentVersion,
5166
5215
  version,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flydocs/cli",
3
- "version": "0.6.0-alpha.33",
3
+ "version": "0.6.0-alpha.35",
4
4
  "type": "module",
5
5
  "description": "FlyDocs AI CLI — install, setup, and manage FlyDocs projects",
6
6
  "bin": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.6.0-alpha.33",
2
+ "version": "0.6.0-alpha.35",
3
3
  "sourceRepo": "github.com/plastrlab/flydocs-core",
4
4
  "tier": "local",
5
5
  "setupComplete": false,
@@ -1 +1 @@
1
- 0.6.0-alpha.33
1
+ 0.6.0-alpha.35
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.6.0-alpha.33",
2
+ "version": "0.6.0-alpha.35",
3
3
  "description": "FlyDocs Core - Manifest of all managed files",
4
4
  "repository": "github.com/plastrlab/flydocs-core",
5
5