bmad-stella 1.0.0 → 1.0.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/README.md CHANGED
@@ -52,8 +52,9 @@ npx bmad-stella install
52
52
  3. Enter Confluence URL for architecture docs
53
53
  4. Select **Claude Code** as IDE
54
54
  5. Skip web bundles installation (enter `n`)
55
- 6. Configure Atlassian MCP Server (enter `y`)
56
- 7. Provide JIRA instance URL (e.g., `https://stellaint.atlassian.net`)
55
+ 6. Allow Claude Code Permissions Setup (enter `y`)
56
+ 7. Configure Atlassian MCP Server (enter `y`)
57
+ 8. Provide JIRA instance URL (e.g., `https://stellaint.atlassian.net`)
57
58
 
58
59
  **📖 [Detailed Installation Guide](docs/stella-user-guide.md#bmad-stella-installation-process)**
59
60
 
@@ -58,12 +58,14 @@ core_principles:
58
58
 
59
59
  # All commands require * prefix when used (e.g., *help)
60
60
  commands:
61
- - help: Show numbered list of the following commands to allow selection
61
+ - help: Show numbered list of the following commands to allow selection. Format each as "{number}. *{command-name} {parameters} - {description}"
62
62
  - implement-task:
63
- - order-of-execution: 'Read (first or next) task from implementation plan→Implement Task and its subtasks→Write tests→Execute validations→Only if ALL pass, then update the task checkbox with [x] in plan→Update plan section File List to ensure it lists any new or modified or deleted source file→HALT and ask user if they want to proceed to next task→If yes, repeat order-of-execution; if no, remain HALTED'
63
+ - order-of-execution: 'Read (first or next) task from implementation plan→Implement Task and its subtasks→Update the task checkbox with [x] in plan→Update plan file `File List` subsection in `Dev Agent Record` section to ensure it lists any new or modified or deleted source file→HALT and ask user: "Proceed to next task, build project, or stop?"→If next task: repeat order-of-execution→If build: run build command and report result then ask "Proceed to next task or stop?"→If stop: remain HALTED'
64
64
  - plan-file-updates-ONLY:
65
65
  - CRITICAL: ONLY UPDATE THE IMPLEMENTATION PLAN FILE WITH UPDATES TO SECTIONS INDICATED BELOW. DO NOT MODIFY ANY OTHER SECTIONS.
66
- - CRITICAL: You are ONLY authorized to edit these specific sections of implementation plan files - Tasks / Subtasks Checkboxes, Dev Agent Record section (Agent Model Used, Debug Log References, Completion Notes List, File List), Change Log, Status
66
+ - CRITICAL: Don't ask for user permission for plan file update.
67
+ - CRITICAL: MUST UPDATE `Agent Model Used` and `File List` SUBSECTION IN `Dev Agent Record` SECTION OF IMPLEMENTATION PLAN
68
+ - CRITICAL: You are ONLY authorized to edit these specific sections of implementation plan files - Tasks / Subtasks Checkboxes, `Dev Agent Record` section (Agent Model Used, Debug Log References, Completion Notes List, File List), Change Log, Status
67
69
  - CRITICAL: DO NOT modify Ticket Information, Requirements, Acceptance Criteria, Technical Approach, Technical Context / Dev Notes, Files to Change, Dependencies and Risks, Feedback, or any other sections not listed above
68
70
  - interaction-rules:
69
71
  - Don't perform DB Migrations and manual tests automatically. Ask user to perform these and wait for confirmation before going to the next step
@@ -74,8 +76,8 @@ commands:
74
76
  - ready-for-review: 'Code matches requirements + All validations pass + Follows standards + File List complete in Dev Agent Record'
75
77
  - completion: "All Tasks and Subtasks marked [x] and have tests→Validations and full regression passes (DON'T BE LAZY, EXECUTE ALL TESTS and CONFIRM)→Ensure Dev Agent Record File List is Complete→run the task execute-checklist for the checklist task-dod-checklist→set plan status: 'Ready for Review'→HALT"
76
78
  - explain: teach me what and why you did whatever you just did in detail so I can learn. Explain to me as if you were training a junior engineer.
77
- - comment-plan {plan-file}: Post implementation summary to Jira ticket using Atlassian MCP server using Jira markdown formatting
78
- - order-of-execution: Extract Jira ticket number/URL from plan file Ticket Information section→Verify Atlassian MCP server connectivityCheck if Acceptance Criteria already exists in Jira ticket description→Format comment according to comment-structure rules→Display formatted comment to user and request permission to post→Post comment to Jira ticket→Display Jira ticket URL and confirm successful posting
79
+ - comment-plan {plan-file}:
80
+ - order-of-execution: 'Extract Jira ticket number/URL from plan file Ticket Information section→Attempt to fetch Jira ticket using atlassian MCP→If fetch fails, notify user: "Atlassian MCP not connected. Please reauthenticate."If connected, check if Acceptance Criteria already exists in Jira ticket description→Format comment according to comment-structure rules using Jira markdown formatting→Display formatted comment to user and request permission to post→Post comment to Jira ticket→Display Jira ticket URL and confirm successful posting'
79
81
  - comment-structure:
80
82
  - Section 1 - Tasks Completed: Copy all tasks and subtasks from Tasks/Subtasks section exactly as written with their checkbox status ([x] or [ ])
81
83
  - Section 2 - Technical Summary: Write a 5-10 sentence summary describing what was implemented based on Technical Approach section content
@@ -20,7 +20,7 @@ activation-instructions:
20
20
  - STEP 1: Read THIS ENTIRE FILE - it contains your complete persona definition
21
21
  - STEP 2: Adopt the persona defined in the 'agent' and 'persona' sections below
22
22
  - STEP 3: Load and read `.bmad-core/core-config.yaml` (project configuration) before any greeting
23
- - STEP 4: Read documentation from the `architectureFolderUrl` in `.bmad-core/core-config.yaml`. Delete and recreate the `architecture/` folder inside `bmad-docs/` if it exists. Save content into files named coding-standards, tech-stack, git-workflow, and project-structure based on content meaning rather than page names, and save any additional pages as separate files if present. Number of files should be same as number of child pages in provided url. If atlassian mcp shows authentication/login required, inform user to authenticate Atlassian MCP, HALT activation process, wait for user confirmation of authentication, then retry STEP 4. Do NOT proceed to STEP 5 until architecture docs are successfully loaded.
23
+ - STEP 4: Before any greeting, fetch documentation from the `architectureFolderUrl` in `.bmad-core/core-config.yaml`. Delete and recreate the `architecture/` folder inside `bmad-docs/` if it exists. Use "Bash(rm -rf **/bmad-docs/architecture)" OR "Bash(rm -rf bmad-docs/architecture)" to delete architecture folder. Save content into files named coding-standards, tech-stack, git-workflow, and project-structure based on content meaning rather than page names, and save any additional pages as separate files if present. Number of files should be same as number of child pages in provided url. If attempt to fetch pages fail using atlassian MCP, notify user - "Atlassian MCP not connected. Please reauthenticate.", then retry STEP 4. Do NOT proceed to STEP 5 until architecture docs are successfully loaded.
24
24
  - STEP 5: Greet user with your name/role and immediately run `*help` to display available commands
25
25
  - DO NOT: Load any other agent files during activation
26
26
  - ONLY load dependency files when user selects them for execution via command or request of a task
@@ -60,10 +60,10 @@ persona:
60
60
  - Standards & Patterns Adherence - Ensure plans align with project conventions
61
61
  # All commands require * prefix when used (e.g., *help)
62
62
  commands:
63
- - help: Show numbered list of the following commands to allow selection
64
- - retrieve-ticket-information {ticket-number-or-url}: Retrieve and validate JIRA ticket information using Atlassian MCP server, preparing it for implementation planning
65
- - order-of-execution: Verify Atlassian MCP server connectivity→Fetch ticket information (title, description, comments, attachments) using ticket number/URL→Check for Requirements or Acceptance Criteria in ticket description→If absent, check for attached images and request user to provide them via copy/paste (alt+v) or file path if downloaded→Prepare Acceptance Criteria text based on ticket description, comments, and provided attachments→Display ticket contents with prepared Acceptance Criteria and request user validation→Prompt user to proceed with draft-plan command. If no ticket identifier provided, ask for one
66
- - attachment-rules: if there exists any attachments in the ticket request user to provide them via copy/paste (alt+v) or file path if downloaded
63
+ - help: Show numbered list of the following commands to allow selection. Format each as "{number}. *{command-name} {parameters} - {description}"
64
+ - retrieve-ticket-information {ticket-number-or-url}:
65
+ - order-of-execution: 'Fetch ticket information (title, description, comments, attachments) using ticket number/URL with `atlassian` MCPIf fetch fails, notify user: "Atlassian MCP not connected. Please reauthenticate." and HALT until user confirms reconnection, then retry fetch→Check for Requirements or Acceptance Criteria in ticket description→If absent, check for attached images and request user to provide them via copy/paste (alt+v) or file path if downloaded→Prepare Acceptance Criteria text based on ticket description, comments, and provided attachments→Display ticket contents with prepared Acceptance Criteria and request user validation→Prompt user to proceed with draft-plan command. If no ticket identifier provided, ask for one'
66
+ - attachment-rules: If there exists any attachments in the ticket request user to provide them via copy/paste (alt+v) or file path if downloaded
67
67
  - acceptance-criteria-rules: Prepare criteria only if Requirements AND Acceptance Criteria sections are both absent. Request attachments first if present. Format as testable, numbered list based on ticket description and attachments. Do not create any files - only compose text for display
68
68
  - output-format: Display ticket title, description, comments, attachments list, and prepared Acceptance Criteria (if created) with clear validation prompt
69
69
  - draft-plan {ticket-file-or-description}: Analyze JIRA ticket (feature/bug/migration) information with description having `Acceptance Criteria`/ `Requirements` and create detailed implementation plan with step-by-step tasks executing create-implementation-plan
@@ -62,7 +62,7 @@ task-file-permissions:
62
62
  - Assessment documents include: test-design-*.md, trace-*.md files
63
63
  # All commands require * prefix when used (e.g., *help)
64
64
  commands:
65
- - help: Show numbered list of the following commands to allow selection
65
+ - help: Show numbered list of the following commands to allow selection. Format each as "{number}. *{command-name} {parameters} - {description}"
66
66
  - test-design {task-file}: Execute test-design task to create comprehensive test scenarios
67
67
  - implement-test {task-file}: Execute implement-test task to write test code from test design scenarios
68
68
  - trace {task-file}: Execute trace-requirements task to map requirements to tests using Given-When-Then
@@ -16,6 +16,7 @@ To transform JIRA tickets (features, bugs, migrations) into comprehensive, actio
16
16
  - **Get search hints first:** Ask user for helpful hints to narrow the search (e.g., "Look in services folder", "Related to authentication", "Files with 'payment' in name", "Backend API files")
17
17
  - **Check project structure docs:** ALWAYS read `bmad-docs/architecture/project-structure.md` (or `project-structure.md`) FIRST to understand file locations and naming conventions
18
18
  - **Perform targeted search:** Use hints + structure knowledge to create focused Glob/Grep searches instead of broad codebase scans
19
+ - **Identify impacted files:** When modifying a function, component, or interface, search for its usages across codebase using targeted Glob/Grep before making changes. Update all impacted files accordingly.
19
20
 
20
21
  ## SEQUENTIAL Task Execution (Do not proceed until current Task is complete)
21
22
 
@@ -84,14 +85,14 @@ If critical information is missing, ask the user targeted questions:
84
85
 
85
86
  **For Database Changes (All Ticket Types):**
86
87
 
87
- - Does this work require any database table updates or creation?
88
- - **If uncertain, ASK the user** - better to clarify than assume
88
+ - Analyze Does this work require any database table updates or creation?
89
+ - **If not mentioned in ticket and uncertain, ASK the user** - better to clarify than assume
89
90
  - If YES:
90
91
  - **Database migration tasks must be handled by the user** (add in tasks list but tell user to do this)
91
92
  - If specific fields to add to a model or a new model structure are NOT specified in the ticket info/requirements:
92
93
  - **Ask the user to specify the fields to be added or the model structure** (field names, types, constraints, relationships)
93
94
  - **If uncertain about any database-related details, ALWAYS ask the user** - do not make assumptions or proceed silently
94
- - Document the model/table changes needed in the Technical Approach sectio
95
+ - Document the model/table changes needed in the Technical Approach section
95
96
 
96
97
  **CRITICAL:** Only ask essential questions. Use your senior developer judgment to infer reasonable details when possible.
97
98
 
@@ -28,7 +28,7 @@ Before installing BMad-Stella, ensure you have:
28
28
  Open your terminal and run:
29
29
 
30
30
  ```bash
31
- npx github:Asrarul-BS23/BMad-Stella install
31
+ npx bmad-stella install
32
32
  ```
33
33
 
34
34
  #### Step 2: Provide Project Directory
@@ -87,7 +87,17 @@ When prompted about web bundles:
87
87
 
88
88
  Enter: **n**
89
89
 
90
- #### Step 7: Configure Atlassian MCP Server
90
+ #### Step 7: Allow Claude Code Permissions Setup
91
+
92
+ When prompted about permission setup:
93
+
94
+ ```
95
+ Add 32 missing BMAD permissions to existing settings.local.json? (Y/n)
96
+ ```
97
+
98
+ Enter: **y**
99
+
100
+ #### Step 8: Configure Atlassian MCP Server
91
101
 
92
102
  If Atlassian MCP is not already configured, you'll see:
93
103
 
@@ -110,7 +120,7 @@ Enter: `https://stellaint.atlassian.net` (or your organization's JIRA URL)
110
120
  - MCP server configuration is created
111
121
  - Authentication is required to connect with JIRA instance
112
122
 
113
- #### Step 8: Complete Installation
123
+ #### Step 9: Complete Installation
114
124
 
115
125
  You should see:
116
126
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "bmad-stella",
4
- "version": "1.0.0",
4
+ "version": "1.0.1",
5
5
  "description": "Breakthrough Method of Agile AI-driven Development (Customized for Stella)",
6
6
  "keywords": [
7
7
  "agile",
@@ -0,0 +1,380 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('node:path');
3
+ const chalk = require('chalk').default || require('chalk');
4
+ const inquirer = require('inquirer').default || require('inquirer');
5
+ const cjson = require('comment-json');
6
+
7
+ class ClaudePermissionsManager {
8
+ constructor() {
9
+ // Define BMAD required permissions for Claude Code
10
+ this.bmadPermissions = [
11
+ // Atlassian MCP tools
12
+ 'mcp__atlassian__getConfluencePage',
13
+ 'mcp__atlassian__getConfluencePageDescendants',
14
+ 'mcp__atlassian__getJiraIssue',
15
+ 'mcp__atlassian__searchJiraIssuesUsingJql',
16
+ 'mcp__atlassian__fetch',
17
+ 'mcp__atlassian__addCommentToJiraIssue',
18
+
19
+ 'WebFetch(domain:stellaint.atlassian.net)',
20
+
21
+ // File operations for markdown files
22
+ 'Write(bmad-docs/**)',
23
+ 'Write(*bmad-docs*)',
24
+ 'Edit(bmad-docs/**)',
25
+ 'Edit(*bmad-docs*)',
26
+
27
+ // Bash commands for directory operations (Unix)
28
+ 'Bash(mkdir -p bmad-docs/**)',
29
+ 'Bash(mkdir -p **/bmad-docs/**)',
30
+ 'Bash(mkdir bmad-docs/**)',
31
+ 'Bash(mkdir **/bmad-docs/**)',
32
+ 'Bash(rm -rf *bmad-docs*)',
33
+ 'Bash(rm -rf */bmad-docs/architecture*)',
34
+ 'Bash(rm *bmad-docs*)',
35
+ 'Bash(rm */bmad-docs/architecture*)',
36
+ 'Bash(rm bmad-docs/temporary/*.md)',
37
+ 'Bash(rm **/bmad-docs/temporary/*.md)',
38
+
39
+ // Bash commands for directory operations (Windows)
40
+ 'Bash(if exist *bmad-docs* rmdir /s /q *bmad-docs*)',
41
+ String.raw`Bash(if exist *bmad-docs\architecture* rmdir /s /q *bmad-docs\architecture*)`,
42
+ 'Bash(mkdir *bmad-docs*)',
43
+
44
+ // Directory listing and existence checks (Unix)
45
+ 'Bash(ls bmad-docs/**)',
46
+ 'Bash(ls **/bmad-docs/**)',
47
+ 'Bash(test -f bmad-docs/**)',
48
+ 'Bash(test -f **/bmad-docs/**)',
49
+ 'Bash(test -d bmad-docs/**)',
50
+ 'Bash(test -d **/bmad-docs/**)',
51
+ 'Bash([ -f bmad-docs/** ])',
52
+ 'Bash([ -d bmad-docs/** ])',
53
+
54
+ // Directory listing (Windows)
55
+ 'Bash(dir bmad-docs/**)',
56
+ 'Bash(dir **/bmad-docs/**)',
57
+ 'Bash(dir *bmad-docs*)',
58
+ ];
59
+ }
60
+
61
+ /**
62
+ * Get the path to settings.local.json
63
+ * @param {string} installDir - Target installation directory
64
+ * @returns {string} Path to settings.local.json
65
+ */
66
+ getSettingsPath(installDir) {
67
+ return path.join(installDir, '.claude', 'settings.local.json');
68
+ }
69
+
70
+ /**
71
+ * Check if settings.local.json exists
72
+ * @param {string} installDir - Target installation directory
73
+ * @returns {Promise<boolean>}
74
+ */
75
+ async settingsExists(installDir) {
76
+ const settingsPath = this.getSettingsPath(installDir);
77
+ return fs.pathExists(settingsPath);
78
+ }
79
+
80
+ /**
81
+ * Read existing settings.local.json
82
+ * @param {string} installDir - Target installation directory
83
+ * @returns {Promise<object|null>} Parsed settings or null if not found
84
+ */
85
+ async readSettings(installDir) {
86
+ const settingsPath = this.getSettingsPath(installDir);
87
+
88
+ try {
89
+ if (!(await fs.pathExists(settingsPath))) {
90
+ return null;
91
+ }
92
+
93
+ const content = await fs.readFile(settingsPath, 'utf8');
94
+
95
+ try {
96
+ // Try parsing with comment-json to preserve comments
97
+ return cjson.parse(content);
98
+ } catch {
99
+ // Fallback to standard JSON
100
+ return JSON.parse(content);
101
+ }
102
+ } catch (error) {
103
+ console.warn(chalk.yellow(`Warning: Could not read settings.local.json: ${error.message}`));
104
+ return null;
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Write settings.local.json
110
+ * @param {string} installDir - Target installation directory
111
+ * @param {object} settings - Settings object to write
112
+ * @returns {Promise<boolean>}
113
+ */
114
+ async writeSettings(installDir, settings) {
115
+ const claudeDir = path.join(installDir, '.claude');
116
+ const settingsPath = this.getSettingsPath(installDir);
117
+
118
+ try {
119
+ // Ensure .claude directory exists
120
+ await fs.ensureDir(claudeDir);
121
+
122
+ // Write with pretty formatting
123
+ const output = cjson.stringify(settings, null, 2);
124
+ await fs.writeFile(settingsPath, output, 'utf8');
125
+ return true;
126
+ } catch (error) {
127
+ console.error(chalk.red(`Failed to write settings.local.json: ${error.message}`));
128
+ return false;
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Get list of missing BMAD permissions from current settings
134
+ * @param {object} settings - Current settings object
135
+ * @returns {string[]} Array of missing permission strings
136
+ */
137
+ getMissingPermissions(settings) {
138
+ const existingPermissions = new Set(settings?.permissions?.allow || []);
139
+ return this.bmadPermissions.filter((perm) => !existingPermissions.has(perm));
140
+ }
141
+
142
+ /**
143
+ * Check and setup Claude Code permissions
144
+ * @param {string} installDir - Target installation directory
145
+ * @param {object} spinner - Ora spinner instance (optional)
146
+ * @returns {Promise<object>} Results object with status
147
+ */
148
+ async checkAndSetupPermissions(installDir, spinner = null) {
149
+ const results = {
150
+ settingsExisted: false,
151
+ created: false,
152
+ updated: false,
153
+ skipped: false,
154
+ permissionsAdded: 0,
155
+ error: null,
156
+ };
157
+
158
+ try {
159
+ const settingsPath = this.getSettingsPath(installDir);
160
+ results.settingsExisted = await this.settingsExists(installDir);
161
+
162
+ if (spinner) spinner.stop();
163
+
164
+ // Always show permissions setup prompt
165
+ console.log(chalk.cyan('\n🔧 Claude Code Permissions Setup'));
166
+ console.log(
167
+ chalk.dim('BMAD agents require certain permissions to work without repeated prompts.'),
168
+ );
169
+ console.log(
170
+ chalk.dim(
171
+ '(Only for bmad-docs/ and Atlassian MCP - does NOT include source code changes)\n',
172
+ ),
173
+ );
174
+
175
+ if (results.settingsExisted) {
176
+ // Settings file exists - check for missing permissions
177
+ const settings = await this.readSettings(installDir);
178
+
179
+ if (!settings) {
180
+ results.error = 'Could not parse existing settings.local.json';
181
+ console.log(chalk.yellow(`⚠️ ${results.error}`));
182
+ if (spinner) spinner.start();
183
+ return results;
184
+ }
185
+
186
+ // Ensure permissions.allow array exists
187
+ if (!settings.permissions) {
188
+ settings.permissions = {};
189
+ }
190
+ if (!settings.permissions.allow) {
191
+ settings.permissions.allow = [];
192
+ }
193
+
194
+ // Find missing permissions
195
+ const missingPermissions = this.getMissingPermissions(settings);
196
+
197
+ if (missingPermissions.length > 0) {
198
+ // Ask user before adding permissions
199
+ const { updateSettings } = await inquirer.prompt([
200
+ {
201
+ type: 'confirm',
202
+ name: 'updateSettings',
203
+ message: `Add ${missingPermissions.length} missing BMAD permissions to existing settings.local.json?`,
204
+ default: true,
205
+ },
206
+ ]);
207
+
208
+ if (!updateSettings) {
209
+ console.log(chalk.yellow('⚠️ Skipping Claude Code permissions update.'));
210
+ results.skipped = true;
211
+ if (spinner) spinner.start();
212
+ return results;
213
+ }
214
+
215
+ // Add missing permissions
216
+ settings.permissions.allow.push(...missingPermissions);
217
+
218
+ const success = await this.writeSettings(installDir, settings);
219
+
220
+ if (success) {
221
+ results.updated = true;
222
+ results.permissionsAdded = missingPermissions.length;
223
+ console.log(chalk.green('✓ Updated .claude/settings.local.json with BMAD permissions'));
224
+ console.log(chalk.dim(` - Added ${missingPermissions.length} new permission rules`));
225
+ } else {
226
+ results.error = 'Failed to update settings file';
227
+ }
228
+ } else {
229
+ console.log(chalk.green('✓ BMAD permissions already present in settings.local.json'));
230
+ }
231
+ } else {
232
+ // Ask user if they want to create settings.local.json
233
+ const { createSettings } = await inquirer.prompt([
234
+ {
235
+ type: 'confirm',
236
+ name: 'createSettings',
237
+ message: 'Grant Claude Code with BMAD related permissions? (Recommended)',
238
+ default: true,
239
+ },
240
+ ]);
241
+
242
+ if (!createSettings) {
243
+ console.log(chalk.yellow('⚠️ Skipping Claude Code permissions setup.'));
244
+ console.log(
245
+ chalk.dim(' You may be prompted for permissions when using BMAD agents.\n'),
246
+ );
247
+ results.skipped = true;
248
+ if (spinner) spinner.start();
249
+ return results;
250
+ }
251
+
252
+ // Create new settings file
253
+ const settings = {
254
+ permissions: {
255
+ allow: [...this.bmadPermissions],
256
+ },
257
+ };
258
+
259
+ const success = await this.writeSettings(installDir, settings);
260
+
261
+ if (success) {
262
+ results.created = true;
263
+ results.permissionsAdded = this.bmadPermissions.length;
264
+ console.log(chalk.green('✓ Created .claude/settings.local.json with BMAD permissions'));
265
+ console.log(chalk.dim(` - Added ${this.bmadPermissions.length} permission rules`));
266
+ } else {
267
+ results.error = 'Failed to create settings file';
268
+ }
269
+ }
270
+
271
+ if (spinner) spinner.start();
272
+ return results;
273
+ } catch (error) {
274
+ results.error = error.message;
275
+ console.log(chalk.yellow(`⚠️ Could not setup Claude Code permissions: ${error.message}`));
276
+ if (spinner) spinner.start();
277
+ return results;
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Show summary of permissions setup
283
+ * @param {object} results - Results from checkAndSetupPermissions
284
+ */
285
+ showSetupSummary(results) {
286
+ if (results.error) {
287
+ console.log(chalk.red(`\n✗ Claude Code permissions setup failed: ${results.error}`));
288
+ console.log(chalk.yellow('You may need to add BMAD permissions manually.'));
289
+ this.showManualInstructions();
290
+ return;
291
+ }
292
+
293
+ if (results.skipped) {
294
+ console.log(chalk.yellow('\n⚠️ Claude Code permissions were not configured.'));
295
+ console.log(chalk.dim(' Run the installer again or add permissions manually.'));
296
+ return;
297
+ }
298
+
299
+ if (results.created) {
300
+ console.log(chalk.green('\n✓ Claude Code permissions configured successfully!'));
301
+ console.log(chalk.dim(` ${results.permissionsAdded} permission rules added.`));
302
+ } else if (results.updated) {
303
+ console.log(chalk.green('\n✓ Claude Code permissions updated successfully!'));
304
+ console.log(chalk.dim(` ${results.permissionsAdded} new permission rules added.`));
305
+ }
306
+ }
307
+
308
+ /**
309
+ * Show manual setup instructions
310
+ */
311
+ showManualInstructions() {
312
+ console.log(chalk.cyan('\n📋 Manual Setup Instructions:'));
313
+ console.log(chalk.dim('1. Create .claude/settings.local.json in your project root'));
314
+ console.log(chalk.dim('2. Add the following content:\n'));
315
+
316
+ const exampleSettings = {
317
+ permissions: {
318
+ allow: [...this.bmadPermissions.slice(0, 5), '... (see full list in docs)'],
319
+ },
320
+ };
321
+
322
+ console.log(chalk.dim(JSON.stringify(exampleSettings, null, 2)));
323
+ console.log(
324
+ chalk.dim('\nSee BMAD documentation for the complete list of required permissions.'),
325
+ );
326
+ }
327
+
328
+ /**
329
+ * Add custom permissions to an existing or new settings file
330
+ * @param {string} installDir - Target installation directory
331
+ * @param {string[]} customPermissions - Array of custom permission strings
332
+ * @returns {Promise<boolean>}
333
+ */
334
+ async addCustomPermissions(installDir, customPermissions) {
335
+ try {
336
+ let settings = await this.readSettings(installDir);
337
+
338
+ if (!settings) {
339
+ settings = { permissions: { allow: [] } };
340
+ }
341
+
342
+ if (!settings.permissions) {
343
+ settings.permissions = {};
344
+ }
345
+ if (!settings.permissions.allow) {
346
+ settings.permissions.allow = [];
347
+ }
348
+
349
+ const existingPermissions = new Set(settings.permissions.allow);
350
+ let addedCount = 0;
351
+
352
+ for (const permission of customPermissions) {
353
+ if (!existingPermissions.has(permission)) {
354
+ settings.permissions.allow.push(permission);
355
+ addedCount++;
356
+ }
357
+ }
358
+
359
+ if (addedCount > 0) {
360
+ await this.writeSettings(installDir, settings);
361
+ console.log(chalk.green(`✓ Added ${addedCount} custom permissions`));
362
+ }
363
+
364
+ return true;
365
+ } catch (error) {
366
+ console.error(chalk.red(`Failed to add custom permissions: ${error.message}`));
367
+ return false;
368
+ }
369
+ }
370
+
371
+ /**
372
+ * Get all BMAD permissions
373
+ * @returns {string[]} Array of all BMAD permission strings
374
+ */
375
+ getAllPermissions() {
376
+ return [...this.bmadPermissions];
377
+ }
378
+ }
379
+
380
+ module.exports = new ClaudePermissionsManager();