@fenglimg/fabric-cli 1.6.0 → 1.8.0-rc.1

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 (45) hide show
  1. package/README.md +8 -14
  2. package/dist/{chunk-QSAEGVKE.js → chunk-NMMUETVK.js} +4 -8
  3. package/dist/{chunk-AEOYCVBG.js → chunk-QPCRBQ5Y.js} +52 -5
  4. package/dist/doctor-F52XWWZC.js +98 -0
  5. package/dist/index.js +5 -20
  6. package/dist/{init-LBVOI2QI.js → init-AEO5JU7R.js} +1084 -167
  7. package/dist/{scan-QH76LC7Z.js → scan-NNBNGIZG.js} +2 -4
  8. package/dist/{serve-4J2CQY25.js → serve-466QXQ5Q.js} +17 -9
  9. package/package.json +5 -7
  10. package/templates/agents-md/AGENTS.md.template +7 -7
  11. package/templates/agents-md/variants/cocos.md +7 -7
  12. package/templates/agents-md/variants/next.md +7 -7
  13. package/templates/agents-md/variants/vite.md +7 -7
  14. package/templates/bootstrap/CLAUDE.md +3 -1
  15. package/templates/bootstrap/GEMINI.md +3 -1
  16. package/templates/bootstrap/codex-AGENTS-header.md +3 -1
  17. package/templates/bootstrap/cursor-fabric-bootstrap.mdc +5 -6
  18. package/templates/bootstrap/roo-fabric.md +5 -6
  19. package/templates/bootstrap/windsurf-fabric.md +5 -6
  20. package/templates/claude-skills/fabric-init/SKILL.md +163 -0
  21. package/templates/codex-skills/fabric-init/SKILL.md +153 -18
  22. package/templates/husky/pre-commit +9 -24
  23. package/templates/skill-source/fabric-init/SOURCE.md +157 -0
  24. package/templates/skill-source/fabric-init/clients.json +17 -0
  25. package/dist/approve-YT4DEABS.js +0 -138
  26. package/dist/bootstrap-VGL3AR26.js +0 -16
  27. package/dist/chunk-2YW5CJ32.js +0 -147
  28. package/dist/chunk-6ICJICVU.js +0 -10
  29. package/dist/chunk-BEKSXO5N.js +0 -442
  30. package/dist/chunk-BVTMVW5M.js +0 -159
  31. package/dist/chunk-KOAEIH72.js +0 -270
  32. package/dist/chunk-L43IGJ6X.js +0 -106
  33. package/dist/chunk-T2WJF5I3.js +0 -254
  34. package/dist/chunk-WWNXR34K.js +0 -49
  35. package/dist/chunk-YDZJRLHL.js +0 -155
  36. package/dist/config-EC5L2QNI.js +0 -16
  37. package/dist/doctor-4BPYHV7V.js +0 -134
  38. package/dist/hooks-ZSWVH2JD.js +0 -12
  39. package/dist/human-lint-YSFOZHZ7.js +0 -13
  40. package/dist/ledger-append-3MDNR3GU.js +0 -10
  41. package/dist/pre-commit-53ENJDRZ.js +0 -98
  42. package/dist/sync-meta-IZR2WLIL.js +0 -16
  43. package/dist/update-M5M5PYKE.js +0 -116
  44. package/templates/claude-skills/agents-md-init/SKILL.md +0 -86
  45. package/templates/fabric/human-lock.json +0 -12
