contextos-agents 2.1.0 → 2.2.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 (192) hide show
  1. package/.agents/adapters/aider/export.js +2 -2
  2. package/.agents/adapters/claude/export.js +53 -2
  3. package/.agents/adapters/drift-detector.js +6 -3
  4. package/.agents/adapters/pure-compiler.js +18 -6
  5. package/.agents/ctx.js +13 -8
  6. package/.agents/plugins.js +347 -26
  7. package/.agents/profiles.js +32 -11
  8. package/README.md +38 -3
  9. package/bin/commands/hook.js +50 -12
  10. package/bin/commands/scan.js +10 -3
  11. package/bin/index.js +165 -53
  12. package/bin/lib/git-snapshot.js +70 -43
  13. package/bin/lib/scan.js +108 -27
  14. package/bin/lib/ui.js +140 -0
  15. package/catalog/skills/adapters/EXAMPLES.md +19 -0
  16. package/catalog/skills/adapters/SKILL.md +101 -0
  17. package/catalog/skills/adapters/TROUBLESHOOTING.md +7 -0
  18. package/catalog/skills/adapters/VALIDATION.json +12 -0
  19. package/catalog/skills/adapters/skill.yaml +13 -0
  20. package/catalog/skills/api-design/EXAMPLES.md +91 -0
  21. package/catalog/skills/api-design/SKILL.md +63 -0
  22. package/catalog/skills/api-design/TROUBLESHOOTING.md +54 -0
  23. package/catalog/skills/api-design/VALIDATION.json +11 -0
  24. package/catalog/skills/api-design/skill.yaml +14 -0
  25. package/catalog/skills/architecture-diagrams/SKILL.md +108 -0
  26. package/catalog/skills/architecture-diagrams/VALIDATION.json +12 -0
  27. package/catalog/skills/architecture-diagrams/skill.yaml +9 -0
  28. package/catalog/skills/brutalist-design/EXAMPLES.md +59 -0
  29. package/catalog/skills/brutalist-design/SKILL.md +150 -0
  30. package/catalog/skills/brutalist-design/VALIDATION.json +12 -0
  31. package/catalog/skills/brutalist-design/skill.yaml +10 -0
  32. package/catalog/skills/ci-cd/EXAMPLES.md +79 -0
  33. package/catalog/skills/ci-cd/SKILL.md +69 -0
  34. package/catalog/skills/ci-cd/TROUBLESHOOTING.md +52 -0
  35. package/catalog/skills/ci-cd/VALIDATION.json +11 -0
  36. package/catalog/skills/ci-cd/skill.yaml +13 -0
  37. package/catalog/skills/database/EXAMPLES.md +74 -0
  38. package/catalog/skills/database/SKILL.md +101 -0
  39. package/catalog/skills/database/TROUBLESHOOTING.md +18 -0
  40. package/catalog/skills/database/VALIDATION.json +11 -0
  41. package/catalog/skills/database/skill.yaml +14 -0
  42. package/catalog/skills/ddd/EXAMPLES.md +42 -0
  43. package/catalog/skills/ddd/SKILL.md +247 -0
  44. package/catalog/skills/ddd/TROUBLESHOOTING.md +19 -0
  45. package/catalog/skills/ddd/VALIDATION.json +12 -0
  46. package/catalog/skills/ddd/skill.yaml +14 -0
  47. package/catalog/skills/decisions/EXAMPLES.md +35 -0
  48. package/catalog/skills/decisions/SKILL.md +90 -0
  49. package/catalog/skills/decisions/TROUBLESHOOTING.md +13 -0
  50. package/catalog/skills/decisions/VALIDATION.json +12 -0
  51. package/catalog/skills/decisions/skill.yaml +13 -0
  52. package/catalog/skills/docker/EXAMPLES.md +56 -0
  53. package/catalog/skills/docker/SKILL.md +169 -0
  54. package/catalog/skills/docker/TROUBLESHOOTING.md +18 -0
  55. package/catalog/skills/docker/VALIDATION.json +11 -0
  56. package/catalog/skills/docker/skill.yaml +13 -0
  57. package/catalog/skills/fastapi/EXAMPLES.md +36 -0
  58. package/catalog/skills/fastapi/SKILL.md +171 -0
  59. package/catalog/skills/fastapi/TROUBLESHOOTING.md +19 -0
  60. package/catalog/skills/fastapi/VALIDATION.json +12 -0
  61. package/catalog/skills/fastapi/skill.yaml +14 -0
  62. package/catalog/skills/generators/EXAMPLES.md +19 -0
  63. package/catalog/skills/generators/SKILL.md +110 -0
  64. package/catalog/skills/generators/TROUBLESHOOTING.md +7 -0
  65. package/catalog/skills/generators/VALIDATION.json +12 -0
  66. package/catalog/skills/generators/skill.yaml +22 -0
  67. package/catalog/skills/generators/templates/API.md +77 -0
  68. package/catalog/skills/generators/templates/ARCHITECTURE.md +70 -0
  69. package/catalog/skills/generators/templates/DATABASE.md +42 -0
  70. package/catalog/skills/generators/templates/DECISION.md +46 -0
  71. package/catalog/skills/generators/templates/PRD.md +67 -0
  72. package/catalog/skills/generators/templates/PROJECT_GRAPH.md +56 -0
  73. package/catalog/skills/generators/templates/ROADMAP.md +51 -0
  74. package/catalog/skills/generators/templates/TASKS.md +43 -0
  75. package/catalog/skills/generators/templates/UI.md +73 -0
  76. package/catalog/skills/graphify/EXAMPLES.md +73 -0
  77. package/catalog/skills/graphify/SKILL.md +130 -0
  78. package/catalog/skills/graphify/VALIDATION.json +12 -0
  79. package/catalog/skills/graphify/skill.yaml +13 -0
  80. package/catalog/skills/impeccable-design/EXAMPLES.md +26 -0
  81. package/catalog/skills/impeccable-design/SKILL.md +201 -0
  82. package/catalog/skills/impeccable-design/TROUBLESHOOTING.md +19 -0
  83. package/catalog/skills/impeccable-design/VALIDATION.json +12 -0
  84. package/catalog/skills/impeccable-design/skill.yaml +15 -0
  85. package/catalog/skills/interview-me/SKILL.md +97 -0
  86. package/catalog/skills/interview-me/VALIDATION.json +12 -0
  87. package/catalog/skills/interview-me/skill.yaml +9 -0
  88. package/catalog/skills/microservices/EXAMPLES.md +38 -0
  89. package/catalog/skills/microservices/SKILL.md +164 -0
  90. package/catalog/skills/microservices/TROUBLESHOOTING.md +19 -0
  91. package/catalog/skills/microservices/VALIDATION.json +12 -0
  92. package/catalog/skills/microservices/skill.yaml +14 -0
  93. package/catalog/skills/minimalist-design/EXAMPLES.md +58 -0
  94. package/catalog/skills/minimalist-design/SKILL.md +113 -0
  95. package/catalog/skills/minimalist-design/VALIDATION.json +12 -0
  96. package/catalog/skills/minimalist-design/skill.yaml +10 -0
  97. package/catalog/skills/nestjs/EXAMPLES.md +40 -0
  98. package/catalog/skills/nestjs/SKILL.md +139 -0
  99. package/catalog/skills/nestjs/TROUBLESHOOTING.md +19 -0
  100. package/catalog/skills/nestjs/VALIDATION.json +12 -0
  101. package/catalog/skills/nestjs/skill.yaml +14 -0
  102. package/catalog/skills/nextjs/EXAMPLES.md +40 -0
  103. package/catalog/skills/nextjs/SKILL.md +163 -0
  104. package/catalog/skills/nextjs/TROUBLESHOOTING.md +19 -0
  105. package/catalog/skills/nextjs/VALIDATION.json +12 -0
  106. package/catalog/skills/nextjs/skill.yaml +14 -0
  107. package/catalog/skills/node/EXAMPLES.md +80 -0
  108. package/catalog/skills/node/SKILL.md +128 -0
  109. package/catalog/skills/node/TROUBLESHOOTING.md +19 -0
  110. package/catalog/skills/node/VALIDATION.json +12 -0
  111. package/catalog/skills/node/skill.yaml +14 -0
  112. package/catalog/skills/performance/EXAMPLES.md +30 -0
  113. package/catalog/skills/performance/SKILL.md +75 -0
  114. package/catalog/skills/performance/TROUBLESHOOTING.md +19 -0
  115. package/catalog/skills/performance/VALIDATION.json +12 -0
  116. package/catalog/skills/performance/skill.yaml +14 -0
  117. package/catalog/skills/react/EXAMPLES.md +79 -0
  118. package/catalog/skills/react/SKILL.md +132 -0
  119. package/catalog/skills/react/TROUBLESHOOTING.md +19 -0
  120. package/catalog/skills/react/VALIDATION.json +12 -0
  121. package/catalog/skills/react/skill.yaml +14 -0
  122. package/catalog/skills/react-best-practices/SKILL.md +158 -0
  123. package/catalog/skills/react-best-practices/VALIDATION.json +12 -0
  124. package/catalog/skills/react-best-practices/skill.yaml +13 -0
  125. package/catalog/skills/redesign-audit/SKILL.md +117 -0
  126. package/catalog/skills/redesign-audit/VALIDATION.json +12 -0
  127. package/catalog/skills/redesign-audit/skill.yaml +9 -0
  128. package/catalog/skills/security-audit/EXAMPLES.md +79 -0
  129. package/catalog/skills/security-audit/SKILL.md +91 -0
  130. package/catalog/skills/security-audit/TROUBLESHOOTING.md +46 -0
  131. package/catalog/skills/security-audit/VALIDATION.json +11 -0
  132. package/catalog/skills/security-audit/skill.yaml +14 -0
  133. package/catalog/skills/soft-design/EXAMPLES.md +51 -0
  134. package/catalog/skills/soft-design/SKILL.md +108 -0
  135. package/catalog/skills/soft-design/VALIDATION.json +12 -0
  136. package/catalog/skills/soft-design/skill.yaml +10 -0
  137. package/catalog/skills/state-management/EXAMPLES.md +56 -0
  138. package/catalog/skills/state-management/SKILL.md +168 -0
  139. package/catalog/skills/state-management/TROUBLESHOOTING.md +18 -0
  140. package/catalog/skills/state-management/VALIDATION.json +11 -0
  141. package/catalog/skills/state-management/skill.yaml +14 -0
  142. package/catalog/skills/subagent-orchestrator/SKILL.md +117 -0
  143. package/catalog/skills/subagent-orchestrator/VALIDATION.json +12 -0
  144. package/catalog/skills/subagent-orchestrator/skill.yaml +9 -0
  145. package/catalog/skills/system-design/EXAMPLES.md +75 -0
  146. package/catalog/skills/system-design/SKILL.md +419 -0
  147. package/catalog/skills/system-design/TROUBLESHOOTING.md +19 -0
  148. package/catalog/skills/system-design/VALIDATION.json +12 -0
  149. package/catalog/skills/system-design/skill.yaml +14 -0
  150. package/catalog/skills/terraform/EXAMPLES.md +74 -0
  151. package/catalog/skills/terraform/SKILL.md +55 -0
  152. package/catalog/skills/terraform/TROUBLESHOOTING.md +53 -0
  153. package/catalog/skills/terraform/VALIDATION.json +11 -0
  154. package/catalog/skills/terraform/skill.yaml +14 -0
  155. package/catalog/skills/testing/EXAMPLES.md +122 -0
  156. package/catalog/skills/testing/SKILL.md +70 -0
  157. package/catalog/skills/testing/TROUBLESHOOTING.md +18 -0
  158. package/catalog/skills/testing/VALIDATION.json +11 -0
  159. package/catalog/skills/testing/skill.yaml +14 -0
  160. package/catalog/skills/typescript/EXAMPLES.md +64 -0
  161. package/catalog/skills/typescript/SKILL.md +112 -0
  162. package/catalog/skills/typescript/TROUBLESHOOTING.md +19 -0
  163. package/catalog/skills/typescript/VALIDATION.json +12 -0
  164. package/catalog/skills/typescript/skill.yaml +14 -0
  165. package/catalog/skills/ui-design/EXAMPLES.md +21 -0
  166. package/catalog/skills/ui-design/SKILL.md +124 -0
  167. package/catalog/skills/ui-design/TROUBLESHOOTING.md +19 -0
  168. package/catalog/skills/ui-design/VALIDATION.json +12 -0
  169. package/catalog/skills/ui-design/skill.yaml +16 -0
  170. package/catalog/skills/ui-ux-pro/EXAMPLES.md +62 -0
  171. package/catalog/skills/ui-ux-pro/SKILL.md +418 -0
  172. package/catalog/skills/ui-ux-pro/TROUBLESHOOTING.md +19 -0
  173. package/catalog/skills/ui-ux-pro/VALIDATION.json +12 -0
  174. package/catalog/skills/ui-ux-pro/skill.yaml +14 -0
  175. package/catalog/skills/ux-design/EXAMPLES.md +36 -0
  176. package/catalog/skills/ux-design/SKILL.md +116 -0
  177. package/catalog/skills/ux-design/TROUBLESHOOTING.md +19 -0
  178. package/catalog/skills/ux-design/VALIDATION.json +12 -0
  179. package/catalog/skills/ux-design/skill.yaml +16 -0
  180. package/catalog/skills/vercel-optimize/SKILL.md +83 -0
  181. package/catalog/skills/vercel-optimize/VALIDATION.json +12 -0
  182. package/catalog/skills/vercel-optimize/scripts/collect-signals.mjs +131 -0
  183. package/catalog/skills/vercel-optimize/scripts/gate-investigations.mjs +142 -0
  184. package/catalog/skills/vercel-optimize/scripts/merge-signals.mjs +143 -0
  185. package/catalog/skills/vercel-optimize/scripts/scan-codebase.mjs +174 -0
  186. package/catalog/skills/vercel-optimize/skill.yaml +15 -0
  187. package/catalog/skills/web-accessibility/EXAMPLES.md +39 -0
  188. package/catalog/skills/web-accessibility/SKILL.md +151 -0
  189. package/catalog/skills/web-accessibility/TROUBLESHOOTING.md +19 -0
  190. package/catalog/skills/web-accessibility/VALIDATION.json +12 -0
  191. package/catalog/skills/web-accessibility/skill.yaml +14 -0
  192. package/package.json +3 -2
