contextos-agents 1.6.1 → 1.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 (86) hide show
  1. package/.agents/AGENTS.md +5 -0
  2. package/.agents/adapters/aider/export.js +4 -2
  3. package/.agents/adapters/copilot/export.js +4 -2
  4. package/.agents/adapters/cursor/export.js +48 -12
  5. package/.agents/adapters/zed/export.js +53 -14
  6. package/.agents/core/skills/adapters/skill.yaml +6 -0
  7. package/.agents/core/skills/architecture-diagrams/skill.yaml +4 -0
  8. package/.agents/core/skills/brutalist-design/skill.yaml +4 -0
  9. package/.agents/core/skills/context-manager/references/context-rules.md +59 -0
  10. package/.agents/core/skills/context-manager/skill.yaml +7 -0
  11. package/.agents/core/skills/context-os/skill.yaml +11 -0
  12. package/.agents/core/skills/database/skill.yaml +6 -0
  13. package/.agents/core/skills/ddd/skill.yaml +7 -0
  14. package/.agents/core/skills/decisions/skill.yaml +6 -0
  15. package/.agents/core/skills/docker/skill.yaml +6 -0
  16. package/.agents/core/skills/engineering-workflow/SKILL.md +1 -1
  17. package/.agents/core/skills/engineering-workflow/skill.yaml +6 -0
  18. package/.agents/core/skills/fastapi/skill.yaml +7 -0
  19. package/.agents/core/skills/gemini-precision/SKILL.md +4 -0
  20. package/.agents/core/skills/gemini-precision/skill.yaml +4 -0
  21. package/.agents/core/skills/generators/skill.yaml +15 -0
  22. package/.agents/core/skills/graphify/SKILL.md +2 -2
  23. package/.agents/core/skills/graphify/skill.yaml +6 -1
  24. package/.agents/core/skills/gstack-roles/SKILL.md +3 -1
  25. package/.agents/core/skills/gstack-roles/skill.yaml +6 -0
  26. package/.agents/core/skills/impeccable-design/skill.yaml +6 -0
  27. package/.agents/core/skills/interview-me/skill.yaml +4 -0
  28. package/.agents/core/skills/microservices/skill.yaml +7 -0
  29. package/.agents/core/skills/minimalist-design/skill.yaml +4 -0
  30. package/.agents/core/skills/nestjs/skill.yaml +7 -0
  31. package/.agents/core/skills/nextjs/skill.yaml +7 -0
  32. package/.agents/core/skills/node/skill.yaml +7 -0
  33. package/.agents/core/skills/performance/skill.yaml +7 -0
  34. package/.agents/core/skills/ponytail-mindset/skill.yaml +6 -0
  35. package/.agents/core/skills/react/skill.yaml +7 -0
  36. package/.agents/core/skills/react-best-practices/skill.yaml +4 -0
  37. package/.agents/core/skills/redesign-audit/skill.yaml +4 -0
  38. package/.agents/core/skills/security/skill.yaml +7 -0
  39. package/.agents/core/skills/soft-design/skill.yaml +4 -0
  40. package/.agents/core/skills/state-management/skill.yaml +6 -0
  41. package/.agents/core/skills/subagent-orchestrator/SKILL.md +17 -0
  42. package/.agents/core/skills/subagent-orchestrator/skill.yaml +4 -0
  43. package/.agents/core/skills/system-design/skill.yaml +7 -0
  44. package/.agents/core/skills/testing/skill.yaml +6 -0
  45. package/.agents/core/skills/typescript/skill.yaml +7 -0
  46. package/.agents/core/skills/ui-design/skill.yaml +7 -0
  47. package/.agents/core/skills/ui-ux-pro/skill.yaml +6 -0
  48. package/.agents/core/skills/ux-design/skill.yaml +7 -0
  49. package/.agents/core/skills/vercel-optimize/scripts/collect-signals.mjs +131 -0
  50. package/.agents/core/skills/vercel-optimize/scripts/gate-investigations.mjs +142 -0
  51. package/.agents/core/skills/vercel-optimize/scripts/merge-signals.mjs +143 -0
  52. package/.agents/core/skills/vercel-optimize/scripts/scan-codebase.mjs +174 -0
  53. package/.agents/core/skills/vercel-optimize/skill.yaml +8 -0
  54. package/.agents/core/skills/web-accessibility/skill.yaml +7 -0
  55. package/.agents/ctx.js +14 -1
  56. package/.agents/doctor.js +193 -4
  57. package/.agents/generated/claude/skills/engineering-workflow/SKILL.md +1 -1
  58. package/.agents/generated/claude/skills/gemini-precision/SKILL.md +4 -0
  59. package/.agents/generated/claude/skills/graphify/SKILL.md +1 -1
  60. package/.agents/generated/claude/skills/gstack-roles/SKILL.md +3 -1
  61. package/.agents/generated/claude/skills/subagent-orchestrator/SKILL.md +17 -0
  62. package/.agents/generated/gemini/skills/engineering-workflow/SKILL.md +1 -1
  63. package/.agents/generated/gemini/skills/gemini-precision/SKILL.md +4 -0
  64. package/.agents/generated/gemini/skills/graphify/SKILL.md +2 -2
  65. package/.agents/generated/gemini/skills/gstack-roles/SKILL.md +3 -1
  66. package/.agents/generated/gemini/skills/subagent-orchestrator/SKILL.md +17 -0
  67. package/.agents/plugins/contextos/hooks.json +25 -0
  68. package/.agents/plugins/contextos/plugin.json +19 -0
  69. package/.agents/plugins.js +180 -20
  70. package/.agents/profiles.js +26 -0
  71. package/.agents/resolver.js +150 -30
  72. package/.agents/stats.js +22 -9
  73. package/.agents/validate.js +99 -13
  74. package/bin/commands/uninstall.js +207 -0
  75. package/bin/commands/update.js +262 -0
  76. package/bin/commands.js +305 -0
  77. package/bin/index.js +203 -83
  78. package/bin/lib/detector.js +106 -0
  79. package/bin/lib/lockfile.js +251 -0
  80. package/bin/lib/safe-writer.js +259 -0
  81. package/package.json +5 -6
  82. package/registry.json +13 -5
  83. package/registry.schema.json +3 -1
  84. package/.agents/mcp/runtime.py +0 -470
  85. package/.agents/mcp/server.mjs +0 -189271
  86. package/benchmarks/gemini-issues.js +0 -533
