contextos-agents 1.6.0 → 1.6.1

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.
@@ -25,6 +25,7 @@ prefer_skills:
25
25
  exclude_skills:
26
26
  - ddd
27
27
  - microservices
28
+ - system-design
28
29
  - kubernetes
29
30
  - monitoring
30
31
  - cicd
package/.agents/ctx.js CHANGED
@@ -46,6 +46,10 @@ function printHelp() {
46
46
  console.log(' audit Alias for validate (check skills)');
47
47
  console.log(' validate Validate skill sources, frontmatter, deps & sync');
48
48
  console.log(' clean-worktrees Clean up lingering .swarm-worktrees and swarm/* branches');
49
+ console.log(' doctor Run project diagnostic health check');
50
+ console.log(' stats Display token context savings report');
51
+ console.log(' watch Start continuous file watcher and auto-sync daemon');
52
+ console.log(' init Show initialization guide');
49
53
  console.log(' install-skill <ref> Alias for skill add (install a plugin)');
50
54
  console.log(' skill add <ref> Install a plugin skill (GitHub or npm)');
51
55
  console.log(' skill remove <name> Uninstall a plugin skill');
@@ -363,6 +367,33 @@ if (command === 'export') {
363
367
 
364
368
  console.log(`✓ Cleaned up ${dirCount} worktree directory(ies) and ${branchCount} swarm branch(es).`);
365
369
 
370
+ // ── doctor ────────────────────────────────────────────────────────────────────
371
+ } else if (command === 'doctor') {
372
+ const doctorModule = require('./doctor.js');
373
+ doctorModule.runDoctor(process.cwd());
374
+
375
+ // ── stats ─────────────────────────────────────────────────────────────────────
376
+ } else if (command === 'stats') {
377
+ const statsModule = require('./stats.js');
378
+ statsModule.runStats(process.cwd());
379
+
380
+ // ── watch ─────────────────────────────────────────────────────────────────────
381
+ } else if (command === 'watch') {
382
+ const watchModule = require('./watch.js');
383
+ watchModule.runWatch(process.cwd());
384
+
385
+ // ── init ──────────────────────────────────────────────────────────────────────
386
+ } else if (command === 'init') {
387
+ console.log('\nContextOS — Project Initialization Guide\n');
388
+ console.log('To set up ContextOS in your project:');
389
+ console.log(' npx contextos Install .agents/ with auto-detected profile');
390
+ console.log(' npx contextos --minimal Install with minimal core skills');
391
+ console.log(' npx contextos --profile <name> Install with specific profile (mvp, startup, enterprise, etc.)');
392
+ console.log(' npx contextos --with-mcp Install with MCP execution server enabled');
393
+ console.log('\nAfter setup, verify your installation:');
394
+ console.log(' node .agents/ctx.js doctor');
395
+ console.log(' node .agents/ctx.js stats\n');
396
+
366
397
  // ── unknown ───────────────────────────────────────────────────────────────────
367
398
  } else {
368
399
  console.error(`Unknown command: ${command}`);
@@ -41570,121 +41570,6 @@ var require_browser = __commonJS({
41570
41570
  }
41571
41571
  });
41572
41572
 
41573
- // ../node_modules/has-flag/index.js
41574
- var require_has_flag = __commonJS({
41575
- "../node_modules/has-flag/index.js"(exports, module) {
41576
- "use strict";
41577
- module.exports = (flag, argv = process.argv) => {
41578
- const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
41579
- const position = argv.indexOf(prefix + flag);
41580
- const terminatorPosition = argv.indexOf("--");
41581
- return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
41582
- };
41583
- }
41584
- });
41585
-
41586
- // ../node_modules/supports-color/index.js
41587
- var require_supports_color = __commonJS({
41588
- "../node_modules/supports-color/index.js"(exports, module) {
41589
- "use strict";
41590
- var os7 = __require("os");
41591
- var tty = __require("tty");
41592
- var hasFlag = require_has_flag();
41593
- var { env } = process;
41594
- var forceColor;
41595
- if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
41596
- forceColor = 0;
41597
- } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
41598
- forceColor = 1;
41599
- }
41600
- if ("FORCE_COLOR" in env) {
41601
- if (env.FORCE_COLOR === "true") {
41602
- forceColor = 1;
41603
- } else if (env.FORCE_COLOR === "false") {
41604
- forceColor = 0;
41605
- } else {
41606
- forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
41607
- }
41608
- }
41609
- function translateLevel(level) {
41610
- if (level === 0) {
41611
- return false;
41612
- }
41613
- return {
41614
- level,
41615
- hasBasic: true,
41616
- has256: level >= 2,
41617
- has16m: level >= 3
41618
- };
41619
- }
41620
- function supportsColor(haveStream, streamIsTTY) {
41621
- if (forceColor === 0) {
41622
- return 0;
41623
- }
41624
- if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
41625
- return 3;
41626
- }
41627
- if (hasFlag("color=256")) {
41628
- return 2;
41629
- }
41630
- if (haveStream && !streamIsTTY && forceColor === void 0) {
41631
- return 0;
41632
- }
41633
- const min = forceColor || 0;
41634
- if (env.TERM === "dumb") {
41635
- return min;
41636
- }
41637
- if (process.platform === "win32") {
41638
- const osRelease = os7.release().split(".");
41639
- if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
41640
- return Number(osRelease[2]) >= 14931 ? 3 : 2;
41641
- }
41642
- return 1;
41643
- }
41644
- if ("CI" in env) {
41645
- if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
41646
- return 1;
41647
- }
41648
- return min;
41649
- }
41650
- if ("TEAMCITY_VERSION" in env) {
41651
- return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
41652
- }
41653
- if (env.COLORTERM === "truecolor") {
41654
- return 3;
41655
- }
41656
- if ("TERM_PROGRAM" in env) {
41657
- const version2 = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
41658
- switch (env.TERM_PROGRAM) {
41659
- case "iTerm.app":
41660
- return version2 >= 3 ? 3 : 2;
41661
- case "Apple_Terminal":
41662
- return 2;
41663
- }
41664
- }
41665
- if (/-256(color)?$/i.test(env.TERM)) {
41666
- return 2;
41667
- }
41668
- if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
41669
- return 1;
41670
- }
41671
- if ("COLORTERM" in env) {
41672
- return 1;
41673
- }
41674
- return min;
41675
- }
41676
- function getSupportLevel(stream2) {
41677
- const level = supportsColor(stream2, stream2 && stream2.isTTY);
41678
- return translateLevel(level);
41679
- }
41680
- module.exports = {
41681
- supportsColor: getSupportLevel,
41682
- stdout: translateLevel(supportsColor(true, tty.isatty(1))),
41683
- stderr: translateLevel(supportsColor(true, tty.isatty(2)))
41684
- };
41685
- }
41686
- });
41687
-
41688
41573
  // node_modules/debug/src/node.js
