bmad-plus 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/README.md +144 -144
- package/package.json +1 -1
- package/readme-international/README.de.md +125 -125
- package/readme-international/README.es.md +215 -215
- package/readme-international/README.fr.md +213 -213
- package/src/bmad-plus/module.yaml +13 -0
- package/src/bmad-plus/packs/pack-memory/README.md +106 -0
- package/src/bmad-plus/packs/pack-memory/memory-orchestrator.md +79 -0
- package/src/bmad-plus/packs/pack-memory/shared/karpathy-guardrails.md +86 -0
- package/src/bmad-plus/packs/pack-memory/shared/memory-protocol.md +143 -0
- package/src/bmad-plus/packs/pack-memory/templates/context.md +39 -0
- package/src/bmad-plus/packs/pack-memory/templates/decisions.md +25 -0
- package/src/bmad-plus/packs/pack-memory/templates/identity.yaml +39 -0
- package/src/bmad-plus/packs/pack-memory/templates/lessons.md +31 -0
- package/src/bmad-plus/packs/pack-memory/templates/patterns.md +24 -0
- package/src/bmad-plus/packs/pack-memory/templates/session-handoff.md +25 -0
- package/src/bmad-plus/packs/pack-memory/zecher-agent.md +157 -0
- package/tools/cli/bmad-plus-cli.js +22 -0
- package/tools/cli/commands/install.js +169 -1
- package/tools/cli/commands/memory.js +194 -0
- package/tools/cli/commands/scan.js +335 -0
- package/tools/cli/i18n.js +30 -10
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BMAD+ Scan Command
|
|
3
|
+
* Scan directories to discover projects, detect stacks, and index them in the global brain.
|
|
4
|
+
* Interactive validation — user confirms each project before indexing.
|
|
5
|
+
*
|
|
6
|
+
* Author: Laurent Rochetta
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const path = require('node:path');
|
|
10
|
+
const fs = require('node:fs');
|
|
11
|
+
const os = require('node:os');
|
|
12
|
+
const crypto = require('node:crypto');
|
|
13
|
+
const clack = require('@clack/prompts');
|
|
14
|
+
const pc = require('picocolors');
|
|
15
|
+
|
|
16
|
+
// Project detection markers (priority order)
|
|
17
|
+
const PROJECT_MARKERS = [
|
|
18
|
+
{ file: 'package.json', stack: 'Node.js', detect: (dir) => {
|
|
19
|
+
try {
|
|
20
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'));
|
|
21
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
22
|
+
if (deps['next']) return 'Next.js';
|
|
23
|
+
if (deps['nuxt']) return 'Nuxt';
|
|
24
|
+
if (deps['react']) return 'React';
|
|
25
|
+
if (deps['vue']) return 'Vue.js';
|
|
26
|
+
if (deps['svelte']) return 'Svelte';
|
|
27
|
+
if (deps['express']) return 'Express';
|
|
28
|
+
if (deps['fastify']) return 'Fastify';
|
|
29
|
+
if (deps['electron']) return 'Electron';
|
|
30
|
+
if (deps['tauri']) return 'Tauri';
|
|
31
|
+
return 'Node.js';
|
|
32
|
+
} catch { return 'Node.js'; }
|
|
33
|
+
}},
|
|
34
|
+
{ file: 'Cargo.toml', stack: 'Rust' },
|
|
35
|
+
{ file: 'pyproject.toml', stack: 'Python' },
|
|
36
|
+
{ file: 'requirements.txt', stack: 'Python' },
|
|
37
|
+
{ file: 'go.mod', stack: 'Go' },
|
|
38
|
+
{ file: 'composer.json', stack: 'PHP' },
|
|
39
|
+
{ file: 'Gemfile', stack: 'Ruby' },
|
|
40
|
+
{ file: 'pom.xml', stack: 'Java' },
|
|
41
|
+
{ file: 'build.gradle', stack: 'Java/Kotlin' },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
// Directories to skip during scanning
|
|
45
|
+
const SKIP_DIRS = new Set([
|
|
46
|
+
'node_modules', '.git', 'vendor', '__pycache__', 'dist', 'build',
|
|
47
|
+
'.next', '.nuxt', '.svelte-kit', 'target', '.venv', 'venv',
|
|
48
|
+
'.cache', '.output', 'coverage', '.turbo', '.angular',
|
|
49
|
+
'$RECYCLE.BIN', 'System Volume Information', 'Windows',
|
|
50
|
+
'Program Files', 'Program Files (x86)', 'ProgramData',
|
|
51
|
+
'AppData', 'Recovery', 'PerfLogs',
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
function getProjectStatus(dir) {
|
|
55
|
+
try {
|
|
56
|
+
const stat = fs.statSync(dir);
|
|
57
|
+
const daysSince = (Date.now() - stat.mtimeMs) / (1000 * 60 * 60 * 24);
|
|
58
|
+
if (daysSince < 30) return 'active';
|
|
59
|
+
if (daysSince < 180) return 'paused';
|
|
60
|
+
return 'archived';
|
|
61
|
+
} catch { return 'unknown'; }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function getStatusIcon(status) {
|
|
65
|
+
switch (status) {
|
|
66
|
+
case 'active': return pc.green('●');
|
|
67
|
+
case 'paused': return pc.yellow('◐');
|
|
68
|
+
case 'archived': return pc.dim('○');
|
|
69
|
+
default: return pc.dim('?');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getProjectName(dir) {
|
|
74
|
+
try {
|
|
75
|
+
const pkgPath = path.join(dir, 'package.json');
|
|
76
|
+
if (fs.existsSync(pkgPath)) {
|
|
77
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
78
|
+
if (pkg.name) return pkg.name;
|
|
79
|
+
}
|
|
80
|
+
} catch {}
|
|
81
|
+
return path.basename(dir);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function hasBmadInstalled(dir) {
|
|
85
|
+
return fs.existsSync(path.join(dir, '.agents')) ||
|
|
86
|
+
fs.existsSync(path.join(dir, '_bmad'));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function scanDirectory(rootDir, maxDepth = 4, currentDepth = 0) {
|
|
90
|
+
const projects = [];
|
|
91
|
+
|
|
92
|
+
if (currentDepth > maxDepth) return projects;
|
|
93
|
+
|
|
94
|
+
let entries;
|
|
95
|
+
try {
|
|
96
|
+
entries = fs.readdirSync(rootDir, { withFileTypes: true });
|
|
97
|
+
} catch {
|
|
98
|
+
return projects; // Permission denied or inaccessible
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Check if current dir is a project
|
|
102
|
+
for (const marker of PROJECT_MARKERS) {
|
|
103
|
+
if (fs.existsSync(path.join(rootDir, marker.file))) {
|
|
104
|
+
const stack = marker.detect ? marker.detect(rootDir) : marker.stack;
|
|
105
|
+
projects.push({
|
|
106
|
+
path: rootDir,
|
|
107
|
+
name: getProjectName(rootDir),
|
|
108
|
+
stack,
|
|
109
|
+
status: getProjectStatus(rootDir),
|
|
110
|
+
bmad: hasBmadInstalled(rootDir),
|
|
111
|
+
hasAgentsMd: fs.existsSync(path.join(rootDir, 'AGENTS.md')),
|
|
112
|
+
hasGit: fs.existsSync(path.join(rootDir, '.git')),
|
|
113
|
+
});
|
|
114
|
+
return projects; // Don't recurse into project subdirs
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Also detect by .git alone (any project with version control)
|
|
119
|
+
if (fs.existsSync(path.join(rootDir, '.git')) && currentDepth > 0) {
|
|
120
|
+
projects.push({
|
|
121
|
+
path: rootDir,
|
|
122
|
+
name: getProjectName(rootDir),
|
|
123
|
+
stack: 'Unknown',
|
|
124
|
+
status: getProjectStatus(rootDir),
|
|
125
|
+
bmad: hasBmadInstalled(rootDir),
|
|
126
|
+
hasAgentsMd: fs.existsSync(path.join(rootDir, 'AGENTS.md')),
|
|
127
|
+
hasGit: true,
|
|
128
|
+
});
|
|
129
|
+
return projects;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Recurse into subdirectories
|
|
133
|
+
for (const entry of entries) {
|
|
134
|
+
if (!entry.isDirectory()) continue;
|
|
135
|
+
if (SKIP_DIRS.has(entry.name)) continue;
|
|
136
|
+
if (entry.name.startsWith('.') && entry.name !== '.git') continue;
|
|
137
|
+
|
|
138
|
+
const subPath = path.join(rootDir, entry.name);
|
|
139
|
+
const subProjects = scanDirectory(subPath, maxDepth, currentDepth + 1);
|
|
140
|
+
projects.push(...subProjects);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return projects;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
module.exports = {
|
|
147
|
+
command: 'scan',
|
|
148
|
+
description: 'Scan directories to discover and index projects in the global brain',
|
|
149
|
+
options: [
|
|
150
|
+
['-d, --directory <path>', 'Directory to scan (default: current directory)'],
|
|
151
|
+
['--depth <n>', 'Max depth to scan (default: 4)', '4'],
|
|
152
|
+
['-y, --yes', 'Index all projects without prompting'],
|
|
153
|
+
],
|
|
154
|
+
action: async (options) => {
|
|
155
|
+
const scanDir = path.resolve(options.directory || process.cwd());
|
|
156
|
+
const maxDepth = parseInt(options.depth) || 4;
|
|
157
|
+
|
|
158
|
+
clack.intro(pc.bgMagenta(pc.white(' 🧠 BMAD+ Project Scanner ')));
|
|
159
|
+
|
|
160
|
+
// Verify directory exists
|
|
161
|
+
if (!fs.existsSync(scanDir)) {
|
|
162
|
+
clack.log.error(`Directory not found: ${scanDir}`);
|
|
163
|
+
clack.outro(pc.red('Scan failed.'));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Scan
|
|
168
|
+
const spinner = clack.spinner();
|
|
169
|
+
spinner.start(`Scanning ${scanDir} (depth: ${maxDepth})...`);
|
|
170
|
+
|
|
171
|
+
const projects = scanDirectory(scanDir, maxDepth);
|
|
172
|
+
|
|
173
|
+
if (projects.length === 0) {
|
|
174
|
+
spinner.stop('No projects found.');
|
|
175
|
+
clack.outro('Try scanning a different directory or increasing --depth');
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
spinner.stop(`Found ${pc.bold(projects.length)} project(s)`);
|
|
180
|
+
|
|
181
|
+
// Display table
|
|
182
|
+
clack.log.info('');
|
|
183
|
+
clack.log.info(pc.bold(' # Status BMAD+ Stack Name Path'));
|
|
184
|
+
clack.log.info(pc.dim(' ' + '─'.repeat(90)));
|
|
185
|
+
|
|
186
|
+
projects.forEach((p, i) => {
|
|
187
|
+
const num = String(i + 1).padStart(3);
|
|
188
|
+
const status = getStatusIcon(p.status) + ' ' + p.status.padEnd(8);
|
|
189
|
+
const bmad = p.bmad ? pc.green('✓') : pc.dim('·');
|
|
190
|
+
const stack = p.stack.padEnd(16);
|
|
191
|
+
const name = p.name.substring(0, 20).padEnd(20);
|
|
192
|
+
const projPath = p.path.length > 40 ? '...' + p.path.slice(-37) : p.path;
|
|
193
|
+
clack.log.info(` ${num} ${status} ${bmad} ${stack} ${name} ${pc.dim(projPath)}`);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
clack.log.info('');
|
|
197
|
+
|
|
198
|
+
// Interactive validation
|
|
199
|
+
const globalBrainDir = path.join(os.homedir(), '.bmad-plus', 'brain', 'projects');
|
|
200
|
+
|
|
201
|
+
if (options.yes) {
|
|
202
|
+
// Auto-index all
|
|
203
|
+
const fsExtra = require('fs-extra');
|
|
204
|
+
fsExtra.ensureDirSync(globalBrainDir);
|
|
205
|
+
|
|
206
|
+
let indexed = 0;
|
|
207
|
+
for (const proj of projects) {
|
|
208
|
+
const hash = crypto.createHash('sha256').update(proj.path).digest('hex').slice(0, 8);
|
|
209
|
+
const meta = {
|
|
210
|
+
path: proj.path,
|
|
211
|
+
name: proj.name,
|
|
212
|
+
hash,
|
|
213
|
+
stack: proj.stack,
|
|
214
|
+
status: proj.status,
|
|
215
|
+
bmad_installed: proj.bmad,
|
|
216
|
+
has_git: proj.hasGit,
|
|
217
|
+
last_scanned: new Date().toISOString().slice(0, 10),
|
|
218
|
+
};
|
|
219
|
+
fs.writeFileSync(
|
|
220
|
+
path.join(globalBrainDir, `${hash}.yaml`),
|
|
221
|
+
Object.entries(meta).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join('\n'),
|
|
222
|
+
'utf8'
|
|
223
|
+
);
|
|
224
|
+
indexed++;
|
|
225
|
+
}
|
|
226
|
+
clack.log.success(`✅ ${indexed} project(s) indexed in ${globalBrainDir}`);
|
|
227
|
+
} else {
|
|
228
|
+
// Interactive mode
|
|
229
|
+
const action = await clack.select({
|
|
230
|
+
message: `${projects.length} project(s) found. What to do?`,
|
|
231
|
+
options: [
|
|
232
|
+
{ value: 'all', label: `✅ Index all ${projects.length} projects` },
|
|
233
|
+
{ value: 'select', label: '✏️ Select which to index' },
|
|
234
|
+
{ value: 'none', label: '⏭️ Skip — don\'t index anything' },
|
|
235
|
+
],
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
if (clack.isCancel(action) || action === 'none') {
|
|
239
|
+
clack.cancel('Scan cancelled.');
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const fsExtra = require('fs-extra');
|
|
244
|
+
fsExtra.ensureDirSync(globalBrainDir);
|
|
245
|
+
|
|
246
|
+
let toIndex = projects;
|
|
247
|
+
|
|
248
|
+
if (action === 'select') {
|
|
249
|
+
const selected = await clack.multiselect({
|
|
250
|
+
message: 'Select projects to index:',
|
|
251
|
+
options: projects.map((p, i) => ({
|
|
252
|
+
value: i,
|
|
253
|
+
label: `${p.name} (${p.stack})`,
|
|
254
|
+
hint: `${p.status} — ${p.path}`,
|
|
255
|
+
})),
|
|
256
|
+
required: false,
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
if (clack.isCancel(selected)) {
|
|
260
|
+
clack.cancel('Scan cancelled.');
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
toIndex = selected.map(i => projects[i]);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
let indexed = 0;
|
|
268
|
+
for (const proj of toIndex) {
|
|
269
|
+
const hash = crypto.createHash('sha256').update(proj.path).digest('hex').slice(0, 8);
|
|
270
|
+
const meta = {
|
|
271
|
+
path: proj.path,
|
|
272
|
+
name: proj.name,
|
|
273
|
+
hash,
|
|
274
|
+
stack: proj.stack,
|
|
275
|
+
status: proj.status,
|
|
276
|
+
bmad_installed: proj.bmad,
|
|
277
|
+
has_git: proj.hasGit,
|
|
278
|
+
last_scanned: new Date().toISOString().slice(0, 10),
|
|
279
|
+
};
|
|
280
|
+
fs.writeFileSync(
|
|
281
|
+
path.join(globalBrainDir, `${hash}.yaml`),
|
|
282
|
+
Object.entries(meta).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join('\n'),
|
|
283
|
+
'utf8'
|
|
284
|
+
);
|
|
285
|
+
indexed++;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
clack.log.success(`✅ ${indexed} project(s) indexed in global brain`);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Generate human-readable index
|
|
292
|
+
const indexPath = path.join(os.homedir(), '.bmad-plus', 'brain', 'projects-index.md');
|
|
293
|
+
const existingProjects = [];
|
|
294
|
+
if (fs.existsSync(globalBrainDir)) {
|
|
295
|
+
for (const f of fs.readdirSync(globalBrainDir)) {
|
|
296
|
+
if (!f.endsWith('.yaml')) continue;
|
|
297
|
+
try {
|
|
298
|
+
const content = fs.readFileSync(path.join(globalBrainDir, f), 'utf8');
|
|
299
|
+
const meta = {};
|
|
300
|
+
for (const line of content.split('\n')) {
|
|
301
|
+
const m = line.match(/^(\w+):\s*(.+)$/);
|
|
302
|
+
if (m) {
|
|
303
|
+
try { meta[m[1]] = JSON.parse(m[2]); } catch { meta[m[1]] = m[2]; }
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
existingProjects.push(meta);
|
|
307
|
+
} catch {}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const indexContent = [
|
|
312
|
+
'---',
|
|
313
|
+
'title: Project Index',
|
|
314
|
+
`last_updated: "${new Date().toISOString().slice(0, 10)}"`,
|
|
315
|
+
`total_projects: ${existingProjects.length}`,
|
|
316
|
+
'---',
|
|
317
|
+
'',
|
|
318
|
+
'# Project Index',
|
|
319
|
+
'',
|
|
320
|
+
`> Auto-generated by \`npx bmad-plus scan\` — ${new Date().toISOString().slice(0, 10)}`,
|
|
321
|
+
'',
|
|
322
|
+
'| Status | Name | Stack | BMAD+ | Path |',
|
|
323
|
+
'|--------|------|-------|-------|------|',
|
|
324
|
+
...existingProjects.map(p =>
|
|
325
|
+
`| ${p.status || '?'} | ${p.name || '?'} | ${p.stack || '?'} | ${p.bmad_installed ? '✓' : '·'} | \`${p.path || '?'}\` |`
|
|
326
|
+
),
|
|
327
|
+
'',
|
|
328
|
+
];
|
|
329
|
+
|
|
330
|
+
fs.writeFileSync(indexPath, indexContent.join('\n'), 'utf8');
|
|
331
|
+
clack.log.info(`📋 Project index updated: ${indexPath}`);
|
|
332
|
+
|
|
333
|
+
clack.outro(pc.green('Scan complete! 🧠'));
|
|
334
|
+
},
|
|
335
|
+
};
|
package/tools/cli/i18n.js
CHANGED
|
@@ -10,7 +10,7 @@ const LANGUAGES = {
|
|
|
10
10
|
flag: '🇬🇧',
|
|
11
11
|
name: 'English',
|
|
12
12
|
locale: 'en',
|
|
13
|
-
installer_title: ' BMAD+ Installer v0.
|
|
13
|
+
installer_title: ' BMAD+ Installer v0.7.1 ',
|
|
14
14
|
select_language: 'Select your language',
|
|
15
15
|
installing_to: 'Installing to',
|
|
16
16
|
select_packs: 'Which packs to install? (Core is always included)',
|
|
@@ -76,13 +76,23 @@ const LANGUAGES = {
|
|
|
76
76
|
guide_example_backup: '🗂️ Backup: "/backup create" → ZIP timestamped',
|
|
77
77
|
guide_example_animated: '🎬 Animated: "/animated build hero.mp4"',
|
|
78
78
|
guide_example_osint: '🔍 OSINT: "Shadow, investigate John Doe"',
|
|
79
|
+
guide_memory: '🧠 Persistent Brain',
|
|
80
|
+
guide_dev_studio: '🏗️ Dev Studio',
|
|
81
|
+
guide_example_memory_1: '🧠 Memory: "Zecher, scan projects in D:\\DEV"',
|
|
82
|
+
guide_example_memory_2: '🧠 Memory: "Zecher, where were we?"',
|
|
83
|
+
guide_example_memory_3: '🧠 Memory: "Zecher, consolidate memory"',
|
|
84
|
+
guide_example_dev_studio_1: '🏗️ Dev Studio: "Miriam, brainstorm a productivity app"',
|
|
85
|
+
guide_example_dev_studio_2: '🏗️ Dev Studio: "Bezalel, design the architecture"',
|
|
86
|
+
guide_example_dev_studio_3: '🏗️ Dev Studio: "Oholiab, implement story S1"',
|
|
87
|
+
brain_detected: 'Existing brain detected',
|
|
88
|
+
brain_created: 'Global brain created',
|
|
79
89
|
},
|
|
80
90
|
|
|
81
91
|
fr: {
|
|
82
92
|
flag: '🇫🇷',
|
|
83
93
|
name: 'Français',
|
|
84
94
|
locale: 'fr',
|
|
85
|
-
installer_title: ' BMAD+ Installeur v0.
|
|
95
|
+
installer_title: ' BMAD+ Installeur v0.7.1 ',
|
|
86
96
|
select_language: 'Choisissez votre langue',
|
|
87
97
|
installing_to: 'Installation dans',
|
|
88
98
|
select_packs: 'Quels packs installer ? (Core est toujours inclus)',
|
|
@@ -146,13 +156,23 @@ const LANGUAGES = {
|
|
|
146
156
|
guide_example_backup: '🗂️ Backup : "/backup create" → ZIP horodaté',
|
|
147
157
|
guide_example_animated: '🎬 Animé : "/animated build hero.mp4"',
|
|
148
158
|
guide_example_osint: '🔍 OSINT : "Shadow, investigate John Doe"',
|
|
159
|
+
guide_memory: '🧠 Cerveau persistant',
|
|
160
|
+
guide_dev_studio: '🏗️ Dev Studio',
|
|
161
|
+
guide_example_memory_1: '🧠 Mémoire : "Zecher, scanne les projets dans D:\\DEV"',
|
|
162
|
+
guide_example_memory_2: '🧠 Mémoire : "Zecher, où en étions-nous ?"',
|
|
163
|
+
guide_example_memory_3: '🧠 Mémoire : "Zecher, consolide la mémoire"',
|
|
164
|
+
guide_example_dev_studio_1: '🏗️ Dev Studio : "Miriam, brainstorme une app de productivité"',
|
|
165
|
+
guide_example_dev_studio_2: '🏗️ Dev Studio : "Bezalel, conçois l\'architecture"',
|
|
166
|
+
guide_example_dev_studio_3: '🏗️ Dev Studio : "Oholiab, implémente la story S1"',
|
|
167
|
+
brain_detected: 'Cerveau existant détecté',
|
|
168
|
+
brain_created: 'Cerveau global créé',
|
|
149
169
|
},
|
|
150
170
|
|
|
151
171
|
es: {
|
|
152
172
|
flag: '🇪🇸',
|
|
153
173
|
name: 'Español',
|
|
154
174
|
locale: 'es',
|
|
155
|
-
installer_title: ' BMAD+ Instalador v0.
|
|
175
|
+
installer_title: ' BMAD+ Instalador v0.7.1 ',
|
|
156
176
|
select_language: 'Seleccione su idioma',
|
|
157
177
|
installing_to: 'Instalando en',
|
|
158
178
|
select_packs: '¿Qué packs instalar? (Core siempre está incluido)',
|
|
@@ -222,7 +242,7 @@ const LANGUAGES = {
|
|
|
222
242
|
flag: '🇩🇪',
|
|
223
243
|
name: 'Deutsch',
|
|
224
244
|
locale: 'de',
|
|
225
|
-
installer_title: ' BMAD+ Installer v0.
|
|
245
|
+
installer_title: ' BMAD+ Installer v0.7.1 ',
|
|
226
246
|
select_language: 'Wählen Sie Ihre Sprache',
|
|
227
247
|
installing_to: 'Installiere in',
|
|
228
248
|
select_packs: 'Welche Packs installieren? (Core ist immer enthalten)',
|
|
@@ -292,7 +312,7 @@ const LANGUAGES = {
|
|
|
292
312
|
flag: '🇧🇷',
|
|
293
313
|
name: 'Português (Brasil)',
|
|
294
314
|
locale: 'pt-BR',
|
|
295
|
-
installer_title: ' BMAD+ Instalador v0.
|
|
315
|
+
installer_title: ' BMAD+ Instalador v0.7.1 ',
|
|
296
316
|
select_language: 'Selecione seu idioma',
|
|
297
317
|
installing_to: 'Instalando em',
|
|
298
318
|
select_packs: 'Quais packs instalar? (Core sempre está incluído)',
|
|
@@ -362,7 +382,7 @@ const LANGUAGES = {
|
|
|
362
382
|
flag: '🇷🇺',
|
|
363
383
|
name: 'Русский',
|
|
364
384
|
locale: 'ru',
|
|
365
|
-
installer_title: ' BMAD+ Установщик v0.
|
|
385
|
+
installer_title: ' BMAD+ Установщик v0.7.1 ',
|
|
366
386
|
select_language: 'Выберите язык',
|
|
367
387
|
installing_to: 'Установка в',
|
|
368
388
|
select_packs: 'Какие пакеты установить? (Core всегда включён)',
|
|
@@ -432,7 +452,7 @@ const LANGUAGES = {
|
|
|
432
452
|
flag: '🇨🇳',
|
|
433
453
|
name: '中文 (简体)',
|
|
434
454
|
locale: 'zh-CN',
|
|
435
|
-
installer_title: ' BMAD+ 安装程序 v0.
|
|
455
|
+
installer_title: ' BMAD+ 安装程序 v0.7.1 ',
|
|
436
456
|
select_language: '选择您的语言',
|
|
437
457
|
installing_to: '安装到',
|
|
438
458
|
select_packs: '安装哪些包?(Core 始终包含)',
|
|
@@ -502,7 +522,7 @@ const LANGUAGES = {
|
|
|
502
522
|
flag: '🇮🇱',
|
|
503
523
|
name: 'עברית',
|
|
504
524
|
locale: 'he',
|
|
505
|
-
installer_title: ' BMAD+ מתקין v0.
|
|
525
|
+
installer_title: ' BMAD+ מתקין v0.7.1 ',
|
|
506
526
|
select_language: 'בחר את השפה שלך',
|
|
507
527
|
installing_to: 'מתקין ב',
|
|
508
528
|
select_packs: 'אילו חבילות להתקין? (Core תמיד כלול)',
|
|
@@ -572,7 +592,7 @@ const LANGUAGES = {
|
|
|
572
592
|
flag: '🇯🇵',
|
|
573
593
|
name: '日本語',
|
|
574
594
|
locale: 'ja',
|
|
575
|
-
installer_title: ' BMAD+ インストーラー v0.
|
|
595
|
+
installer_title: ' BMAD+ インストーラー v0.7.1 ',
|
|
576
596
|
select_language: '言語を選択してください',
|
|
577
597
|
installing_to: 'インストール先',
|
|
578
598
|
select_packs: 'どのパックをインストールしますか?(Coreは常に含まれます)',
|
|
@@ -642,7 +662,7 @@ const LANGUAGES = {
|
|
|
642
662
|
flag: '🇮🇹',
|
|
643
663
|
name: 'Italiano',
|
|
644
664
|
locale: 'it',
|
|
645
|
-
installer_title: ' BMAD+ Installatore v0.
|
|
665
|
+
installer_title: ' BMAD+ Installatore v0.7.1 ',
|
|
646
666
|
select_language: 'Seleziona la tua lingua',
|
|
647
667
|
installing_to: 'Installazione in',
|
|
648
668
|
select_packs: 'Quali pack installare? (Core è sempre incluso)',
|