@agents-dev/cli 0.7.7

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 (152) hide show
  1. package/AGENTS.md +400 -0
  2. package/CHANGELOG.md +297 -0
  3. package/CONTRIBUTING.md +164 -0
  4. package/LICENSE +21 -0
  5. package/README.md +117 -0
  6. package/bin/agents +24 -0
  7. package/dist/cli.d.ts +1 -0
  8. package/dist/cli.js +282 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/commands/connect.d.ts +7 -0
  11. package/dist/commands/connect.js +48 -0
  12. package/dist/commands/connect.js.map +1 -0
  13. package/dist/commands/disconnect.d.ts +7 -0
  14. package/dist/commands/disconnect.js +47 -0
  15. package/dist/commands/disconnect.js.map +1 -0
  16. package/dist/commands/doctor.d.ts +6 -0
  17. package/dist/commands/doctor.js +430 -0
  18. package/dist/commands/doctor.js.map +1 -0
  19. package/dist/commands/init.d.ts +5 -0
  20. package/dist/commands/init.js +24 -0
  21. package/dist/commands/init.js.map +1 -0
  22. package/dist/commands/mcp-add.d.ts +20 -0
  23. package/dist/commands/mcp-add.js +250 -0
  24. package/dist/commands/mcp-add.js.map +1 -0
  25. package/dist/commands/mcp-import.d.ts +13 -0
  26. package/dist/commands/mcp-import.js +207 -0
  27. package/dist/commands/mcp-import.js.map +1 -0
  28. package/dist/commands/mcp-list.d.ts +5 -0
  29. package/dist/commands/mcp-list.js +34 -0
  30. package/dist/commands/mcp-list.js.map +1 -0
  31. package/dist/commands/mcp-remove.d.ts +7 -0
  32. package/dist/commands/mcp-remove.js +34 -0
  33. package/dist/commands/mcp-remove.js.map +1 -0
  34. package/dist/commands/mcp-test.d.ts +8 -0
  35. package/dist/commands/mcp-test.js +402 -0
  36. package/dist/commands/mcp-test.js.map +1 -0
  37. package/dist/commands/reset.d.ts +6 -0
  38. package/dist/commands/reset.js +76 -0
  39. package/dist/commands/reset.js.map +1 -0
  40. package/dist/commands/start.d.ts +6 -0
  41. package/dist/commands/start.js +292 -0
  42. package/dist/commands/start.js.map +1 -0
  43. package/dist/commands/status.d.ts +7 -0
  44. package/dist/commands/status.js +278 -0
  45. package/dist/commands/status.js.map +1 -0
  46. package/dist/commands/sync.d.ts +6 -0
  47. package/dist/commands/sync.js +22 -0
  48. package/dist/commands/sync.js.map +1 -0
  49. package/dist/commands/watch.d.ts +7 -0
  50. package/dist/commands/watch.js +117 -0
  51. package/dist/commands/watch.js.map +1 -0
  52. package/dist/core/claudeCli.d.ts +7 -0
  53. package/dist/core/claudeCli.js +35 -0
  54. package/dist/core/claudeCli.js.map +1 -0
  55. package/dist/core/config.d.ts +17 -0
  56. package/dist/core/config.js +121 -0
  57. package/dist/core/config.js.map +1 -0
  58. package/dist/core/cursorCli.d.ts +9 -0
  59. package/dist/core/cursorCli.js +60 -0
  60. package/dist/core/cursorCli.js.map +1 -0
  61. package/dist/core/fs.d.ts +11 -0
  62. package/dist/core/fs.js +76 -0
  63. package/dist/core/fs.js.map +1 -0
  64. package/dist/core/gitignore.d.ts +3 -0
  65. package/dist/core/gitignore.js +54 -0
  66. package/dist/core/gitignore.js.map +1 -0
  67. package/dist/core/mcp.d.ts +8 -0
  68. package/dist/core/mcp.js +134 -0
  69. package/dist/core/mcp.js.map +1 -0
  70. package/dist/core/mcpCrud.d.ts +34 -0
  71. package/dist/core/mcpCrud.js +105 -0
  72. package/dist/core/mcpCrud.js.map +1 -0
  73. package/dist/core/mcpImport.d.ts +14 -0
  74. package/dist/core/mcpImport.js +507 -0
  75. package/dist/core/mcpImport.js.map +1 -0
  76. package/dist/core/mcpSecrets.d.ts +27 -0
  77. package/dist/core/mcpSecrets.js +144 -0
  78. package/dist/core/mcpSecrets.js.map +1 -0
  79. package/dist/core/mcpValidation.d.ts +19 -0
  80. package/dist/core/mcpValidation.js +78 -0
  81. package/dist/core/mcpValidation.js.map +1 -0
  82. package/dist/core/paths.d.ts +37 -0
  83. package/dist/core/paths.js +43 -0
  84. package/dist/core/paths.js.map +1 -0
  85. package/dist/core/project.d.ts +16 -0
  86. package/dist/core/project.js +34 -0
  87. package/dist/core/project.js.map +1 -0
  88. package/dist/core/renderers.d.ts +14 -0
  89. package/dist/core/renderers.js +113 -0
  90. package/dist/core/renderers.js.map +1 -0
  91. package/dist/core/shell.d.ts +8 -0
  92. package/dist/core/shell.js +21 -0
  93. package/dist/core/shell.js.map +1 -0
  94. package/dist/core/shellWords.d.ts +1 -0
  95. package/dist/core/shellWords.js +84 -0
  96. package/dist/core/shellWords.js.map +1 -0
  97. package/dist/core/skills.d.ts +8 -0
  98. package/dist/core/skills.js +150 -0
  99. package/dist/core/skills.js.map +1 -0
  100. package/dist/core/skillsValidation.d.ts +1 -0
  101. package/dist/core/skillsValidation.js +68 -0
  102. package/dist/core/skillsValidation.js.map +1 -0
  103. package/dist/core/sync.d.ts +2 -0
  104. package/dist/core/sync.js +427 -0
  105. package/dist/core/sync.js.map +1 -0
  106. package/dist/core/syncLock.d.ts +1 -0
  107. package/dist/core/syncLock.js +84 -0
  108. package/dist/core/syncLock.js.map +1 -0
  109. package/dist/core/templates.d.ts +1 -0
  110. package/dist/core/templates.js +38 -0
  111. package/dist/core/templates.js.map +1 -0
  112. package/dist/core/trust.d.ts +7 -0
  113. package/dist/core/trust.js +51 -0
  114. package/dist/core/trust.js.map +1 -0
  115. package/dist/core/vscodeSettings.d.ts +17 -0
  116. package/dist/core/vscodeSettings.js +212 -0
  117. package/dist/core/vscodeSettings.js.map +1 -0
  118. package/dist/core/warnings.d.ts +2 -0
  119. package/dist/core/warnings.js +26 -0
  120. package/dist/core/warnings.js.map +1 -0
  121. package/dist/integrations/antigravity.d.ts +9 -0
  122. package/dist/integrations/antigravity.js +13 -0
  123. package/dist/integrations/antigravity.js.map +1 -0
  124. package/dist/integrations/claude.d.ts +1 -0
  125. package/dist/integrations/claude.js +4 -0
  126. package/dist/integrations/claude.js.map +1 -0
  127. package/dist/integrations/codex.d.ts +5 -0
  128. package/dist/integrations/codex.js +5 -0
  129. package/dist/integrations/codex.js.map +1 -0
  130. package/dist/integrations/copilotVscode.d.ts +7 -0
  131. package/dist/integrations/copilotVscode.js +9 -0
  132. package/dist/integrations/copilotVscode.js.map +1 -0
  133. package/dist/integrations/cursor.d.ts +7 -0
  134. package/dist/integrations/cursor.js +9 -0
  135. package/dist/integrations/cursor.js.map +1 -0
  136. package/dist/integrations/gemini.d.ts +12 -0
  137. package/dist/integrations/gemini.js +15 -0
  138. package/dist/integrations/gemini.js.map +1 -0
  139. package/dist/integrations/registry.d.ts +9 -0
  140. package/dist/integrations/registry.js +21 -0
  141. package/dist/integrations/registry.js.map +1 -0
  142. package/dist/types.d.ts +85 -0
  143. package/dist/types.js +2 -0
  144. package/dist/types.js.map +1 -0
  145. package/docs/EXAMPLES.md +211 -0
  146. package/docs/README.md +26 -0
  147. package/docs/agents-system.md +178 -0
  148. package/package.json +77 -0
  149. package/templates/agents/AGENTS.md +23 -0
  150. package/templates/agents/README.md +25 -0
  151. package/templates/agents/skills/README.md +27 -0
  152. package/templates/agents/skills/skill-guide/SKILL.md +29 -0