41689
41574
  var require_node = __commonJS({
41690
41575
  "node_modules/debug/src/node.js"(exports, module) {
@@ -41703,7 +41588,7 @@ var require_node = __commonJS({
41703
41588
  );
41704
41589
  exports.colors = [6, 2, 3, 4, 5, 1];
41705
41590
  try {
41706
- const supportsColor = require_supports_color();
41591
+ const supportsColor = __require("supports-color");
41707
41592
  if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
41708
41593
  exports.colors = [
41709
41594
  20,
@@ -414,6 +414,58 @@ function checkValidationJson(sourceSkills) {
414
414
  info(`[validation] ${pass} VALIDATION.json files are valid`);
415
415
  }
416
416
 
417
+ // ═════════════════════════════════════════════════════════════════════════════
418
+ // CHECK 9 — MCP Bundle Synchronization
419
+ // ═════════════════════════════════════════════════════════════════════════════
420
+ function checkMcpBundleSync() {
421
+ const mcpSrcDir = path.join(ROOT, 'contextos-mcp', 'src');
422
+ const bundlePath = path.join(AGENTS_DIR, 'mcp', 'server.mjs');
423
+
424
+ if (!fs.existsSync(mcpSrcDir)) {
425
+ return;
426
+ }
427
+
428
+ if (!fs.existsSync(bundlePath)) {
429
+ warn(`[mcp-sync] Missing compiled MCP server bundle at .agents/mcp/server.mjs. Run: cd contextos-mcp && npm run build:bundle`);
430
+ return;
431
+ }
432
+
433
+ const bundleStat = fs.statSync(bundlePath);
434
+ const bundleMtime = bundleStat.mtimeMs;
435
+
436
+ let newestSrcFile = null;
437
+ let newestSrcMtime = 0;
438
+
439
+ function walk(dir) {
440
+ let entries;
441
+ try {
442
+ entries = fs.readdirSync(dir, { withFileTypes: true });
443
+ } catch {
444
+ return;
445
+ }
446
+ for (const entry of entries) {
447
+ const full = path.join(dir, entry.name);
448
+ if (entry.isDirectory()) {
449
+ walk(full);
450
+ } else if (entry.isFile()) {
451
+ const stat = fs.statSync(full);
452
+ if (stat.mtimeMs > newestSrcMtime) {
453
+ newestSrcMtime = stat.mtimeMs;
454
+ newestSrcFile = path.relative(ROOT, full);
455
+ }
456
+ }
457
+ }
458
+ }
459
+
460
+ walk(mcpSrcDir);
461
+
462
+ if (newestSrcMtime > bundleMtime) {
463
+ warn(`[mcp-sync] Compiled MCP bundle (.agents/mcp/server.mjs) is older than source file ${newestSrcFile}. Run: cd contextos-mcp && npm run build:bundle`);
464
+ } else {
465
+ info(`[mcp-sync] Compiled MCP bundle (.agents/mcp/server.mjs) is up to date with contextos-mcp/src/`);
466
+ }
467
+ }
468
+
417
469
  // ═════════════════════════════════════════════════════════════════════════════
418
470
  // REPORT
419
471
  // ═════════════════════════════════════════════════════════════════════════════
@@ -487,6 +539,7 @@ function run() {
487
539
  checkContentQuality(sourceSkills);
488
540
  checkCostarHeaders(sourceSkills);
489
541
  checkValidationJson(sourceSkills);
542
+ checkMcpBundleSync();
490
543
 
491
544
  const passed = printReport();
492
545
  process.exit(passed ? 0 : 1);
package/README.md CHANGED
@@ -12,7 +12,8 @@ This is an open-source set of skills and behavioral rules for AI assistants. The
12
12
  You do not need to clone anything manually. Just open your terminal in the root of your project and run:
13
13
 
14
14
  ```bash
15
- npx contextos-agents
15
+ npx contextos
16
+ # or: npx contextos-agents
16
17
  ```
17
18
 
18
19
  The script will automatically detect your project tech stack, create the `.agents` folder, configure skills, and compile them for your AI agent.
@@ -20,15 +21,16 @@ The script will automatically detect your project tech stack, create the `.agent
20
21
  ### Options
21
22
 
22
23
  ```bash
23
- npx contextos-agents --help # Show all options
24
- npx contextos-agents --version # Show version
25
- npx contextos-agents --profile mvp # Install with specific profile (mvp, startup, enterprise, frontend, backend)
26
- npx contextos-agents --auto # Auto-detect tech stack and apply recommended profile
27
- npx contextos-agents --with-mcp # Install with MCP execution server enabled (.agents/mcp/)
28
- npx contextos-agents setup-mcp # Add MCP server to an existing .agents/ project
29
- npx contextos-agents --dry-run # Preview what will be installed
30
- npx contextos-agents --force # Overwrite an existing .agents/ folder
31
- npx contextos-agents --skip-compile # Skip auto-compilation step
24
+ npx contextos --help # Show all options
25
+ npx contextos --version # Show version
26
+ npx contextos --minimal # Install only 5 core skills (lightweight footprint)
27
+ npx contextos --profile mvp # Install with specific profile (mvp, startup, enterprise, frontend, backend)
28
+ npx contextos --auto # Auto-detect tech stack and apply recommended profile
29
+ npx contextos --with-mcp # Install with MCP execution server enabled (.agents/mcp/)
30
+ npx contextos setup-mcp # Add MCP server to an existing .agents/ project
31
+ npx contextos --dry-run # Preview what will be installed
32
+ npx contextos --force # Overwrite an existing .agents/ folder
33
+ npx contextos --skip-compile # Skip auto-compilation step
32
34
  ```
33
35
 
34
36
  ## Why ContextOS?
@@ -70,16 +72,17 @@ ContextOS allows you to tailor your AI rules to the project lifecycle and archit
70
72
 
71
73
  ```bash
72
74
  # Auto-detect tech stack in the current project
73
- node .agents/ctx.js detect
75
+ contextos detect
76
+ # or: node .agents/ctx.js detect
74
77
 
75
78
  # List available profiles and current active profile
76
- node .agents/ctx.js profile list
79
+ contextos profile list
77
80
 
78
81
  # Apply a profile
79
- node .agents/ctx.js profile apply mvp
82
+ contextos profile apply mvp
80
83
 
81
84
  # Recompile all agent exports for the active profile
82
- node .agents/ctx.js export all
85
+ contextos export all
83
86
  ```
84
87
 
85
88
  ## What's Inside?
@@ -146,9 +149,9 @@ ContextOS maps development phases directly to slash commands in your AI chat:
146
149
  | `/review` | Staff Engineer + Designer | 5-axis quality gate (correctness, architecture, security, performance, design) |
147
150
  | `/ship` | Release Engineer | Verify clean CI, lint checks, docs, and rollback plan before merging |
148
151
 
149
- ## Dynamic Skill Resolution & CLI (`ctx.js`)
152
+ ## Dynamic Skill Resolution & Unified CLI (`contextos` / `ctx.js`)
150
153
 
151
- The `.agents/ctx.js` file is the **Context Engine** — it resolves minimal skills on the fly and compiles exports for AI assistants.
154
+ ContextOS provides a unified CLI (`contextos` or `npx contextos`) and local engine (`.agents/ctx.js`) to resolve minimal skills on the fly, run health diagnostics, and compile exports for AI assistants.
152
155
 
153
156
  ### Dynamic Skill Resolution (`resolve` & `index`)
154
157
 
@@ -156,48 +159,74 @@ To prevent context bloat, ContextOS dynamically resolves the exact 2–4 skills
156
159
 
157
160
  ```bash
158
161
  # Resolve skills for a task description (English):
159
- node .agents/ctx.js resolve "Build an accessible modal component with React and Tailwind"
162
+ contextos resolve "Build an accessible modal component with React and Tailwind"
160
163
 
161
164
  # Output:
162
165
  # [DOMAIN: Frontend] [PHASE: Build] [ROLE: Senior Developer]
163
166
  # Skills loaded: ponytail-mindset, engineering-workflow, react, ui-ux-pro, web-accessibility
164
167
 
165
168
  # Multilingual support (Russian):
166
- node .agents/ctx.js resolve "создай модальное окно авторизации и напиши юнит-тесты"
169
+ contextos resolve "создай модальное окно авторизации и напиши юнит-тесты"
167
170
 
168
171
  # Output:
169
172
  # [DOMAIN: Frontend] [PHASE: Build] [ROLE: Senior Developer]
170
173
  # Skills loaded: ponytail-mindset, engineering-workflow, react, ui-ux-pro, security, testing
171
174
 
172
- # Resolve skills based on active files:
173
- node .agents/ctx.js resolve --files "app/api/auth/route.ts"
175
+ # Resolve skills based on active files (hybrid AST & config analysis):
176
+ contextos resolve --files "app/api/auth/route.ts"
174
177
 
175
178
  # Generate/update progressive lightweight skills index:
176
- node .agents/ctx.js index
179
+ contextos index
177
180
 
178
181
  # Clean up lingering .swarm-worktrees directories and orphaned swarm/* git branches:
179
- node .agents/ctx.js clean-worktrees
182
+ contextos clean-worktrees
183
+ ```
184
+
185
+ ### Diagnostic Health Check (`contextos doctor`)
186
+
187
+ Run a comprehensive pre-flight verification across your repository to ensure valid skills, profile alignment, symlinks, git worktree status, and compiler synchronization:
188
+
189
+ ```bash
190
+ contextos doctor
191
+ # or: npx contextos doctor
192
+ ```
193
+
194
+ ### Context Savings Analytics (`contextos stats`)
195
+
196
+ Measure your real token savings. Compares monolithic prompt injection against ContextOS dynamic skill resolution across frontend, backend, security, and full-stack tasks:
197
+
198
+ ```bash
199
+ contextos stats
200
+ ```
201
+
202
+ ### Continuous Auto-Sync Daemon (`contextos watch`)
203
+
204
+ Watch your source skills in `.agents/core/skills/` and automatically recompile adapter outputs (`.cursorrules`, `.zed/rules.md`, `.github/copilot-instructions.md`, etc.) upon saving:
205
+
206
+ ```bash
207
+ contextos watch
208
+ # or: npm run watch
180
209
  ```
181
210
 
182
211
  ### Supported Agents & Compilation
183
212
 
184
213
  | Agent | Command | Output Format |
185
214
  |-------|---------|---------------|
186
- | **Gemini / Antigravity** | `export gemini` | `.agents/generated/gemini/skills/` |
187
- | **Claude Code** | `export claude` | `.agents/generated/claude/skills/` |
188
- | **Cursor IDE** | `export cursor` | `.cursor/rules/*.mdc` (modular globs) + `.cursorrules` |
189
- | **GitHub Copilot** | `export copilot` | `.github/copilot-instructions.md` |
190
- | **Aider** | `export aider` | `.aider.conf.yml` + `CONVENTIONS.md` |
191
- | **Zed IDE** | `export zed` | `.zed/rules.md` + `.zed/prompts/*.md` |
215
+ | **Gemini / Antigravity** | `contextos export gemini` | `.agents/generated/gemini/skills/` |
216
+ | **Claude Code** | `contextos export claude` | `.agents/generated/claude/skills/` |
217
+ | **Cursor IDE** | `contextos export cursor` | `.cursor/rules/*.mdc` (modular globs) + `.cursorrules` |
218
+ | **GitHub Copilot** | `contextos export copilot` | `.github/copilot-instructions.md` |
219
+ | **Aider** | `contextos export aider` | `.aider.conf.yml` + `CONVENTIONS.md` |
220
+ | **Zed IDE** | `contextos export zed` | `.zed/rules.md` + `.zed/prompts/*.md` |
192
221
 
193
222
  ```bash
194
- node .agents/ctx.js export all # Compile for all agents
195
- node .agents/ctx.js export gemini # Compile for Gemini / Antigravity
196
- node .agents/ctx.js export claude # Compile for Claude Code
197
- node .agents/ctx.js export cursor # Compile for Cursor (.cursor/rules/*.mdc)
198
- node .agents/ctx.js export copilot # Compile for GitHub Copilot
199
- node .agents/ctx.js export aider # Compile for Aider
200
- node .agents/ctx.js export zed # Compile for Zed IDE
223
+ contextos export all # Compile for all agents (or: node .agents/ctx.js export all)
224
+ contextos export gemini # Compile for Gemini / Antigravity
225
+ contextos export claude # Compile for Claude Code
226
+ contextos export cursor # Compile for Cursor (.cursor/rules/*.mdc)
227
+ contextos export copilot # Compile for GitHub Copilot
228
+ contextos export aider # Compile for Aider
229
+ contextos export zed # Compile for Zed IDE
201
230
  ```
202
231
 
203
232
  ### Pre-Compiled Artifacts & Git Architecture
@@ -241,13 +270,14 @@ You can expand your `.agents` folder with community plugins or validate your own
241
270
 
242
271
  ```bash
243
272
  # Launch the interactive skill installer to browse and install community skills
244
- npx contextos-agents install-skill
273
+ contextos install-skill
274
+ # or: npx contextos install-skill
245
275
 
246
276
  # Or install a specific skill from a GitHub repository automatically
247
- npx contextos-agents install-skill --from-repo kok-o/awesome-skill
277
+ contextos install-skill --from-repo kok-o/awesome-skill
248
278
 
249
279
  # Validate your local skills (checks frontmatter, dependencies, and sync)
250
- npx contextos-agents audit
280
+ contextos audit
251
281
  ```
252
282
 
253
283
  ## ContextOS MCP Server & Autonomous Multi-Agent Swarm
@@ -312,39 +342,39 @@ Add ContextOS to your IDE's MCP settings (e.g. in `.agents/mcp_config.json`):
312
342
 
313
343
  Tests use the **Node.js built-in test runner** for the core framework and **Vitest** for the MCP engine — zero external test bloat.
314
344
 
315
- ### 1. Root Test Suite (121 tests)
345
+ ### 1. Root Test Suite (131 tests)
316
346
 
317
347
  ```bash
318
348
  npm test
319
349
  ```
320
350
 
321
351
  ```text
322
- # tests 121
352
+ # tests 131
323
353
  # suites 27
324
- # pass 121
354
+ # pass 131
325
355
  # fail 0
326
356
  ```
327
357
 
328
- ### 2. MCP Server Test Suite (428 tests)
358
+ ### 2. MCP Server Test Suite (440 tests)
329
359
 
330
360
  ```bash
331
361
  cd contextos-mcp && npm test
332
362
  ```
333
363
 
334
364
  ```text
335
- Test Files 24 passed (24)
336
- Tests 428 passed (428)
365
+ Test Files 25 passed | 1 skipped (26)
366
+ Tests 440 passed | 13 skipped (453)
337
367
  ```
338
368
 
339
369
  **Test coverage:**
340
370
 
341
- - `tests/install.test.js` — installer CLI flags (--help, --dry-run, --force)
342
- - `tests/export.test.js` — ctx.js export for gemini, claude, cursor (.mdc rules), copilot, aider
371
+ - `tests/install.test.js` — installer CLI flags (--help, --minimal, --dry-run, --force)
372
+ - `tests/export.test.js` — ctx.js export for gemini, claude, cursor (.mdc rules), copilot, aider, zed
343
373
  - `tests/skills.test.js` — validates all skill source files and frontmatter
344
374
  - `tests/profile.test.js` — profile resolution, stack auto-detection, and skill filtering
345
375
  - `tests/validate.test.js` — validator rules, dependency graph, and sync checks
346
376
  - `tests/plugins.test.js` — plugin lockfile, registry fetching, and security checks
347
- - `tests/resolver.test.js` — dynamic skill resolution, progressive index, and bilingual prompt matching
377
+ - `tests/resolver.test.js` — dynamic skill resolution, AST import graph analysis, progressive index, and bilingual prompt matching
348
378
  - `tests/benchmark.test.js` — benchmark scoring engine, static AST checks, runtime sandbox, and reporters
349
379
  - `contextos-mcp/tests/unit/session-persistence.test.ts` — session disk persistence, thread state tracking, and orphan purge
350
380
  - `contextos-mcp/tests/unit/contextos-tools.test.ts` — all 6 MCP tool handlers and validation
package/bin/index.js CHANGED
@@ -95,65 +95,69 @@ Examples:
95
95
  // ── Top-level Commands & Proxy Routing ────────────────────────────────────────
96
96
  const mainCommand = args[0] && !args[0].startsWith('-') ? args[0] : null;
97
97
 
98
- // Doctor diagnostic health check
99
- if (mainCommand === 'doctor') {
100
- let doctorModule;
101
- const localDoctor = path.join(process.cwd(), '.agents', 'doctor.js');
102
- if (fs.existsSync(localDoctor)) {
103
- doctorModule = require(localDoctor);
104
- } else {
105
- doctorModule = require('../.agents/doctor.js');
98
+ // Proxy commands to .agents/ctx.js when executed in a ContextOS project
99
+ const PROXY_COMMANDS = [
100
+ 'profile', 'export', 'validate', 'resolve', 'skill', 'index',
101
+ 'clean-worktrees', 'doctor', 'stats', 'watch', 'init'
102
+ ];
103
+
104
+ const ctxPath = path.join(process.cwd(), '.agents', 'ctx.js');
105
+ const hasLocalCtx = fs.existsSync(ctxPath);
106
+
107
+ if (mainCommand && PROXY_COMMANDS.includes(mainCommand) && hasLocalCtx) {
108
+ const { execFileSync } = require('child_process');
109
+ try {
110
+ execFileSync(process.execPath, [ctxPath, ...args], { stdio: 'inherit' });
111
+ } catch (e) {
112
+ process.exit(e.status || 1);
106
113
  }
114
+ process.exit(0);
115
+ }
116
+
117
+ // Fallbacks when running outside an initialized .agents/ directory
118
+ if (mainCommand === 'doctor') {
119
+ const doctorModule = require('../.agents/doctor.js');
107
120
  doctorModule.runDoctor(process.cwd());
108
121
  process.exit(0);
109
122
  }
110
123
 
111
- // Context savings statistics report
112
124
  if (mainCommand === 'stats') {
113
- let statsModule;
114
- const localStats = path.join(process.cwd(), '.agents', 'stats.js');
115
- if (fs.existsSync(localStats)) {
116
- statsModule = require(localStats);
117
- } else {
118
- statsModule = require('../.agents/stats.js');
119
- }
125
+ const statsModule = require('../.agents/stats.js');
120
126
  statsModule.runStats(process.cwd());
121
127
  process.exit(0);
122
128
  }
123
129
 
124
- // Background auto-sync file watcher daemon
125
130
  if (mainCommand === 'watch') {
126
- let watchModule;
127
- const localWatch = path.join(process.cwd(), '.agents', 'watch.js');
128
- if (fs.existsSync(localWatch)) {
129
- watchModule = require(localWatch);
130
- } else {
131
- watchModule = require('../.agents/watch.js');
132
- }
131
+ const watchModule = require('../.agents/watch.js');
133
132
  watchModule.runWatch(process.cwd());
134
133
  }
135
134
 
136
- // Proxy commands to .agents/ctx.js when executed in a ContextOS project
137
- const PROXY_COMMANDS = ['profile', 'export', 'validate', 'resolve', 'skill', 'index', 'clean-worktrees'];
138
- if (mainCommand && PROXY_COMMANDS.includes(mainCommand)) {
139
- const ctxPath = path.join(process.cwd(), '.agents', 'ctx.js');
140
- if (!fs.existsSync(ctxPath)) {
141
- console.error('[ERROR] .agents/ctx.js not found in current directory.');
142
- console.error(' Are you in a ContextOS project? Run `contextos` or `npx contextos-agents` first.');
143
- process.exit(1);
144
- }
145
- const { execFileSync } = require('child_process');
146
- try {
147
- execFileSync(process.execPath, [ctxPath, ...args], { stdio: 'inherit' });
148
- } catch (e) {
149
- process.exit(e.status || 1);
150
- }
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
+ `);
151
149
  process.exit(0);
152
150
  }
153
151
 
152
+ const PROJECT_ONLY_COMMANDS = ['profile', 'export', 'validate', 'resolve', 'skill', 'index', 'clean-worktrees'];
153
+ if (mainCommand && PROJECT_ONLY_COMMANDS.includes(mainCommand) && !hasLocalCtx) {
154
+ console.error('[ERROR] .agents/ctx.js not found in current directory.');
155
+ console.error(' Are you in a ContextOS project? Run `contextos` or `npx contextos-agents` first.');
156
+ process.exit(1);
157
+ }
158
+
154
159
  if (mainCommand === 'audit') {
155
- const ctxPath = path.join(process.cwd(), '.agents', 'ctx.js');
156
- if (!fs.existsSync(ctxPath)) {
160
+ if (!hasLocalCtx) {
157
161
  console.error('[ERROR] .agents/ctx.js not found. Are you in a ContextOS project?');
158
162
  process.exit(1);
159
163
  }
@@ -198,10 +202,10 @@ if (mainCommand === 'install-skill') {
198
202
  }
199
203
  process.exit(0);
200
204
  } else {
201
- // Interactive menu
205
+ // Interactive menu using standard library readline
202
206
  (async () => {
203
207
  try {
204
- const inquirer = require('inquirer');
208
+ const readline = require('readline');
205
209
  const https = require('https');
206
210
 
207
211
  console.log('Fetching community skills from registry...');
@@ -210,33 +214,68 @@ if (mainCommand === 'install-skill') {
210
214
  https.get('https://raw.githubusercontent.com/kok-o/contextos-agents/main/registry.json', (res) => {
211
215
  let data = '';
212
216
  res.on('data', chunk => data += chunk);
213
- res.on('end', () => resolve(JSON.parse(data)));
217
+ res.on('end', () => {
218
+ try {
219
+ resolve(JSON.parse(data));
220
+ } catch (err) {
221
+ reject(err);
222
+ }
223
+ });
214
224
  }).on('error', reject);
215
225
  });
216
226
 
217
227
  const registry = await fetchRegistry();
218
- const choices = registry.skills.map(s => ({
219
- name: `${s.name} - ${s.description}`,
228
+ const skillsList = (registry.skills || []).map((s, idx) => ({
229
+ idx: idx + 1,
230
+ name: s.name,
231
+ desc: s.description || '',
220
232
  value: s.github ? `${s.github}${s.path ? '/' + s.path : ''}` : s.npm
221
233
  }));
222
-
223
- const answers = await inquirer.prompt([
224
- {
225
- type: 'checkbox',
226
- name: 'selectedSkills',
227
- message: 'Select skills to install:',
228
- choices
229
- }
230
- ]);
231
-
232
- if (!answers.selectedSkills || answers.selectedSkills.length === 0) {
233
- console.log('No skills selected.');
234
+
235
+ if (skillsList.length === 0) {
236
+ console.log('No community skills found in registry.');
234
237
  process.exit(0);
235
238
  }
236
-
239
+
240
+ console.log('\nAvailable community skills:\n');
241
+ for (const item of skillsList) {
242
+ console.log(` [${item.idx}] ${item.name.padEnd(20)} ${item.desc}`);
243
+ }
244
+ console.log('\nEnter skill numbers to install (comma-separated, e.g. 1, 3) or press Enter to cancel:');
245
+
246
+ const rl = readline.createInterface({
247
+ input: process.stdin,
248
+ output: process.stdout,
249
+ });
250
+
251
+ const answer = await new Promise((resolve) => {
252
+ rl.question('> ', (ans) => {
253
+ rl.close();
254
+ resolve(ans.trim());
255
+ });
256
+ });
257
+
258
+ if (!answer) {
259
+ console.log('No skills selected. Operation cancelled.');
260
+ process.exit(0);
261
+ }
262
+
263
+ const selectedIndices = answer
264
+ .split(/[\s,]+/)
265
+ .map(n => parseInt(n, 10))
266
+ .filter(n => !isNaN(n) && n >= 1 && n <= skillsList.length);
267
+
268
+ const selectedSkills = selectedIndices.map(n => skillsList[n - 1].value);
269
+
270
+ if (selectedSkills.length === 0) {
271
+ console.log('No valid skill numbers selected.');
272
+ process.exit(0);
273
+ }
274
+
237
275
  const { execFileSync } = require('child_process');
238
- for (const skillRef of answers.selectedSkills) {
276
+ for (const skillRef of selectedSkills) {
239
277
  try {
278
+ console.log(`\nInstalling ${skillRef}...`);
240
279
  execFileSync(process.execPath, [ctxPath, 'skill', 'add', skillRef], { stdio: 'inherit' });
241
280
  } catch (e) {
242
281
  console.error(`Failed to install ${skillRef}`);
@@ -244,9 +283,6 @@ if (mainCommand === 'install-skill') {
244
283
  }
245
284
  } catch (error) {
246
285
  console.error('Failed to run interactive installer:', error.message);
247
- if (error.code === 'MODULE_NOT_FOUND' && error.message.includes('inquirer')) {
248
- console.error('It seems inquirer is not installed. Did you run npm install?');
249
- }
250
286
  process.exit(1);
251
287
  }
252
288
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contextos-agents",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "Install a .agents folder into your project to teach AI assistants best practices: UI/UX, architecture, security, and engineering workflow skills.",
5
5
  "bin": {
6
6
  "contextos": "./bin/index.js",
@@ -71,7 +71,5 @@
71
71
  "devDependencies": {
72
72
  "markdownlint-cli": "^0.43.0"
73
73
  },
74
- "dependencies": {
75
- "inquirer": "^8.2.7"
76
- }
74
+ "dependencies": {}
77
75
  }