@snapback/cli 1.1.12 → 1.1.15
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 +79 -18
- package/dist/SkippedTestDetector-AXTMWWHC.js +5 -0
- package/dist/SkippedTestDetector-QLSQV7K7.js +5 -0
- package/dist/analysis-6WTBZJH3.js +6 -0
- package/dist/analysis-C472LUGW.js +2475 -0
- package/dist/auth-HFJRXXG2.js +1446 -0
- package/dist/auto-provision-organization-SF6XM7X4.js +161 -0
- package/dist/chunk-23G5VYA3.js +4259 -0
- package/dist/{chunk-QAKFE3NE.js → chunk-4YTE4JEW.js} +3 -4
- package/dist/chunk-5EOPYJ4Y.js +12 -0
- package/dist/{chunk-G7QXHNGB.js → chunk-5SQA44V7.js} +1125 -32
- package/dist/{chunk-BW7RALUZ.js → chunk-7ADPL4Q3.js} +11 -4
- package/dist/chunk-CBGOC6RV.js +293 -0
- package/dist/chunk-DNEADD2G.js +3499 -0
- package/dist/{chunk-NKBZIXCN.js → chunk-DPWFZNMY.js} +122 -15
- package/dist/chunk-GQ73B37K.js +314 -0
- package/dist/chunk-HR34NJP7.js +6133 -0
- package/dist/chunk-ICKSHS3A.js +2264 -0
- package/dist/{chunk-KPETDXQO.js → chunk-OI2HNNT6.js} +565 -50
- package/dist/chunk-PL4HF4M2.js +593 -0
- package/dist/chunk-WS36HDEU.js +3735 -0
- package/dist/chunk-XYU5FFE3.js +111 -0
- package/dist/chunk-ZBQDE6WJ.js +108 -0
- package/dist/client-WIO6W447.js +8 -0
- package/dist/dist-E7E2T3DQ.js +9 -0
- package/dist/dist-TEWNOZYS.js +5 -0
- package/dist/dist-YZBJAYEJ.js +12 -0
- package/dist/index.js +65215 -26627
- package/dist/local-service-adapter-3JHN6G4O.js +6 -0
- package/dist/pioneer-oauth-hook-V2JKEXM7.js +12 -0
- package/dist/{secure-credentials-6UMEU22H.js → secure-credentials-UEPG7GWW.js} +15 -8
- package/dist/snapback-dir-MG7DTRMF.js +6 -0
- package/package.json +8 -42
- package/scripts/postinstall.mjs +2 -3
- package/dist/SkippedTestDetector-B3JZUE5G.js +0 -5
- package/dist/SkippedTestDetector-B3JZUE5G.js.map +0 -1
- package/dist/analysis-Z53F5FT2.js +0 -6
- package/dist/analysis-Z53F5FT2.js.map +0 -1
- package/dist/chunk-6MR2TINI.js +0 -27
- package/dist/chunk-6MR2TINI.js.map +0 -1
- package/dist/chunk-BW7RALUZ.js.map +0 -1
- package/dist/chunk-G7QXHNGB.js.map +0 -1
- package/dist/chunk-ISVRGBWT.js +0 -16223
- package/dist/chunk-ISVRGBWT.js.map +0 -1
- package/dist/chunk-KPETDXQO.js.map +0 -1
- package/dist/chunk-NKBZIXCN.js.map +0 -1
- package/dist/chunk-QAKFE3NE.js.map +0 -1
- package/dist/chunk-YOVA65PS.js +0 -12745
- package/dist/chunk-YOVA65PS.js.map +0 -1
- package/dist/dist-7UKXVKH3.js +0 -5
- package/dist/dist-7UKXVKH3.js.map +0 -1
- package/dist/dist-VDK7WEF4.js +0 -5
- package/dist/dist-VDK7WEF4.js.map +0 -1
- package/dist/dist-WKLJSPJT.js +0 -8
- package/dist/dist-WKLJSPJT.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/secure-credentials-6UMEU22H.js.map +0 -1
- package/dist/snapback-dir-T3CRQRY6.js +0 -6
- package/dist/snapback-dir-T3CRQRY6.js.map +0 -1
|
@@ -1,16 +1,92 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { __name } from './chunk-
|
|
3
|
-
import {
|
|
1
|
+
#!/usr/bin/env node --no-warnings=ExperimentalWarning
|
|
2
|
+
import { __name } from './chunk-7ADPL4Q3.js';
|
|
3
|
+
import { readFileSync, mkdirSync, writeFileSync, existsSync } from 'fs';
|
|
4
4
|
import { homedir, platform } from 'os';
|
|
5
5
|
import { join, resolve, dirname } from 'path';
|
|
6
6
|
import { randomUUID } from 'crypto';
|
|
7
|
-
import { execSync } from 'child_process';
|
|
7
|
+
import { exec, execSync } from 'child_process';
|
|
8
|
+
import { promisify } from 'util';
|
|
8
9
|
|
|
10
|
+
process.env.SNAPBACK_CLI='true';
|
|
9
11
|
var __defProp = Object.defineProperty;
|
|
10
12
|
var __name2 = /* @__PURE__ */ __name((target, value) => __defProp(target, "name", {
|
|
11
13
|
value,
|
|
12
14
|
configurable: true
|
|
13
15
|
}), "__name");
|
|
16
|
+
var CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
17
|
+
function getCacheFilePath() {
|
|
18
|
+
return join(homedir(), ".snapback", "mcp-configs", "paths.json");
|
|
19
|
+
}
|
|
20
|
+
__name(getCacheFilePath, "getCacheFilePath");
|
|
21
|
+
__name2(getCacheFilePath, "getCacheFilePath");
|
|
22
|
+
function readCache() {
|
|
23
|
+
try {
|
|
24
|
+
const raw = readFileSync(getCacheFilePath(), "utf-8");
|
|
25
|
+
const parsed = JSON.parse(raw);
|
|
26
|
+
if (parsed.version === 1 && typeof parsed.discovered === "object") {
|
|
27
|
+
return parsed;
|
|
28
|
+
}
|
|
29
|
+
} catch {
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
version: 1,
|
|
33
|
+
discovered: {}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
__name(readCache, "readCache");
|
|
37
|
+
__name2(readCache, "readCache");
|
|
38
|
+
function writeCache(cache) {
|
|
39
|
+
try {
|
|
40
|
+
const dir = join(homedir(), ".snapback", "mcp-configs");
|
|
41
|
+
mkdirSync(dir, {
|
|
42
|
+
recursive: true
|
|
43
|
+
});
|
|
44
|
+
writeFileSync(getCacheFilePath(), JSON.stringify(cache, null, 2));
|
|
45
|
+
} catch {
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
__name(writeCache, "writeCache");
|
|
49
|
+
__name2(writeCache, "writeCache");
|
|
50
|
+
function getCachedPath(clientName) {
|
|
51
|
+
const cache = readCache();
|
|
52
|
+
const entry = cache.discovered[clientName];
|
|
53
|
+
if (!entry) return null;
|
|
54
|
+
const age = Date.now() - new Date(entry.discoveredAt).getTime();
|
|
55
|
+
if (age > CACHE_TTL_MS) return null;
|
|
56
|
+
if (!existsSync(entry.path)) {
|
|
57
|
+
delete cache.discovered[clientName];
|
|
58
|
+
writeCache(cache);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return entry.path;
|
|
62
|
+
}
|
|
63
|
+
__name(getCachedPath, "getCachedPath");
|
|
64
|
+
__name2(getCachedPath, "getCachedPath");
|
|
65
|
+
function setCachedPath(clientName, configPath) {
|
|
66
|
+
const cache = readCache();
|
|
67
|
+
cache.discovered[clientName] = {
|
|
68
|
+
path: configPath,
|
|
69
|
+
discoveredAt: /* @__PURE__ */ (/* @__PURE__ */ new Date()).toISOString(),
|
|
70
|
+
platform: process.platform
|
|
71
|
+
};
|
|
72
|
+
writeCache(cache);
|
|
73
|
+
}
|
|
74
|
+
__name(setCachedPath, "setCachedPath");
|
|
75
|
+
__name2(setCachedPath, "setCachedPath");
|
|
76
|
+
function evictCachedPath(clientName) {
|
|
77
|
+
const cache = readCache();
|
|
78
|
+
if (cache.discovered[clientName]) {
|
|
79
|
+
delete cache.discovered[clientName];
|
|
80
|
+
writeCache(cache);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
__name(evictCachedPath, "evictCachedPath");
|
|
84
|
+
__name2(evictCachedPath, "evictCachedPath");
|
|
85
|
+
function getAllCachedPaths() {
|
|
86
|
+
return readCache().discovered;
|
|
87
|
+
}
|
|
88
|
+
__name(getAllCachedPaths, "getAllCachedPaths");
|
|
89
|
+
__name2(getAllCachedPaths, "getAllCachedPaths");
|
|
14
90
|
var CLIENT_CONFIGS = {
|
|
15
91
|
claude: /* @__PURE__ */ __name2((home) => {
|
|
16
92
|
switch (platform()) {
|
|
@@ -35,11 +111,17 @@ var CLIENT_CONFIGS = {
|
|
|
35
111
|
] : [],
|
|
36
112
|
join(_home, ".cursor/mcp.json")
|
|
37
113
|
], "cursor"),
|
|
114
|
+
// Windsurf only has a global config — no project-level support (confirmed by Windsurf docs, June 2025)
|
|
38
115
|
windsurf: /* @__PURE__ */ __name2((home) => [
|
|
39
116
|
join(home, ".codeium/windsurf/mcp_config.json")
|
|
40
117
|
], "windsurf"),
|
|
41
|
-
|
|
42
|
-
|
|
118
|
+
// Continue: global config.json or config.yaml; project-level .continue/mcpServers/mcp.json
|
|
119
|
+
continue: /* @__PURE__ */ __name2((home, cwd) => [
|
|
120
|
+
...cwd ? [
|
|
121
|
+
join(cwd, ".continue/mcpServers/mcp.json")
|
|
122
|
+
] : [],
|
|
123
|
+
join(home, ".continue/config.json"),
|
|
124
|
+
join(home, ".continue/config.yaml")
|
|
43
125
|
], "continue"),
|
|
44
126
|
// New clients
|
|
45
127
|
vscode: /* @__PURE__ */ __name2((_home, cwd) => [
|
|
@@ -47,9 +129,16 @@ var CLIENT_CONFIGS = {
|
|
|
47
129
|
join(cwd, ".vscode/mcp.json")
|
|
48
130
|
] : []
|
|
49
131
|
], "vscode"),
|
|
50
|
-
|
|
132
|
+
// Zed: global ~/.config/zed/settings.json, plus project-level .zed/settings.json
|
|
133
|
+
zed: /* @__PURE__ */ __name2((home, cwd) => [
|
|
134
|
+
...cwd ? [
|
|
135
|
+
join(cwd, ".zed/settings.json")
|
|
136
|
+
] : [],
|
|
51
137
|
join(home, ".config/zed/settings.json")
|
|
52
138
|
], "zed"),
|
|
139
|
+
// Cline / Roo Code store their actual settings in VS Code extension globalStorage,
|
|
140
|
+
// but `snap tools configure --cline/--roo-code` writes to these paths as a side-channel.
|
|
141
|
+
// Detection via these paths is best-effort; users may need `snap mcp link --client cline` instead.
|
|
53
142
|
cline: /* @__PURE__ */ __name2((home) => [
|
|
54
143
|
join(home, ".cline/mcp.json")
|
|
55
144
|
], "cline"),
|
|
@@ -63,21 +152,31 @@ var CLIENT_CONFIGS = {
|
|
|
63
152
|
join(home, ".roo-code/mcp.json")
|
|
64
153
|
], "roo-code"),
|
|
65
154
|
// Qoder (VS Code fork) - supports both project-level and global configs
|
|
66
|
-
qoder: /* @__PURE__ */ __name2((home) => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
155
|
+
qoder: /* @__PURE__ */ __name2((home, cwd) => {
|
|
156
|
+
const workspaceConfig = cwd ? [
|
|
157
|
+
join(cwd, ".qoder-mcp-config.json")
|
|
158
|
+
] : [];
|
|
159
|
+
const globalConfigs = (() => {
|
|
160
|
+
switch (platform()) {
|
|
161
|
+
case "darwin":
|
|
162
|
+
return [
|
|
163
|
+
join(home, "Library/Application Support/Qoder/SharedClientCache/mcp.json"),
|
|
164
|
+
join(home, "Library/Application Support/Qoder/SharedClientCache/extension/local/mcp.json")
|
|
165
|
+
];
|
|
166
|
+
case "win32":
|
|
167
|
+
return [
|
|
168
|
+
join(process.env.APPDATA || "", "Qoder/mcp.json")
|
|
169
|
+
];
|
|
170
|
+
default:
|
|
171
|
+
return [
|
|
172
|
+
join(home, ".config/Qoder/mcp.json")
|
|
173
|
+
];
|
|
174
|
+
}
|
|
175
|
+
})();
|
|
176
|
+
return [
|
|
177
|
+
...workspaceConfig,
|
|
178
|
+
...globalConfigs
|
|
179
|
+
];
|
|
81
180
|
}, "qoder")
|
|
82
181
|
};
|
|
83
182
|
var CLIENT_DISPLAY_NAMES = {
|
|
@@ -99,7 +198,12 @@ function detectAIClients(options = {}) {
|
|
|
99
198
|
const clients = [];
|
|
100
199
|
const seenPaths = /* @__PURE__ */ new Set();
|
|
101
200
|
for (const [name, getPaths] of Object.entries(CLIENT_CONFIGS)) {
|
|
102
|
-
const
|
|
201
|
+
const candidates = getPaths(home, cwd);
|
|
202
|
+
const cachedPath = getCachedPath(name);
|
|
203
|
+
const paths = cachedPath && candidates.includes(cachedPath) ? [
|
|
204
|
+
cachedPath,
|
|
205
|
+
...candidates.filter((p) => p !== cachedPath)
|
|
206
|
+
] : candidates;
|
|
103
207
|
for (const configPath of paths) {
|
|
104
208
|
if (seenPaths.has(configPath)) {
|
|
105
209
|
continue;
|
|
@@ -108,6 +212,7 @@ function detectAIClients(options = {}) {
|
|
|
108
212
|
const exists = existsSync(configPath);
|
|
109
213
|
let hasSnapback = false;
|
|
110
214
|
if (exists) {
|
|
215
|
+
setCachedPath(name, configPath);
|
|
111
216
|
try {
|
|
112
217
|
const content = readFileSync(configPath, "utf-8");
|
|
113
218
|
if (configPath.endsWith(".yaml") || configPath.endsWith(".yml")) {
|
|
@@ -160,20 +265,34 @@ function checkForSnapback(config, format) {
|
|
|
160
265
|
case "claude":
|
|
161
266
|
case "cursor":
|
|
162
267
|
case "windsurf":
|
|
163
|
-
case "vscode":
|
|
164
268
|
case "cline":
|
|
165
269
|
case "roo-code":
|
|
270
|
+
if ("mcpServers" in configObj && typeof configObj.mcpServers === "object" && configObj.mcpServers !== null) {
|
|
271
|
+
const servers = configObj.mcpServers;
|
|
272
|
+
return "snapback" in servers || `snapback-${format}` in servers;
|
|
273
|
+
}
|
|
274
|
+
return false;
|
|
166
275
|
case "qoder":
|
|
167
276
|
if ("mcpServers" in configObj && typeof configObj.mcpServers === "object" && configObj.mcpServers !== null) {
|
|
168
277
|
const servers = configObj.mcpServers;
|
|
169
|
-
return "snapback"
|
|
278
|
+
return Object.keys(servers).some((k) => k === "snapback" || k.startsWith("snapback-"));
|
|
279
|
+
}
|
|
280
|
+
return false;
|
|
281
|
+
case "vscode":
|
|
282
|
+
if ("servers" in configObj && typeof configObj.servers === "object" && configObj.servers !== null) {
|
|
283
|
+
const servers = configObj.servers;
|
|
284
|
+
return "snapback" in servers || "snapback-vscode" in servers;
|
|
170
285
|
}
|
|
171
286
|
return false;
|
|
172
287
|
case "gemini":
|
|
173
288
|
case "zed":
|
|
289
|
+
if ("context_servers" in configObj && typeof configObj.context_servers === "object" && configObj.context_servers !== null) {
|
|
290
|
+
const servers = configObj.context_servers;
|
|
291
|
+
return "snapback" in servers || "snapback-zed" in servers;
|
|
292
|
+
}
|
|
174
293
|
if ("mcpServers" in configObj && typeof configObj.mcpServers === "object" && configObj.mcpServers !== null) {
|
|
175
294
|
const servers = configObj.mcpServers;
|
|
176
|
-
return "snapback" in servers;
|
|
295
|
+
return "snapback" in servers || `snapback-${format}` in servers;
|
|
177
296
|
}
|
|
178
297
|
return false;
|
|
179
298
|
case "continue":
|
|
@@ -212,6 +331,64 @@ function readClientConfig(client) {
|
|
|
212
331
|
}
|
|
213
332
|
__name(readClientConfig, "readClientConfig");
|
|
214
333
|
__name2(readClientConfig, "readClientConfig");
|
|
334
|
+
function detectWorkspaceConfig(workspaceRoot) {
|
|
335
|
+
const root = workspaceRoot || process.cwd();
|
|
336
|
+
const qoderConfig = join(root, ".qoder-mcp-config.json");
|
|
337
|
+
if (existsSync(qoderConfig)) {
|
|
338
|
+
try {
|
|
339
|
+
const content = readFileSync(qoderConfig, "utf-8");
|
|
340
|
+
if (content.includes("snapback")) {
|
|
341
|
+
return {
|
|
342
|
+
path: qoderConfig,
|
|
343
|
+
type: "qoder"
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
} catch {
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
const cursorConfig = join(root, ".cursor", "mcp.json");
|
|
350
|
+
if (existsSync(cursorConfig)) {
|
|
351
|
+
try {
|
|
352
|
+
const content = readFileSync(cursorConfig, "utf-8");
|
|
353
|
+
if (content.includes("snapback")) {
|
|
354
|
+
return {
|
|
355
|
+
path: cursorConfig,
|
|
356
|
+
type: "cursor"
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
} catch {
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
const vscodeConfig = join(root, ".vscode", "mcp.json");
|
|
363
|
+
if (existsSync(vscodeConfig)) {
|
|
364
|
+
try {
|
|
365
|
+
const content = readFileSync(vscodeConfig, "utf-8");
|
|
366
|
+
if (content.includes("snapback")) {
|
|
367
|
+
return {
|
|
368
|
+
path: vscodeConfig,
|
|
369
|
+
type: "vscode"
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
} catch {
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const windsurfConfig = join(root, ".windsurf", "mcp.json");
|
|
376
|
+
if (existsSync(windsurfConfig)) {
|
|
377
|
+
try {
|
|
378
|
+
const content = readFileSync(windsurfConfig, "utf-8");
|
|
379
|
+
if (content.includes("snapback")) {
|
|
380
|
+
return {
|
|
381
|
+
path: windsurfConfig,
|
|
382
|
+
type: "windsurf"
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
} catch {
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
__name(detectWorkspaceConfig, "detectWorkspaceConfig");
|
|
391
|
+
__name2(detectWorkspaceConfig, "detectWorkspaceConfig");
|
|
215
392
|
function getSnapbackConfigDir() {
|
|
216
393
|
const isWindows = process.platform === "win32";
|
|
217
394
|
if (isWindows) {
|
|
@@ -308,6 +485,90 @@ function resetIdentityCache() {
|
|
|
308
485
|
}
|
|
309
486
|
__name(resetIdentityCache, "resetIdentityCache");
|
|
310
487
|
__name2(resetIdentityCache, "resetIdentityCache");
|
|
488
|
+
var execAsync = promisify(exec);
|
|
489
|
+
async function detectMCPProcesses() {
|
|
490
|
+
try {
|
|
491
|
+
const { stdout } = await execAsync('ps aux | grep -E "(mcp.*--stdio|--stdio.*mcp|uvx.*mcp-server|npx.*mcp|node.*mcp)" | grep -v grep', {
|
|
492
|
+
timeout: 5e3
|
|
493
|
+
});
|
|
494
|
+
const processes = parseProcessOutput(stdout);
|
|
495
|
+
const snapbackProcesses = processes.filter((p) => p.isSnapback);
|
|
496
|
+
return {
|
|
497
|
+
allProcesses: processes,
|
|
498
|
+
snapbackProcesses,
|
|
499
|
+
snapbackRunning: snapbackProcesses.length > 0,
|
|
500
|
+
totalCount: processes.length,
|
|
501
|
+
checkedAt: /* @__PURE__ */ new Date()
|
|
502
|
+
};
|
|
503
|
+
} catch {
|
|
504
|
+
return {
|
|
505
|
+
allProcesses: [],
|
|
506
|
+
snapbackProcesses: [],
|
|
507
|
+
snapbackRunning: false,
|
|
508
|
+
totalCount: 0,
|
|
509
|
+
checkedAt: /* @__PURE__ */ new Date()
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
__name(detectMCPProcesses, "detectMCPProcesses");
|
|
514
|
+
__name2(detectMCPProcesses, "detectMCPProcesses");
|
|
515
|
+
function parseProcessOutput(output) {
|
|
516
|
+
const lines = output.trim().split("\n").filter((line) => line.trim());
|
|
517
|
+
const processes = [];
|
|
518
|
+
for (const line of lines) {
|
|
519
|
+
const match = line.match(/^(\S+)\s+(\d+)\s+.*?\s+(.+)$/);
|
|
520
|
+
if (!match) {
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
const [, , pidStr, command] = match;
|
|
524
|
+
const pid = Number.parseInt(pidStr, 10);
|
|
525
|
+
if (Number.isNaN(pid)) {
|
|
526
|
+
continue;
|
|
527
|
+
}
|
|
528
|
+
const serverName = extractServerName(command);
|
|
529
|
+
const isSnapback = command.toLowerCase().includes("snapback");
|
|
530
|
+
processes.push({
|
|
531
|
+
pid,
|
|
532
|
+
command: command.trim(),
|
|
533
|
+
serverName,
|
|
534
|
+
isSnapback
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
return processes;
|
|
538
|
+
}
|
|
539
|
+
__name(parseProcessOutput, "parseProcessOutput");
|
|
540
|
+
__name2(parseProcessOutput, "parseProcessOutput");
|
|
541
|
+
function extractServerName(command) {
|
|
542
|
+
const patterns = [
|
|
543
|
+
// snapback mcp --stdio
|
|
544
|
+
/snapback[/\s]/i,
|
|
545
|
+
// mcp-server-fetch
|
|
546
|
+
/mcp-server-(\w+)/,
|
|
547
|
+
// @modelcontextprotocol/server-sequential-thinking
|
|
548
|
+
/server-(\w+)/,
|
|
549
|
+
// context7-mcp
|
|
550
|
+
/(\w+)-mcp/,
|
|
551
|
+
// fly mcp server
|
|
552
|
+
/fly.*mcp/i,
|
|
553
|
+
// supabase-mcp
|
|
554
|
+
/supabase-mcp/i
|
|
555
|
+
];
|
|
556
|
+
for (const pattern of patterns) {
|
|
557
|
+
const match = command.match(pattern);
|
|
558
|
+
if (match) {
|
|
559
|
+
return match[1] || match[0];
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return "mcp";
|
|
563
|
+
}
|
|
564
|
+
__name(extractServerName, "extractServerName");
|
|
565
|
+
__name2(extractServerName, "extractServerName");
|
|
566
|
+
async function isSnapbackMCPRunning() {
|
|
567
|
+
const health = await detectMCPProcesses();
|
|
568
|
+
return health.snapbackRunning;
|
|
569
|
+
}
|
|
570
|
+
__name(isSnapbackMCPRunning, "isSnapbackMCPRunning");
|
|
571
|
+
__name2(isSnapbackMCPRunning, "isSnapbackMCPRunning");
|
|
311
572
|
function validateClientConfig(client) {
|
|
312
573
|
const issues = [];
|
|
313
574
|
if (!existsSync(client.configPath)) {
|
|
@@ -504,7 +765,15 @@ function validateSnapbackConfig(config, issues) {
|
|
|
504
765
|
severity: "error",
|
|
505
766
|
code: "MISSING_STDIO_ARG",
|
|
506
767
|
message: "Args must include '--stdio' flag",
|
|
507
|
-
fix: "Run: snap
|
|
768
|
+
fix: "Run: snap mcp repair --client <name>"
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
if (config.args.includes("shim")) {
|
|
772
|
+
issues.push({
|
|
773
|
+
severity: "error",
|
|
774
|
+
code: "DEPRECATED_SHIM_COMMAND",
|
|
775
|
+
message: "Args contain deprecated 'shim' command - use '--stdio' instead",
|
|
776
|
+
fix: "Run: snap mcp repair --client <name>"
|
|
508
777
|
});
|
|
509
778
|
}
|
|
510
779
|
if (!config.args.includes("--workspace")) {
|
|
@@ -623,14 +892,15 @@ function isCommandExecutable2(command) {
|
|
|
623
892
|
}
|
|
624
893
|
__name(isCommandExecutable2, "isCommandExecutable2");
|
|
625
894
|
__name2(isCommandExecutable2, "isCommandExecutable");
|
|
895
|
+
var STDIO_ONLY_CLIENTS = /* @__PURE__ */ new Set([
|
|
896
|
+
"claude"
|
|
897
|
+
]);
|
|
626
898
|
function getSnapbackMCPConfig(options = {}) {
|
|
627
|
-
const { apiKey, workspaceId, serverUrl,
|
|
899
|
+
const { apiKey, workspaceId, serverUrl, useBinary = false, customCommand, additionalEnv, workspaceRoot, useLocalDev = false, localCliPath, client, useDoppler = false, dopplerProject = "snapback-shared", dopplerConfig = "dev", useSse = false, useStreamableHttp = false } = options;
|
|
900
|
+
const useNpx = options.useNpx ?? (client ? STDIO_ONLY_CLIENTS.has(client) : false);
|
|
628
901
|
const env = {
|
|
629
902
|
...additionalEnv
|
|
630
903
|
};
|
|
631
|
-
if (workspaceId) {
|
|
632
|
-
env.SNAPBACK_WORKSPACE_ID = workspaceId;
|
|
633
|
-
}
|
|
634
904
|
if (apiKey) {
|
|
635
905
|
env.SNAPBACK_API_KEY = apiKey;
|
|
636
906
|
}
|
|
@@ -643,9 +913,65 @@ function getSnapbackMCPConfig(options = {}) {
|
|
|
643
913
|
}
|
|
644
914
|
};
|
|
645
915
|
}
|
|
916
|
+
if (useSse || useStreamableHttp) {
|
|
917
|
+
const url = serverUrl || "https://mcp.snapback.dev/mcp";
|
|
918
|
+
const headers2 = {};
|
|
919
|
+
if (workspaceId) {
|
|
920
|
+
headers2["x-workspace-id"] = workspaceId;
|
|
921
|
+
}
|
|
922
|
+
if (apiKey) {
|
|
923
|
+
headers2["x-api-key"] = apiKey;
|
|
924
|
+
}
|
|
925
|
+
return {
|
|
926
|
+
url,
|
|
927
|
+
...Object.keys(headers2).length > 0 && {
|
|
928
|
+
headers: headers2
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
if (useDoppler && localCliPath) {
|
|
933
|
+
const tier = apiKey ? "pro" : "free";
|
|
934
|
+
const nodePath = resolveNodePath();
|
|
935
|
+
const dopplerArgs = [
|
|
936
|
+
"run",
|
|
937
|
+
"--project",
|
|
938
|
+
dopplerProject,
|
|
939
|
+
"--config",
|
|
940
|
+
dopplerConfig,
|
|
941
|
+
"--",
|
|
942
|
+
nodePath,
|
|
943
|
+
localCliPath,
|
|
944
|
+
"mcp",
|
|
945
|
+
"--stdio",
|
|
946
|
+
"--tier",
|
|
947
|
+
tier
|
|
948
|
+
];
|
|
949
|
+
if (workspaceRoot) {
|
|
950
|
+
dopplerArgs.push("--workspace", workspaceRoot);
|
|
951
|
+
}
|
|
952
|
+
return {
|
|
953
|
+
command: "doppler",
|
|
954
|
+
args: dopplerArgs
|
|
955
|
+
};
|
|
956
|
+
}
|
|
646
957
|
if (useNpx) {
|
|
958
|
+
const isClaudeDesktop = client === "claude";
|
|
959
|
+
if (isClaudeDesktop) {
|
|
960
|
+
const args2 = [
|
|
961
|
+
"--yes",
|
|
962
|
+
"@snapback/mcpb"
|
|
963
|
+
];
|
|
964
|
+
if (workspaceRoot) {
|
|
965
|
+
args2.push(workspaceRoot);
|
|
966
|
+
}
|
|
967
|
+
return {
|
|
968
|
+
command: "npx",
|
|
969
|
+
args: args2
|
|
970
|
+
};
|
|
971
|
+
}
|
|
647
972
|
const tier = apiKey ? "pro" : "free";
|
|
648
973
|
const args = [
|
|
974
|
+
"--yes",
|
|
649
975
|
"@snapback/cli",
|
|
650
976
|
"mcp",
|
|
651
977
|
"--stdio",
|
|
@@ -663,12 +989,19 @@ function getSnapbackMCPConfig(options = {}) {
|
|
|
663
989
|
}
|
|
664
990
|
};
|
|
665
991
|
}
|
|
666
|
-
if (serverUrl || !useLocalDev && !useBinary) {
|
|
667
|
-
const url = serverUrl || "https://
|
|
992
|
+
if (serverUrl || !useLocalDev && !useBinary && !useDoppler) {
|
|
993
|
+
const url = serverUrl || "https://mcp.snapback.dev/mcp";
|
|
994
|
+
const headers2 = {};
|
|
995
|
+
if (workspaceId) {
|
|
996
|
+
headers2["x-workspace-id"] = workspaceId;
|
|
997
|
+
}
|
|
998
|
+
if (apiKey) {
|
|
999
|
+
headers2["x-api-key"] = apiKey;
|
|
1000
|
+
}
|
|
668
1001
|
return {
|
|
669
1002
|
url,
|
|
670
|
-
...Object.keys(
|
|
671
|
-
|
|
1003
|
+
...Object.keys(headers2).length > 0 && {
|
|
1004
|
+
headers: headers2
|
|
672
1005
|
}
|
|
673
1006
|
};
|
|
674
1007
|
}
|
|
@@ -712,10 +1045,17 @@ function getSnapbackMCPConfig(options = {}) {
|
|
|
712
1045
|
}
|
|
713
1046
|
};
|
|
714
1047
|
}
|
|
1048
|
+
const headers = {};
|
|
1049
|
+
if (workspaceId) {
|
|
1050
|
+
headers["x-workspace-id"] = workspaceId;
|
|
1051
|
+
}
|
|
1052
|
+
if (apiKey) {
|
|
1053
|
+
headers["x-api-key"] = apiKey;
|
|
1054
|
+
}
|
|
715
1055
|
return {
|
|
716
|
-
url: "https://
|
|
717
|
-
...Object.keys(
|
|
718
|
-
|
|
1056
|
+
url: "https://mcp.snapback.dev/mcp",
|
|
1057
|
+
...Object.keys(headers).length > 0 && {
|
|
1058
|
+
headers
|
|
719
1059
|
}
|
|
720
1060
|
};
|
|
721
1061
|
}
|
|
@@ -773,6 +1113,10 @@ function removeSnapbackConfig(client) {
|
|
|
773
1113
|
case "claude":
|
|
774
1114
|
case "cursor":
|
|
775
1115
|
case "windsurf":
|
|
1116
|
+
case "cline":
|
|
1117
|
+
case "roo-code":
|
|
1118
|
+
case "gemini":
|
|
1119
|
+
case "qoder":
|
|
776
1120
|
if (config.mcpServers?.[serverKey]) {
|
|
777
1121
|
delete config.mcpServers[serverKey];
|
|
778
1122
|
}
|
|
@@ -780,6 +1124,28 @@ function removeSnapbackConfig(client) {
|
|
|
780
1124
|
delete config.mcpServers.snapback;
|
|
781
1125
|
}
|
|
782
1126
|
break;
|
|
1127
|
+
case "vscode": {
|
|
1128
|
+
const vscodeConfig = config;
|
|
1129
|
+
const servers = vscodeConfig.servers;
|
|
1130
|
+
if (servers?.[serverKey]) {
|
|
1131
|
+
delete servers[serverKey];
|
|
1132
|
+
}
|
|
1133
|
+
if (servers?.snapback) {
|
|
1134
|
+
delete servers.snapback;
|
|
1135
|
+
}
|
|
1136
|
+
break;
|
|
1137
|
+
}
|
|
1138
|
+
case "zed": {
|
|
1139
|
+
const zedConfig = config;
|
|
1140
|
+
const contextServers = zedConfig.context_servers;
|
|
1141
|
+
if (contextServers?.[serverKey]) {
|
|
1142
|
+
delete contextServers[serverKey];
|
|
1143
|
+
}
|
|
1144
|
+
if (contextServers?.snapback) {
|
|
1145
|
+
delete contextServers.snapback;
|
|
1146
|
+
}
|
|
1147
|
+
break;
|
|
1148
|
+
}
|
|
783
1149
|
case "continue": {
|
|
784
1150
|
const experimental = config.experimental;
|
|
785
1151
|
if (experimental?.modelContextProtocolServers) {
|
|
@@ -790,6 +1156,7 @@ function removeSnapbackConfig(client) {
|
|
|
790
1156
|
}
|
|
791
1157
|
}
|
|
792
1158
|
writeFileSync(client.configPath, JSON.stringify(config, null, 2));
|
|
1159
|
+
evictCachedPath(client.name);
|
|
793
1160
|
return {
|
|
794
1161
|
success: true
|
|
795
1162
|
};
|
|
@@ -815,13 +1182,9 @@ function mergeConfig(existing, snapbackConfig, format) {
|
|
|
815
1182
|
switch (format) {
|
|
816
1183
|
case "claude":
|
|
817
1184
|
case "cursor":
|
|
818
|
-
case "windsurf":
|
|
819
|
-
case "vscode":
|
|
820
1185
|
case "cline":
|
|
821
1186
|
case "roo-code":
|
|
822
1187
|
case "gemini":
|
|
823
|
-
case "zed":
|
|
824
|
-
case "qoder":
|
|
825
1188
|
return {
|
|
826
1189
|
...existing,
|
|
827
1190
|
mcpServers: {
|
|
@@ -829,6 +1192,58 @@ function mergeConfig(existing, snapbackConfig, format) {
|
|
|
829
1192
|
[serverKey]: snapbackConfig
|
|
830
1193
|
}
|
|
831
1194
|
};
|
|
1195
|
+
case "windsurf":
|
|
1196
|
+
return {
|
|
1197
|
+
...existing,
|
|
1198
|
+
mcpServers: {
|
|
1199
|
+
...existing.mcpServers || {},
|
|
1200
|
+
[serverKey]: {
|
|
1201
|
+
...snapbackConfig,
|
|
1202
|
+
disabled: false,
|
|
1203
|
+
alwaysAllow: []
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
};
|
|
1207
|
+
case "qoder": {
|
|
1208
|
+
const qoderType = snapbackConfig.url ? "sse" : "stdio";
|
|
1209
|
+
return {
|
|
1210
|
+
...existing,
|
|
1211
|
+
mcpServers: {
|
|
1212
|
+
...existing.mcpServers || {},
|
|
1213
|
+
[serverKey]: {
|
|
1214
|
+
type: qoderType,
|
|
1215
|
+
...snapbackConfig
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
case "vscode": {
|
|
1221
|
+
const vscodeConfig = existing;
|
|
1222
|
+
const servers = vscodeConfig.servers || {};
|
|
1223
|
+
const { mcpServers: _, ...rest } = vscodeConfig;
|
|
1224
|
+
return {
|
|
1225
|
+
...rest,
|
|
1226
|
+
servers: {
|
|
1227
|
+
...servers,
|
|
1228
|
+
[serverKey]: {
|
|
1229
|
+
type: "stdio",
|
|
1230
|
+
...snapbackConfig
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1235
|
+
case "zed": {
|
|
1236
|
+
const zedConfig = existing;
|
|
1237
|
+
const contextServers = zedConfig.context_servers || {};
|
|
1238
|
+
const { mcpServers: _, ...rest } = zedConfig;
|
|
1239
|
+
return {
|
|
1240
|
+
...rest,
|
|
1241
|
+
context_servers: {
|
|
1242
|
+
...contextServers,
|
|
1243
|
+
[serverKey]: snapbackConfig
|
|
1244
|
+
}
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
832
1247
|
case "continue": {
|
|
833
1248
|
const continueConfig = existing;
|
|
834
1249
|
const experimental = continueConfig.experimental || {};
|
|
@@ -863,6 +1278,87 @@ function mergeConfig(existing, snapbackConfig, format) {
|
|
|
863
1278
|
}
|
|
864
1279
|
__name(mergeConfig, "mergeConfig");
|
|
865
1280
|
__name2(mergeConfig, "mergeConfig");
|
|
1281
|
+
function patchApiKeyInClientConfig(client, apiKey) {
|
|
1282
|
+
try {
|
|
1283
|
+
if (!existsSync(client.configPath)) return false;
|
|
1284
|
+
const raw = readFileSync(client.configPath, "utf-8");
|
|
1285
|
+
const config = JSON.parse(raw);
|
|
1286
|
+
const serverKey = getServerKey(client.format);
|
|
1287
|
+
let patched = false;
|
|
1288
|
+
const patchEntry = /* @__PURE__ */ __name2((entry) => {
|
|
1289
|
+
if (typeof entry !== "object" || entry === null) return false;
|
|
1290
|
+
const e = entry;
|
|
1291
|
+
if (e.url && typeof e.url === "string") {
|
|
1292
|
+
if (!e.headers || typeof e.headers !== "object") {
|
|
1293
|
+
e.headers = {};
|
|
1294
|
+
}
|
|
1295
|
+
e.headers["x-api-key"] = apiKey;
|
|
1296
|
+
const headers = e.headers;
|
|
1297
|
+
if (headers.Authorization?.includes("<your-token>")) {
|
|
1298
|
+
delete headers.Authorization;
|
|
1299
|
+
}
|
|
1300
|
+
return true;
|
|
1301
|
+
}
|
|
1302
|
+
if (!e.env || typeof e.env !== "object") {
|
|
1303
|
+
e.env = {};
|
|
1304
|
+
}
|
|
1305
|
+
e.env.SNAPBACK_API_KEY = apiKey;
|
|
1306
|
+
return true;
|
|
1307
|
+
}, "patchEntry");
|
|
1308
|
+
switch (client.format) {
|
|
1309
|
+
case "claude":
|
|
1310
|
+
case "cursor":
|
|
1311
|
+
case "windsurf":
|
|
1312
|
+
case "cline":
|
|
1313
|
+
case "roo-code":
|
|
1314
|
+
case "gemini": {
|
|
1315
|
+
const servers = config.mcpServers || {};
|
|
1316
|
+
const entry = servers[serverKey] ?? servers.snapback;
|
|
1317
|
+
if (entry) patched = patchEntry(entry);
|
|
1318
|
+
break;
|
|
1319
|
+
}
|
|
1320
|
+
case "qoder": {
|
|
1321
|
+
const servers = config.mcpServers || {};
|
|
1322
|
+
for (const key of Object.keys(servers)) {
|
|
1323
|
+
if (key === "snapback" || key.startsWith("snapback-")) {
|
|
1324
|
+
patched = patchEntry(servers[key]) || patched;
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
break;
|
|
1328
|
+
}
|
|
1329
|
+
case "vscode": {
|
|
1330
|
+
const servers = config.servers || {};
|
|
1331
|
+
const entry = servers[serverKey] ?? servers.snapback;
|
|
1332
|
+
if (entry) patched = patchEntry(entry);
|
|
1333
|
+
break;
|
|
1334
|
+
}
|
|
1335
|
+
case "zed": {
|
|
1336
|
+
const servers = config.context_servers || {};
|
|
1337
|
+
const entry = servers[serverKey] ?? servers.snapback;
|
|
1338
|
+
if (entry) patched = patchEntry(entry);
|
|
1339
|
+
break;
|
|
1340
|
+
}
|
|
1341
|
+
case "continue": {
|
|
1342
|
+
const exp = config.experimental || {};
|
|
1343
|
+
const list = exp.modelContextProtocolServers || [];
|
|
1344
|
+
for (const item of list) {
|
|
1345
|
+
if (typeof item.name === "string" && item.name.startsWith("snapback")) {
|
|
1346
|
+
patched = patchEntry(item) || patched;
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
break;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
if (patched) {
|
|
1353
|
+
writeFileSync(client.configPath, JSON.stringify(config, null, 2));
|
|
1354
|
+
}
|
|
1355
|
+
return patched;
|
|
1356
|
+
} catch {
|
|
1357
|
+
return false;
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
__name(patchApiKeyInClientConfig, "patchApiKeyInClientConfig");
|
|
1361
|
+
__name2(patchApiKeyInClientConfig, "patchApiKeyInClientConfig");
|
|
866
1362
|
function validateConfig(client) {
|
|
867
1363
|
try {
|
|
868
1364
|
const content = readFileSync(client.configPath, "utf-8");
|
|
@@ -872,15 +1368,33 @@ function validateConfig(client) {
|
|
|
872
1368
|
case "claude":
|
|
873
1369
|
case "cursor":
|
|
874
1370
|
case "windsurf":
|
|
875
|
-
case "vscode":
|
|
876
1371
|
case "cline":
|
|
877
1372
|
case "roo-code":
|
|
878
1373
|
case "gemini":
|
|
879
|
-
case "zed":
|
|
880
1374
|
case "qoder": {
|
|
881
1375
|
const serverConfig = config.mcpServers?.[serverKey] || config.mcpServers?.snapback;
|
|
882
1376
|
return Boolean(serverConfig?.command || serverConfig?.url);
|
|
883
1377
|
}
|
|
1378
|
+
case "vscode": {
|
|
1379
|
+
const vscodeConfig = config;
|
|
1380
|
+
const servers = vscodeConfig.servers;
|
|
1381
|
+
const serverConfig = servers?.[serverKey] || servers?.snapback;
|
|
1382
|
+
if (typeof serverConfig === "object" && serverConfig !== null) {
|
|
1383
|
+
const cfg = serverConfig;
|
|
1384
|
+
return Boolean(cfg.command || cfg.url);
|
|
1385
|
+
}
|
|
1386
|
+
return false;
|
|
1387
|
+
}
|
|
1388
|
+
case "zed": {
|
|
1389
|
+
const zedConfig = config;
|
|
1390
|
+
const contextServers = zedConfig.context_servers;
|
|
1391
|
+
const serverConfig = contextServers?.[serverKey] || contextServers?.snapback;
|
|
1392
|
+
if (typeof serverConfig === "object" && serverConfig !== null) {
|
|
1393
|
+
const cfg = serverConfig;
|
|
1394
|
+
return Boolean(cfg.command || cfg.url);
|
|
1395
|
+
}
|
|
1396
|
+
return false;
|
|
1397
|
+
}
|
|
884
1398
|
case "continue": {
|
|
885
1399
|
const expCfg = config.experimental;
|
|
886
1400
|
const srvs = expCfg?.modelContextProtocolServers;
|
|
@@ -1007,6 +1521,7 @@ function attemptFix(client, issue, _validation, options) {
|
|
|
1007
1521
|
case "MISSING_ARGS":
|
|
1008
1522
|
case "MISSING_MCP_ARG":
|
|
1009
1523
|
case "MISSING_STDIO_ARG":
|
|
1524
|
+
case "DEPRECATED_SHIM_COMMAND":
|
|
1010
1525
|
case "INVALID_URL":
|
|
1011
1526
|
return performFullReconfiguration(client, options);
|
|
1012
1527
|
case "COMMAND_NOT_EXECUTABLE": {
|
|
@@ -1072,7 +1587,8 @@ function performFullReconfiguration(client, options) {
|
|
|
1072
1587
|
workspaceId: options.workspaceId,
|
|
1073
1588
|
workspaceRoot,
|
|
1074
1589
|
useLocalDev: true,
|
|
1075
|
-
localCliPath: cliPath
|
|
1590
|
+
localCliPath: cliPath,
|
|
1591
|
+
client: client.format
|
|
1076
1592
|
});
|
|
1077
1593
|
const nodePath = resolveNodePath();
|
|
1078
1594
|
console.error(`[MCP Repair] Using node path: ${nodePath}`);
|
|
@@ -1080,9 +1596,10 @@ function performFullReconfiguration(client, options) {
|
|
|
1080
1596
|
mcpConfig = getSnapbackMCPConfig({
|
|
1081
1597
|
apiKey: options.apiKey,
|
|
1082
1598
|
workspaceId: options.workspaceId,
|
|
1083
|
-
useLocalDev: false
|
|
1599
|
+
useLocalDev: false,
|
|
1600
|
+
client: client.format
|
|
1084
1601
|
});
|
|
1085
|
-
console.error("[MCP Repair] Using
|
|
1602
|
+
console.error("[MCP Repair] Using default mode (CLI not found locally)");
|
|
1086
1603
|
}
|
|
1087
1604
|
const writeResult = writeClientConfig(client, mcpConfig);
|
|
1088
1605
|
if (writeResult.success) {
|
|
@@ -1155,6 +1672,4 @@ function findCliPath() {
|
|
|
1155
1672
|
__name(findCliPath, "findCliPath");
|
|
1156
1673
|
__name2(findCliPath, "findCliPath");
|
|
1157
1674
|
|
|
1158
|
-
export { createManagedMetadata, detectAIClients, getClient, getClientConfigPath, getConfiguredClients, getOrCreateIdentity, getServerKey, getSnapbackConfigDir, getSnapbackMCPConfig, injectWorkspacePath, isCommandExecutable2, isOwnedByThisInstall, readClientConfig, removeSnapbackConfig, repairClientConfig, resetIdentityCache, resolveNodePath, validateClientConfig, validateConfig, validateWorkspacePath, writeClientConfig };
|
|
1159
|
-
//# sourceMappingURL=chunk-KPETDXQO.js.map
|
|
1160
|
-
//# sourceMappingURL=chunk-KPETDXQO.js.map
|
|
1675
|
+
export { createManagedMetadata, detectAIClients, detectMCPProcesses, detectWorkspaceConfig, evictCachedPath, getAllCachedPaths, getCachedPath, getClient, getClientConfigPath, getConfiguredClients, getOrCreateIdentity, getServerKey, getSnapbackConfigDir, getSnapbackMCPConfig, injectWorkspacePath, isCommandExecutable2, isOwnedByThisInstall, isSnapbackMCPRunning, patchApiKeyInClientConfig, readClientConfig, removeSnapbackConfig, repairClientConfig, resetIdentityCache, resolveNodePath, setCachedPath, validateClientConfig, validateConfig, validateWorkspacePath, writeClientConfig };
|