@swarmvaultai/cli 3.10.0 → 3.11.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.
- package/README.md +38 -2
- package/dist/index.js +122 -101
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -73,6 +73,7 @@ swarmvault update .
|
|
|
73
73
|
swarmvault graph cluster
|
|
74
74
|
swarmvault cluster-only
|
|
75
75
|
swarmvault graph tree --output ./exports/tree.html
|
|
76
|
+
swarmvault tree --output ./exports/tree.html
|
|
76
77
|
swarmvault graph query "Which nodes bridge the biggest clusters?"
|
|
77
78
|
swarmvault graph explain "concept:drift"
|
|
78
79
|
swarmvault watch status
|
|
@@ -84,7 +85,9 @@ swarmvault graph export --html ./exports/graph.html
|
|
|
84
85
|
swarmvault graph export --cypher ./exports/graph.cypher
|
|
85
86
|
swarmvault graph export --neo4j ./exports/graph.cypher
|
|
86
87
|
swarmvault graph merge ./exports/graph.json ./other-graph.json --out ./exports/merged-graph.json
|
|
88
|
+
swarmvault merge-graphs ./exports/graph.json ./other-graph.json --out ./exports/merged-graph.json
|
|
87
89
|
swarmvault graph push neo4j --dry-run
|
|
90
|
+
swarmvault clone https://github.com/owner/repo --no-viz
|
|
88
91
|
```
|
|
89
92
|
|
|
90
93
|
## Commands
|
|
@@ -110,7 +113,7 @@ Set `SWARMVAULT_OUT=<dir>` when generated artifacts should be isolated from the
|
|
|
110
113
|
|
|
111
114
|
`--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`.
|
|
112
115
|
|
|
113
|
-
### `swarmvault scan <directory|github-url> [--port <port>] [--no-serve] [--branch <name>] [--ref <ref>] [--checkout-dir <path>]`
|
|
116
|
+
### `swarmvault scan <directory|github-url> [--port <port>] [--no-serve] [--no-viz] [--mcp] [--branch <name>] [--ref <ref>] [--checkout-dir <path>]`
|
|
114
117
|
|
|
115
118
|
Quick-start a scratch vault from a local directory or public GitHub repo root URL in one command.
|
|
116
119
|
|
|
@@ -118,12 +121,22 @@ Quick-start a scratch vault from a local directory or public GitHub repo root UR
|
|
|
118
121
|
- ingests the supplied directory as local sources, or registers/syncs the supplied public GitHub repo root URL
|
|
119
122
|
- compiles the vault immediately
|
|
120
123
|
- writes `wiki/graph/share-card.md`, `wiki/graph/share-card.svg`, and `wiki/graph/share-kit/`, then prints the paths
|
|
121
|
-
- starts `graph serve` unless you pass `--no-serve`
|
|
124
|
+
- starts `graph serve` unless you pass `--no-serve` or `--no-viz`
|
|
125
|
+
- `--no-viz` is a compatibility alias for `--no-serve`
|
|
126
|
+
- `--mcp` starts the MCP stdio server after compile instead of the graph viewer
|
|
122
127
|
- respects `--port` when you want a specific viewer port
|
|
123
128
|
- for GitHub repo URLs, supports `--branch`, `--ref`, and `--checkout-dir`
|
|
124
129
|
|
|
125
130
|
Use this when you want the fastest repo or docs-tree walkthrough without first deciding on managed-source registration.
|
|
126
131
|
|
|
132
|
+
### `swarmvault clone <directory|github-url> [--no-viz] [--mcp] [--branch <name>] [--ref <ref>] [--checkout-dir <path>]`
|
|
133
|
+
|
|
134
|
+
Compatibility alias for `swarmvault scan`.
|
|
135
|
+
|
|
136
|
+
- initializes, ingests or registers the input, and compiles in one command
|
|
137
|
+
- supports the same public GitHub repo checkout flags as `scan`
|
|
138
|
+
- accepts `--no-serve`, `--no-viz`, `--mcp`, and `--port`
|
|
139
|
+
|
|
127
140
|
### `swarmvault demo [--port <port>] [--no-serve]`
|
|
128
141
|
|
|
129
142
|
Create a temporary sample vault with bundled sources, compile it immediately, and launch the graph viewer unless you pass `--no-serve`.
|
|
@@ -440,6 +453,13 @@ Write a collapsible HTML source tree for the current `state/graph.json`.
|
|
|
440
453
|
- `--max-children` caps very wide folders or modules with a `+N more` row
|
|
441
454
|
- `--json` returns the output path, source count, node count, and tree payload
|
|
442
455
|
|
|
456
|
+
### `swarmvault tree [--output <html>] [--root <path>] [--label <name>] [--max-children <n>]`
|
|
457
|
+
|
|
458
|
+
Compatibility alias for `swarmvault graph tree`.
|
|
459
|
+
|
|
460
|
+
- writes the same source/module/symbol tree
|
|
461
|
+
- returns the same JSON shape as `graph tree`
|
|
462
|
+
|
|
443
463
|
### `swarmvault graph merge <graph...> --out <path> [--label <name>]`
|
|
444
464
|
|
|
445
465
|
Merge multiple graph JSON files into one namespaced graph artifact.
|
|
@@ -450,6 +470,13 @@ Merge multiple graph JSON files into one namespaced graph artifact.
|
|
|
450
470
|
- maps explicit extracted/inferred/ambiguous edge evidence into SwarmVault edge semantics
|
|
451
471
|
- `--json` returns the merged graph, input summaries, and warnings
|
|
452
472
|
|
|
473
|
+
### `swarmvault merge-graphs <graph...> --out <path> [--label <name>]`
|
|
474
|
+
|
|
475
|
+
Compatibility alias for `swarmvault graph merge`.
|
|
476
|
+
|
|
477
|
+
- accepts the same SwarmVault and NetworkX/node-link graph inputs
|
|
478
|
+
- returns the same JSON shape as `graph merge`
|
|
479
|
+
|
|
453
480
|
### `swarmvault graph status [path]`
|
|
454
481
|
|
|
455
482
|
Read-only graph freshness check for tracked repo roots or one explicit repo path.
|
|
@@ -461,6 +488,15 @@ Read-only graph freshness check for tracked repo roots or one explicit repo path
|
|
|
461
488
|
- recommends `swarmvault compile` when graph/report artifacts are missing, non-code files changed, or a semantic refresh is pending
|
|
462
489
|
- supports global `--json` for automation
|
|
463
490
|
|
|
491
|
+
### `swarmvault watch [path] [--once] [--code-only] [--lint]`
|
|
492
|
+
|
|
493
|
+
Watch or refresh one explicit repo root without first writing `watch.repoRoots`.
|
|
494
|
+
|
|
495
|
+
- positional `[path]` is treated as a repo-root override and turns on repo mode
|
|
496
|
+
- `--once` runs one refresh cycle and exits
|
|
497
|
+
- `--code-only` limits the refresh to parser-backed repo graph artifacts
|
|
498
|
+
- repeated `--root <path>` remains available when you need multiple roots
|
|
499
|
+
|
|
464
500
|
### `swarmvault graph stats`
|
|
465
501
|
|
|
466
502
|
Summarize the current compiled graph without opening the viewer.
|
package/dist/index.js
CHANGED
|
@@ -315,9 +315,9 @@ program.name("swarmvault").description("SwarmVault is a local-first knowledge co
|
|
|
315
315
|
function readCliVersion() {
|
|
316
316
|
try {
|
|
317
317
|
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
318
|
-
return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "3.
|
|
318
|
+
return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "3.11.0";
|
|
319
319
|
} catch {
|
|
320
|
-
return "3.
|
|
320
|
+
return "3.11.0";
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
323
|
function parsePositiveInt(value, fallback) {
|
|
@@ -545,6 +545,110 @@ async function runGraphClusterCommand(options, rootDir = process2.cwd()) {
|
|
|
545
545
|
`Refreshed ${result.communityCount} communities across ${result.nodeCount} nodes and ${result.edgeCount} edges. Report: ${result.reportPath}`
|
|
546
546
|
);
|
|
547
547
|
}
|
|
548
|
+
async function runGraphTreeCommand(options) {
|
|
549
|
+
const rootDir = options.root ? path2.resolve(process2.cwd(), options.root) : process2.cwd();
|
|
550
|
+
const result = await exportGraphTree(rootDir, options.output, {
|
|
551
|
+
label: options.label,
|
|
552
|
+
maxChildren: parsePositiveInt(options.maxChildren, 250)
|
|
553
|
+
});
|
|
554
|
+
if (isJson()) {
|
|
555
|
+
emitJson(result);
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
log(`Graph tree: ${result.outputPath}`);
|
|
559
|
+
log(`Sources: ${result.sourceCount}; nodes: ${result.nodeCount}.`);
|
|
560
|
+
}
|
|
561
|
+
async function runGraphMergeCommand(graphPaths, options) {
|
|
562
|
+
const result = await mergeGraphFiles(
|
|
563
|
+
graphPaths.map((inputPath) => path2.resolve(process2.cwd(), inputPath)),
|
|
564
|
+
path2.resolve(process2.cwd(), options.out),
|
|
565
|
+
{ label: options.label }
|
|
566
|
+
);
|
|
567
|
+
if (isJson()) {
|
|
568
|
+
emitJson(result);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
log(
|
|
572
|
+
`Merged ${result.inputGraphs.length} graph${result.inputGraphs.length === 1 ? "" : "s"} into ${result.outputPath}. Nodes ${result.graph.nodes.length}, edges ${result.graph.edges.length}.`
|
|
573
|
+
);
|
|
574
|
+
for (const warning of result.warnings) {
|
|
575
|
+
log(`Warning: ${warning}`);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
async function runScanCommand(input, options) {
|
|
579
|
+
const rootDir = process2.cwd();
|
|
580
|
+
await initVault(rootDir, {});
|
|
581
|
+
if (!isJson()) {
|
|
582
|
+
log("Initialized workspace.");
|
|
583
|
+
}
|
|
584
|
+
const result = isHttpUrlInput(input) ? await addManagedSource(rootDir, input, {
|
|
585
|
+
compile: true,
|
|
586
|
+
brief: false,
|
|
587
|
+
branch: options.branch,
|
|
588
|
+
ref: options.ref,
|
|
589
|
+
checkoutDir: options.checkoutDir
|
|
590
|
+
}) : await ingestDirectory(rootDir, input, {});
|
|
591
|
+
if (!isJson()) {
|
|
592
|
+
if ("source" in result) {
|
|
593
|
+
log(
|
|
594
|
+
`Registered ${result.source.kind} source ${result.source.id}. Imported ${result.source.lastSyncCounts?.importedCount ?? 0}, updated ${result.source.lastSyncCounts?.updatedCount ?? 0}.`
|
|
595
|
+
);
|
|
596
|
+
} else {
|
|
597
|
+
log(`Ingested ${result.imported.length} file(s).`);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
const compiled = "compile" in result && result.compile ? result.compile : await compileVault(rootDir, {});
|
|
601
|
+
const { paths } = await loadVaultConfig(rootDir);
|
|
602
|
+
const shareCardPath = path2.join(paths.wikiDir, "graph", "share-card.md");
|
|
603
|
+
const shareCardSvgPath = path2.join(paths.wikiDir, "graph", "share-card.svg");
|
|
604
|
+
const shareKitPath = path2.join(paths.wikiDir, "graph", "share-kit");
|
|
605
|
+
if (!isJson()) {
|
|
606
|
+
log(`Compiled ${compiled.sourceCount} source(s), ${compiled.pageCount} page(s).`);
|
|
607
|
+
log(`Share card: ${shareCardPath}`);
|
|
608
|
+
log(`Visual card: ${shareCardSvgPath}`);
|
|
609
|
+
log(`Share kit: ${shareKitPath}`);
|
|
610
|
+
log("Post text: swarmvault graph share --post");
|
|
611
|
+
}
|
|
612
|
+
if (options.mcp) {
|
|
613
|
+
process2.stderr.write(`${JSON.stringify({ status: "running", transport: "stdio", compiled: compiled.sourceCount })}
|
|
614
|
+
`);
|
|
615
|
+
const controller = await startMcpServer(rootDir);
|
|
616
|
+
process2.on("SIGINT", async () => {
|
|
617
|
+
try {
|
|
618
|
+
await controller.close();
|
|
619
|
+
} catch {
|
|
620
|
+
}
|
|
621
|
+
process2.exit(0);
|
|
622
|
+
});
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
if (options.serve !== false && options.viz !== false) {
|
|
626
|
+
const port = options.port ? parsePositiveInt(options.port, 0) || void 0 : void 0;
|
|
627
|
+
const server = await startGraphServer(rootDir, port, { full: false });
|
|
628
|
+
if (isJson()) {
|
|
629
|
+
emitJson({
|
|
630
|
+
...result,
|
|
631
|
+
compiled,
|
|
632
|
+
shareCardPath,
|
|
633
|
+
shareCardSvgPath,
|
|
634
|
+
shareKitPath,
|
|
635
|
+
port: server.port,
|
|
636
|
+
url: `http://localhost:${server.port}`
|
|
637
|
+
});
|
|
638
|
+
} else {
|
|
639
|
+
log(`Graph viewer running at http://localhost:${server.port}`);
|
|
640
|
+
}
|
|
641
|
+
process2.on("SIGINT", async () => {
|
|
642
|
+
try {
|
|
643
|
+
await server.close();
|
|
644
|
+
} catch {
|
|
645
|
+
}
|
|
646
|
+
process2.exit(0);
|
|
647
|
+
});
|
|
648
|
+
} else if (isJson()) {
|
|
649
|
+
emitJson({ ...result, compiled, shareCardPath, shareCardSvgPath, shareKitPath });
|
|
650
|
+
}
|
|
651
|
+
}
|
|
548
652
|
program.hook("postAction", async (_thisCommand, actionCommand) => {
|
|
549
653
|
const notices = await collectCliNotices({
|
|
550
654
|
commandPath: getCommandPath(actionCommand),
|
|
@@ -1215,36 +1319,8 @@ program.command("lint").description("Run anti-drift and wiki-health checks.").op
|
|
|
1215
1319
|
var graph = program.command("graph").description("Graph-related commands.").enablePositionalOptions();
|
|
1216
1320
|
var graphPush = graph.command("push").description("Push the compiled graph into external sinks.");
|
|
1217
1321
|
graph.command("update").alias("refresh").description("Refresh code-derived graph artifacts from tracked repo roots or one explicit repo path.").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);
|
|
1218
|
-
graph.command("tree").description("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(
|
|
1219
|
-
|
|
1220
|
-
const result = await exportGraphTree(rootDir, options.output, {
|
|
1221
|
-
label: options.label,
|
|
1222
|
-
maxChildren: parsePositiveInt(options.maxChildren, 250)
|
|
1223
|
-
});
|
|
1224
|
-
if (isJson()) {
|
|
1225
|
-
emitJson(result);
|
|
1226
|
-
return;
|
|
1227
|
-
}
|
|
1228
|
-
log(`Graph tree: ${result.outputPath}`);
|
|
1229
|
-
log(`Sources: ${result.sourceCount}; nodes: ${result.nodeCount}.`);
|
|
1230
|
-
});
|
|
1231
|
-
graph.command("merge").description("Merge SwarmVault or node-link JSON graph 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(async (graphPaths, options) => {
|
|
1232
|
-
const result = await mergeGraphFiles(
|
|
1233
|
-
graphPaths.map((inputPath) => path2.resolve(process2.cwd(), inputPath)),
|
|
1234
|
-
path2.resolve(process2.cwd(), options.out),
|
|
1235
|
-
{ label: options.label }
|
|
1236
|
-
);
|
|
1237
|
-
if (isJson()) {
|
|
1238
|
-
emitJson(result);
|
|
1239
|
-
return;
|
|
1240
|
-
}
|
|
1241
|
-
log(
|
|
1242
|
-
`Merged ${result.inputGraphs.length} graph${result.inputGraphs.length === 1 ? "" : "s"} into ${result.outputPath}. Nodes ${result.graph.nodes.length}, edges ${result.graph.edges.length}.`
|
|
1243
|
-
);
|
|
1244
|
-
for (const warning of result.warnings) {
|
|
1245
|
-
log(`Warning: ${warning}`);
|
|
1246
|
-
}
|
|
1247
|
-
});
|
|
1322
|
+
graph.command("tree").description("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);
|
|
1323
|
+
graph.command("merge").description("Merge SwarmVault or node-link JSON graph 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);
|
|
1248
1324
|
graph.command("status").description("Read-only check for graph/report presence and tracked repo changes.").argument("[path]", "Optional repo root to check instead of configured/tracked roots").action(showGraphStatusCommand);
|
|
1249
1325
|
graph.command("stats").description("Summarize compiled graph counts, node types, evidence classes, and relation mix.").action(async () => {
|
|
1250
1326
|
const stats = await graphStatsVault(process2.cwd());
|
|
@@ -1691,14 +1767,16 @@ async function confirmInteractive(message) {
|
|
|
1691
1767
|
rl.close();
|
|
1692
1768
|
}
|
|
1693
1769
|
}
|
|
1694
|
-
var watch = program.command("watch").description("Watch the inbox directory and optionally tracked repos, or run one refresh cycle immediately.").option("--lint", "Run lint after each compile cycle", false).option("--repo", "Also refresh tracked repo sources and watch their repo roots", false).option("--once", "Run one import/refresh cycle immediately instead of starting a watcher", false).option("--code-only", "Only re-extract code sources (AST-only, no LLM re-analysis)", false).option("--debounce <ms>", "Debounce window in milliseconds", "900").option("--root <path>", "Watch this repo root instead of config/auto-discovery (repeat for multiple)", collectRepeated, []).option("--force", "Allow graph updates even when node or edge counts shrink sharply", false).action(
|
|
1695
|
-
async (options) => {
|
|
1770
|
+
var watch = program.command("watch").description("Watch the inbox directory and optionally tracked repos, or run one refresh cycle immediately.").argument("[path]", "Optional repo root to watch or refresh instead of config/auto-discovery").option("--lint", "Run lint after each compile cycle", false).option("--repo", "Also refresh tracked repo sources and watch their repo roots", false).option("--once", "Run one import/refresh cycle immediately instead of starting a watcher", false).option("--code-only", "Only re-extract code sources (AST-only, no LLM re-analysis)", false).option("--debounce <ms>", "Debounce window in milliseconds", "900").option("--root <path>", "Watch this repo root instead of config/auto-discovery (repeat for multiple)", collectRepeated, []).option("--force", "Allow graph updates even when node or edge counts shrink sharply", false).action(
|
|
1771
|
+
async (targetPath, options) => {
|
|
1696
1772
|
const debounceMs = parsePositiveInt(options.debounce, 900);
|
|
1697
|
-
const
|
|
1773
|
+
const rootOverrides = [...targetPath ? [targetPath] : [], ...options.root ?? []];
|
|
1774
|
+
const overrideRoots = rootOverrides.length > 0 ? rootOverrides : void 0;
|
|
1775
|
+
const repoMode = options.repo || Boolean(targetPath);
|
|
1698
1776
|
if (options.once) {
|
|
1699
1777
|
const result = await runWatchCycle(process2.cwd(), {
|
|
1700
1778
|
lint: options.lint ?? false,
|
|
1701
|
-
repo:
|
|
1779
|
+
repo: repoMode,
|
|
1702
1780
|
codeOnly: options.codeOnly ?? false,
|
|
1703
1781
|
debounceMs,
|
|
1704
1782
|
force: options.force ?? false,
|
|
@@ -1708,7 +1786,7 @@ var watch = program.command("watch").description("Watch the inbox directory and
|
|
|
1708
1786
|
emitJson(result);
|
|
1709
1787
|
} else {
|
|
1710
1788
|
log(
|
|
1711
|
-
`Refreshed inbox${
|
|
1789
|
+
`Refreshed inbox${repoMode ? " and tracked repos" : ""}. Imported ${result.importedCount}, repo imported ${result.repoImportedCount}, repo updated ${result.repoUpdatedCount}, repo removed ${result.repoRemovedCount}.`
|
|
1712
1790
|
);
|
|
1713
1791
|
}
|
|
1714
1792
|
return;
|
|
@@ -1716,16 +1794,16 @@ var watch = program.command("watch").description("Watch the inbox directory and
|
|
|
1716
1794
|
const { paths } = await loadVaultConfig(process2.cwd());
|
|
1717
1795
|
const controller = await watchVault(process2.cwd(), {
|
|
1718
1796
|
lint: options.lint ?? false,
|
|
1719
|
-
repo:
|
|
1797
|
+
repo: repoMode,
|
|
1720
1798
|
codeOnly: options.codeOnly ?? false,
|
|
1721
1799
|
debounceMs,
|
|
1722
1800
|
force: options.force ?? false,
|
|
1723
1801
|
overrideRoots
|
|
1724
1802
|
});
|
|
1725
1803
|
if (isJson()) {
|
|
1726
|
-
emitJson({ status: "watching", inboxDir: paths.inboxDir, repo:
|
|
1804
|
+
emitJson({ status: "watching", inboxDir: paths.inboxDir, repo: repoMode });
|
|
1727
1805
|
} else {
|
|
1728
|
-
log(`Watching inbox${
|
|
1806
|
+
log(`Watching inbox${repoMode ? " and tracked repos" : ""} for changes. Press Ctrl+C to stop.`);
|
|
1729
1807
|
}
|
|
1730
1808
|
process2.on("SIGINT", async () => {
|
|
1731
1809
|
try {
|
|
@@ -1785,6 +1863,8 @@ program.command("update").description("Compatibility alias for graph update: ref
|
|
|
1785
1863
|
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(
|
|
1786
1864
|
(vaultPath, options) => runGraphClusterCommand(options, vaultPath ? path2.resolve(process2.cwd(), vaultPath) : process2.cwd())
|
|
1787
1865
|
);
|
|
1866
|
+
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);
|
|
1867
|
+
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);
|
|
1788
1868
|
var hook = program.command("hook").description("Install local git hooks that keep tracked repos and the vault in sync.");
|
|
1789
1869
|
hook.command("install").description("Install post-commit and post-checkout hooks for the nearest git repository.").action(async () => {
|
|
1790
1870
|
const status = await installGitHooks(process2.cwd());
|
|
@@ -2265,67 +2345,8 @@ retrieval.command("doctor").description("Diagnose retrieval index problems and o
|
|
|
2265
2345
|
log(`Warning: ${warning}`);
|
|
2266
2346
|
}
|
|
2267
2347
|
});
|
|
2268
|
-
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("--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(
|
|
2269
|
-
|
|
2270
|
-
await initVault(rootDir, {});
|
|
2271
|
-
if (!isJson()) {
|
|
2272
|
-
log("Initialized workspace.");
|
|
2273
|
-
}
|
|
2274
|
-
const result = isHttpUrlInput(input) ? await addManagedSource(rootDir, input, {
|
|
2275
|
-
compile: true,
|
|
2276
|
-
brief: false,
|
|
2277
|
-
branch: options.branch,
|
|
2278
|
-
ref: options.ref,
|
|
2279
|
-
checkoutDir: options.checkoutDir
|
|
2280
|
-
}) : await ingestDirectory(rootDir, input, {});
|
|
2281
|
-
if (!isJson()) {
|
|
2282
|
-
if ("source" in result) {
|
|
2283
|
-
log(
|
|
2284
|
-
`Registered ${result.source.kind} source ${result.source.id}. Imported ${result.source.lastSyncCounts?.importedCount ?? 0}, updated ${result.source.lastSyncCounts?.updatedCount ?? 0}.`
|
|
2285
|
-
);
|
|
2286
|
-
} else {
|
|
2287
|
-
log(`Ingested ${result.imported.length} file(s).`);
|
|
2288
|
-
}
|
|
2289
|
-
}
|
|
2290
|
-
const compiled = "compile" in result && result.compile ? result.compile : await compileVault(rootDir, {});
|
|
2291
|
-
const { paths } = await loadVaultConfig(rootDir);
|
|
2292
|
-
const shareCardPath = path2.join(paths.wikiDir, "graph", "share-card.md");
|
|
2293
|
-
const shareCardSvgPath = path2.join(paths.wikiDir, "graph", "share-card.svg");
|
|
2294
|
-
const shareKitPath = path2.join(paths.wikiDir, "graph", "share-kit");
|
|
2295
|
-
if (!isJson()) {
|
|
2296
|
-
log(`Compiled ${compiled.sourceCount} source(s), ${compiled.pageCount} page(s).`);
|
|
2297
|
-
log(`Share card: ${shareCardPath}`);
|
|
2298
|
-
log(`Visual card: ${shareCardSvgPath}`);
|
|
2299
|
-
log(`Share kit: ${shareKitPath}`);
|
|
2300
|
-
log("Post text: swarmvault graph share --post");
|
|
2301
|
-
}
|
|
2302
|
-
if (options.serve !== false) {
|
|
2303
|
-
const port = options.port ? parsePositiveInt(options.port, 0) || void 0 : void 0;
|
|
2304
|
-
const server = await startGraphServer(rootDir, port, { full: false });
|
|
2305
|
-
if (isJson()) {
|
|
2306
|
-
emitJson({
|
|
2307
|
-
...result,
|
|
2308
|
-
compiled,
|
|
2309
|
-
shareCardPath,
|
|
2310
|
-
shareCardSvgPath,
|
|
2311
|
-
shareKitPath,
|
|
2312
|
-
port: server.port,
|
|
2313
|
-
url: `http://localhost:${server.port}`
|
|
2314
|
-
});
|
|
2315
|
-
} else {
|
|
2316
|
-
log(`Graph viewer running at http://localhost:${server.port}`);
|
|
2317
|
-
}
|
|
2318
|
-
process2.on("SIGINT", async () => {
|
|
2319
|
-
try {
|
|
2320
|
-
await server.close();
|
|
2321
|
-
} catch {
|
|
2322
|
-
}
|
|
2323
|
-
process2.exit(0);
|
|
2324
|
-
});
|
|
2325
|
-
} else if (isJson()) {
|
|
2326
|
-
emitJson({ ...result, compiled, shareCardPath, shareCardSvgPath, shareKitPath });
|
|
2327
|
-
}
|
|
2328
|
-
});
|
|
2348
|
+
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);
|
|
2349
|
+
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);
|
|
2329
2350
|
function enableStructuredJsonOnSubcommands(command) {
|
|
2330
2351
|
for (const subcommand of command.commands) {
|
|
2331
2352
|
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.
|
|
3
|
+
"version": "3.11.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.
|
|
47
|
+
"@swarmvaultai/engine": "3.11.0",
|
|
48
48
|
"commander": "^14.0.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|