@swarmvaultai/cli 0.7.21 → 0.7.23
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 +30 -7
- package/dist/index.js +82 -25
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -72,6 +72,18 @@ The schema file is the vault-specific instruction layer. Edit it to define namin
|
|
|
72
72
|
|
|
73
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
|
+
### `swarmvault scan <directory> [--port <port>] [--no-serve]`
|
|
76
|
+
|
|
77
|
+
Quick-start a scratch vault from a local directory in one command.
|
|
78
|
+
|
|
79
|
+
- initializes the current directory as a SwarmVault workspace
|
|
80
|
+
- ingests the supplied directory as local sources
|
|
81
|
+
- compiles the vault immediately
|
|
82
|
+
- starts `graph serve` unless you pass `--no-serve`
|
|
83
|
+
- respects `--port` when you want a specific viewer port
|
|
84
|
+
|
|
85
|
+
Use this when you want the fastest repo or docs-tree walkthrough without first deciding on managed-source registration.
|
|
86
|
+
|
|
75
87
|
### `swarmvault source add|list|reload|review|guide|session|delete`
|
|
76
88
|
|
|
77
89
|
Manage recurring source roots through a registry-backed workflow.
|
|
@@ -244,12 +256,14 @@ Set `profile.deepLintDefault: true` when deep lint should be the default for `sw
|
|
|
244
256
|
|
|
245
257
|
`--conflicts` filters the results down to contradiction-focused findings so you can audit conflicting claims without the rest of the lint output.
|
|
246
258
|
|
|
247
|
-
### `swarmvault watch [--lint] [--repo] [--once] [--debounce <ms>]`
|
|
259
|
+
### `swarmvault watch [--lint] [--repo] [--once] [--code-only] [--debounce <ms>]`
|
|
248
260
|
|
|
249
|
-
Watch the inbox directory and trigger import and compile cycles when files change. With `--repo`, each cycle also refreshes tracked repo roots that were previously ingested through directory ingest. With `--once`, SwarmVault runs one refresh cycle immediately instead of starting a long-running watcher. With `--lint`, each cycle also runs linting. Each cycle writes a canonical session artifact to `state/sessions/`, and compatibility run metadata is still appended to `state/jobs.ndjson`.
|
|
261
|
+
Watch the inbox directory and trigger import and compile cycles when files change. With `--repo`, each cycle also refreshes tracked repo roots that were previously ingested through directory ingest. With `--once`, SwarmVault runs one refresh cycle immediately instead of starting a long-running watcher. With `--code-only`, SwarmVault forces the narrower AST-only refresh path and skips non-code semantic re-analysis until you run a normal `compile`. With `--lint`, each cycle also runs linting. Each cycle writes a canonical session artifact to `state/sessions/`, and compatibility run metadata is still appended to `state/jobs.ndjson`.
|
|
250
262
|
|
|
251
263
|
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.
|
|
252
264
|
|
|
265
|
+
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.
|
|
266
|
+
|
|
253
267
|
### `swarmvault watch status`
|
|
254
268
|
|
|
255
269
|
Show watched repo roots, the latest watch run, and any pending semantic refresh entries for tracked non-code repo changes.
|
|
@@ -262,7 +276,7 @@ Manage SwarmVault's local git hook blocks for the nearest git repository.
|
|
|
262
276
|
- `hook uninstall` removes only the SwarmVault-managed hook block
|
|
263
277
|
- `hook status` reports whether those managed hook blocks are installed
|
|
264
278
|
|
|
265
|
-
The installed hooks run `swarmvault watch --repo --once` from the vault root so
|
|
279
|
+
The installed hooks run `swarmvault watch --repo --once --code-only` from the vault root so commit and checkout refreshes update code pages and graph structure quickly. Run a normal `swarmvault compile` when you also want non-code semantic re-analysis.
|
|
266
280
|
|
|
267
281
|
### `swarmvault mcp`
|
|
268
282
|
|
|
@@ -299,14 +313,20 @@ Inspect graph metadata, community membership, neighbors, provenance, and group-p
|
|
|
299
313
|
|
|
300
314
|
List the most connected bridge-heavy nodes in the current graph.
|
|
301
315
|
|
|
302
|
-
### `swarmvault graph export --html|--svg|--graphml|--cypher <output>`
|
|
316
|
+
### `swarmvault graph export --html|--html-standalone|--svg|--graphml|--cypher|--json|--obsidian|--canvas <output>`
|
|
303
317
|
|
|
304
|
-
Export the current graph as one
|
|
318
|
+
Export the current graph as one or more shareable formats:
|
|
305
319
|
|
|
306
|
-
- `--html` for the
|
|
320
|
+
- `--html` for the full self-contained read-only graph workspace
|
|
321
|
+
- `--html-standalone` for a lighter vis.js export with node search, legend, and sidebar inspection
|
|
307
322
|
- `--svg` for a static shareable diagram
|
|
308
323
|
- `--graphml` for graph-tool interoperability
|
|
309
324
|
- `--cypher` for Neo4j-style import scripts
|
|
325
|
+
- `--json` for a deterministic machine-readable graph package
|
|
326
|
+
- `--obsidian` for an Obsidian-friendly markdown vault with one note per node plus community notes
|
|
327
|
+
- `--canvas` for an Obsidian canvas grouped by community
|
|
328
|
+
|
|
329
|
+
You can combine multiple flags in one run to write several exports at once.
|
|
310
330
|
|
|
311
331
|
### `swarmvault graph push neo4j`
|
|
312
332
|
|
|
@@ -331,7 +351,7 @@ Defaults:
|
|
|
331
351
|
- namespaces every remote record by `vaultId` so multiple vaults can safely share one Neo4j database
|
|
332
352
|
- upserts current graph records and does not prune stale remote data yet
|
|
333
353
|
|
|
334
|
-
### `swarmvault install --agent <codex|claude|cursor|goose|pi|gemini|opencode|aider|copilot>`
|
|
354
|
+
### `swarmvault install --agent <codex|claude|cursor|goose|pi|gemini|opencode|aider|copilot|trae|claw|droid>`
|
|
335
355
|
|
|
336
356
|
Install agent-specific rules into the current project so an agent understands the SwarmVault workspace contract and workflow.
|
|
337
357
|
|
|
@@ -352,6 +372,9 @@ Agent target mapping:
|
|
|
352
372
|
- `aider` writes `CONVENTIONS.md` and merges `.aider.conf.yml`
|
|
353
373
|
- `copilot` writes `.github/copilot-instructions.md` plus `AGENTS.md`
|
|
354
374
|
- `cursor` writes `.cursor/rules/swarmvault.mdc`
|
|
375
|
+
- `trae` writes `.trae/rules/swarmvault.md`
|
|
376
|
+
- `claw` writes `.claw/skills/swarmvault/SKILL.md`
|
|
377
|
+
- `droid` writes `.factory/rules/swarmvault.md`
|
|
355
378
|
|
|
356
379
|
Hook semantics:
|
|
357
380
|
|
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.
|
|
273
|
+
return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "0.7.23";
|
|
272
274
|
} catch {
|
|
273
|
-
return "0.7.
|
|
275
|
+
return "0.7.23";
|
|
274
276
|
}
|
|
275
277
|
}
|
|
276
278
|
function parsePositiveInt(value, fallback) {
|
|
@@ -812,29 +814,49 @@ graph.command("serve").description("Serve the local graph viewer.").option("--po
|
|
|
812
814
|
process2.exit(0);
|
|
813
815
|
});
|
|
814
816
|
});
|
|
815
|
-
graph.command("export").description(
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
for (const
|
|
834
|
-
|
|
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
|
+
}
|
|
835
857
|
}
|
|
836
858
|
}
|
|
837
|
-
|
|
859
|
+
);
|
|
838
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) => {
|
|
839
861
|
const budget = options.budget ? parsePositiveInt(options.budget, 0) || void 0 : void 0;
|
|
840
862
|
const result = await queryGraphVault(process2.cwd(), question, {
|
|
@@ -959,12 +981,13 @@ candidate.command("archive").description("Archive a candidate by removing it fro
|
|
|
959
981
|
log(`Archived ${result.pageId}`);
|
|
960
982
|
}
|
|
961
983
|
});
|
|
962
|
-
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("--debounce <ms>", "Debounce window in milliseconds", "900").action(async (options) => {
|
|
984
|
+
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").action(async (options) => {
|
|
963
985
|
const debounceMs = parsePositiveInt(options.debounce, 900);
|
|
964
986
|
if (options.once) {
|
|
965
987
|
const result = await runWatchCycle(process2.cwd(), {
|
|
966
988
|
lint: options.lint ?? false,
|
|
967
989
|
repo: options.repo ?? false,
|
|
990
|
+
codeOnly: options.codeOnly ?? false,
|
|
968
991
|
debounceMs
|
|
969
992
|
});
|
|
970
993
|
if (isJson()) {
|
|
@@ -980,6 +1003,7 @@ var watch = program.command("watch").description("Watch the inbox directory and
|
|
|
980
1003
|
const controller = await watchVault(process2.cwd(), {
|
|
981
1004
|
lint: options.lint ?? false,
|
|
982
1005
|
repo: options.repo ?? false,
|
|
1006
|
+
codeOnly: options.codeOnly ?? false,
|
|
983
1007
|
debounceMs
|
|
984
1008
|
});
|
|
985
1009
|
if (isJson()) {
|
|
@@ -1097,7 +1121,7 @@ program.command("mcp").description("Run SwarmVault as a local MCP server over st
|
|
|
1097
1121
|
process2.exit(0);
|
|
1098
1122
|
});
|
|
1099
1123
|
});
|
|
1100
|
-
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
|
|
1124
|
+
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(
|
|
1101
1125
|
async (options) => {
|
|
1102
1126
|
const hookCapableAgents = /* @__PURE__ */ new Set(["claude", "opencode", "gemini", "copilot"]);
|
|
1103
1127
|
if (options.hook && !hookCapableAgents.has(options.agent)) {
|
|
@@ -1117,6 +1141,39 @@ program.command("install").description("Install SwarmVault instructions for an a
|
|
|
1117
1141
|
}
|
|
1118
1142
|
}
|
|
1119
1143
|
);
|
|
1144
|
+
program.command("scan").description("Quick-start: initialize, ingest, compile, and serve a graph viewer in one command.").argument("<directory>", "Directory to scan").option("--port <port>", "Port for the graph viewer").option("--no-serve", "Skip launching the graph viewer after compile").action(async (directory, options) => {
|
|
1145
|
+
const rootDir = process2.cwd();
|
|
1146
|
+
await initVault(rootDir, {});
|
|
1147
|
+
if (!isJson()) {
|
|
1148
|
+
log("Initialized workspace.");
|
|
1149
|
+
}
|
|
1150
|
+
const result = await ingestDirectory(rootDir, directory, {});
|
|
1151
|
+
if (!isJson()) {
|
|
1152
|
+
log(`Ingested ${result.imported.length} file(s).`);
|
|
1153
|
+
}
|
|
1154
|
+
const compiled = await compileVault(rootDir, {});
|
|
1155
|
+
if (!isJson()) {
|
|
1156
|
+
log(`Compiled ${compiled.sourceCount} source(s), ${compiled.pageCount} page(s).`);
|
|
1157
|
+
}
|
|
1158
|
+
if (options.serve !== false) {
|
|
1159
|
+
const port = options.port ? parsePositiveInt(options.port, 0) || void 0 : void 0;
|
|
1160
|
+
const server = await startGraphServer(rootDir, port, { full: false });
|
|
1161
|
+
if (isJson()) {
|
|
1162
|
+
emitJson({ ...result, compiled, port: server.port, url: `http://localhost:${server.port}` });
|
|
1163
|
+
} else {
|
|
1164
|
+
log(`Graph viewer running at http://localhost:${server.port}`);
|
|
1165
|
+
}
|
|
1166
|
+
process2.on("SIGINT", async () => {
|
|
1167
|
+
try {
|
|
1168
|
+
await server.close();
|
|
1169
|
+
} catch {
|
|
1170
|
+
}
|
|
1171
|
+
process2.exit(0);
|
|
1172
|
+
});
|
|
1173
|
+
} else if (isJson()) {
|
|
1174
|
+
emitJson({ ...result, compiled });
|
|
1175
|
+
}
|
|
1176
|
+
});
|
|
1120
1177
|
program.parseAsync(process2.argv).catch((error) => {
|
|
1121
1178
|
const message = error instanceof Error ? error.message : String(error);
|
|
1122
1179
|
if (isJson()) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swarmvaultai/cli",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.23",
|
|
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.
|
|
41
|
+
"@swarmvaultai/engine": "0.7.23",
|
|
42
42
|
"commander": "^14.0.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|