@swarmvaultai/cli 3.11.0 → 3.13.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 +66 -53
- package/dist/index.js +171 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -29,67 +29,45 @@ 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
|
|
36
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
swarmvault
|
|
44
|
-
swarmvault
|
|
45
|
-
|
|
46
|
-
swarmvault
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
After the first compile, use:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
swarmvault query "What are the key concepts?"
|
|
52
|
+
swarmvault graph serve
|
|
53
|
+
swarmvault doctor
|
|
54
|
+
swarmvault candidate list
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Use the step-by-step flow when you want more control:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
swarmvault init --obsidian --profile personal-research
|
|
61
|
+
swarmvault ingest ./src --repo-root .
|
|
62
|
+
swarmvault ingest ./meeting.srt --guide
|
|
51
63
|
swarmvault add https://arxiv.org/abs/2401.12345
|
|
52
|
-
swarmvault compile
|
|
53
|
-
swarmvault
|
|
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 context build "Ship this feature safely" --target ./src --budget 8000
|
|
60
|
-
swarmvault task start "Ship this feature safely" --target ./src --agent codex
|
|
61
|
-
swarmvault retrieval status
|
|
62
|
-
swarmvault doctor --repair
|
|
63
|
-
swarmvault query "Turn this into slides" --format slides
|
|
64
|
-
swarmvault explore "What should I research next?" --steps 3
|
|
65
|
-
swarmvault lint --deep
|
|
66
|
-
swarmvault graph blast ./src/index.ts
|
|
67
|
-
swarmvault graph status ./src
|
|
68
|
-
swarmvault check-update ./src
|
|
69
|
-
swarmvault graph stats
|
|
70
|
-
swarmvault graph validate --strict
|
|
71
|
-
swarmvault graph update .
|
|
72
|
-
swarmvault update .
|
|
73
|
-
swarmvault graph cluster
|
|
74
|
-
swarmvault cluster-only
|
|
75
|
-
swarmvault graph tree --output ./exports/tree.html
|
|
76
|
-
swarmvault tree --output ./exports/tree.html
|
|
77
|
-
swarmvault graph query "Which nodes bridge the biggest clusters?"
|
|
78
|
-
swarmvault graph explain "concept:drift"
|
|
79
|
-
swarmvault watch status
|
|
80
|
-
swarmvault watch --repo --once
|
|
81
|
-
swarmvault hook install
|
|
64
|
+
swarmvault compile
|
|
65
|
+
swarmvault query "What is the auth flow?"
|
|
82
66
|
swarmvault graph serve
|
|
83
|
-
swarmvault graph export --report ./exports/report.html
|
|
84
|
-
swarmvault graph export --html ./exports/graph.html
|
|
85
|
-
swarmvault graph export --cypher ./exports/graph.cypher
|
|
86
|
-
swarmvault graph export --neo4j ./exports/graph.cypher
|
|
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
|
|
89
|
-
swarmvault graph push neo4j --dry-run
|
|
90
|
-
swarmvault clone https://github.com/owner/repo --no-viz
|
|
91
67
|
```
|
|
92
68
|
|
|
69
|
+
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`.
|
|
70
|
+
|
|
93
71
|
## Commands
|
|
94
72
|
|
|
95
73
|
### `swarmvault init [--obsidian] [--profile <alias-or-presets>]`
|
|
@@ -113,6 +91,19 @@ Set `SWARMVAULT_OUT=<dir>` when generated artifacts should be isolated from the
|
|
|
113
91
|
|
|
114
92
|
`--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`.
|
|
115
93
|
|
|
94
|
+
### `swarmvault quickstart <directory|github-url> [--port <port>] [--no-serve] [--no-viz] [--mcp] [--branch <name>] [--ref <ref>] [--checkout-dir <path>]`
|
|
95
|
+
|
|
96
|
+
Beginner-friendly alias for `swarmvault scan`.
|
|
97
|
+
|
|
98
|
+
- initializes the current directory as a SwarmVault workspace
|
|
99
|
+
- ingests the supplied local directory, or registers/syncs the supplied public GitHub repo root URL
|
|
100
|
+
- compiles wiki, graph, search, and share artifacts immediately
|
|
101
|
+
- prints the generated `raw/`, `wiki/`, `state/graph.json`, and `wiki/graph/` paths in human output
|
|
102
|
+
- starts `graph serve` unless you pass `--no-serve` or `--no-viz`
|
|
103
|
+
- keeps the same JSON output contract as `scan`
|
|
104
|
+
|
|
105
|
+
Use this as the default first-run command in docs and onboarding.
|
|
106
|
+
|
|
116
107
|
### `swarmvault scan <directory|github-url> [--port <port>] [--no-serve] [--no-viz] [--mcp] [--branch <name>] [--ref <ref>] [--checkout-dir <path>]`
|
|
117
108
|
|
|
118
109
|
Quick-start a scratch vault from a local directory or public GitHub repo root URL in one command.
|
|
@@ -155,6 +146,28 @@ Compare the current `state/graph.json` against the last committed graph in git.
|
|
|
155
146
|
- when no git baseline exists, falls back to a summary of the current graph state
|
|
156
147
|
- supports `--json` for structured automation output
|
|
157
148
|
|
|
149
|
+
### `swarmvault chat [question...] [--resume [id]] [--list] [--delete <id>]`
|
|
150
|
+
|
|
151
|
+
Ask the compiled wiki in a persisted multi-turn session.
|
|
152
|
+
|
|
153
|
+
- without a question, opens an interactive TTY chat loop with `/help`, `/sessions`, `/status`, `/clear`, and `/exit`
|
|
154
|
+
- with a question, runs one turn and persists the transcript under `wiki/outputs/chat-sessions/`
|
|
155
|
+
- stores structured session state under `state/chat-sessions/`
|
|
156
|
+
- `--resume <id>` resumes by id or unique prefix; `--resume` alone resumes the most recent session
|
|
157
|
+
- `--list` prints saved sessions and `--delete <id>` removes one
|
|
158
|
+
- `--save-output` also writes each turn as a regular `wiki/outputs/` query page
|
|
159
|
+
- supports `--format markdown|report|slides|chart|image`, `--gap-fill`, and global `--json`
|
|
160
|
+
|
|
161
|
+
### `swarmvault export ai [--out <dir>] [--max-full-chars <n>] [--no-page-siblings]`
|
|
162
|
+
|
|
163
|
+
Write a static AI handoff pack for agents, crawlers, and documentation systems.
|
|
164
|
+
|
|
165
|
+
- defaults to `wiki/exports/ai/`
|
|
166
|
+
- writes `llms.txt`, `llms-full.txt`, `graph.jsonld`, `manifest.json`, and `ai-readme.md`
|
|
167
|
+
- writes per-page `.txt` and `.json` siblings under `pages/` unless `--no-page-siblings` is passed
|
|
168
|
+
- caps `llms-full.txt` with `--max-full-chars` so huge vaults stay bounded
|
|
169
|
+
- includes SHA-256 hashes and file metadata in `manifest.json`
|
|
170
|
+
|
|
158
171
|
### `swarmvault doctor [--repair]`
|
|
159
172
|
|
|
160
173
|
Run a whole-vault health check before handing the workspace to an agent or opening the live viewer.
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
addManagedSource,
|
|
13
13
|
addWatchedRoot,
|
|
14
14
|
archiveCandidate,
|
|
15
|
+
askChatSession,
|
|
15
16
|
autoCommitWikiChanges,
|
|
16
17
|
benchmarkVault,
|
|
17
18
|
blastRadiusVault,
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
compileVault,
|
|
21
22
|
consolidateVault,
|
|
22
23
|
createSupersessionEdge,
|
|
24
|
+
deleteChatSession,
|
|
23
25
|
deleteContextPack,
|
|
24
26
|
deleteManagedSource,
|
|
25
27
|
doctorRetrieval,
|
|
@@ -27,6 +29,7 @@ import {
|
|
|
27
29
|
downloadWhisperModel,
|
|
28
30
|
explainGraphVault,
|
|
29
31
|
exploreVault,
|
|
32
|
+
exportAiPack,
|
|
30
33
|
exportGraphFormat,
|
|
31
34
|
exportGraphHtml,
|
|
32
35
|
exportGraphReportHtml,
|
|
@@ -51,6 +54,7 @@ import {
|
|
|
51
54
|
lintVault,
|
|
52
55
|
listApprovals,
|
|
53
56
|
listCandidates,
|
|
57
|
+
listChatSessions,
|
|
54
58
|
listContextPacks,
|
|
55
59
|
listGodNodes,
|
|
56
60
|
listManagedSourceRecords,
|
|
@@ -315,9 +319,9 @@ program.name("swarmvault").description("SwarmVault is a local-first knowledge co
|
|
|
315
319
|
function readCliVersion() {
|
|
316
320
|
try {
|
|
317
321
|
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.
|
|
322
|
+
return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "3.13.0";
|
|
319
323
|
} catch {
|
|
320
|
-
return "3.
|
|
324
|
+
return "3.13.0";
|
|
321
325
|
}
|
|
322
326
|
}
|
|
323
327
|
function parsePositiveInt(value, fallback) {
|
|
@@ -604,10 +608,19 @@ async function runScanCommand(input, options) {
|
|
|
604
608
|
const shareKitPath = path2.join(paths.wikiDir, "graph", "share-kit");
|
|
605
609
|
if (!isJson()) {
|
|
606
610
|
log(`Compiled ${compiled.sourceCount} source(s), ${compiled.pageCount} page(s).`);
|
|
611
|
+
log(`Vault workspace: ${rootDir}`);
|
|
612
|
+
log(`Raw sources: ${paths.rawDir}`);
|
|
613
|
+
log(`Wiki output: ${paths.wikiDir}`);
|
|
614
|
+
log(`Graph JSON: ${paths.graphPath}`);
|
|
607
615
|
log(`Share card: ${shareCardPath}`);
|
|
608
616
|
log(`Visual card: ${shareCardSvgPath}`);
|
|
609
617
|
log(`Share kit: ${shareKitPath}`);
|
|
610
|
-
log("
|
|
618
|
+
log("");
|
|
619
|
+
log("Next steps:");
|
|
620
|
+
log(' swarmvault query "What are the key concepts?"');
|
|
621
|
+
log(" swarmvault graph serve");
|
|
622
|
+
log(" swarmvault doctor");
|
|
623
|
+
log(" swarmvault candidate list");
|
|
611
624
|
}
|
|
612
625
|
if (options.mcp) {
|
|
613
626
|
process2.stderr.write(`${JSON.stringify({ status: "running", transport: "stdio", compiled: compiled.sourceCount })}
|
|
@@ -649,6 +662,105 @@ async function runScanCommand(input, options) {
|
|
|
649
662
|
emitJson({ ...result, compiled, shareCardPath, shareCardSvgPath, shareKitPath });
|
|
650
663
|
}
|
|
651
664
|
}
|
|
665
|
+
async function resolveChatResumeId(resume) {
|
|
666
|
+
if (!resume) {
|
|
667
|
+
return void 0;
|
|
668
|
+
}
|
|
669
|
+
if (typeof resume === "string") {
|
|
670
|
+
return resume;
|
|
671
|
+
}
|
|
672
|
+
const sessions = await listChatSessions(process2.cwd());
|
|
673
|
+
return sessions[0]?.id;
|
|
674
|
+
}
|
|
675
|
+
function logChatSessions(sessions) {
|
|
676
|
+
if (!sessions.length) {
|
|
677
|
+
log("No chat sessions yet.");
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
for (const session of sessions) {
|
|
681
|
+
log(`${session.id} ${session.turnCount} turn${session.turnCount === 1 ? "" : "s"} ${session.title}`);
|
|
682
|
+
log(` updated: ${session.updatedAt}`);
|
|
683
|
+
log(` markdown: ${session.markdownPath}`);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
async function runChatQuestion(question, options) {
|
|
687
|
+
const sessionId = await resolveChatResumeId(options.resume);
|
|
688
|
+
return askChatSession(process2.cwd(), {
|
|
689
|
+
question,
|
|
690
|
+
sessionId,
|
|
691
|
+
saveOutput: options.saveOutput ?? false,
|
|
692
|
+
gapFill: options.gapFill ?? false,
|
|
693
|
+
format: options.format,
|
|
694
|
+
maxHistoryTurns: parsePositiveInt(options.maxHistoryTurns, 6)
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
async function runInteractiveChat(options) {
|
|
698
|
+
if (isJson()) {
|
|
699
|
+
throw new Error("Interactive chat is not available with --json. Pass a question for one-shot JSON output.");
|
|
700
|
+
}
|
|
701
|
+
if (!process2.stdin.isTTY) {
|
|
702
|
+
throw new Error("Pass a chat question, or run `swarmvault chat` in an interactive terminal.");
|
|
703
|
+
}
|
|
704
|
+
let sessionId = await resolveChatResumeId(options.resume);
|
|
705
|
+
log(sessionId ? `Resuming chat session ${sessionId}.` : "Starting a new chat session.");
|
|
706
|
+
log("Type /help for commands or /exit to quit.");
|
|
707
|
+
const reader = createInterface({ input: process2.stdin, output: process2.stdout });
|
|
708
|
+
try {
|
|
709
|
+
while (true) {
|
|
710
|
+
const input = (await reader.question("swarmvault> ")).trim();
|
|
711
|
+
if (!input) {
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
if (input === "/exit" || input === "/quit") {
|
|
715
|
+
break;
|
|
716
|
+
}
|
|
717
|
+
if (input === "/help") {
|
|
718
|
+
log(
|
|
719
|
+
[
|
|
720
|
+
"/help Show commands",
|
|
721
|
+
"/sessions List chat sessions",
|
|
722
|
+
"/status Show vault health summary",
|
|
723
|
+
"/clear Start a fresh session",
|
|
724
|
+
"/exit Quit"
|
|
725
|
+
].join("\n")
|
|
726
|
+
);
|
|
727
|
+
continue;
|
|
728
|
+
}
|
|
729
|
+
if (input === "/sessions") {
|
|
730
|
+
logChatSessions(await listChatSessions(process2.cwd()));
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
if (input === "/status") {
|
|
734
|
+
const report = await doctorVault(process2.cwd(), {});
|
|
735
|
+
log(`Vault health: ${report.ok ? "ok" : "needs attention"} (${report.recommendations.length} recommendation(s))`);
|
|
736
|
+
for (const recommendation of report.recommendations.slice(0, 5)) {
|
|
737
|
+
log(`- ${recommendation.label}: ${recommendation.command ?? recommendation.summary}`);
|
|
738
|
+
}
|
|
739
|
+
continue;
|
|
740
|
+
}
|
|
741
|
+
if (input === "/clear") {
|
|
742
|
+
sessionId = void 0;
|
|
743
|
+
log("Started a fresh chat session.");
|
|
744
|
+
continue;
|
|
745
|
+
}
|
|
746
|
+
const result = await askChatSession(process2.cwd(), {
|
|
747
|
+
question: input,
|
|
748
|
+
sessionId,
|
|
749
|
+
saveOutput: options.saveOutput ?? false,
|
|
750
|
+
gapFill: options.gapFill ?? false,
|
|
751
|
+
format: options.format,
|
|
752
|
+
maxHistoryTurns: parsePositiveInt(options.maxHistoryTurns, 6)
|
|
753
|
+
});
|
|
754
|
+
sessionId = result.session.id;
|
|
755
|
+
log(result.answer);
|
|
756
|
+
log(`Session: ${result.session.id}`);
|
|
757
|
+
log(`Saved transcript: ${result.markdownPath}`);
|
|
758
|
+
await maybeEmitHeuristicNotice(["chat"]);
|
|
759
|
+
}
|
|
760
|
+
} finally {
|
|
761
|
+
reader.close();
|
|
762
|
+
}
|
|
763
|
+
}
|
|
652
764
|
program.hook("postAction", async (_thisCommand, actionCommand) => {
|
|
653
765
|
const notices = await collectCliNotices({
|
|
654
766
|
commandPath: getCommandPath(actionCommand),
|
|
@@ -659,6 +771,7 @@ program.hook("postAction", async (_thisCommand, actionCommand) => {
|
|
|
659
771
|
emitNotice(notice);
|
|
660
772
|
}
|
|
661
773
|
});
|
|
774
|
+
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);
|
|
662
775
|
program.command("init").description("Initialize a SwarmVault workspace in the current directory.").option("--obsidian", "Generate a minimal .obsidian workspace alongside the vault", false).option(
|
|
663
776
|
"--profile <profile>",
|
|
664
777
|
"Starter workspace profile or comma-separated preset list (for example: personal-research or reader,timeline)"
|
|
@@ -1027,6 +1140,44 @@ program.command("query").description("Query the compiled SwarmVault wiki.").argu
|
|
|
1027
1140
|
await maybeEmitHeuristicNotice(["query"]);
|
|
1028
1141
|
}
|
|
1029
1142
|
);
|
|
1143
|
+
program.command("chat").description("Ask the compiled wiki in a persisted multi-turn chat session.").argument("[question...]", "Question to ask in a chat session").option("--resume [id]", "Resume a chat session by id/prefix, or the most recent session when no id is supplied").option("--list", "List saved chat sessions", false).option("--delete <id>", "Delete a saved chat session by id/prefix").option("--save-output", "Also persist each answer as a regular wiki/outputs query page", false).option("--gap-fill", "Pull external web-search evidence when the local wiki has gaps (requires webSearch.tasks.queryProvider).").option("--max-history-turns <n>", "Number of prior turns to include as conversational context", "6").addOption(
|
|
1144
|
+
new Option("--format <format>", "Answer format for generated turns").choices(["markdown", "report", "slides", "chart", "image"]).default("markdown")
|
|
1145
|
+
).action(
|
|
1146
|
+
async (questionParts, options) => {
|
|
1147
|
+
if (options.list) {
|
|
1148
|
+
const sessions = await listChatSessions(process2.cwd());
|
|
1149
|
+
if (isJson()) {
|
|
1150
|
+
emitJson(sessions);
|
|
1151
|
+
} else {
|
|
1152
|
+
logChatSessions(sessions);
|
|
1153
|
+
}
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
if (options.delete) {
|
|
1157
|
+
const deleted = await deleteChatSession(process2.cwd(), options.delete);
|
|
1158
|
+
if (isJson()) {
|
|
1159
|
+
emitJson(deleted);
|
|
1160
|
+
} else {
|
|
1161
|
+
log(`Deleted chat session ${deleted.id}`);
|
|
1162
|
+
}
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
const question = (questionParts ?? []).join(" ").trim();
|
|
1166
|
+
if (!question) {
|
|
1167
|
+
await runInteractiveChat(options);
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
const result = await runChatQuestion(question, options);
|
|
1171
|
+
if (isJson()) {
|
|
1172
|
+
emitJson(result);
|
|
1173
|
+
} else {
|
|
1174
|
+
log(result.answer);
|
|
1175
|
+
log(`Session: ${result.session.id}`);
|
|
1176
|
+
log(`Saved transcript: ${result.markdownPath}`);
|
|
1177
|
+
}
|
|
1178
|
+
await maybeEmitHeuristicNotice(["chat"]);
|
|
1179
|
+
}
|
|
1180
|
+
);
|
|
1030
1181
|
var context = program.command("context").description("Build and manage token-bounded agent context packs.");
|
|
1031
1182
|
context.command("build").description("Build a cited, token-bounded context pack for an agent task.").argument("<goal>", "Task, question, or goal the agent needs context for").option("--target <target>", "Optional page, node, path, project, or label to anchor the pack").option("--budget <tokens>", "Approximate token budget for included context", String(8e3)).option("--task <id>", "Attach the context pack to an agent task").option("--memory <id>", "Compatibility alias for --task").addOption(new Option("--format <format>", "Output format").choices(["markdown", "json", "llms"]).default("markdown")).action(
|
|
1032
1183
|
async (goal, options) => {
|
|
@@ -1294,6 +1445,23 @@ program.command("benchmark").description("Measure graph-guided context reduction
|
|
|
1294
1445
|
}
|
|
1295
1446
|
}
|
|
1296
1447
|
});
|
|
1448
|
+
var exportCommand = program.command("export").description("Export portable SwarmVault artifacts.");
|
|
1449
|
+
exportCommand.command("ai").description("Export static AI handoff files for agents, crawlers, and documentation systems.").option("--out <dir>", "Output directory", path2.join("wiki", "exports", "ai")).option("--max-full-chars <n>", "Maximum characters to include in llms-full.txt", "5000000").option("--no-page-siblings", "Skip per-page .txt and .json sibling files").action(async (options) => {
|
|
1450
|
+
const result = await exportAiPack(process2.cwd(), {
|
|
1451
|
+
outDir: options.out,
|
|
1452
|
+
maxFullChars: parsePositiveInt(options.maxFullChars, 5e6),
|
|
1453
|
+
pageSiblings: options.pageSiblings ?? true
|
|
1454
|
+
});
|
|
1455
|
+
if (isJson()) {
|
|
1456
|
+
emitJson(result);
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
log(`Exported AI handoff pack to ${result.outputDir}`);
|
|
1460
|
+
log(`Files: ${result.files.length}; pages: ${result.pageCount}; nodes: ${result.nodeCount}; edges: ${result.edgeCount}`);
|
|
1461
|
+
if (result.truncatedFullText) {
|
|
1462
|
+
log("llms-full.txt was truncated; rerun with --max-full-chars for a larger export.");
|
|
1463
|
+
}
|
|
1464
|
+
});
|
|
1297
1465
|
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).option("--decay", "Filter to decay-related findings only", false).option("--tiers", "Filter to consolidation-tier findings only", false).action(async (options) => {
|
|
1298
1466
|
const lintConfig = await loadVaultConfig(process2.cwd()).catch(() => null);
|
|
1299
1467
|
const deepEnabled = options.decay || options.tiers ? false : options.deep ?? lintConfig?.config.profile.deepLintDefault ?? false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swarmvaultai/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.13.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.13.0",
|
|
48
48
|
"commander": "^14.0.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|