@swarmvaultai/cli 0.7.2 → 0.7.22

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 +20 -7
  2. package/dist/index.js +50 -26
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -70,7 +70,7 @@ Create a workspace with:
70
70
 
71
71
  The schema file is the vault-specific instruction layer. Edit it to define naming rules, categories, grounding expectations, and exclusions before a serious compile.
72
72
 
73
- `--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` starter profile also sets `profile.guidedIngestDefault: true`, so guided ingest/source flows are on by default until you override them with `--no-guide`.
73
+ `--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` starter profile 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`.
74
74
 
75
75
  ### `swarmvault source add|list|reload|review|guide|session|delete`
76
76
 
@@ -225,7 +225,7 @@ Each step:
225
225
 
226
226
  The command also writes a hub page linking the root question, saved step pages, and generated follow-up questions.
227
227
 
228
- ### `swarmvault lint [--deep] [--web] [--conflicts]`
228
+ ### `swarmvault lint [--deep] [--no-deep] [--web] [--conflicts]`
229
229
 
230
230
  Run anti-drift and vault health checks such as stale pages, missing graph artifacts, contradiction findings, and other structural issues.
231
231
 
@@ -238,7 +238,9 @@ Run anti-drift and vault health checks such as stale pages, missing graph artifa
238
238
  - `candidate_page`
239
239
  - `follow_up_question`
240
240
 
241
- `--web` can only be used with `--deep`. It enriches deep-lint findings with external evidence snippets and URLs from a configured web-search provider.
241
+ Set `profile.deepLintDefault: true` when deep lint should be the default for `swarmvault lint`, and use `--no-deep` when one run should stay structural only.
242
+
243
+ `--web` can only be used when deep lint is enabled, either explicitly with `--deep` or through `profile.deepLintDefault`. It enriches deep-lint findings with external evidence snippets and URLs from a configured web-search provider.
242
244
 
243
245
  `--conflicts` filters the results down to contradiction-focused findings so you can audit conflicting claims without the rest of the lint output.
244
246
 
@@ -248,6 +250,8 @@ Watch the inbox directory and trigger import and compile cycles when files chang
248
250
 
249
251
  When `--repo` sees non-code changes under tracked repo roots, SwarmVault records those files under `state/watch/pending-semantic-refresh.json`, marks affected compiled pages stale, and exposes the pending set through `watch status` and the local graph workspace instead of silently re-ingesting them.
250
252
 
253
+ When `--repo` sees only code-file changes under tracked repo roots, SwarmVault takes the faster code-only path: it refreshes code pages and graph structure without re-running non-code semantic analysis for unchanged sources.
254
+
251
255
  ### `swarmvault watch status`
252
256
 
253
257
  Show watched repo roots, the latest watch run, and any pending semantic refresh entries for tracked non-code repo changes.
@@ -297,14 +301,20 @@ Inspect graph metadata, community membership, neighbors, provenance, and group-p
297
301
 
298
302
  List the most connected bridge-heavy nodes in the current graph.
299
303
 
300
- ### `swarmvault graph export --html|--svg|--graphml|--cypher <output>`
304
+ ### `swarmvault graph export --html|--html-standalone|--svg|--graphml|--cypher|--json|--obsidian|--canvas <output>`
301
305
 
302
- Export the current graph as one of four formats:
306
+ Export the current graph as one or more shareable formats:
303
307
 
304
- - `--html` for the standalone read-only graph workspace
308
+ - `--html` for the full self-contained read-only graph workspace
309
+ - `--html-standalone` for a lighter vis.js export with node search, legend, and sidebar inspection
305
310
  - `--svg` for a static shareable diagram
306
311
  - `--graphml` for graph-tool interoperability
307
312
  - `--cypher` for Neo4j-style import scripts
313
+ - `--json` for a deterministic machine-readable graph package
314
+ - `--obsidian` for an Obsidian-friendly markdown vault with one note per node plus community notes
315
+ - `--canvas` for an Obsidian canvas grouped by community
316
+
317
+ You can combine multiple flags in one run to write several exports at once.
308
318
 
309
319
  ### `swarmvault graph push neo4j`
310
320
 
@@ -329,7 +339,7 @@ Defaults:
329
339
  - namespaces every remote record by `vaultId` so multiple vaults can safely share one Neo4j database
330
340
  - upserts current graph records and does not prune stale remote data yet
331
341
 
332
- ### `swarmvault install --agent <codex|claude|cursor|goose|pi|gemini|opencode|aider|copilot>`
342
+ ### `swarmvault install --agent <codex|claude|cursor|goose|pi|gemini|opencode|aider|copilot|trae|claw|droid>`
333
343
 
334
344
  Install agent-specific rules into the current project so an agent understands the SwarmVault workspace contract and workflow.
335
345
 
@@ -350,6 +360,9 @@ Agent target mapping:
350
360
  - `aider` writes `CONVENTIONS.md` and merges `.aider.conf.yml`
351
361
  - `copilot` writes `.github/copilot-instructions.md` plus `AGENTS.md`
352
362
  - `cursor` writes `.cursor/rules/swarmvault.mdc`
363
+ - `trae` writes `.trae/rules/swarmvault.md`
364
+ - `claw` writes `.claw/skills/swarmvault/SKILL.md`
365
+ - `droid` writes `.factory/rules/swarmvault.md`
353
366
 
354
367
  Hook semantics:
355
368
 
package/dist/index.js CHANGED
@@ -16,6 +16,8 @@ import {
16
16
  exploreVault,
17
17
  exportGraphFormat,
18
18
  exportGraphHtml,
19
+ exportObsidianCanvas,
20
+ exportObsidianVault,
19
21
  getGitHookStatus,
20
22
  getWatchStatus,
21
23
  guideManagedSource,
@@ -268,9 +270,9 @@ program.name("swarmvault").description("SwarmVault is a local-first knowledge co
268
270
  function readCliVersion() {
269
271
  try {
270
272
  const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
271
- return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "0.7.2";
273
+ return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "0.7.22";
272
274
  } catch {
273
- return "0.7.2";
275
+ return "0.7.22";
274
276
  }
275
277
  }
276
278
  function parsePositiveInt(value, fallback) {
@@ -738,9 +740,11 @@ program.command("benchmark").description("Measure graph-guided context reduction
738
740
  }
739
741
  }
740
742
  });
741
- program.command("lint").description("Run anti-drift and wiki-health checks.").option("--deep", "Run LLM-powered advisory lint", false).option("--web", "Augment deep lint with configured web search", false).option("--conflicts", "Filter to contradiction findings only", false).action(async (options) => {
743
+ program.command("lint").description("Run anti-drift and wiki-health checks.").option("--deep", "Run LLM-powered advisory lint (default: from config)").option("--no-deep", "Skip deep lint even if enabled in config").option("--web", "Augment deep lint with configured web search", false).option("--conflicts", "Filter to contradiction findings only", false).action(async (options) => {
744
+ const lintConfig = await loadVaultConfig(process2.cwd()).catch(() => null);
745
+ const deepEnabled = options.deep ?? lintConfig?.config.profile.deepLintDefault ?? false;
742
746
  const findings = await lintVault(process2.cwd(), {
743
- deep: options.deep ?? false,
747
+ deep: deepEnabled,
744
748
  web: options.web ?? false,
745
749
  conflicts: options.conflicts ?? false
746
750
  });
@@ -810,29 +814,49 @@ graph.command("serve").description("Serve the local graph viewer.").option("--po
810
814
  process2.exit(0);
811
815
  });
812
816
  });
813
- graph.command("export").description("Export the graph as HTML, SVG, GraphML, or Cypher. Combine flags to write multiple formats in one run.").option("--html <output>", "Output HTML file path").option("--svg <output>", "Output SVG file path").option("--graphml <output>", "Output GraphML file path").option("--cypher <output>", "Output Cypher file path").option("--full", "Disable overview sampling for HTML export", false).action(async (options) => {
814
- const targets = [
815
- options.html ? { format: "html", outputPath: options.html } : null,
816
- options.svg ? { format: "svg", outputPath: options.svg } : null,
817
- options.graphml ? { format: "graphml", outputPath: options.graphml } : null,
818
- options.cypher ? { format: "cypher", outputPath: options.cypher } : null
819
- ].filter((target) => Boolean(target));
820
- if (targets.length === 0) {
821
- throw new Error("Pass at least one of --html, --svg, --graphml, or --cypher.");
822
- }
823
- const results = [];
824
- for (const target of targets) {
825
- const outputPath = target.format === "html" ? await exportGraphHtml(process2.cwd(), target.outputPath, { full: options.full ?? false }) : (await exportGraphFormat(process2.cwd(), target.format, target.outputPath)).outputPath;
826
- results.push({ format: target.format, outputPath });
827
- }
828
- if (isJson()) {
829
- emitJson(results.length === 1 ? results[0] : { exports: results });
830
- } else {
831
- for (const result of results) {
832
- log(`Exported graph ${result.format} to ${result.outputPath}`);
817
+ graph.command("export").description(
818
+ "Export the graph as HTML, SVG, GraphML, Cypher, JSON, Obsidian vault, or Obsidian canvas. Combine flags to write multiple formats in one run."
819
+ ).option("--html <output>", "Output HTML file path").option("--html-standalone <output>", "Output lightweight standalone HTML file path (vis.js, no build tooling)").option("--svg <output>", "Output SVG file path").option("--graphml <output>", "Output GraphML file path").option("--cypher <output>", "Output Cypher file path").option("--json <output>", "Output JSON file path").option("--obsidian <output>", "Output Obsidian vault directory path").option("--canvas <output>", "Output Obsidian canvas file path").option("--full", "Disable overview sampling for HTML export", false).action(
820
+ async (options) => {
821
+ const targets = [
822
+ options.html ? { format: "html", outputPath: options.html } : null,
823
+ options.htmlStandalone ? { format: "html-standalone", outputPath: options.htmlStandalone } : null,
824
+ options.svg ? { format: "svg", outputPath: options.svg } : null,
825
+ options.graphml ? { format: "graphml", outputPath: options.graphml } : null,
826
+ options.cypher ? { format: "cypher", outputPath: options.cypher } : null,
827
+ options.json ? { format: "json", outputPath: options.json } : null,
828
+ options.obsidian ? { format: "obsidian", outputPath: options.obsidian } : null,
829
+ options.canvas ? { format: "canvas", outputPath: options.canvas } : null
830
+ ].filter((target) => Boolean(target));
831
+ if (targets.length === 0) {
832
+ throw new Error("Pass at least one of --html, --html-standalone, --svg, --graphml, --cypher, --json, --obsidian, or --canvas.");
833
+ }
834
+ const results = [];
835
+ for (const target of targets) {
836
+ if (target.format === "html") {
837
+ const outputPath = await exportGraphHtml(process2.cwd(), target.outputPath, { full: options.full ?? false });
838
+ results.push({ format: target.format, outputPath });
839
+ } else if (target.format === "obsidian") {
840
+ const result = await exportObsidianVault(process2.cwd(), target.outputPath);
841
+ results.push({ format: result.format, outputPath: result.outputPath, fileCount: result.fileCount });
842
+ } else if (target.format === "canvas") {
843
+ const result = await exportObsidianCanvas(process2.cwd(), target.outputPath);
844
+ results.push({ format: result.format, outputPath: result.outputPath });
845
+ } else {
846
+ const result = await exportGraphFormat(process2.cwd(), target.format, target.outputPath);
847
+ results.push({ format: result.format, outputPath: result.outputPath });
848
+ }
849
+ }
850
+ if (isJson()) {
851
+ emitJson(results.length === 1 ? results[0] : { exports: results });
852
+ } else {
853
+ for (const result of results) {
854
+ const suffix = result.fileCount ? ` (${result.fileCount} files)` : "";
855
+ log(`Exported graph ${result.format} to ${result.outputPath}${suffix}`);
856
+ }
833
857
  }
834
858
  }
835
- });
859
+ );
836
860
  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) => {
837
861
  const budget = options.budget ? parsePositiveInt(options.budget, 0) || void 0 : void 0;
838
862
  const result = await queryGraphVault(process2.cwd(), question, {
@@ -1095,7 +1119,7 @@ program.command("mcp").description("Run SwarmVault as a local MCP server over st
1095
1119
  process2.exit(0);
1096
1120
  });
1097
1121
  });
1098
- program.command("install").description("Install SwarmVault instructions for an agent in the current project.").requiredOption("--agent <agent>", "codex, claude, cursor, goose, pi, gemini, opencode, aider, or copilot").option("--hook", "Also install hook/plugin guidance when the target agent supports it", false).action(
1122
+ program.command("install").description("Install SwarmVault instructions for an agent in the current project.").requiredOption("--agent <agent>", "codex, claude, cursor, goose, pi, gemini, opencode, aider, copilot, trae, claw, or droid").option("--hook", "Also install hook/plugin guidance when the target agent supports it", false).action(
1099
1123
  async (options) => {
1100
1124
  const hookCapableAgents = /* @__PURE__ */ new Set(["claude", "opencode", "gemini", "copilot"]);
1101
1125
  if (options.hook && !hookCapableAgents.has(options.agent)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swarmvaultai/cli",
3
- "version": "0.7.2",
3
+ "version": "0.7.22",
4
4
  "description": "Global CLI for SwarmVault.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -38,7 +38,7 @@
38
38
  "node": ">=24.0.0"
39
39
  },
40
40
  "dependencies": {
41
- "@swarmvaultai/engine": "0.7.2",
41
+ "@swarmvaultai/engine": "0.7.22",
42
42
  "commander": "^14.0.1"
43
43
  },
44
44
  "devDependencies": {