@swarmvaultai/cli 1.1.0 → 1.3.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 +15 -0
  2. package/dist/index.js +71 -18
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -39,6 +39,8 @@ swarmvault ingest ./repo
39
39
  swarmvault add https://arxiv.org/abs/2401.12345
40
40
  swarmvault compile --max-tokens 120000
41
41
  swarmvault diff
42
+ swarmvault graph share --post
43
+ swarmvault graph share --svg ./share-card.svg
42
44
  swarmvault benchmark
43
45
  swarmvault query "What keeps recurring?" --commit
44
46
  swarmvault query "Turn this into slides" --format slides
@@ -85,6 +87,7 @@ Quick-start a scratch vault from a local directory in one command.
85
87
  - initializes the current directory as a SwarmVault workspace
86
88
  - ingests the supplied directory as local sources
87
89
  - compiles the vault immediately
90
+ - writes `wiki/graph/share-card.md` and `wiki/graph/share-card.svg`, then prints both paths
88
91
  - starts `graph serve` unless you pass `--no-serve`
89
92
  - respects `--port` when you want a specific viewer port
90
93
 
@@ -97,6 +100,7 @@ Create a temporary sample vault with bundled sources, compile it immediately, an
97
100
  - writes the demo vault under the system temp directory
98
101
  - requires no API keys or extra setup
99
102
  - is the fastest way to inspect the full init + ingest + compile + graph workflow on a clean machine
103
+ - writes `wiki/graph/share-card.md` and `wiki/graph/share-card.svg` inside the demo vault
100
104
  - respects `--port` when you want a specific viewer port
101
105
 
102
106
  ### `swarmvault diff`
@@ -207,6 +211,7 @@ Compile the current manifests into:
207
211
  - generated markdown in `wiki/`
208
212
  - structured graph data in `state/graph.json`
209
213
  - local search data in `state/search.sqlite`
214
+ - share cards at `wiki/graph/share-card.md` and `wiki/graph/share-card.svg`
210
215
 
211
216
  The compiler also reads `swarmvault.schema.md` and records a `schema_hash` plus lifecycle metadata such as `status`, `created_at`, `updated_at`, `compiled_from`, and `managed_by` in generated pages so schema edits can mark pages stale without losing lifecycle state.
212
217
 
@@ -366,6 +371,16 @@ Inspect graph metadata, community membership, neighbors, provenance, and group-p
366
371
 
367
372
  List the most connected bridge-heavy nodes in the current graph.
368
373
 
374
+ ### `swarmvault graph share [--post] [--svg [path]]`
375
+
376
+ Print a shareable summary of the compiled graph.
377
+
378
+ - default output is the same markdown shape written to `wiki/graph/share-card.md`
379
+ - `--post` prints only the concise social-post text
380
+ - `--svg [path]` writes the 1200x630 visual share card, defaulting to `wiki/graph/share-card.svg`
381
+ - `--json` emits the structured share artifact for automation; with `--svg`, it also includes `svgPath`
382
+ - useful immediately after `swarmvault scan`, `swarmvault demo`, or a normal compile
383
+
369
384
  ### `swarmvault graph blast <target> [--depth <n>]`
370
385
 
371
386
  Trace the reverse-import blast radius of changing a file or module.
package/dist/index.js CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { readFileSync } from "fs";
5
- import { readFile as readFile2 } from "fs/promises";
5
+ import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
6
+ import path2 from "path";
6
7
  import process2 from "process";
7
8
  import { createInterface } from "readline/promises";
