@output.ai/cli 0.5.6 → 0.7.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.
Files changed (57) hide show
  1. package/README.md +1 -0
  2. package/dist/api/generated/api.d.ts +25 -0
  3. package/dist/api/generated/api.js +11 -0
  4. package/dist/commands/agents/init.d.ts +0 -1
  5. package/dist/commands/agents/init.js +9 -16
  6. package/dist/commands/agents/init.spec.js +49 -224
  7. package/dist/commands/workflow/generate.js +2 -2
  8. package/dist/commands/workflow/plan.js +3 -3
  9. package/dist/commands/workflow/plan.spec.js +13 -13
  10. package/dist/commands/workflow/terminate.d.ts +13 -0
  11. package/dist/commands/workflow/terminate.js +39 -0
  12. package/dist/services/claude_client.d.ts +4 -4
  13. package/dist/services/claude_client.integration.test.js +2 -2
  14. package/dist/services/claude_client.js +7 -7
  15. package/dist/services/claude_client.spec.js +3 -3
  16. package/dist/services/coding_agents.d.ts +10 -24
  17. package/dist/services/coding_agents.js +112 -368
  18. package/dist/services/coding_agents.spec.js +101 -290
  19. package/dist/services/project_scaffold.js +3 -3
  20. package/dist/services/workflow_builder.d.ts +1 -1
  21. package/dist/services/workflow_builder.js +1 -1
  22. package/dist/services/workflow_planner.js +5 -3
  23. package/dist/services/workflow_planner.spec.js +4 -5
  24. package/dist/templates/agent_instructions/dotclaude/settings.json.template +29 -0
  25. package/dist/templates/agent_instructions/{AGENTS.md.template → dotoutputai/AGENTS.md.template} +12 -10
  26. package/dist/utils/claude.d.ts +5 -0
  27. package/dist/utils/claude.js +19 -0
  28. package/dist/utils/claude.spec.d.ts +1 -0
  29. package/dist/utils/claude.spec.js +119 -0
  30. package/dist/utils/paths.d.ts +0 -4
  31. package/dist/utils/paths.js +0 -6
  32. package/package.json +3 -3
  33. package/dist/templates/agent_instructions/agents/workflow_context_fetcher.md.template +0 -82
  34. package/dist/templates/agent_instructions/agents/workflow_debugger.md.template +0 -98
  35. package/dist/templates/agent_instructions/agents/workflow_planner.md.template +0 -113
  36. package/dist/templates/agent_instructions/agents/workflow_prompt_writer.md.template +0 -595
  37. package/dist/templates/agent_instructions/agents/workflow_quality.md.template +0 -244
  38. package/dist/templates/agent_instructions/commands/build_workflow.md.template +0 -290
  39. package/dist/templates/agent_instructions/commands/debug_workflow.md.template +0 -198
  40. package/dist/templates/agent_instructions/commands/plan_workflow.md.template +0 -261
  41. package/dist/templates/agent_instructions/meta/post_flight.md.template +0 -94
  42. package/dist/templates/agent_instructions/meta/pre_flight.md.template +0 -60
  43. package/dist/templates/agent_instructions/skills/output-error-direct-io/SKILL.md.template +0 -249
  44. package/dist/templates/agent_instructions/skills/output-error-http-client/SKILL.md.template +0 -298
  45. package/dist/templates/agent_instructions/skills/output-error-missing-schemas/SKILL.md.template +0 -265
  46. package/dist/templates/agent_instructions/skills/output-error-nondeterminism/SKILL.md.template +0 -252
  47. package/dist/templates/agent_instructions/skills/output-error-try-catch/SKILL.md.template +0 -226
  48. package/dist/templates/agent_instructions/skills/output-error-zod-import/SKILL.md.template +0 -209
  49. package/dist/templates/agent_instructions/skills/output-services-check/SKILL.md.template +0 -128
  50. package/dist/templates/agent_instructions/skills/output-workflow-list/SKILL.md.template +0 -117
  51. package/dist/templates/agent_instructions/skills/output-workflow-result/SKILL.md.template +0 -199
  52. package/dist/templates/agent_instructions/skills/output-workflow-run/SKILL.md.template +0 -228
  53. package/dist/templates/agent_instructions/skills/output-workflow-runs-list/SKILL.md.template +0 -141
  54. package/dist/templates/agent_instructions/skills/output-workflow-start/SKILL.md.template +0 -201
  55. package/dist/templates/agent_instructions/skills/output-workflow-status/SKILL.md.template +0 -151
  56. package/dist/templates/agent_instructions/skills/output-workflow-stop/SKILL.md.template +0 -164
  57. package/dist/templates/agent_instructions/skills/output-workflow-trace/SKILL.md.template +0 -134