@@ -17,7 +17,28 @@ const HOOK_MARKER_START = '# BEGIN CONTEXTOS HOOK';
17
17
  const HOOK_MARKER_END = '# END CONTEXTOS HOOK';
18
18
 
19
19
  const HOOK_PAYLOAD = `${HOOK_MARKER_START}
20
- npx contextos-agents scan --staged --enforce || exit 1
20
+ CTX_SCOPE_ARG=""
21
+ if [ -f ".agents/task-scope.json" ]; then
22
+ CTX_SCOPE_ARG="--scope .agents/task-scope.json"
23
+ fi
24
+
25
+ if [ -f "./node_modules/.bin/contextos" ]; then
26
+ ./node_modules/.bin/contextos scan --staged --enforce --placeholders $CTX_SCOPE_ARG
27
+ CTX_STATUS=$?
28
+ elif [ -f "./node_modules/.bin/contextos-agents" ]; then
29
+ ./node_modules/.bin/contextos-agents scan --staged --enforce --placeholders $CTX_SCOPE_ARG
30
+ CTX_STATUS=$?
31
+ elif [ -f "./bin/index.js" ] && [ -f "./package.json" ]; then
32
+ node ./bin/index.js scan --staged --enforce --placeholders $CTX_SCOPE_ARG
33
+ CTX_STATUS=$?
34
+ else
35
+ echo "[ERROR] ContextOS local runner not found. Install locally (npm i -D contextos-agents) before committing." >&2
36
+ exit 2
37
+ fi
38
+
39
+ if [ $CTX_STATUS -ne 0 ]; then
40
+ exit $CTX_STATUS
41
+ fi
21
42
  ${HOOK_MARKER_END}`;