8
9
  import {
@@ -14,6 +15,7 @@ import {
14
15
  autoCommitWikiChanges,
15
16
  benchmarkVault,
16
17
  blastRadiusVault,
18
+ buildGraphShareArtifact,
17
19
  compileVault,
18
20
  consolidateVault,
19
21
  createSupersessionEdge,
@@ -53,10 +55,13 @@ import {
53
55
  queryGraphVault,
54
56
  queryVault,
55
57
  readApproval,
58
+ readGraphReport,
56
59
  registerLocalWhisperProvider,
57
60
  rejectApproval,
58
61
  reloadManagedSources,
59
62
  removeWatchedRoot,
63
+ renderGraphShareMarkdown,
64
+ renderGraphShareSvg,
60
65
  resumeSourceSession,
61
66
  reviewManagedSource,
62
67
  reviewSourceScope,
@@ -287,9 +292,9 @@ program.name("swarmvault").description("SwarmVault is a local-first knowledge co
287
292
  function readCliVersion() {
288
293
  try {
289
294
  const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
290
- return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "1.1.0";
295
+ return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "1.3.0";
291
296
  } catch {
292
- return "1.1.0";
297
+ return "1.3.0";
293
298
  }
294
299
  }
295
300
  function parsePositiveInt(value, fallback) {
@@ -971,6 +976,36 @@ graph.command("export").description(
971
976
  }
972
977
  }
973
978
  );
979
+ graph.command("share").description("Print a shareable summary of the compiled graph.").option("--post", "Print only the short social post text", false).option("--svg [path]", "Write the visual SVG share card, defaulting to wiki/graph/share-card.svg").action(async (options) => {
980
+ if (options.post && options.svg) {
981
+ throw new Error("Choose either --post or --svg, not both.");
982
+ }
983
+ const { paths } = await loadVaultConfig(process2.cwd());
984
+ const raw = await readFile2(paths.graphPath, "utf-8");
985
+ const graph2 = JSON.parse(raw);
986
+ const report = await readGraphReport(process2.cwd());
987
+ const artifact = buildGraphShareArtifact({
988
+ graph: graph2,
989
+ report,
990
+ vaultName: path2.basename(paths.rootDir)
991
+ });
992
+ if (options.svg) {
993
+ const svgPath = typeof options.svg === "string" ? path2.resolve(process2.cwd(), options.svg) : path2.join(paths.wikiDir, "graph", "share-card.svg");
994
+ await mkdir2(path2.dirname(svgPath), { recursive: true });
995
+ await writeFile2(svgPath, renderGraphShareSvg(artifact), "utf8");
996
+ if (isJson()) {
997
+ emitJson({ ...artifact, svgPath });
998
+ return;
999
+ }
1000
+ log(`Wrote SVG share card to ${svgPath}`);
1001
+ return;
1002
+ }
1003
+ if (isJson()) {
1004
+ emitJson(artifact);
1005
+ return;
1006
+ }
1007
+ log(options.post ? artifact.shortPost : renderGraphShareMarkdown(artifact));
1008
+ });
974
1009
  graph.command("query").description("Traverse the compiled graph deterministically from local search seeds.").argument("<question>", "Question or graph search seed").option("--dfs", "Prefer a depth-first traversal instead of breadth-first", false).option("--budget <n>", "Maximum number of graph nodes to summarize").action(async (question, options) => {
975
1010
  const budget = options.budget ? parsePositiveInt(options.budget, 0) || void 0 : void 0;
976
1011
  const result = await queryGraphVault(process2.cwd(), question, {
@@ -1429,17 +1464,17 @@ program.command("install").description("Install SwarmVault instructions for an a
1429
1464
  }
1430
1465
  );
1431
1466
  program.command("demo").description("Try SwarmVault with a bundled sample vault \u2014 zero config, zero API keys.").option("--port <port>", "Port for the graph viewer").option("--no-serve", "Skip launching the graph viewer after compile").action(async (options) => {
1432
- const { mkdtemp, writeFile: writeFile2, mkdir: mkdir2 } = await import("fs/promises");
1467
+ const { mkdtemp, writeFile: writeFile3, mkdir: mkdir3 } = await import("fs/promises");
1433
1468
  const { tmpdir } = await import("os");
1434
- const path2 = await import("path");
1435
- const demoDir = await mkdtemp(path2.join(tmpdir(), "swarmvault-demo-"));
1469
+ const path3 = await import("path");
1470
+ const demoDir = await mkdtemp(path3.join(tmpdir(), "swarmvault-demo-"));
1436
1471
  if (!isJson()) {
1437
1472
  log(`Creating demo vault in ${demoDir}`);
1438
1473
  }
1439
- const rawDir = path2.join(demoDir, "raw", "sources");
1440
- await mkdir2(rawDir, { recursive: true });
1441
- await writeFile2(
1442
- path2.join(rawDir, "llm-wiki-pattern.md"),
1474
+ const rawDir = path3.join(demoDir, "raw", "sources");
1475
+ await mkdir3(rawDir, { recursive: true });
1476
+ await writeFile3(
1477
+ path3.join(rawDir, "llm-wiki-pattern.md"),
1443
1478
  [
1444
1479
  "# The LLM Wiki Pattern",
1445
1480
  "",
@@ -1467,8 +1502,8 @@ program.command("demo").description("Try SwarmVault with a bundled sample vault
1467
1502
  ""
1468
1503
  ].join("\n")
1469
1504
  );
1470
- await writeFile2(
1471
- path2.join(rawDir, "knowledge-graphs.md"),
1505
+ await writeFile3(
1506
+ path3.join(rawDir, "knowledge-graphs.md"),
1472
1507
  [
1473
1508
  "# Knowledge Graphs for AI",
1474
1509
  "",
@@ -1500,8 +1535,8 @@ program.command("demo").description("Try SwarmVault with a bundled sample vault
1500
1535
  ""
1501
1536
  ].join("\n")
1502
1537
  );
1503
- await writeFile2(
1504
- path2.join(rawDir, "local-first-tools.md"),
1538
+ await writeFile3(
1539
+ path3.join(rawDir, "local-first-tools.md"),
1505
1540
  [
1506
1541
  "# Local-First AI Tools",
1507
1542
  "",
@@ -1531,6 +1566,8 @@ program.command("demo").description("Try SwarmVault with a bundled sample vault
1531
1566
  await ingestDirectory(demoDir, rawDir, {});
1532
1567
  await compileVault(demoDir, {});
1533
1568
  const { paths } = await loadVaultConfig(demoDir);
1569
+ const shareCardPath = path3.join(demoDir, "wiki", "graph", "share-card.md");
1570
+ const shareCardSvgPath = path3.join(demoDir, "wiki", "graph", "share-card.svg");
1534
1571
  let graphStats = "";
1535
1572
  try {
1536
1573
  const raw = await readFile2(paths.graphPath, "utf-8");
@@ -1548,17 +1585,27 @@ program.command("demo").description("Try SwarmVault with a bundled sample vault
1548
1585
  log(" 3. Generated wiki pages with cross-references and a graph report");
1549
1586
  log("");
1550
1587
  log(`Vault location: ${demoDir}`);
1588
+ log(`Share card: ${shareCardPath}`);
1589
+ log(`Visual card: ${shareCardSvgPath}`);
1551
1590
  }
1552
1591
  if (options.serve !== false) {
1553
1592
  const port = options.port ? parsePositiveInt(options.port, 0) || void 0 : void 0;
1554
1593
  const server = await startGraphServer(demoDir, port, { full: false });
1555
1594
  if (isJson()) {
1556
- emitJson({ demoDir, graphStats: graphStats.trim(), port: server.port, url: `http://localhost:${server.port}` });
1595
+ emitJson({
1596
+ demoDir,
1597
+ graphStats: graphStats.trim(),
1598
+ shareCardPath,
1599
+ shareCardSvgPath,
1600
+ port: server.port,
1601
+ url: `http://localhost:${server.port}`
1602
+ });
1557
1603
  } else {
1558
1604
  log(`Graph viewer running at http://localhost:${server.port}`);
1559
1605
  log("");
1560
1606
  log("Try next:");
1561
1607
  log(` cd ${demoDir}`);
1608
+ log(" swarmvault graph share --post");
1562
1609
  log(' swarmvault query "How does contradiction detection work?"');
1563
1610
  log(" swarmvault lint");
1564
1611
  }
@@ -1570,11 +1617,12 @@ program.command("demo").description("Try SwarmVault with a bundled sample vault
1570
1617
  process2.exit(0);
1571
1618
  });
1572
1619
  } else if (isJson()) {
1573
- emitJson({ demoDir, graphStats: graphStats.trim() });
1620
+ emitJson({ demoDir, graphStats: graphStats.trim(), shareCardPath, shareCardSvgPath });
1574
1621
  } else {
1575
1622
  log("");
1576
1623
  log("Try next:");
1577
1624
  log(` cd ${demoDir}`);
1625
+ log(" swarmvault graph share --post");
1578
1626
  log(" swarmvault graph serve");
1579
1627
  log(' swarmvault query "How does contradiction detection work?"');
1580
1628
  }
@@ -1702,14 +1750,19 @@ program.command("scan").description("Quick-start: initialize, ingest, compile, a
1702
1750
  log(`Ingested ${result.imported.length} file(s).`);
1703
1751
  }
1704
1752
  const compiled = await compileVault(rootDir, {});
1753
+ const shareCardPath = path2.join(rootDir, "wiki", "graph", "share-card.md");
1754
+ const shareCardSvgPath = path2.join(rootDir, "wiki", "graph", "share-card.svg");
1705
1755
  if (!isJson()) {
1706
1756
  log(`Compiled ${compiled.sourceCount} source(s), ${compiled.pageCount} page(s).`);
1757
+ log(`Share card: ${shareCardPath}`);
1758
+ log(`Visual card: ${shareCardSvgPath}`);
1759
+ log("Post text: swarmvault graph share --post");
1707
1760
  }
1708
1761
  if (options.serve !== false) {
1709
1762
  const port = options.port ? parsePositiveInt(options.port, 0) || void 0 : void 0;
1710
1763
  const server = await startGraphServer(rootDir, port, { full: false });
1711
1764
  if (isJson()) {
1712
- emitJson({ ...result, compiled, port: server.port, url: `http://localhost:${server.port}` });
1765
+ emitJson({ ...result, compiled, shareCardPath, shareCardSvgPath, port: server.port, url: `http://localhost:${server.port}` });
1713
1766
  } else {
1714
1767
  log(`Graph viewer running at http://localhost:${server.port}`);
1715
1768
  }
@@ -1721,7 +1774,7 @@ program.command("scan").description("Quick-start: initialize, ingest, compile, a
1721
1774
  process2.exit(0);
1722
1775
  });
1723
1776
  } else if (isJson()) {
1724
- emitJson({ ...result, compiled });
1777
+ emitJson({ ...result, compiled, shareCardPath, shareCardSvgPath });
1725
1778
  }
1726
1779
  });
1727
1780
  function enableStructuredJsonOnSubcommands(command) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swarmvaultai/cli",
3
- "version": "1.1.0",
3
+ "version": "1.3.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": "1.1.0",
47
+ "@swarmvaultai/engine": "1.3.0",
48
48
  "commander": "^14.0.1"
49
49
  },
50
50
  "devDependencies": {