@@ -7,284 +7,11 @@ import { access } from 'node:fs/promises';
7
7
  import path from 'node:path';
8
8
  import { join } from 'node:path';
9
9
  import { ux } from '@oclif/core';
10
- import { confirm } from '@inquirer/prompts';
11
10
  import { AGENT_CONFIG_DIR } from '#config.js';
12
11
  import { getTemplateDir } from '#utils/paths.js';
12
+ import { executeClaudeCommand } from '#utils/claude.js';
13
13
  import { processTemplate } from '#utils/template.js';
14
- /**
15
- * Agent configuration mappings for different providers
16
- */
17
- export const AGENT_CONFIGS = {
18
- outputai: {
19
- id: 'outputai',
20
- name: 'OutputAI Core Files',
21
- mappings: [
22
- {
23
- type: 'template',
24
- from: 'AGENTS.md.template',
25
- to: `${AGENT_CONFIG_DIR}/AGENTS.md`
26
- },
27
- {
28
- type: 'template',
29
- from: 'agents/workflow_planner.md.template',
30
- to: `${AGENT_CONFIG_DIR}/agents/workflow_planner.md`
31
- },
32
- {
33
- type: 'template',
34
- from: 'agents/workflow_quality.md.template',
35
- to: `${AGENT_CONFIG_DIR}/agents/workflow_quality.md`
36
- },
37
- {
38
- type: 'template',
39
- from: 'agents/workflow_context_fetcher.md.template',
40
- to: `${AGENT_CONFIG_DIR}/agents/workflow_context_fetcher.md`
41
- },
42
- {
43
- type: 'template',
44
- from: 'agents/workflow_prompt_writer.md.template',
45
- to: `${AGENT_CONFIG_DIR}/agents/workflow_prompt_writer.md`
46
- },
47
- {
48
- type: 'template',
49
- from: 'agents/workflow_debugger.md.template',
50
- to: `${AGENT_CONFIG_DIR}/agents/workflow_debugger.md`
51
- },
52
- {
53
- type: 'template',
54
- from: 'commands/plan_workflow.md.template',
55
- to: `${AGENT_CONFIG_DIR}/commands/plan_workflow.md`
56
- },
57
- {
58
- type: 'template',
59
- from: 'commands/debug_workflow.md.template',
60
- to: `${AGENT_CONFIG_DIR}/commands/debug_workflow.md`
61
- },
62
- {
63
- type: 'template',
64
- from: 'commands/build_workflow.md.template',
65
- to: `${AGENT_CONFIG_DIR}/commands/build_workflow.md`
66
- },
67
- {
68
- type: 'template',
69
- from: 'meta/pre_flight.md.template',
70
- to: '.outputai/meta/pre_flight.md'
71
- },
72
- {
73
- type: 'template',
74
- from: 'meta/post_flight.md.template',
75
- to: '.outputai/meta/post_flight.md'
76
- },
77
- // Skills (all at top level - no nesting allowed)
78
- {
79
- type: 'template',
80
- from: 'skills/output-services-check/SKILL.md.template',
81
- to: `${AGENT_CONFIG_DIR}/skills/output-services-check/SKILL.md`
82
- },
83
- {
84
- type: 'template',
85
- from: 'skills/output-workflow-trace/SKILL.md.template',
86
- to: `${AGENT_CONFIG_DIR}/skills/output-workflow-trace/SKILL.md`
87
- },
88
- {
89
- type: 'template',
90
- from: 'skills/output-workflow-list/SKILL.md.template',
91
- to: `${AGENT_CONFIG_DIR}/skills/output-workflow-list/SKILL.md`
92
- },
93
- {
94
- type: 'template',
95
- from: 'skills/output-workflow-runs-list/SKILL.md.template',
96
- to: `${AGENT_CONFIG_DIR}/skills/output-workflow-runs-list/SKILL.md`
97
- },
98
- {
99
- type: 'template',
100
- from: 'skills/output-workflow-run/SKILL.md.template',
101
- to: `${AGENT_CONFIG_DIR}/skills/output-workflow-run/SKILL.md`
102
- },
103
- {
104
- type: 'template',
105
- from: 'skills/output-workflow-start/SKILL.md.template',
106
- to: `${AGENT_CONFIG_DIR}/skills/output-workflow-start/SKILL.md`
107
- },
108
- {
109
- type: 'template',
110
- from: 'skills/output-workflow-status/SKILL.md.template',
111
- to: `${AGENT_CONFIG_DIR}/skills/output-workflow-status/SKILL.md`
112
- },
113
- {
114
- type: 'template',
115
- from: 'skills/output-workflow-result/SKILL.md.template',
116
- to: `${AGENT_CONFIG_DIR}/skills/output-workflow-result/SKILL.md`
117
- },
118
- {
119
- type: 'template',
120
- from: 'skills/output-workflow-stop/SKILL.md.template',
121
- to: `${AGENT_CONFIG_DIR}/skills/output-workflow-stop/SKILL.md`
122
- },
123
- {
124
- type: 'template',
125
- from: 'skills/output-error-zod-import/SKILL.md.template',
126
- to: `${AGENT_CONFIG_DIR}/skills/output-error-zod-import/SKILL.md`
127
- },
128
- {
129
- type: 'template',
130
- from: 'skills/output-error-nondeterminism/SKILL.md.template',
131
- to: `${AGENT_CONFIG_DIR}/skills/output-error-nondeterminism/SKILL.md`
132
- },
133
- {
134
- type: 'template',
135
- from: 'skills/output-error-try-catch/SKILL.md.template',
136
- to: `${AGENT_CONFIG_DIR}/skills/output-error-try-catch/SKILL.md`
137
- },
138
- {
139
- type: 'template',
140
- from: 'skills/output-error-missing-schemas/SKILL.md.template',
141
- to: `${AGENT_CONFIG_DIR}/skills/output-error-missing-schemas/SKILL.md`
142
- },
143
- {
144
- type: 'template',
145
- from: 'skills/output-error-direct-io/SKILL.md.template',
146
- to: `${AGENT_CONFIG_DIR}/skills/output-error-direct-io/SKILL.md`
147
- },
148
- {
149
- type: 'template',
150
- from: 'skills/output-error-http-client/SKILL.md.template',
151
- to: `${AGENT_CONFIG_DIR}/skills/output-error-http-client/SKILL.md`
152
- }
153
- ]
154
- },
155
- 'claude-code': {
156
- id: 'claude-code',
157
- name: 'Claude Code',
158
- mappings: [
159
- {
160
- type: 'symlink',
161
- from: `${AGENT_CONFIG_DIR}/AGENTS.md`,
162
- to: 'CLAUDE.md'
163
- },
164
- {
165
- type: 'symlink',
166
- from: `${AGENT_CONFIG_DIR}/agents/workflow_planner.md`,
167
- to: '.claude/agents/workflow_planner.md'
168
- },
169
- {
170
- type: 'symlink',
171
- from: `${AGENT_CONFIG_DIR}/agents/workflow_quality.md`,
172
- to: '.claude/agents/workflow_quality.md'
173
- },
174
- {
175
- type: 'symlink',
176
- from: `${AGENT_CONFIG_DIR}/agents/workflow_context_fetcher.md`,
177
- to: '.claude/agents/workflow_context_fetcher.md'
178
- },
179
- {
180
- type: 'symlink',
181
- from: `${AGENT_CONFIG_DIR}/agents/workflow_prompt_writer.md`,
182
- to: '.claude/agents/workflow_prompt_writer.md'
183
- },
184
- {
185
- type: 'symlink',
186
- from: `${AGENT_CONFIG_DIR}/agents/workflow_debugger.md`,
187
- to: '.claude/agents/workflow_debugger.md'
188
- },
189
- {
190
- type: 'symlink',
191
- from: `${AGENT_CONFIG_DIR}/commands/plan_workflow.md`,
192
- to: '.claude/commands/plan_workflow.md'
193
- },
194
- {
195
- type: 'symlink',
196
- from: `${AGENT_CONFIG_DIR}/commands/debug_workflow.md`,
197
- to: '.claude/commands/debug_workflow.md'
198
- },
199
- {
200
- type: 'symlink',
201
- from: `${AGENT_CONFIG_DIR}/commands/build_workflow.md`,
202
- to: '.claude/commands/build_workflow.md'
203
- },
204
- // Skills Symlinks (all at top level - no nesting allowed)
205
- {
206
- type: 'symlink',
207
- from: `${AGENT_CONFIG_DIR}/skills/output-services-check/SKILL.md`,
208
- to: '.claude/skills/output-services-check/SKILL.md'
209
- },
210
- {
211
- type: 'symlink',
212
- from: `${AGENT_CONFIG_DIR}/skills/output-workflow-trace/SKILL.md`,
213
- to: '.claude/skills/output-workflow-trace/SKILL.md'
214
- },
215
- {
216
- type: 'symlink',
217
- from: `${AGENT_CONFIG_DIR}/skills/output-workflow-list/SKILL.md`,
218
- to: '.claude/skills/output-workflow-list/SKILL.md'
219
- },
220
- {
221
- type: 'symlink',
222
- from: `${AGENT_CONFIG_DIR}/skills/output-workflow-runs-list/SKILL.md`,
223
- to: '.claude/skills/output-workflow-runs-list/SKILL.md'
224
- },
225
- {
226
- type: 'symlink',
227
- from: `${AGENT_CONFIG_DIR}/skills/output-workflow-run/SKILL.md`,
228
- to: '.claude/skills/output-workflow-run/SKILL.md'
229
- },
230
- {
231
- type: 'symlink',
232
- from: `${AGENT_CONFIG_DIR}/skills/output-workflow-start/SKILL.md`,
233
- to: '.claude/skills/output-workflow-start/SKILL.md'
234
- },
235
- {
236
- type: 'symlink',
237
- from: `${AGENT_CONFIG_DIR}/skills/output-workflow-status/SKILL.md`,
238
- to: '.claude/skills/output-workflow-status/SKILL.md'
239
- },
240
- {
241
- type: 'symlink',
242
- from: `${AGENT_CONFIG_DIR}/skills/output-workflow-result/SKILL.md`,
243
- to: '.claude/skills/output-workflow-result/SKILL.md'
244
- },
245
- {
246
- type: 'symlink',
247
- from: `${AGENT_CONFIG_DIR}/skills/output-workflow-stop/SKILL.md`,
248
- to: '.claude/skills/output-workflow-stop/SKILL.md'
249
- },
250
- {
251
- type: 'symlink',
252
- from: `${AGENT_CONFIG_DIR}/skills/output-error-zod-import/SKILL.md`,
253
- to: '.claude/skills/output-error-zod-import/SKILL.md'
254
- },
255
- {
256
- type: 'symlink',
257
- from: `${AGENT_CONFIG_DIR}/skills/output-error-nondeterminism/SKILL.md`,
258
- to: '.claude/skills/output-error-nondeterminism/SKILL.md'
259
- },
260
- {
261
- type: 'symlink',
262
- from: `${AGENT_CONFIG_DIR}/skills/output-error-try-catch/SKILL.md`,
263
- to: '.claude/skills/output-error-try-catch/SKILL.md'
264
- },
265
- {
266
- type: 'symlink',
267
- from: `${AGENT_CONFIG_DIR}/skills/output-error-missing-schemas/SKILL.md`,
268
- to: '.claude/skills/output-error-missing-schemas/SKILL.md'
269
- },
270
- {
271
- type: 'symlink',
272
- from: `${AGENT_CONFIG_DIR}/skills/output-error-direct-io/SKILL.md`,
273
- to: '.claude/skills/output-error-direct-io/SKILL.md'
274
- },
275
- {
276
- type: 'symlink',
277
- from: `${AGENT_CONFIG_DIR}/skills/output-error-http-client/SKILL.md`,
278
- to: '.claude/skills/output-error-http-client/SKILL.md'
279
- }
280
- ]
281
- }
282
- };
283
- export function getRequiredFiles() {
284
- const outputaiFiles = AGENT_CONFIGS.outputai.mappings.map(m => m.to);
285
- const claudeCodeFiles = AGENT_CONFIGS['claude-code'].mappings.map(m => m.to);
286
- return [...outputaiFiles, ...claudeCodeFiles];
287
- }
14
+ const EXPECTED_MARKETPLACE_REPO = 'growthxai/output-claude-plugins';
288
15
  /**
289
16
  * Get the full path to the agent configuration directory
290
17
  */
