agent-toggle 0.1.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.
@@ -0,0 +1,483 @@
1
+ /*
2
+ * Agents that are usually not installed on the development machine: their
3
+ * adapters follow the official docs. When no native switch is documented, the
4
+ * safe fallback is used (stash for config entries, <dir>.disabled/ for files),
5
+ * because some agents reject unknown keys (Codebuff, Trae).
6
+ */
7
+ import path from "node:path";
8
+ import { boolMapSection, describeServer, dirNames, dirSection, frontmatterSkillsSection, hooksSection, listSection, mcpSection, shortPath, sortByGroup, YAML_IO } from "../core/generic.js";
9
+ import { getPath, home, readJson, toggled } from "../core/jsonio.js";
10
+ import { readToml, setArrayTableKey } from "../core/toml.js";
11
+ import { tomlListSection } from "./_toml.js";
12
+ import { skillsIn } from "./_skills.js";
13
+ import { editYaml, readYaml } from "../core/yaml.js";
14
+ import { sameEntry, stashed, updateStash } from "../core/stash.js";
15
+ import { t } from "../core/i18n.js";
16
+ import { mcpGroup } from "../core/groups.js";
17
+ const appData = () => process.env.APPDATA ?? home("AppData", "Roaming");
18
+ const xdgConfig = (...p) => process.platform === "win32" ? path.join(appData(), ...p) : path.join(process.env.XDG_CONFIG_HOME ?? home(".config"), ...p);
19
+ // ------------------------------------------------------------------ JetBrains Junie
20
+ const JUNIE = process.env.JUNIE_HOME ?? home(".junie");
21
+ export const junie = {
22
+ id: "junie",
23
+ name: "JetBrains Junie CLI",
24
+ bins: ["junie"],
25
+ dirs: [".junie"],
26
+ sections: [
27
+ mcpSection({
28
+ agent: "junie",
29
+ files: { user: () => path.join(JUNIE, "mcp", "mcp.json"), project: (c) => path.join(c.root, ".junie", "mcp", "mcp.json") },
30
+ key: ["mcpServers"],
31
+ disable: { type: "stash" },
32
+ }),
33
+ dirSection({ kind: "skills", dirs: { user: () => path.join(JUNIE, "skills"), project: (c) => path.join(c.root, ".junie", "skills") }, entry: { dir: "SKILL.md" } }),
34
+ hooksSection({ agent: "junie", files: { user: () => path.join(JUNIE, "config.json") }, key: ["hooks"] }),
35
+ dirSection({ kind: "commands", dirs: { user: () => path.join(JUNIE, "commands"), project: (c) => path.join(c.root, ".junie", "commands") }, entry: { ext: [".md"] } }),
36
+ dirSection({ kind: "agents", dirs: { user: () => path.join(JUNIE, "agents"), project: (c) => path.join(c.root, ".junie", "agents") }, entry: { ext: [".md"] } }),
37
+ ],
38
+ notes: ["notes.junie.native"],
39
+ };
40
+ // ------------------------------------------------------------------ Amazon Q Developer CLI (legacy of Kiro CLI)
41
+ export const amazonq = {
42
+ id: "amazonq",
43
+ name: "Amazon Q Developer CLI",
44
+ bins: ["qchat"],
45
+ dirs: [".aws/amazonq"],
46
+ sections: [
47
+ mcpSection({
48
+ agent: "amazonq",
49
+ files: { user: () => home(".aws", "amazonq", "mcp.json"), project: (c) => path.join(c.root, ".amazonq", "mcp.json") },
50
+ key: ["mcpServers"],
51
+ disable: { type: "flag", key: "disabled", off: true },
52
+ }),
53
+ dirSection({ kind: "commands", title: "title.kiroPrompts", dirs: { user: () => home(".aws", "amazonq", "prompts"), project: (c) => path.join(c.root, ".amazonq", "prompts") }, entry: { ext: [".md"] } }),
54
+ dirSection({ kind: "agents", dirs: { user: () => home(".aws", "amazonq", "cli-agents"), project: (c) => path.join(c.root, ".amazonq", "cli-agents") }, entry: { ext: [".json"] } }),
55
+ ],
56
+ notes: ["notes.amazonq.legacy"],
57
+ };
58
+ // ------------------------------------------------------------------ Letta Code
59
+ const LETTA = home(".letta");
60
+ export const letta = {
61
+ id: "letta",
62
+ name: "Letta Code",
63
+ bins: ["letta"],
64
+ dirs: [".letta"],
65
+ sections: [
66
+ hooksSection({
67
+ agent: "letta",
68
+ files: {
69
+ user: () => path.join(LETTA, "settings.json"),
70
+ project: (c) => path.join(c.root, ".letta", "settings.json"),
71
+ local: (c) => path.join(c.root, ".letta", "settings.local.json"),
72
+ },
73
+ key: ["hooks"],
74
+ disableAll: { path: ["hooks", "disabled"], off: true },
75
+ }),
76
+ dirSection({ kind: "plugins", title: "title.mods", dirs: { user: () => path.join(LETTA, "mods") }, entry: { ext: [".ts", ".js"] } }),
77
+ dirSection({ kind: "skills", dirs: { user: () => path.join(LETTA, "skills"), project: (c) => path.join(c.root, ".agents", "skills") }, entry: { dir: "SKILL.md" }, note: "note.sharedSkillsMoved" }),
78
+ dirSection({ kind: "commands", dirs: { user: () => path.join(LETTA, "commands"), project: (c) => path.join(c.root, ".commands") }, entry: { ext: [".md"] } }),
79
+ dirSection({ kind: "agents", dirs: { user: () => path.join(LETTA, "agents"), project: (c) => path.join(c.root, ".letta", "agents") }, entry: { ext: [".md"] } }),
80
+ ],
81
+ notes: ["notes.letta.mcp"],
82
+ };
83
+ // ------------------------------------------------------------------ Pi coding agent
84
+ const PI = process.env.PI_CODING_AGENT_DIR ?? home(".pi", "agent");
85
+ export const pi = {
86
+ id: "pi",
87
+ name: "Pi coding agent",
88
+ bins: [],
89
+ dirs: [".pi/agent"],
90
+ sections: [
91
+ dirSection({ kind: "plugins", title: "title.extensions", dirs: { user: () => path.join(PI, "extensions"), project: (c) => path.join(c.root, ".pi", "extensions") }, entry: { ext: [".ts", ".js"] } }),
92
+ dirSection({ kind: "skills", dirs: { user: () => path.join(PI, "skills"), project: (c) => path.join(c.root, ".pi", "skills") }, entry: { dir: "SKILL.md" } }),
93
+ dirSection({ kind: "commands", title: "title.promptTemplates", dirs: { user: () => path.join(PI, "prompts"), project: (c) => path.join(c.root, ".pi", "prompts") }, entry: { ext: [".md"] } }),
94
+ ],
95
+ notes: ["notes.pi.noMcp"],
96
+ };
97
+ // ------------------------------------------------------------------ Codebuff / Freebuff
98
+ export const codebuff = {
99
+ id: "codebuff",
100
+ name: "Codebuff",
101
+ bins: ["codebuff", "freebuff"],
102
+ dirs: [".config/manicode"],
103
+ sections: [
104
+ mcpSection({
105
+ agent: "codebuff",
106
+ files: { user: () => home(".agents", "mcp.json"), project: (c) => path.join(c.root, ".agents", "mcp.json") },
107
+ key: ["mcpServers"],
108
+ disable: { type: "stash" },
109
+ note: "note.strictSchema",
110
+ }),
111
+ ],
112
+ };
113
+ // ------------------------------------------------------------------ Trae Agent
114
+ export const trae = {
115
+ id: "trae",
116
+ name: "Trae Agent",
117
+ bins: ["trae-cli"],
118
+ dirs: [],
119
+ sections: [
120
+ listSection({
121
+ kind: "mcp",
122
+ files: { project: (c) => path.join(c.root, "trae_config.yaml") },
123
+ path: ["allow_mcp_servers"],
124
+ mode: "allow",
125
+ io: YAML_IO,
126
+ discover: (ctx) => Object.keys(readYaml(path.join(ctx.root, "trae_config.yaml")).mcp_servers ?? {}).map((id) => ({ id, group: mcpGroup(id) })),
127
+ note: "note.traeAllow",
128
+ }),
129
+ ],
130
+ };
131
+ // ------------------------------------------------------------------ Windsurf (Devin Desktop)
132
+ export const windsurf = {
133
+ id: "windsurf",
134
+ name: "Windsurf",
135
+ bins: ["windsurf"],
136
+ dirs: [".codeium/windsurf"],
137
+ sections: [
138
+ mcpSection({
139
+ agent: "windsurf",
140
+ files: { user: () => home(".codeium", "windsurf", "mcp_config.json") },
141
+ key: ["mcpServers"],
142
+ disable: { type: "stash" },
143
+ }),
144
+ ],
145
+ notes: ["notes.windsurf.devin"],
146
+ };
147
+ // ------------------------------------------------------------------ Hermes Agent
148
+ const HERMES = home(".hermes");
149
+ export const hermes = {
150
+ id: "hermes",
151
+ name: "Hermes Agent",
152
+ bins: ["hermes"],
153
+ dirs: [".hermes"],
154
+ sections: [
155
+ mcpSection({
156
+ agent: "hermes",
157
+ files: { user: () => path.join(HERMES, "config.yaml") },
158
+ key: ["mcp_servers"],
159
+ disable: { type: "flag", key: "enabled", off: false },
160
+ io: YAML_IO,
161
+ }),
162
+ dirSection({ kind: "skills", dirs: { user: () => path.join(HERMES, "skills") }, entry: { dir: "SKILL.md" } }),
163
+ ],
164
+ };
165
+ // ------------------------------------------------------------------ Qoder CLI
166
+ const QODER = home(".qoder");
167
+ const qoderSettings = {
168
+ user: () => path.join(QODER, "settings.json"),
169
+ project: (c) => path.join(c.root, ".qoder", "settings.json"),
170
+ local: (c) => path.join(c.root, ".qoder", "settings.local.json"),
171
+ };
172
+ export const qoder = {
173
+ id: "qoder",
174
+ name: "Qoder CLI",
175
+ bins: ["qodercli", "qoder"],
176
+ dirs: [".qoder"],
177
+ sections: [
178
+ mcpSection({ agent: "qoder", files: qoderSettings, key: ["mcpServers"], disable: { type: "stash" } }),
179
+ dirSection({ kind: "skills", dirs: { user: () => path.join(QODER, "skills"), project: (c) => path.join(c.root, ".qoder", "skills") }, entry: { dir: "SKILL.md" } }),
180
+ dirSection({ kind: "commands", dirs: { user: () => path.join(QODER, "commands"), project: (c) => path.join(c.root, ".qoder", "commands") }, entry: { ext: [".md"] } }),
181
+ dirSection({ kind: "agents", dirs: { user: () => path.join(QODER, "agents"), project: (c) => path.join(c.root, ".qoder", "agents") }, entry: { ext: [".md"] } }),
182
+ ],
183
+ };
184
+ // ------------------------------------------------------------------ CodeBuddy Code (Tencent)
185
+ const CB = process.env.CODEBUDDY_CONFIG_DIR ?? home(".codebuddy");
186
+ const cbSettings = {
187
+ user: () => path.join(CB, "settings.json"),
188
+ project: (c) => path.join(c.root, ".codebuddy", "settings.json"),
189
+ local: (c) => path.join(c.root, ".codebuddy", "settings.local.json"),
190
+ };
191
+ export const codebuddy = {
192
+ id: "codebuddy",
193
+ name: "CodeBuddy Code",
194
+ bins: ["codebuddy"],
195
+ dirs: [".codebuddy"],
196
+ sections: [
197
+ mcpSection({ agent: "codebuddy", files: { user: () => path.join(CB, ".mcp.json"), project: (c) => path.join(c.root, ".mcp.json") }, key: ["mcpServers"], disable: { type: "stash" } }),
198
+ boolMapSection({ kind: "plugins", files: cbSettings, path: ["enabledPlugins"], discover: () => [] }),
199
+ dirSection({ kind: "skills", dirs: { user: () => path.join(CB, "skills"), project: (c) => path.join(c.root, ".codebuddy", "skills") }, entry: { dir: "SKILL.md" } }),
200
+ hooksSection({ agent: "codebuddy", files: cbSettings, key: ["hooks"] }),
201
+ dirSection({ kind: "commands", dirs: { user: () => path.join(CB, "commands"), project: (c) => path.join(c.root, ".codebuddy", "commands") }, entry: { ext: [".md"] } }),
202
+ dirSection({ kind: "agents", dirs: { user: () => path.join(CB, "agents"), project: (c) => path.join(c.root, ".codebuddy", "agents") }, entry: { ext: [".md"] } }),
203
+ ],
204
+ };
205
+ // ------------------------------------------------------------------ Command Code
206
+ export const commandcode = {
207
+ id: "commandcode",
208
+ name: "Command Code",
209
+ bins: ["commandcode", "cmd-code"],
210
+ dirs: [".commandcode"],
211
+ sections: [
212
+ mcpSection({ agent: "commandcode", files: { user: () => home(".commandcode", "mcp.json") }, key: ["mcpServers"], disable: { type: "stash" } }),
213
+ hooksSection({ agent: "commandcode", files: { user: () => home(".commandcode", "settings.json") }, key: ["hooks"] }),
214
+ ],
215
+ };
216
+ // ------------------------------------------------------------------ detected, nothing to toggle
217
+ export const aider = { id: "aider", name: "Aider", bins: ["aider"], dirs: [], sections: [], notes: ["notes.aider.none"] };
218
+ export const plandex = { id: "plandex", name: "Plandex", bins: ["plandex", "pdx"], dirs: [".plandex-home-v2"], sections: [], notes: ["notes.plandex.none"] };
219
+ // ------------------------------------------------------------------ Goose
220
+ /** Goose keeps its YAML config under %APPDATA%\Block\goose\config on Windows. */
221
+ const GOOSE = process.env.GOOSE_PATH_ROOT
222
+ ? path.join(process.env.GOOSE_PATH_ROOT, "config")
223
+ : process.platform === "win32" ? path.join(appData(), "Block", "goose", "config") : xdgConfig("goose");
224
+ const gooseSettings = {
225
+ user: () => (process.env.GOOSE_PATH_ROOT ? path.join(process.env.GOOSE_PATH_ROOT, ".config", "goose", "settings.json") : home(".config", "goose", "settings.json")),
226
+ project: (c) => path.join(c.root, ".config", "goose", "settings.json"),
227
+ local: (c) => path.join(c.root, ".config", "goose", "settings.local.json"),
228
+ };
229
+ export const goose = {
230
+ id: "goose",
231
+ name: "Goose",
232
+ bins: ["goose"],
233
+ dirs: [],
234
+ sections: [
235
+ mcpSection({
236
+ agent: "goose",
237
+ files: { user: () => path.join(GOOSE, "config.yaml") },
238
+ key: ["extensions"],
239
+ disable: { type: "flag", key: "enabled", off: false },
240
+ io: YAML_IO,
241
+ }),
242
+ listSection({
243
+ kind: "plugins",
244
+ files: gooseSettings,
245
+ path: ["disabledPlugins"],
246
+ discover: (ctx, scope) => dirNames(scope === "user" ? home(".agents", "plugins") : path.join(ctx.root, ".agents", "plugins")).map((id) => ({ id })),
247
+ }),
248
+ ],
249
+ notes: ["notes.goose.plugins"],
250
+ };
251
+ // ------------------------------------------------------------------ Cline CLI
252
+ const CLINE = process.env.CLINE_DIR ?? home(".cline");
253
+ export const cline = {
254
+ id: "cline",
255
+ name: "Cline CLI",
256
+ bins: ["cline"],
257
+ dirs: [".cline"],
258
+ sections: [
259
+ mcpSection({
260
+ agent: "cline",
261
+ files: { user: () => process.env.CLINE_MCP_SETTINGS_PATH ?? path.join(CLINE, "data", "settings", "cline_mcp_settings.json") },
262
+ key: ["mcpServers"],
263
+ disable: { type: "flag", key: "disabled", off: true },
264
+ }),
265
+ frontmatterSkillsSection({ dirs: { user: () => path.join(CLINE, "skills"), project: (c) => path.join(c.root, ".cline", "skills") } }),
266
+ dirSection({ kind: "hooks", title: "title.hookFiles", dirs: { user: () => path.join(CLINE, "hooks"), project: (c) => path.join(c.root, ".cline", "hooks") }, entry: { ext: [".sh", ".js", ".ts", ".ps1"] } }),
267
+ dirSection({ kind: "commands", title: "title.workflows", dirs: { user: () => path.join(CLINE, "workflows"), project: (c) => path.join(c.root, ".cline", "workflows") }, entry: { ext: [".md"] } }),
268
+ dirSection({ kind: "agents", dirs: { user: () => path.join(CLINE, "agents"), project: (c) => path.join(c.root, ".cline", "agents") }, entry: { ext: [".md"] } }),
269
+ ],
270
+ };
271
+ // ------------------------------------------------------------------ Continue CLI
272
+ const CONTINUE = process.env.CONTINUE_GLOBAL_DIR ?? home(".continue");
273
+ const continueYaml = () => path.join(CONTINUE, "config.yaml");
274
+ /**
275
+ * Continue lists its MCP servers as a YAML array (mcpServers: [{ name, … }])
276
+ * without any enabled flag: a disabled server is taken out of the array and
277
+ * kept in the stash, then appended back.
278
+ */
279
+ const continueMcp = {
280
+ kind: "mcp",
281
+ scopes: ["user"],
282
+ note: () => `${shortPath(continueYaml())} · ${t("note.noNativeStash")}`,
283
+ list() {
284
+ const file = continueYaml();
285
+ const items = (getPath(readYaml(file), ["mcpServers"]) ?? []).map((d) => ({
286
+ id: String(d.name), label: String(d.name), hint: describeServer(d), group: mcpGroup(String(d.name)), enabled: true,
287
+ }));
288
+ for (const e of stashed("continue", file))
289
+ items.push({ id: String(e.value.name), label: String(e.value.name), hint: `${describeServer(e.value)} · ${t("hint.stash")}`, group: mcpGroup(String(e.value.name)), enabled: false });
290
+ return sortByGroup(items);
291
+ },
292
+ set(_ctx, _scope, item, enabled) {
293
+ const file = continueYaml();
294
+ const list = getPath(readYaml(file), ["mcpServers"]) ?? [];
295
+ const label = `MCP ${item.id}`;
296
+ if (!enabled) {
297
+ const def = list.find((d) => String(d.name) === item.id);
298
+ if (!def)
299
+ return;
300
+ updateStash(t("change.stashed", { what: label }), (s) => s.entries.push({ agent: "continue", file, kind: "array", path: ["mcpServers"], value: def }));
301
+ const rest = list.filter((d) => String(d.name) !== item.id);
302
+ editYaml(file, toggled(label, false, shortPath(file)), [{ path: ["mcpServers"], value: rest.length ? rest : undefined }]);
303
+ }
304
+ else {
305
+ const entry = stashed("continue", file).find((e) => String(e.value.name) === item.id);
306
+ if (!entry)
307
+ return;
308
+ editYaml(file, toggled(label, true, shortPath(file)), [{ path: ["mcpServers"], value: [...list, entry.value] }]);
309
+ updateStash(t("change.unstashed", { what: label }), (s) => { s.entries = s.entries.filter((e) => !sameEntry(e, entry)); });
310
+ }
311
+ },
312
+ };
313
+ export const continueCli = {
314
+ id: "continue",
315
+ name: "Continue CLI",
316
+ bins: ["cn"],
317
+ dirs: [".continue"],
318
+ sections: [
319
+ continueMcp,
320
+ dirSection({ kind: "skills", dirs: { user: () => path.join(CONTINUE, "skills"), project: (c) => path.join(c.root, ".continue", "skills") }, entry: { dir: "SKILL.md" } }),
321
+ hooksSection({
322
+ agent: "continue",
323
+ files: {
324
+ user: () => path.join(CONTINUE, "settings.json"),
325
+ project: (c) => path.join(c.root, ".continue", "settings.json"),
326
+ local: (c) => path.join(c.root, ".continue", "settings.local.json"),
327
+ },
328
+ key: ["hooks"],
329
+ disableAll: { path: ["disableAllHooks"], off: true },
330
+ }),
331
+ ],
332
+ notes: ["notes.continue.maintenance"],
333
+ };
334
+ // ------------------------------------------------------------------ Augment Auggie CLI
335
+ const AUG = home(".augment");
336
+ const augSettings = {
337
+ user: () => path.join(AUG, "settings.json"),
338
+ project: (c) => path.join(c.root, ".augment", "settings.json"),
339
+ local: (c) => path.join(c.root, ".augment", "settings.local.json"),
340
+ };
341
+ export const auggie = {
342
+ id: "auggie",
343
+ name: "Augment Auggie CLI",
344
+ bins: ["auggie"],
345
+ dirs: [".augment"],
346
+ sections: [
347
+ mcpSection({ agent: "auggie", files: augSettings, key: ["mcpServers"], disable: { type: "stash" } }),
348
+ boolMapSection({ kind: "plugins", files: augSettings, path: ["enabledPlugins"], discover: () => [] }),
349
+ dirSection({ kind: "skills", dirs: { user: () => path.join(AUG, "skills"), project: (c) => path.join(c.root, ".augment", "skills") }, entry: { dir: "SKILL.md" } }),
350
+ hooksSection({ agent: "auggie", files: augSettings, key: ["hooks"] }),
351
+ dirSection({ kind: "commands", dirs: { user: () => path.join(AUG, "commands"), project: (c) => path.join(c.root, ".augment", "commands") }, entry: { ext: [".md"] } }),
352
+ dirSection({ kind: "agents", dirs: { user: () => path.join(AUG, "agents"), project: (c) => path.join(c.root, ".augment", "agents") }, entry: { ext: [".md"] } }),
353
+ ],
354
+ };
355
+ // ------------------------------------------------------------------ OpenHands CLI
356
+ const OH = process.env.OPENHANDS_PERSISTENCE_DIR ?? home(".openhands");
357
+ export const openhands = {
358
+ id: "openhands",
359
+ name: "OpenHands CLI",
360
+ bins: ["openhands"],
361
+ dirs: [".openhands"],
362
+ sections: [
363
+ mcpSection({
364
+ agent: "openhands",
365
+ files: { user: () => path.join(OH, "mcp.json") },
366
+ key: ["mcpServers"],
367
+ disable: { type: "flag", key: "enabled", off: false },
368
+ }),
369
+ dirSection({ kind: "skills", dirs: { user: () => path.join(OH, "skills"), project: (c) => path.join(c.root, ".openhands", "skills") }, entry: { dir: "SKILL.md" } }),
370
+ dirSection({ kind: "agents", dirs: { user: () => path.join(OH, "agents"), project: (c) => path.join(c.root, ".openhands", "agents") }, entry: { ext: [".md"] } }),
371
+ ],
372
+ };
373
+ // ------------------------------------------------------------------ Kimi CLI
374
+ const KIMI = process.env.KIMI_SHARE_DIR ?? home(".kimi");
375
+ export const kimi = {
376
+ id: "kimi",
377
+ name: "Kimi CLI",
378
+ bins: ["kimi", "kimi-cli"],
379
+ dirs: [".kimi"],
380
+ sections: [
381
+ mcpSection({ agent: "kimi", files: { user: () => path.join(KIMI, "mcp.json") }, key: ["mcpServers"], disable: { type: "stash" } }),
382
+ dirSection({ kind: "plugins", dirs: { user: () => path.join(KIMI, "plugins") }, entry: { dir: "plugin.json" } }),
383
+ dirSection({ kind: "skills", dirs: { user: () => home(".kimi", "skills"), project: (c) => path.join(c.root, ".kimi", "skills") }, entry: { dir: "SKILL.md" } }),
384
+ ],
385
+ };
386
+ // ------------------------------------------------------------------ Mistral Vibe
387
+ const VIBE = process.env.VIBE_HOME ?? home(".vibe");
388
+ const vibeConfig = { user: () => path.join(VIBE, "config.toml"), project: (c) => path.join(c.root, ".vibe", "config.toml") };
389
+ const vibeFor = (scope, ctx) => (scope === "user" ? vibeConfig.user() : vibeConfig.project(ctx));
390
+ /** MCP: [[mcp_servers]] blocks identified by name, with a native disabled = true. */
391
+ const vibeMcp = {
392
+ kind: "mcp",
393
+ scopes: ["user", "project"],
394
+ note: (s, c) => `${shortPath(vibeFor(s, c))} · [[mcp_servers]] disabled = true`,
395
+ list(ctx, scope) {
396
+ const servers = readToml(vibeFor(scope, ctx)).mcp_servers ?? [];
397
+ return sortByGroup(servers.filter((d) => d?.name).map((d) => ({
398
+ id: String(d.name), label: String(d.name), hint: describeServer(d), group: mcpGroup(String(d.name)), enabled: d.disabled !== true,
399
+ })));
400
+ },
401
+ set(ctx, scope, item, enabled) {
402
+ const file = vibeFor(scope, ctx);
403
+ setArrayTableKey(file, ["mcp_servers"], (d) => String(d.name) === item.id, "disabled", enabled ? undefined : true, toggled(`MCP ${item.id}`, enabled, shortPath(file)));
404
+ },
405
+ };
406
+ export const vibe = {
407
+ id: "vibe",
408
+ name: "Mistral Vibe",
409
+ bins: ["vibe"],
410
+ dirs: [".vibe"],
411
+ sections: [
412
+ vibeMcp,
413
+ tomlListSection({
414
+ kind: "skills",
415
+ files: vibeConfig,
416
+ table: [],
417
+ key: "disabled_skills",
418
+ discover: (ctx, scope) => scope === "user"
419
+ ? skillsIn([path.join(VIBE, "skills"), home(".agents", "skills")], t("group.user"))
420
+ : skillsIn([path.join(ctx.root, ".vibe", "skills"), path.join(ctx.root, ".agents", "skills")], t("group.project")),
421
+ }),
422
+ tomlListSection({
423
+ kind: "agents",
424
+ files: vibeConfig,
425
+ table: [],
426
+ key: "disabled_agents",
427
+ discover: (ctx, scope) => dirSection({ kind: "agents", dirs: { user: () => (scope === "user" ? path.join(VIBE, "agents") : path.join(ctx.root, ".vibe", "agents")) }, entry: { ext: [".toml"] } })
428
+ .list(ctx, "user").map((i) => ({ id: i.label })),
429
+ }),
430
+ ],
431
+ notes: ["notes.vibe.trust"],
432
+ };
433
+ // ------------------------------------------------------------------ iFlow CLI (discontinued)
434
+ const IFLOW = process.env.IFLOW_HOME ?? home(".iflow");
435
+ const iflowSettings = { user: () => path.join(IFLOW, "settings.json"), project: (c) => path.join(c.root, ".iflow", "settings.json") };
436
+ export const iflow = {
437
+ id: "iflow",
438
+ name: "iFlow CLI",
439
+ bins: ["iflow"],
440
+ dirs: [".iflow"],
441
+ sections: [
442
+ listSection({
443
+ kind: "mcp",
444
+ files: iflowSettings,
445
+ path: ["excludeMCPServers"],
446
+ discover: (ctx) => [iflowSettings.user(), iflowSettings.project(ctx)].flatMap((f) => Object.keys(readJson(f).mcpServers ?? {}).map((id) => ({ id, group: mcpGroup(id) }))),
447
+ }),
448
+ hooksSection({ agent: "iflow", files: iflowSettings, key: ["hooks"] }),
449
+ dirSection({ kind: "commands", dirs: { user: () => path.join(IFLOW, "commands"), project: (c) => path.join(c.root, ".iflow", "commands") }, entry: { ext: [".md", ".toml"] } }),
450
+ dirSection({ kind: "agents", dirs: { user: () => path.join(IFLOW, "agents"), project: (c) => path.join(c.root, ".iflow", "agents") }, entry: { ext: [".md"] } }),
451
+ ],
452
+ notes: ["notes.iflow.discontinued"],
453
+ };
454
+ // ------------------------------------------------------------------ Qodo Command (deprecated)
455
+ export const qodo = {
456
+ id: "qodo",
457
+ name: "Qodo Command",
458
+ bins: ["qodo"],
459
+ dirs: [".qodo"],
460
+ sections: [
461
+ mcpSection({ agent: "qodo", files: { project: (c) => path.join(c.root, "mcp.json") }, key: ["mcpServers"], disable: { type: "stash" } }),
462
+ ],
463
+ notes: ["notes.qodo.deprecated"],
464
+ };
465
+ // ------------------------------------------------------------------ Rovo Dev CLI (Atlassian)
466
+ const ROVO = home(".rovodev");
467
+ export const rovodev = {
468
+ id: "rovodev",
469
+ name: "Rovo Dev CLI",
470
+ bins: [],
471
+ dirs: [".rovodev"],
472
+ sections: [
473
+ listSection({
474
+ kind: "mcp",
475
+ files: { user: () => path.join(ROVO, "config.yml") },
476
+ path: ["mcp", "disabledMcpServers"],
477
+ io: YAML_IO,
478
+ discover: () => ["mcp.json", "mcp_config.json"].flatMap((f) => Object.keys(readJson(path.join(ROVO, f)).mcpServers ?? {}).map((id) => ({ id, group: mcpGroup(id) }))),
479
+ }),
480
+ dirSection({ kind: "skills", dirs: { user: () => path.join(ROVO, "skills"), project: (c) => path.join(c.root, ".rovodev", "skills") }, entry: { dir: "SKILL.md" } }),
481
+ dirSection({ kind: "agents", dirs: { user: () => path.join(ROVO, "subagents"), project: (c) => path.join(c.root, ".rovodev", "subagents") }, entry: { ext: [".md"] } }),
482
+ ],
483
+ };