22
43
 
23
44
  function installHook(cwd = process.cwd()) {
@@ -37,19 +58,36 @@ function installHook(cwd = process.cwd()) {
37
58
  if (fs.existsSync(hookFile)) {
38
59
  const existing = fs.readFileSync(hookFile, 'utf8');
39
60
 
40
- if (existing.includes(HOOK_MARKER_START)) {
41
- // Replace existing block cleanly
42
- const regex = new RegExp(`${HOOK_MARKER_START}[\\s\\S]*?${HOOK_MARKER_END}`);
43
- const updated = existing.replace(regex, HOOK_PAYLOAD);
44
- fs.writeFileSync(hookFile, updated, 'utf8');
45
- console.log(`✓ ContextOS pre-commit hook updated in ${hookFile}`);
61
+ // Validate shebang if present
62
+ const shebangMatch = existing.match(/^#!([^\r\n]+)/);
63
+ if (shebangMatch) {
64
+ const interpreter = shebangMatch[1].toLowerCase();
65
+ const isShell = /\b(sh|bash|zsh|dash)\b/.test(interpreter);
66
+ if (!isShell) {
67
+ console.error(`[ERROR] Pre-commit hook uses non-shell interpreter (${shebangMatch[0]}). ContextOS pre-commit hook requires POSIX shell.`);
68
+ process.exit(1);
69
+ }
70
+ }
71
+
72
+ // Strip any existing ContextOS block (e.g. legacy trailing block from v2.1.0)
73
+ const stripped = existing.includes(HOOK_MARKER_START)
74
+ ? existing.replace(new RegExp(`\\n?${HOOK_MARKER_START}[\\s\\S]*?${HOOK_MARKER_END}\\n?`, 'g'), '').trim()
75
+ : existing.trim();
76
+
77
+ // Place HOOK_PAYLOAD right after shebang so it runs first and cannot be bypassed by user 'exit 0'
78
+ let updated;
79
+ const strippedShebangMatch = stripped.match(/^#!.*(?:\r?\n|$)/);
80
+ if (strippedShebangMatch) {
81
+ const shebang = strippedShebangMatch[0];
82
+ const rest = stripped.slice(shebang.length).trim();
83
+ const sep = rest ? '\n\n' : '\n';
84
+ updated = `${shebang.trimEnd()}\n\n${HOOK_PAYLOAD}${sep}${rest}`;
46
85
  } else {
47
- // Append while preserving user's existing hook script
48
- const separator = existing.endsWith('\n') ? '\n' : '\n\n';
49
- const updated = existing + separator + HOOK_PAYLOAD + '\n';
50
- fs.writeFileSync(hookFile, updated, 'utf8');
51
- console.log(`✓ ContextOS pre-commit hook appended to existing hook in ${hookFile}`);
86
+ updated = `#!/bin/sh\n\n${HOOK_PAYLOAD}${stripped ? `\n\n${stripped}` : ''}`;
52
87
  }
88
+
89
+ fs.writeFileSync(hookFile, updated.trimEnd() + '\n', 'utf8');
90
+ console.log(`✓ ContextOS pre-commit hook installed in ${hookFile}`);
53
91
  } else {
54
92
  // Fresh hook installation with shebang
55
93
  const fresh = `#!/bin/sh\n\n${HOOK_PAYLOAD}\n`;
@@ -7,9 +7,10 @@
7
7
 
8
8
  'use strict';
9
9
 
10
+ const path = require('path');
10
11
  const { runScan } = require('../lib/scan.js');
11
12
 
12
- function scanCommand(args, flags) {
13
+ function scanCommand(args, flags = {}) {
13
14
  const isJson = flags.json || args.includes('--json');
14
15
  const enforce = flags.enforce || args.includes('--enforce');
15
16
  const checkPlaceholders = flags.placeholders || args.includes('--placeholders');
@@ -18,8 +19,13 @@ function scanCommand(args, flags) {
18
19
  const scopeIdx = args.indexOf('--scope');
19
20
  const scopeFile = scopeIdx !== -1 && args[scopeIdx + 1] ? args[scopeIdx + 1] : null;
20
21
 
22
+ const projectIdx = args.indexOf('--project');
23
+ const projectArg = projectIdx !== -1 && args[projectIdx + 1] ? args[projectIdx + 1] : null;
24
+ const targetProject = flags.project || projectArg;
25
+ const projectDir = targetProject ? path.resolve(targetProject) : process.cwd();
26
+
21
27
  const result = runScan({
22
- cwd: process.cwd(),
28
+ cwd: projectDir,
23
29
  staged: true,
24
30
  secrets: checkSecrets,
25
31
  placeholders: checkPlaceholders,
@@ -43,6 +49,7 @@ function scanCommand(args, flags) {
43
49
 
44
50
  console.log(` Staged Files Scanned : ${result.stats.stagedFilesCount}`);
45
51
  console.log(` Enforcement Mode : ${enforce ? 'STRICT (fails on findings)' : 'ADVISORY (warnings only)'}`);
52
+ console.log(` Scope Containment : ${result.scope.status.toUpperCase()}`);
46
53
  console.log(` Violations Found : ${result.stats.violationsCount}\n`);
47
54
 
48
55
  if (result.findings.length > 0) {
@@ -58,7 +65,7 @@ function scanCommand(args, flags) {
58
65
 
59
66
  console.log('──────────────────────────────────────────────────────');
60
67
  if (result.ok) {
61
- console.log(' RESULT: PASSED (No blocking violations in staged index)');
68
+ console.log(' RESULT: PASSED (Verification completed cleanly, no blocking violations)');
62
69
  } else {
63
70
  console.log(' RESULT: FAILED (Commit blocked due to staged violations)');
64
71
  }
package/bin/index.js CHANGED
@@ -7,6 +7,7 @@ const profiles = require('../.agents/profiles.js');
7
7
  const { isKnownCommand, getStatus, formatStatusText } = require('./commands.js');
8
8
  const { detectProjectAttributes } = require('./lib/detector.js');
9
9
  const lockfileLib = require('./lib/lockfile.js');
10
+ const ui = require('./lib/ui.js');
10
11
 
11
12
  // ── CLI argument parsing ──────────────────────────────────────────────────────
12
13
  const args = process.argv.slice(2);
@@ -41,6 +42,27 @@ const flags = {
41
42
  return i !== -1 && args[i + 1] && !args[i + 1].startsWith('-') ? args[i + 1] : null;
42
43
  })(),
43
44
  githubAnnotations: args.includes('--github-annotations'),
45
+ all: args.includes('--all') || args.includes('--full'),
46
+ preset: (() => {
47
+ const i = args.indexOf('--preset');
48
+ return i !== -1 && args[i + 1] && !args[i + 1].startsWith('-') ? args[i + 1].toLowerCase() : null;
49
+ })(),
50
+ };
51
+
52
+ const PRESETS = {
53
+ frontend: [
54
+ 'react', 'react-best-practices', 'nextjs', 'typescript',
55
+ 'ui-ux-pro', 'impeccable-design', 'state-management', 'web-accessibility'
56
+ ],
57
+ backend: [
58
+ 'node', 'fastapi', 'nestjs', 'system-design',
59
+ 'api-design', 'microservices', 'ddd', 'database'
60
+ ],
61
+ devops: [
62
+ 'docker', 'ci-cd', 'terraform', 'security-audit'
63
+ ],
64
+ full: null,
65
+ all: null,
44
66
  };
45
67
 
46
68
  // ── Help / Version ────────────────────────────────────────────────────────────
@@ -71,6 +93,8 @@ Options:
71
93
  --dry-run Preview what will be copied without making changes
72
94
  --force Overwrite an existing .agents/ folder
73
95
  --minimal Install only 7 core skills (lightweight footprint)
96
+ --all, --full Install all 36 catalog skills alongside 7 core skills
97
+ --preset <name> Install domain preset (frontend, backend, devops, full)
74
98
  --profile <name> Install a specific profile (mvp, startup, enterprise, frontend, backend)
75
99
  --auto Auto-detect tech stack and apply recommended profile
76
100
  --project <path> Specify target project root directory (default: current directory)
@@ -82,6 +106,7 @@ Options:
82
106
 
83
107
  Commands:
84
108
  init Install and configure .agents/ in target project
109
+ skill <subcmd> Manage skills (add, remove, list, search, override, diff, eject)
85
110
  gate Run deterministic quality gate against adapter drift
86
111
  status Display project configuration, active profile, and lockfile status
87
112
  update Safely update skills without overwriting custom changes
@@ -119,9 +144,14 @@ Plugin ref formats:
119
144
  @scope/npm-package A scoped npm skill package
120
145
 
121
146
  Examples:
122
- npx contextos-agents init Install .agents/ with auto-detected stack
147
+ npx contextos-agents init Install Lean Core (7 foundational skills)
148
+ npx contextos-agents init --all Install ContextOS with all 43 skills
149
+ npx contextos-agents init --preset frontend Install ContextOS with frontend domain skills
123
150
  npx contextos-agents init --agent auto Install and configure for detected stack & IDE
124
- npx contextos-agents init --minimal Install only 7 core essential skills
151
+ npx contextos skill add <name> Install a domain skill from catalog
152
+ npx contextos skill add --all Install all catalog skills into existing project
153
+ npx contextos skill list --available List all available catalog domain skills
154
+ npx contextos skill override <name> Create editable local copy of a skill
125
155
  npx contextos status Show project configuration and lockfile status
126
156
  npx contextos doctor Run project health check
127
157
  npx contextos export gemini Compile skills for Gemini
@@ -178,7 +208,7 @@ if (mainCommand === 'detect') {
178
208
  }, null, 2));
179
209
  } else {
180
210
  console.log('\n══════════════════════════════════════════');
181
- console.log(' ContextOS — Workspace Scoped Detection');
211
+ console.log(' ContextOS - Workspace Scoped Detection');
182
212
  console.log('══════════════════════════════════════════\n');
183
213
  console.log(` Scope Path : ${scopeArg}`);
184
214
  if (nearestPkg) {
@@ -193,7 +223,7 @@ if (mainCommand === 'detect') {
193
223
  if (evidence.length > 0) {
194
224
  console.log('\n Scoped Evidence:');
195
225
  for (const ev of evidence.slice(0, 10)) {
196
- console.log(` • [${ev.source}] ${ev.target} (+${ev.weight}) — ${ev.description}`);
226
+ console.log(` • [${ev.source}] ${ev.target} (+${ev.weight}) - ${ev.description}`);
197
227
  }
198
228
  if (evidence.length > 10) {
199
229
  console.log(` ... and ${evidence.length - 10} more signals`);
@@ -212,7 +242,7 @@ if (mainCommand === 'detect') {
212
242
  }, null, 2));
213
243
  } else if (explain) {
214
244
  console.log('\n══════════════════════════════════════════');
215
- console.log(' ContextOS — Workspace Evidence Graph');
245
+ console.log(' ContextOS - Workspace Evidence Graph');
216
246
  console.log('══════════════════════════════════════════\n');
217
247
  console.log(` Repository Root : ${graph.repositoryRoot}`);
218
248
  console.log(` Fingerprint : ${graph.fingerprint}`);
@@ -234,7 +264,7 @@ if (mainCommand === 'detect') {
234
264
  console.log('──────────────────────────────────────────\n');
235
265
  } else {
236
266
  const detection = detectProjectAttributes(process.cwd());
237
- console.log('\nContextOS — Tech Stack & Environment Detection\n');
267
+ console.log('\nContextOS - Tech Stack & Environment Detection\n');
238
268
  console.log(` Repository Root : ${graph.repositoryRoot}`);
239
269
  console.log(` Packages Detected : ${graph.packages.map(p => `${p.id} (${p.root})`).join(', ')}`);
240
270
  console.log(` Detected Technologies : ${detection.summary.technologies.join(', ')}`);
@@ -270,7 +300,10 @@ if (mainCommand === 'recover') {
270
300
  // Gate command (deterministic quality gate verification)
271
301
  if (mainCommand === 'gate') {
272
302
  const { runGate, emitGitHubAnnotations, writeGitHubSummary } = require('./lib/gate.js');
273
- const target = flags.target || (args[1] && !args[1].startsWith('-') ? args[1] : 'all');
303
+ let target = flags.target || (args[1] && !args[1].startsWith('-') ? args[1] : 'all');
304
+ if (typeof target === 'string' && target.includes(',')) {
305
+ target = target.split(',').map(s => s.trim()).filter(Boolean);
306
+ }
274
307
  const result = runGate(flags.project, {
275
308
  target,
276
309
  profile: flags.profile,
@@ -377,7 +410,7 @@ if (mainCommand === 'hook') {
377
410
 
378
411
  // Proxy commands to trusted package .agents/ctx.js targeting flags.project
379
412
  const PROXY_COMMANDS = [
380
- 'profile', 'export', 'validate', 'resolve', 'skill', 'index',
413
+ 'profile', 'export', 'validate', 'audit', 'resolve', 'skill', 'index',
381
414
  'clean-worktrees', 'stats', 'watch', 'compile', 'explain',
382
415
  'thread'
383
416
  ];
@@ -477,7 +510,32 @@ if (mainCommand === 'install-skill') {
477
510
  }).on('error', reject);
478
511
  });
479
512
 
480
- const registry = await fetchRegistry();
513
+ let registry;
514
+ try {
515
+ registry = await fetchRegistry();
516
+ } catch {
517
+ const catalogDir = path.join(__dirname, '..', 'catalog', 'skills');
518
+ if (fs.existsSync(catalogDir)) {
519
+ const catalogSkills = fs.readdirSync(catalogDir).filter(n => {
520
+ try {
521
+ return fs.statSync(path.join(catalogDir, n)).isDirectory();
522
+ } catch {
523
+ return false;
524
+ }
525
+ });
526
+ registry = {
527
+ skills: catalogSkills.map(name => ({
528
+ name,
529
+ description: `Domain catalog skill: ${name}`,
530
+ github: null,
531
+ npm: name,
532
+ })),
533
+ };
534
+ } else {
535
+ console.error('[ERROR] Could not fetch remote registry and local catalog is unavailable.');
536
+ process.exit(1);
537
+ }
538
+ }
481
539
  const skillsList = (registry.skills || []).map((s, idx) => ({
482
540
  idx: idx + 1,
483
541
  name: s.name,
@@ -545,6 +603,9 @@ if (mainCommand === 'install-skill') {
545
603
  console.error(' To use the MCP Bridge or execution runtime, install @contextos/mcp:');
546
604
  console.error(' npm install @contextos/mcp --save-dev');
547
605
  process.exit(1);
606
+ } else if (mainCommand && mainCommand !== 'init') {
607
+ console.error(`[ERROR] Unknown command: '${mainCommand}'. Run 'contextos --help' for available commands.`);
608
+ process.exit(1);
548
609
  } else {
549
610
 
550
611
  // ── Paths ─────────────────────────────────────────────────────────────────────
@@ -600,6 +661,13 @@ function installAtomically(source, target, options = {}) {
600
661
  return true;
601
662
  },
602
663
  });
664
+
665
+ const catalogSrc = path.join(__dirname, '..', 'catalog');
666
+ const catalogDest = path.join(stagingPath, 'catalog');
667
+ if (fs.existsSync(catalogSrc)) {
668
+ fs.cpSync(catalogSrc, catalogDest, { recursive: true, force: true });
669
+ }
670
+
603
671
  if (fs.existsSync(target)) {
604
672
  fs.renameSync(target, backupPath);
605
673
  movedExisting = true;
@@ -680,7 +748,7 @@ if (flags.dryRun) {
680
748
 
681
749
  console.log('[DRY-RUN] No files will be written.\n');
682
750
  if (fs.existsSync(targetPath)) {
683
- console.log(`[WARN] .agents/ already exists — would be overwritten with --force.`);
751
+ console.log(`[WARN] .agents/ already exists - would be overwritten with --force.`);
684
752
  } else {
685
753
  console.log(`[OK] Would create .agents/ in: ${process.cwd()}`);
686
754
  }
@@ -700,7 +768,13 @@ if (flags.dryRun) {
700
768
 
701
769
  // ── Main install ──────────────────────────────────────────────────────────────
702
770
  if (!flags.json) {
703
- console.log('Installing AI assistant skills (.agents/)...');
771
+ ui.renderBanner(version);
772
+ ui.renderStep(1, 4, 'Analyzing project environment & tech stack',
773
+ stackDetection.detected.length > 0
774
+ ? `Detected stack: ${stackDetection.detected.join(', ')}`
775
+ : 'Detected stack: Generic JavaScript environment'
776
+ );
777
+ console.log('');
704
778
  }
705
779
 
706
780
  try {
@@ -740,18 +814,14 @@ try {
740
814
  }
741
815
 
742
816
  if (!flags.json) {
743
- console.log('[OK] .agents/ successfully installed in your project!');
744
- if (flags.minimal) {
745
- console.log('[OK] Minimal profile: 5 core skills installed.');
746
- console.log(' (engineering-workflow, ponytail-mindset, gstack-roles, gemini-precision, react)');
747
- console.log(' Tip: Add more skills anytime with: contextos skill add <name>');
748
- }
749
- if (stackDetection.detected.length > 0) {
750
- console.log(`[OK] Detected project stack: ${stackDetection.detected.join(', ')}`);
751
- }
752
- if (ideDetection.detected.length > 0) {
753
- console.log(`[OK] Detected developer environment: ${ideDetection.detected.join(', ')}`);
754
- }
817
+ ui.renderStep(2, 4, 'Deploying Lean Core engine (.agents/)', [
818
+ 'Installed 7 foundational core skills in .agents/core/skills/',
819
+ 'Why 7? ContextOS uses a Lean Core to keep your AI context small, fast, and token-efficient.',
820
+ 'To add domain skills (React, FastAPI, Docker, etc.): npx contextos skill add <name> (or --all)',
821
+ ]);
822
+ console.log('');
823
+ ui.renderStep(3, 4, 'Generating lockfile & security governance', 'contextos.lock.json synchronized');
824
+ console.log('');
755
825
  }
756
826
 
757
827
  // ── Deprecation warning for --with-mcp ────────────────────────────────────────────────
@@ -765,7 +835,7 @@ try {
765
835
  if (selectedProfile) {
766
836
  try {
767
837
  const applied = profiles.applyProfile(selectedProfile, process.cwd());
768
- if (!flags.json) console.log(`[OK] Applied profile '${applied.name}' (excluded: ${(applied.exclude_skills || []).join(', ') || 'none'})`);
838
+ if (!flags.json) console.log(` [OK] Applied profile '${applied.name}' (excluded: ${(applied.exclude_skills || []).join(', ') || 'none'})\n`);
769
839
  } catch (e) {
770
840
  if (flags.json) {
771
841
  console.error(JSON.stringify({ success: false, error: `Could not apply profile '${selectedProfile}': ${e.message}` }));
@@ -776,58 +846,112 @@ try {
776
846
  }
777
847
  }
778
848
 
779
- if (!flags.json) {
780
- console.log('[OK] Your AI assistant now has skills and rules configured.\n');
781
- }
782
-
783
849
  // ── Auto-compile skills for target agents ──────────────────────────────────
784
850
  if (!flags.skipCompile) {
785
851
  const ctxPath = path.join(targetPath, 'ctx.js');
786
852
  if (fs.existsSync(ctxPath)) {
853
+ if (!flags.json) {
854
+ ui.renderStep(4, 4, 'Configuring AI assistants & compiling rules', `${targetAgents.join(', ')} synchronized`);
855
+ console.log('');
856
+ }
787
857
  const { execFileSync } = require('child_process');
788
858
  for (const ag of targetAgents) {
789
- if (!flags.json) console.log(`Compiling skills for ${ag}...`);
790
859
  try {
791
860
  execFileSync(process.execPath, [ctxPath, 'export', ag], {
792
861
  cwd: process.cwd(),
793
- stdio: flags.json ? 'ignore' : 'inherit',
862
+ stdio: 'ignore',
794
863
  });
795
864
  } catch (e) {
796
865
  if (flags.json) {
797
866
  console.error(JSON.stringify({ success: false, error: `Skill compilation for '${ag}' failed` }));
798
867
  } else {
799
- console.error(`[ERROR] Skill compilation for '${ag}' failed — run manually: contextos export ${ag}`);
868
+ console.error(` [ERROR] Skill compilation for '${ag}' failed - run manually: contextos export ${ag}`);
800
869
  }
801
870
  process.exit(1);
802
871
  }
803
872
  }
804
873
  }
805
874
  } else if (!flags.json) {
806
- console.log('Tip: Run `contextos export gemini` to compile skills.');
875
+ ui.renderStep(4, 4, 'Configuring AI assistants & compiling rules', [
876
+ 'Skipped auto-compilation (--skip-compile)',
877
+ 'Tip: Run `contextos export gemini` to compile skills when ready.',
878
+ ]);
879
+ console.log('');
807
880
  }
808
881
 
809
882
  // ── --add-skill flag ────────────────────────────────────────────────────────
810
883
  if (flags.addSkill) {
811
- const ctxPath = path.join(targetPath, 'ctx.js');
812
- if (fs.existsSync(ctxPath)) {
884
+ const packageCtxPath = path.join(__dirname, '..', '.agents', 'ctx.js');
885
+ const ctxScript = fs.existsSync(packageCtxPath) ? packageCtxPath : path.join(targetPath, 'ctx.js');
886
+ if (fs.existsSync(ctxScript)) {
813
887
  if (!flags.json) console.log(`Installing plugin skill: ${flags.addSkill}`);
814
888
  try {
815
889
  const { execFileSync } = require('child_process');
816
- execFileSync(process.execPath, [ctxPath, 'skill', 'add', flags.addSkill], {
890
+ const catalogDir = path.join(__dirname, '..', 'catalog', 'skills');
891
+ const subEnv = { ...process.env, CONTEXTOS_CATALOG_DIR: catalogDir };
892
+ execFileSync(process.execPath, [ctxScript, 'skill', 'add', flags.addSkill], {
817
893
  cwd: process.cwd(),
818
894
  stdio: flags.json ? 'ignore' : 'inherit',
895
+ env: subEnv,
819
896
  });
820
897
  } catch (e) {
821
898
  if (flags.json) {
822
899
  console.error(JSON.stringify({ success: false, error: `Skill install failed for ${flags.addSkill}` }));
823
900
  } else {
824
- console.error(`[ERROR] Skill install failed — run manually: node .agents/ctx.js skill add ${flags.addSkill}`);
901
+ console.error(`[ERROR] Skill install failed - run manually: node .agents/ctx.js skill add ${flags.addSkill}`);
825
902
  }
826
903
  process.exit(1);
827
904
  }
828
905
  }
829
906
  }
830
907
 
908
+ // ── --all / --preset flags ──────────────────────────────────────────────────
909
+ if (flags.all || flags.preset) {
910
+ const packageCtxPath = path.join(__dirname, '..', '.agents', 'ctx.js');
911
+ const ctxScript = fs.existsSync(packageCtxPath) ? packageCtxPath : path.join(targetPath, 'ctx.js');
912
+ if (fs.existsSync(ctxScript)) {
913
+ const presetKey = flags.all ? 'full' : (flags.preset || 'full');
914
+ const { execFileSync } = require('child_process');
915
+ const catalogDir = path.join(__dirname, '..', 'catalog', 'skills');
916
+ const subEnv = { ...process.env, CONTEXTOS_CATALOG_DIR: catalogDir };
917
+
918
+ if (presetKey === 'full' || presetKey === 'all') {
919
+ if (!flags.json) console.log('\nInstalling all 36 catalog skills (--all)...');
920
+ try {
921
+ execFileSync(process.execPath, [ctxScript, 'skill', 'add', '--all'], {
922
+ cwd: process.cwd(),
923
+ stdio: flags.json ? 'ignore' : 'inherit',
924
+ env: subEnv,
925
+ });
926
+ } catch (e) {
927
+ if (!flags.json) console.error(' [WARN] Failed to install catalog skills:', e.message);
928
+ }
929
+ } else if (PRESETS[presetKey]) {
930
+ if (!flags.json) console.log(` Installing preset '${presetKey}' skills:`);
931
+ const totalSkills = PRESETS[presetKey].length;
932
+ let count = 0;
933
+ for (const skillName of PRESETS[presetKey]) {
934
+ count++;
935
+ if (!flags.json) {
936
+ ui.renderProgressBar(count, totalSkills, skillName);
937
+ }
938
+ try {
939
+ execFileSync(process.execPath, [ctxScript, 'skill', 'add', skillName], {
940
+ cwd: process.cwd(),
941
+ stdio: 'ignore',
942
+ env: subEnv,
943
+ });
944
+ } catch (e) {
945
+ if (!flags.json) console.error(`\n [WARN] Failed to install preset skill '${skillName}':`, e.message);
946
+ }
947
+ }
948
+ if (!flags.json) console.log('\n');
949
+ } else {
950
+ if (!flags.json) console.error(` [WARN] Unknown preset '${flags.preset}'. Supported presets: frontend, backend, devops, full`);
951
+ }
952
+ }
953
+ }
954
+
831
955
  if (flags.json) {
832
956
  console.log(JSON.stringify({
833
957
  success: true,
@@ -838,27 +962,15 @@ try {
838
962
  agents: targetAgents,
839
963
  withMcp: flags.withMcp,
840
964
  minimal: flags.minimal,
965
+ all: flags.all,
966
+ preset: flags.preset,
841
967
  }, null, 2));
842
968
  process.exit(0);
843
969
  }
844
970
 
845
- console.log('\n Next steps:');
846
- console.log(' 1. Open your project in your AI assistant');
847
- console.log(' 2. The assistant will automatically load .agents/AGENTS.md');
848
- console.log(' 3. Inspect project health anytime:');
849
- console.log(' contextos doctor');
850
- console.log(' 4. Switch profiles anytime:');
851
- console.log(' contextos profile list');
852
- console.log(' contextos profile apply mvp');
853
- console.log(' 5. Export to other AI tools:');
854
- console.log(' contextos export cursor → .cursorrules & .cursor/rules');
855
- console.log(' contextos export copilot → .github/copilot-instructions.md');
856
- console.log(' contextos export aider → .aider.conf.yml + CONVENTIONS.md');
857
- console.log(' 6. Add community skills (plugins):');
858
- console.log(' contextos skill add username/my-skill');
859
- console.log(' contextos skill list');
860
-
861
- console.log('');
971
+ if (!flags.json) {
972
+ ui.renderSuccessCard();
973
+ }
862
974
 
863
975
  } catch (error) {
864
976
  if (flags.json) {