@@ -1,442 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/config/resolver.ts
4
- import { existsSync as existsSync4 } from "fs";
5
- import { join as join4 } from "path";
6
- import { homedir as homedir4 } from "os";
7
-
8
- // src/config/claude-code.ts
9
- import { existsSync as existsSync2 } from "fs";
10
- import { join as join2, resolve as resolve2 } from "path";
11
- import { homedir as homedir2, platform } from "os";
12
-
13
- // src/config/json.ts
14
- import { existsSync } from "fs";
15
- import { mkdir, readFile, writeFile } from "fs/promises";
16
- import { dirname, join, resolve } from "path";
17
- import { homedir } from "os";
18
-
19
- // src/config/writer.ts
20
- function createServerEntry(serverPath) {
21
- return {
22
- command: process.execPath,
23
- args: [serverPath]
24
- };
25
- }
26
-
27
- // src/config/json.ts
28
- function expandHome(filePath) {
29
- if (filePath === "~") {
30
- return homedir();
31
- }
32
- if (filePath.startsWith("~/")) {
33
- return join(homedir(), filePath.slice(2));
34
- }
35
- return filePath;
36
- }
37
- function normalizeConfigPath(filePath) {
38
- return resolve(expandHome(filePath));
39
- }
40
- async function readJsonConfig(configPath) {
41
- try {
42
- const raw = await readFile(configPath, "utf8");
43
- if (raw.trim().length === 0) {
44
- return {};
45
- }
46
- const parsed = JSON.parse(raw);
47
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
48
- throw new Error(`Expected JSON object in ${configPath}`);
49
- }
50
- return parsed;
51
- } catch (error) {
52
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
53
- return {};
54
- }
55
- throw error;
56
- }
57
- }
58
- async function writeJsonClientConfig(configPath, serverEntry) {
59
- const config = await readJsonConfig(configPath);
60
- const existingServers = config.mcpServers;
61
- config.mcpServers = existingServers !== null && typeof existingServers === "object" && !Array.isArray(existingServers) ? { ...existingServers, fabric: serverEntry } : { fabric: serverEntry };
62
- await mkdir(dirname(configPath), { recursive: true });
63
- await writeFile(configPath, `${JSON.stringify(config, null, 2)}
64
- `, "utf8");
65
- }
66
- var JsonClientConfigWriter = class {
67
- configuredPath;
68
- constructor(configuredPath) {
69
- this.configuredPath = configuredPath;
70
- }
71
- async detect(workspaceRoot, overridePath) {
72
- const explicitPath = overridePath ?? this.configuredPath;
73
- if (explicitPath !== void 0) {
74
- return normalizeConfigPath(explicitPath);
75
- }
76
- const configPath = this.defaultPath(workspaceRoot);
77
- return configPath === null ? null : normalizeConfigPath(configPath);
78
- }
79
- async write(serverPath, workspaceRoot, overridePath) {
80
- const configPath = await this.detect(workspaceRoot, overridePath);
81
- if (configPath === null) {
82
- return;
83
- }
84
- await writeJsonClientConfig(configPath, createServerEntry(serverPath));
85
- }
86
- };
87
- var ClaudeCodeCLIWriter = class extends JsonClientConfigWriter {
88
- clientKind = "ClaudeCodeCLI";
89
- constructor(configuredPath) {
90
- super(configuredPath);
91
- }
92
- // Writes to project-level .claude/settings.json so MCP is scoped to the project.
93
- // Detection in resolver still checks ~/ to confirm Claude Code is installed.
94
- defaultPath(workspaceRoot) {
95
- const globalClaudeDir = join(homedir(), ".claude");
96
- const projectClaudeDir = join(workspaceRoot, ".claude");
97
- if (!existsSync(globalClaudeDir) && !existsSync(projectClaudeDir)) {
98
- return null;
99
- }
100
- return join(projectClaudeDir, "settings.json");
101
- }
102
- };
103
- var CursorWriter = class extends JsonClientConfigWriter {
104
- clientKind = "Cursor";
105
- constructor(configuredPath) {
106
- super(configuredPath);
107
- }
108
- defaultPath(workspaceRoot) {
109
- const cursorDir = join(workspaceRoot, ".cursor");
110
- return existsSync(cursorDir) ? join(cursorDir, "mcp.json") : null;
111
- }
112
- };
113
- var WindsurfWriter = class extends JsonClientConfigWriter {
114
- clientKind = "Windsurf";
115
- constructor(configuredPath) {
116
- super(configuredPath);
117
- }
118
- defaultPath(workspaceRoot) {
119
- const windsurfDir = join(workspaceRoot, ".windsurf");
120
- return existsSync(windsurfDir) ? join(windsurfDir, "mcp.json") : null;
121
- }
122
- };
123
- var RooCodeWriter = class extends JsonClientConfigWriter {
124
- clientKind = "RooCode";
125
- constructor(configuredPath) {
126
- super(configuredPath);
127
- }
128
- defaultPath(workspaceRoot) {
129
- const rooDir = join(workspaceRoot, ".roo");
130
- return existsSync(rooDir) ? join(rooDir, "mcp.json") : null;
131
- }
132
- };
133
- var GeminiCLIWriter = class extends JsonClientConfigWriter {
134
- clientKind = "GeminiCLI";
135
- constructor(configuredPath) {
136
- super(configuredPath);
137
- }
138
- defaultPath(workspaceRoot) {
139
- const geminiDir = join(homedir(), ".gemini");
140
- return existsSync(geminiDir) || existsSync(join(workspaceRoot, "GEMINI.md")) ? join(geminiDir, "settings.json") : null;
141
- }
142
- };
143
-
144
- // src/config/claude-code.ts
145
- function getClaudeDesktopConfigPath() {
146
- const os = platform();
147
- if (os === "darwin") {
148
- return join2(homedir2(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
149
- }
150
- if (os === "win32") {
151
- return join2(process.env.APPDATA ?? join2(homedir2(), "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
152
- }
153
- return join2(homedir2(), ".config", "Claude", "claude_desktop_config.json");
154
- }
155
- var ClaudeCodeDesktopWriter = class {
156
- clientKind = "ClaudeCodeDesktop";
157
- configuredPath;
158
- constructor(configuredPath) {
159
- this.configuredPath = configuredPath;
160
- }
161
- async detect(_workspaceRoot, overridePath) {
162
- const configPath = normalizeConfigPath(overridePath ?? this.configuredPath ?? getClaudeDesktopConfigPath());
163
- return existsSync2(configPath) || overridePath !== void 0 || this.configuredPath !== void 0 ? configPath : null;
164
- }
165
- async write(serverPath, workspaceRoot, overridePath) {
166
- const configPath = await this.detect(workspaceRoot, overridePath);
167
- if (configPath === null) {
168
- return;
169
- }
170
- await writeJsonClientConfig(configPath, {
171
- command: process.execPath,
172
- args: [serverPath]
173
- });
174
- }
175
- };
176
-
177
- // src/config/toml.ts
178
- import { existsSync as existsSync3 } from "fs";
179
- import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
180
- import { dirname as dirname2, join as join3, resolve as resolve3 } from "path";
181
- import { homedir as homedir3 } from "os";
182
- function expandHome2(filePath) {
183
- if (filePath === "~") {
184
- return homedir3();
185
- }
186
- if (filePath.startsWith("~/")) {
187
- return join3(homedir3(), filePath.slice(2));
188
- }
189
- return filePath;
190
- }
191
- function escapeTomlString(value) {
192
- return JSON.stringify(value);
193
- }
194
- function serializeTomlStringArray(values) {
195
- return `[${values.map((value) => escapeTomlString(value)).join(", ")}]`;
196
- }
197
- function serializeTomlInlineTable(values) {
198
- const entries = Object.entries(values).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `${key} = ${escapeTomlString(value)}`);
199
- return `{ ${entries.join(", ")} }`;
200
- }
201
- function serializeCodexServerBlock(serverName, serverEntry) {
202
- const lines = [
203
- `[mcp_servers.${serverName}]`,
204
- `command = ${escapeTomlString(serverEntry.command)}`,
205
- `args = ${serializeTomlStringArray(serverEntry.args)}`
206
- ];
207
- if (serverEntry.env !== void 0 && Object.keys(serverEntry.env).length > 0) {
208
- lines.push(`env = ${serializeTomlInlineTable(serverEntry.env)}`);
209
- }
210
- return `${lines.join("\n")}
211
- `;
212
- }
213
- function trimTrailingBlankLines(value) {
214
- return value.replace(/\s+$/u, "");
215
- }
216
- function upsertCodexServerBlock(rawConfig, serverName, serverEntry) {
217
- const block = serializeCodexServerBlock(serverName, serverEntry);
218
- const normalized = rawConfig.replace(/\r\n/g, "\n");
219
- const legacyPattern = new RegExp(String.raw`\n?\[mcp\.servers\.${serverName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\]\n[\s\S]*?(?=\n\[[^\n]+\]\n|$)`, "g");
220
- const currentPattern = new RegExp(
221
- String.raw`\n?\[mcp_servers\.${serverName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\]\n[\s\S]*?(?=\n\[[^\n]+\]\n|$)`,
222
- "g"
223
- );
224
- const withoutLegacy = normalized.replace(legacyPattern, "");
225
- const withoutExisting = withoutLegacy.replace(currentPattern, "");
226
- const trimmed = trimTrailingBlankLines(withoutExisting);
227
- if (trimmed.length === 0) {
228
- return block;
229
- }
230
- return `${trimmed}
231
-
232
- ${block}`;
233
- }
234
- async function readTomlConfigText(configPath) {
235
- try {
236
- return await readFile2(configPath, "utf8");
237
- } catch (error) {
238
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
239
- return "";
240
- }
241
- throw error;
242
- }
243
- }
244
- var CodexTOMLConfigWriter = class {
245
- clientKind = "CodexCLI";
246
- configuredPath;
247
- constructor(configuredPath) {
248
- this.configuredPath = configuredPath;
249
- }
250
- async detect(_workspaceRoot, overridePath) {
251
- const explicitPath = overridePath ?? this.configuredPath;
252
- if (explicitPath !== void 0) {
253
- return resolve3(expandHome2(explicitPath));
254
- }
255
- const codexDir = join3(homedir3(), ".codex");
256
- return existsSync3(codexDir) ? resolve3(join3(codexDir, "config.toml")) : null;
257
- }
258
- async write(serverPath, workspaceRoot, overridePath) {
259
- const configPath = await this.detect(workspaceRoot, overridePath);
260
- if (configPath === null) {
261
- return;
262
- }
263
- const rawConfig = await readTomlConfigText(configPath);
264
- const nextConfig = upsertCodexServerBlock(rawConfig, "fabric", createServerEntry(serverPath));
265
- await mkdir2(dirname2(configPath), { recursive: true });
266
- await writeFile2(configPath, nextConfig, "utf8");
267
- }
268
- };
269
-
270
- // src/config/resolver.ts
271
- import { clientPathsSchema, fabricConfigSchema } from "@fenglimg/fabric-shared";
272
- function hasExplicitPath(clientPaths, key) {
273
- return typeof clientPaths?.[key] === "string" && clientPaths[key].trim().length > 0;
274
- }
275
- function addIfDetected(writers, detected, createWriter, configuredPath) {
276
- if (configuredPath !== void 0 || detected) {
277
- writers.push(createWriter(configuredPath));
278
- }
279
- }
280
- function resolveClients(workspaceRoot, fabricConfig = {}) {
281
- const clientPaths = fabricConfig.clientPaths;
282
- const writers = [];
283
- addIfDetected(
284
- writers,
285
- existsSync4(join4(homedir4(), ".claude")) || existsSync4(join4(workspaceRoot, ".claude")),
286
- (configuredPath) => new ClaudeCodeCLIWriter(configuredPath),
287
- hasExplicitPath(clientPaths, "claudeCodeCLI") ? clientPaths.claudeCodeCLI : void 0
288
- );
289
- addIfDetected(
290
- writers,
291
- existsSync4(getClaudeDesktopConfigPath()),
292
- (configuredPath) => new ClaudeCodeDesktopWriter(configuredPath),
293
- hasExplicitPath(clientPaths, "claudeCodeDesktop") ? clientPaths.claudeCodeDesktop : void 0
294
- );
295
- addIfDetected(
296
- writers,
297
- existsSync4(join4(workspaceRoot, ".cursor")),
298
- (configuredPath) => new CursorWriter(configuredPath),
299
- hasExplicitPath(clientPaths, "cursor") ? clientPaths.cursor : void 0
300
- );
301
- addIfDetected(
302
- writers,
303
- existsSync4(join4(workspaceRoot, ".windsurf")),
304
- (configuredPath) => new WindsurfWriter(configuredPath),
305
- hasExplicitPath(clientPaths, "windsurf") ? clientPaths.windsurf : void 0
306
- );
307
- addIfDetected(
308
- writers,
309
- existsSync4(join4(workspaceRoot, ".roo")),
310
- (configuredPath) => new RooCodeWriter(configuredPath),
311
- hasExplicitPath(clientPaths, "rooCode") ? clientPaths.rooCode : void 0
312
- );
313
- addIfDetected(
314
- writers,
315
- existsSync4(join4(homedir4(), ".gemini")) || existsSync4(join4(workspaceRoot, "GEMINI.md")),
316
- (configuredPath) => new GeminiCLIWriter(configuredPath),
317
- hasExplicitPath(clientPaths, "geminiCLI") ? clientPaths.geminiCLI : void 0
318
- );
319
- addIfDetected(
320
- writers,
321
- existsSync4(join4(homedir4(), ".codex")),
322
- (configuredPath) => new CodexTOMLConfigWriter(configuredPath),
323
- hasExplicitPath(clientPaths, "codexCLI") ? clientPaths.codexCLI : void 0
324
- );
325
- return writers;
326
- }
327
- function detectClientSupports(workspaceRoot, fabricConfig = {}) {
328
- const clientPaths = fabricConfig.clientPaths;
329
- const claudeDetected = existsSync4(join4(homedir4(), ".claude")) || existsSync4(join4(workspaceRoot, ".claude"));
330
- const claudeDesktopDetected = existsSync4(getClaudeDesktopConfigPath());
331
- const cursorDetected = existsSync4(join4(workspaceRoot, ".cursor"));
332
- const windsurfDetected = existsSync4(join4(workspaceRoot, ".windsurf"));
333
- const rooDetected = existsSync4(join4(workspaceRoot, ".roo"));
334
- const geminiDetected = existsSync4(join4(homedir4(), ".gemini")) || existsSync4(join4(workspaceRoot, "GEMINI.md"));
335
- const codexDetected = existsSync4(join4(homedir4(), ".codex"));
336
- return [
337
- {
338
- clientKind: "ClaudeCodeCLI",
339
- label: "Claude Code CLI",
340
- detected: claudeDetected || hasExplicitPath(clientPaths, "claudeCodeCLI"),
341
- bootstrapTargetPath: ".fabric/bootstrap/README.md",
342
- configPath: "project .claude/settings.json",
343
- capabilities: {
344
- bootstrap: true,
345
- mcp: true,
346
- hook: true,
347
- skill: true
348
- },
349
- installedCapabilities: {
350
- hook: true,
351
- skill: true
352
- }
353
- },
354
- {
355
- clientKind: "ClaudeCodeDesktop",
356
- label: "Claude Code Desktop",
357
- detected: claudeDesktopDetected || hasExplicitPath(clientPaths, "claudeCodeDesktop"),
358
- bootstrapTargetPath: ".fabric/bootstrap/README.md",
359
- configPath: "desktop Claude config",
360
- capabilities: {
361
- bootstrap: true,
362
- mcp: true,
363
- hook: false,
364
- skill: false
365
- }
366
- },
367
- {
368
- clientKind: "Cursor",
369
- label: "Cursor",
370
- detected: cursorDetected || hasExplicitPath(clientPaths, "cursor"),
371
- bootstrapTargetPath: ".fabric/bootstrap/README.md",
372
- configPath: ".cursor/mcp.json",
373
- capabilities: {
374
- bootstrap: true,
375
- mcp: true,
376
- hook: false,
377
- skill: false
378
- }
379
- },
380
- {
381
- clientKind: "Windsurf",
382
- label: "Windsurf",
383
- detected: windsurfDetected || hasExplicitPath(clientPaths, "windsurf"),
384
- bootstrapTargetPath: ".fabric/bootstrap/README.md",
385
- configPath: ".windsurf/mcp.json",
386
- capabilities: {
387
- bootstrap: true,
388
- mcp: true,
389
- hook: false,
390
- skill: false
391
- }
392
- },
393
- {
394
- clientKind: "RooCode",
395
- label: "Roo Code",
396
- detected: rooDetected || hasExplicitPath(clientPaths, "rooCode"),
397
- bootstrapTargetPath: ".fabric/bootstrap/README.md",
398
- configPath: ".roo/mcp.json",
399
- capabilities: {
400
- bootstrap: true,
401
- mcp: true,
402
- hook: false,
403
- skill: false
404
- }
405
- },
406
- {
407
- clientKind: "GeminiCLI",
408
- label: "Gemini CLI",
409
- detected: geminiDetected || hasExplicitPath(clientPaths, "geminiCLI"),
410
- bootstrapTargetPath: ".fabric/bootstrap/README.md",
411
- configPath: "~/.gemini/settings.json",
412
- capabilities: {
413
- bootstrap: true,
414
- mcp: true,
415
- hook: false,
416
- skill: false
417
- }
418
- },
419
- {
420
- clientKind: "CodexCLI",
421
- label: "Codex CLI",
422
- detected: codexDetected || hasExplicitPath(clientPaths, "codexCLI"),
423
- bootstrapTargetPath: ".fabric/bootstrap/README.md",
424
- configPath: "~/.codex/config.toml",
425
- capabilities: {
426
- bootstrap: true,
427
- mcp: true,
428
- hook: true,
429
- skill: true
430
- },
431
- installedCapabilities: {
432
- hook: existsSync4(join4(workspaceRoot, ".codex", "hooks.json")),
433
- skill: existsSync4(join4(workspaceRoot, ".agents", "skills", "fabric-init", "SKILL.md"))
434
- }
435
- }
436
- ];
437
- }
438
-
439
- export {
440
- resolveClients,
441
- detectClientSupports
442
- };
@@ -1,159 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- resolveClients
4
- } from "./chunk-BEKSXO5N.js";
5
- import {
6
- hooksCommand
7
- } from "./chunk-YDZJRLHL.js";
8
- import {
9
- t
10
- } from "./chunk-6ICJICVU.js";
11
-
12
- // src/commands/config.ts
13
- import { existsSync } from "fs";
14
- import { readFile } from "fs/promises";
15
- import { resolve } from "path";
16
- import { fileURLToPath } from "url";
17
- import { defineCommand } from "citty";
18
- var CLIENT_ALIASES = {
19
- claude: "ClaudeCodeCLI",
20
- claudecodecli: "ClaudeCodeCLI",
21
- "claude-code-cli": "ClaudeCodeCLI",
22
- claudecli: "ClaudeCodeCLI",
23
- claudecodedesktop: "ClaudeCodeDesktop",
24
- "claude-code-desktop": "ClaudeCodeDesktop",
25
- claudedesktop: "ClaudeCodeDesktop",
26
- cursor: "Cursor",
27
- windsurf: "Windsurf",
28
- roocode: "RooCode",
29
- "roo-code": "RooCode",
30
- roo: "RooCode",
31
- geminicli: "GeminiCLI",
32
- "gemini-cli": "GeminiCLI",
33
- gemini: "GeminiCLI",
34
- codexcli: "CodexCLI",
35
- "codex-cli": "CodexCLI",
36
- codex: "CodexCLI"
37
- };
38
- function parseClientFilter(value) {
39
- if (value === void 0 || value.trim().length === 0) {
40
- return null;
41
- }
42
- const clients = /* @__PURE__ */ new Set();
43
- for (const rawClient of value.split(",")) {
44
- const alias = rawClient.trim().toLowerCase();
45
- const clientKind = CLIENT_ALIASES[alias];
46
- if (clientKind === void 0) {
47
- throw new Error(t("cli.config.errors.unknown-client", { client: rawClient }));
48
- }
49
- clients.add(clientKind);
50
- }
51
- return clients;
52
- }
53
- async function loadFabricConfig(workspaceRoot) {
54
- const configPath = resolve(workspaceRoot, "fabric.config.json");
55
- if (!existsSync(configPath)) {
56
- return {};
57
- }
58
- const parsed = JSON.parse(await readFile(configPath, "utf8"));
59
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
60
- throw new Error(t("cli.config.errors.expected-object", { path: configPath }));
61
- }
62
- return parsed;
63
- }
64
- function resolveServerPath(override) {
65
- if (override) return override;
66
- if (process.env.FAB_SERVER_PATH) return resolve(process.env.FAB_SERVER_PATH);
67
- return fileURLToPath(import.meta.resolve("@fenglimg/fabric-server"));
68
- }
69
- function writeStderr(message) {
70
- process.stderr.write(`${message}
71
- `);
72
- }
73
- var configCmd = defineCommand({
74
- meta: {
75
- name: "config",
76
- description: t("cli.config.description")
77
- },
78
- subCommands: {
79
- hooks: hooksCommand,
80
- install: defineCommand({
81
- meta: {
82
- name: "install",
83
- description: t("cli.config.install.description")
84
- },
85
- args: {
86
- clients: {
87
- type: "string",
88
- description: t("cli.config.install.args.clients.description")
89
- },
90
- "dry-run": {
91
- type: "boolean",
92
- description: t("cli.config.install.args.dry-run.description"),
93
- default: false
94
- }
95
- },
96
- async run({ args }) {
97
- const selectedClients = parseClientFilter(args.clients);
98
- const result = await installMcpClients(process.cwd(), {
99
- clients: selectedClients === null ? void 0 : Array.from(selectedClients),
100
- dryRun: args["dry-run"]
101
- });
102
- if (result.details.length === 0) {
103
- writeStderr(t("cli.config.install.no-configs"));
104
- return;
105
- }
106
- for (const detail of result.details) {
107
- if (detail.action === "skipped") {
108
- writeStderr(t("cli.config.install.no-config-path", { client: detail.client }));
109
- continue;
110
- }
111
- if (detail.action === "dry-run" && detail.path !== null) {
112
- writeStderr(t("cli.config.install.dry-run", { client: detail.client, path: detail.path }));
113
- continue;
114
- }
115
- if (detail.path !== null) {
116
- writeStderr(t("cli.config.install.wrote", { client: detail.client, path: detail.path }));
117
- }
118
- }
119
- }
120
- })
121
- }
122
- });
123
- var config_default = configCmd;
124
- async function installMcpClients(target, options = {}) {
125
- const workspaceRoot = resolve(target);
126
- const fabricConfig = await loadFabricConfig(workspaceRoot);
127
- const selectedClients = options.clients === void 0 ? null : new Set(options.clients);
128
- const serverPath = resolveServerPath(options.localServerPath);
129
- const writers = resolveClients(workspaceRoot, fabricConfig).filter(
130
- (writer) => selectedClients === null ? true : selectedClients.has(writer.clientKind)
131
- );
132
- const installed = [];
133
- const skipped = [];
134
- const details = [];
135
- for (const writer of writers) {
136
- const configPath = await writer.detect(workspaceRoot);
137
- if (configPath === null) {
138
- skipped.push(writer.clientKind);
139
- details.push({ client: writer.clientKind, path: null, action: "skipped" });
140
- continue;
141
- }
142
- if (options.dryRun) {
143
- skipped.push(writer.clientKind);
144
- details.push({ client: writer.clientKind, path: configPath, action: "dry-run" });
145
- continue;
146
- }
147
- await writer.write(serverPath, workspaceRoot);
148
- installed.push(writer.clientKind);
149
- details.push({ client: writer.clientKind, path: configPath, action: "wrote" });
150
- }
151
- return { installed, skipped, details };
152
- }
153
-
154
- export {
155
- parseClientFilter,
156
- configCmd,
157
- config_default,
158
- installMcpClients
159
- };