package/bin/index.js CHANGED
@@ -4,6 +4,9 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
  const { version } = require('../package.json');
6
6
  const profiles = require('../.agents/profiles.js');
7
+ const { isKnownCommand, getStatus, formatStatusText } = require('./commands.js');
8
+ const { detectProjectAttributes } = require('./lib/detector.js');
9
+ const lockfileLib = require('./lib/lockfile.js');
7
10
 
8
11
  // ── CLI argument parsing ──────────────────────────────────────────────────────
9
12
  const args = process.argv.slice(2);
@@ -15,7 +18,12 @@ const flags = {
15
18
  skipCompile: args.includes('--skip-compile'),
16
19
  auto: args.includes('--auto'),
17
20
  minimal: args.includes('--minimal'),
21
+ json: args.includes('--json'),
18
22
  withMcp: args.includes('--with-mcp') || args.includes('--mcp'),
23
+ agent: (() => {
24
+ const i = args.indexOf('--agent');
25
+ return i !== -1 ? args[i + 1] : null;
26
+ })(),
19
27
  profile: (() => {
20
28
  const i = args.indexOf('--profile');
21
29
  return i !== -1 ? args[i + 1] : null;
@@ -28,7 +36,11 @@ const flags = {
28
36
 
29
37
  // ── Help / Version ────────────────────────────────────────────────────────────
30
38
  if (flags.ver) {
31
- console.log(`contextos-agents v${version}`);
39
+ if (flags.json) {
40
+ console.log(JSON.stringify({ package: 'contextos-agents', version }));
41
+ } else {
42
+ console.log(`contextos-agents v${version}`);
43
+ }
32
44
  process.exit(0);
33
45
  }
34
46
 
@@ -38,12 +50,15 @@ contextos / contextos-agents v${version}
38
50
  Install AI assistant skills and rules into your project.
39
51
 
40
52
  Usage:
41
- npx contextos [options]
53
+ npx contextos-agents init [options]
54
+ npx contextos-agents <command> [args...]
42
55
  contextos <command> [args...]
43
56
 
44
57
  Options:
45
58
  --help, -h Show this help message
46
59
  --version, -v Show version number
60
+ --json Output machine-readable JSON format
61
+ --agent <name> Target AI agent or IDE (gemini, claude, cursor, auto)
47
62
  --dry-run Preview what will be copied without making changes
48
63
  --force Overwrite an existing .agents/ folder
49
64
  --minimal Install only 5 core skills (lightweight footprint)
@@ -54,6 +69,10 @@ Options:
54
69
  --add-skill <ref> Install a community plugin skill after setup
55
70
 
56
71
  Commands:
72
+ init Install and configure .agents/ in target project
73
+ status Display project configuration, active profile, and lockfile status
74
+ update Safely update skills without overwriting custom changes
75
+ uninstall Safely uninstall ContextOS files (preserves user custom skills)
57
76
  doctor Run full project diagnostic health check
58
77
  audit Validate local skills (alias for validate)
59
78
  validate Validate local skills, frontmatter, and sync
@@ -62,7 +81,7 @@ Commands:
62
81
  resolve <prompt> Dynamically resolve minimal skills for a prompt or files
63
82
  stats Display token context savings report
64
83
  watch Start continuous file watcher and auto-sync daemon
65
- detect Analyze project and display detected tech stack
84
+ detect Analyze project and display detected tech stack & IDE
66
85
  install-skill Interactive skill installer (or pass <ref> / --from-repo)
67
86
  setup-mcp Add MCP execution server to an existing .agents/ project
68
87
 
@@ -82,12 +101,12 @@ Plugin ref formats:
82
101
  @scope/npm-package A scoped npm skill package
83
102
 
84
103
  Examples:
85
- npx contextos Install .agents/ into current project
86
- npx contextos --minimal Install only 5 core essential skills
87
- npx contextos --profile startup Install with startup profile
88
- contextos doctor Run project health check
89
- contextos export gemini Compile skills for Gemini
90
- contextos profile list List available profiles
104
+ npx contextos-agents init Install .agents/ with auto-detected stack
105
+ npx contextos-agents init --agent auto Install and configure for detected stack & IDE
106
+ npx contextos-agents init --minimal Install only 5 core essential skills
107
+ npx contextos status Show project configuration and lockfile status
108
+ npx contextos doctor Run project health check
109
+ npx contextos export gemini Compile skills for Gemini
91
110
  `);
92
111
  process.exit(0);
93
112
  }
@@ -95,10 +114,55 @@ Examples:
95
114
  // ── Top-level Commands & Proxy Routing ────────────────────────────────────────
96
115
  const mainCommand = args[0] && !args[0].startsWith('-') ? args[0] : null;
97
116
 
117
+ // Unknown command check
118
+ if (mainCommand && mainCommand !== 'init' && !isKnownCommand(mainCommand)) {
119
+ if (flags.json) {
120
+ console.error(JSON.stringify({ error: `Unknown command: ${mainCommand}`, code: 1 }));
121
+ } else {
122
+ console.error(`[ERROR] Unknown command: ${mainCommand}`);
123
+ console.error(' Run `npx contextos-agents --help` to view available commands.');
124
+ }
125
+ process.exit(1);
126
+ }
127
+
128
+ // Status command
129
+ if (mainCommand === 'status') {
130
+ const status = getStatus(process.cwd());
131
+ if (flags.json) {
132
+ console.log(JSON.stringify(status, null, 2));
133
+ } else {
134
+ console.log(formatStatusText(status));
135
+ }
136
+ process.exit(0);
137
+ }
138
+
139
+ // Detect command
140
+ if (mainCommand === 'detect') {
141
+ const detection = detectProjectAttributes(process.cwd());
142
+ if (flags.json) {
143
+ console.log(JSON.stringify(detection, null, 2));
144
+ } else {
145
+ console.log('\nContextOS — Tech Stack & Environment Detection\n');
146
+ console.log(` Detected Technologies : ${detection.summary.technologies.join(', ')}`);
147
+ console.log(` Detected Environments : ${detection.summary.ides.join(', ')}`);
148
+ console.log(` Recommended Profile : ${detection.summary.recommendedProfile}`);
149
+ console.log(` Recommended Agents : ${detection.summary.recommendedAgents.join(', ')}`);
150
+ console.log(` Recommended Skills : ${detection.summary.recommendedSkills.join(', ')}\n`);
151
+ }
152
+ process.exit(0);
153
+ }
154
+
155
+ // Doctor command
156
+ if (mainCommand === 'doctor') {
157
+ const doctorModule = require('../.agents/doctor.js');
158
+ const result = doctorModule.runDoctor(process.cwd(), { json: flags.json });
159
+ process.exit(result && result.ok === false ? 1 : 0);
160
+ }
161
+
98
162
  // Proxy commands to .agents/ctx.js when executed in a ContextOS project
99
163
  const PROXY_COMMANDS = [
100
164
  'profile', 'export', 'validate', 'resolve', 'skill', 'index',
101
- 'clean-worktrees', 'doctor', 'stats', 'watch', 'init'
165
+ 'clean-worktrees', 'stats', 'watch'
102
166
  ];
103
167
 
104
168
  const ctxPath = path.join(process.cwd(), '.agents', 'ctx.js');
@@ -115,9 +179,21 @@ if (mainCommand && PROXY_COMMANDS.includes(mainCommand) && hasLocalCtx) {
115
179
  }
116
180
 
117
181
  // Fallbacks when running outside an initialized .agents/ directory
118
- if (mainCommand === 'doctor') {
119
- const doctorModule = require('../.agents/doctor.js');
120
- doctorModule.runDoctor(process.cwd());
182
+ if (mainCommand === 'update') {
183
+ const { runUpdate } = require('./commands/update.js');
184
+ runUpdate(process.cwd(), {
185
+ dryRun: flags.dryRun,
186
+ skipCompile: flags.skipCompile,
187
+ profile: flags.profile,
188
+ });
189
+ process.exit(0);
190
+ }
191
+
192
+ if (mainCommand === 'uninstall') {
193
+ const { runUninstall } = require('./commands/uninstall.js');
194
+ runUninstall(process.cwd(), {
195
+ dryRun: flags.dryRun,
196
+ });
121
197
  process.exit(0);
122
198
  }
123
199
 
@@ -132,23 +208,6 @@ if (mainCommand === 'watch') {
132
208
  watchModule.runWatch(process.cwd());
133
209
  }
134
210
 
135
- if (mainCommand === 'init') {
136
- console.log(`
137
- ContextOS — Project Setup
138
-
139
- Usage:
140
- npx contextos Install .agents/ with auto-detected stack
141
- npx contextos --profile <name> Install with specific profile (mvp, startup, enterprise, frontend, backend)
142
- npx contextos --minimal Install only 5 core skills
143
- npx contextos --with-mcp Install with MCP execution server enabled
144
-
145
- Run:
146
- contextos doctor Verify installation health
147
- contextos stats Show token savings report
148
- `);
149
- process.exit(0);
150
- }
151
-
152
211
  const PROJECT_ONLY_COMMANDS = ['profile', 'export', 'validate', 'resolve', 'skill', 'index', 'clean-worktrees'];
153
212
  if (mainCommand && PROJECT_ONLY_COMMANDS.includes(mainCommand) && !hasLocalCtx) {
154
213
  console.error('[ERROR] .agents/ctx.js not found in current directory.');
@@ -170,15 +229,6 @@ if (mainCommand === 'audit') {
170
229
  process.exit(0);
171
230
  }
172
231
 
173
- if (mainCommand === 'detect') {
174
- const stack = profiles.detectStack(process.cwd());
175
- console.log('\nContextOS — Tech Stack Detection\n');
176
- console.log(` Detected Technologies : ${stack.detected.length ? stack.detected.join(', ') : 'Generic JavaScript'}`);
177
- console.log(` Recommended Profile : ${stack.recommendedProfile}`);
178
- console.log(` Recommended Skills : ${stack.recommendedSkills.join(', ')}\n`);
179
- process.exit(0);
180
- }
181
-
182
232
  if (mainCommand === 'install-skill') {
183
233
  const ctxPath = path.join(process.cwd(), '.agents', 'ctx.js');
184
234
  if (!fs.existsSync(ctxPath)) {
@@ -404,12 +454,18 @@ function installAtomically(source, target, options = {}) {
404
454
  }
405
455
  }
406
456
 
407
- // ── Stack detection ───────────────────────────────────────────────────────────
408
- const stackDetection = profiles.detectStack(process.cwd());
457
+ // ── Stack & IDE detection ───────────────────────────────────────────────────
458
+ const projectAttrs = detectProjectAttributes(process.cwd());
459
+ const stackDetection = projectAttrs.stack;
460
+ const ideDetection = projectAttrs.ide;
461
+
462
+ const targetProfile = flags.profile || (flags.auto || flags.agent === 'auto' ? stackDetection.recommendedProfile : 'none');
463
+ const targetAgents = (flags.agent === 'auto' || flags.auto)
464
+ ? ideDetection.recommendedAgents
465
+ : (flags.agent ? [flags.agent] : ['gemini']);
409
466
 
410
467
  // ── Dry run ───────────────────────────────────────────────────────────────────
411
468
  if (flags.dryRun) {
412
- console.log('[DRY-RUN] No files will be written.\n');
413
469
  if (!fs.existsSync(sourcePath)) {
414
470
  console.error('[ERROR] Source .agents/ folder not found in package.');
415
471
  process.exit(1);
@@ -439,14 +495,34 @@ if (flags.dryRun) {
439
495
  return count;
440
496
  };
441
497
  const total = countFiles(sourcePath);
498
+
499
+ if (flags.json) {
500
+ console.log(JSON.stringify({
501
+ dryRun: true,
502
+ targetPath,
503
+ targetProfile,
504
+ detectedStack: stackDetection.detected,
505
+ detectedIde: ideDetection.detected,
506
+ targetAgents,
507
+ filesCount: total,
508
+ minimal: flags.minimal,
509
+ withMcp: flags.withMcp,
510
+ }, null, 2));
511
+ process.exit(0);
512
+ }
513
+
514
+ console.log('[DRY-RUN] No files will be written.\n');
442
515
  if (fs.existsSync(targetPath)) {
443
516
  console.log(`[WARN] .agents/ already exists — would be overwritten with --force.`);
444
517
  } else {
445
518
  console.log(`[OK] Would create .agents/ in: ${process.cwd()}`);
446
519
  }
447
520
  console.log(`[INFO] Detected stack: ${stackDetection.detected.length ? stackDetection.detected.join(', ') : 'Generic JavaScript'}`);
448
- const targetProfile = flags.profile || (flags.auto ? stackDetection.recommendedProfile : 'none');
521
+ if (ideDetection.detected.length > 0) {
522
+ console.log(`[INFO] Detected IDEs: ${ideDetection.detected.join(', ')}`);
523
+ }
449
524
  console.log(`[INFO] Selected profile: ${targetProfile}`);
525
+ console.log(`[INFO] Target agents for export: ${targetAgents.join(', ')}`);
450
526
  if (flags.minimal) {
451
527
  console.log(`[INFO] Minimal mode: copying only 5 core essential skills`);
452
528
  }
@@ -456,7 +532,9 @@ if (flags.dryRun) {
456
532
  }
457
533
 
458
534
  // ── Main install ──────────────────────────────────────────────────────────────
459
- console.log('Installing AI assistant skills (.agents/)...');
535
+ if (!flags.json) {
536
+ console.log('Installing AI assistant skills (.agents/)...');
537
+ }
460
538
 
461
539
  try {
462
540
  if (!fs.existsSync(sourcePath)) {
@@ -477,14 +555,31 @@ try {
477
555
 
478
556
  installAtomically(sourcePath, targetPath, { withMcp: flags.withMcp, minimal: flags.minimal });
479
557
 
480
- console.log('[OK] .agents/ successfully installed in your project!');
481
- if (flags.minimal) {
482
- console.log('[OK] Minimal profile: 5 core skills installed.');
483
- console.log(' (engineering-workflow, ponytail-mindset, gstack-roles, gemini-precision, react)');
484
- console.log(' Tip: Add more skills anytime with: contextos skill add <name>');
558
+ // ── Create/update lockfile for provenance & safe lifecycle ─────────────────
559
+ const selectedProfile = flags.profile || (flags.auto || flags.agent === 'auto' ? stackDetection.recommendedProfile : null);
560
+ try {
561
+ lockfileLib.migrateExistingInstallation(process.cwd(), sourcePath, {
562
+ selectedProfile: selectedProfile || 'none',
563
+ installedPackage: 'contextos-agents',
564
+ version,
565
+ });
566
+ } catch (err) {
567
+ if (!flags.json) console.warn(`[WARN] Could not generate lockfile: ${err.message}`);
485
568
  }
486
- if (stackDetection.detected.length > 0) {
487
- console.log(`[OK] Detected project stack: ${stackDetection.detected.join(', ')}`);
569
+
570
+ if (!flags.json) {
571
+ console.log('[OK] .agents/ successfully installed in your project!');
572
+ if (flags.minimal) {
573
+ console.log('[OK] Minimal profile: 5 core skills installed.');
574
+ console.log(' (engineering-workflow, ponytail-mindset, gstack-roles, gemini-precision, react)');
575
+ console.log(' Tip: Add more skills anytime with: contextos skill add <name>');
576
+ }
577
+ if (stackDetection.detected.length > 0) {
578
+ console.log(`[OK] Detected project stack: ${stackDetection.detected.join(', ')}`);
579
+ }
580
+ if (ideDetection.detected.length > 0) {
581
+ console.log(`[OK] Detected developer environment: ${ideDetection.detected.join(', ')}`);
582
+ }
488
583
  }
489
584
 
490
585
  // ── Create mcp_config.json only if --with-mcp ────────────────────────────────
@@ -500,41 +595,80 @@ try {
500
595
  }
501
596
  };
502
597
  fs.writeFileSync(mcpConfigPath, JSON.stringify(defaultMcpConfig, null, 2));
503
- console.log('[OK] Created default MCP configuration (.agents/mcp_config.json)');
598
+ if (!flags.json) console.log('[OK] Created default MCP configuration (.agents/mcp_config.json)');
504
599
  }
505
600
  }
506
601
 
507
602
  // ── Apply profile if requested or auto ──────────────────────────────────────
508
- const selectedProfile = flags.profile || (flags.auto ? stackDetection.recommendedProfile : null);
509
603
  if (selectedProfile) {
510
604
  try {
511
605
  const applied = profiles.applyProfile(selectedProfile, process.cwd());
512
- console.log(`[OK] Applied profile '${applied.name}' (excluded: ${(applied.exclude_skills || []).join(', ') || 'none'})`);
606
+ if (!flags.json) console.log(`[OK] Applied profile '${applied.name}' (excluded: ${(applied.exclude_skills || []).join(', ') || 'none'})`);
513
607
  } catch (e) {
514
- console.warn(`[WARN] Could not apply profile '${selectedProfile}': ${e.message}`);
608
+ if (!flags.json) console.warn(`[WARN] Could not apply profile '${selectedProfile}': ${e.message}`);
515
609
  }
516
610
  }
517
611
 
518
- console.log('[OK] Your AI assistant now has skills and rules configured.\n');
612
+ if (!flags.json) {
613
+ console.log('[OK] Your AI assistant now has skills and rules configured.\n');
614
+ }
519
615
 
520
- // ── Auto-compile skills ───────────────────────────────────────────────────
616
+ // ── Auto-compile skills for target agents ──────────────────────────────────
521
617
  if (!flags.skipCompile) {
522
618
  const ctxPath = path.join(targetPath, 'ctx.js');
523
619
  if (fs.existsSync(ctxPath)) {
524
- console.log('Compiling skills for Gemini...');
620
+ const { execFileSync } = require('child_process');
621
+ for (const ag of targetAgents) {
622
+ if (!flags.json) console.log(`Compiling skills for ${ag}...`);
623
+ try {
624
+ execFileSync(process.execPath, [ctxPath, 'export', ag], {
625
+ cwd: process.cwd(),
626
+ stdio: flags.json ? 'ignore' : 'inherit',
627
+ });
628
+ } catch (e) {
629
+ if (!flags.json) {
630
+ console.warn(`[WARN] Skill compilation for '${ag}' failed — run manually:`);
631
+ console.warn(` contextos export ${ag}`);
632
+ }
633
+ }
634
+ }
635
+ }
636
+ } else if (!flags.json) {
637
+ console.log('Tip: Run `contextos export gemini` to compile skills.');
638
+ }
639
+
640
+ // ── --add-skill flag ────────────────────────────────────────────────────────
641
+ if (flags.addSkill) {
642
+ const ctxPath = path.join(targetPath, 'ctx.js');
643
+ if (fs.existsSync(ctxPath)) {
644
+ if (!flags.json) console.log(`Installing plugin skill: ${flags.addSkill}`);
525
645
  try {
526
646
  const { execFileSync } = require('child_process');
527
- execFileSync(process.execPath, [ctxPath, 'export', 'gemini'], {
647
+ execFileSync(process.execPath, [ctxPath, 'skill', 'add', flags.addSkill], {
528
648
  cwd: process.cwd(),
529
- stdio: 'inherit',
649
+ stdio: flags.json ? 'ignore' : 'inherit',
530
650
  });
531
651
  } catch (e) {
532
- console.warn('[WARN] Skill compilation failed — run manually:');
533
- console.warn(' contextos export gemini');
652
+ if (!flags.json) {
653
+ console.warn(`[WARN] Skill install failed — run manually:`);
654
+ console.warn(` node .agents/ctx.js skill add ${flags.addSkill}`);
655
+ }
534
656
  }
535
657
  }
536
- } else {
537
- console.log('Tip: Run `contextos export gemini` to compile skills.');
658
+ }
659
+
660
+ if (flags.json) {
661
+ console.log(JSON.stringify({
662
+ success: true,
663
+ package: 'contextos-agents',
664
+ version,
665
+ projectDir: process.cwd(),
666
+ profile: selectedProfile || 'default',
667
+ agents: targetAgents,
668
+ withMcp: flags.withMcp,
669
+ minimal: flags.minimal,
670
+ }, null, 2));
671
+ process.exit(0);
538
672
  }
539
673
 
540
674
  console.log('\n Next steps:');
@@ -558,26 +692,12 @@ try {
558
692
  }
559
693
  console.log('');
560
694
 
561
- // ── --add-skill flag ────────────────────────────────────────────────────────
562
- if (flags.addSkill) {
563
- const ctxPath = path.join(targetPath, 'ctx.js');
564
- if (fs.existsSync(ctxPath)) {
565
- console.log(`Installing plugin skill: ${flags.addSkill}`);
566
- try {
567
- const { execFileSync } = require('child_process');
568
- execFileSync(process.execPath, [ctxPath, 'skill', 'add', flags.addSkill], {
569
- cwd: process.cwd(),
570
- stdio: 'inherit',
571
- });
572
- } catch (e) {
573
- console.warn(`[WARN] Skill install failed — run manually:`);
574
- console.warn(` node .agents/ctx.js skill add ${flags.addSkill}`);
575
- }
576
- }
577
- }
578
-
579
695
  } catch (error) {
580
- console.error('[ERROR] Installation failed:', error.message);
696
+ if (flags.json) {
697
+ console.error(JSON.stringify({ success: false, error: error.message }));
698
+ } else {
699
+ console.error('[ERROR] Installation failed:', error.message);
700
+ }
581
701
  process.exit(1);
582
702
  }
583
703
 
@@ -0,0 +1,106 @@
1
+ /**
2
+ * bin/lib/detector.js
3
+ * ContextOS — Full Stack & IDE Environment Detector
4
+ *
5
+ * Inspects the target repository to detect:
6
+ * 1. Project tech stack (Next.js, React, NestJS, FastAPI, etc.)
7
+ * 2. Active developer IDE / agent tools (Cursor, Claude, Zed, VSCode Copilot, Gemini)
8
+ * 3. Recommended profile and auto-export adapter targets
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const profiles = require('../../.agents/profiles.js');
16
+
17
+ /**
18
+ * Detects active IDEs and AI assistant configs in the project.
19
+ *
20
+ * @param {string} [projectDir=process.cwd()] - Project directory
21
+ * @returns {{ detected: string[], recommendedAgents: string[] }}
22
+ */
23
+ function detectIdeEnvironment(projectDir = process.cwd()) {
24
+ const detected = [];
25
+ const recommendedAgents = new Set();
26
+
27
+ // 1. Cursor
28
+ if (fs.existsSync(path.join(projectDir, '.cursor')) ||
29
+ fs.existsSync(path.join(projectDir, '.cursorrules')) ||
30
+ fs.existsSync(path.join(projectDir, '.cursor', 'rules'))) {
31
+ detected.push('Cursor');
32
+ recommendedAgents.add('cursor');
33
+ }
34
+
35
+ // 2. Claude Code
36
+ if (fs.existsSync(path.join(projectDir, 'CLAUDE.md')) ||
37
+ fs.existsSync(path.join(projectDir, '.claude'))) {
38
+ detected.push('Claude Code');
39
+ recommendedAgents.add('claude');
40
+ }
41
+
42
+ // 3. Zed
43
+ if (fs.existsSync(path.join(projectDir, '.zed'))) {
44
+ detected.push('Zed');
45
+ recommendedAgents.add('zed');
46
+ }
47
+
48
+ // 4. GitHub Copilot / VSCode
49
+ if (fs.existsSync(path.join(projectDir, '.github', 'copilot-instructions.md')) ||
50
+ fs.existsSync(path.join(projectDir, '.vscode'))) {
51
+ detected.push('GitHub Copilot');
52
+ recommendedAgents.add('copilot');
53
+ }
54
+
55
+ // 5. Aider
56
+ if (fs.existsSync(path.join(projectDir, '.aider.conf.yml')) ||
57
+ fs.existsSync(path.join(projectDir, 'CONVENTIONS.md'))) {
58
+ detected.push('Aider');
59
+ recommendedAgents.add('aider');
60
+ }
61
+
62
+ // 6. Gemini / Antigravity
63
+ if (fs.existsSync(path.join(projectDir, '.gemini')) ||
64
+ fs.existsSync(path.join(projectDir, 'GEMINI.md'))) {
65
+ detected.push('Google Gemini / Antigravity');
66
+ recommendedAgents.add('gemini');
67
+ }
68
+
69
+ // Default agent is gemini if none detected
70
+ if (recommendedAgents.size === 0) {
71
+ recommendedAgents.add('gemini');
72
+ }
73
+
74
+ return {
75
+ detected,
76
+ recommendedAgents: Array.from(recommendedAgents),
77
+ };
78
+ }
79
+
80
+ /**
81
+ * Performs unified tech stack and IDE environment detection.
82
+ *
83
+ * @param {string} [projectDir=process.cwd()] - Project directory
84
+ * @returns {Object} Full detection report
85
+ */
86
+ function detectProjectAttributes(projectDir = process.cwd()) {
87
+ const stack = profiles.detectStack(projectDir);
88
+ const ide = detectIdeEnvironment(projectDir);
89
+
90
+ return {
91
+ stack,
92
+ ide,
93
+ summary: {
94
+ technologies: stack.detected.length ? stack.detected : ['Generic JavaScript'],
95
+ ides: ide.detected.length ? ide.detected : ['Standard IDE'],
96
+ recommendedProfile: stack.recommendedProfile,
97
+ recommendedAgents: ide.recommendedAgents,
98
+ recommendedSkills: stack.recommendedSkills,
99
+ },
100
+ };
101
+ }
102
+
103
+ module.exports = {
104
+ detectIdeEnvironment,
105
+ detectProjectAttributes,
106
+ };