contextos-agents 1.6.0 → 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.
- package/.agents/AGENTS.md +5 -0
- package/.agents/adapters/aider/export.js +4 -2
- package/.agents/adapters/copilot/export.js +4 -2
- package/.agents/adapters/cursor/export.js +48 -12
- package/.agents/adapters/zed/export.js +53 -14
- package/.agents/core/profiles/mvp.yaml +1 -0
- package/.agents/core/skills/adapters/skill.yaml +6 -0
- package/.agents/core/skills/architecture-diagrams/skill.yaml +4 -0
- package/.agents/core/skills/brutalist-design/skill.yaml +4 -0
- package/.agents/core/skills/context-manager/references/context-rules.md +59 -0
- package/.agents/core/skills/context-manager/skill.yaml +7 -0
- package/.agents/core/skills/context-os/skill.yaml +11 -0
- package/.agents/core/skills/database/skill.yaml +6 -0
- package/.agents/core/skills/ddd/skill.yaml +7 -0
- package/.agents/core/skills/decisions/skill.yaml +6 -0
- package/.agents/core/skills/docker/skill.yaml +6 -0
- package/.agents/core/skills/engineering-workflow/SKILL.md +1 -1
- package/.agents/core/skills/engineering-workflow/skill.yaml +6 -0
- package/.agents/core/skills/fastapi/skill.yaml +7 -0
- package/.agents/core/skills/gemini-precision/SKILL.md +4 -0
- package/.agents/core/skills/gemini-precision/skill.yaml +4 -0
- package/.agents/core/skills/generators/skill.yaml +15 -0
- package/.agents/core/skills/graphify/SKILL.md +2 -2
- package/.agents/core/skills/graphify/skill.yaml +6 -1
- package/.agents/core/skills/gstack-roles/SKILL.md +3 -1
- package/.agents/core/skills/gstack-roles/skill.yaml +6 -0
- package/.agents/core/skills/impeccable-design/skill.yaml +6 -0
- package/.agents/core/skills/interview-me/skill.yaml +4 -0
- package/.agents/core/skills/microservices/skill.yaml +7 -0
- package/.agents/core/skills/minimalist-design/skill.yaml +4 -0
- package/.agents/core/skills/nestjs/skill.yaml +7 -0
- package/.agents/core/skills/nextjs/skill.yaml +7 -0
- package/.agents/core/skills/node/skill.yaml +7 -0
- package/.agents/core/skills/performance/skill.yaml +7 -0
- package/.agents/core/skills/ponytail-mindset/skill.yaml +6 -0
- package/.agents/core/skills/react/skill.yaml +7 -0
- package/.agents/core/skills/react-best-practices/skill.yaml +4 -0
- package/.agents/core/skills/redesign-audit/skill.yaml +4 -0
- package/.agents/core/skills/security/skill.yaml +7 -0
- package/.agents/core/skills/soft-design/skill.yaml +4 -0
- package/.agents/core/skills/state-management/skill.yaml +6 -0
- package/.agents/core/skills/subagent-orchestrator/SKILL.md +17 -0
- package/.agents/core/skills/subagent-orchestrator/skill.yaml +4 -0
- package/.agents/core/skills/system-design/skill.yaml +7 -0
- package/.agents/core/skills/testing/skill.yaml +6 -0
- package/.agents/core/skills/typescript/skill.yaml +7 -0
- package/.agents/core/skills/ui-design/skill.yaml +7 -0
- package/.agents/core/skills/ui-ux-pro/skill.yaml +6 -0
- package/.agents/core/skills/ux-design/skill.yaml +7 -0
- package/.agents/core/skills/vercel-optimize/scripts/collect-signals.mjs +131 -0
- package/.agents/core/skills/vercel-optimize/scripts/gate-investigations.mjs +142 -0
- package/.agents/core/skills/vercel-optimize/scripts/merge-signals.mjs +143 -0
- package/.agents/core/skills/vercel-optimize/scripts/scan-codebase.mjs +174 -0
- package/.agents/core/skills/vercel-optimize/skill.yaml +8 -0
- package/.agents/core/skills/web-accessibility/skill.yaml +7 -0
- package/.agents/ctx.js +44 -0
- package/.agents/doctor.js +193 -4
- package/.agents/generated/claude/skills/engineering-workflow/SKILL.md +1 -1
- package/.agents/generated/claude/skills/gemini-precision/SKILL.md +4 -0
- package/.agents/generated/claude/skills/graphify/SKILL.md +1 -1
- package/.agents/generated/claude/skills/gstack-roles/SKILL.md +3 -1
- package/.agents/generated/claude/skills/subagent-orchestrator/SKILL.md +17 -0
- package/.agents/generated/gemini/skills/engineering-workflow/SKILL.md +1 -1
- package/.agents/generated/gemini/skills/gemini-precision/SKILL.md +4 -0
- package/.agents/generated/gemini/skills/graphify/SKILL.md +2 -2
- package/.agents/generated/gemini/skills/gstack-roles/SKILL.md +3 -1
- package/.agents/generated/gemini/skills/subagent-orchestrator/SKILL.md +17 -0
- package/.agents/plugins/contextos/hooks.json +25 -0
- package/.agents/plugins/contextos/plugin.json +19 -0
- package/.agents/plugins.js +180 -20
- package/.agents/profiles.js +26 -0
- package/.agents/resolver.js +150 -30
- package/.agents/stats.js +22 -9
- package/.agents/validate.js +152 -13
- package/README.md +77 -47
- package/bin/commands/uninstall.js +207 -0
- package/bin/commands/update.js +262 -0
- package/bin/commands.js +305 -0
- package/bin/index.js +275 -119
- package/bin/lib/detector.js +106 -0
- package/bin/lib/lockfile.js +251 -0
- package/bin/lib/safe-writer.js +259 -0
- package/package.json +6 -9
- package/registry.json +13 -5
- package/registry.schema.json +3 -1
- package/.agents/mcp/runtime.py +0 -470
- package/.agents/mcp/server.mjs +0 -189386
- 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
|
-
|
|
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
|
|
86
|
-
npx contextos --
|
|
87
|
-
npx contextos --
|
|
88
|
-
contextos
|
|
89
|
-
contextos
|
|
90
|
-
contextos
|
|
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,53 +114,61 @@ Examples:
|
|
|
95
114
|
// ── Top-level Commands & Proxy Routing ────────────────────────────────────────
|
|
96
115
|
const mainCommand = args[0] && !args[0].startsWith('-') ? args[0] : null;
|
|
97
116
|
|
|
98
|
-
//
|
|
99
|
-
if (mainCommand
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (fs.existsSync(localDoctor)) {
|
|
103
|
-
doctorModule = require(localDoctor);
|
|
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 }));
|
|
104
121
|
} else {
|
|
105
|
-
|
|
122
|
+
console.error(`[ERROR] Unknown command: ${mainCommand}`);
|
|
123
|
+
console.error(' Run `npx contextos-agents --help` to view available commands.');
|
|
106
124
|
}
|
|
107
|
-
|
|
108
|
-
process.exit(0);
|
|
125
|
+
process.exit(1);
|
|
109
126
|
}
|
|
110
127
|
|
|
111
|
-
//
|
|
112
|
-
if (mainCommand === '
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
statsModule = require(localStats);
|
|
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));
|
|
117
133
|
} else {
|
|
118
|
-
|
|
134
|
+
console.log(formatStatusText(status));
|
|
119
135
|
}
|
|
120
|
-
statsModule.runStats(process.cwd());
|
|
121
136
|
process.exit(0);
|
|
122
137
|
}
|
|
123
138
|
|
|
124
|
-
//
|
|
125
|
-
if (mainCommand === '
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
watchModule = require(localWatch);
|
|
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));
|
|
130
144
|
} else {
|
|
131
|
-
|
|
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`);
|
|
132
151
|
}
|
|
133
|
-
|
|
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);
|
|
134
160
|
}
|
|
135
161
|
|
|
136
162
|
// Proxy commands to .agents/ctx.js when executed in a ContextOS project
|
|
137
|
-
const PROXY_COMMANDS = [
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
163
|
+
const PROXY_COMMANDS = [
|
|
164
|
+
'profile', 'export', 'validate', 'resolve', 'skill', 'index',
|
|
165
|
+
'clean-worktrees', 'stats', 'watch'
|
|
166
|
+
];
|
|
167
|
+
|
|
168
|
+
const ctxPath = path.join(process.cwd(), '.agents', 'ctx.js');
|
|
169
|
+
const hasLocalCtx = fs.existsSync(ctxPath);
|
|
170
|
+
|
|
171
|
+
if (mainCommand && PROXY_COMMANDS.includes(mainCommand) && hasLocalCtx) {
|
|
145
172
|
const { execFileSync } = require('child_process');
|
|
146
173
|
try {
|
|
147
174
|
execFileSync(process.execPath, [ctxPath, ...args], { stdio: 'inherit' });
|
|
@@ -151,9 +178,45 @@ if (mainCommand && PROXY_COMMANDS.includes(mainCommand)) {
|
|
|
151
178
|
process.exit(0);
|
|
152
179
|
}
|
|
153
180
|
|
|
181
|
+
// Fallbacks when running outside an initialized .agents/ directory
|
|
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
|
+
});
|
|
197
|
+
process.exit(0);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (mainCommand === 'stats') {
|
|
201
|
+
const statsModule = require('../.agents/stats.js');
|
|
202
|
+
statsModule.runStats(process.cwd());
|
|
203
|
+
process.exit(0);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (mainCommand === 'watch') {
|
|
207
|
+
const watchModule = require('../.agents/watch.js');
|
|
208
|
+
watchModule.runWatch(process.cwd());
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const PROJECT_ONLY_COMMANDS = ['profile', 'export', 'validate', 'resolve', 'skill', 'index', 'clean-worktrees'];
|
|
212
|
+
if (mainCommand && PROJECT_ONLY_COMMANDS.includes(mainCommand) && !hasLocalCtx) {
|
|
213
|
+
console.error('[ERROR] .agents/ctx.js not found in current directory.');
|
|
214
|
+
console.error(' Are you in a ContextOS project? Run `contextos` or `npx contextos-agents` first.');
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
|
|
154
218
|
if (mainCommand === 'audit') {
|
|
155
|
-
|
|
156
|
-
if (!fs.existsSync(ctxPath)) {
|
|
219
|
+
if (!hasLocalCtx) {
|
|
157
220
|
console.error('[ERROR] .agents/ctx.js not found. Are you in a ContextOS project?');
|
|
158
221
|
process.exit(1);
|
|
159
222
|
}
|
|
@@ -166,15 +229,6 @@ if (mainCommand === 'audit') {
|
|
|
166
229
|
process.exit(0);
|
|
167
230
|
}
|
|
168
231
|
|
|
169
|
-
if (mainCommand === 'detect') {
|
|
170
|
-
const stack = profiles.detectStack(process.cwd());
|
|
171
|
-
console.log('\nContextOS — Tech Stack Detection\n');
|
|
172
|
-
console.log(` Detected Technologies : ${stack.detected.length ? stack.detected.join(', ') : 'Generic JavaScript'}`);
|
|
173
|
-
console.log(` Recommended Profile : ${stack.recommendedProfile}`);
|
|
174
|
-
console.log(` Recommended Skills : ${stack.recommendedSkills.join(', ')}\n`);
|
|
175
|
-
process.exit(0);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
232
|
if (mainCommand === 'install-skill') {
|
|
179
233
|
const ctxPath = path.join(process.cwd(), '.agents', 'ctx.js');
|
|
180
234
|
if (!fs.existsSync(ctxPath)) {
|
|
@@ -198,10 +252,10 @@ if (mainCommand === 'install-skill') {
|
|
|
198
252
|
}
|
|
199
253
|
process.exit(0);
|
|
200
254
|
} else {
|
|
201
|
-
// Interactive menu
|
|
255
|
+
// Interactive menu using standard library readline
|
|
202
256
|
(async () => {
|
|
203
257
|
try {
|
|
204
|
-
const
|
|
258
|
+
const readline = require('readline');
|
|
205
259
|
const https = require('https');
|
|
206
260
|
|
|
207
261
|
console.log('Fetching community skills from registry...');
|
|
@@ -210,33 +264,68 @@ if (mainCommand === 'install-skill') {
|
|
|
210
264
|
https.get('https://raw.githubusercontent.com/kok-o/contextos-agents/main/registry.json', (res) => {
|
|
211
265
|
let data = '';
|
|
212
266
|
res.on('data', chunk => data += chunk);
|
|
213
|
-
res.on('end', () =>
|
|
267
|
+
res.on('end', () => {
|
|
268
|
+
try {
|
|
269
|
+
resolve(JSON.parse(data));
|
|
270
|
+
} catch (err) {
|
|
271
|
+
reject(err);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
214
274
|
}).on('error', reject);
|
|
215
275
|
});
|
|
216
276
|
|
|
217
277
|
const registry = await fetchRegistry();
|
|
218
|
-
const
|
|
219
|
-
|
|
278
|
+
const skillsList = (registry.skills || []).map((s, idx) => ({
|
|
279
|
+
idx: idx + 1,
|
|
280
|
+
name: s.name,
|
|
281
|
+
desc: s.description || '',
|
|
220
282
|
value: s.github ? `${s.github}${s.path ? '/' + s.path : ''}` : s.npm
|
|
221
283
|
}));
|
|
222
|
-
|
|
223
|
-
|
|
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.');
|
|
284
|
+
|
|
285
|
+
if (skillsList.length === 0) {
|
|
286
|
+
console.log('No community skills found in registry.');
|
|
234
287
|
process.exit(0);
|
|
235
288
|
}
|
|
236
|
-
|
|
289
|
+
|
|
290
|
+
console.log('\nAvailable community skills:\n');
|
|
291
|
+
for (const item of skillsList) {
|
|
292
|
+
console.log(` [${item.idx}] ${item.name.padEnd(20)} ${item.desc}`);
|
|
293
|
+
}
|
|
294
|
+
console.log('\nEnter skill numbers to install (comma-separated, e.g. 1, 3) or press Enter to cancel:');
|
|
295
|
+
|
|
296
|
+
const rl = readline.createInterface({
|
|
297
|
+
input: process.stdin,
|
|
298
|
+
output: process.stdout,
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
const answer = await new Promise((resolve) => {
|
|
302
|
+
rl.question('> ', (ans) => {
|
|
303
|
+
rl.close();
|
|
304
|
+
resolve(ans.trim());
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
if (!answer) {
|
|
309
|
+
console.log('No skills selected. Operation cancelled.');
|
|
310
|
+
process.exit(0);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const selectedIndices = answer
|
|
314
|
+
.split(/[\s,]+/)
|
|
315
|
+
.map(n => parseInt(n, 10))
|
|
316
|
+
.filter(n => !isNaN(n) && n >= 1 && n <= skillsList.length);
|
|
317
|
+
|
|
318
|
+
const selectedSkills = selectedIndices.map(n => skillsList[n - 1].value);
|
|
319
|
+
|
|
320
|
+
if (selectedSkills.length === 0) {
|
|
321
|
+
console.log('No valid skill numbers selected.');
|
|
322
|
+
process.exit(0);
|
|
323
|
+
}
|
|
324
|
+
|
|
237
325
|
const { execFileSync } = require('child_process');
|
|
238
|
-
for (const skillRef of
|
|
326
|
+
for (const skillRef of selectedSkills) {
|
|
239
327
|
try {
|
|
328
|
+
console.log(`\nInstalling ${skillRef}...`);
|
|
240
329
|
execFileSync(process.execPath, [ctxPath, 'skill', 'add', skillRef], { stdio: 'inherit' });
|
|
241
330
|
} catch (e) {
|
|
242
331
|
console.error(`Failed to install ${skillRef}`);
|
|
@@ -244,9 +333,6 @@ if (mainCommand === 'install-skill') {
|
|
|
244
333
|
}
|
|
245
334
|
} catch (error) {
|
|
246
335
|
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
336
|
process.exit(1);
|
|
251
337
|
}
|
|
252
338
|
})();
|
|
@@ -368,12 +454,18 @@ function installAtomically(source, target, options = {}) {
|
|
|
368
454
|
}
|
|
369
455
|
}
|
|
370
456
|
|
|
371
|
-
// ── Stack detection
|
|
372
|
-
const
|
|
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']);
|
|
373
466
|
|
|
374
467
|
// ── Dry run ───────────────────────────────────────────────────────────────────
|
|
375
468
|
if (flags.dryRun) {
|
|
376
|
-
console.log('[DRY-RUN] No files will be written.\n');
|
|
377
469
|
if (!fs.existsSync(sourcePath)) {
|
|
378
470
|
console.error('[ERROR] Source .agents/ folder not found in package.');
|
|
379
471
|
process.exit(1);
|
|
@@ -403,14 +495,34 @@ if (flags.dryRun) {
|
|
|
403
495
|
return count;
|
|
404
496
|
};
|
|
405
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');
|
|
406
515
|
if (fs.existsSync(targetPath)) {
|
|
407
516
|
console.log(`[WARN] .agents/ already exists — would be overwritten with --force.`);
|
|
408
517
|
} else {
|
|
409
518
|
console.log(`[OK] Would create .agents/ in: ${process.cwd()}`);
|
|
410
519
|
}
|
|
411
520
|
console.log(`[INFO] Detected stack: ${stackDetection.detected.length ? stackDetection.detected.join(', ') : 'Generic JavaScript'}`);
|
|
412
|
-
|
|
521
|
+
if (ideDetection.detected.length > 0) {
|
|
522
|
+
console.log(`[INFO] Detected IDEs: ${ideDetection.detected.join(', ')}`);
|
|
523
|
+
}
|
|
413
524
|
console.log(`[INFO] Selected profile: ${targetProfile}`);
|
|
525
|
+
console.log(`[INFO] Target agents for export: ${targetAgents.join(', ')}`);
|
|
414
526
|
if (flags.minimal) {
|
|
415
527
|
console.log(`[INFO] Minimal mode: copying only 5 core essential skills`);
|
|
416
528
|
}
|
|
@@ -420,7 +532,9 @@ if (flags.dryRun) {
|
|
|
420
532
|
}
|
|
421
533
|
|
|
422
534
|
// ── Main install ──────────────────────────────────────────────────────────────
|
|
423
|
-
|
|
535
|
+
if (!flags.json) {
|
|
536
|
+
console.log('Installing AI assistant skills (.agents/)...');
|
|
537
|
+
}
|
|
424
538
|
|
|
425
539
|
try {
|
|
426
540
|
if (!fs.existsSync(sourcePath)) {
|
|
@@ -441,14 +555,31 @@ try {
|
|
|
441
555
|
|
|
442
556
|
installAtomically(sourcePath, targetPath, { withMcp: flags.withMcp, minimal: flags.minimal });
|
|
443
557
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
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}`);
|
|
449
568
|
}
|
|
450
|
-
|
|
451
|
-
|
|
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
|
+
}
|
|
452
583
|
}
|
|
453
584
|
|
|
454
585
|
// ── Create mcp_config.json only if --with-mcp ────────────────────────────────
|
|
@@ -464,41 +595,80 @@ try {
|
|
|
464
595
|
}
|
|
465
596
|
};
|
|
466
597
|
fs.writeFileSync(mcpConfigPath, JSON.stringify(defaultMcpConfig, null, 2));
|
|
467
|
-
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)');
|
|
468
599
|
}
|
|
469
600
|
}
|
|
470
601
|
|
|
471
602
|
// ── Apply profile if requested or auto ──────────────────────────────────────
|
|
472
|
-
const selectedProfile = flags.profile || (flags.auto ? stackDetection.recommendedProfile : null);
|
|
473
603
|
if (selectedProfile) {
|
|
474
604
|
try {
|
|
475
605
|
const applied = profiles.applyProfile(selectedProfile, process.cwd());
|
|
476
|
-
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'})`);
|
|
477
607
|
} catch (e) {
|
|
478
|
-
console.warn(`[WARN] Could not apply profile '${selectedProfile}': ${e.message}`);
|
|
608
|
+
if (!flags.json) console.warn(`[WARN] Could not apply profile '${selectedProfile}': ${e.message}`);
|
|
479
609
|
}
|
|
480
610
|
}
|
|
481
611
|
|
|
482
|
-
|
|
612
|
+
if (!flags.json) {
|
|
613
|
+
console.log('[OK] Your AI assistant now has skills and rules configured.\n');
|
|
614
|
+
}
|
|
483
615
|
|
|
484
|
-
// ── Auto-compile skills
|
|
616
|
+
// ── Auto-compile skills for target agents ──────────────────────────────────
|
|
485
617
|
if (!flags.skipCompile) {
|
|
486
618
|
const ctxPath = path.join(targetPath, 'ctx.js');
|
|
487
619
|
if (fs.existsSync(ctxPath)) {
|
|
488
|
-
|
|
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}`);
|
|
489
645
|
try {
|
|
490
646
|
const { execFileSync } = require('child_process');
|
|
491
|
-
execFileSync(process.execPath, [ctxPath, '
|
|
647
|
+
execFileSync(process.execPath, [ctxPath, 'skill', 'add', flags.addSkill], {
|
|
492
648
|
cwd: process.cwd(),
|
|
493
|
-
stdio: 'inherit',
|
|
649
|
+
stdio: flags.json ? 'ignore' : 'inherit',
|
|
494
650
|
});
|
|
495
651
|
} catch (e) {
|
|
496
|
-
|
|
497
|
-
|
|
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
|
+
}
|
|
498
656
|
}
|
|
499
657
|
}
|
|
500
|
-
}
|
|
501
|
-
|
|
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);
|
|
502
672
|
}
|
|
503
673
|
|
|
504
674
|
console.log('\n Next steps:');
|
|
@@ -522,26 +692,12 @@ try {
|
|
|
522
692
|
}
|
|
523
693
|
console.log('');
|
|
524
694
|
|
|
525
|
-
// ── --add-skill flag ────────────────────────────────────────────────────────
|
|
526
|
-
if (flags.addSkill) {
|
|
527
|
-
const ctxPath = path.join(targetPath, 'ctx.js');
|
|
528
|
-
if (fs.existsSync(ctxPath)) {
|
|
529
|
-
console.log(`Installing plugin skill: ${flags.addSkill}`);
|
|
530
|
-
try {
|
|
531
|
-
const { execFileSync } = require('child_process');
|
|
532
|
-
execFileSync(process.execPath, [ctxPath, 'skill', 'add', flags.addSkill], {
|
|
533
|
-
cwd: process.cwd(),
|
|
534
|
-
stdio: 'inherit',
|
|
535
|
-
});
|
|
536
|
-
} catch (e) {
|
|
537
|
-
console.warn(`[WARN] Skill install failed — run manually:`);
|
|
538
|
-
console.warn(` node .agents/ctx.js skill add ${flags.addSkill}`);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
|
|
543
695
|
} catch (error) {
|
|
544
|
-
|
|
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
|
+
}
|
|
545
701
|
process.exit(1);
|
|
546
702
|
}
|
|
547
703
|
|