@swarmvaultai/cli 3.12.0 → 3.14.0

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.
Files changed (3) hide show
  1. package/README.md +58 -56
  2. package/dist/index.js +275 -13
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -29,72 +29,61 @@ The smoke parses `packages/cli/src/index.ts` with the TypeScript compiler API, c
29
29
 
30
30
  ## First Run
31
31
 
32
+ Start in an empty folder or scratch folder:
33
+
32
34
  ```bash
33
35
  mkdir my-vault
34
36
  cd my-vault
35
- swarmvault init --obsidian --profile personal-research
36
- swarmvault init --obsidian --profile reader,timeline
37
+ swarmvault quickstart ../your-repo
38
+ ```
39
+
40
+ That single command initializes a vault, ingests the input, compiles the wiki and graph, writes share artifacts, and opens the local graph viewer. It is the beginner-friendly alias for `swarmvault scan`.
41
+
42
+ No input ready yet?
43
+
44
+ ```bash
37
45
  swarmvault demo
38
- swarmvault source add https://github.com/karpathy/micrograd
39
- swarmvault source add https://github.com/owner/repo --branch main --checkout-dir .swarmvault-checkouts/repo
40
- swarmvault source add https://example.com/docs/getting-started
41
- swarmvault source add ./exports/customer-call.srt --guide
42
- swarmvault source session file-customer-call-srt-12345678
43
- swarmvault source list
44
- swarmvault source reload --all
45
- sed -n '1,120p' swarmvault.schema.md
46
- swarmvault ingest ./notes.md
47
- swarmvault ingest ./customer-call.mp3
48
- swarmvault ingest https://www.youtube.com/watch?v=dQw4w9WgXcQ
49
- swarmvault ingest --video https://example.com/product-demo.mp4
50
- swarmvault ingest ./repo
46
+ ```
47
+
48
+ After the first compile, use:
49
+
50
+ ```bash
51
+ swarmvault next
52
+ swarmvault query "What are the key concepts?"
53
+ swarmvault graph serve
54
+ swarmvault doctor
55
+ swarmvault candidate list
56
+ ```
57
+
58
+ `swarmvault next` is read-only. It detects whether the current folder needs init, ingest, compile, graph refresh, review, or query work and prints the safest next commands.
59
+
60
+ Use the step-by-step flow when you want more control:
61
+
62
+ ```bash
63
+ swarmvault init --obsidian --profile personal-research
64
+ swarmvault ingest ./src --repo-root .
65
+ swarmvault ingest ./meeting.srt --guide
51
66
  swarmvault add https://arxiv.org/abs/2401.12345
52
- swarmvault compile --max-tokens 120000
53
- swarmvault diff
54
- swarmvault graph share --post
55
- swarmvault graph share --svg ./share-card.svg
56
- swarmvault graph share --bundle ./share-kit
57
- swarmvault benchmark
58
- swarmvault query "What keeps recurring?" --commit
59
- swarmvault chat "What should the next agent know?"
60
- swarmvault chat --resume <session-id> "What changed?"
61
- swarmvault export ai --out ./exports/ai
62
- swarmvault context build "Ship this feature safely" --target ./src --budget 8000
63
- swarmvault task start "Ship this feature safely" --target ./src --agent codex
64
- swarmvault retrieval status
65
- swarmvault doctor --repair
66
- swarmvault query "Turn this into slides" --format slides
67
- swarmvault explore "What should I research next?" --steps 3
68
- swarmvault lint --deep
69
- swarmvault graph blast ./src/index.ts
70
- swarmvault graph status ./src
71
- swarmvault check-update ./src
72
- swarmvault graph stats
73
- swarmvault graph validate --strict
74
- swarmvault graph update .
75
- swarmvault update .
76
- swarmvault graph cluster
77
- swarmvault cluster-only
78
- swarmvault graph tree --output ./exports/tree.html
79
- swarmvault tree --output ./exports/tree.html
80
- swarmvault graph query "Which nodes bridge the biggest clusters?"
81
- swarmvault graph explain "concept:drift"
82
- swarmvault watch status
83
- swarmvault watch --repo --once
84
- swarmvault hook install
67
+ swarmvault compile
68
+ swarmvault next
69
+ swarmvault query "What is the auth flow?"
85
70
  swarmvault graph serve
86
- swarmvault graph export --report ./exports/report.html
87
- swarmvault graph export --html ./exports/graph.html
88
- swarmvault graph export --cypher ./exports/graph.cypher
89
- swarmvault graph export --neo4j ./exports/graph.cypher
90
- swarmvault graph merge ./exports/graph.json ./other-graph.json --out ./exports/merged-graph.json
91
- swarmvault merge-graphs ./exports/graph.json ./other-graph.json --out ./exports/merged-graph.json
92
- swarmvault graph push neo4j --dry-run
93
- swarmvault clone https://github.com/owner/repo --no-viz
94
71
  ```
