@aslomon/effectum 0.2.1 → 0.3.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 +23 -16
- package/bin/install.js +182 -108
- package/bin/lib/app-types.js +96 -0
- package/bin/lib/config.js +22 -3
- package/bin/lib/constants.js +14 -30
- package/bin/lib/foundation.js +63 -0
- package/bin/lib/languages.js +77 -0
- package/bin/lib/recommendation.js +392 -0
- package/bin/lib/specializations.js +123 -0
- package/bin/lib/template.js +2 -1
- package/bin/lib/ui.js +350 -21
- package/bin/reconfigure.js +29 -3
- package/package.json +1 -1
package/bin/lib/ui.js
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared @clack/prompts helpers and display utilities.
|
|
3
3
|
* Uses dynamic import() because @clack/prompts is ESM-only.
|
|
4
|
+
*
|
|
5
|
+
* Supports the 9-step intelligent setup flow:
|
|
6
|
+
* 1. Install Scope 2. Project Basics 3. App Type 4. Description
|
|
7
|
+
* 5. Language 6. Autonomy 7. Recommendation Preview 8. Decision 9. Install
|
|
4
8
|
*/
|
|
5
9
|
"use strict";
|
|
6
10
|
|
|
11
|
+
const { STACK_CHOICES, AUTONOMY_CHOICES, MCP_SERVERS } = require("./constants");
|
|
12
|
+
const { LANGUAGE_CHOICES } = require("./languages");
|
|
13
|
+
const { APP_TYPE_CHOICES } = require("./app-types");
|
|
14
|
+
const { FOUNDATION_HOOKS } = require("./foundation");
|
|
7
15
|
const {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
getAllCommands,
|
|
17
|
+
getAllHooks,
|
|
18
|
+
getAllSkills,
|
|
19
|
+
getAllMcps,
|
|
20
|
+
getAllSubagents,
|
|
21
|
+
} = require("./recommendation");
|
|
13
22
|
|
|
14
23
|
/** @type {import("@clack/prompts")} */
|
|
15
24
|
let p;
|
|
@@ -26,7 +35,7 @@ async function initClack() {
|
|
|
26
35
|
}
|
|
27
36
|
|
|
28
37
|
/**
|
|
29
|
-
* Get the loaded clack instance
|
|
38
|
+
* Get the loaded clack instance.
|
|
30
39
|
* @returns {import("@clack/prompts")}
|
|
31
40
|
*/
|
|
32
41
|
function getClack() {
|
|
@@ -38,7 +47,7 @@ function getClack() {
|
|
|
38
47
|
* Print the Effectum banner via clack intro.
|
|
39
48
|
*/
|
|
40
49
|
function printBanner() {
|
|
41
|
-
p.intro("EFFECTUM —
|
|
50
|
+
p.intro("EFFECTUM — Intelligent Setup for Claude Code");
|
|
42
51
|
}
|
|
43
52
|
|
|
44
53
|
/**
|
|
@@ -52,6 +61,35 @@ function handleCancel(value) {
|
|
|
52
61
|
}
|
|
53
62
|
}
|
|
54
63
|
|
|
64
|
+
// ─── Step 1: Install Scope ──────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Ask for install scope.
|
|
68
|
+
* @returns {Promise<string>} "local" or "global"
|
|
69
|
+
*/
|
|
70
|
+
async function askScope() {
|
|
71
|
+
const value = await p.select({
|
|
72
|
+
message: "Install scope",
|
|
73
|
+
options: [
|
|
74
|
+
{
|
|
75
|
+
value: "local",
|
|
76
|
+
label: "Local",
|
|
77
|
+
hint: "This project only (./.claude/)",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
value: "global",
|
|
81
|
+
label: "Global",
|
|
82
|
+
hint: "All projects (~/.claude/)",
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
initialValue: "local",
|
|
86
|
+
});
|
|
87
|
+
handleCancel(value);
|
|
88
|
+
return value;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ─── Step 2: Project Basics ─────────────────────────────────────────────────
|
|
92
|
+
|
|
55
93
|
/**
|
|
56
94
|
* Ask for project name with a detected default.
|
|
57
95
|
* @param {string} detected
|
|
@@ -89,6 +127,47 @@ async function askStack(detected) {
|
|
|
89
127
|
return value;
|
|
90
128
|
}
|
|
91
129
|
|
|
130
|
+
// ─── Step 3: App Type ───────────────────────────────────────────────────────
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Ask for app type selection.
|
|
134
|
+
* @returns {Promise<string>}
|
|
135
|
+
*/
|
|
136
|
+
async function askAppType() {
|
|
137
|
+
const value = await p.select({
|
|
138
|
+
message: "What are you building?",
|
|
139
|
+
options: APP_TYPE_CHOICES.map((c) => ({
|
|
140
|
+
value: c.value,
|
|
141
|
+
label: c.label,
|
|
142
|
+
hint: c.hint,
|
|
143
|
+
})),
|
|
144
|
+
initialValue: "web-app",
|
|
145
|
+
});
|
|
146
|
+
handleCancel(value);
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ─── Step 4: Description ────────────────────────────────────────────────────
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Ask for a free-text project description.
|
|
154
|
+
* @returns {Promise<string>}
|
|
155
|
+
*/
|
|
156
|
+
async function askDescription() {
|
|
157
|
+
const value = await p.text({
|
|
158
|
+
message: "Describe what you want to build (one sentence)",
|
|
159
|
+
placeholder: "e.g. An internal CRM dashboard with auth and analytics",
|
|
160
|
+
validate: (v) => {
|
|
161
|
+
if (!v.trim())
|
|
162
|
+
return "A short description helps generate better recommendations";
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
handleCancel(value);
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ─── Step 5: Language ───────────────────────────────────────────────────────
|
|
170
|
+
|
|
92
171
|
/**
|
|
93
172
|
* Ask for communication language.
|
|
94
173
|
* @returns {Promise<{ language: string, customLanguage?: string }>}
|
|
@@ -120,13 +199,15 @@ async function askLanguage() {
|
|
|
120
199
|
return { language: value };
|
|
121
200
|
}
|
|
122
201
|
|
|
202
|
+
// ─── Step 6: Autonomy ───────────────────────────────────────────────────────
|
|
203
|
+
|
|
123
204
|
/**
|
|
124
205
|
* Ask for autonomy level.
|
|
125
206
|
* @returns {Promise<string>}
|
|
126
207
|
*/
|
|
127
208
|
async function askAutonomy() {
|
|
128
209
|
const value = await p.select({
|
|
129
|
-
message: "
|
|
210
|
+
message: "How should Claude work?",
|
|
130
211
|
options: AUTONOMY_CHOICES.map((c) => ({
|
|
131
212
|
value: c.value,
|
|
132
213
|
label: c.label,
|
|
@@ -138,6 +219,232 @@ async function askAutonomy() {
|
|
|
138
219
|
return value;
|
|
139
220
|
}
|
|
140
221
|
|
|
222
|
+
// ─── Step 7: Recommendation Preview ─────────────────────────────────────────
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Display the recommendation preview.
|
|
226
|
+
* @param {object} rec - recommendation from recommend()
|
|
227
|
+
*/
|
|
228
|
+
function showRecommendation(rec) {
|
|
229
|
+
const lines = [];
|
|
230
|
+
|
|
231
|
+
lines.push("FOUNDATION (always active)");
|
|
232
|
+
for (const h of FOUNDATION_HOOKS) {
|
|
233
|
+
lines.push(` + ${h.label}`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
lines.push("");
|
|
237
|
+
lines.push("RECOMMENDED COMMANDS");
|
|
238
|
+
for (const key of rec.commands) {
|
|
239
|
+
lines.push(` + /${key}`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
lines.push("");
|
|
243
|
+
lines.push("RECOMMENDED HOOKS");
|
|
244
|
+
for (const key of rec.hooks) {
|
|
245
|
+
lines.push(` + ${key}`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (rec.skills.length > 0) {
|
|
249
|
+
lines.push("");
|
|
250
|
+
lines.push("RECOMMENDED SKILLS");
|
|
251
|
+
for (const key of rec.skills) {
|
|
252
|
+
lines.push(` + ${key}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
lines.push("");
|
|
257
|
+
lines.push("RECOMMENDED MCP SERVERS");
|
|
258
|
+
for (const key of rec.mcps) {
|
|
259
|
+
const server = MCP_SERVERS.find((s) => s.key === key);
|
|
260
|
+
lines.push(` + ${server ? server.label : key}`);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
lines.push("");
|
|
264
|
+
lines.push("RECOMMENDED SUBAGENT SPECIALIZATIONS");
|
|
265
|
+
for (const key of rec.subagents) {
|
|
266
|
+
lines.push(` + ${key}`);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
lines.push("");
|
|
270
|
+
lines.push("AGENT TEAMS: disabled (experimental, enable manually)");
|
|
271
|
+
|
|
272
|
+
p.note(lines.join("\n"), "Recommended Setup");
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// ─── Step 8: Decision ───────────────────────────────────────────────────────
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Ask user how to proceed with the recommendation.
|
|
279
|
+
* @returns {Promise<string>} "recommended" | "customize" | "manual"
|
|
280
|
+
*/
|
|
281
|
+
async function askSetupMode() {
|
|
282
|
+
const value = await p.select({
|
|
283
|
+
message: "How do you want to proceed?",
|
|
284
|
+
options: [
|
|
285
|
+
{
|
|
286
|
+
value: "recommended",
|
|
287
|
+
label: "Use Recommended",
|
|
288
|
+
hint: "Install the recommended setup as-is",
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
value: "customize",
|
|
292
|
+
label: "Customize",
|
|
293
|
+
hint: "Start from recommendations, toggle items on/off",
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
value: "manual",
|
|
297
|
+
label: "Manual Selection",
|
|
298
|
+
hint: "Choose everything yourself from scratch",
|
|
299
|
+
},
|
|
300
|
+
],
|
|
301
|
+
initialValue: "recommended",
|
|
302
|
+
});
|
|
303
|
+
handleCancel(value);
|
|
304
|
+
return value;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Let user customize the recommended setup by toggling items.
|
|
309
|
+
* @param {object} rec - current recommendation
|
|
310
|
+
* @returns {Promise<object>} modified recommendation
|
|
311
|
+
*/
|
|
312
|
+
async function askCustomize(rec) {
|
|
313
|
+
const result = { ...rec };
|
|
314
|
+
|
|
315
|
+
// Commands
|
|
316
|
+
const commands = await p.multiselect({
|
|
317
|
+
message: "Commands (space to toggle)",
|
|
318
|
+
options: getAllCommands().map((c) => ({
|
|
319
|
+
value: c.key,
|
|
320
|
+
label: c.label,
|
|
321
|
+
})),
|
|
322
|
+
initialValues: rec.commands,
|
|
323
|
+
required: false,
|
|
324
|
+
});
|
|
325
|
+
handleCancel(commands);
|
|
326
|
+
result.commands = commands;
|
|
327
|
+
|
|
328
|
+
// Skills
|
|
329
|
+
const skills = await p.multiselect({
|
|
330
|
+
message: "Skills (space to toggle)",
|
|
331
|
+
options: getAllSkills().map((s) => ({
|
|
332
|
+
value: s.key,
|
|
333
|
+
label: s.label,
|
|
334
|
+
})),
|
|
335
|
+
initialValues: rec.skills,
|
|
336
|
+
required: false,
|
|
337
|
+
});
|
|
338
|
+
handleCancel(skills);
|
|
339
|
+
result.skills = skills;
|
|
340
|
+
|
|
341
|
+
// MCP servers
|
|
342
|
+
const mcps = await p.multiselect({
|
|
343
|
+
message: "MCP servers (space to toggle)",
|
|
344
|
+
options: getAllMcps().map((m) => ({
|
|
345
|
+
value: m.key,
|
|
346
|
+
label: m.label,
|
|
347
|
+
hint: m.desc,
|
|
348
|
+
})),
|
|
349
|
+
initialValues: rec.mcps,
|
|
350
|
+
required: false,
|
|
351
|
+
});
|
|
352
|
+
handleCancel(mcps);
|
|
353
|
+
result.mcps = mcps;
|
|
354
|
+
|
|
355
|
+
// Subagent specializations
|
|
356
|
+
const subagents = await p.multiselect({
|
|
357
|
+
message: "Subagent specializations (space to toggle)",
|
|
358
|
+
options: getAllSubagents().map((s) => ({
|
|
359
|
+
value: s.key,
|
|
360
|
+
label: s.label,
|
|
361
|
+
})),
|
|
362
|
+
initialValues: rec.subagents,
|
|
363
|
+
required: false,
|
|
364
|
+
});
|
|
365
|
+
handleCancel(subagents);
|
|
366
|
+
result.subagents = subagents;
|
|
367
|
+
|
|
368
|
+
// Agent Teams (experimental)
|
|
369
|
+
const agentTeams = await p.confirm({
|
|
370
|
+
message: "Enable Agent Teams? (experimental, advanced)",
|
|
371
|
+
initialValue: false,
|
|
372
|
+
});
|
|
373
|
+
handleCancel(agentTeams);
|
|
374
|
+
result.agentTeams = agentTeams;
|
|
375
|
+
|
|
376
|
+
return result;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Full manual selection — nothing pre-selected.
|
|
381
|
+
* @returns {Promise<object>} user-selected setup
|
|
382
|
+
*/
|
|
383
|
+
async function askManual() {
|
|
384
|
+
const commands = await p.multiselect({
|
|
385
|
+
message: "Select commands",
|
|
386
|
+
options: getAllCommands().map((c) => ({
|
|
387
|
+
value: c.key,
|
|
388
|
+
label: c.label,
|
|
389
|
+
})),
|
|
390
|
+
initialValues: [],
|
|
391
|
+
required: false,
|
|
392
|
+
});
|
|
393
|
+
handleCancel(commands);
|
|
394
|
+
|
|
395
|
+
const skills = await p.multiselect({
|
|
396
|
+
message: "Select skills",
|
|
397
|
+
options: getAllSkills().map((s) => ({
|
|
398
|
+
value: s.key,
|
|
399
|
+
label: s.label,
|
|
400
|
+
})),
|
|
401
|
+
initialValues: [],
|
|
402
|
+
required: false,
|
|
403
|
+
});
|
|
404
|
+
handleCancel(skills);
|
|
405
|
+
|
|
406
|
+
const mcps = await p.multiselect({
|
|
407
|
+
message: "Select MCP servers",
|
|
408
|
+
options: getAllMcps().map((m) => ({
|
|
409
|
+
value: m.key,
|
|
410
|
+
label: m.label,
|
|
411
|
+
hint: m.desc,
|
|
412
|
+
})),
|
|
413
|
+
initialValues: [],
|
|
414
|
+
required: false,
|
|
415
|
+
});
|
|
416
|
+
handleCancel(mcps);
|
|
417
|
+
|
|
418
|
+
const subagents = await p.multiselect({
|
|
419
|
+
message: "Select subagent specializations",
|
|
420
|
+
options: getAllSubagents().map((s) => ({
|
|
421
|
+
value: s.key,
|
|
422
|
+
label: s.label,
|
|
423
|
+
})),
|
|
424
|
+
initialValues: [],
|
|
425
|
+
required: false,
|
|
426
|
+
});
|
|
427
|
+
handleCancel(subagents);
|
|
428
|
+
|
|
429
|
+
const agentTeams = await p.confirm({
|
|
430
|
+
message: "Enable Agent Teams? (experimental, advanced)",
|
|
431
|
+
initialValue: false,
|
|
432
|
+
});
|
|
433
|
+
handleCancel(agentTeams);
|
|
434
|
+
|
|
435
|
+
return {
|
|
436
|
+
commands,
|
|
437
|
+
hooks: getAllHooks().map((h) => h.key),
|
|
438
|
+
skills,
|
|
439
|
+
mcps,
|
|
440
|
+
subagents,
|
|
441
|
+
agentTeams,
|
|
442
|
+
tags: [],
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// ─── Legacy prompts (kept for backward compat) ──────────────────────────────
|
|
447
|
+
|
|
141
448
|
/**
|
|
142
449
|
* Ask which MCP servers to install via multi-select.
|
|
143
450
|
* @returns {Promise<string[]>}
|
|
@@ -192,6 +499,8 @@ async function askGitBranch() {
|
|
|
192
499
|
return { create: true, name };
|
|
193
500
|
}
|
|
194
501
|
|
|
502
|
+
// ─── Display helpers ────────────────────────────────────────────────────────
|
|
503
|
+
|
|
195
504
|
/**
|
|
196
505
|
* Display a summary note.
|
|
197
506
|
* @param {object} config
|
|
@@ -199,17 +508,29 @@ async function askGitBranch() {
|
|
|
199
508
|
*/
|
|
200
509
|
function showSummary(config, files) {
|
|
201
510
|
const lines = [
|
|
202
|
-
`Project:
|
|
203
|
-
`Stack:
|
|
204
|
-
`
|
|
205
|
-
`
|
|
206
|
-
`
|
|
207
|
-
`
|
|
208
|
-
`
|
|
209
|
-
""
|
|
210
|
-
`Files created/updated:`,
|
|
211
|
-
...files.map((f) => ` ${f}`),
|
|
511
|
+
`Project: ${config.projectName}`,
|
|
512
|
+
`Stack: ${config.stack}`,
|
|
513
|
+
`App Type: ${config.appType || "n/a"}`,
|
|
514
|
+
`Language: ${config.language}`,
|
|
515
|
+
`Autonomy: ${config.autonomyLevel}`,
|
|
516
|
+
`Pkg Manager: ${config.packageManager}`,
|
|
517
|
+
`Formatter: ${config.formatter}`,
|
|
518
|
+
`Mode: ${config.mode || "recommended"}`,
|
|
212
519
|
];
|
|
520
|
+
|
|
521
|
+
if (config.recommended) {
|
|
522
|
+
lines.push(
|
|
523
|
+
`Commands: ${config.recommended.commands.length}`,
|
|
524
|
+
`Skills: ${config.recommended.skills.length}`,
|
|
525
|
+
`MCPs: ${config.recommended.mcps.length}`,
|
|
526
|
+
`Subagents: ${config.recommended.subagents.length}`,
|
|
527
|
+
`Agent Teams: ${config.recommended.agentTeams ? "enabled" : "disabled"}`,
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
lines.push("", `Files created/updated:`);
|
|
532
|
+
lines.push(...files.map((f) => ` ${f}`));
|
|
533
|
+
|
|
213
534
|
p.note(lines.join("\n"), "Configuration Summary");
|
|
214
535
|
}
|
|
215
536
|
|
|
@@ -219,9 +540,7 @@ function showSummary(config, files) {
|
|
|
219
540
|
*/
|
|
220
541
|
function showOutro(isGlobal) {
|
|
221
542
|
if (isGlobal) {
|
|
222
|
-
p.outro(
|
|
223
|
-
"Effectum ready! In any project, run: npx @aslomon/effectum init",
|
|
224
|
-
);
|
|
543
|
+
p.outro("Effectum ready! In any project, run: npx @aslomon/effectum init");
|
|
225
544
|
} else {
|
|
226
545
|
p.outro(
|
|
227
546
|
"Effectum ready! Open Claude Code here and start building. Try /plan or /prd:new",
|
|
@@ -234,13 +553,23 @@ module.exports = {
|
|
|
234
553
|
getClack,
|
|
235
554
|
printBanner,
|
|
236
555
|
handleCancel,
|
|
556
|
+
// Step prompts
|
|
557
|
+
askScope,
|
|
237
558
|
askProjectName,
|
|
238
559
|
askStack,
|
|
560
|
+
askAppType,
|
|
561
|
+
askDescription,
|
|
239
562
|
askLanguage,
|
|
240
563
|
askAutonomy,
|
|
564
|
+
showRecommendation,
|
|
565
|
+
askSetupMode,
|
|
566
|
+
askCustomize,
|
|
567
|
+
askManual,
|
|
568
|
+
// Legacy / utility prompts
|
|
241
569
|
askMcpServers,
|
|
242
570
|
askPlaywright,
|
|
243
571
|
askGitBranch,
|
|
572
|
+
// Display
|
|
244
573
|
showSummary,
|
|
245
574
|
showOutro,
|
|
246
575
|
};
|
package/bin/reconfigure.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Reconfigure — re-apply settings from .effectum.json.
|
|
4
4
|
* Reads the saved config and regenerates CLAUDE.md, settings.json, guardrails.md.
|
|
5
|
+
* Supports v0.4.0 config schema with appType, description, recommended setup.
|
|
5
6
|
*/
|
|
6
7
|
"use strict";
|
|
7
8
|
|
|
@@ -13,12 +14,12 @@ const {
|
|
|
13
14
|
buildSubstitutionMap,
|
|
14
15
|
renderTemplate,
|
|
15
16
|
findTemplatePath,
|
|
16
|
-
findRemainingPlaceholders,
|
|
17
|
-
substituteAll,
|
|
18
17
|
} = require("./lib/template");
|
|
19
18
|
const { AUTONOMY_MAP, FORMATTER_MAP } = require("./lib/constants");
|
|
20
19
|
const { ensureDir, deepMerge, findRepoRoot } = require("./lib/utils");
|
|
21
20
|
const { initClack } = require("./lib/ui");
|
|
21
|
+
const { recommend } = require("./lib/recommendation");
|
|
22
|
+
const { writeConfig } = require("./lib/config");
|
|
22
23
|
|
|
23
24
|
// ─── Main ─────────────────────────────────────────────────────────────────
|
|
24
25
|
|
|
@@ -40,7 +41,24 @@ async function main() {
|
|
|
40
41
|
process.exit(1);
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
// Re-run recommendation engine with current config values
|
|
45
|
+
if (config.appType || config.description) {
|
|
46
|
+
const rec = recommend({
|
|
47
|
+
stack: config.stack,
|
|
48
|
+
appType: config.appType || "web-app",
|
|
49
|
+
description: config.description || "",
|
|
50
|
+
autonomyLevel: config.autonomyLevel || "standard",
|
|
51
|
+
language: config.language || "english",
|
|
52
|
+
});
|
|
53
|
+
config.recommended = rec;
|
|
54
|
+
// Persist updated recommendations
|
|
55
|
+
writeConfig(targetDir, config);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const configInfo = [`"${config.projectName}" (${config.stack})`];
|
|
59
|
+
if (config.appType) configInfo.push(`type: ${config.appType}`);
|
|
60
|
+
if (config.mode) configInfo.push(`mode: ${config.mode}`);
|
|
61
|
+
p.log.info(`Reconfiguring ${configInfo.join(", ")}`);
|
|
44
62
|
|
|
45
63
|
if (dryRun) {
|
|
46
64
|
p.note(JSON.stringify(config, null, 2), "Current Configuration");
|
|
@@ -94,6 +112,14 @@ async function main() {
|
|
|
94
112
|
deny: settingsObj.permissions?.deny || [],
|
|
95
113
|
};
|
|
96
114
|
|
|
115
|
+
// Apply Agent Teams env var from saved config
|
|
116
|
+
if (settingsObj.env && config.recommended) {
|
|
117
|
+
settingsObj.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS = config.recommended
|
|
118
|
+
.agentTeams
|
|
119
|
+
? "1"
|
|
120
|
+
: "0";
|
|
121
|
+
}
|
|
122
|
+
|
|
97
123
|
const formatter = FORMATTER_MAP[config.stack] || FORMATTER_MAP.generic;
|
|
98
124
|
if (settingsObj.hooks?.PostToolUse) {
|
|
99
125
|
for (const group of settingsObj.hooks.PostToolUse) {
|
package/package.json
CHANGED