@@ -0,0 +1,427 @@
1
+ import path from 'node:path';
2
+ import { ensureDir, pathExists, readJson, readTextOrEmpty, writeJsonAtomic, writeTextAtomic } from './fs.js';
3
+ import { loadAgentsConfig, saveAgentsConfig } from './config.js';
4
+ import { loadResolvedRegistry } from './mcp.js';
5
+ import { getProjectPaths } from './paths.js';
6
+ import { commandExists, runCommand } from './shell.js';
7
+ import { buildCodexConfig } from '../integrations/codex.js';
8
+ import { toManagedClaudeName } from '../integrations/claude.js';
9
+ import { buildGeminiPayload } from '../integrations/gemini.js';
10
+ import { buildVscodeMcpPayload } from '../integrations/copilotVscode.js';
11
+ import { buildCursorPayload } from '../integrations/cursor.js';
12
+ import { buildAntigravityPayload } from '../integrations/antigravity.js';
13
+ import { renderVscodeMcp } from './renderers.js';
14
+ import { ensureProjectGitignore } from './gitignore.js';
15
+ import { syncSkills } from './skills.js';
16
+ import { syncVscodeSettings } from './vscodeSettings.js';
17
+ import { listCursorMcpStatuses } from './cursorCli.js';
18
+ import { listClaudeManagedServerNames } from './claudeCli.js';
19
+ import { validateEnvKey, validateEnvValueForShell, validateHeaderKey, validateServerName } from './mcpValidation.js';
20
+ import { acquireSyncLock } from './syncLock.js';
21
+ export async function performSync(options) {
22
+ const { projectRoot, check, verbose } = options;
23
+ const paths = getProjectPaths(projectRoot);
24
+ const releaseLock = await acquireSyncLock(paths.generatedSyncLock);
25
+ try {
26
+ const config = await loadAgentsConfig(projectRoot);
27
+ const resolved = await loadResolvedRegistry(projectRoot);
28
+ const warnings = [...resolved.warnings];
29
+ if (resolved.missingRequiredEnv.length > 0) {
30
+ warnings.push(`Skipped servers because required env vars are missing: ${resolved.missingRequiredEnv.join('; ')}`);
31
+ }
32
+ validateResolvedServers(resolved.serversByTarget);
33
+ const changed = [];
34
+ if (!check) {
35
+ const gitignoreChanged = await ensureProjectGitignore(projectRoot, config.syncMode);
36
+ if (gitignoreChanged) {
37
+ changed.push('.gitignore');
38
+ }
39
+ }
40
+ await ensureDir(paths.generatedDir);
41
+ await syncGeneratedFiles({
42
+ projectRoot,
43
+ check,
44
+ changed,
45
+ warnings,
46
+ resolvedByTarget: resolved.serversByTarget
47
+ });
48
+ const enabled = new Set(config.integrations.enabled);
49
+ if (enabled.has('codex')) {
50
+ await materializeCodex(paths.generatedCodex, paths.codexConfig, check, changed);
51
+ }
52
+ if (enabled.has('gemini')) {
53
+ await materializeGemini(paths.generatedGemini, paths.geminiSettings, check, changed);
54
+ }
55
+ if (enabled.has('copilot_vscode')) {
56
+ await materializeCopilot(paths.generatedCopilot, paths.vscodeMcp, check, changed);
57
+ }
58
+ if (enabled.has('cursor')) {
59
+ await materializeCursor(paths.generatedCursor, paths.cursorMcp, check, changed);
60
+ }
61
+ if (enabled.has('antigravity')) {
62
+ await materializeAntigravityProject(paths.generatedAntigravity, paths.antigravityProjectMcp, check, changed);
63
+ }
64
+ await syncClaude({
65
+ enabled: enabled.has('claude'),
66
+ check,
67
+ projectRoot,
68
+ servers: resolved.serversByTarget.claude,
69
+ statePath: paths.generatedClaudeState,
70
+ changed,
71
+ warnings
72
+ });
73
+ await syncCursor({
74
+ enabled: enabled.has('cursor'),
75
+ autoApprove: config.integrations.options.cursorAutoApprove,
76
+ check,
77
+ projectRoot,
78
+ servers: resolved.serversByTarget.cursor,
79
+ statePath: paths.generatedCursorState,
80
+ changed,
81
+ warnings
82
+ });
83
+ await syncSkills({
84
+ projectRoot,
85
+ enabledIntegrations: config.integrations.enabled,
86
+ check,
87
+ changed,
88
+ warnings
89
+ });
90
+ await syncVscodeSettings({
91
+ settingsPath: paths.vscodeSettings,
92
+ statePath: paths.generatedVscodeSettingsState,
93
+ hiddenPaths: config.workspace.vscode.hiddenPaths,
94
+ hideGenerated: config.workspace.vscode.hideGenerated,
95
+ check,
96
+ changed,
97
+ warnings,
98
+ projectRoot
99
+ });
100
+ if (!check) {
101
+ config.lastSync = new Date().toISOString();
102
+ await saveAgentsConfig(projectRoot, config);
103
+ }
104
+ if (verbose && changed.length > 0) {
105
+ for (const entry of changed) {
106
+ process.stdout.write(`updated: ${entry}\n`);
107
+ }
108
+ }
109
+ return {
110
+ changed: uniqueSorted(changed),
111
+ warnings: uniqueSorted(warnings)
112
+ };
113
+ }
114
+ finally {
115
+ await releaseLock();
116
+ }
117
+ }
118
+ async function syncGeneratedFiles(args) {
119
+ const { projectRoot, check, changed, warnings, resolvedByTarget } = args;
120
+ const paths = getProjectPaths(projectRoot);
121
+ const codex = buildCodexConfig(resolvedByTarget.codex);
122
+ warnings.push(...codex.warnings);
123
+ await writeManagedFile(paths.generatedCodex, codex.content, projectRoot, check, changed);
124
+ const gemini = buildGeminiPayload(resolvedByTarget.gemini);
125
+ warnings.push(...gemini.warnings);
126
+ await writeManagedFile(paths.generatedGemini, `${JSON.stringify(gemini.payload, null, 2)}\n`, projectRoot, check, changed);
127
+ const copilot = buildVscodeMcpPayload(resolvedByTarget.copilot_vscode);
128
+ warnings.push(...copilot.warnings);
129
+ await writeManagedFile(paths.generatedCopilot, `${JSON.stringify(copilot.payload, null, 2)}\n`, projectRoot, check, changed);
130
+ const cursor = buildCursorPayload(resolvedByTarget.cursor);
131
+ warnings.push(...cursor.warnings);
132
+ await writeManagedFile(paths.generatedCursor, `${JSON.stringify(cursor.payload, null, 2)}\n`, projectRoot, check, changed);
133
+ const antigravity = buildAntigravityPayload(resolvedByTarget.antigravity);
134
+ warnings.push(...antigravity.warnings);
135
+ await writeManagedFile(paths.generatedAntigravity, `${JSON.stringify(antigravity.payload, null, 2)}\n`, projectRoot, check, changed);
136
+ const claude = renderVscodeMcp(resolvedByTarget.claude);
137
+ warnings.push(...claude.warnings);
138
+ await writeManagedFile(paths.generatedClaude, `${JSON.stringify({ mcpServers: claude.servers }, null, 2)}\n`, projectRoot, check, changed);
139
+ }
140
+ async function materializeCodex(generatedPath, targetPath, check, changed) {
141
+ const content = await readTextOrEmpty(generatedPath);
142
+ await writeManagedFile(targetPath, content, path.dirname(path.dirname(targetPath)), check, changed);
143
+ }
144
+ async function materializeGemini(generatedPath, targetPath, check, changed) {
145
+ const rawGenerated = await readTextOrEmpty(generatedPath);
146
+ let generated = {};
147
+ if (rawGenerated.trim()) {
148
+ try {
149
+ generated = JSON.parse(rawGenerated);
150
+ }
151
+ catch (error) {
152
+ throw new Error(`Failed to parse generated Gemini config: ${error instanceof Error ? error.message : String(error)}`);
153
+ }
154
+ }
155
+ let existing = {};
156
+ if (await pathExists(targetPath)) {
157
+ try {
158
+ existing = await readJson(targetPath);
159
+ }
160
+ catch (error) {
161
+ // Warn instead of silently ignoring - corrupted files should be noticed
162
+ console.warn(`Warning: Failed to read existing Gemini config at ${targetPath}, starting fresh. Error: ${error instanceof Error ? error.message : String(error)}`);
163
+ existing = {};
164
+ }
165
+ }
166
+ const merged = {
167
+ ...existing,
168
+ context: {
169
+ ...(typeof existing.context === 'object' && existing.context !== null
170
+ ? existing.context
171
+ : {}),
172
+ fileName: 'AGENTS.md'
173
+ },
174
+ contextFileName: generated.contextFileName,
175
+ mcpServers: generated.mcpServers
176
+ };
177
+ await writeManagedFile(targetPath, `${JSON.stringify(merged, null, 2)}\n`, path.dirname(path.dirname(targetPath)), check, changed);
178
+ }
179
+ async function materializeCopilot(generatedPath, targetPath, check, changed) {
180
+ const content = await readTextOrEmpty(generatedPath);
181
+ await writeManagedFile(targetPath, content, path.dirname(path.dirname(targetPath)), check, changed);
182
+ }
183
+ async function materializeCursor(generatedPath, targetPath, check, changed) {
184
+ const content = await readTextOrEmpty(generatedPath);
185
+ await writeManagedFile(targetPath, content, path.dirname(path.dirname(targetPath)), check, changed);
186
+ }
187
+ async function materializeAntigravityProject(generatedPath, targetPath, check, changed) {
188
+ const content = await readTextOrEmpty(generatedPath);
189
+ await writeManagedFile(targetPath, content, path.dirname(path.dirname(targetPath)), check, changed);
190
+ }
191
+ async function syncClaude(args) {
192
+ const { enabled, check, projectRoot, servers, statePath, changed, warnings } = args;
193
+ const command = 'claude';
194
+ const state = (await pathExists(statePath))
195
+ ? await readJson(statePath)
196
+ : { managedNames: [] };
197
+ // Validate all server names before using them in commands
198
+ for (const server of servers) {
199
+ validateServerName(server.name);
200
+ }
201
+ const desiredNames = enabled ? servers.map((server) => toManagedClaudeName(server.name)) : [];
202
+ let currentNames = state.managedNames ?? [];
203
+ const hasClaudeCli = commandExists(command);
204
+ if (hasClaudeCli) {
205
+ const listed = listClaudeManagedServerNames(projectRoot);
206
+ if (listed.ok) {
207
+ currentNames = listed.names;
208
+ }
209
+ else {
210
+ warnings.push(`Failed checking Claude MCP status: ${compactError(listed.stderr)}`);
211
+ }
212
+ }
213
+ if (equalSets(new Set(currentNames), new Set(desiredNames))) {
214
+ return;
215
+ }
216
+ changed.push('claude-local-scope');
217
+ if (check)
218
+ return;
219
+ if (!hasClaudeCli) {
220
+ warnings.push('Claude CLI not found; skipped Claude MCP sync.');
221
+ return;
222
+ }
223
+ // Remove servers that exist in current but not in desired (proper set difference)
224
+ const namesToRemove = currentNames.filter((name) => !desiredNames.includes(name));
225
+ for (const name of namesToRemove) {
226
+ const removed = runCommand(command, ['mcp', 'remove', '-s', 'local', name], projectRoot);
227
+ if (!removed.ok &&
228
+ !removed.stderr.includes('not found') &&
229
+ !removed.stderr.includes('No project-local MCP server found')) {
230
+ warnings.push(`Failed removing Claude MCP server ${name}: ${compactError(removed.stderr)}`);
231
+ }
232
+ }
233
+ if (!enabled) {
234
+ await writeJsonAtomic(statePath, { managedNames: [] });
235
+ return;
236
+ }
237
+ const appliedNames = [];
238
+ for (const server of servers) {
239
+ const name = toManagedClaudeName(server.name);
240
+ const result = addClaudeServer(command, projectRoot, name, server);
241
+ if (!result.ok) {
242
+ warnings.push(`Failed adding Claude MCP server ${name}: ${compactError(result.stderr)}`);
243
+ continue;
244
+ }
245
+ appliedNames.push(name);
246
+ }
247
+ await ensureDir(path.dirname(statePath));
248
+ await writeJsonAtomic(statePath, { managedNames: appliedNames });
249
+ }
250
+ async function syncCursor(args) {
251
+ const { enabled, autoApprove, check, projectRoot, servers, statePath, changed, warnings } = args;
252
+ const command = 'cursor-agent';
253
+ const state = (await pathExists(statePath))
254
+ ? await readJson(statePath)
255
+ : { managedNames: [] };
256
+ // Validate all server names before using them in commands
257
+ for (const server of servers) {
258
+ validateServerName(server.name);
259
+ }
260
+ const desiredNames = enabled ? servers.map((server) => server.name) : [];
261
+ const currentNames = state.managedNames ?? [];
262
+ const hasCursorCli = commandExists(command);
263
+ let namesNeedingApproval = new Set();
264
+ if (enabled && autoApprove && hasCursorCli) {
265
+ const listed = listCursorMcpStatuses(projectRoot);
266
+ if (!listed.ok) {
267
+ warnings.push(`Failed checking Cursor MCP status: ${compactError(listed.stderr)}`);
268
+ }
269
+ else {
270
+ const unknownStatuses = [];
271
+ const errorStatuses = [];
272
+ namesNeedingApproval = new Set();
273
+ for (const name of desiredNames) {
274
+ const status = listed.statuses[name];
275
+ if (status === undefined) {
276
+ namesNeedingApproval.add(name);
277
+ continue;
278
+ }
279
+ if (status === 'needs-approval' || status === 'disabled') {
280
+ namesNeedingApproval.add(name);
281
+ continue;
282
+ }
283
+ if (status === 'unknown') {
284
+ unknownStatuses.push(name);
285
+ continue;
286
+ }
287
+ if (status === 'error') {
288
+ errorStatuses.push(name);
289
+ }
290
+ }
291
+ if (unknownStatuses.length > 0) {
292
+ warnings.push(`Cursor MCP status unknown for: ${unknownStatuses.join(', ')}. Skipping auto-approval retries for these servers.`);
293
+ }
294
+ if (errorStatuses.length > 0) {
295
+ warnings.push(`Cursor MCP connection errors for: ${errorStatuses.join(', ')}. Skipping auto-approval retries for these servers.`);
296
+ }
297
+ }
298
+ }
299
+ if (equalSets(new Set(currentNames), new Set(desiredNames))
300
+ && namesNeedingApproval.size === 0) {
301
+ return;
302
+ }
303
+ changed.push('cursor-local-approval');
304
+ if (check)
305
+ return;
306
+ if (!hasCursorCli) {
307
+ warnings.push('Cursor CLI not found; skipped Cursor MCP approval sync.');
308
+ return;
309
+ }
310
+ const toDisable = currentNames.filter((name) => !desiredNames.includes(name));
311
+ for (const name of toDisable) {
312
+ const result = runCommand(command, ['mcp', 'disable', name], projectRoot);
313
+ if (!result.ok && !result.stderr.toLowerCase().includes('not found')) {
314
+ warnings.push(`Failed disabling Cursor MCP server ${name}: ${compactError(result.stderr)}`);
315
+ }
316
+ }
317
+ if (!enabled || !autoApprove) {
318
+ await writeJsonAtomic(statePath, { managedNames: desiredNames });
319
+ return;
320
+ }
321
+ const approved = [];
322
+ for (const name of desiredNames) {
323
+ if (!namesNeedingApproval.has(name)) {
324
+ approved.push(name);
325
+ continue;
326
+ }
327
+ const result = runCommand(command, ['mcp', 'enable', name], projectRoot);
328
+ if (!result.ok && !isCursorAlreadyEnabledError(result.stderr)) {
329
+ warnings.push(`Failed enabling Cursor MCP server ${name}: ${compactError(result.stderr)}`);
330
+ continue;
331
+ }
332
+ approved.push(name);
333
+ }
334
+ await ensureDir(path.dirname(statePath));
335
+ await writeJsonAtomic(statePath, { managedNames: approved });
336
+ }
337
+ function addClaudeServer(command, projectRoot, name, server) {
338
+ if (server.transport === 'stdio') {
339
+ if (!server.command) {
340
+ return { ok: false, stderr: 'missing command' };
341
+ }
342
+ const args = ['mcp', 'add', '-s', 'local', name];
343
+ // Validate environment variables before using them
344
+ for (const [key, value] of Object.entries(server.env ?? {})) {
345
+ validateEnvValueForShell(key, value, 'environment variable');
346
+ args.push('-e', `${key}=${value}`);
347
+ }
348
+ args.push('--', server.command, ...(server.args ?? []));
349
+ const result = runCommand(command, args, projectRoot);
350
+ if (!result.ok && isClaudeAlreadyExistsError(result.stderr)) {
351
+ return { ok: true, stderr: result.stderr };
352
+ }
353
+ return { ok: result.ok, stderr: result.stderr };
354
+ }
355
+ if (!server.url) {
356
+ return { ok: false, stderr: 'missing url' };
357
+ }
358
+ const args = ['mcp', 'add', '-s', 'local', '-t', server.transport, name, server.url];
359
+ // Validate headers before using them
360
+ for (const [key, value] of Object.entries(server.headers ?? {})) {
361
+ validateEnvValueForShell(key, value, 'header');
362
+ args.push('-H', `${key}: ${value}`);
363
+ }
364
+ const result = runCommand(command, args, projectRoot);
365
+ if (!result.ok && isClaudeAlreadyExistsError(result.stderr)) {
366
+ return { ok: true, stderr: result.stderr };
367
+ }
368
+ return { ok: result.ok, stderr: result.stderr };
369
+ }
370
+ async function writeManagedFile(absolutePath, content, projectRoot, check, changed) {
371
+ const previous = await readTextOrEmpty(absolutePath);
372
+ if (previous === content)
373
+ return;
374
+ const relative = path.relative(projectRoot, absolutePath) || absolutePath;
375
+ changed.push(relative);
376
+ if (check)
377
+ return;
378
+ await writeTextAtomic(absolutePath, content);
379
+ }
380
+ function equalSets(a, b) {
381
+ if (a.size !== b.size)
382
+ return false;
383
+ for (const value of a) {
384
+ if (!b.has(value))
385
+ return false;
386
+ }
387
+ return true;
388
+ }
389
+ function compactError(stderr) {
390
+ return stderr.trim().split('\n').at(-1) ?? 'unknown error';
391
+ }
392
+ function isClaudeAlreadyExistsError(stderr) {
393
+ return stderr.toLowerCase().includes('already exists in local config');
394
+ }
395
+ function isCursorAlreadyEnabledError(stderr) {
396
+ const lowered = stderr.toLowerCase();
397
+ return lowered.includes('already enabled') || lowered.includes('already approved');
398
+ }
399
+ function validateResolvedServers(resolvedByTarget) {
400
+ for (const [target, servers] of Object.entries(resolvedByTarget)) {
401
+ for (const server of servers) {
402
+ validateServerName(server.name);
403
+ for (const [key, value] of Object.entries(server.env ?? {})) {
404
+ try {
405
+ validateEnvKey(key, 'environment variable');
406
+ }
407
+ catch (error) {
408
+ throw new Error(`Invalid environment variable key "${key}" in server "${server.name}" (target: ${target}): ${error instanceof Error ? error.message : String(error)}`);
409
+ }
410
+ validateEnvValueForShell(key, value, 'environment variable');
411
+ }
412
+ for (const [key, value] of Object.entries(server.headers ?? {})) {
413
+ try {
414
+ validateHeaderKey(key, 'header');
415
+ }
416
+ catch (error) {
417
+ throw new Error(`Invalid header key "${key}" in server "${server.name}" (target: ${target}): ${error instanceof Error ? error.message : String(error)}`);
418
+ }
419
+ validateEnvValueForShell(key, value, 'header');
420
+ }
421
+ }
422
+ }
423
+ }
424
+ function uniqueSorted(values) {
425
+ return [...new Set(values)].sort((a, b) => a.localeCompare(b));
426
+ }
427
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/core/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function acquireSyncLock(lockPath: string, staleMs?: number): Promise<() => Promise<void>>;
@@ -0,0 +1,84 @@
1
+ import { open, readFile, rm, stat } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { ensureDir } from './fs.js';
4
+ const DEFAULT_STALE_MS = 5 * 60_000;
5
+ export async function acquireSyncLock(lockPath, staleMs = DEFAULT_STALE_MS) {
6
+ await ensureDir(path.dirname(lockPath));
7
+ for (let attempt = 0; attempt < 2; attempt += 1) {
8
+ try {
9
+ const handle = await open(lockPath, 'wx');
10
+ try {
11
+ const metadata = {
12
+ pid: process.pid,
13
+ startedAt: new Date().toISOString()
14
+ };
15
+ await handle.writeFile(`${JSON.stringify(metadata)}\n`, 'utf8');
16
+ }
17
+ finally {
18
+ await handle.close();
19
+ }
20
+ return async () => {
21
+ await rm(lockPath, { force: true });
22
+ };
23
+ }
24
+ catch (error) {
25
+ const code = getErrorCode(error);
26
+ if (code !== 'EEXIST') {
27
+ throw error;
28
+ }
29
+ const stale = await isLockStale(lockPath, staleMs);
30
+ if (stale) {
31
+ await rm(lockPath, { force: true });
32
+ continue;
33
+ }
34
+ throw new Error(buildLockBusyMessage(lockPath, await readLockMetadata(lockPath)));
35
+ }
36
+ }
37
+ throw new Error(`Failed to acquire sync lock at ${lockPath}.`);
38
+ }
39
+ function buildLockBusyMessage(lockPath, metadata) {
40
+ if (!metadata) {
41
+ return `Another sync is already running for this project (${lockPath}). Try again in a few seconds.`;
42
+ }
43
+ const parts = [];
44
+ if (typeof metadata.pid === 'number')
45
+ parts.push(`pid=${String(metadata.pid)}`);
46
+ if (typeof metadata.startedAt === 'string' && metadata.startedAt.trim().length > 0) {
47
+ parts.push(`startedAt=${metadata.startedAt}`);
48
+ }
49
+ if (parts.length === 0) {
50
+ return `Another sync is already running for this project (${lockPath}). Try again in a few seconds.`;
51
+ }
52
+ return `Another sync is already running for this project (${lockPath}, ${parts.join(', ')}). Try again in a few seconds.`;
53
+ }
54
+ async function isLockStale(lockPath, staleMs) {
55
+ try {
56
+ const info = await stat(lockPath);
57
+ const ageMs = Date.now() - info.mtimeMs;
58
+ return ageMs > staleMs;
59
+ }
60
+ catch {
61
+ return true;
62
+ }
63
+ }
64
+ async function readLockMetadata(lockPath) {
65
+ try {
66
+ const raw = await readFile(lockPath, 'utf8');
67
+ const parsed = JSON.parse(raw);
68
+ if (typeof parsed !== 'object' || parsed === null)
69
+ return null;
70
+ return parsed;
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ function getErrorCode(value) {
77
+ if (typeof value !== 'object' || value === null)
78
+ return undefined;
79
+ if (!('code' in value))
80
+ return undefined;
81
+ const code = value.code;
82
+ return typeof code === 'string' ? code : undefined;
83
+ }
84
+ //# sourceMappingURL=syncLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syncLock.js","sourceRoot":"","sources":["../../src/core/syncLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAEnC,MAAM,gBAAgB,GAAG,CAAC,GAAG,MAAM,CAAA;AAOnC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB,EAAE,OAAO,GAAG,gBAAgB;IAChF,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEvC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;YACzC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAiB;oBAC7B,GAAG,EAAE,OAAO,CAAC,GAAG;oBAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACpC,CAAA;gBACD,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YACjE,CAAC;oBAAS,CAAC;gBACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;YACtB,CAAC;YAED,OAAO,KAAK,IAAmB,EAAE;gBAC/B,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;YACrC,CAAC,CAAA;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;YAChC,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,MAAM,KAAK,CAAA;YACb,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;YAClD,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;gBACnC,SAAQ;YACV,CAAC;YAED,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,QAAQ,EAAE,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;QACnF,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,GAAG,CAAC,CAAA;AAChE,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAgB,EAAE,QAA6B;IAC3E,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,qDAAqD,QAAQ,gCAAgC,CAAA;IACtG,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,OAAO,QAAQ,CAAC,GAAG,KAAK,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC/E,IAAI,OAAO,QAAQ,CAAC,SAAS,KAAK,QAAQ,IAAI,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnF,KAAK,CAAC,IAAI,CAAC,aAAa,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAA;IAC/C,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,qDAAqD,QAAQ,gCAAgC,CAAA;IACtG,CAAC;IAED,OAAO,qDAAqD,QAAQ,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gCAAgC,CAAA;AAC3H,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,OAAe;IAC1D,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAA;QACjC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QACvC,OAAO,KAAK,GAAG,OAAO,CAAA;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiB,CAAA;QAC9C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,IAAI,CAAA;QAC9D,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAA;IACjE,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA;IACxC,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAA;IAC/C,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;AACpD,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function scaffoldBaseTemplates(projectRoot: string, force: boolean): Promise<string[]>;
@@ -0,0 +1,38 @@
1
+ import path from 'node:path';
2
+ import { copyFile } from 'node:fs/promises';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { ensureDir, pathExists, writeTextAtomic } from './fs.js';
5
+ import { getProjectPaths } from './paths.js';
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+ const TEMPLATE_ROOT = path.resolve(__dirname, '../../templates/agents');
9
+ export async function scaffoldBaseTemplates(projectRoot, force) {
10
+ const paths = getProjectPaths(projectRoot);
11
+ await ensureDir(paths.agentsDir);
12
+ await ensureDir(paths.generatedDir);
13
+ await ensureDir(paths.agentsSkillsDir);
14
+ const pairs = [
15
+ { from: path.join(TEMPLATE_ROOT, 'AGENTS.md'), to: paths.rootAgentsMd },
16
+ { from: path.join(TEMPLATE_ROOT, 'README.md'), to: paths.agentsReadme },
17
+ { from: path.join(TEMPLATE_ROOT, 'skills', 'README.md'), to: path.join(paths.agentsSkillsDir, 'README.md') },
18
+ {
19
+ from: path.join(TEMPLATE_ROOT, 'skills', 'skill-guide', 'SKILL.md'),
20
+ to: path.join(paths.agentsSkillsDir, 'skill-guide', 'SKILL.md')
21
+ }
22
+ ];
23
+ const changed = [];
24
+ for (const pair of pairs) {
25
+ if (!force && (await pathExists(pair.to))) {
26
+ continue;
27
+ }
28
+ await ensureDir(path.dirname(pair.to));
29
+ await copyFile(pair.from, pair.to);
30
+ changed.push(path.relative(projectRoot, pair.to) || pair.to);
31
+ }
32
+ if (!(await pathExists(paths.agentsLocal))) {
33
+ await writeTextAtomic(paths.agentsLocal, '{\n "mcpServers": {}\n}\n');
34
+ changed.push(path.relative(projectRoot, paths.agentsLocal) || paths.agentsLocal);
35
+ }
36
+ return changed;
37
+ }
38
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/core/templates.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACjD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;AAC1C,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,wBAAwB,CAAC,CAAA;AAEvE,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,WAAmB,EAAE,KAAc;IAC7E,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,CAAC,CAAA;IAC1C,MAAM,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IAChC,MAAM,SAAS,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IACnC,MAAM,SAAS,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;IAEtC,MAAM,KAAK,GAAwC;QACjD,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,YAAY,EAAE;QACvE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,YAAY,EAAE;QACvE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,WAAW,CAAC,EAAE;QAC5G;YACE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC;YACnE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,aAAa,EAAE,UAAU,CAAC;SAChE;KACF,CAAA;IAED,MAAM,OAAO,GAAa,EAAE,CAAA;IAE5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YAC1C,SAAQ;QACV,CAAC;QACD,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;QACtC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAA;QAClC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;IAC9D,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QAC3C,MAAM,eAAe,CAAC,KAAK,CAAC,WAAW,EAAE,4BAA4B,CAAC,CAAA;QACtE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,CAAA;IAClF,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type CodexTrustState = 'trusted' | 'untrusted';
2
+ export declare function getCodexConfigPath(): string;
3
+ export declare function getCodexTrustState(projectRoot: string): Promise<CodexTrustState>;
4
+ export declare function ensureCodexProjectTrusted(projectRoot: string): Promise<{
5
+ changed: boolean;
6
+ path: string;
7
+ }>;