95
72
 
73
+ Use `source add` for recurring inputs (`swarmvault source add https://github.com/karpathy/micrograd`, `swarmvault source add https://example.com/docs/getting-started`, `swarmvault source list`, `swarmvault source reload --all`, and `swarmvault source session file-customer-call-srt-12345678`). Use advanced graph/context surfaces when needed: `swarmvault graph status ./src`, `swarmvault check-update ./src`, `swarmvault update ./src`, `swarmvault graph stats`, `swarmvault graph validate --strict`, `swarmvault graph cluster`, `swarmvault cluster-only`, `swarmvault tree --output ./exports/tree.html`, `swarmvault export ai --out ./exports/ai`, `swarmvault context build "Ship this feature safely" --target ./src --budget 8000`, and `swarmvault task start "Ship this feature safely" --target ./src --agent codex`.
74
+
96
75
  ## Commands
97
76
 
77
+ ### `swarmvault next`
78
+
79
+ Print the safest next command for the current directory without changing files.
80
+
81
+ - reports `uninitialized`, `initialized`, or `compiled`
82
+ - prints key vault paths such as config, schema, `raw/`, `wiki/`, `state/graph.json`, and the graph report
83
+ - recommends `quickstart`, `init`, `ingest`, `compile`, `query`, review, doctor, or graph refresh commands based on current state
84
+ - supports `--json` with `status`, `paths`, `checks`, and `recommendations`
85
+ - does not emit notices, prompts, repairs, or writes
86
+
98
87
  ### `swarmvault init [--obsidian] [--profile <alias-or-presets>]`
99
88
 
100
89
  Create a workspace with:
@@ -116,6 +105,19 @@ Set `SWARMVAULT_OUT=<dir>` when generated artifacts should be isolated from the
116
105
 
117
106
  `--profile` accepts `default`, `personal-research`, or a comma-separated preset list such as `reader,timeline`. For fully custom vault behavior, edit the `profile` block in `swarmvault.config.json`; that deterministic profile layer works alongside the human-written `swarmvault.schema.md`. The `personal-research` preset also sets `profile.guidedIngestDefault: true` and `profile.deepLintDefault: true`, so guided ingest/source and lint flows are on by default until you override them with `--no-guide` or `--no-deep`.
118
107
 
108
+ ### `swarmvault quickstart <directory|github-url> [--port <port>] [--no-serve] [--no-viz] [--mcp] [--branch <name>] [--ref <ref>] [--checkout-dir <path>]`
109
+
110
+ Beginner-friendly alias for `swarmvault scan`.
111
+
112
+ - initializes the current directory as a SwarmVault workspace
113
+ - ingests the supplied local directory, or registers/syncs the supplied public GitHub repo root URL
114
+ - compiles wiki, graph, search, and share artifacts immediately
115
+ - prints the generated `raw/`, `wiki/`, `state/graph.json`, and `wiki/graph/` paths in human output
116
+ - starts `graph serve` unless you pass `--no-serve` or `--no-viz`
117
+ - keeps the same JSON output contract as `scan`
118
+
119
+ Use this as the default first-run command in docs and onboarding.
120
+
119
121
  ### `swarmvault scan <directory|github-url> [--port <port>] [--no-serve] [--no-viz] [--mcp] [--branch <name>] [--ref <ref>] [--checkout-dir <path>]`
120
122
 