@@ -313,31 +40,38 @@ async function fileExists(filePath) {
313
40
  return false;
314
41
  }
315
42
  }
316
- async function findMissingFiles(files, projectRoot) {
317
- const checks = await Promise.all(files.map(async (file) => ({
318
- file,
319
- missing: !await fileExists(join(projectRoot, file))
320
- })));
321
- return checks
322
- .filter(check => check.missing)
323
- .map(check => check.file);
43
+ /**
44
+ * Validate settings.json content has correct marketplace and plugin configuration
45
+ */
46
+ async function validateSettingsJson(projectRoot) {
47
+ const settingsPath = join(projectRoot, '.claude/settings.json');
48
+ try {
49
+ const content = await fs.readFile(settingsPath, 'utf-8');
50
+ const settings = JSON.parse(content);
51
+ const marketplaceRepo = settings.extraKnownMarketplaces?.['team-tools']?.source?.repo;
52
+ const pluginEnabled = settings.enabledPlugins?.['outputai@outputai'];
53
+ return marketplaceRepo === EXPECTED_MARKETPLACE_REPO && pluginEnabled === true;
54
+ }
55
+ catch {
56
+ return false;
57
+ }
324
58
  }
325
59
  export async function checkAgentStructure(projectRoot) {
326
- const requiredFiles = getRequiredFiles();
327
- const dirExists = await checkAgentConfigDirExists(projectRoot);
328
- if (!dirExists) {
329
- return {
330
- dirExists: false,
331
- missingFiles: requiredFiles,
332
- isComplete: false
333
- };
60
+ const outputaiDirExists = await checkAgentConfigDirExists(projectRoot);
61
+ const settingsValid = await validateSettingsJson(projectRoot);
62
+ const claudeMdExists = await fileExists(join(projectRoot, 'CLAUDE.md'));
63
+ if (!settingsValid) {
64
+ ux.warn('.claude/settings.json missing critical configuration.');
334
65
  }
335
- const missingFiles = await findMissingFiles(requiredFiles, projectRoot);
336
- return {
337
- dirExists: true,
338
- missingFiles,
339
- isComplete: missingFiles.length === 0
340
- };
66
+ if (!claudeMdExists) {
67
+ ux.warn('CLAUDE.md missing.');
68
+ }
69
+ if (!outputaiDirExists) {
70
+ ux.warn('.outputai/ directory missing.');
71
+ }
72
+ const isComplete = outputaiDirExists && settingsValid && claudeMdExists;
73
+ const needsInit = !outputaiDirExists || !settingsValid;
74
+ return { isComplete, needsInit };
341
75
  }
342
76
  /**
343
77
  * Prepare template variables for file generation
@@ -368,14 +102,24 @@ async function ensureDirectoryExists(dir) {
368
102
  /**
369
103
  * Create a file from a template
370
104
  */
371
- async function createFromTemplate(template, output, variables) {
105
+ async function createFromTemplate(templateSubpath, output, variables) {
372
106
  const templateDir = getTemplateDir('agent_instructions');
373
- const templatePath = path.join(templateDir, template);
107
+ const templatePath = path.join(templateDir, templateSubpath);
374
108
  const content = await fs.readFile(templatePath, 'utf-8');
375
109
  const processed = processTemplate(content, variables);
376
110
  await fs.writeFile(output, processed, 'utf-8');
377
111
  ux.stdout(ux.colorize('gray', `Created from template: ${output}`));
378
112
  }
113
+ /**
114
+ * Create a static file (no template processing)
115
+ */
116
+ async function createStaticFile(templateSubpath, output) {
117
+ const templateDir = getTemplateDir('agent_instructions');
118
+ const templatePath = path.join(templateDir, templateSubpath);
119
+ const content = await fs.readFile(templatePath, 'utf-8');
120
+ await fs.writeFile(output, content, 'utf-8');
121
+ ux.stdout(ux.colorize('gray', `Created file: ${output}`));
122
+ }
379
123
  /**
380
124
  * Create a symlink, falling back to copying if symlinks are not supported
381
125
  */
@@ -397,7 +141,6 @@ async function createSymlink(source, target, projectRoot) {
397
141
  const code = error.code;
398
142
  if (code === 'ENOTSUP' || code === 'EPERM') {
399
143
  ux.stdout(ux.colorize('gray', `Symlinks not supported, creating copy: ${target}`));
400
- // Use resolved source path for copying
401
144
  const resolvedSource = path.isAbsolute(source) ?
402
145
  source :
403
146
  path.join(projectRoot, source);
@@ -409,90 +152,91 @@ async function createSymlink(source, target, projectRoot) {
409
152
  }
410
153
  }
411
154
  /**
412
- * Copy a file from source to target
155
+ * Create .outputai/AGENTS.md file from template
413
156
  */
414
- async function copyFile(source, target) {
415
- const content = await fs.readFile(source, 'utf-8');
416
- await fs.writeFile(target, content, 'utf-8');
417
- ux.stdout(ux.colorize('gray', `Copied file: ${source} -> ${target}`));
157
+ async function createAgentsMdFile(projectRoot, force, variables) {
158
+ const outputaiDir = join(projectRoot, AGENT_CONFIG_DIR);
159
+ await ensureDirectoryExists(outputaiDir);
160
+ const agentsMdPath = join(outputaiDir, 'AGENTS.md');
161
+ if (force || !await fileExists(agentsMdPath)) {
162
+ await createFromTemplate('dotoutputai/AGENTS.md.template', agentsMdPath, variables);
163
+ }
164
+ else {
165
+ ux.warn(`File already exists: ${AGENT_CONFIG_DIR}/AGENTS.md (use --force to overwrite)`);
166
+ }
418
167
  }
419
168
  /**
420
- * Process file mappings for a specific agent configuration
169
+ * Create .claude/settings.json file from template
421
170
  */
422
- async function processMappings(config, variables, force, projectRoot) {
423
- for (const mapping of config.mappings) {
424
- const fullPath = path.isAbsolute(mapping.to) ?
425
- mapping.to :
426
- path.join(projectRoot, mapping.to);
427
- const dir = path.dirname(fullPath);
428
- await ensureDirectoryExists(dir);
429
- if (!force && await fileExists(fullPath)) {
430
- ux.warn(`File already exists: ${mapping.to} (use --force to overwrite)`);
431
- continue;
432
- }
433
- switch (mapping.type) {
434
- case 'template':
435
- await createFromTemplate(mapping.from, fullPath, variables);
436
- break;
437
- case 'symlink':
438
- await createSymlink(mapping.from, fullPath, projectRoot);
439
- break;
440
- case 'copy':
441
- await copyFile(mapping.from, fullPath);
442
- break;
443
- }
171
+ async function createSettingsFile(projectRoot, force) {
172
+ const claudeDir = join(projectRoot, '.claude');
173
+ await ensureDirectoryExists(claudeDir);
174
+ const settingsPath = join(claudeDir, 'settings.json');
175
+ if (force || !await fileExists(settingsPath)) {
176
+ await createStaticFile('dotclaude/settings.json.template', settingsPath);
177
+ }
178
+ else {
179
+ ux.warn('File already exists: .claude/settings.json (use --force to overwrite)');
444
180
  }
445
181
  }
446
182
  /**
447
- * Initialize agent configuration files
448
- * Main entry point for agent initialization logic
183
+ * Create CLAUDE.md symlink pointing to .outputai/AGENTS.md
184
+ * Only checks if CLAUDE.md exists, not AGENTS.md - developers can remove AGENTS.md freely
449
185
  */
450
- export async function initializeAgentConfig(options) {
451
- const { projectRoot, force, agentProvider } = options;
452
- const variables = prepareTemplateVariables();
453
- await processMappings(AGENT_CONFIGS.outputai, variables, force, projectRoot);
454
- await processMappings(AGENT_CONFIGS[agentProvider], variables, force, projectRoot);
455
- }
456
- function formatMissingFilesList(files) {
457
- return files.map(f => ` • ${f}`).join('\n');
186
+ async function createClaudeMdSymlink(projectRoot, force) {
187
+ const claudeMdPath = join(projectRoot, 'CLAUDE.md');
188
+ if (force || !await fileExists(claudeMdPath)) {
189
+ await createSymlink(`${AGENT_CONFIG_DIR}/AGENTS.md`, claudeMdPath, projectRoot);
190
+ }
191
+ else {
192
+ ux.warn('File already exists: CLAUDE.md (use --force to overwrite)');
193
+ }
458
194
  }
459
- async function promptForReinitialize() {
460
- return confirm({
461
- message: 'Would you like to run "agents init --force" to recreate missing files?',
462
- default: true
463
- });
195
+ /**
196
+ * Register and update the OutputAI plugin marketplace
197
+ */
198
+ async function registerPluginMarketplace(projectRoot) {
199
+ ux.stdout(ux.colorize('gray', 'Registering plugin marketplace...'));
200
+ await executeClaudeCommand(['plugin', 'marketplace', 'add', 'growthxai/output-claude-plugins'], projectRoot, { ignoreFailure: true });
201
+ ux.stdout(ux.colorize('gray', 'Updating plugin marketplace...'));
202
+ await executeClaudeCommand(['plugin', 'marketplace', 'update', 'outputai'], projectRoot);
464
203
  }
465
- async function initializeAgentStructure(projectRoot, force) {
466
- await initializeAgentConfig({
467
- projectRoot,
468
- force,
469
- agentProvider: 'claude-code'
470
- });
204
+ /**
205
+ * Install the OutputAI plugin
206
+ */
207
+ async function installOutputAIPlugin(projectRoot) {
208
+ ux.stdout(ux.colorize('gray', 'Installing OutputAI plugin...'));
209
+ await executeClaudeCommand(['plugin', 'install', 'outputai@outputai', '--scope', 'project'], projectRoot);
471
210
  }
472
- function createIncompleteConfigError(missingFiles) {
473
- return new Error(`Agent configuration incomplete. Missing files:\n${missingFiles.join('\n')}\n\n` +
474
- 'Run "output-cli agents init --force" to recreate them.');
211
+ /**
212
+ * Initialize agent configuration files and register Claude Code plugin
213
+ * Creates 3 files:
214
+ * - .outputai/AGENTS.md (from template with Handlebars processing)
215
+ * - .claude/settings.json (static JSON)
216
+ * - CLAUDE.md symlink to .outputai/AGENTS.md
217
+ * Then runs Claude CLI commands to register the plugin marketplace and install the plugin
218
+ */
219
+ export async function initializeAgentConfig(options) {
220
+ const { projectRoot, force } = options;
221
+ const variables = prepareTemplateVariables();
222
+ await createAgentsMdFile(projectRoot, force, variables);
223
+ await createSettingsFile(projectRoot, force);
224
+ await createClaudeMdSymlink(projectRoot, force);
225
+ await registerPluginMarketplace(projectRoot);
226
+ await installOutputAIPlugin(projectRoot);
475
227
  }
476
228
  /**
477
- * Ensure .outputai directory structure exists by invoking agents init if needed
478
- * Displays warnings for missing files and prompts for reinitialization
229
+ * Ensure OutputAI system is initialized by invoking agents init if needed
230
+ * Creates configuration files and registers Claude Code plugin
479
231
  * @param projectRoot - Root directory of the project
480
- * @throws Error if user declines to initialize or if initialization fails
481
232
  */
482
- export async function ensureOutputAIStructure(projectRoot) {
483
- const structureCheck = await checkAgentStructure(projectRoot);
484
- if (structureCheck.isComplete) {
485
- return;
486
- }
487
- if (!structureCheck.dirExists) {
488
- await initializeAgentStructure(projectRoot, false);
233
+ export async function ensureOutputAISystem(projectRoot) {
234
+ const { isComplete, needsInit } = await checkAgentStructure(projectRoot);
235
+ if (isComplete) {
489
236
  return;
490
237
  }
491
- const missingList = formatMissingFilesList(structureCheck.missingFiles);
492
- ux.warn(`\n⚠️ Agent configuration is incomplete. Missing files:\n${missingList}\n`);
493
- const shouldReinit = await promptForReinitialize();
494
- if (!shouldReinit) {
495
- throw createIncompleteConfigError(structureCheck.missingFiles);
238
+ if (needsInit) {
239
+ ux.warn('Agent configuration is incomplete. Initializing...');
240
+ await initializeAgentConfig({ projectRoot, force: false });
496
241
  }
497
- await initializeAgentStructure(projectRoot, true);
498
242
  }