multimodel-dev-os 0.3.0 → 0.5.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/README.md +103 -98
- package/bin/multimodel-dev-os.js +351 -35
- package/docs/caveman-mode.md +7 -3
- package/docs/cli-roadmap.md +33 -21
- package/docs/comparison.md +33 -0
- package/docs/faq.md +21 -4
- package/docs/installers.md +1 -1
- package/docs/launch-kit.md +99 -0
- package/docs/multimodel-workflow.md +10 -11
- package/docs/npm-publishing.md +2 -2
- package/docs/quickstart.md +42 -29
- package/docs/templates-guide.md +65 -0
- package/docs/use-cases.md +39 -0
- package/examples/ecommerce-store/.ai/config.yaml +7 -4
- package/examples/ecommerce-store/.ai/context/architecture.md +6 -0
- package/examples/ecommerce-store/.ai/context/context-budget.md +4 -0
- package/examples/ecommerce-store/.ai/context/model-map.md +4 -0
- package/examples/ecommerce-store/.ai/context/project-brief.md +3 -0
- package/examples/ecommerce-store/.ai/skills/webhook-handler.md +15 -0
- package/examples/ecommerce-store/AGENTS.md +15 -2
- package/examples/ecommerce-store/MEMORY.md +4 -3
- package/examples/ecommerce-store/TASKS.md +10 -0
- package/examples/general-app/.ai/config.yaml +7 -4
- package/examples/general-app/.ai/context/architecture.md +12 -0
- package/examples/general-app/.ai/context/context-budget.md +5 -0
- package/examples/general-app/.ai/context/model-map.md +7 -0
- package/examples/general-app/.ai/context/project-brief.md +6 -0
- package/examples/general-app/.ai/skills/example-skill.md +8 -0
- package/examples/general-app/AGENTS.md +69 -4
- package/examples/general-app/MEMORY.md +32 -2
- package/examples/general-app/TASKS.md +9 -0
- package/examples/nextjs-saas/.ai/config.yaml +7 -4
- package/examples/nextjs-saas/.ai/context/architecture.md +8 -0
- package/examples/nextjs-saas/.ai/context/context-budget.md +4 -0
- package/examples/nextjs-saas/.ai/context/model-map.md +4 -0
- package/examples/nextjs-saas/.ai/context/project-brief.md +5 -0
- package/examples/nextjs-saas/.ai/skills/nextjs-action-build.md +16 -0
- package/examples/nextjs-saas/AGENTS.md +8 -2
- package/examples/nextjs-saas/MEMORY.md +7 -4
- package/examples/nextjs-saas/TASKS.md +12 -0
- package/examples/seo-landing-page/.ai/config.yaml +0 -0
- package/examples/seo-landing-page/.ai/context/architecture.md +12 -0
- package/examples/seo-landing-page/.ai/context/context-budget.md +5 -0
- package/examples/seo-landing-page/.ai/context/model-map.md +7 -0
- package/examples/seo-landing-page/.ai/context/project-brief.md +6 -0
- package/examples/seo-landing-page/.ai/skills/seo-audit.md +21 -0
- package/examples/seo-landing-page/AGENTS.md +69 -4
- package/examples/seo-landing-page/MEMORY.md +33 -4
- package/examples/seo-landing-page/TASKS.md +9 -0
- package/examples/wordpress-site/.ai/config.yaml +7 -4
- package/examples/wordpress-site/.ai/context/architecture.md +7 -0
- package/examples/wordpress-site/.ai/context/context-budget.md +4 -0
- package/examples/wordpress-site/.ai/context/model-map.md +4 -0
- package/examples/wordpress-site/.ai/context/project-brief.md +3 -0
- package/examples/wordpress-site/.ai/skills/plugin-boilerplate.md +21 -0
- package/examples/wordpress-site/AGENTS.md +16 -3
- package/examples/wordpress-site/MEMORY.md +4 -3
- package/examples/wordpress-site/TASKS.md +10 -0
- package/package.json +1 -1
- package/scripts/install.ps1 +1 -1
- package/scripts/install.sh +1 -1
- package/scripts/verify.sh +12 -12
package/bin/multimodel-dev-os.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* multimodel-dev-os CLI
|
|
5
|
-
* Dependency-free local initialization and validation utility.
|
|
5
|
+
* Dependency-free local initialization, diagnostics, and validation utility.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, statSync } from 'fs';
|
|
@@ -13,7 +13,7 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
13
13
|
const __dirname = dirname(__filename);
|
|
14
14
|
const sourceRoot = resolve(__dirname, '..');
|
|
15
15
|
|
|
16
|
-
let version = '0.
|
|
16
|
+
let version = '0.5.0';
|
|
17
17
|
try {
|
|
18
18
|
const pkgData = JSON.parse(readFileSync(resolve(sourceRoot, 'package.json'), 'utf8'));
|
|
19
19
|
version = pkgData.version;
|
|
@@ -60,6 +60,44 @@ function parseArgs(args) {
|
|
|
60
60
|
const params = parseArgs(ARGS);
|
|
61
61
|
const COMMAND = params.command;
|
|
62
62
|
|
|
63
|
+
const TEMPLATES = {
|
|
64
|
+
'nextjs-saas': {
|
|
65
|
+
name: 'nextjs-saas',
|
|
66
|
+
description: 'Next.js App Router starter with TypeScript, Prisma database, Tailwind CSS, and Stripe subscription setup.',
|
|
67
|
+
stack: 'Next.js 14, React 18, TypeScript, Tailwind CSS, Prisma ORM, Stripe payments',
|
|
68
|
+
skill: 'nextjs-action-build.md',
|
|
69
|
+
skillDesc: 'React Server Actions secure implementation conventions.'
|
|
70
|
+
},
|
|
71
|
+
'wordpress-site': {
|
|
72
|
+
name: 'wordpress-site',
|
|
73
|
+
description: 'WordPress custom block theme and plugin development profile with secure PHP database query rules.',
|
|
74
|
+
stack: 'WordPress Core, PHP, Gutenberg Block APIs, theme customization hooks',
|
|
75
|
+
skill: 'plugin-boilerplate.md',
|
|
76
|
+
skillDesc: 'PHP hook registrations and sanitization gates boilerplate.'
|
|
77
|
+
},
|
|
78
|
+
'ecommerce-store': {
|
|
79
|
+
name: 'ecommerce-store',
|
|
80
|
+
description: 'PCI-compliant headless e-commerce store with secure checkout loops, card state validations, and Stripe webhooks.',
|
|
81
|
+
stack: 'Headless Store API, cart states, secure payment webhooks, order database triggers',
|
|
82
|
+
skill: 'webhook-handler.md',
|
|
83
|
+
skillDesc: 'Stripe order checkout webhook secure listener verification rules.'
|
|
84
|
+
},
|
|
85
|
+
'seo-landing-page': {
|
|
86
|
+
name: 'seo-landing-page',
|
|
87
|
+
description: 'Ultra-fast static landing page layout optimized for Astro, high Core Web Vitals scores, and JSON-LD schema markup.',
|
|
88
|
+
stack: 'Astro, HTML5, structured JSON-LD SEO markup, asset minification frameworks',
|
|
89
|
+
skill: 'seo-audit.md',
|
|
90
|
+
skillDesc: 'Lighthouse audits optimization guidelines and Core Web Vitals targets.'
|
|
91
|
+
},
|
|
92
|
+
'general-app': {
|
|
93
|
+
name: 'general-app',
|
|
94
|
+
description: 'Baseline generic fallback profile for standard backend systems (Python, Go, Node, Rust) and universal git workflows.',
|
|
95
|
+
stack: 'Universal backends baseline structure, default git flow parameters',
|
|
96
|
+
skill: 'example-skill.md',
|
|
97
|
+
skillDesc: 'Generic baseline instructions and coding standards.'
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
63
101
|
if (params.help || !COMMAND) {
|
|
64
102
|
showHelp();
|
|
65
103
|
process.exit(0);
|
|
@@ -69,6 +107,19 @@ if (COMMAND === 'init') {
|
|
|
69
107
|
handleInit(params);
|
|
70
108
|
} else if (COMMAND === 'verify') {
|
|
71
109
|
handleVerify(params);
|
|
110
|
+
} else if (COMMAND === 'templates' || COMMAND === 'list-templates') {
|
|
111
|
+
handleListTemplates();
|
|
112
|
+
} else if (COMMAND === 'show-template') {
|
|
113
|
+
const tName = ARGS[1];
|
|
114
|
+
if (!tName || tName.startsWith('-')) {
|
|
115
|
+
console.error('\x1b[31mError: Please specify a template name. Example: node bin/multimodel-dev-os.js show-template nextjs-saas\x1b[0m');
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
handleShowTemplate(tName);
|
|
119
|
+
} else if (COMMAND === 'doctor') {
|
|
120
|
+
handleDoctor(params);
|
|
121
|
+
} else if (COMMAND === 'validate') {
|
|
122
|
+
handleValidate(params);
|
|
72
123
|
} else {
|
|
73
124
|
console.error(`\x1b[31mUnknown command: ${COMMAND}\x1b[0m`);
|
|
74
125
|
showHelp();
|
|
@@ -80,8 +131,13 @@ function showHelp() {
|
|
|
80
131
|
console.log('====================================');
|
|
81
132
|
console.log('Usage: node bin/multimodel-dev-os.js <command> [options]\n');
|
|
82
133
|
console.log('Commands:');
|
|
83
|
-
console.log(' init
|
|
84
|
-
console.log(' verify
|
|
134
|
+
console.log(' init Initialize a project with configs and adapters');
|
|
135
|
+
console.log(' verify Validate structural integrity of an existing project');
|
|
136
|
+
console.log(' templates List all built-in template profiles with details');
|
|
137
|
+
console.log(' list-templates Alias for templates command');
|
|
138
|
+
console.log(' show-template <t> Inspect detailed stack specifications of template <t>');
|
|
139
|
+
console.log(' doctor Advisory checkup of project compatibility loops and ignored folders');
|
|
140
|
+
console.log(' validate Strict validation checks to verify directory schema compliance\n');
|
|
85
141
|
console.log('Options:');
|
|
86
142
|
console.log(' -t, --target <path> Target folder destination (default: current working directory)');
|
|
87
143
|
console.log(' --template <name> Template profile: nextjs-saas, wordpress-site, ecommerce-store,');
|
|
@@ -92,6 +148,48 @@ function showHelp() {
|
|
|
92
148
|
console.log(' -f, --force Overwrite existing files without prompting\n');
|
|
93
149
|
}
|
|
94
150
|
|
|
151
|
+
function handleListTemplates() {
|
|
152
|
+
console.log(`\n🧠 \x1b[36mBuilt-in Template Profiles [v${version}]\x1b[0m`);
|
|
153
|
+
console.log('==================================================');
|
|
154
|
+
Object.keys(TEMPLATES).forEach(key => {
|
|
155
|
+
const t = TEMPLATES[key];
|
|
156
|
+
console.log(`\n\x1b[32m* ${t.name}\x1b[0m`);
|
|
157
|
+
console.log(` \x1b[33mStack:\x1b[0m ${t.stack}`);
|
|
158
|
+
console.log(` \x1b[37mDescription:\x1b[0m ${t.description}`);
|
|
159
|
+
});
|
|
160
|
+
console.log('\nUse \x1b[36mshow-template <template-name>\x1b[0m to view detailed layout specifications.\n');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function handleShowTemplate(name) {
|
|
164
|
+
const t = TEMPLATES[name];
|
|
165
|
+
if (!t) {
|
|
166
|
+
console.error(`\n\x1b[31mError: Template '${name}' does not exist. Available: nextjs-saas, wordpress-site, ecommerce-store, seo-landing-page, general-app\x1b[0m\n`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
console.log(`\n🔍 \x1b[36mTemplate Profile: ${t.name}\x1b[0m`);
|
|
171
|
+
console.log('==================================================');
|
|
172
|
+
console.log(`\x1b[33mStack Blueprint:\x1b[0m ${t.stack}`);
|
|
173
|
+
console.log(`\x1b[33mOverview:\x1b[0m ${t.description}`);
|
|
174
|
+
console.log(`\x1b[33mHighlighted Skill:\x1b[0m .ai/skills/${t.skill}`);
|
|
175
|
+
console.log(` └─> ${t.skillDesc}`);
|
|
176
|
+
console.log('\n\x1b[33mScaffolding Directory Layout:\x1b[0m');
|
|
177
|
+
console.log(' ├── AGENTS.md (Stack building conventions)');
|
|
178
|
+
console.log(' ├── MEMORY.md (Architectural constraints record)');
|
|
179
|
+
console.log(' ├── TASKS.md (Pre-populated first project tasks)');
|
|
180
|
+
console.log(' ├── RUNBOOK.md (Default operations guide)');
|
|
181
|
+
console.log(' └── .ai/');
|
|
182
|
+
console.log(' ├── config.yaml (Enabled adapter options)');
|
|
183
|
+
console.log(' ├── context/');
|
|
184
|
+
console.log(' │ ├── project-brief.md (Scaffolding baseline brief)');
|
|
185
|
+
console.log(' │ ├── architecture.md (Stack specific architecture map)');
|
|
186
|
+
console.log(' │ ├── model-map.md (AI routing specifications)');
|
|
187
|
+
console.log(' │ └── context-budget.md (Token allocation guidelines)');
|
|
188
|
+
console.log(` └── skills/`);
|
|
189
|
+
console.log(` └── ${t.skill} (Custom template skills code boiler)`);
|
|
190
|
+
console.log('\nUse \x1b[32minit --template ' + t.name + '\x1b[0m to bootstrap this profile.\n');
|
|
191
|
+
}
|
|
192
|
+
|
|
95
193
|
function handleInit(options) {
|
|
96
194
|
console.log(`\n\x1b[34mInitializing multimodel-dev-os in: ${options.target}\x1b[0m`);
|
|
97
195
|
console.log(`Template profile: \x1b[32m${options.template}\x1b[0m`);
|
|
@@ -101,23 +199,18 @@ function handleInit(options) {
|
|
|
101
199
|
const operations = [];
|
|
102
200
|
const conflicts = [];
|
|
103
201
|
|
|
104
|
-
//
|
|
105
|
-
let
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
let runbookSrc = join(sourceRoot, 'RUNBOOK.md');
|
|
109
|
-
let configSrc = join(sourceRoot, '.ai', 'config.yaml');
|
|
110
|
-
|
|
111
|
-
// Load custom template directories if selected
|
|
112
|
-
if (options.template !== 'general-app') {
|
|
113
|
-
const templateDir = join(sourceRoot, 'examples', options.template);
|
|
114
|
-
if (existsSync(templateDir)) {
|
|
115
|
-
agentsSrc = join(templateDir, 'AGENTS.md');
|
|
116
|
-
memorySrc = join(templateDir, 'MEMORY.md');
|
|
117
|
-
configSrc = join(templateDir, '.ai', 'config.yaml');
|
|
118
|
-
}
|
|
202
|
+
// Source path mapping for core files
|
|
203
|
+
let templateDir = join(sourceRoot, 'examples', options.template);
|
|
204
|
+
if (!existsSync(templateDir)) {
|
|
205
|
+
templateDir = join(sourceRoot, 'examples', 'general-app');
|
|
119
206
|
}
|
|
120
207
|
|
|
208
|
+
let agentsSrc = join(templateDir, 'AGENTS.md');
|
|
209
|
+
let memorySrc = join(templateDir, 'MEMORY.md');
|
|
210
|
+
let tasksSrc = join(templateDir, 'TASKS.md');
|
|
211
|
+
let runbookSrc = join(sourceRoot, 'RUNBOOK.md'); // Global operational runbook fallback
|
|
212
|
+
let configSrc = join(templateDir, '.ai', 'config.yaml');
|
|
213
|
+
|
|
121
214
|
// Handle Caveman Mode overrides
|
|
122
215
|
if (options.caveman) {
|
|
123
216
|
agentsSrc = join(sourceRoot, '.ai', 'templates', 'AGENTS.caveman.md');
|
|
@@ -126,32 +219,55 @@ function handleInit(options) {
|
|
|
126
219
|
runbookSrc = join(sourceRoot, '.ai', 'templates', 'RUNBOOK.caveman.md');
|
|
127
220
|
}
|
|
128
221
|
|
|
129
|
-
// 1. Core Root Files
|
|
130
222
|
operations.push({ dest: 'AGENTS.md', src: agentsSrc });
|
|
131
223
|
operations.push({ dest: 'MEMORY.md', src: memorySrc });
|
|
132
224
|
operations.push({ dest: 'TASKS.md', src: tasksSrc });
|
|
133
225
|
operations.push({ dest: 'RUNBOOK.md', src: runbookSrc });
|
|
134
226
|
operations.push({ dest: '.ai/config.yaml', src: configSrc });
|
|
135
227
|
|
|
136
|
-
//
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
228
|
+
// Add all files from template-specific context and skills folders if they exist
|
|
229
|
+
const templateAiDir = join(templateDir, '.ai');
|
|
230
|
+
if (existsSync(templateAiDir) && !options.caveman) {
|
|
231
|
+
const subdirs = ['context', 'skills'];
|
|
232
|
+
subdirs.forEach(sub => {
|
|
233
|
+
const subPath = join(templateAiDir, sub);
|
|
234
|
+
if (existsSync(subPath)) {
|
|
235
|
+
readdirSync(subPath).forEach(file => {
|
|
236
|
+
operations.push({
|
|
237
|
+
dest: join('.ai', sub, file),
|
|
238
|
+
src: join(subPath, file)
|
|
239
|
+
});
|
|
145
240
|
});
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Fallback to copy default global folders if files aren't already included by template
|
|
246
|
+
const globalAiSubdirs = ['context', 'agents', 'skills', 'prompts', 'checks', 'templates', 'session-logs'];
|
|
247
|
+
globalAiSubdirs.forEach(sub => {
|
|
248
|
+
const globalPath = join(sourceRoot, '.ai', sub);
|
|
249
|
+
if (existsSync(globalPath)) {
|
|
250
|
+
readdirSync(globalPath).forEach(file => {
|
|
251
|
+
const destRel = join('.ai', sub, file);
|
|
252
|
+
// Only push if not already loaded from the template specific directory overrides
|
|
253
|
+
if (!operations.some(op => op.dest === destRel)) {
|
|
254
|
+
// If --caveman is active, skip regular context/skills to save token files
|
|
255
|
+
if (options.caveman && (sub === 'context' || sub === 'skills' || sub === 'prompts' || sub === 'checks')) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
operations.push({
|
|
259
|
+
dest: destRel,
|
|
260
|
+
src: join(globalPath, file)
|
|
261
|
+
});
|
|
262
|
+
}
|
|
146
263
|
});
|
|
147
264
|
}
|
|
148
265
|
});
|
|
149
266
|
|
|
150
|
-
//
|
|
267
|
+
// Selected Adapters
|
|
151
268
|
options.adapters.forEach(adapter => {
|
|
152
269
|
const adapterDir = join(sourceRoot, 'adapters', adapter);
|
|
153
270
|
if (existsSync(adapterDir)) {
|
|
154
|
-
// Helper function to read recursive files in adapter
|
|
155
271
|
const copyRecursive = (currSrc, currRel) => {
|
|
156
272
|
if (statSync(currSrc).isDirectory()) {
|
|
157
273
|
readdirSync(currSrc).forEach(file => {
|
|
@@ -172,7 +288,7 @@ function handleInit(options) {
|
|
|
172
288
|
}
|
|
173
289
|
});
|
|
174
290
|
|
|
175
|
-
//
|
|
291
|
+
// Audit conflicts
|
|
176
292
|
operations.forEach(op => {
|
|
177
293
|
const targetFile = join(options.target, op.dest);
|
|
178
294
|
if (existsSync(targetFile)) {
|
|
@@ -207,6 +323,16 @@ function handleInit(options) {
|
|
|
207
323
|
}
|
|
208
324
|
});
|
|
209
325
|
|
|
326
|
+
// Ensure crucial directories exist (e.g. for --caveman or missing folders check compliance)
|
|
327
|
+
const dirsToEnsure = ['.ai/context', '.ai/skills', '.ai/session-logs'];
|
|
328
|
+
dirsToEnsure.forEach(d => {
|
|
329
|
+
const fullPath = join(options.target, d);
|
|
330
|
+
if (!options.dryRun && !existsSync(fullPath)) {
|
|
331
|
+
mkdirSync(fullPath, { recursive: true });
|
|
332
|
+
console.log(` \x1b[32mCREATE DIR:\x1b[0m ${d}`);
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
|
|
210
336
|
console.log(`\n\x1b[32m✔ Project initialized successfully! [Total Operations: ${operations.length}]\x1b[0m\n`);
|
|
211
337
|
}
|
|
212
338
|
|
|
@@ -227,11 +353,9 @@ function handleVerify(options) {
|
|
|
227
353
|
}
|
|
228
354
|
};
|
|
229
355
|
|
|
230
|
-
// 1. Core Files
|
|
231
356
|
const rootFiles = ['AGENTS.md', 'MEMORY.md', 'TASKS.md', 'RUNBOOK.md', '.ai/config.yaml'];
|
|
232
357
|
rootFiles.forEach(assertFile);
|
|
233
358
|
|
|
234
|
-
// 2. .ai/context
|
|
235
359
|
const contextFiles = [
|
|
236
360
|
'.ai/context/project-brief.md',
|
|
237
361
|
'.ai/context/architecture.md',
|
|
@@ -243,7 +367,6 @@ function handleVerify(options) {
|
|
|
243
367
|
];
|
|
244
368
|
contextFiles.forEach(assertFile);
|
|
245
369
|
|
|
246
|
-
// 3. .ai/agents
|
|
247
370
|
const agentFiles = [
|
|
248
371
|
'.ai/agents/multimodel-orchestrator.md',
|
|
249
372
|
'.ai/agents/planner.md',
|
|
@@ -265,3 +388,196 @@ function handleVerify(options) {
|
|
|
265
388
|
process.exit(0);
|
|
266
389
|
}
|
|
267
390
|
}
|
|
391
|
+
|
|
392
|
+
function handleDoctor(options) {
|
|
393
|
+
console.log(`\n🩺 \x1b[36mRunning advisory doctor checkup in: ${options.target}\x1b[0m\n`);
|
|
394
|
+
|
|
395
|
+
let warnings = 0;
|
|
396
|
+
|
|
397
|
+
const warn = (msg) => {
|
|
398
|
+
console.warn(` \x1b[33m[WARNING]\x1b[0m ${msg}`);
|
|
399
|
+
warnings++;
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
// 1. .gitignore checks
|
|
403
|
+
const gitignorePath = join(options.target, '.gitignore');
|
|
404
|
+
if (existsSync(gitignorePath)) {
|
|
405
|
+
const content = readFileSync(gitignorePath, 'utf8');
|
|
406
|
+
if (!content.includes('node_modules')) {
|
|
407
|
+
warn('.gitignore is missing node_modules! This will cause AI tools to choke by scanning dependencies.');
|
|
408
|
+
}
|
|
409
|
+
if (!content.includes('.env')) {
|
|
410
|
+
warn('.gitignore is missing .env config boundaries! Secret tokens might get exposed to models.');
|
|
411
|
+
}
|
|
412
|
+
} else {
|
|
413
|
+
warn('Missing .gitignore file in target workspace! AI tools might read large build artifacts.');
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// 2. Build/test/lint presence inside AGENTS.md
|
|
417
|
+
const agentsPath = join(options.target, 'AGENTS.md');
|
|
418
|
+
if (existsSync(agentsPath)) {
|
|
419
|
+
const content = readFileSync(agentsPath, 'utf8');
|
|
420
|
+
if (!content.includes('build:') && !content.includes('build')) {
|
|
421
|
+
warn('AGENTS.md is missing build command specifications.');
|
|
422
|
+
}
|
|
423
|
+
if (!content.includes('test:') && !content.includes('test')) {
|
|
424
|
+
warn('AGENTS.md is missing test command specifications.');
|
|
425
|
+
}
|
|
426
|
+
if (!content.includes('lint:') && !content.includes('lint')) {
|
|
427
|
+
warn('AGENTS.md is missing lint command specifications.');
|
|
428
|
+
}
|
|
429
|
+
} else {
|
|
430
|
+
warn('AGENTS.md is missing from project root.');
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// 3. Null placeholders check in MEMORY.md
|
|
434
|
+
const memoryPath = join(options.target, 'MEMORY.md');
|
|
435
|
+
if (existsSync(memoryPath)) {
|
|
436
|
+
const content = readFileSync(memoryPath, 'utf8');
|
|
437
|
+
const placeholdersCount = (content.match(/null/g) || []).length;
|
|
438
|
+
if (placeholdersCount > 3) {
|
|
439
|
+
warn(`MEMORY.md contains ${placeholdersCount} empty 'null' placeholders. Update project constraints.`);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// 4. Tasks checklist status
|
|
444
|
+
const tasksPath = join(options.target, 'TASKS.md');
|
|
445
|
+
if (existsSync(tasksPath)) {
|
|
446
|
+
const content = readFileSync(tasksPath, 'utf8');
|
|
447
|
+
if (!content.includes('- [ ]') && !content.includes('- [/]')) {
|
|
448
|
+
warn('TASKS.md has no active task section (no tasks marked as - [ ] or - [/]).');
|
|
449
|
+
}
|
|
450
|
+
} else {
|
|
451
|
+
warn('TASKS.md is missing from project root.');
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// 5. Active adapters files audit
|
|
455
|
+
const configPath = join(options.target, '.ai', 'config.yaml');
|
|
456
|
+
if (existsSync(configPath)) {
|
|
457
|
+
const content = readFileSync(configPath, 'utf8');
|
|
458
|
+
const checkAdapter = (adapterName, filename) => {
|
|
459
|
+
const regex = new RegExp(`${adapterName}:\\s*true`);
|
|
460
|
+
if (regex.test(content)) {
|
|
461
|
+
const filePath = join(options.target, filename);
|
|
462
|
+
if (!existsSync(filePath)) {
|
|
463
|
+
warn(`Adapter '${adapterName}' is enabled in .ai/config.yaml but matching adapter file '${filename}' is missing from root.`);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
checkAdapter('cursor', '.cursorrules');
|
|
468
|
+
checkAdapter('claude', 'CLAUDE.md');
|
|
469
|
+
checkAdapter('gemini', 'GEMINI.md');
|
|
470
|
+
checkAdapter('vscode', '.vscode/settings.json');
|
|
471
|
+
} else {
|
|
472
|
+
warn('.ai/config.yaml is missing from project. Active adapters could not be audited.');
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// 6. Token sinks audit
|
|
476
|
+
const sinkFolders = ['node_modules', 'dist', 'build', '.next', '.git'];
|
|
477
|
+
sinkFolders.forEach(folder => {
|
|
478
|
+
const fullPath = join(options.target, folder);
|
|
479
|
+
if (existsSync(fullPath)) {
|
|
480
|
+
const gitignore = existsSync(gitignorePath) ? readFileSync(gitignorePath, 'utf8') : '';
|
|
481
|
+
if (!gitignore.includes(folder)) {
|
|
482
|
+
warn(`Large token-sink directory '${folder}/' is present in workspace but not ignored in .gitignore. AI tools may read it.`);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
console.log('\n==================================================');
|
|
488
|
+
if (warnings > 0) {
|
|
489
|
+
console.log(`\x1b[33mDoctor checkup complete. Found ${warnings} advisory warnings.\x1b[0m\n`);
|
|
490
|
+
} else {
|
|
491
|
+
console.log('\x1b[32m✔ Doctor checkup complete. Your project context layout is pristine!\x1b[0m\n');
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
function handleValidate(options) {
|
|
496
|
+
console.log(`\n🛡 \x1b[34mRunning strict schema validation in: ${options.target}\x1b[0m\n`);
|
|
497
|
+
|
|
498
|
+
let errors = 0;
|
|
499
|
+
|
|
500
|
+
const assertPath = (relPath, type) => {
|
|
501
|
+
const fullPath = join(options.target, relPath);
|
|
502
|
+
if (existsSync(fullPath)) {
|
|
503
|
+
const stat = statSync(fullPath);
|
|
504
|
+
const isOk = (type === 'file') ? stat.isFile() : stat.isDirectory();
|
|
505
|
+
if (isOk) {
|
|
506
|
+
console.log(` \x1b[32m✓\x1b[0m ${relPath} (${type})`);
|
|
507
|
+
} else {
|
|
508
|
+
console.error(` \x1b[31m✗ ${relPath} (expected to be a ${type})\x1b[0m`);
|
|
509
|
+
errors++;
|
|
510
|
+
}
|
|
511
|
+
} else {
|
|
512
|
+
console.error(` \x1b[31m✗ ${relPath} (missing)\x1b[0m`);
|
|
513
|
+
errors++;
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
// 1. Assert Core files
|
|
518
|
+
const core = ['AGENTS.md', 'MEMORY.md', 'TASKS.md', 'RUNBOOK.md', '.ai/config.yaml'];
|
|
519
|
+
core.forEach(f => assertPath(f, 'file'));
|
|
520
|
+
|
|
521
|
+
// 2. Assert Core folders (excluding agents first)
|
|
522
|
+
const dirs = ['.ai/context', '.ai/skills', '.ai/session-logs'];
|
|
523
|
+
dirs.forEach(d => assertPath(d, 'dir'));
|
|
524
|
+
|
|
525
|
+
// 3. Assert .ai/agents exists OR global agent use is explained in AGENTS.md
|
|
526
|
+
const agentsPath = join(options.target, '.ai/agents');
|
|
527
|
+
const agentsExist = existsSync(agentsPath) && statSync(agentsPath).isDirectory();
|
|
528
|
+
if (agentsExist) {
|
|
529
|
+
console.log(` \x1b[32m✓\x1b[0m .ai/agents (dir)`);
|
|
530
|
+
} else {
|
|
531
|
+
const agentsMdPath = join(options.target, 'AGENTS.md');
|
|
532
|
+
let explained = false;
|
|
533
|
+
if (existsSync(agentsMdPath)) {
|
|
534
|
+
const agentsMdContent = readFileSync(agentsMdPath, 'utf8');
|
|
535
|
+
if (
|
|
536
|
+
agentsMdContent.includes('multimodel') ||
|
|
537
|
+
agentsMdContent.includes('orchestrator') ||
|
|
538
|
+
agentsMdContent.includes('global') ||
|
|
539
|
+
agentsMdContent.includes('role') ||
|
|
540
|
+
agentsMdContent.includes('Agent Roles')
|
|
541
|
+
) {
|
|
542
|
+
explained = true;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
if (explained) {
|
|
546
|
+
console.log(` \x1b[32m✓\x1b[0m .ai/agents (missing, but global agent/orchestrator usage explained in AGENTS.md)`);
|
|
547
|
+
} else {
|
|
548
|
+
console.error(` \x1b[31m✗ .ai/agents (missing and global agent use is not explained in AGENTS.md)\x1b[0m`);
|
|
549
|
+
errors++;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// 4. Assert Active adapters files (adapter references are not broken)
|
|
554
|
+
const configPath = join(options.target, '.ai', 'config.yaml');
|
|
555
|
+
if (existsSync(configPath)) {
|
|
556
|
+
const content = readFileSync(configPath, 'utf8');
|
|
557
|
+
const assertAdapter = (adapterName, filename) => {
|
|
558
|
+
const regex = new RegExp(`${adapterName}:\\s*true`);
|
|
559
|
+
if (regex.test(content)) {
|
|
560
|
+
const fullPath = join(options.target, filename);
|
|
561
|
+
if (existsSync(fullPath)) {
|
|
562
|
+
console.log(` \x1b[32m✓\x1b[0m ${filename} (enabled adapter rules file verified)`);
|
|
563
|
+
} else {
|
|
564
|
+
console.error(` \x1b[31m✗ ${filename} (adapter '${adapterName}' is enabled in .ai/config.yaml, but rule file is missing!)\x1b[0m`);
|
|
565
|
+
errors++;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
assertAdapter('cursor', '.cursorrules');
|
|
570
|
+
assertAdapter('claude', 'CLAUDE.md');
|
|
571
|
+
assertAdapter('gemini', 'GEMINI.md');
|
|
572
|
+
assertAdapter('vscode', '.vscode/settings.json');
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
console.log('\n==================================================');
|
|
576
|
+
if (errors > 0) {
|
|
577
|
+
console.error(` \x1b[31mValidation FAILED. Found ${errors} strict structural compliance errors.\x1b[0m\n`);
|
|
578
|
+
process.exit(1);
|
|
579
|
+
} else {
|
|
580
|
+
console.log(' \x1b[32m✔ Validation PASSED. Your project context structure is strictly compliant!\x1b[0m\n');
|
|
581
|
+
process.exit(0);
|
|
582
|
+
}
|
|
583
|
+
}
|
package/docs/caveman-mode.md
CHANGED
|
@@ -21,12 +21,16 @@ AI agents consume tokens for every file they read. In large projects, context wi
|
|
|
21
21
|
| `RUNBOOK.md` | ~400 tokens | ~80 tokens | 80% |
|
|
22
22
|
| **Total** | **~1,600** | **~340** | **~79%** |
|
|
23
23
|
|
|
24
|
-
## How to Use
|
|
25
|
-
|
|
26
24
|
### Fresh Install
|
|
27
25
|
|
|
26
|
+
**Via npx (Recommended):**
|
|
27
|
+
```bash
|
|
28
|
+
npx multimodel-dev-os@latest init --caveman
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Via shell script installer:**
|
|
28
32
|
```bash
|
|
29
|
-
curl -fsSL
|
|
33
|
+
curl -fsSL https://raw.githubusercontent.com/rizvee/multimodel-dev-os/main/scripts/install.sh | bash -s -- --caveman
|
|
30
34
|
```
|
|
31
35
|
|
|
32
36
|
### Convert Existing Project
|
package/docs/cli-roadmap.md
CHANGED
|
@@ -1,44 +1,56 @@
|
|
|
1
1
|
# CLI Roadmap
|
|
2
2
|
|
|
3
|
-
> The
|
|
3
|
+
> The zero-dependency CLI utility is fully integrated with `npm` and `npx` in v0.3.0!
|
|
4
4
|
|
|
5
5
|
## Current CLI Usage
|
|
6
6
|
|
|
7
|
+
Recommended way to execute the CLI globally via npx:
|
|
8
|
+
|
|
7
9
|
```bash
|
|
8
|
-
# Initialize
|
|
9
|
-
|
|
10
|
+
# Initialize standard configuration in current directory
|
|
11
|
+
npx multimodel-dev-os@latest init
|
|
10
12
|
|
|
11
13
|
# Initialize with specific template and adapters
|
|
12
|
-
|
|
14
|
+
npx multimodel-dev-os@latest init --template nextjs-saas --adapter cursor --adapter claude
|
|
13
15
|
|
|
14
|
-
# Run dry-run preview
|
|
15
|
-
|
|
16
|
+
# Run dry-run preview before executing file writes
|
|
17
|
+
npx multimodel-dev-os@latest init --dry-run
|
|
16
18
|
|
|
17
19
|
# Force overwrite existing files
|
|
18
|
-
|
|
20
|
+
npx multimodel-dev-os@latest init --force
|
|
19
21
|
|
|
20
22
|
# Check structural health of target directory
|
|
21
|
-
|
|
23
|
+
npx multimodel-dev-os@latest verify
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
Alternatively, you can run the CLI locally within a cloned workspace:
|
|
27
|
+
```bash
|
|
28
|
+
node bin/multimodel-dev-os.js init
|
|
29
|
+
node bin/multimodel-dev-os.js verify
|
|
30
|
+
```
|
|
25
31
|
|
|
26
32
|
| Command | Purpose | Target Version | Status |
|
|
27
33
|
|---------|---------|----------------|--------|
|
|
28
34
|
| `init` | Scaffold multimodel-dev-os into a project | v0.2.0 | ✅ Completed |
|
|
29
35
|
| `verify` | Check that all required files exist and are valid | v0.2.0 | ✅ Completed |
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
36
|
+
| `templates` | List all built-in template profiles with details | v0.5.0 | ✅ Completed |
|
|
37
|
+
| `show-template` | Inspect stack specifications of a template | v0.5.0 | ✅ Completed |
|
|
38
|
+
| `doctor` | Advisory checkup of workspace compatibility | v0.5.0 | ✅ Completed |
|
|
39
|
+
| `validate` | Strict directory schema compliance checks | v0.5.0 | ✅ Completed |
|
|
40
|
+
| `sync` | Regenerate adapter files from root AGENTS.md | v0.6.0 | 📋 Planned |
|
|
41
|
+
| `add-adapter` | Add a new adapter to the project | v0.6.0 | 📋 Planned |
|
|
42
|
+
|
|
43
|
+
## Requirements Completed in v0.5.0
|
|
44
|
+
|
|
45
|
+
- [x] Implemented strict `validate` CLI command for structural directory validation.
|
|
46
|
+
- [x] Implemented advisory `doctor` command for project compatibility warnings.
|
|
47
|
+
- [x] Implemented `templates` and `show-template` commands for built-in profiles inspection.
|
|
48
|
+
- [x] Upgraded all 5 built-in template profiles with practical real-world contents.
|
|
49
|
+
- [x] Implemented dynamic context budgetary constraints and skills validation.
|
|
50
|
+
- [x] Preserved zero-dependency pure Node CLI implementations.
|
|
32
51
|
|
|
33
|
-
##
|
|
52
|
+
## Future Releases (v0.6.0+)
|
|
34
53
|
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
- [x] Template profile injection (Next.js SaaS, WordPress, etc.)
|
|
38
|
-
- [x] Conflict protection and `--force` overrides
|
|
39
|
-
- [x] Dry-run preview mode
|
|
40
|
-
- [x] Tested on Node 18+ and Windows/macOS/Linux
|
|
54
|
+
* **Adapter Autoregeneration (`sync`):** Parse custom override boundaries inside adapters and automatically synchronize them with updates in the root markdown source of truth.
|
|
55
|
+
* **Interactive Mode:** Provide step-by-step CLI options if run without arguments.
|
|
41
56
|
|
|
42
|
-
## Future Releases (v0.3.0+)
|
|
43
|
-
- Publish package to npm as `multimodel-dev-os` to support `npx` execution.
|
|
44
|
-
- Implement the `sync` subcommand to parse custom override markers inside adapters and align them with changes in root instructions.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Comparison Guide: multimodel-dev-os vs. Alternatives
|
|
2
|
+
|
|
3
|
+
Selecting how to manage AI instructions inside a codebase significantly impacts developer speed, token consumption, and context drift. This document contrasts `multimodel-dev-os` with standard configurations.
|
|
4
|
+
|
|
5
|
+
## The Strategy Matrix
|
|
6
|
+
|
|
7
|
+
| Feature | AGENTS.md Only (DIY) | Tool-Specific Prompt Packs | MultiModel Dev OS (`.ai/` + CLI) |
|
|
8
|
+
| :--- | :--- | :--- | :--- |
|
|
9
|
+
| **Tool Portability** | Manual copying when changing tools | Zero portability (highly vendor-locked) | **Portable & Vendor-Neutral** (Single source of truth) |
|
|
10
|
+
| **Instruction Synchronization** | Manually synchronizing `.cursorrules`, `CLAUDE.md`, etc. | No synchronization (rules drift quickly) | **Automated** (Adapters mirror root rules instantly) |
|
|
11
|
+
| **Token Optimization** | No budgeting (full rules read every time) | Vague, static rules | **Caveman Mode** (slashes token footprints by **~79%**) |
|
|
12
|
+
| **Structural Segregation** | Flat single-file instructions (easily cluttered) | Disorganized configs | **Concise modular directories** (Context, Skills, Prompts, Checks) |
|
|
13
|
+
| **CI/CD Quality Gates** | None (no structural safety checks) | None | **Verify subcommand** (`npm run verify` protects standard formats) |
|
|
14
|
+
| **Standardized Hand-offs** | Manual human explanations | Manual human explanations | **Sequential hand-off protocol** with structured session logs |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Detailed Evaluation
|
|
19
|
+
|
|
20
|
+
### 1. The DIY Approach (AGENTS.md Only)
|
|
21
|
+
Many developers start by dropping a single `AGENTS.md` file in their root. While better than nothing, this approach quickly breaks down:
|
|
22
|
+
* **Drift:** You modify a build command in `AGENTS.md`, but forget to update Cursor's `.cursorrules`. Cursor continues running the old build script, causing confusing errors.
|
|
23
|
+
* **Clutter:** A single markdown file gets bloated with styling guidelines, deployment procedures, and troubleshooting steps. Soon, the AI spends 10,000 tokens just reading instructions on every turn.
|
|
24
|
+
|
|
25
|
+
### 2. Tool-Specific Prompt Packs
|
|
26
|
+
Using tools like `Cursorrules` websites or Claude Code presets locks your project configuration into one vendor's ecosystem:
|
|
27
|
+
* **Vendor Lock:** If your team uses Cursor for coding and Claude Code for debugging, you must duplicate and manually translate the syntax for both tools.
|
|
28
|
+
* **No Collaboration:** Co-workers using different IDEs or terminal utilities cannot benefit from the unified context.
|
|
29
|
+
|
|
30
|
+
### 3. MultiModel Dev OS
|
|
31
|
+
`multimodel-dev-os` establishes a lightweight, vendor-neutral layer that decouples your project's rules from specific tools:
|
|
32
|
+
* **Translate once, read everywhere:** You write build parameters once in the root. The CLI and adapters expose these configurations cleanly to Cursor, Claude, Antigravity, VS Code, and Codex.
|
|
33
|
+
* **Continuous Integration:** You can add `multimodel-dev-os verify` to your CI pipeline or pre-commit hooks to guarantee that all developers share healthy, correctly-formatted AI configurations.
|
package/docs/faq.md
CHANGED
|
@@ -19,16 +19,23 @@ Not "multimodal" (multiple input types like text + image).
|
|
|
19
19
|
## Setup
|
|
20
20
|
|
|
21
21
|
**Do I need Node.js?**
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
It depends on your installation path:
|
|
23
|
+
* **Yes:** If you run the primary, recommended `npx multimodel-dev-os@latest init` workflow, Node.js is required.
|
|
24
|
+
* **No:** If you run the fallback automated shell installer scripts (`install.sh` or `install.ps1`), they run purely on native bash or PowerShell and download resources directly.
|
|
25
|
+
|
|
26
|
+
**Why not just write a single manual AGENTS.md myself?**
|
|
27
|
+
While you can write a raw markdown instruction file manually, `multimodel-dev-os` offers a standardized development environment:
|
|
28
|
+
1. **Automated Bridging:** Rather than copying and pasting rules into `.cursorrules`, `CLAUDE.md`, `.vscode/settings.json`, and `.gemini/settings.json`, our adapters dynamically references your root source of truth.
|
|
29
|
+
2. **Standardized Context Segregation:** Separates concerns cleanly (`MEMORY.md` for architectural context, `TASKS.md` for task state tracking, `RUNBOOK.md` for incident response, and `.ai/` for skills and prompts).
|
|
30
|
+
3. **Structured Verification:** Pre-packaged CLI and verification scripts test and assert the structural completeness of your rules.
|
|
31
|
+
4. **Token Savings:** Seamlessly switches into Caveman Mode to slash token footprints by **~79%** for smaller models.
|
|
24
32
|
|
|
25
33
|
**Can I use just one AI tool?**
|
|
26
34
|
Yes. Use a single adapter. The multi-agent features are optional.
|
|
27
35
|
|
|
28
36
|
**Which files are required?**
|
|
29
37
|
At minimum: `AGENTS.md`. Everything else is optional.
|
|
30
|
-
The installer creates the full structure, but you can delete what you
|
|
31
|
-
don't need.
|
|
38
|
+
The installer creates the full structure, but you can delete what you don't need.
|
|
32
39
|
|
|
33
40
|
## Adapters
|
|
34
41
|
|
|
@@ -64,3 +71,13 @@ should coordinate. Runtime orchestration is planned for v0.2+.
|
|
|
64
71
|
**Do I need the orchestrator for single-agent workflows?**
|
|
65
72
|
No. The orchestrator is only relevant when multiple agents work
|
|
66
73
|
on the same codebase.
|
|
74
|
+
|
|
75
|
+
## Diagnostics & Validation
|
|
76
|
+
|
|
77
|
+
**What is the difference between `validate` and `doctor`?**
|
|
78
|
+
* **`validate`** is strict and verifies that your workspace strictly complies with the multimodel-dev-os directory schema. It checks for the existence of core files/directories and ensures enabled adapter rule references are not broken. If any checks fail, it exits with an error status (exit code 1).
|
|
79
|
+
* **`doctor`** is advisory. It inspects compatibility constraints, warning you about potential context bloat (e.g. missing `.gitignore` files or non-ignored build directories) or active rules missing matching files. It reports warnings without blocking execution.
|
|
80
|
+
|
|
81
|
+
**How do I view available scaffolding templates?**
|
|
82
|
+
You can use `node bin/multimodel-dev-os.js templates` (or `list-templates`) to view all available tech stacks and detailed blueprints, or `show-template <name>` to inspect a specific template's specifications.
|
|
83
|
+
|