121
123
  Quick-start a scratch vault from a local directory or public GitHub repo root URL in one command.
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { readFileSync } from "fs";
5
- import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
5
+ import { access, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
6
6
  import path2 from "path";
7
7
  import process2 from "process";
8
8
  import { createInterface } from "readline/promises";
@@ -21,6 +21,7 @@ import {
21
21
  compileVault,
22
22
  consolidateVault,
23
23
  createSupersessionEdge,
24
+ defaultVaultConfig,
24
25
  deleteChatSession,
25
26
  deleteContextPack,
26
27
  deleteManagedSource,
@@ -85,6 +86,7 @@ import {
85
86
  renderGraphShareBundleFiles,
86
87
  renderGraphShareMarkdown,
87
88
  renderGraphShareSvg,
89
+ resolvePaths,
88
90
  resumeMemoryTask,
89
91
  resumeSourceSession,
90
92
  reviewManagedSource,
@@ -316,12 +318,21 @@ var program = new Command();
316
318
  var CLI_VERSION = readCliVersion();
317
319
  var activeCommand = null;
318
320
  program.name("swarmvault").description("SwarmVault is a local-first knowledge compiler with graph outputs and optional provider-backed workflows.").version(CLI_VERSION).enablePositionalOptions().option("--json", "Emit structured JSON output", false);
321
+ program.addHelpText(
322
+ "after",
323
+ (context2) => context2.command === program ? [
324
+ "",
325
+ "Need help choosing? Run `swarmvault next`.",
326
+ "Advanced and compatibility commands are still available with `swarmvault <command> --help`.",
327
+ "CLI docs: https://www.swarmvault.ai/docs/cli"
328
+ ].join("\n") : ""
329
+ );
319
330
  function readCliVersion() {
320
331
  try {
321
332
  const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
322
- return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "3.12.0";
333
+ return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "3.14.0";
323
334
  } catch {
324
- return "3.12.0";
335
+ return "3.14.0";
325
336
  }
326
337
  }
327
338
  function parsePositiveInt(value, fallback) {
@@ -386,6 +397,232 @@ function log(message) {
386
397
  `);
387
398
  }
388
399
  }
400
+ function serializeNextPaths(paths) {
401
+ return {
402
+ configPath: paths.configPath,
403
+ schemaPath: paths.schemaPath,
404
+ rawDir: paths.rawDir,
405
+ wikiDir: paths.wikiDir,
406
+ stateDir: paths.stateDir,
407
+ graphPath: paths.graphPath,
408
+ reportPath: path2.join(paths.wikiDir, "graph", "report.md")
409
+ };
410
+ }
411
+ async function pathExists(filePath) {
412
+ try {
413
+ await access(filePath);
414
+ return true;
415
+ } catch {
416
+ return false;
417
+ }
418
+ }
419
+ function nextRecommendation(label, command, description, priority) {
420
+ return { label, command, description, priority };
421
+ }
422
+ function dedupeNextRecommendations(recommendations) {
423
+ const seen = /* @__PURE__ */ new Set();
424
+ const rank = { high: 0, medium: 1, low: 2 };
425
+ return recommendations.filter((recommendation) => {
426
+ if (seen.has(recommendation.command)) {
427
+ return false;
428
+ }
429
+ seen.add(recommendation.command);
430
+ return true;
431
+ }).sort((left, right) => rank[left.priority] - rank[right.priority] || left.command.localeCompare(right.command));
432
+ }
433
+ async function buildNextCommandReport(rootDir) {
434
+ const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
435
+ const fallbackPaths = resolvePaths(rootDir, defaultVaultConfig());
436
+ const fallbackNextPaths = serializeNextPaths(fallbackPaths);
437
+ const [configExists, schemaExists] = await Promise.all([pathExists(fallbackPaths.configPath), pathExists(fallbackPaths.schemaPath)]);
438
+ if (!configExists && !schemaExists) {
439
+ return {
440
+ status: "uninitialized",
441
+ rootDir,
442
+ generatedAt,
443
+ paths: fallbackNextPaths,
444
+ checks: [
445
+ {
446
+ id: "workspace",
447
+ label: "Workspace",
448
+ status: "error",
449
+ summary: "No SwarmVault workspace files were found in this directory.",
450
+ command: "swarmvault quickstart ./your-repo"
451
+ }
452
+ ],
453
+ recommendations: [
454
+ nextRecommendation(
455
+ "Fast start",
456
+ "swarmvault quickstart ./your-repo",
457
+ "Initialize, ingest, compile, and open the graph viewer.",
458
+ "high"
459
+ ),
460
+ nextRecommendation("Try a sample", "swarmvault demo", "Build a small demo vault before using your own files.", "medium"),
461
+ nextRecommendation(
462
+ "Manual setup",
463
+ "swarmvault init",
464
+ "Create an empty vault when you want to ingest and compile step by step.",
465
+ "medium"
466
+ )
467
+ ]
468
+ };
469
+ }
470
+ let paths;
471
+ try {
472
+ ({ paths } = await loadVaultConfig(rootDir));
473
+ } catch (error) {
474
+ return {
475
+ status: "initialized",
476
+ rootDir,
477
+ generatedAt,
478
+ paths: fallbackNextPaths,
479
+ checks: [
480
+ {
481
+ id: "config",
482
+ label: "Config",
483
+ status: "error",
484
+ summary: "SwarmVault workspace files exist, but the config could not be loaded.",
485
+ detail: error instanceof Error ? error.message : String(error),
486
+ command: "swarmvault doctor"
487
+ }
488
+ ],
489
+ recommendations: [
490
+ nextRecommendation(
491
+ "Inspect workspace health",
492
+ "swarmvault doctor",
493
+ "Review the config/schema issue before ingesting or compiling.",
494
+ "high"
495
+ )
496
+ ]
497
+ };
498
+ }
499
+ const nextPaths = serializeNextPaths(paths);
500
+ const graphStatus = await getGraphStatus(rootDir).catch(() => null);
501
+ const graphExists = graphStatus?.graphExists ?? await pathExists(paths.graphPath);
502
+ if (!graphExists) {
503
+ return {
504
+ status: "initialized",
505
+ rootDir,
506
+ generatedAt,
507
+ paths: nextPaths,
508
+ checks: [
509
+ {
510
+ id: "workspace",
511
+ label: "Workspace",
512
+ status: "ok",
513
+ summary: "Workspace config and schema are present."
514
+ },
515
+ {
516
+ id: "graph",
517
+ label: "Graph",
518
+ status: "error",
519
+ summary: "No compiled graph artifact was found.",
520
+ command: "swarmvault compile"
521
+ }
522
+ ],
523
+ recommendations: [
524
+ nextRecommendation("Add sources", "swarmvault ingest ./your-source", "Import a directory, file, or URL into raw/.", "high"),
525
+ nextRecommendation("Compile vault", "swarmvault compile", "Build wiki pages, graph JSON, and the graph report.", "high"),
526
+ nextRecommendation("Open the viewer", "swarmvault graph serve", "Open the local graph viewer after compiling.", "medium")
527
+ ],
528
+ graph: graphStatus ? {
529
+ exists: graphStatus.graphExists,
530
+ reportExists: graphStatus.reportExists,
531
+ stale: graphStatus.stale,
532
+ codeChangeCount: graphStatus.codeChangeCount,
533
+ semanticChangeCount: graphStatus.semanticChangeCount,
534
+ trackedRepoRoots: graphStatus.trackedRepoRoots
535
+ } : void 0
536
+ };
537
+ }
538
+ const doctor = await doctorVault(rootDir, { repair: false });
539
+ const recommendations = dedupeNextRecommendations([
540
+ ...graphStatus?.recommendedCommand ? [
541
+ nextRecommendation(
542
+ graphStatus.stale ? "Refresh graph" : "Check graph",
543
+ graphStatus.recommendedCommand,
544
+ graphStatus.stale ? "Tracked inputs changed since the graph was compiled." : "Review graph freshness.",
545
+ graphStatus.stale ? "high" : "medium"
546
+ )
547
+ ] : [],
548
+ ...doctor.recommendations.filter((recommendation) => recommendation.command).map(
549
+ (recommendation) => nextRecommendation(
550
+ recommendation.label,
551
+ recommendation.command,
552
+ recommendation.description ?? recommendation.summary,
553
+ recommendation.priority
554
+ )
555
+ ),
556
+ ...doctor.recommendations.length ? [] : [
557
+ nextRecommendation(
558
+ "Ask a question",
559
+ 'swarmvault query "What are the key concepts?"',
560
+ "Query the compiled wiki and graph.",
561
+ "medium"
562
+ ),
563
+ nextRecommendation("Open the graph", "swarmvault graph serve", "Explore the compiled graph locally.", "medium"),
564
+ nextRecommendation("Run health checks", "swarmvault doctor", "Re-check graph, retrieval, review queues, and migrations.", "low")
565
+ ]
566
+ ]);
567
+ return {
568
+ status: "compiled",
569
+ rootDir,
570
+ generatedAt,
571
+ paths: nextPaths,
572
+ checks: doctor.checks.map((check) => ({
573
+ id: check.id,
574
+ label: check.label,
575
+ status: check.status,
576
+ summary: check.summary,
577
+ detail: check.detail,
578
+ command: check.actions?.[0]?.command
579
+ })),
580
+ recommendations,
581
+ counts: doctor.counts,
582
+ graph: graphStatus ? {
583
+ exists: graphStatus.graphExists,
584
+ reportExists: graphStatus.reportExists,
585
+ stale: graphStatus.stale,
586
+ codeChangeCount: graphStatus.codeChangeCount,
587
+ semanticChangeCount: graphStatus.semanticChangeCount,
588
+ trackedRepoRoots: graphStatus.trackedRepoRoots
589
+ } : void 0
590
+ };
591
+ }
592
+ function printNextCommandReport(report) {
593
+ if (report.status === "uninitialized") {
594
+ log(`SwarmVault is not initialized in ${report.rootDir}.`);
595
+ log("");
596
+ log("Start here:");
597
+ } else {
598
+ log(`SwarmVault workspace: ${report.rootDir}`);
599
+ log(`Config: ${report.paths.configPath}`);
600
+ log(`Schema: ${report.paths.schemaPath}`);
601
+ log(`Raw sources: ${report.paths.rawDir}`);
602
+ log(`Wiki output: ${report.paths.wikiDir}`);
603
+ const graphPresent = report.graph?.exists ?? report.status === "compiled";
604
+ log(`Graph JSON: ${graphPresent ? report.paths.graphPath : `missing (${report.paths.graphPath})`}`);
605
+ log(`Graph report: ${report.graph?.reportExists ? report.paths.reportPath : `missing (${report.paths.reportPath})`}`);
606
+ if (report.graph) {
607
+ log(`Graph state: ${report.graph.stale ? "stale" : "fresh"}`);
608
+ log(`Tracked repo roots: ${report.graph.trackedRepoRoots.length ? report.graph.trackedRepoRoots.join(", ") : "none"}`);
609
+ log(`Pending changes: ${report.graph.codeChangeCount + report.graph.semanticChangeCount}`);
610
+ }
611
+ if (report.counts) {
612
+ log(
613
+ `Counts: ${report.counts.sources} source(s), ${report.counts.pages} page(s), ${report.counts.nodes} node(s), ${report.counts.edges} edge(s).`
614
+ );
615
+ }
616
+ log("");
617
+ log(report.status === "initialized" ? "Status: initialized, not compiled yet." : "Status: compiled.");
618
+ log("");
619
+ log("Next steps:");
620
+ }
621
+ for (const recommendation of report.recommendations.slice(0, 6)) {
622
+ log(` ${recommendation.command}`);
623
+ log(` ${recommendation.description}`);
624
+ }
625
+ }
389
626
  async function writeShareBundle(bundlePath, files) {
390
627
  await mkdir2(bundlePath, { recursive: true });
391
628
  const bundleFiles = {
@@ -608,10 +845,20 @@ async function runScanCommand(input, options) {
608
845
  const shareKitPath = path2.join(paths.wikiDir, "graph", "share-kit");
609
846
  if (!isJson()) {
610
847
  log(`Compiled ${compiled.sourceCount} source(s), ${compiled.pageCount} page(s).`);
848
+ log(`Vault workspace: ${rootDir}`);
849
+ log(`Raw sources: ${paths.rawDir}`);
850
+ log(`Wiki output: ${paths.wikiDir}`);
851
+ log(`Graph JSON: ${paths.graphPath}`);
611
852
  log(`Share card: ${shareCardPath}`);
612
853
  log(`Visual card: ${shareCardSvgPath}`);
613
854
  log(`Share kit: ${shareKitPath}`);
614
- log("Post text: swarmvault graph share --post");
855
+ log("");
856
+ log("Next steps:");
857
+ log(' swarmvault query "What are the key concepts?"');
858
+ log(" swarmvault graph serve");
859
+ log(" swarmvault doctor");
860
+ log(" swarmvault candidate list");
861
+ log(" swarmvault next");
615
862
  }
616
863
  if (options.mcp) {
617
864
  process2.stderr.write(`${JSON.stringify({ status: "running", transport: "stdio", compiled: compiled.sourceCount })}
@@ -641,6 +888,7 @@ async function runScanCommand(input, options) {
641
888
  });
642
889
  } else {
643
890
  log(`Graph viewer running at http://localhost:${server.port}`);
891
+ log("Next orientation: swarmvault next");
644
892
  }
645
893
  process2.on("SIGINT", async () => {
646
894
  try {
@@ -753,8 +1001,12 @@ async function runInteractiveChat(options) {
753
1001
  }
754
1002
  }
755
1003
  program.hook("postAction", async (_thisCommand, actionCommand) => {
1004
+ const commandPath = getCommandPath(actionCommand);
1005
+ if (commandPath[0] === "next" || commandPath[0] === "quickstart" || commandPath[0] === "init") {
1006
+ return;
1007
+ }
756
1008
  const notices = await collectCliNotices({
757
- commandPath: getCommandPath(actionCommand),
1009
+ commandPath,
758
1010
  currentVersion: CLI_VERSION,
759
1011
  json: isJson()
760
1012
  });
@@ -762,6 +1014,15 @@ program.hook("postAction", async (_thisCommand, actionCommand) => {
762
1014
  emitNotice(notice);
763
1015
  }
764
1016
  });
1017
+ program.command("next").description("Show the safest next command for this directory without changing files.").action(async () => {
1018
+ const report = await buildNextCommandReport(process2.cwd());
1019
+ if (isJson()) {
1020
+ emitJson(report);
1021
+ return;
1022
+ }
1023
+ printNextCommandReport(report);
1024
+ });
1025
+ program.command("quickstart").description("Beginner path: initialize, ingest, compile, and optionally open the graph viewer in one command.").argument("<input>", "Directory or public GitHub repo root URL to turn into a vault").option("--port <port>", "Port for the graph viewer").option("--no-serve", "Skip launching the graph viewer after compile").option("--no-viz", "Compatibility alias for --no-serve; skip launching the graph viewer after compile").option("--mcp", "Start the MCP stdio server after compile instead of launching the graph viewer", false).option("--branch <name>", "GitHub branch to clone when the input is a public repo URL").option("--ref <ref>", "Git ref, tag, or commit to check out when the input is a public repo URL").option("--checkout-dir <path>", "Persistent checkout directory for a public GitHub repo input").action(runScanCommand);
765
1026
  program.command("init").description("Initialize a SwarmVault workspace in the current directory.").option("--obsidian", "Generate a minimal .obsidian workspace alongside the vault", false).option(
766
1027
  "--profile <profile>",
767
1028
  "Starter workspace profile or comma-separated preset list (for example: personal-research or reader,timeline)"
@@ -785,6 +1046,7 @@ program.command("init").description("Initialize a SwarmVault workspace in the cu
785
1046
  });
786
1047
  } else {
787
1048
  log(options.lite ? "Initialized SwarmVault lite workspace." : "Initialized SwarmVault workspace.");
1049
+ log("Next: swarmvault next");
788
1050
  }
789
1051
  });
790
1052
  program.command("ingest").description("Ingest a local file path, directory path, or URL into the raw SwarmVault workspace.").argument("<input>", "Local file path, directory path, or URL").option("--review", "Stage a source review artifact after ingest and compile", false).option("--guide", "Stage a guided source integration bundle after ingest and compile (default: from config)").option("--no-guide", "Skip guided mode even if enabled in config").option("--answers-file <path>", "JSON file with guided-session answers keyed by question id or listed in prompt order").option("--include-assets", "Download remote image assets when ingesting URLs", true).option("--no-include-assets", "Skip downloading remote image assets when ingesting URLs").option("--max-asset-size <bytes>", "Maximum number of bytes to fetch for a single remote image asset").option("--repo-root <path>", "Override the detected repo root when ingesting a directory").option("--include <glob...>", "Only ingest files matching one or more glob patterns").option("--exclude <glob...>", "Skip files matching one or more glob patterns").option("--max-files <n>", "Maximum number of files to ingest from a directory").option("--include-third-party", "Also ingest repo files classified as third-party", false).option("--include-resources", "Also ingest repo files classified as resources", false).option("--include-generated", "Also ingest repo files classified as generated output", false).option("--no-gitignore", "Ignore .gitignore rules when ingesting a directory").option("--no-swarmvaultignore", "Ignore .swarmvaultignore rules when ingesting a directory").option("--video", "Treat a URL input as a public video and transcribe extracted audio", false).option("--resume <run-id>", "Re-run only the failed files from a prior ingest run id").option("--commit", "Auto-commit wiki and state changes after ingest").option("--no-redact", "Skip PII/secret redaction for this run (overrides config)").action(
@@ -1224,7 +1486,7 @@ context.command("delete").description("Delete a saved context pack artifact and
1224
1486
  }
1225
1487
  log(`Deleted context pack ${deleted.id}.`);
1226
1488
  });
1227
- var memory = program.command("memory").description("Manage git-backed agent memory task ledger entries.");
1489
+ var memory = program.command("memory", { hidden: true }).description("Manage git-backed agent memory task ledger entries.");
1228
1490
  memory.command("start").description("Start a durable agent memory task and build its initial context pack.").argument("<goal>", "Task goal to preserve in agent memory").option("--target <target>", "Optional page, node, path, project, or label to anchor the initial context pack").option("--budget <tokens>", "Approximate token budget for the initial context pack", String(8e3)).option("--agent <name>", "Agent name to record on the task").option("--context-pack <id>", "Attach an existing context pack instead of building a new one").action(async (goal, options) => {
1229
1491
  const result = await startMemoryTask(process2.cwd(), {
1230
1492
  goal,
@@ -2016,13 +2278,13 @@ async function showWatchStatus() {
2016
2278
  }
2017
2279
  watch.command("status").description("Show the latest watch run plus pending semantic refresh entries.").action(showWatchStatus);
2018
2280
  program.command("watch-status").description("Show the latest watch run plus pending semantic refresh entries.").action(showWatchStatus);
2019
- program.command("check-update").description("Compatibility alias for graph status: read-only graph/report freshness and tracked repo change check.").argument("[path]", "Optional repo root to check instead of configured/tracked roots").action(showGraphStatusCommand);
2020
- program.command("update").description("Compatibility alias for graph update: refresh code-derived graph artifacts from tracked repo roots.").argument("[path]", "Optional repo root to refresh instead of configured/tracked roots").option("--lint", "Run lint after the refresh cycle", false).option("--force", "Allow graph updates even when node or edge counts shrink sharply", false).action(runGraphUpdateCommand);
2021
- program.command("cluster-only").description("Compatibility alias for graph cluster: recompute graph communities and report artifacts without re-ingesting.").argument("[vault]", "Optional vault root to cluster instead of the current directory").option("--resolution <number>", "Override the Louvain community resolution for this run").action(
2281
+ program.command("check-update", { hidden: true }).description("Compatibility alias for graph status: read-only graph/report freshness and tracked repo change check.").argument("[path]", "Optional repo root to check instead of configured/tracked roots").action(showGraphStatusCommand);
2282
+ program.command("update", { hidden: true }).description("Compatibility alias for graph update: refresh code-derived graph artifacts from tracked repo roots.").argument("[path]", "Optional repo root to refresh instead of configured/tracked roots").option("--lint", "Run lint after the refresh cycle", false).option("--force", "Allow graph updates even when node or edge counts shrink sharply", false).action(runGraphUpdateCommand);
2283
+ program.command("cluster-only", { hidden: true }).description("Compatibility alias for graph cluster: recompute graph communities and report artifacts without re-ingesting.").argument("[vault]", "Optional vault root to cluster instead of the current directory").option("--resolution <number>", "Override the Louvain community resolution for this run").action(
2022
2284
  (vaultPath, options) => runGraphClusterCommand(options, vaultPath ? path2.resolve(process2.cwd(), vaultPath) : process2.cwd())
2023
2285
  );
2024
- program.command("tree").description("Compatibility alias for graph tree: write a collapsible source/module/symbol tree for the compiled graph.").option("--output <html>", "Output HTML path (default: wiki/graph/tree.html)").option("--root <path>", "Vault root to read instead of the current directory").option("--label <name>", "Tree title").option("--max-children <n>", "Maximum children to render per tree node", "250").action(runGraphTreeCommand);
2025
- program.command("merge-graphs").description("Compatibility alias for graph merge: combine graph JSON files into one namespaced graph artifact.").argument("<graphs...>", "Graph JSON files to merge").requiredOption("--out <path>", "Output graph JSON path").option("--label <name>", "Label/prefix to use when merging one graph").action(runGraphMergeCommand);
2286
+ program.command("tree", { hidden: true }).description("Compatibility alias for graph tree: write a collapsible source/module/symbol tree for the compiled graph.").option("--output <html>", "Output HTML path (default: wiki/graph/tree.html)").option("--root <path>", "Vault root to read instead of the current directory").option("--label <name>", "Tree title").option("--max-children <n>", "Maximum children to render per tree node", "250").action(runGraphTreeCommand);
2287
+ program.command("merge-graphs", { hidden: true }).description("Compatibility alias for graph merge: combine graph JSON files into one namespaced graph artifact.").argument("<graphs...>", "Graph JSON files to merge").requiredOption("--out <path>", "Output graph JSON path").option("--label <name>", "Label/prefix to use when merging one graph").action(runGraphMergeCommand);
2026
2288
  var hook = program.command("hook").description("Install local git hooks that keep tracked repos and the vault in sync.");
2027
2289
  hook.command("install").description("Install post-commit and post-checkout hooks for the nearest git repository.").action(async () => {
2028
2290
  const status = await installGitHooks(process2.cwd());
@@ -2503,8 +2765,8 @@ retrieval.command("doctor").description("Diagnose retrieval index problems and o
2503
2765
  log(`Warning: ${warning}`);
2504
2766
  }
2505
2767
  });
2506
- program.command("scan").description("Quick-start: initialize, ingest, compile, and serve a graph viewer in one command.").argument("<input>", "Directory or public GitHub repo root URL to scan").option("--port <port>", "Port for the graph viewer").option("--no-serve", "Skip launching the graph viewer after compile").option("--no-viz", "Compatibility alias for --no-serve; skip launching the graph viewer after compile").option("--mcp", "Start the MCP stdio server after compile instead of launching the graph viewer", false).option("--branch <name>", "GitHub branch to clone when scanning a public repo URL").option("--ref <ref>", "Git ref, tag, or commit to check out when scanning a public repo URL").option("--checkout-dir <path>", "Persistent checkout directory for a public GitHub repo scan").action(runScanCommand);
2507
- program.command("clone").description("Compatibility alias for scan: initialize, clone/register a public repo URL, and compile it into the vault.").argument("<input>", "Public GitHub repo URL or local directory to scan").option("--port <port>", "Port for the graph viewer").option("--no-serve", "Skip launching the graph viewer after compile").option("--no-viz", "Compatibility alias for --no-serve; skip launching the graph viewer after compile").option("--mcp", "Start the MCP stdio server after compile instead of launching the graph viewer", false).option("--branch <name>", "GitHub branch to clone when scanning a public repo URL").option("--ref <ref>", "Git ref, tag, or commit to check out when scanning a public repo URL").option("--checkout-dir <path>", "Persistent checkout directory for a public GitHub repo scan").action(runScanCommand);
2768
+ program.command("scan", { hidden: true }).description("Quick-start: initialize, ingest, compile, and serve a graph viewer in one command.").argument("<input>", "Directory or public GitHub repo root URL to scan").option("--port <port>", "Port for the graph viewer").option("--no-serve", "Skip launching the graph viewer after compile").option("--no-viz", "Compatibility alias for --no-serve; skip launching the graph viewer after compile").option("--mcp", "Start the MCP stdio server after compile instead of launching the graph viewer", false).option("--branch <name>", "GitHub branch to clone when scanning a public repo URL").option("--ref <ref>", "Git ref, tag, or commit to check out when scanning a public repo URL").option("--checkout-dir <path>", "Persistent checkout directory for a public GitHub repo scan").action(runScanCommand);
2769
+ program.command("clone", { hidden: true }).description("Compatibility alias for scan: initialize, clone/register a public repo URL, and compile it into the vault.").argument("<input>", "Public GitHub repo URL or local directory to scan").option("--port <port>", "Port for the graph viewer").option("--no-serve", "Skip launching the graph viewer after compile").option("--no-viz", "Compatibility alias for --no-serve; skip launching the graph viewer after compile").option("--mcp", "Start the MCP stdio server after compile instead of launching the graph viewer", false).option("--branch <name>", "GitHub branch to clone when scanning a public repo URL").option("--ref <ref>", "Git ref, tag, or commit to check out when scanning a public repo URL").option("--checkout-dir <path>", "Persistent checkout directory for a public GitHub repo scan").action(runScanCommand);
2508
2770
  function enableStructuredJsonOnSubcommands(command) {
2509
2771
  for (const subcommand of command.commands) {
2510
2772
  const hasJsonOption = subcommand.options.some((option) => option.attributeName() === "json");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swarmvaultai/cli",
3
- "version": "3.12.0",
3
+ "version": "3.14.0",
4
4
  "description": "Global CLI for SwarmVault.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -44,7 +44,7 @@
44
44
  "prepublishOnly": "node ../../scripts/check-release-sync.mjs && node ../../scripts/check-published-manifests.mjs"
45
45
  },
46
46
  "dependencies": {
47
- "@swarmvaultai/engine": "3.12.0",
47
+ "@swarmvaultai/engine": "3.14.0",
48
48
  "commander": "^14.0.1"
49
49
  },
50
50
  "devDependencies": {